]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_iface.c
Merge pull request #6385 from GalaxyGorilla/bfd_igp_topotest
[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 zassert(ifp);
119 zassert(!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 zassert(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 zassert(ifp);
202 pim_ifp = ifp->info;
203 zassert(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 zassert(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 zassert(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 zassert(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)) {
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 zassert(ifc);
511
512 ifp = ifc->ifp;
513 zassert(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 char buf[BUFSIZ];
523 prefix2str(ifc->address, buf, BUFSIZ);
524 zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
525 __func__, ifp->name, ifp->ifindex, buf,
526 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
527 ? "secondary"
528 : "primary");
529 }
530
531 ifaddr = ifc->address->u.prefix4;
532
533 detect_address_change(ifp, 0, __func__);
534
535 // if (ifc->address->family != AF_INET)
536 // return;
537
538 if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
539 struct igmp_sock *igmp;
540
541 /* lookup IGMP socket */
542 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
543 ifaddr);
544 if (!igmp) {
545 /* if addr new, add IGMP socket */
546 if (ifc->address->family == AF_INET)
547 pim_igmp_sock_add(pim_ifp->igmp_socket_list,
548 ifaddr, ifp, false);
549 } else if (igmp->mtrace_only) {
550 igmp_sock_delete(igmp);
551 pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
552 ifp, false);
553 }
554
555 /* Replay Static IGMP groups */
556 if (pim_ifp->igmp_join_list) {
557 struct listnode *node;
558 struct listnode *nextnode;
559 struct igmp_join *ij;
560 int join_fd;
561
562 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node,
563 nextnode, ij)) {
564 /* Close socket and reopen with Source and Group
565 */
566 close(ij->sock_fd);
567 join_fd = igmp_join_sock(
568 ifp->name, ifp->ifindex, ij->group_addr,
569 ij->source_addr);
570 if (join_fd < 0) {
571 char group_str[INET_ADDRSTRLEN];
572 char source_str[INET_ADDRSTRLEN];
573 pim_inet4_dump("<grp?>", ij->group_addr,
574 group_str,
575 sizeof(group_str));
576 pim_inet4_dump(
577 "<src?>", ij->source_addr,
578 source_str, sizeof(source_str));
579 zlog_warn(
580 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
581 __func__, group_str, source_str,
582 ifp->name);
583 /* warning only */
584 } else
585 ij->sock_fd = join_fd;
586 }
587 }
588 } /* igmp */
589 else {
590 struct igmp_sock *igmp;
591
592 /* lookup IGMP socket */
593 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
594 ifaddr);
595 if (ifc->address->family == AF_INET) {
596 if (igmp)
597 igmp_sock_delete(igmp);
598 /* if addr new, add IGMP socket */
599 pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
600 ifp, true);
601 }
602 } /* igmp mtrace only */
603
604 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
605
606 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
607
608 /* Interface has a valid socket ? */
609 if (pim_ifp->pim_sock_fd < 0) {
610 if (pim_sock_add(ifp)) {
611 zlog_warn(
612 "Failure creating PIM socket for interface %s",
613 ifp->name);
614 }
615 }
616 struct pim_nexthop_cache *pnc = NULL;
617 struct pim_rpf rpf;
618 struct zclient *zclient = NULL;
619
620 zclient = pim_zebra_zclient_get();
621 /* RP config might come prior to (local RP's interface)
622 IF UP event.
623 In this case, pnc would not have pim enabled
624 nexthops.
625 Once Interface is UP and pim info is available,
626 reregister
627 with RNH address to receive update and add the
628 interface as nexthop. */
629 memset(&rpf, 0, sizeof(struct pim_rpf));
630 rpf.rpf_addr.family = AF_INET;
631 rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
632 rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
633 pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
634 if (pnc)
635 pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
636 pnc,
637 ZEBRA_NEXTHOP_REGISTER);
638 }
639 } /* pim */
640
641 /*
642 PIM or IGMP is enabled on interface, and there is at least one
643 address assigned, then try to create a vif_index.
644 */
645 if (pim_ifp->mroute_vif_index < 0) {
646 vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
647 pim_if_add_vif(ifp, false, vxlan_term);
648 }
649 pim_ifchannel_scan_forward_start(ifp);
650 }
651
652 static void pim_if_addr_del_igmp(struct connected *ifc)
653 {
654 struct pim_interface *pim_ifp = ifc->ifp->info;
655 struct igmp_sock *igmp;
656 struct in_addr ifaddr;
657
658 if (ifc->address->family != AF_INET) {
659 /* non-IPv4 address */
660 return;
661 }
662
663 if (!pim_ifp) {
664 /* IGMP not enabled on interface */
665 return;
666 }
667
668 ifaddr = ifc->address->u.prefix4;
669
670 /* lookup IGMP socket */
671 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
672 if (igmp) {
673 /* if addr found, del IGMP socket */
674 igmp_sock_delete(igmp);
675 }
676 }
677
678 static void pim_if_addr_del_pim(struct connected *ifc)
679 {
680 struct pim_interface *pim_ifp = ifc->ifp->info;
681
682 if (ifc->address->family != AF_INET) {
683 /* non-IPv4 address */
684 return;
685 }
686
687 if (!pim_ifp) {
688 /* PIM not enabled on interface */
689 return;
690 }
691
692 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
693 /* Interface keeps a valid primary address */
694 return;
695 }
696
697 if (pim_ifp->pim_sock_fd < 0) {
698 /* Interface does not hold a valid socket any longer */
699 return;
700 }
701
702 /*
703 pim_sock_delete() closes the socket, stops read and timer threads,
704 and kills all neighbors.
705 */
706 pim_sock_delete(ifc->ifp,
707 "last address has been removed from interface");
708 }
709
710 void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
711 {
712 struct interface *ifp;
713
714 zassert(ifc);
715 ifp = ifc->ifp;
716 zassert(ifp);
717
718 if (PIM_DEBUG_ZEBRA) {
719 char buf[BUFSIZ];
720 prefix2str(ifc->address, buf, BUFSIZ);
721 zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
722 __func__, ifp->name, ifp->ifindex, buf,
723 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
724 ? "secondary"
725 : "primary");
726 }
727
728 detect_address_change(ifp, force_prim_as_any, __func__);
729
730 pim_if_addr_del_igmp(ifc);
731 pim_if_addr_del_pim(ifc);
732 }
733
734 void pim_if_addr_add_all(struct interface *ifp)
735 {
736 struct connected *ifc;
737 struct listnode *node;
738 struct listnode *nextnode;
739 int v4_addrs = 0;
740 int v6_addrs = 0;
741 struct pim_interface *pim_ifp = ifp->info;
742 bool vxlan_term;
743
744
745 /* PIM/IGMP enabled ? */
746 if (!pim_ifp)
747 return;
748
749 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
750 struct prefix *p = ifc->address;
751
752 if (p->family != AF_INET)
753 v6_addrs++;
754 else
755 v4_addrs++;
756 pim_if_addr_add(ifc);
757 }
758
759 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
760 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
761
762 /* Interface has a valid primary address ? */
763 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
764
765 /* Interface has a valid socket ? */
766 if (pim_ifp->pim_sock_fd < 0) {
767 if (pim_sock_add(ifp)) {
768 zlog_warn(
769 "Failure creating PIM socket for interface %s",
770 ifp->name);
771 }
772 }
773 }
774 } /* pim */
775 }
776 /*
777 * PIM or IGMP is enabled on interface, and there is at least one
778 * address assigned, then try to create a vif_index.
779 */
780 if (pim_ifp->mroute_vif_index < 0) {
781 vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
782 pim_if_add_vif(ifp, false, vxlan_term);
783 }
784 pim_ifchannel_scan_forward_start(ifp);
785
786 pim_rp_setup(pim_ifp->pim);
787 pim_rp_check_on_if_add(pim_ifp);
788 }
789
790 void pim_if_addr_del_all(struct interface *ifp)
791 {
792 struct connected *ifc;
793 struct listnode *node;
794 struct listnode *nextnode;
795 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
796 struct pim_instance *pim;
797
798 if (!vrf)
799 return;
800 pim = vrf->info;
801
802 /* PIM/IGMP enabled ? */
803 if (!ifp->info)
804 return;
805
806 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
807 struct prefix *p = ifc->address;
808
809 if (p->family != AF_INET)
810 continue;
811
812 pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */);
813 }
814
815 pim_rp_setup(pim);
816 pim_i_am_rp_re_evaluate(pim);
817 }
818
819 void pim_if_addr_del_all_igmp(struct interface *ifp)
820 {
821 struct connected *ifc;
822 struct listnode *node;
823 struct listnode *nextnode;
824
825 /* PIM/IGMP enabled ? */
826 if (!ifp->info)
827 return;
828
829 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
830 struct prefix *p = ifc->address;
831
832 if (p->family != AF_INET)
833 continue;
834
835 pim_if_addr_del_igmp(ifc);
836 }
837 }
838
839 void pim_if_addr_del_all_pim(struct interface *ifp)
840 {
841 struct connected *ifc;
842 struct listnode *node;
843 struct listnode *nextnode;
844
845 /* PIM/IGMP enabled ? */
846 if (!ifp->info)
847 return;
848
849 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
850 struct prefix *p = ifc->address;
851
852 if (p->family != AF_INET)
853 continue;
854
855 pim_if_addr_del_pim(ifc);
856 }
857 }
858
859 struct in_addr pim_find_primary_addr(struct interface *ifp)
860 {
861 struct connected *ifc;
862 struct listnode *node;
863 struct in_addr addr = {0};
864 int v4_addrs = 0;
865 int v6_addrs = 0;
866 struct pim_interface *pim_ifp = ifp->info;
867 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
868
869 if (!vrf)
870 return addr;
871
872 if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
873 return pim_ifp->update_source;
874 }
875
876 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
877 struct prefix *p = ifc->address;
878
879 if (p->family != AF_INET) {
880 v6_addrs++;
881 continue;
882 }
883
884 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
885 zlog_warn(
886 "%s: null IPv4 address connected to interface %s",
887 __func__, ifp->name);
888 continue;
889 }
890
891 v4_addrs++;
892
893 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
894 continue;
895
896 return p->u.prefix4;
897 }
898
899 /*
900 * If we have no v4_addrs and v6 is configured
901 * We probably are using unnumbered
902 * So let's grab the loopbacks v4 address
903 * and use that as the primary address
904 */
905 if (!v4_addrs && v6_addrs) {
906 struct interface *lo_ifp;
907
908 // DBS - Come back and check here
909 if (ifp->vrf_id == VRF_DEFAULT)
910 lo_ifp = if_lookup_by_name("lo", vrf->vrf_id);
911 else
912 lo_ifp = if_lookup_by_name(vrf->name, vrf->vrf_id);
913
914 if (lo_ifp && (lo_ifp != ifp))
915 return pim_find_primary_addr(lo_ifp);
916 }
917
918 addr.s_addr = PIM_NET_INADDR_ANY;
919
920 return addr;
921 }
922
923 static int pim_iface_next_vif_index(struct interface *ifp)
924 {
925 struct pim_interface *pim_ifp = ifp->info;
926 struct pim_instance *pim = pim_ifp->pim;
927 int i;
928
929 /*
930 * The pimreg vif is always going to be in index 0
931 * of the table.
932 */
933 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
934 return 0;
935
936 for (i = 1; i < MAXVIFS; i++) {
937 if (pim->iface_vif_index[i] == 0)
938 return i;
939 }
940 return MAXVIFS;
941 }
942
943 /*
944 pim_if_add_vif() uses ifindex as vif_index
945
946 see also pim_if_find_vifindex_by_ifindex()
947 */
948 int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
949 {
950 struct pim_interface *pim_ifp = ifp->info;
951 struct in_addr ifaddr;
952 unsigned char flags = 0;
953
954 zassert(pim_ifp);
955
956 if (pim_ifp->mroute_vif_index > 0) {
957 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
958 __func__, pim_ifp->mroute_vif_index, ifp->name,
959 ifp->ifindex);
960 return -1;
961 }
962
963 if (ifp->ifindex < 0) {
964 zlog_warn("%s: ifindex=%d < 1 on interface %s", __func__,
965 ifp->ifindex, ifp->name);
966 return -2;
967 }
968
969 ifaddr = pim_ifp->primary_address;
970 if (!ispimreg && !is_vxlan_term && PIM_INADDR_IS_ANY(ifaddr)) {
971 zlog_warn(
972 "%s: could not get address for interface %s ifindex=%d",
973 __func__, ifp->name, ifp->ifindex);
974 return -4;
975 }
976
977 pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp);
978
979 if (pim_ifp->mroute_vif_index >= MAXVIFS) {
980 zlog_warn(
981 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
982 __func__, MAXVIFS, ifp->name);
983 return -3;
984 }
985
986 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
987 flags = VIFF_REGISTER;
988 #ifdef VIFF_USE_IFINDEX
989 else
990 flags = VIFF_USE_IFINDEX;
991 #endif
992
993 if (pim_mroute_add_vif(ifp, ifaddr, flags)) {
994 /* pim_mroute_add_vif reported error */
995 return -5;
996 }
997
998 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
999
1000 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
1001 pim_vxlan_add_vif(ifp);
1002
1003 return 0;
1004 }
1005
1006 int pim_if_del_vif(struct interface *ifp)
1007 {
1008 struct pim_interface *pim_ifp = ifp->info;
1009
1010 if (pim_ifp->mroute_vif_index < 1) {
1011 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1012 __func__, pim_ifp->mroute_vif_index, ifp->name,
1013 ifp->ifindex);
1014 return -1;
1015 }
1016
1017 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
1018 pim_vxlan_del_vif(ifp);
1019
1020 pim_mroute_del_vif(ifp);
1021
1022 /*
1023 Update vif_index
1024 */
1025 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 0;
1026
1027 pim_ifp->mroute_vif_index = -1;
1028
1029 return 0;
1030 }
1031
1032 // DBS - VRF Revist
1033 struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
1034 ifindex_t vif_index)
1035 {
1036 struct interface *ifp;
1037
1038 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1039 if (ifp->info) {
1040 struct pim_interface *pim_ifp;
1041 pim_ifp = ifp->info;
1042
1043 if (vif_index == pim_ifp->mroute_vif_index)
1044 return ifp;
1045 }
1046 }
1047
1048 return 0;
1049 }
1050
1051 /*
1052 pim_if_add_vif() uses ifindex as vif_index
1053 */
1054 int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex)
1055 {
1056 struct pim_interface *pim_ifp;
1057 struct interface *ifp;
1058
1059 ifp = if_lookup_by_index(ifindex, pim->vrf_id);
1060 if (!ifp || !ifp->info)
1061 return -1;
1062 pim_ifp = ifp->info;
1063
1064 return pim_ifp->mroute_vif_index;
1065 }
1066
1067 int pim_if_lan_delay_enabled(struct interface *ifp)
1068 {
1069 struct pim_interface *pim_ifp;
1070
1071 pim_ifp = ifp->info;
1072 zassert(pim_ifp);
1073 zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
1074
1075 return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;
1076 }
1077
1078 uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp)
1079 {
1080 if (pim_if_lan_delay_enabled(ifp)) {
1081 struct pim_interface *pim_ifp;
1082 pim_ifp = ifp->info;
1083 return pim_ifp->pim_neighbors_highest_propagation_delay_msec;
1084 } else {
1085 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
1086 }
1087 }
1088
1089 uint16_t pim_if_effective_override_interval_msec(struct interface *ifp)
1090 {
1091 if (pim_if_lan_delay_enabled(ifp)) {
1092 struct pim_interface *pim_ifp;
1093 pim_ifp = ifp->info;
1094 return pim_ifp->pim_neighbors_highest_override_interval_msec;
1095 } else {
1096 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
1097 }
1098 }
1099
1100 int pim_if_t_override_msec(struct interface *ifp)
1101 {
1102 int effective_override_interval_msec;
1103 int t_override_msec;
1104
1105 effective_override_interval_msec =
1106 pim_if_effective_override_interval_msec(ifp);
1107
1108 t_override_msec =
1109 frr_weak_random() % (effective_override_interval_msec + 1);
1110
1111 return t_override_msec;
1112 }
1113
1114 uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
1115 {
1116 return pim_if_effective_propagation_delay_msec(ifp)
1117 + pim_if_effective_override_interval_msec(ifp);
1118 }
1119
1120 /*
1121 RFC 4601: 4.1.6. State Summarization Macros
1122
1123 The function NBR( I, A ) uses information gathered through PIM Hello
1124 messages to map the IP address A of a directly connected PIM
1125 neighbor router on interface I to the primary IP address of the same
1126 router (Section 4.3.4). The primary IP address of a neighbor is the
1127 address that it uses as the source of its PIM Hello messages.
1128 */
1129 struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
1130 struct in_addr addr)
1131 {
1132 struct listnode *neighnode;
1133 struct pim_neighbor *neigh;
1134 struct pim_interface *pim_ifp;
1135 struct prefix p;
1136
1137 zassert(ifp);
1138
1139 pim_ifp = ifp->info;
1140 if (!pim_ifp) {
1141 zlog_warn("%s: multicast not enabled on interface %s", __func__,
1142 ifp->name);
1143 return 0;
1144 }
1145
1146 p.family = AF_INET;
1147 p.u.prefix4 = addr;
1148 p.prefixlen = IPV4_MAX_PREFIXLEN;
1149
1150 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1151 neigh)) {
1152
1153 /* primary address ? */
1154 if (neigh->source_addr.s_addr == addr.s_addr)
1155 return neigh;
1156
1157 /* secondary address ? */
1158 if (pim_neighbor_find_secondary(neigh, &p))
1159 return neigh;
1160 }
1161
1162 if (PIM_DEBUG_PIM_TRACE) {
1163 char addr_str[INET_ADDRSTRLEN];
1164 pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
1165 zlog_debug(
1166 "%s: neighbor not found for address %s on interface %s",
1167 __func__, addr_str, ifp->name);
1168 }
1169
1170 return NULL;
1171 }
1172
1173 long pim_if_t_suppressed_msec(struct interface *ifp)
1174 {
1175 struct pim_interface *pim_ifp;
1176 long t_suppressed_msec;
1177 uint32_t ramount = 0;
1178
1179 pim_ifp = ifp->info;
1180 zassert(pim_ifp);
1181
1182 /* join suppression disabled ? */
1183 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options))
1184 return 0;
1185
1186 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1187 ramount = 1100 + (frr_weak_random() % (1400 - 1100 + 1));
1188 t_suppressed_msec = router->t_periodic * ramount;
1189
1190 return t_suppressed_msec;
1191 }
1192
1193 static void igmp_join_free(struct igmp_join *ij)
1194 {
1195 XFREE(MTYPE_PIM_IGMP_JOIN, ij);
1196 }
1197
1198 static struct igmp_join *igmp_join_find(struct list *join_list,
1199 struct in_addr group_addr,
1200 struct in_addr source_addr)
1201 {
1202 struct listnode *node;
1203 struct igmp_join *ij;
1204
1205 zassert(join_list);
1206
1207 for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) {
1208 if ((group_addr.s_addr == ij->group_addr.s_addr)
1209 && (source_addr.s_addr == ij->source_addr.s_addr))
1210 return ij;
1211 }
1212
1213 return 0;
1214 }
1215
1216 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
1217 struct in_addr group_addr, struct in_addr source_addr)
1218 {
1219 int join_fd;
1220
1221 join_fd = pim_socket_raw(IPPROTO_IGMP);
1222 if (join_fd < 0) {
1223 return -1;
1224 }
1225
1226 if (pim_igmp_join_source(join_fd, ifindex, group_addr, source_addr)) {
1227 char group_str[INET_ADDRSTRLEN];
1228 char source_str[INET_ADDRSTRLEN];
1229 pim_inet4_dump("<grp?>", group_addr, group_str,
1230 sizeof(group_str));
1231 pim_inet4_dump("<src?>", source_addr, source_str,
1232 sizeof(source_str));
1233 zlog_warn(
1234 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1235 __func__, join_fd, group_str, source_str, ifindex,
1236 ifname, errno, safe_strerror(errno));
1237
1238 close(join_fd);
1239 return -2;
1240 }
1241
1242 return join_fd;
1243 }
1244
1245 static struct igmp_join *igmp_join_new(struct interface *ifp,
1246 struct in_addr group_addr,
1247 struct in_addr source_addr)
1248 {
1249 struct pim_interface *pim_ifp;
1250 struct igmp_join *ij;
1251 int join_fd;
1252
1253 pim_ifp = ifp->info;
1254 zassert(pim_ifp);
1255
1256 join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
1257 source_addr);
1258 if (join_fd < 0) {
1259 char group_str[INET_ADDRSTRLEN];
1260 char source_str[INET_ADDRSTRLEN];
1261
1262 pim_inet4_dump("<grp?>", group_addr, group_str,
1263 sizeof(group_str));
1264 pim_inet4_dump("<src?>", source_addr, source_str,
1265 sizeof(source_str));
1266 zlog_warn(
1267 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1268 __func__, group_str, source_str, ifp->name);
1269 return 0;
1270 }
1271
1272 ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
1273
1274 ij->sock_fd = join_fd;
1275 ij->group_addr = group_addr;
1276 ij->source_addr = source_addr;
1277 ij->sock_creation = pim_time_monotonic_sec();
1278
1279 listnode_add(pim_ifp->igmp_join_list, ij);
1280
1281 return ij;
1282 }
1283
1284 ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
1285 struct in_addr source_addr)
1286 {
1287 struct pim_interface *pim_ifp;
1288 struct igmp_join *ij;
1289
1290 pim_ifp = ifp->info;
1291 if (!pim_ifp) {
1292 return ferr_cfg_invalid("multicast not enabled on interface %s",
1293 ifp->name);
1294 }
1295
1296 if (!pim_ifp->igmp_join_list) {
1297 pim_ifp->igmp_join_list = list_new();
1298 pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
1299 }
1300
1301 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1302
1303 /* This interface has already been configured to join this IGMP group
1304 */
1305 if (ij) {
1306 return ferr_ok();
1307 }
1308
1309 (void)igmp_join_new(ifp, group_addr, source_addr);
1310
1311 if (PIM_DEBUG_IGMP_EVENTS) {
1312 char group_str[INET_ADDRSTRLEN];
1313 char source_str[INET_ADDRSTRLEN];
1314 pim_inet4_dump("<grp?>", group_addr, group_str,
1315 sizeof(group_str));
1316 pim_inet4_dump("<src?>", source_addr, source_str,
1317 sizeof(source_str));
1318 zlog_debug(
1319 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1320 __func__, source_str, group_str, ifp->name);
1321 }
1322
1323 return ferr_ok();
1324 }
1325
1326
1327 int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
1328 struct in_addr source_addr)
1329 {
1330 struct pim_interface *pim_ifp;
1331 struct igmp_join *ij;
1332
1333 pim_ifp = ifp->info;
1334 if (!pim_ifp) {
1335 zlog_warn("%s: multicast not enabled on interface %s", __func__,
1336 ifp->name);
1337 return -1;
1338 }
1339
1340 if (!pim_ifp->igmp_join_list) {
1341 zlog_warn("%s: no IGMP join on interface %s", __func__,
1342 ifp->name);
1343 return -2;
1344 }
1345
1346 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1347 if (!ij) {
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: could not find IGMP group %s source %s on interface %s",
1356 __func__, group_str, source_str, ifp->name);
1357 return -3;
1358 }
1359
1360 if (close(ij->sock_fd)) {
1361 char group_str[INET_ADDRSTRLEN];
1362 char source_str[INET_ADDRSTRLEN];
1363 pim_inet4_dump("<grp?>", group_addr, group_str,
1364 sizeof(group_str));
1365 pim_inet4_dump("<src?>", source_addr, source_str,
1366 sizeof(source_str));
1367 zlog_warn(
1368 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1369 __func__, ij->sock_fd, group_str, source_str, ifp->name,
1370 errno, safe_strerror(errno));
1371 /* warning only */
1372 }
1373 listnode_delete(pim_ifp->igmp_join_list, ij);
1374 igmp_join_free(ij);
1375 if (listcount(pim_ifp->igmp_join_list) < 1) {
1376 list_delete(&pim_ifp->igmp_join_list);
1377 pim_ifp->igmp_join_list = 0;
1378 }
1379
1380 return 0;
1381 }
1382
1383 static void pim_if_igmp_join_del_all(struct interface *ifp)
1384 {
1385 struct pim_interface *pim_ifp;
1386 struct listnode *node;
1387 struct listnode *nextnode;
1388 struct igmp_join *ij;
1389
1390 pim_ifp = ifp->info;
1391 if (!pim_ifp) {
1392 zlog_warn("%s: multicast not enabled on interface %s", __func__,
1393 ifp->name);
1394 return;
1395 }
1396
1397 if (!pim_ifp->igmp_join_list)
1398 return;
1399
1400 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij))
1401 pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);
1402 }
1403
1404 /*
1405 RFC 4601
1406
1407 Transitions from "I am Assert Loser" State
1408
1409 Current Winner's GenID Changes or NLT Expires
1410
1411 The Neighbor Liveness Timer associated with the current winner
1412 expires or we receive a Hello message from the current winner
1413 reporting a different GenID from the one it previously reported.
1414 This indicates that the current winner's interface or router has
1415 gone down (and may have come back up), and so we must assume it no
1416 longer knows it was the winner.
1417 */
1418 void pim_if_assert_on_neighbor_down(struct interface *ifp,
1419 struct in_addr neigh_addr)
1420 {
1421 struct pim_interface *pim_ifp;
1422 struct pim_ifchannel *ch;
1423
1424 pim_ifp = ifp->info;
1425 zassert(pim_ifp);
1426
1427 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1428 /* Is (S,G,I) assert loser ? */
1429 if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
1430 continue;
1431 /* Dead neighbor was winner ? */
1432 if (ch->ifassert_winner.s_addr != neigh_addr.s_addr)
1433 continue;
1434
1435 assert_action_a5(ch);
1436 }
1437 }
1438
1439 void pim_if_update_join_desired(struct pim_interface *pim_ifp)
1440 {
1441 struct pim_ifchannel *ch;
1442
1443 /* clear off flag from interface's upstreams */
1444 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1445 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1446 ch->upstream->flags);
1447 }
1448
1449 /* scan per-interface (S,G,I) state on this I interface */
1450 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1451 struct pim_upstream *up = ch->upstream;
1452
1453 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
1454 continue;
1455
1456 /* update join_desired for the global (S,G) state */
1457 pim_upstream_update_join_desired(pim_ifp->pim, up);
1458 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags);
1459 }
1460 }
1461
1462 void pim_if_update_assert_tracking_desired(struct interface *ifp)
1463 {
1464 struct pim_interface *pim_ifp;
1465 struct pim_ifchannel *ch;
1466
1467 pim_ifp = ifp->info;
1468 if (!pim_ifp)
1469 return;
1470
1471 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1472 pim_ifchannel_update_assert_tracking_desired(ch);
1473 }
1474 }
1475
1476 /*
1477 * PIM wants to have an interface pointer for everything it does.
1478 * The pimreg is a special interface that we have that is not
1479 * quite an inteface but a VIF is created for it.
1480 */
1481 void pim_if_create_pimreg(struct pim_instance *pim)
1482 {
1483 char pimreg_name[INTERFACE_NAMSIZ];
1484
1485 if (!pim->regiface) {
1486 if (pim->vrf_id == VRF_DEFAULT)
1487 strlcpy(pimreg_name, "pimreg", sizeof(pimreg_name));
1488 else
1489 snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
1490 pim->vrf->data.l.table_id);
1491
1492 pim->regiface = if_create_name(pimreg_name, pim->vrf_id);
1493 pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
1494
1495 pim_if_new(pim->regiface, false, false, true,
1496 false /*vxlan_term*/);
1497 /*
1498 * On vrf moves we delete the interface if there
1499 * is nothing going on with it. We cannot have
1500 * the pimregiface deleted.
1501 */
1502 pim->regiface->configured = true;
1503
1504 }
1505 }
1506
1507 int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
1508 {
1509 struct listnode *cnode;
1510 struct connected *c;
1511 struct prefix p;
1512
1513 if (!ifp)
1514 return 0;
1515
1516 p.family = AF_INET;
1517 p.u.prefix4 = src;
1518 p.prefixlen = IPV4_MAX_BITLEN;
1519
1520 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
1521 if ((c->address->family == AF_INET)
1522 && prefix_match(CONNECTED_PREFIX(c), &p)) {
1523 return 1;
1524 }
1525 }
1526
1527 return 0;
1528 }
1529
1530 bool pim_if_is_vrf_device(struct interface *ifp)
1531 {
1532 if (if_is_vrf(ifp))
1533 return true;
1534
1535 return false;
1536 }
1537
1538 int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
1539 {
1540 struct pim_ifchannel *ch;
1541 int count = 0;
1542
1543 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1544 count++;
1545 }
1546
1547 return count;
1548 }
1549
1550 int pim_ifp_create(struct interface *ifp)
1551 {
1552 struct pim_instance *pim;
1553
1554 pim = pim_get_pim_instance(ifp->vrf_id);
1555 if (PIM_DEBUG_ZEBRA) {
1556 zlog_debug(
1557 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
1558 __func__, ifp->name, ifp->ifindex, ifp->vrf_id,
1559 (long)ifp->flags, ifp->metric, ifp->mtu,
1560 if_is_operative(ifp));
1561 }
1562
1563 if (if_is_operative(ifp)) {
1564 struct pim_interface *pim_ifp;
1565
1566 pim_ifp = ifp->info;
1567 /*
1568 * If we have a pim_ifp already and this is an if_add
1569 * that means that we probably have a vrf move event
1570 * If that is the case, set the proper vrfness.
1571 */
1572 if (pim_ifp)
1573 pim_ifp->pim = pim;
1574 pim_if_addr_add_all(ifp);
1575 }
1576
1577 /*
1578 * If we are a vrf device that is up, open up the pim_socket for
1579 * listening
1580 * to incoming pim messages irrelevant if the user has configured us
1581 * for pim or not.
1582 */
1583 if (pim_if_is_vrf_device(ifp)) {
1584 struct pim_interface *pim_ifp;
1585
1586 if (!ifp->info) {
1587 pim_ifp = pim_if_new(ifp, false, false, false,
1588 false /*vxlan_term*/);
1589 ifp->info = pim_ifp;
1590 }
1591
1592 pim_sock_add(ifp);
1593 }
1594
1595 if (!strncmp(ifp->name, PIM_VXLAN_TERM_DEV_NAME,
1596 sizeof(PIM_VXLAN_TERM_DEV_NAME))) {
1597 if (pim->mcast_if_count < MAXVIFS)
1598 pim_vxlan_add_term_dev(pim, ifp);
1599 else
1600 zlog_warn(
1601 "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
1602 __func__, ifp->name, MAXVIFS);
1603 }
1604
1605 return 0;
1606 }
1607
1608 int pim_ifp_up(struct interface *ifp)
1609 {
1610 struct pim_interface *pim_ifp;
1611 struct pim_instance *pim;
1612 uint32_t table_id;
1613
1614 if (PIM_DEBUG_ZEBRA) {
1615 zlog_debug(
1616 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
1617 __func__, ifp->name, ifp->ifindex, ifp->vrf_id,
1618 (long)ifp->flags, ifp->metric, ifp->mtu,
1619 if_is_operative(ifp));
1620 }
1621
1622 pim = pim_get_pim_instance(ifp->vrf_id);
1623
1624 pim_ifp = ifp->info;
1625 /*
1626 * If we have a pim_ifp already and this is an if_add
1627 * that means that we probably have a vrf move event
1628 * If that is the case, set the proper vrfness.
1629 */
1630 if (pim_ifp)
1631 pim_ifp->pim = pim;
1632
1633 /*
1634 pim_if_addr_add_all() suffices for bringing up both IGMP and
1635 PIM
1636 */
1637 pim_if_addr_add_all(ifp);
1638
1639 /*
1640 * If we have a pimreg device callback and it's for a specific
1641 * table set the master appropriately
1642 */
1643 if (sscanf(ifp->name, "pimreg%" SCNu32, &table_id) == 1) {
1644 struct vrf *vrf;
1645 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1646 if ((table_id == vrf->data.l.table_id)
1647 && (ifp->vrf_id != vrf->vrf_id)) {
1648 struct interface *master = if_lookup_by_name(
1649 vrf->name, vrf->vrf_id);
1650
1651 if (!master) {
1652 zlog_debug(
1653 "%s: Unable to find Master interface for %s",
1654 __func__, vrf->name);
1655 return 0;
1656 }
1657 pim_zebra_interface_set_master(master, ifp);
1658 }
1659 }
1660 }
1661 return 0;
1662 }
1663
1664 int pim_ifp_down(struct interface *ifp)
1665 {
1666 if (PIM_DEBUG_ZEBRA) {
1667 zlog_debug(
1668 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
1669 __func__, ifp->name, ifp->ifindex, ifp->vrf_id,
1670 (long)ifp->flags, ifp->metric, ifp->mtu,
1671 if_is_operative(ifp));
1672 }
1673
1674 if (!if_is_operative(ifp)) {
1675 pim_ifchannel_delete_all(ifp);
1676 /*
1677 pim_if_addr_del_all() suffices for shutting down IGMP,
1678 but not for shutting down PIM
1679 */
1680 pim_if_addr_del_all(ifp);
1681
1682 /*
1683 pim_sock_delete() closes the socket, stops read and timer
1684 threads,
1685 and kills all neighbors.
1686 */
1687 if (ifp->info) {
1688 pim_sock_delete(ifp, "link down");
1689 }
1690 }
1691
1692 if (ifp->info)
1693 pim_if_del_vif(ifp);
1694
1695 return 0;
1696 }
1697
1698 int pim_ifp_destroy(struct interface *ifp)
1699 {
1700 struct pim_instance *pim;
1701
1702 if (PIM_DEBUG_ZEBRA) {
1703 zlog_debug(
1704 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
1705 __func__, ifp->name, ifp->ifindex, ifp->vrf_id,
1706 (long)ifp->flags, ifp->metric, ifp->mtu,
1707 if_is_operative(ifp));
1708 }
1709
1710 if (!if_is_operative(ifp))
1711 pim_if_addr_del_all(ifp);
1712
1713 pim = pim_get_pim_instance(ifp->vrf_id);
1714 if (pim && pim->vxlan.term_if == ifp)
1715 pim_vxlan_del_term_dev(pim);
1716
1717 return 0;
1718 }