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