]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_iface.c
*: conform with COMMUNITY.md formatting rules, via 'make indent'
[mirror_frr.git] / pimd / pim_iface.c
1 /*
2 * PIM for Quagga
3 * Copyright (C) 2008 Everton da Silva Marques
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <zebra.h>
20
21 #include "if.h"
22 #include "log.h"
23 #include "vty.h"
24 #include "memory.h"
25 #include "prefix.h"
26 #include "vrf.h"
27 #include "linklist.h"
28 #include "plist.h"
29 #include "hash.h"
30 #include "ferr.h"
31
32 #include "pimd.h"
33 #include "pim_instance.h"
34 #include "pim_zebra.h"
35 #include "pim_iface.h"
36 #include "pim_igmp.h"
37 #include "pim_mroute.h"
38 #include "pim_oil.h"
39 #include "pim_str.h"
40 #include "pim_pim.h"
41 #include "pim_neighbor.h"
42 #include "pim_ifchannel.h"
43 #include "pim_sock.h"
44 #include "pim_time.h"
45 #include "pim_ssmpingd.h"
46 #include "pim_rp.h"
47 #include "pim_nht.h"
48 #include "pim_jp_agg.h"
49
50 static void pim_if_igmp_join_del_all(struct interface *ifp);
51 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
52 struct in_addr group_addr,
53 struct in_addr source_addr);
54
55 void pim_if_init(struct pim_instance *pim)
56 {
57 int i;
58
59 for (i = 0; i < MAXVIFS; i++)
60 pim->iface_vif_index[i] = 0;
61 }
62
63 void pim_if_terminate(struct pim_instance *pim)
64 {
65 // Nothing to do at this moment
66 return;
67 }
68
69 static void *if_list_clean(struct pim_interface *pim_ifp)
70 {
71 struct pim_ifchannel *ch;
72
73 if (pim_ifp->igmp_join_list)
74 list_delete_and_null(&pim_ifp->igmp_join_list);
75
76 if (pim_ifp->igmp_socket_list)
77 list_delete_and_null(&pim_ifp->igmp_socket_list);
78
79 if (pim_ifp->pim_neighbor_list)
80 list_delete_and_null(&pim_ifp->pim_neighbor_list);
81
82 if (pim_ifp->upstream_switch_list)
83 list_delete_and_null(&pim_ifp->upstream_switch_list);
84
85 if (pim_ifp->sec_addr_list)
86 list_delete_and_null(&pim_ifp->sec_addr_list);
87
88 while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
89 ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
90
91 pim_ifchannel_delete(ch);
92 }
93
94 XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
95
96 return 0;
97 }
98
99 static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
100 {
101 XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
102 }
103
104 static int pim_sec_addr_comp(const void *p1, const void *p2)
105 {
106 const struct pim_secondary_addr *sec1 = p1;
107 const struct pim_secondary_addr *sec2 = p2;
108
109 if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
110 return -1;
111
112 if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
113 return 1;
114
115 if (sec1->addr.family == AF_INET) {
116 if (ntohl(sec1->addr.u.prefix4.s_addr)
117 < ntohl(sec2->addr.u.prefix4.s_addr))
118 return -1;
119
120 if (ntohl(sec1->addr.u.prefix4.s_addr)
121 > ntohl(sec2->addr.u.prefix4.s_addr))
122 return 1;
123 } else {
124 return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
125 sizeof(struct in6_addr));
126 }
127
128 return 0;
129 }
130
131 struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
132 {
133 struct pim_interface *pim_ifp;
134
135 zassert(ifp);
136 zassert(!ifp->info);
137
138 pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
139 if (!pim_ifp) {
140 zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp));
141 return 0;
142 }
143
144 pim_ifp->options = 0;
145 pim_ifp->pim = pim_get_pim_instance(ifp->vrf_id);
146 pim_ifp->mroute_vif_index = -1;
147
148 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
149 pim_ifp->igmp_default_robustness_variable =
150 IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
151 pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
152 pim_ifp->igmp_query_max_response_time_dsec =
153 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
154 pim_ifp->igmp_specific_query_max_response_time_dsec =
155 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
156
157 /*
158 RFC 3376: 8.3. Query Response Interval
159 The number of seconds represented by the [Query Response Interval]
160 must be less than the [Query Interval].
161 */
162 zassert(pim_ifp->igmp_query_max_response_time_dsec
163 < pim_ifp->igmp_default_query_interval);
164
165 if (pim)
166 PIM_IF_DO_PIM(pim_ifp->options);
167 if (igmp)
168 PIM_IF_DO_IGMP(pim_ifp->options);
169
170 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options);
171
172 pim_ifp->igmp_join_list = NULL;
173 pim_ifp->igmp_socket_list = NULL;
174 pim_ifp->pim_neighbor_list = NULL;
175 pim_ifp->upstream_switch_list = NULL;
176 pim_ifp->pim_generation_id = 0;
177
178 /* list of struct igmp_sock */
179 pim_ifp->igmp_socket_list = list_new();
180 if (!pim_ifp->igmp_socket_list) {
181 zlog_err("%s: failure: igmp_socket_list=list_new()",
182 __PRETTY_FUNCTION__);
183 return if_list_clean(pim_ifp);
184 }
185 pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
186
187 /* list of struct pim_neighbor */
188 pim_ifp->pim_neighbor_list = list_new();
189 if (!pim_ifp->pim_neighbor_list) {
190 zlog_err("%s: failure: pim_neighbor_list=list_new()",
191 __PRETTY_FUNCTION__);
192 return if_list_clean(pim_ifp);
193 }
194 pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
195
196 pim_ifp->upstream_switch_list = list_new();
197 if (!pim_ifp->upstream_switch_list) {
198 zlog_err("%s: failure: upstream_switch_list=list_new()",
199 __PRETTY_FUNCTION__);
200 return if_list_clean(pim_ifp);
201 }
202 pim_ifp->upstream_switch_list->del =
203 (void (*)(void *))pim_jp_agg_group_list_free;
204 pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
205
206 pim_ifp->sec_addr_list = list_new();
207 if (!pim_ifp->sec_addr_list) {
208 zlog_err("%s: failure: secondary addresslist",
209 __PRETTY_FUNCTION__);
210 return if_list_clean(pim_ifp);
211 }
212 pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
213 pim_ifp->sec_addr_list->cmp =
214 (int (*)(void *, void *))pim_sec_addr_comp;
215
216 RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
217
218 ifp->info = pim_ifp;
219
220 pim_sock_reset(ifp);
221
222 pim_if_add_vif(ifp);
223
224 return pim_ifp;
225 }
226
227 void pim_if_delete(struct interface *ifp)
228 {
229 struct pim_interface *pim_ifp;
230 struct pim_ifchannel *ch;
231
232 zassert(ifp);
233 pim_ifp = ifp->info;
234 zassert(pim_ifp);
235
236 if (pim_ifp->igmp_join_list) {
237 pim_if_igmp_join_del_all(ifp);
238 }
239
240 pim_ifchannel_delete_all(ifp);
241 igmp_sock_delete_all(ifp);
242
243 pim_neighbor_delete_all(ifp, "Interface removed from configuration");
244
245 pim_if_del_vif(ifp);
246
247 list_delete_and_null(&pim_ifp->igmp_socket_list);
248 list_delete_and_null(&pim_ifp->pim_neighbor_list);
249 list_delete_and_null(&pim_ifp->upstream_switch_list);
250 list_delete_and_null(&pim_ifp->sec_addr_list);
251
252 if (pim_ifp->boundary_oil_plist)
253 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
254
255 while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
256 ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
257
258 pim_ifchannel_delete(ch);
259 }
260
261 XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
262
263 ifp->info = NULL;
264 }
265
266 void pim_if_update_could_assert(struct interface *ifp)
267 {
268 struct pim_interface *pim_ifp;
269 struct pim_ifchannel *ch;
270
271 pim_ifp = ifp->info;
272 zassert(pim_ifp);
273
274 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
275 pim_ifchannel_update_could_assert(ch);
276 }
277 }
278
279 static void pim_if_update_my_assert_metric(struct interface *ifp)
280 {
281 struct pim_interface *pim_ifp;
282 struct pim_ifchannel *ch;
283
284 pim_ifp = ifp->info;
285 zassert(pim_ifp);
286
287 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
288 pim_ifchannel_update_my_assert_metric(ch);
289 }
290 }
291
292 static void pim_addr_change(struct interface *ifp)
293 {
294 struct pim_interface *pim_ifp;
295
296 pim_ifp = ifp->info;
297 zassert(pim_ifp);
298
299 pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes --
300 Done TODO T30 */
301 pim_if_update_join_desired(pim_ifp); /* depends on DR */
302 pim_if_update_could_assert(ifp); /* depends on DR */
303 pim_if_update_my_assert_metric(ifp); /* depends on could_assert */
304 pim_if_update_assert_tracking_desired(
305 ifp); /* depends on DR, join_desired */
306
307 /*
308 RFC 4601: 4.3.1. Sending Hello Messages
309
310 1) Before an interface goes down or changes primary IP address, a
311 Hello message with a zero HoldTime should be sent immediately
312 (with the old IP address if the IP address changed).
313 -- FIXME See CAVEAT C13
314
315 2) After an interface has changed its IP address, it MUST send a
316 Hello message with its new IP address.
317 -- DONE below
318
319 3) If an interface changes one of its secondary IP addresses, a
320 Hello message with an updated Address_List option and a non-zero
321 HoldTime should be sent immediately.
322 -- FIXME See TODO T31
323 */
324 pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */
325 if (pim_ifp->pim_sock_fd < 0)
326 return;
327 pim_hello_restart_now(ifp); /* send hello and restart timer */
328 }
329
330 static int detect_primary_address_change(struct interface *ifp,
331 int force_prim_as_any,
332 const char *caller)
333 {
334 struct pim_interface *pim_ifp = ifp->info;
335 struct in_addr new_prim_addr;
336 int changed;
337
338 if (force_prim_as_any)
339 new_prim_addr.s_addr = INADDR_ANY;
340 else
341 new_prim_addr = pim_find_primary_addr(ifp);
342
343 changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr;
344
345 if (PIM_DEBUG_ZEBRA) {
346 char new_prim_str[INET_ADDRSTRLEN];
347 char old_prim_str[INET_ADDRSTRLEN];
348 pim_inet4_dump("<new?>", new_prim_addr, new_prim_str,
349 sizeof(new_prim_str));
350 pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str,
351 sizeof(old_prim_str));
352 zlog_debug("%s: old=%s new=%s on interface %s: %s",
353 __PRETTY_FUNCTION__, old_prim_str, new_prim_str,
354 ifp->name, changed ? "changed" : "unchanged");
355 }
356
357 if (changed) {
358 pim_ifp->primary_address = new_prim_addr;
359 }
360
361 return changed;
362 }
363
364 static struct pim_secondary_addr *
365 pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
366 {
367 struct pim_secondary_addr *sec_addr;
368 struct listnode *node;
369
370 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
371 if (prefix_cmp(&sec_addr->addr, addr)) {
372 return sec_addr;
373 }
374 }
375
376 return NULL;
377 }
378
379 static void pim_sec_addr_del(struct pim_interface *pim_ifp,
380 struct pim_secondary_addr *sec_addr)
381 {
382 listnode_delete(pim_ifp->sec_addr_list, sec_addr);
383 pim_sec_addr_free(sec_addr);
384 }
385
386 static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
387 {
388 int changed = 0;
389 struct pim_secondary_addr *sec_addr;
390
391 sec_addr = pim_sec_addr_find(pim_ifp, addr);
392 if (sec_addr) {
393 sec_addr->flags &= ~PIM_SEC_ADDRF_STALE;
394 return changed;
395 }
396
397 sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
398 if (!sec_addr)
399 return changed;
400
401 changed = 1;
402 sec_addr->addr = *addr;
403 listnode_add_sort(pim_ifp->sec_addr_list, sec_addr);
404
405 return changed;
406 }
407
408 static int pim_sec_addr_del_all(struct pim_interface *pim_ifp)
409 {
410 int changed = 0;
411
412 if (!list_isempty(pim_ifp->sec_addr_list)) {
413 changed = 1;
414 /* remove all nodes and free up the list itself */
415 list_delete_all_node(pim_ifp->sec_addr_list);
416 }
417
418 return changed;
419 }
420
421 static int pim_sec_addr_update(struct interface *ifp)
422 {
423 struct pim_interface *pim_ifp = ifp->info;
424 struct connected *ifc;
425 struct listnode *node;
426 struct listnode *nextnode;
427 struct pim_secondary_addr *sec_addr;
428 int changed = 0;
429
430 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
431 sec_addr->flags |= PIM_SEC_ADDRF_STALE;
432 }
433
434 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
435 struct prefix *p = ifc->address;
436
437 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
438 continue;
439 }
440
441 if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) {
442 /* don't add the primary address into the secondary
443 * address list */
444 continue;
445 }
446
447 if (pim_sec_addr_add(pim_ifp, p)) {
448 changed = 1;
449 }
450 }
451
452 /* Drop stale entries */
453 for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
454 sec_addr)) {
455 if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
456 pim_sec_addr_del(pim_ifp, sec_addr);
457 changed = 1;
458 }
459 }
460
461 return changed;
462 }
463
464 static int detect_secondary_address_change(struct interface *ifp,
465 int force_prim_as_any,
466 const char *caller)
467 {
468 struct pim_interface *pim_ifp = ifp->info;
469 int changed = 0;
470
471 if (force_prim_as_any) {
472 /* if primary address is being forced to zero just flush the
473 * secondary address list */
474 changed = pim_sec_addr_del_all(pim_ifp);
475 } else {
476 /* re-evaluate the secondary address list */
477 changed = pim_sec_addr_update(ifp);
478 }
479
480 return changed;
481 }
482
483 static void detect_address_change(struct interface *ifp, int force_prim_as_any,
484 const char *caller)
485 {
486 int changed = 0;
487 struct pim_interface *pim_ifp;
488
489 pim_ifp = ifp->info;
490 if (!pim_ifp)
491 return;
492
493 if (detect_primary_address_change(ifp, force_prim_as_any, caller)) {
494 changed = 1;
495 }
496
497 if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) {
498 changed = 1;
499 }
500
501
502 if (changed) {
503 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
504 return;
505 }
506
507 pim_addr_change(ifp);
508 }
509
510 /* XXX: if we have unnumbered interfaces we need to run detect address
511 * address change on all of them when the lo address changes */
512 }
513
514 int pim_update_source_set(struct interface *ifp, struct in_addr source)
515 {
516 struct pim_interface *pim_ifp = ifp->info;
517
518 if (!pim_ifp) {
519 return PIM_IFACE_NOT_FOUND;
520 }
521
522 if (pim_ifp->update_source.s_addr == source.s_addr) {
523 return PIM_UPDATE_SOURCE_DUP;
524 }
525
526 pim_ifp->update_source = source;
527 detect_address_change(ifp, 0 /* force_prim_as_any */,
528 __PRETTY_FUNCTION__);
529
530 return PIM_SUCCESS;
531 }
532
533 void pim_if_addr_add(struct connected *ifc)
534 {
535 struct pim_interface *pim_ifp;
536 struct interface *ifp;
537 struct in_addr ifaddr;
538
539 zassert(ifc);
540
541 ifp = ifc->ifp;
542 zassert(ifp);
543 pim_ifp = ifp->info;
544 if (!pim_ifp)
545 return;
546
547 if (!if_is_operative(ifp))
548 return;
549
550 if (PIM_DEBUG_ZEBRA) {
551 char buf[BUFSIZ];
552 prefix2str(ifc->address, buf, BUFSIZ);
553 zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
554 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf,
555 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
556 ? "secondary"
557 : "primary");
558 }
559
560 ifaddr = ifc->address->u.prefix4;
561
562 detect_address_change(ifp, 0, __PRETTY_FUNCTION__);
563
564 // if (ifc->address->family != AF_INET)
565 // return;
566
567 if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
568 struct igmp_sock *igmp;
569
570 /* lookup IGMP socket */
571 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
572 ifaddr);
573 if (!igmp) {
574 /* if addr new, add IGMP socket */
575 if (ifc->address->family == AF_INET)
576 pim_igmp_sock_add(pim_ifp->igmp_socket_list,
577 ifaddr, ifp);
578 }
579
580 /* Replay Static IGMP groups */
581 if (pim_ifp->igmp_join_list) {
582 struct listnode *node;
583 struct listnode *nextnode;
584 struct igmp_join *ij;
585 int join_fd;
586
587 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node,
588 nextnode, ij)) {
589 /* Close socket and reopen with Source and Group
590 */
591 close(ij->sock_fd);
592 join_fd = igmp_join_sock(
593 ifp->name, ifp->ifindex, ij->group_addr,
594 ij->source_addr);
595 if (join_fd < 0) {
596 char group_str[INET_ADDRSTRLEN];
597 char source_str[INET_ADDRSTRLEN];
598 pim_inet4_dump("<grp?>", ij->group_addr,
599 group_str,
600 sizeof(group_str));
601 pim_inet4_dump(
602 "<src?>", ij->source_addr,
603 source_str, sizeof(source_str));
604 zlog_warn(
605 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
606 __PRETTY_FUNCTION__, group_str,
607 source_str, ifp->name);
608 /* warning only */
609 } else
610 ij->sock_fd = join_fd;
611 }
612 }
613 } /* igmp */
614
615 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
616
617 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
618
619 /* Interface has a valid socket ? */
620 if (pim_ifp->pim_sock_fd < 0) {
621 if (pim_sock_add(ifp)) {
622 zlog_warn(
623 "Failure creating PIM socket for interface %s",
624 ifp->name);
625 }
626 }
627 struct pim_nexthop_cache *pnc = NULL;
628 struct pim_rpf rpf;
629 struct zclient *zclient = NULL;
630
631 zclient = pim_zebra_zclient_get();
632 /* RP config might come prior to (local RP's interface)
633 IF UP event.
634 In this case, pnc would not have pim enabled
635 nexthops.
636 Once Interface is UP and pim info is available,
637 reregister
638 with RNH address to receive update and add the
639 interface as nexthop. */
640 memset(&rpf, 0, sizeof(struct pim_rpf));
641 rpf.rpf_addr.family = AF_INET;
642 rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
643 rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
644 pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
645 if (pnc)
646 pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
647 pnc,
648 ZEBRA_NEXTHOP_REGISTER);
649 }
650 } /* pim */
651
652 /*
653 PIM or IGMP is enabled on interface, and there is at least one
654 address assigned, then try to create a vif_index.
655 */
656 if (pim_ifp->mroute_vif_index < 0) {
657 pim_if_add_vif(ifp);
658 }
659 pim_ifchannel_scan_forward_start(ifp);
660 }
661
662 static void pim_if_addr_del_igmp(struct connected *ifc)
663 {
664 struct pim_interface *pim_ifp = ifc->ifp->info;
665 struct igmp_sock *igmp;
666 struct in_addr ifaddr;
667
668 if (ifc->address->family != AF_INET) {
669 /* non-IPv4 address */
670 return;
671 }
672
673 if (!pim_ifp) {
674 /* IGMP not enabled on interface */
675 return;
676 }
677
678 ifaddr = ifc->address->u.prefix4;
679
680 /* lookup IGMP socket */
681 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
682 if (igmp) {
683 /* if addr found, del IGMP socket */
684 igmp_sock_delete(igmp);
685 }
686 }
687
688 static void pim_if_addr_del_pim(struct connected *ifc)
689 {
690 struct pim_interface *pim_ifp = ifc->ifp->info;
691
692 if (ifc->address->family != AF_INET) {
693 /* non-IPv4 address */
694 return;
695 }
696
697 if (!pim_ifp) {
698 /* PIM not enabled on interface */
699 return;
700 }
701
702 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
703 /* Interface keeps a valid primary address */
704 return;
705 }
706
707 if (pim_ifp->pim_sock_fd < 0) {
708 /* Interface does not hold a valid socket any longer */
709 return;
710 }
711
712 /*
713 pim_sock_delete() closes the socket, stops read and timer threads,
714 and kills all neighbors.
715 */
716 pim_sock_delete(ifc->ifp,
717 "last address has been removed from interface");
718 }
719
720 void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
721 {
722 struct interface *ifp;
723
724 zassert(ifc);
725 ifp = ifc->ifp;
726 zassert(ifp);
727
728 if (PIM_DEBUG_ZEBRA) {
729 char buf[BUFSIZ];
730 prefix2str(ifc->address, buf, BUFSIZ);
731 zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
732 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf,
733 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
734 ? "secondary"
735 : "primary");
736 }
737
738 detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__);
739
740 pim_if_addr_del_igmp(ifc);
741 pim_if_addr_del_pim(ifc);
742 }
743
744 void pim_if_addr_add_all(struct interface *ifp)
745 {
746 struct connected *ifc;
747 struct listnode *node;
748 struct listnode *nextnode;
749 int v4_addrs = 0;
750 int v6_addrs = 0;
751 struct pim_interface *pim_ifp = ifp->info;
752
753
754 /* PIM/IGMP enabled ? */
755 if (!pim_ifp)
756 return;
757
758 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
759 struct prefix *p = ifc->address;
760
761 if (p->family != AF_INET)
762 v6_addrs++;
763 else
764 v4_addrs++;
765 pim_if_addr_add(ifc);
766 }
767
768 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
769 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
770
771 /* Interface has a valid primary address ? */
772 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
773
774 /* Interface has a valid socket ? */
775 if (pim_ifp->pim_sock_fd < 0) {
776 if (pim_sock_add(ifp)) {
777 zlog_warn(
778 "Failure creating PIM socket for interface %s",
779 ifp->name);
780 }
781 }
782 }
783 } /* pim */
784 }
785 /*
786 * PIM or IGMP is enabled on interface, and there is at least one
787 * address assigned, then try to create a vif_index.
788 */
789 if (pim_ifp->mroute_vif_index < 0) {
790 pim_if_add_vif(ifp);
791 }
792 pim_ifchannel_scan_forward_start(ifp);
793
794 pim_rp_setup(pim_ifp->pim);
795 pim_rp_check_on_if_add(pim_ifp);
796 }
797
798 void pim_if_addr_del_all(struct interface *ifp)
799 {
800 struct connected *ifc;
801 struct listnode *node;
802 struct listnode *nextnode;
803 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
804 struct pim_instance *pim;
805
806 if (!vrf)
807 return;
808 pim = vrf->info;
809
810 /* PIM/IGMP enabled ? */
811 if (!ifp->info)
812 return;
813
814 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
815 struct prefix *p = ifc->address;
816
817 if (p->family != AF_INET)
818 continue;
819
820 pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */);
821 }
822
823 pim_rp_setup(pim);
824 pim_i_am_rp_re_evaluate(pim);
825 }
826
827 void pim_if_addr_del_all_igmp(struct interface *ifp)
828 {
829 struct connected *ifc;
830 struct listnode *node;
831 struct listnode *nextnode;
832
833 /* PIM/IGMP enabled ? */
834 if (!ifp->info)
835 return;
836
837 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
838 struct prefix *p = ifc->address;
839
840 if (p->family != AF_INET)
841 continue;
842
843 pim_if_addr_del_igmp(ifc);
844 }
845 }
846
847 void pim_if_addr_del_all_pim(struct interface *ifp)
848 {
849 struct connected *ifc;
850 struct listnode *node;
851 struct listnode *nextnode;
852
853 /* PIM/IGMP enabled ? */
854 if (!ifp->info)
855 return;
856
857 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
858 struct prefix *p = ifc->address;
859
860 if (p->family != AF_INET)
861 continue;
862
863 pim_if_addr_del_pim(ifc);
864 }
865 }
866
867 struct in_addr pim_find_primary_addr(struct interface *ifp)
868 {
869 struct connected *ifc;
870 struct listnode *node;
871 struct in_addr addr = {0};
872 int v4_addrs = 0;
873 int v6_addrs = 0;
874 struct pim_interface *pim_ifp = ifp->info;
875 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
876
877 if (!vrf)
878 return addr;
879
880 if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
881 return pim_ifp->update_source;
882 }
883
884 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
885 struct prefix *p = ifc->address;
886
887 if (p->family != AF_INET) {
888 v6_addrs++;
889 continue;
890 }
891
892 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
893 zlog_warn(
894 "%s: null IPv4 address connected to interface %s",
895 __PRETTY_FUNCTION__, ifp->name);
896 continue;
897 }
898
899 v4_addrs++;
900
901 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
902 continue;
903
904 return p->u.prefix4;
905 }
906
907 /*
908 * If we have no v4_addrs and v6 is configured
909 * We probably are using unnumbered
910 * So let's grab the loopbacks v4 address
911 * and use that as the primary address
912 */
913 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
914 struct interface *lo_ifp;
915 // DBS - Come back and check here
916 if (ifp->vrf_id == VRF_DEFAULT)
917 lo_ifp = if_lookup_by_name("lo", vrf->vrf_id);
918 else
919 lo_ifp = if_lookup_by_name(vrf->name, vrf->vrf_id);
920
921 if (lo_ifp)
922 return pim_find_primary_addr(lo_ifp);
923 }
924
925 addr.s_addr = PIM_NET_INADDR_ANY;
926
927 return addr;
928 }
929
930 static int pim_iface_next_vif_index(struct interface *ifp)
931 {
932 struct pim_interface *pim_ifp = ifp->info;
933 struct pim_instance *pim = pim_ifp->pim;
934 int i;
935
936 /*
937 * The pimreg vif is always going to be in index 0
938 * of the table.
939 */
940 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
941 return 0;
942
943 for (i = 1; i < MAXVIFS; i++) {
944 if (pim->iface_vif_index[i] == 0)
945 return i;
946 }
947 return MAXVIFS;
948 }
949
950 /*
951 pim_if_add_vif() uses ifindex as vif_index
952
953 see also pim_if_find_vifindex_by_ifindex()
954 */
955 int pim_if_add_vif(struct interface *ifp)
956 {
957 struct pim_interface *pim_ifp = ifp->info;
958 struct in_addr ifaddr;
959 unsigned char flags = 0;
960
961 zassert(pim_ifp);
962
963 if (pim_ifp->mroute_vif_index > 0) {
964 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
965 __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index,
966 ifp->name, ifp->ifindex);
967 return -1;
968 }
969
970 if (ifp->ifindex < 0) {
971 zlog_warn("%s: ifindex=%d < 1 on interface %s",
972 __PRETTY_FUNCTION__, ifp->ifindex, ifp->name);
973 return -2;
974 }
975
976 ifaddr = pim_ifp->primary_address;
977 if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF
978 && PIM_INADDR_IS_ANY(ifaddr)) {
979 zlog_warn(
980 "%s: could not get address for interface %s ifindex=%d",
981 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex);
982 return -4;
983 }
984
985 pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp);
986
987 if (pim_ifp->mroute_vif_index >= MAXVIFS) {
988 zlog_warn(
989 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
990 __PRETTY_FUNCTION__, MAXVIFS, ifp->name);
991 return -3;
992 }
993
994 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
995 flags = VIFF_REGISTER;
996 #ifdef VIFF_USE_IFINDEX
997 else
998 flags = VIFF_USE_IFINDEX;
999 #endif
1000
1001 if (pim_mroute_add_vif(ifp, ifaddr, flags)) {
1002 /* pim_mroute_add_vif reported error */
1003 return -5;
1004 }
1005
1006 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
1007 return 0;
1008 }
1009
1010 int pim_if_del_vif(struct interface *ifp)
1011 {
1012 struct pim_interface *pim_ifp = ifp->info;
1013
1014 if (pim_ifp->mroute_vif_index < 1) {
1015 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1016 __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index,
1017 ifp->name, ifp->ifindex);
1018 return -1;
1019 }
1020
1021 pim_mroute_del_vif(ifp);
1022
1023 /*
1024 Update vif_index
1025 */
1026 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 0;
1027
1028 pim_ifp->mroute_vif_index = -1;
1029
1030 return 0;
1031 }
1032
1033 // DBS - VRF Revist
1034 struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
1035 ifindex_t vif_index)
1036 {
1037 struct interface *ifp;
1038
1039 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1040 if (ifp->info) {
1041 struct pim_interface *pim_ifp;
1042 pim_ifp = ifp->info;
1043
1044 if (vif_index == pim_ifp->mroute_vif_index)
1045 return ifp;
1046 }
1047 }
1048
1049 return 0;
1050 }
1051
1052 /*
1053 pim_if_add_vif() uses ifindex as vif_index
1054 */
1055 int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex)
1056 {
1057 struct pim_interface *pim_ifp;
1058 struct interface *ifp;
1059
1060 ifp = if_lookup_by_index(ifindex, pim->vrf_id);
1061 if (!ifp || !ifp->info)
1062 return -1;
1063 pim_ifp = ifp->info;
1064
1065 return pim_ifp->mroute_vif_index;
1066 }
1067
1068 int pim_if_lan_delay_enabled(struct interface *ifp)
1069 {
1070 struct pim_interface *pim_ifp;
1071
1072 pim_ifp = ifp->info;
1073 zassert(pim_ifp);
1074 zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
1075
1076 return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;
1077 }
1078
1079 uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp)
1080 {
1081 if (pim_if_lan_delay_enabled(ifp)) {
1082 struct pim_interface *pim_ifp;
1083 pim_ifp = ifp->info;
1084 return pim_ifp->pim_neighbors_highest_propagation_delay_msec;
1085 } else {
1086 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
1087 }
1088 }
1089
1090 uint16_t pim_if_effective_override_interval_msec(struct interface *ifp)
1091 {
1092 if (pim_if_lan_delay_enabled(ifp)) {
1093 struct pim_interface *pim_ifp;
1094 pim_ifp = ifp->info;
1095 return pim_ifp->pim_neighbors_highest_override_interval_msec;
1096 } else {
1097 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
1098 }
1099 }
1100
1101 int pim_if_t_override_msec(struct interface *ifp)
1102 {
1103 int effective_override_interval_msec;
1104 int t_override_msec;
1105
1106 effective_override_interval_msec =
1107 pim_if_effective_override_interval_msec(ifp);
1108
1109 t_override_msec = 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",
1142 __PRETTY_FUNCTION__, 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 __PRETTY_FUNCTION__, 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 + (random() % (1400 - 1100 + 1));
1188 t_suppressed_msec = qpim_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_socket_join_source(join_fd, ifindex, group_addr, source_addr,
1227 ifname)) {
1228 close(join_fd);
1229 return -2;
1230 }
1231
1232 return join_fd;
1233 }
1234
1235 static struct igmp_join *igmp_join_new(struct interface *ifp,
1236 struct in_addr group_addr,
1237 struct in_addr source_addr)
1238 {
1239 struct pim_interface *pim_ifp;
1240 struct igmp_join *ij;
1241 int join_fd;
1242
1243 pim_ifp = ifp->info;
1244 zassert(pim_ifp);
1245
1246 join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
1247 source_addr);
1248 if (join_fd < 0) {
1249 char group_str[INET_ADDRSTRLEN];
1250 char source_str[INET_ADDRSTRLEN];
1251 pim_inet4_dump("<grp?>", group_addr, group_str,
1252 sizeof(group_str));
1253 pim_inet4_dump("<src?>", source_addr, source_str,
1254 sizeof(source_str));
1255 zlog_warn(
1256 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1257 __PRETTY_FUNCTION__, group_str, source_str, ifp->name);
1258 return 0;
1259 }
1260
1261 ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
1262 if (!ij) {
1263 char group_str[INET_ADDRSTRLEN];
1264 char source_str[INET_ADDRSTRLEN];
1265 pim_inet4_dump("<grp?>", group_addr, group_str,
1266 sizeof(group_str));
1267 pim_inet4_dump("<src?>", source_addr, source_str,
1268 sizeof(source_str));
1269 zlog_err(
1270 "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s",
1271 __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str,
1272 ifp->name);
1273 close(join_fd);
1274 return 0;
1275 }
1276
1277 ij->sock_fd = join_fd;
1278 ij->group_addr = group_addr;
1279 ij->source_addr = source_addr;
1280 ij->sock_creation = pim_time_monotonic_sec();
1281
1282 listnode_add(pim_ifp->igmp_join_list, ij);
1283
1284 return ij;
1285 }
1286
1287 ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
1288 struct in_addr source_addr)
1289 {
1290 struct pim_interface *pim_ifp;
1291 struct igmp_join *ij;
1292
1293 pim_ifp = ifp->info;
1294 if (!pim_ifp) {
1295 return ferr_cfg_invalid("multicast not enabled on interface %s",
1296 ifp->name);
1297 }
1298
1299 if (!pim_ifp->igmp_join_list) {
1300 pim_ifp->igmp_join_list = list_new();
1301 if (!pim_ifp->igmp_join_list) {
1302 return ferr_cfg_invalid("Insufficient memory");
1303 }
1304 pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
1305 }
1306
1307 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1308
1309 /* This interface has already been configured to join this IGMP group
1310 */
1311 if (ij) {
1312 return ferr_ok();
1313 }
1314
1315 ij = igmp_join_new(ifp, group_addr, source_addr);
1316 if (!ij) {
1317 return ferr_cfg_invalid(
1318 "Failure to create new join data structure, see log file for more information");
1319 }
1320
1321 if (PIM_DEBUG_IGMP_EVENTS) {
1322 char group_str[INET_ADDRSTRLEN];
1323 char source_str[INET_ADDRSTRLEN];
1324 pim_inet4_dump("<grp?>", group_addr, group_str,
1325 sizeof(group_str));
1326 pim_inet4_dump("<src?>", source_addr, source_str,
1327 sizeof(source_str));
1328 zlog_debug(
1329 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1330 __PRETTY_FUNCTION__, source_str, group_str, ifp->name);
1331 }
1332
1333 return ferr_ok();
1334 }
1335
1336
1337 int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
1338 struct in_addr source_addr)
1339 {
1340 struct pim_interface *pim_ifp;
1341 struct igmp_join *ij;
1342
1343 pim_ifp = ifp->info;
1344 if (!pim_ifp) {
1345 zlog_warn("%s: multicast not enabled on interface %s",
1346 __PRETTY_FUNCTION__, ifp->name);
1347 return -1;
1348 }
1349
1350 if (!pim_ifp->igmp_join_list) {
1351 zlog_warn("%s: no IGMP join on interface %s",
1352 __PRETTY_FUNCTION__, ifp->name);
1353 return -2;
1354 }
1355
1356 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1357 if (!ij) {
1358 char group_str[INET_ADDRSTRLEN];
1359 char source_str[INET_ADDRSTRLEN];
1360 pim_inet4_dump("<grp?>", group_addr, group_str,
1361 sizeof(group_str));
1362 pim_inet4_dump("<src?>", source_addr, source_str,
1363 sizeof(source_str));
1364 zlog_warn(
1365 "%s: could not find IGMP group %s source %s on interface %s",
1366 __PRETTY_FUNCTION__, group_str, source_str, ifp->name);
1367 return -3;
1368 }
1369
1370 if (close(ij->sock_fd)) {
1371 char group_str[INET_ADDRSTRLEN];
1372 char source_str[INET_ADDRSTRLEN];
1373 pim_inet4_dump("<grp?>", group_addr, group_str,
1374 sizeof(group_str));
1375 pim_inet4_dump("<src?>", source_addr, source_str,
1376 sizeof(source_str));
1377 zlog_warn(
1378 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1379 __PRETTY_FUNCTION__, ij->sock_fd, group_str, source_str,
1380 ifp->name, errno, safe_strerror(errno));
1381 /* warning only */
1382 }
1383 listnode_delete(pim_ifp->igmp_join_list, ij);
1384 igmp_join_free(ij);
1385 if (listcount(pim_ifp->igmp_join_list) < 1) {
1386 list_delete_and_null(&pim_ifp->igmp_join_list);
1387 pim_ifp->igmp_join_list = 0;
1388 }
1389
1390 return 0;
1391 }
1392
1393 static void pim_if_igmp_join_del_all(struct interface *ifp)
1394 {
1395 struct pim_interface *pim_ifp;
1396 struct listnode *node;
1397 struct listnode *nextnode;
1398 struct igmp_join *ij;
1399
1400 pim_ifp = ifp->info;
1401 if (!pim_ifp) {
1402 zlog_warn("%s: multicast not enabled on interface %s",
1403 __PRETTY_FUNCTION__, ifp->name);
1404 return;
1405 }
1406
1407 if (!pim_ifp->igmp_join_list)
1408 return;
1409
1410 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij))
1411 pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);
1412 }
1413
1414 /*
1415 RFC 4601
1416
1417 Transitions from "I am Assert Loser" State
1418
1419 Current Winner's GenID Changes or NLT Expires
1420
1421 The Neighbor Liveness Timer associated with the current winner
1422 expires or we receive a Hello message from the current winner
1423 reporting a different GenID from the one it previously reported.
1424 This indicates that the current winner's interface or router has
1425 gone down (and may have come back up), and so we must assume it no
1426 longer knows it was the winner.
1427 */
1428 void pim_if_assert_on_neighbor_down(struct interface *ifp,
1429 struct in_addr neigh_addr)
1430 {
1431 struct pim_interface *pim_ifp;
1432 struct pim_ifchannel *ch;
1433
1434 pim_ifp = ifp->info;
1435 zassert(pim_ifp);
1436
1437 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1438 /* Is (S,G,I) assert loser ? */
1439 if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
1440 continue;
1441 /* Dead neighbor was winner ? */
1442 if (ch->ifassert_winner.s_addr != neigh_addr.s_addr)
1443 continue;
1444
1445 assert_action_a5(ch);
1446 }
1447 }
1448
1449 void pim_if_update_join_desired(struct pim_interface *pim_ifp)
1450 {
1451 struct pim_ifchannel *ch;
1452
1453 /* clear off flag from interface's upstreams */
1454 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1455 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1456 ch->upstream->flags);
1457 }
1458
1459 /* scan per-interface (S,G,I) state on this I interface */
1460 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1461 struct pim_upstream *up = ch->upstream;
1462
1463 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
1464 continue;
1465
1466 /* update join_desired for the global (S,G) state */
1467 pim_upstream_update_join_desired(pim_ifp->pim, up);
1468 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags);
1469 }
1470 }
1471
1472 void pim_if_update_assert_tracking_desired(struct interface *ifp)
1473 {
1474 struct pim_interface *pim_ifp;
1475 struct pim_ifchannel *ch;
1476
1477 pim_ifp = ifp->info;
1478 if (!pim_ifp)
1479 return;
1480
1481 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1482 pim_ifchannel_update_assert_tracking_desired(ch);
1483 }
1484 }
1485
1486 /*
1487 * PIM wants to have an interface pointer for everything it does.
1488 * The pimreg is a special interface that we have that is not
1489 * quite an inteface but a VIF is created for it.
1490 */
1491 void pim_if_create_pimreg(struct pim_instance *pim)
1492 {
1493 char pimreg_name[INTERFACE_NAMSIZ];
1494
1495 if (!pim->regiface) {
1496 if (pim->vrf_id == VRF_DEFAULT)
1497 strlcpy(pimreg_name, "pimreg", sizeof(pimreg_name));
1498 else
1499 snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
1500 pim->vrf->data.l.table_id);
1501
1502 pim->regiface = if_create(pimreg_name, pim->vrf_id);
1503 pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
1504
1505 pim_if_new(pim->regiface, 0, 0);
1506 }
1507 }
1508
1509 int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
1510 {
1511 struct listnode *cnode;
1512 struct connected *c;
1513 struct prefix p;
1514
1515 if (!ifp)
1516 return 0;
1517
1518 p.family = AF_INET;
1519 p.u.prefix4 = src;
1520 p.prefixlen = IPV4_MAX_BITLEN;
1521
1522 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
1523 if ((c->address->family == AF_INET)
1524 && prefix_match(CONNECTED_PREFIX(c), &p)) {
1525 return 1;
1526 }
1527 }
1528
1529 return 0;
1530 }
1531
1532 int pim_if_is_loopback(struct pim_instance *pim, struct interface *ifp)
1533 {
1534 if (if_is_loopback(ifp))
1535 return 1;
1536
1537 if (strcmp(ifp->name, pim->vrf->name) == 0)
1538 return 1;
1539
1540 return 0;
1541 }
1542
1543 int pim_if_is_vrf_device(struct interface *ifp)
1544 {
1545 struct vrf *vrf;
1546
1547 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1548 if (strncmp(ifp->name, vrf->name, strlen(ifp->name)) == 0)
1549 return 1;
1550 }
1551
1552 return 0;
1553 }
1554
1555 int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
1556 {
1557 struct pim_ifchannel *ch;
1558 int count = 0;
1559
1560 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1561 count++;
1562 }
1563
1564 return count;
1565 }