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