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