]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_iface.c
Merge pull request #10658 from proelbtn/fix/srv6-l3vpn-transposition
[mirror_frr.git] / pimd / pim_iface.c
1 /*
2 * PIM for Quagga
3 * Copyright (C) 2008 Everton da Silva Marques
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <zebra.h>
20
21 #include "if.h"
22 #include "log.h"
23 #include "vty.h"
24 #include "memory.h"
25 #include "prefix.h"
26 #include "vrf.h"
27 #include "linklist.h"
28 #include "plist.h"
29 #include "hash.h"
30 #include "ferr.h"
31 #include "network.h"
32
33 #include "pimd.h"
34 #include "pim_instance.h"
35 #include "pim_zebra.h"
36 #include "pim_iface.h"
37 #include "pim_igmp.h"
38 #include "pim_mroute.h"
39 #include "pim_oil.h"
40 #include "pim_str.h"
41 #include "pim_pim.h"
42 #include "pim_neighbor.h"
43 #include "pim_ifchannel.h"
44 #include "pim_sock.h"
45 #include "pim_time.h"
46 #include "pim_ssmpingd.h"
47 #include "pim_rp.h"
48 #include "pim_nht.h"
49 #include "pim_jp_agg.h"
50 #include "pim_igmp_join.h"
51 #include "pim_vxlan.h"
52
53 static void pim_if_igmp_join_del_all(struct interface *ifp);
54 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
55 struct in_addr group_addr,
56 struct in_addr source_addr);
57
58 void pim_if_init(struct pim_instance *pim)
59 {
60 int i;
61
62 for (i = 0; i < MAXVIFS; i++)
63 pim->iface_vif_index[i] = 0;
64 }
65
66 void pim_if_terminate(struct pim_instance *pim)
67 {
68 struct interface *ifp;
69
70 FOR_ALL_INTERFACES (pim->vrf, ifp) {
71 struct pim_interface *pim_ifp = ifp->info;
72
73 if (!pim_ifp)
74 continue;
75
76 pim_if_delete(ifp);
77 }
78 return;
79 }
80
81 static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
82 {
83 XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
84 }
85
86 static int pim_sec_addr_comp(const void *p1, const void *p2)
87 {
88 const struct pim_secondary_addr *sec1 = p1;
89 const struct pim_secondary_addr *sec2 = p2;
90
91 if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
92 return -1;
93
94 if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
95 return 1;
96
97 if (sec1->addr.family == AF_INET) {
98 if (ntohl(sec1->addr.u.prefix4.s_addr)
99 < ntohl(sec2->addr.u.prefix4.s_addr))
100 return -1;
101
102 if (ntohl(sec1->addr.u.prefix4.s_addr)
103 > ntohl(sec2->addr.u.prefix4.s_addr))
104 return 1;
105 } else {
106 return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
107 sizeof(struct in6_addr));
108 }
109
110 return 0;
111 }
112
113 struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
114 bool ispimreg, bool is_vxlan_term)
115 {
116 struct pim_interface *pim_ifp;
117
118 assert(ifp);
119 assert(!ifp->info);
120
121 pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
122
123 pim_ifp->options = 0;
124 pim_ifp->pim = ifp->vrf->info;
125 pim_ifp->mroute_vif_index = -1;
126
127 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
128 pim_ifp->gm_default_robustness_variable =
129 IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
130 pim_ifp->gm_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
131 pim_ifp->gm_query_max_response_time_dsec =
132 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
133 pim_ifp->gm_specific_query_max_response_time_dsec =
134 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
135 pim_ifp->gm_last_member_query_count = IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
136
137 /* BSM config on interface: true by default */
138 pim_ifp->bsm_enable = true;
139 pim_ifp->ucast_bsm_accept = true;
140 pim_ifp->am_i_dr = false;
141
142 /*
143 RFC 3376: 8.3. Query Response Interval
144 The number of seconds represented by the [Query Response Interval]
145 must be less than the [Query Interval].
146 */
147 assert(pim_ifp->gm_query_max_response_time_dsec <
148 pim_ifp->gm_default_query_interval);
149
150 if (pim)
151 PIM_IF_DO_PIM(pim_ifp->options);
152 if (igmp)
153 PIM_IF_DO_IGMP(pim_ifp->options);
154
155 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options);
156
157 pim_ifp->gm_join_list = NULL;
158 pim_ifp->pim_neighbor_list = NULL;
159 pim_ifp->upstream_switch_list = NULL;
160 pim_ifp->pim_generation_id = 0;
161
162 /* list of struct gm_sock */
163 pim_igmp_if_init(pim_ifp, ifp);
164
165 /* list of struct pim_neighbor */
166 pim_ifp->pim_neighbor_list = list_new();
167 pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
168
169 pim_ifp->upstream_switch_list = list_new();
170 pim_ifp->upstream_switch_list->del =
171 (void (*)(void *))pim_jp_agg_group_list_free;
172 pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
173
174 pim_ifp->sec_addr_list = list_new();
175 pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
176 pim_ifp->sec_addr_list->cmp =
177 (int (*)(void *, void *))pim_sec_addr_comp;
178
179 pim_ifp->activeactive = false;
180
181 RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
182
183 ifp->info = pim_ifp;
184
185 pim_sock_reset(ifp);
186
187 pim_if_add_vif(ifp, ispimreg, is_vxlan_term);
188 pim_ifp->pim->mcast_if_count++;
189
190 return pim_ifp;
191 }
192
193 void pim_if_delete(struct interface *ifp)
194 {
195 struct pim_interface *pim_ifp;
196
197 assert(ifp);
198 pim_ifp = ifp->info;
199 assert(pim_ifp);
200
201 if (pim_ifp->gm_join_list) {
202 pim_if_igmp_join_del_all(ifp);
203 }
204
205 pim_ifchannel_delete_all(ifp);
206 igmp_sock_delete_all(ifp);
207
208 pim_neighbor_delete_all(ifp, "Interface removed from configuration");
209
210 pim_if_del_vif(ifp);
211 pim_ifp->pim->mcast_if_count--;
212
213 pim_igmp_if_fini(pim_ifp);
214
215 list_delete(&pim_ifp->pim_neighbor_list);
216 list_delete(&pim_ifp->upstream_switch_list);
217 list_delete(&pim_ifp->sec_addr_list);
218
219 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
220 XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
221
222 ifp->info = NULL;
223 }
224
225 void pim_if_update_could_assert(struct interface *ifp)
226 {
227 struct pim_interface *pim_ifp;
228 struct pim_ifchannel *ch;
229
230 pim_ifp = ifp->info;
231 assert(pim_ifp);
232
233 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
234 pim_ifchannel_update_could_assert(ch);
235 }
236 }
237
238 static void pim_if_update_my_assert_metric(struct interface *ifp)
239 {
240 struct pim_interface *pim_ifp;
241 struct pim_ifchannel *ch;
242
243 pim_ifp = ifp->info;
244 assert(pim_ifp);
245
246 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
247 pim_ifchannel_update_my_assert_metric(ch);
248 }
249 }
250
251 static void pim_addr_change(struct interface *ifp)
252 {
253 struct pim_interface *pim_ifp;
254
255 pim_ifp = ifp->info;
256 assert(pim_ifp);
257
258 pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes --
259 Done TODO T30 */
260 pim_if_update_join_desired(pim_ifp); /* depends on DR */
261 pim_if_update_could_assert(ifp); /* depends on DR */
262 pim_if_update_my_assert_metric(ifp); /* depends on could_assert */
263 pim_if_update_assert_tracking_desired(
264 ifp); /* depends on DR, join_desired */
265
266 /*
267 RFC 4601: 4.3.1. Sending Hello Messages
268
269 1) Before an interface goes down or changes primary IP address, a
270 Hello message with a zero HoldTime should be sent immediately
271 (with the old IP address if the IP address changed).
272 -- Done at the caller of the function as new ip already updated here
273
274 2) After an interface has changed its IP address, it MUST send a
275 Hello message with its new IP address.
276 -- DONE below
277
278 3) If an interface changes one of its secondary IP addresses, a
279 Hello message with an updated Address_List option and a non-zero
280 HoldTime should be sent immediately.
281 -- FIXME See TODO T31
282 */
283 PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp->flags);
284 if (pim_ifp->pim_sock_fd < 0)
285 return;
286 pim_hello_restart_now(ifp); /* send hello and restart timer */
287 }
288
289 static int detect_primary_address_change(struct interface *ifp,
290 int force_prim_as_any,
291 const char *caller)
292 {
293 struct pim_interface *pim_ifp = ifp->info;
294 pim_addr new_prim_addr;
295 int changed;
296
297 if (force_prim_as_any)
298 new_prim_addr = PIMADDR_ANY;
299 else
300 new_prim_addr = pim_find_primary_addr(ifp);
301
302 changed = pim_addr_cmp(new_prim_addr, pim_ifp->primary_address);
303
304 if (PIM_DEBUG_ZEBRA)
305 zlog_debug("%s: old=%pPA new=%pPA on interface %s: %s",
306 __func__, &pim_ifp->primary_address, &new_prim_addr,
307 ifp->name, changed ? "changed" : "unchanged");
308
309 if (changed) {
310 /* Before updating pim_ifp send Hello time with 0 hold time */
311 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
312 pim_hello_send(ifp, 0 /* zero-sec holdtime */);
313 }
314 pim_ifp->primary_address = new_prim_addr;
315 }
316
317 return changed;
318 }
319
320 static struct pim_secondary_addr *
321 pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
322 {
323 struct pim_secondary_addr *sec_addr;
324 struct listnode *node;
325
326 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
327 if (prefix_cmp(&sec_addr->addr, addr) == 0) {
328 return sec_addr;
329 }
330 }
331
332 return NULL;
333 }
334
335 static void pim_sec_addr_del(struct pim_interface *pim_ifp,
336 struct pim_secondary_addr *sec_addr)
337 {
338 listnode_delete(pim_ifp->sec_addr_list, sec_addr);
339 pim_sec_addr_free(sec_addr);
340 }
341
342 static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
343 {
344 int changed = 0;
345 struct pim_secondary_addr *sec_addr;
346
347 sec_addr = pim_sec_addr_find(pim_ifp, addr);
348 if (sec_addr) {
349 sec_addr->flags &= ~PIM_SEC_ADDRF_STALE;
350 return changed;
351 }
352
353 sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
354
355 changed = 1;
356 sec_addr->addr = *addr;
357 listnode_add_sort(pim_ifp->sec_addr_list, sec_addr);
358
359 return changed;
360 }
361
362 static int pim_sec_addr_del_all(struct pim_interface *pim_ifp)
363 {
364 int changed = 0;
365
366 if (!list_isempty(pim_ifp->sec_addr_list)) {
367 changed = 1;
368 /* remove all nodes and free up the list itself */
369 list_delete_all_node(pim_ifp->sec_addr_list);
370 }
371
372 return changed;
373 }
374
375 static int pim_sec_addr_update(struct interface *ifp)
376 {
377 struct pim_interface *pim_ifp = ifp->info;
378 struct connected *ifc;
379 struct listnode *node;
380 struct listnode *nextnode;
381 struct pim_secondary_addr *sec_addr;
382 int changed = 0;
383
384 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
385 sec_addr->flags |= PIM_SEC_ADDRF_STALE;
386 }
387
388 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
389 pim_addr addr = pim_addr_from_prefix(ifc->address);
390
391 if (pim_addr_is_any(addr))
392 continue;
393
394 if (!pim_addr_cmp(addr, pim_ifp->primary_address)) {
395 /* don't add the primary address into the secondary
396 * address list */
397 continue;
398 }
399
400 if (pim_sec_addr_add(pim_ifp, ifc->address)) {
401 changed = 1;
402 }
403 }
404
405 /* Drop stale entries */
406 for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
407 sec_addr)) {
408 if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
409 pim_sec_addr_del(pim_ifp, sec_addr);
410 changed = 1;
411 }
412 }
413
414 return changed;
415 }
416
417 static int detect_secondary_address_change(struct interface *ifp,
418 int force_prim_as_any,
419 const char *caller)
420 {
421 struct pim_interface *pim_ifp = ifp->info;
422 int changed = 0;
423
424 if (force_prim_as_any) {
425 /* if primary address is being forced to zero just flush the
426 * secondary address list */
427 changed = pim_sec_addr_del_all(pim_ifp);
428 } else {
429 /* re-evaluate the secondary address list */
430 changed = pim_sec_addr_update(ifp);
431 }
432
433 return changed;
434 }
435
436 static void detect_address_change(struct interface *ifp, int force_prim_as_any,
437 const char *caller)
438 {
439 int changed = 0;
440 struct pim_interface *pim_ifp;
441
442 pim_ifp = ifp->info;
443 if (!pim_ifp)
444 return;
445
446 if (detect_primary_address_change(ifp, force_prim_as_any, caller)) {
447 changed = 1;
448 }
449
450 if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) {
451 changed = 1;
452 }
453
454
455 if (changed) {
456 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
457 return;
458 }
459
460 pim_addr_change(ifp);
461 }
462
463 /* XXX: if we have unnumbered interfaces we need to run detect address
464 * address change on all of them when the lo address changes */
465 }
466
467 int pim_update_source_set(struct interface *ifp, pim_addr source)
468 {
469 struct pim_interface *pim_ifp = ifp->info;
470
471 if (!pim_ifp) {
472 return PIM_IFACE_NOT_FOUND;
473 }
474
475 if (!pim_addr_cmp(pim_ifp->update_source, source)) {
476 return PIM_UPDATE_SOURCE_DUP;
477 }
478
479 pim_ifp->update_source = source;
480 detect_address_change(ifp, 0 /* force_prim_as_any */, __func__);
481
482 return PIM_SUCCESS;
483 }
484
485 void pim_if_addr_add(struct connected *ifc)
486 {
487 struct pim_interface *pim_ifp;
488 struct interface *ifp;
489 struct in_addr ifaddr;
490 bool vxlan_term;
491
492 assert(ifc);
493
494 ifp = ifc->ifp;
495 assert(ifp);
496 pim_ifp = ifp->info;
497 if (!pim_ifp)
498 return;
499
500 if (!if_is_operative(ifp))
501 return;
502
503 if (PIM_DEBUG_ZEBRA)
504 zlog_debug("%s: %s ifindex=%d connected IP address %pFX %s",
505 __func__, ifp->name, ifp->ifindex, ifc->address,
506 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
507 ? "secondary"
508 : "primary");
509
510 ifaddr = ifc->address->u.prefix4;
511
512 detect_address_change(ifp, 0, __func__);
513
514 // if (ifc->address->family != AF_INET)
515 // return;
516
517 if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
518 struct gm_sock *igmp;
519
520 /* lookup IGMP socket */
521 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
522 ifaddr);
523 if (!igmp) {
524 /* if addr new, add IGMP socket */
525 if (ifc->address->family == AF_INET)
526 pim_igmp_sock_add(pim_ifp->gm_socket_list,
527 ifaddr, ifp, false);
528 } else if (igmp->mtrace_only) {
529 igmp_sock_delete(igmp);
530 pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp,
531 false);
532 }
533
534 /* Replay Static IGMP groups */
535 if (pim_ifp->gm_join_list) {
536 struct listnode *node;
537 struct listnode *nextnode;
538 struct gm_join *ij;
539 int join_fd;
540
541 for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node,
542 nextnode, ij)) {
543 /* Close socket and reopen with Source and Group
544 */
545 close(ij->sock_fd);
546 join_fd = igmp_join_sock(
547 ifp->name, ifp->ifindex, ij->group_addr,
548 ij->source_addr);
549 if (join_fd < 0) {
550 char group_str[INET_ADDRSTRLEN];
551 char source_str[INET_ADDRSTRLEN];
552 pim_inet4_dump("<grp?>", ij->group_addr,
553 group_str,
554 sizeof(group_str));
555 pim_inet4_dump(
556 "<src?>", ij->source_addr,
557 source_str, sizeof(source_str));
558 zlog_warn(
559 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
560 __func__, group_str, source_str,
561 ifp->name);
562 /* warning only */
563 } else
564 ij->sock_fd = join_fd;
565 }
566 }
567 } /* igmp */
568 else {
569 struct gm_sock *igmp;
570
571 /* lookup IGMP socket */
572 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
573 ifaddr);
574 if (ifc->address->family == AF_INET) {
575 if (igmp)
576 igmp_sock_delete(igmp);
577 /* if addr new, add IGMP socket */
578 pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp,
579 true);
580 }
581 } /* igmp mtrace only */
582
583 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
584
585 if (!pim_addr_is_any(pim_ifp->primary_address)) {
586
587 /* Interface has a valid socket ? */
588 if (pim_ifp->pim_sock_fd < 0) {
589 if (pim_sock_add(ifp)) {
590 zlog_warn(
591 "Failure creating PIM socket for interface %s",
592 ifp->name);
593 }
594 }
595 struct pim_nexthop_cache *pnc = NULL;
596 struct pim_rpf rpf;
597 struct zclient *zclient = NULL;
598
599 zclient = pim_zebra_zclient_get();
600 /* RP config might come prior to (local RP's interface)
601 IF UP event.
602 In this case, pnc would not have pim enabled
603 nexthops.
604 Once Interface is UP and pim info is available,
605 reregister
606 with RNH address to receive update and add the
607 interface as nexthop. */
608 memset(&rpf, 0, sizeof(struct pim_rpf));
609 rpf.rpf_addr.family = AF_INET;
610 rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
611 rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
612 pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
613 if (pnc)
614 pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
615 pnc,
616 ZEBRA_NEXTHOP_REGISTER);
617 }
618 } /* pim */
619
620 /*
621 PIM or IGMP is enabled on interface, and there is at least one
622 address assigned, then try to create a vif_index.
623 */
624 if (pim_ifp->mroute_vif_index < 0) {
625 vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
626 pim_if_add_vif(ifp, false, vxlan_term);
627 }
628 pim_ifchannel_scan_forward_start(ifp);
629 }
630
631 static void pim_if_addr_del_igmp(struct connected *ifc)
632 {
633 struct pim_interface *pim_ifp = ifc->ifp->info;
634 struct gm_sock *igmp;
635 struct in_addr ifaddr;
636
637 if (ifc->address->family != AF_INET) {
638 /* non-IPv4 address */
639 return;
640 }
641
642 if (!pim_ifp) {
643 /* IGMP not enabled on interface */
644 return;
645 }
646
647 ifaddr = ifc->address->u.prefix4;
648
649 /* lookup IGMP socket */
650 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, ifaddr);
651 if (igmp) {
652 /* if addr found, del IGMP socket */
653 igmp_sock_delete(igmp);
654 }
655 }
656
657 static void pim_if_addr_del_pim(struct connected *ifc)
658 {
659 struct pim_interface *pim_ifp = ifc->ifp->info;
660
661 if (ifc->address->family != AF_INET) {
662 /* non-IPv4 address */
663 return;
664 }
665
666 if (!pim_ifp) {
667 /* PIM not enabled on interface */
668 return;
669 }
670
671 if (!pim_addr_is_any(pim_ifp->primary_address)) {
672 /* Interface keeps a valid primary address */
673 return;
674 }
675
676 if (pim_ifp->pim_sock_fd < 0) {
677 /* Interface does not hold a valid socket any longer */
678 return;
679 }
680
681 /*
682 pim_sock_delete() closes the socket, stops read and timer threads,
683 and kills all neighbors.
684 */
685 pim_sock_delete(ifc->ifp,
686 "last address has been removed from interface");
687 }
688
689 void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
690 {
691 struct interface *ifp;
692
693 assert(ifc);
694 ifp = ifc->ifp;
695 assert(ifp);
696
697 if (PIM_DEBUG_ZEBRA)
698 zlog_debug("%s: %s ifindex=%d disconnected IP address %pFX %s",
699 __func__, ifp->name, ifp->ifindex, ifc->address,
700 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
701 ? "secondary"
702 : "primary");
703
704 detect_address_change(ifp, force_prim_as_any, __func__);
705
706 pim_if_addr_del_igmp(ifc);
707 pim_if_addr_del_pim(ifc);
708 }
709
710 void pim_if_addr_add_all(struct interface *ifp)
711 {
712 struct connected *ifc;
713 struct listnode *node;
714 struct listnode *nextnode;
715 int v4_addrs = 0;
716 int v6_addrs = 0;
717 struct pim_interface *pim_ifp = ifp->info;
718 bool vxlan_term;
719
720
721 /* PIM/IGMP enabled ? */
722 if (!pim_ifp)
723 return;
724
725 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
726 struct prefix *p = ifc->address;
727
728 if (p->family != AF_INET)
729 v6_addrs++;
730 else
731 v4_addrs++;
732 pim_if_addr_add(ifc);
733 }
734
735 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
736 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
737
738 /* Interface has a valid primary address ? */
739 if (!pim_addr_is_any(pim_ifp->primary_address)) {
740
741 /* Interface has a valid socket ? */
742 if (pim_ifp->pim_sock_fd < 0) {
743 if (pim_sock_add(ifp)) {
744 zlog_warn(
745 "Failure creating PIM socket for interface %s",
746 ifp->name);
747 }
748 }
749 }
750 } /* pim */
751 }
752 /*
753 * PIM or IGMP is enabled on interface, and there is at least one
754 * address assigned, then try to create a vif_index.
755 */
756 if (pim_ifp->mroute_vif_index < 0) {
757 vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
758 pim_if_add_vif(ifp, false, vxlan_term);
759 }
760 pim_ifchannel_scan_forward_start(ifp);
761
762 pim_rp_setup(pim_ifp->pim);
763 pim_rp_check_on_if_add(pim_ifp);
764 }
765
766 void pim_if_addr_del_all(struct interface *ifp)
767 {
768 struct connected *ifc;
769 struct listnode *node;
770 struct listnode *nextnode;
771 struct pim_instance *pim;
772
773 pim = ifp->vrf->info;
774 if (!pim)
775 return;
776
777 /* PIM/IGMP enabled ? */
778 if (!ifp->info)
779 return;
780
781 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
782 struct prefix *p = ifc->address;
783
784 if (p->family != AF_INET)
785 continue;
786
787 pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */);
788 }
789
790 pim_rp_setup(pim);
791 pim_i_am_rp_re_evaluate(pim);
792 }
793
794 void pim_if_addr_del_all_igmp(struct interface *ifp)
795 {
796 struct connected *ifc;
797 struct listnode *node;
798 struct listnode *nextnode;
799
800 /* PIM/IGMP enabled ? */
801 if (!ifp->info)
802 return;
803
804 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
805 struct prefix *p = ifc->address;
806
807 if (p->family != AF_INET)
808 continue;
809
810 pim_if_addr_del_igmp(ifc);
811 }
812 }
813
814 pim_addr pim_find_primary_addr(struct interface *ifp)
815 {
816 struct connected *ifc;
817 struct listnode *node;
818 int v4_addrs = 0;
819 int v6_addrs = 0;
820 struct pim_interface *pim_ifp = ifp->info;
821
822 if (pim_ifp && !pim_addr_is_any(pim_ifp->update_source)) {
823 return pim_ifp->update_source;
824 }
825
826 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
827 pim_addr addr;
828
829 switch (ifc->address->family) {
830 case AF_INET:
831 v4_addrs++;
832 break;
833 case AF_INET6:
834 v6_addrs++;
835 break;
836 default:
837 continue;
838 }
839
840 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
841 continue;
842
843 if (ifc->address->family != PIM_AF)
844 continue;
845
846 addr = pim_addr_from_prefix(ifc->address);
847
848 #if PIM_IPV == 6
849 if (!IN6_IS_ADDR_LINKLOCAL(&addr))
850 continue;
851 #endif
852 return addr;
853 }
854
855 #if PIM_IPV == 4
856 /*
857 * If we have no v4_addrs and v6 is configured
858 * We probably are using unnumbered
859 * So let's grab the loopbacks v4 address
860 * and use that as the primary address
861 */
862 if (!v4_addrs && v6_addrs) {
863 struct interface *lo_ifp;
864
865 // DBS - Come back and check here
866 if (ifp->vrf->vrf_id == VRF_DEFAULT)
867 lo_ifp = if_lookup_by_name("lo", ifp->vrf->vrf_id);
868 else
869 lo_ifp = if_lookup_by_name(ifp->vrf->name,
870 ifp->vrf->vrf_id);
871
872 if (lo_ifp && (lo_ifp != ifp))
873 return pim_find_primary_addr(lo_ifp);
874 }
875 #endif
876 return PIMADDR_ANY;
877 }
878
879 static int pim_iface_next_vif_index(struct interface *ifp)
880 {
881 struct pim_interface *pim_ifp = ifp->info;
882 struct pim_instance *pim = pim_ifp->pim;
883 int i;
884
885 /*
886 * The pimreg vif is always going to be in index 0
887 * of the table.
888 */
889 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
890 return 0;
891
892 for (i = 1; i < MAXVIFS; i++) {
893 if (pim->iface_vif_index[i] == 0)
894 return i;
895 }
896 return MAXVIFS;
897 }
898
899 /*
900 pim_if_add_vif() uses ifindex as vif_index
901
902 see also pim_if_find_vifindex_by_ifindex()
903 */
904 int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
905 {
906 struct pim_interface *pim_ifp = ifp->info;
907 pim_addr ifaddr;
908 unsigned char flags = 0;
909
910 assert(pim_ifp);
911
912 if (pim_ifp->mroute_vif_index > 0) {
913 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
914 __func__, pim_ifp->mroute_vif_index, ifp->name,
915 ifp->ifindex);
916 return -1;
917 }
918
919 if (ifp->ifindex < 0) {
920 zlog_warn("%s: ifindex=%d < 1 on interface %s", __func__,
921 ifp->ifindex, ifp->name);
922 return -2;
923 }
924
925 ifaddr = pim_ifp->primary_address;
926 if (!ispimreg && !is_vxlan_term && pim_addr_is_any(ifaddr)) {
927 zlog_warn(
928 "%s: could not get address for interface %s ifindex=%d",
929 __func__, ifp->name, ifp->ifindex);
930 return -4;
931 }
932
933 pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp);
934
935 if (pim_ifp->mroute_vif_index >= MAXVIFS) {
936 zlog_warn(
937 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
938 __func__, MAXVIFS, ifp->name);
939 return -3;
940 }
941
942 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
943 flags = VIFF_REGISTER;
944 #ifdef VIFF_USE_IFINDEX
945 else
946 flags = VIFF_USE_IFINDEX;
947 #endif
948
949 if (pim_mroute_add_vif(ifp, ifaddr, flags)) {
950 /* pim_mroute_add_vif reported error */
951 return -5;
952 }
953
954 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
955
956 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
957 pim_vxlan_add_vif(ifp);
958
959 return 0;
960 }
961
962 int pim_if_del_vif(struct interface *ifp)
963 {
964 struct pim_interface *pim_ifp = ifp->info;
965
966 if (pim_ifp->mroute_vif_index < 1) {
967 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
968 __func__, pim_ifp->mroute_vif_index, ifp->name,
969 ifp->ifindex);
970 return -1;
971 }
972
973 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
974 pim_vxlan_del_vif(ifp);
975
976 pim_mroute_del_vif(ifp);
977
978 /*
979 Update vif_index
980 */
981 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 0;
982
983 pim_ifp->mroute_vif_index = -1;
984
985 return 0;
986 }
987
988 // DBS - VRF Revist
989 struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
990 ifindex_t vif_index)
991 {
992 struct interface *ifp;
993
994 FOR_ALL_INTERFACES (pim->vrf, ifp) {
995 if (ifp->info) {
996 struct pim_interface *pim_ifp;
997 pim_ifp = ifp->info;
998
999 if (vif_index == pim_ifp->mroute_vif_index)
1000 return ifp;
1001 }
1002 }
1003
1004 return 0;
1005 }
1006
1007 /*
1008 pim_if_add_vif() uses ifindex as vif_index
1009 */
1010 int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex)
1011 {
1012 struct pim_interface *pim_ifp;
1013 struct interface *ifp;
1014
1015 ifp = if_lookup_by_index(ifindex, pim->vrf->vrf_id);
1016 if (!ifp || !ifp->info)
1017 return -1;
1018 pim_ifp = ifp->info;
1019
1020 return pim_ifp->mroute_vif_index;
1021 }
1022
1023 int pim_if_lan_delay_enabled(struct interface *ifp)
1024 {
1025 struct pim_interface *pim_ifp;
1026
1027 pim_ifp = ifp->info;
1028 assert(pim_ifp);
1029 assert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
1030
1031 return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;
1032 }
1033
1034 uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp)
1035 {
1036 if (pim_if_lan_delay_enabled(ifp)) {
1037 struct pim_interface *pim_ifp;
1038 pim_ifp = ifp->info;
1039 return pim_ifp->pim_neighbors_highest_propagation_delay_msec;
1040 } else {
1041 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
1042 }
1043 }
1044
1045 uint16_t pim_if_effective_override_interval_msec(struct interface *ifp)
1046 {
1047 if (pim_if_lan_delay_enabled(ifp)) {
1048 struct pim_interface *pim_ifp;
1049 pim_ifp = ifp->info;
1050 return pim_ifp->pim_neighbors_highest_override_interval_msec;
1051 } else {
1052 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
1053 }
1054 }
1055
1056 int pim_if_t_override_msec(struct interface *ifp)
1057 {
1058 int effective_override_interval_msec;
1059 int t_override_msec;
1060
1061 effective_override_interval_msec =
1062 pim_if_effective_override_interval_msec(ifp);
1063
1064 t_override_msec =
1065 frr_weak_random() % (effective_override_interval_msec + 1);
1066
1067 return t_override_msec;
1068 }
1069
1070 uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
1071 {
1072 return pim_if_effective_propagation_delay_msec(ifp)
1073 + pim_if_effective_override_interval_msec(ifp);
1074 }
1075
1076 /*
1077 RFC 4601: 4.1.6. State Summarization Macros
1078
1079 The function NBR( I, A ) uses information gathered through PIM Hello
1080 messages to map the IP address A of a directly connected PIM
1081 neighbor router on interface I to the primary IP address of the same
1082 router (Section 4.3.4). The primary IP address of a neighbor is the
1083 address that it uses as the source of its PIM Hello messages.
1084 */
1085 struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, pim_addr addr)
1086 {
1087 struct listnode *neighnode;
1088 struct pim_neighbor *neigh;
1089 struct pim_interface *pim_ifp;
1090 struct prefix p;
1091
1092 assert(ifp);
1093
1094 pim_ifp = ifp->info;
1095 if (!pim_ifp) {
1096 zlog_warn("%s: multicast not enabled on interface %s", __func__,
1097 ifp->name);
1098 return 0;
1099 }
1100
1101 pim_addr_to_prefix(&p, addr);
1102
1103 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1104 neigh)) {
1105
1106 /* primary address ? */
1107 if (!pim_addr_cmp(neigh->source_addr, addr))
1108 return neigh;
1109
1110 /* secondary address ? */
1111 if (pim_neighbor_find_secondary(neigh, &p))
1112 return neigh;
1113 }
1114
1115 if (PIM_DEBUG_PIM_TRACE)
1116 zlog_debug(
1117 "%s: neighbor not found for address %pPA on interface %s",
1118 __func__, &addr, ifp->name);
1119
1120 return NULL;
1121 }
1122
1123 long pim_if_t_suppressed_msec(struct interface *ifp)
1124 {
1125 struct pim_interface *pim_ifp;
1126 long t_suppressed_msec;
1127 uint32_t ramount = 0;
1128
1129 pim_ifp = ifp->info;
1130 assert(pim_ifp);
1131
1132 /* join suppression disabled ? */
1133 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPPRESSION(pim_ifp->options))
1134 return 0;
1135
1136 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1137 ramount = 1100 + (frr_weak_random() % (1400 - 1100 + 1));
1138 t_suppressed_msec = router->t_periodic * ramount;
1139
1140 return t_suppressed_msec;
1141 }
1142
1143 static void igmp_join_free(struct gm_join *ij)
1144 {
1145 XFREE(MTYPE_PIM_IGMP_JOIN, ij);
1146 }
1147
1148 static struct gm_join *igmp_join_find(struct list *join_list,
1149 struct in_addr group_addr,
1150 struct in_addr source_addr)
1151 {
1152 struct listnode *node;
1153 struct gm_join *ij;
1154
1155 assert(join_list);
1156
1157 for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) {
1158 if ((group_addr.s_addr == ij->group_addr.s_addr)
1159 && (source_addr.s_addr == ij->source_addr.s_addr))
1160 return ij;
1161 }
1162
1163 return 0;
1164 }
1165
1166 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
1167 struct in_addr group_addr, struct in_addr source_addr)
1168 {
1169 int join_fd;
1170
1171 join_fd = pim_socket_raw(IPPROTO_IGMP);
1172 if (join_fd < 0) {
1173 return -1;
1174 }
1175
1176 if (pim_igmp_join_source(join_fd, ifindex, group_addr, source_addr)) {
1177 char group_str[INET_ADDRSTRLEN];
1178 char source_str[INET_ADDRSTRLEN];
1179 pim_inet4_dump("<grp?>", group_addr, group_str,
1180 sizeof(group_str));
1181 pim_inet4_dump("<src?>", source_addr, source_str,
1182 sizeof(source_str));
1183 zlog_warn(
1184 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1185 __func__, join_fd, group_str, source_str, ifindex,
1186 ifname, errno, safe_strerror(errno));
1187
1188 close(join_fd);
1189 return -2;
1190 }
1191
1192 return join_fd;
1193 }
1194
1195 static struct gm_join *igmp_join_new(struct interface *ifp,
1196 struct in_addr group_addr,
1197 struct in_addr source_addr)
1198 {
1199 struct pim_interface *pim_ifp;
1200 struct gm_join *ij;
1201 int join_fd;
1202
1203 pim_ifp = ifp->info;
1204 assert(pim_ifp);
1205
1206 join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
1207 source_addr);
1208 if (join_fd < 0) {
1209 char group_str[INET_ADDRSTRLEN];
1210 char source_str[INET_ADDRSTRLEN];
1211
1212 pim_inet4_dump("<grp?>", group_addr, group_str,
1213 sizeof(group_str));
1214 pim_inet4_dump("<src?>", source_addr, source_str,
1215 sizeof(source_str));
1216 zlog_warn(
1217 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1218 __func__, group_str, source_str, ifp->name);
1219 return 0;
1220 }
1221
1222 ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
1223
1224 ij->sock_fd = join_fd;
1225 ij->group_addr = group_addr;
1226 ij->source_addr = source_addr;
1227 ij->sock_creation = pim_time_monotonic_sec();
1228
1229 listnode_add(pim_ifp->gm_join_list, ij);
1230
1231 return ij;
1232 }
1233
1234 ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
1235 struct in_addr source_addr)
1236 {
1237 struct pim_interface *pim_ifp;
1238 struct gm_join *ij;
1239
1240 pim_ifp = ifp->info;
1241 if (!pim_ifp) {
1242 return ferr_cfg_invalid("multicast not enabled on interface %s",
1243 ifp->name);
1244 }
1245
1246 if (!pim_ifp->gm_join_list) {
1247 pim_ifp->gm_join_list = list_new();
1248 pim_ifp->gm_join_list->del = (void (*)(void *))igmp_join_free;
1249 }
1250
1251 ij = igmp_join_find(pim_ifp->gm_join_list, group_addr, source_addr);
1252
1253 /* This interface has already been configured to join this IGMP group
1254 */
1255 if (ij) {
1256 return ferr_ok();
1257 }
1258
1259 (void)igmp_join_new(ifp, group_addr, source_addr);
1260
1261 if (PIM_DEBUG_IGMP_EVENTS) {
1262 char group_str[INET_ADDRSTRLEN];
1263 char source_str[INET_ADDRSTRLEN];
1264 pim_inet4_dump("<grp?>", group_addr, group_str,
1265 sizeof(group_str));
1266 pim_inet4_dump("<src?>", source_addr, source_str,
1267 sizeof(source_str));
1268 zlog_debug(
1269 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1270 __func__, source_str, group_str, ifp->name);
1271 }
1272
1273 return ferr_ok();
1274 }
1275
1276
1277 int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
1278 struct in_addr source_addr)
1279 {
1280 struct pim_interface *pim_ifp;
1281 struct gm_join *ij;
1282
1283 pim_ifp = ifp->info;
1284 if (!pim_ifp) {
1285 zlog_warn("%s: multicast not enabled on interface %s", __func__,
1286 ifp->name);
1287 return -1;
1288 }
1289
1290 if (!pim_ifp->gm_join_list) {
1291 zlog_warn("%s: no IGMP join on interface %s", __func__,
1292 ifp->name);
1293 return -2;
1294 }
1295
1296 ij = igmp_join_find(pim_ifp->gm_join_list, group_addr, source_addr);
1297 if (!ij) {
1298 char group_str[INET_ADDRSTRLEN];
1299 char source_str[INET_ADDRSTRLEN];
1300 pim_inet4_dump("<grp?>", group_addr, group_str,
1301 sizeof(group_str));
1302 pim_inet4_dump("<src?>", source_addr, source_str,
1303 sizeof(source_str));
1304 zlog_warn(
1305 "%s: could not find IGMP group %s source %s on interface %s",
1306 __func__, group_str, source_str, ifp->name);
1307 return -3;
1308 }
1309
1310 if (close(ij->sock_fd)) {
1311 char group_str[INET_ADDRSTRLEN];
1312 char source_str[INET_ADDRSTRLEN];
1313 pim_inet4_dump("<grp?>", group_addr, group_str,
1314 sizeof(group_str));
1315 pim_inet4_dump("<src?>", source_addr, source_str,
1316 sizeof(source_str));
1317 zlog_warn(
1318 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1319 __func__, ij->sock_fd, group_str, source_str, ifp->name,
1320 errno, safe_strerror(errno));
1321 /* warning only */
1322 }
1323 listnode_delete(pim_ifp->gm_join_list, ij);
1324 igmp_join_free(ij);
1325 if (listcount(pim_ifp->gm_join_list) < 1) {
1326 list_delete(&pim_ifp->gm_join_list);
1327 pim_ifp->gm_join_list = 0;
1328 }
1329
1330 return 0;
1331 }
1332
1333 static void pim_if_igmp_join_del_all(struct interface *ifp)
1334 {
1335 struct pim_interface *pim_ifp;
1336 struct listnode *node;
1337 struct listnode *nextnode;
1338 struct gm_join *ij;
1339
1340 pim_ifp = ifp->info;
1341 if (!pim_ifp) {
1342 zlog_warn("%s: multicast not enabled on interface %s", __func__,
1343 ifp->name);
1344 return;
1345 }
1346
1347 if (!pim_ifp->gm_join_list)
1348 return;
1349
1350 for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node, nextnode, ij))
1351 pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);
1352 }
1353
1354 /*
1355 RFC 4601
1356
1357 Transitions from "I am Assert Loser" State
1358
1359 Current Winner's GenID Changes or NLT Expires
1360
1361 The Neighbor Liveness Timer associated with the current winner
1362 expires or we receive a Hello message from the current winner
1363 reporting a different GenID from the one it previously reported.
1364 This indicates that the current winner's interface or router has
1365 gone down (and may have come back up), and so we must assume it no
1366 longer knows it was the winner.
1367 */
1368 void pim_if_assert_on_neighbor_down(struct interface *ifp, pim_addr neigh_addr)
1369 {
1370 struct pim_interface *pim_ifp;
1371 struct pim_ifchannel *ch;
1372
1373 pim_ifp = ifp->info;
1374 assert(pim_ifp);
1375
1376 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1377 /* Is (S,G,I) assert loser ? */
1378 if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
1379 continue;
1380 /* Dead neighbor was winner ? */
1381 if (pim_addr_cmp(ch->ifassert_winner, neigh_addr))
1382 continue;
1383
1384 assert_action_a5(ch);
1385 }
1386 }
1387
1388 void pim_if_update_join_desired(struct pim_interface *pim_ifp)
1389 {
1390 struct pim_ifchannel *ch;
1391
1392 /* clear off flag from interface's upstreams */
1393 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1394 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1395 ch->upstream->flags);
1396 }
1397
1398 /* scan per-interface (S,G,I) state on this I interface */
1399 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1400 struct pim_upstream *up = ch->upstream;
1401
1402 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
1403 continue;
1404
1405 /* update join_desired for the global (S,G) state */
1406 pim_upstream_update_join_desired(pim_ifp->pim, up);
1407 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags);
1408 }
1409 }
1410
1411 void pim_if_update_assert_tracking_desired(struct interface *ifp)
1412 {
1413 struct pim_interface *pim_ifp;
1414 struct pim_ifchannel *ch;
1415
1416 pim_ifp = ifp->info;
1417 if (!pim_ifp)
1418 return;
1419
1420 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1421 pim_ifchannel_update_assert_tracking_desired(ch);
1422 }
1423 }
1424
1425 /*
1426 * PIM wants to have an interface pointer for everything it does.
1427 * The pimreg is a special interface that we have that is not
1428 * quite an inteface but a VIF is created for it.
1429 */
1430 void pim_if_create_pimreg(struct pim_instance *pim)
1431 {
1432 char pimreg_name[INTERFACE_NAMSIZ];
1433
1434 if (!pim->regiface) {
1435 if (pim->vrf->vrf_id == VRF_DEFAULT)
1436 strlcpy(pimreg_name, "pimreg", sizeof(pimreg_name));
1437 else
1438 snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
1439 pim->vrf->data.l.table_id);
1440
1441 pim->regiface = if_get_by_name(pimreg_name, pim->vrf->vrf_id,
1442 pim->vrf->name);
1443 pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
1444
1445 pim_if_new(pim->regiface, false, false, true,
1446 false /*vxlan_term*/);
1447 /*
1448 * On vrf moves we delete the interface if there
1449 * is nothing going on with it. We cannot have
1450 * the pimregiface deleted.
1451 */
1452 pim->regiface->configured = true;
1453
1454 }
1455 }
1456
1457 struct prefix *pim_if_connected_to_source(struct interface *ifp, pim_addr src)
1458 {
1459 struct listnode *cnode;
1460 struct connected *c;
1461 struct prefix p;
1462
1463 if (!ifp)
1464 return NULL;
1465
1466 pim_addr_to_prefix(&p, src);
1467
1468 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
1469 if (c->address->family != PIM_AF)
1470 continue;
1471 if (prefix_match(c->address, &p))
1472 return c->address;
1473 if (CONNECTED_PEER(c) && prefix_match(c->destination, &p))
1474 /* this is not a typo, on PtP we need to return the
1475 * *local* address that lines up with src.
1476 */
1477 return c->address;
1478 }
1479
1480 return NULL;
1481 }
1482
1483 bool pim_if_is_vrf_device(struct interface *ifp)
1484 {
1485 if (if_is_vrf(ifp))
1486 return true;
1487
1488 return false;
1489 }
1490
1491 int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
1492 {
1493 struct pim_ifchannel *ch;
1494 int count = 0;
1495
1496 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1497 count++;
1498 }
1499
1500 return count;
1501 }
1502
1503 static int pim_ifp_create(struct interface *ifp)
1504 {
1505 struct pim_instance *pim;
1506
1507 pim = ifp->vrf->info;
1508 if (PIM_DEBUG_ZEBRA) {
1509 zlog_debug(
1510 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1511 __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
1512 ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
1513 ifp->mtu, if_is_operative(ifp));
1514 }
1515
1516 if (if_is_operative(ifp)) {
1517 struct pim_interface *pim_ifp;
1518
1519 pim_ifp = ifp->info;
1520 /*
1521 * If we have a pim_ifp already and this is an if_add
1522 * that means that we probably have a vrf move event
1523 * If that is the case, set the proper vrfness.
1524 */
1525 if (pim_ifp)
1526 pim_ifp->pim = pim;
1527 pim_if_addr_add_all(ifp);
1528
1529 /*
1530 * Due to ordering issues based upon when
1531 * a command is entered we should ensure that
1532 * the pim reg is created for this vrf if we
1533 * have configuration for it already.
1534 *
1535 * this is a no-op if it's already been done.
1536 */
1537 pim_if_create_pimreg(pim);
1538 }
1539
1540 /*
1541 * If we are a vrf device that is up, open up the pim_socket for
1542 * listening
1543 * to incoming pim messages irrelevant if the user has configured us
1544 * for pim or not.
1545 */
1546 if (pim_if_is_vrf_device(ifp)) {
1547 struct pim_interface *pim_ifp;
1548
1549 if (!ifp->info) {
1550 pim_ifp = pim_if_new(ifp, false, false, false,
1551 false /*vxlan_term*/);
1552 ifp->info = pim_ifp;
1553 }
1554
1555 pim_sock_add(ifp);
1556 }
1557
1558 if (!strncmp(ifp->name, PIM_VXLAN_TERM_DEV_NAME,
1559 sizeof(PIM_VXLAN_TERM_DEV_NAME))) {
1560 if (pim->mcast_if_count < MAXVIFS)
1561 pim_vxlan_add_term_dev(pim, ifp);
1562 else
1563 zlog_warn(
1564 "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
1565 __func__, ifp->name, MAXVIFS);
1566 }
1567
1568 return 0;
1569 }
1570
1571 static int pim_ifp_up(struct interface *ifp)
1572 {
1573 struct pim_interface *pim_ifp;
1574 struct pim_instance *pim;
1575 uint32_t table_id;
1576
1577 if (PIM_DEBUG_ZEBRA) {
1578 zlog_debug(
1579 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1580 __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
1581 ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
1582 ifp->mtu, if_is_operative(ifp));
1583 }
1584
1585 pim = ifp->vrf->info;
1586
1587 pim_ifp = ifp->info;
1588 /*
1589 * If we have a pim_ifp already and this is an if_add
1590 * that means that we probably have a vrf move event
1591 * If that is the case, set the proper vrfness.
1592 */
1593 if (pim_ifp)
1594 pim_ifp->pim = pim;
1595
1596 /*
1597 pim_if_addr_add_all() suffices for bringing up both IGMP and
1598 PIM
1599 */
1600 pim_if_addr_add_all(ifp);
1601
1602 /*
1603 * If we have a pimreg device callback and it's for a specific
1604 * table set the master appropriately
1605 */
1606 if (sscanf(ifp->name, "pimreg%" SCNu32, &table_id) == 1) {
1607 struct vrf *vrf;
1608 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1609 if ((table_id == vrf->data.l.table_id)
1610 && (ifp->vrf->vrf_id != vrf->vrf_id)) {
1611 struct interface *master = if_lookup_by_name(
1612 vrf->name, vrf->vrf_id);
1613
1614 if (!master) {
1615 zlog_debug(
1616 "%s: Unable to find Master interface for %s",
1617 __func__, vrf->name);
1618 return 0;
1619 }
1620 pim_zebra_interface_set_master(master, ifp);
1621 }
1622 }
1623 }
1624 return 0;
1625 }
1626
1627 static int pim_ifp_down(struct interface *ifp)
1628 {
1629 if (PIM_DEBUG_ZEBRA) {
1630 zlog_debug(
1631 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1632 __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
1633 ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
1634 ifp->mtu, if_is_operative(ifp));
1635 }
1636
1637 if (!if_is_operative(ifp)) {
1638 pim_ifchannel_delete_all(ifp);
1639 /*
1640 pim_if_addr_del_all() suffices for shutting down IGMP,
1641 but not for shutting down PIM
1642 */
1643 pim_if_addr_del_all(ifp);
1644
1645 /*
1646 pim_sock_delete() closes the socket, stops read and timer
1647 threads,
1648 and kills all neighbors.
1649 */
1650 if (ifp->info) {
1651 pim_sock_delete(ifp, "link down");
1652 }
1653 }
1654
1655 if (ifp->info) {
1656 pim_if_del_vif(ifp);
1657 pim_ifstat_reset(ifp);
1658 }
1659
1660 return 0;
1661 }
1662
1663 static int pim_ifp_destroy(struct interface *ifp)
1664 {
1665 struct pim_instance *pim;
1666
1667 if (PIM_DEBUG_ZEBRA) {
1668 zlog_debug(
1669 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1670 __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
1671 ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
1672 ifp->mtu, if_is_operative(ifp));
1673 }
1674
1675 if (!if_is_operative(ifp))
1676 pim_if_addr_del_all(ifp);
1677
1678 pim = ifp->vrf->info;
1679 if (pim && pim->vxlan.term_if == ifp)
1680 pim_vxlan_del_term_dev(pim);
1681
1682 return 0;
1683 }
1684
1685 static int pim_if_new_hook(struct interface *ifp)
1686 {
1687 return 0;
1688 }
1689
1690 static int pim_if_delete_hook(struct interface *ifp)
1691 {
1692 if (ifp->info)
1693 pim_if_delete(ifp);
1694
1695 return 0;
1696 }
1697
1698 void pim_iface_init(void)
1699 {
1700 hook_register_prio(if_add, 0, pim_if_new_hook);
1701 hook_register_prio(if_del, 0, pim_if_delete_hook);
1702
1703 if_zapi_callbacks(pim_ifp_create, pim_ifp_up, pim_ifp_down,
1704 pim_ifp_destroy);
1705 }