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