]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_iface.c
Merge pull request #1776 from dslicenc/static-inactive-cm19675
[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,
431 sec_addr)) {
432 sec_addr->flags |= PIM_SEC_ADDRF_STALE;
433 }
434
435 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
436 struct prefix *p = ifc->address;
437
438 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
439 continue;
440 }
441
442 if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) {
443 /* don't add the primary address into the secondary
444 * address list */
445 continue;
446 }
447
448 if (pim_sec_addr_add(pim_ifp, p)) {
449 changed = 1;
450 }
451 }
452
453 /* Drop stale entries */
454 for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
455 sec_addr)) {
456 if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
457 pim_sec_addr_del(pim_ifp, sec_addr);
458 changed = 1;
459 }
460 }
461
462 return changed;
463 }
464
465 static int detect_secondary_address_change(struct interface *ifp,
466 int force_prim_as_any,
467 const char *caller)
468 {
469 struct pim_interface *pim_ifp = ifp->info;
470 int changed = 0;
471
472 if (force_prim_as_any) {
473 /* if primary address is being forced to zero just flush the
474 * secondary address list */
475 changed = pim_sec_addr_del_all(pim_ifp);
476 } else {
477 /* re-evaluate the secondary address list */
478 changed = pim_sec_addr_update(ifp);
479 }
480
481 return changed;
482 }
483
484 static void detect_address_change(struct interface *ifp, int force_prim_as_any,
485 const char *caller)
486 {
487 int changed = 0;
488 struct pim_interface *pim_ifp;
489
490 pim_ifp = ifp->info;
491 if (!pim_ifp)
492 return;
493
494 if (detect_primary_address_change(ifp, force_prim_as_any, caller)) {
495 changed = 1;
496 }
497
498 if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) {
499 changed = 1;
500 }
501
502
503 if (changed) {
504 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
505 return;
506 }
507
508 pim_addr_change(ifp);
509 }
510
511 /* XXX: if we have unnumbered interfaces we need to run detect address
512 * address change on all of them when the lo address changes */
513 }
514
515 int pim_update_source_set(struct interface *ifp, struct in_addr source)
516 {
517 struct pim_interface *pim_ifp = ifp->info;
518
519 if (!pim_ifp) {
520 return PIM_IFACE_NOT_FOUND;
521 }
522
523 if (pim_ifp->update_source.s_addr == source.s_addr) {
524 return PIM_UPDATE_SOURCE_DUP;
525 }
526
527 pim_ifp->update_source = source;
528 detect_address_change(ifp, 0 /* force_prim_as_any */,
529 __PRETTY_FUNCTION__);
530
531 return PIM_SUCCESS;
532 }
533
534 void pim_if_addr_add(struct connected *ifc)
535 {
536 struct pim_interface *pim_ifp;
537 struct interface *ifp;
538 struct in_addr ifaddr;
539
540 zassert(ifc);
541
542 ifp = ifc->ifp;
543 zassert(ifp);
544 pim_ifp = ifp->info;
545 if (!pim_ifp)
546 return;
547
548 if (!if_is_operative(ifp))
549 return;
550
551 if (PIM_DEBUG_ZEBRA) {
552 char buf[BUFSIZ];
553 prefix2str(ifc->address, buf, BUFSIZ);
554 zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
555 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf,
556 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
557 ? "secondary"
558 : "primary");
559 }
560
561 ifaddr = ifc->address->u.prefix4;
562
563 detect_address_change(ifp, 0, __PRETTY_FUNCTION__);
564
565 // if (ifc->address->family != AF_INET)
566 // return;
567
568 if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
569 struct igmp_sock *igmp;
570
571 /* lookup IGMP socket */
572 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
573 ifaddr);
574 if (!igmp) {
575 /* if addr new, add IGMP socket */
576 if (ifc->address->family == AF_INET)
577 pim_igmp_sock_add(pim_ifp->igmp_socket_list,
578 ifaddr, ifp);
579 }
580
581 /* Replay Static IGMP groups */
582 if (pim_ifp->igmp_join_list) {
583 struct listnode *node;
584 struct listnode *nextnode;
585 struct igmp_join *ij;
586 int join_fd;
587
588 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node,
589 nextnode, ij)) {
590 /* Close socket and reopen with Source and Group
591 */
592 close(ij->sock_fd);
593 join_fd = igmp_join_sock(
594 ifp->name, ifp->ifindex, ij->group_addr,
595 ij->source_addr);
596 if (join_fd < 0) {
597 char group_str[INET_ADDRSTRLEN];
598 char source_str[INET_ADDRSTRLEN];
599 pim_inet4_dump("<grp?>", ij->group_addr,
600 group_str,
601 sizeof(group_str));
602 pim_inet4_dump(
603 "<src?>", ij->source_addr,
604 source_str, sizeof(source_str));
605 zlog_warn(
606 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
607 __PRETTY_FUNCTION__, group_str,
608 source_str, ifp->name);
609 /* warning only */
610 } else
611 ij->sock_fd = join_fd;
612 }
613 }
614 } /* igmp */
615
616 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
617
618 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
619
620 /* Interface has a valid socket ? */
621 if (pim_ifp->pim_sock_fd < 0) {
622 if (pim_sock_add(ifp)) {
623 zlog_warn(
624 "Failure creating PIM socket for interface %s",
625 ifp->name);
626 }
627 }
628 struct pim_nexthop_cache *pnc = NULL;
629 struct pim_rpf rpf;
630 struct zclient *zclient = NULL;
631
632 zclient = pim_zebra_zclient_get();
633 /* RP config might come prior to (local RP's interface)
634 IF UP event.
635 In this case, pnc would not have pim enabled
636 nexthops.
637 Once Interface is UP and pim info is available,
638 reregister
639 with RNH address to receive update and add the
640 interface as nexthop. */
641 memset(&rpf, 0, sizeof(struct pim_rpf));
642 rpf.rpf_addr.family = AF_INET;
643 rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
644 rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
645 pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
646 if (pnc)
647 pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
648 pnc,
649 ZEBRA_NEXTHOP_REGISTER);
650 }
651 } /* pim */
652
653 /*
654 PIM or IGMP is enabled on interface, and there is at least one
655 address assigned, then try to create a vif_index.
656 */
657 if (pim_ifp->mroute_vif_index < 0) {
658 pim_if_add_vif(ifp);
659 }
660 pim_ifchannel_scan_forward_start(ifp);
661 }
662
663 static void pim_if_addr_del_igmp(struct connected *ifc)
664 {
665 struct pim_interface *pim_ifp = ifc->ifp->info;
666 struct igmp_sock *igmp;
667 struct in_addr ifaddr;
668
669 if (ifc->address->family != AF_INET) {
670 /* non-IPv4 address */
671 return;
672 }
673
674 if (!pim_ifp) {
675 /* IGMP not enabled on interface */
676 return;
677 }
678
679 ifaddr = ifc->address->u.prefix4;
680
681 /* lookup IGMP socket */
682 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
683 if (igmp) {
684 /* if addr found, del IGMP socket */
685 igmp_sock_delete(igmp);
686 }
687 }
688
689 static void pim_if_addr_del_pim(struct connected *ifc)
690 {
691 struct pim_interface *pim_ifp = ifc->ifp->info;
692
693 if (ifc->address->family != AF_INET) {
694 /* non-IPv4 address */
695 return;
696 }
697
698 if (!pim_ifp) {
699 /* PIM not enabled on interface */
700 return;
701 }
702
703 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
704 /* Interface keeps a valid primary address */
705 return;
706 }
707
708 if (pim_ifp->pim_sock_fd < 0) {
709 /* Interface does not hold a valid socket any longer */
710 return;
711 }
712
713 /*
714 pim_sock_delete() closes the socket, stops read and timer threads,
715 and kills all neighbors.
716 */
717 pim_sock_delete(ifc->ifp,
718 "last address has been removed from interface");
719 }
720
721 void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
722 {
723 struct interface *ifp;
724
725 zassert(ifc);
726 ifp = ifc->ifp;
727 zassert(ifp);
728
729 if (PIM_DEBUG_ZEBRA) {
730 char buf[BUFSIZ];
731 prefix2str(ifc->address, buf, BUFSIZ);
732 zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
733 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf,
734 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
735 ? "secondary"
736 : "primary");
737 }
738
739 detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__);
740
741 pim_if_addr_del_igmp(ifc);
742 pim_if_addr_del_pim(ifc);
743 }
744
745 void pim_if_addr_add_all(struct interface *ifp)
746 {
747 struct connected *ifc;
748 struct listnode *node;
749 struct listnode *nextnode;
750 int v4_addrs = 0;
751 int v6_addrs = 0;
752 struct pim_interface *pim_ifp = ifp->info;
753
754
755 /* PIM/IGMP enabled ? */
756 if (!pim_ifp)
757 return;
758
759 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
760 struct prefix *p = ifc->address;
761
762 if (p->family != AF_INET)
763 v6_addrs++;
764 else
765 v4_addrs++;
766 pim_if_addr_add(ifc);
767 }
768
769 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
770 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
771
772 /* Interface has a valid primary address ? */
773 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
774
775 /* Interface has a valid socket ? */
776 if (pim_ifp->pim_sock_fd < 0) {
777 if (pim_sock_add(ifp)) {
778 zlog_warn(
779 "Failure creating PIM socket for interface %s",
780 ifp->name);
781 }
782 }
783 }
784 } /* pim */
785 }
786 /*
787 * PIM or IGMP is enabled on interface, and there is at least one
788 * address assigned, then try to create a vif_index.
789 */
790 if (pim_ifp->mroute_vif_index < 0) {
791 pim_if_add_vif(ifp);
792 }
793 pim_ifchannel_scan_forward_start(ifp);
794
795 pim_rp_setup(pim_ifp->pim);
796 pim_rp_check_on_if_add(pim_ifp);
797 }
798
799 void pim_if_addr_del_all(struct interface *ifp)
800 {
801 struct connected *ifc;
802 struct listnode *node;
803 struct listnode *nextnode;
804 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
805 struct pim_instance *pim;
806
807 if (!vrf)
808 return;
809 pim = vrf->info;
810
811 /* PIM/IGMP enabled ? */
812 if (!ifp->info)
813 return;
814
815 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
816 struct prefix *p = ifc->address;
817
818 if (p->family != AF_INET)
819 continue;
820
821 pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */);
822 }
823
824 pim_rp_setup(pim);
825 pim_i_am_rp_re_evaluate(pim);
826 }
827
828 void pim_if_addr_del_all_igmp(struct interface *ifp)
829 {
830 struct connected *ifc;
831 struct listnode *node;
832 struct listnode *nextnode;
833
834 /* PIM/IGMP enabled ? */
835 if (!ifp->info)
836 return;
837
838 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
839 struct prefix *p = ifc->address;
840
841 if (p->family != AF_INET)
842 continue;
843
844 pim_if_addr_del_igmp(ifc);
845 }
846 }
847
848 void pim_if_addr_del_all_pim(struct interface *ifp)
849 {
850 struct connected *ifc;
851 struct listnode *node;
852 struct listnode *nextnode;
853
854 /* PIM/IGMP enabled ? */
855 if (!ifp->info)
856 return;
857
858 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
859 struct prefix *p = ifc->address;
860
861 if (p->family != AF_INET)
862 continue;
863
864 pim_if_addr_del_pim(ifc);
865 }
866 }
867
868 struct in_addr pim_find_primary_addr(struct interface *ifp)
869 {
870 struct connected *ifc;
871 struct listnode *node;
872 struct in_addr addr = {0};
873 int v4_addrs = 0;
874 int v6_addrs = 0;
875 struct pim_interface *pim_ifp = ifp->info;
876 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
877
878 if (!vrf)
879 return addr;
880
881 if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
882 return pim_ifp->update_source;
883 }
884
885 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
886 struct prefix *p = ifc->address;
887
888 if (p->family != AF_INET) {
889 v6_addrs++;
890 continue;
891 }
892
893 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
894 zlog_warn(
895 "%s: null IPv4 address connected to interface %s",
896 __PRETTY_FUNCTION__, ifp->name);
897 continue;
898 }
899
900 v4_addrs++;
901
902 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
903 continue;
904
905 return p->u.prefix4;
906 }
907
908 /*
909 * If we have no v4_addrs and v6 is configured
910 * We probably are using unnumbered
911 * So let's grab the loopbacks v4 address
912 * and use that as the primary address
913 */
914 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
915 struct interface *lo_ifp;
916 // DBS - Come back and check here
917 if (ifp->vrf_id == VRF_DEFAULT)
918 lo_ifp = if_lookup_by_name("lo", vrf->vrf_id);
919 else
920 lo_ifp = if_lookup_by_name(vrf->name, vrf->vrf_id);
921
922 if (lo_ifp)
923 return pim_find_primary_addr(lo_ifp);
924 }
925
926 addr.s_addr = PIM_NET_INADDR_ANY;
927
928 return addr;
929 }
930
931 static int pim_iface_next_vif_index(struct interface *ifp)
932 {
933 struct pim_interface *pim_ifp = ifp->info;
934 struct pim_instance *pim = pim_ifp->pim;
935 int i;
936
937 /*
938 * The pimreg vif is always going to be in index 0
939 * of the table.
940 */
941 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
942 return 0;
943
944 for (i = 1; i < MAXVIFS; i++) {
945 if (pim->iface_vif_index[i] == 0)
946 return i;
947 }
948 return MAXVIFS;
949 }
950
951 /*
952 pim_if_add_vif() uses ifindex as vif_index
953
954 see also pim_if_find_vifindex_by_ifindex()
955 */
956 int pim_if_add_vif(struct interface *ifp)
957 {
958 struct pim_interface *pim_ifp = ifp->info;
959 struct in_addr ifaddr;
960 unsigned char flags = 0;
961
962 zassert(pim_ifp);
963
964 if (pim_ifp->mroute_vif_index > 0) {
965 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
966 __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index,
967 ifp->name, ifp->ifindex);
968 return -1;
969 }
970
971 if (ifp->ifindex < 0) {
972 zlog_warn("%s: ifindex=%d < 1 on interface %s",
973 __PRETTY_FUNCTION__, ifp->ifindex, ifp->name);
974 return -2;
975 }
976
977 ifaddr = pim_ifp->primary_address;
978 if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF
979 && PIM_INADDR_IS_ANY(ifaddr)) {
980 zlog_warn(
981 "%s: could not get address for interface %s ifindex=%d",
982 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex);
983 return -4;
984 }
985
986 pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp);
987
988 if (pim_ifp->mroute_vif_index >= MAXVIFS) {
989 zlog_warn(
990 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
991 __PRETTY_FUNCTION__, MAXVIFS, ifp->name);
992 return -3;
993 }
994
995 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
996 flags = VIFF_REGISTER;
997 #ifdef VIFF_USE_IFINDEX
998 else
999 flags = VIFF_USE_IFINDEX;
1000 #endif
1001
1002 if (pim_mroute_add_vif(ifp, ifaddr, flags)) {
1003 /* pim_mroute_add_vif reported error */
1004 return -5;
1005 }
1006
1007 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
1008 return 0;
1009 }
1010
1011 int pim_if_del_vif(struct interface *ifp)
1012 {
1013 struct pim_interface *pim_ifp = ifp->info;
1014
1015 if (pim_ifp->mroute_vif_index < 1) {
1016 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1017 __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index,
1018 ifp->name, ifp->ifindex);
1019 return -1;
1020 }
1021
1022 pim_mroute_del_vif(ifp);
1023
1024 /*
1025 Update vif_index
1026 */
1027 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 0;
1028
1029 pim_ifp->mroute_vif_index = -1;
1030
1031 return 0;
1032 }
1033
1034 // DBS - VRF Revist
1035 struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
1036 ifindex_t vif_index)
1037 {
1038 struct interface *ifp;
1039
1040 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1041 if (ifp->info) {
1042 struct pim_interface *pim_ifp;
1043 pim_ifp = ifp->info;
1044
1045 if (vif_index == pim_ifp->mroute_vif_index)
1046 return ifp;
1047 }
1048 }
1049
1050 return 0;
1051 }
1052
1053 /*
1054 pim_if_add_vif() uses ifindex as vif_index
1055 */
1056 int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex)
1057 {
1058 struct pim_interface *pim_ifp;
1059 struct interface *ifp;
1060
1061 ifp = if_lookup_by_index(ifindex, pim->vrf_id);
1062 if (!ifp || !ifp->info)
1063 return -1;
1064 pim_ifp = ifp->info;
1065
1066 return pim_ifp->mroute_vif_index;
1067 }
1068
1069 int pim_if_lan_delay_enabled(struct interface *ifp)
1070 {
1071 struct pim_interface *pim_ifp;
1072
1073 pim_ifp = ifp->info;
1074 zassert(pim_ifp);
1075 zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
1076
1077 return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;
1078 }
1079
1080 uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp)
1081 {
1082 if (pim_if_lan_delay_enabled(ifp)) {
1083 struct pim_interface *pim_ifp;
1084 pim_ifp = ifp->info;
1085 return pim_ifp->pim_neighbors_highest_propagation_delay_msec;
1086 } else {
1087 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
1088 }
1089 }
1090
1091 uint16_t pim_if_effective_override_interval_msec(struct interface *ifp)
1092 {
1093 if (pim_if_lan_delay_enabled(ifp)) {
1094 struct pim_interface *pim_ifp;
1095 pim_ifp = ifp->info;
1096 return pim_ifp->pim_neighbors_highest_override_interval_msec;
1097 } else {
1098 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
1099 }
1100 }
1101
1102 int pim_if_t_override_msec(struct interface *ifp)
1103 {
1104 int effective_override_interval_msec;
1105 int t_override_msec;
1106
1107 effective_override_interval_msec =
1108 pim_if_effective_override_interval_msec(ifp);
1109
1110 t_override_msec = random() % (effective_override_interval_msec + 1);
1111
1112 return t_override_msec;
1113 }
1114
1115 uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
1116 {
1117 return pim_if_effective_propagation_delay_msec(ifp)
1118 + pim_if_effective_override_interval_msec(ifp);
1119 }
1120
1121 /*
1122 RFC 4601: 4.1.6. State Summarization Macros
1123
1124 The function NBR( I, A ) uses information gathered through PIM Hello
1125 messages to map the IP address A of a directly connected PIM
1126 neighbor router on interface I to the primary IP address of the same
1127 router (Section 4.3.4). The primary IP address of a neighbor is the
1128 address that it uses as the source of its PIM Hello messages.
1129 */
1130 struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
1131 struct in_addr addr)
1132 {
1133 struct listnode *neighnode;
1134 struct pim_neighbor *neigh;
1135 struct pim_interface *pim_ifp;
1136 struct prefix p;
1137
1138 zassert(ifp);
1139
1140 pim_ifp = ifp->info;
1141 if (!pim_ifp) {
1142 zlog_warn("%s: multicast not enabled on interface %s",
1143 __PRETTY_FUNCTION__, ifp->name);
1144 return 0;
1145 }
1146
1147 p.family = AF_INET;
1148 p.u.prefix4 = addr;
1149 p.prefixlen = IPV4_MAX_PREFIXLEN;
1150
1151 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1152 neigh)) {
1153
1154 /* primary address ? */
1155 if (neigh->source_addr.s_addr == addr.s_addr)
1156 return neigh;
1157
1158 /* secondary address ? */
1159 if (pim_neighbor_find_secondary(neigh, &p))
1160 return neigh;
1161 }
1162
1163 if (PIM_DEBUG_PIM_TRACE) {
1164 char addr_str[INET_ADDRSTRLEN];
1165 pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
1166 zlog_debug(
1167 "%s: neighbor not found for address %s on interface %s",
1168 __PRETTY_FUNCTION__, addr_str, ifp->name);
1169 }
1170
1171 return NULL;
1172 }
1173
1174 long pim_if_t_suppressed_msec(struct interface *ifp)
1175 {
1176 struct pim_interface *pim_ifp;
1177 long t_suppressed_msec;
1178 uint32_t ramount = 0;
1179
1180 pim_ifp = ifp->info;
1181 zassert(pim_ifp);
1182
1183 /* join suppression disabled ? */
1184 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options))
1185 return 0;
1186
1187 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1188 ramount = 1100 + (random() % (1400 - 1100 + 1));
1189 t_suppressed_msec = qpim_t_periodic * ramount;
1190
1191 return t_suppressed_msec;
1192 }
1193
1194 static void igmp_join_free(struct igmp_join *ij)
1195 {
1196 XFREE(MTYPE_PIM_IGMP_JOIN, ij);
1197 }
1198
1199 static struct igmp_join *igmp_join_find(struct list *join_list,
1200 struct in_addr group_addr,
1201 struct in_addr source_addr)
1202 {
1203 struct listnode *node;
1204 struct igmp_join *ij;
1205
1206 zassert(join_list);
1207
1208 for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) {
1209 if ((group_addr.s_addr == ij->group_addr.s_addr)
1210 && (source_addr.s_addr == ij->source_addr.s_addr))
1211 return ij;
1212 }
1213
1214 return 0;
1215 }
1216
1217 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
1218 struct in_addr group_addr, struct in_addr source_addr)
1219 {
1220 int join_fd;
1221
1222 join_fd = pim_socket_raw(IPPROTO_IGMP);
1223 if (join_fd < 0) {
1224 return -1;
1225 }
1226
1227 if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr,
1228 ifname)) {
1229 close(join_fd);
1230 return -2;
1231 }
1232
1233 return join_fd;
1234 }
1235
1236 static struct igmp_join *igmp_join_new(struct interface *ifp,
1237 struct in_addr group_addr,
1238 struct in_addr source_addr)
1239 {
1240 struct pim_interface *pim_ifp;
1241 struct igmp_join *ij;
1242 int join_fd;
1243
1244 pim_ifp = ifp->info;
1245 zassert(pim_ifp);
1246
1247 join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
1248 source_addr);
1249 if (join_fd < 0) {
1250 char group_str[INET_ADDRSTRLEN];
1251 char source_str[INET_ADDRSTRLEN];
1252 pim_inet4_dump("<grp?>", group_addr, group_str,
1253 sizeof(group_str));
1254 pim_inet4_dump("<src?>", source_addr, source_str,
1255 sizeof(source_str));
1256 zlog_warn(
1257 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1258 __PRETTY_FUNCTION__, group_str, source_str, ifp->name);
1259 return 0;
1260 }
1261
1262 ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
1263 if (!ij) {
1264 char group_str[INET_ADDRSTRLEN];
1265 char source_str[INET_ADDRSTRLEN];
1266 pim_inet4_dump("<grp?>", group_addr, group_str,
1267 sizeof(group_str));
1268 pim_inet4_dump("<src?>", source_addr, source_str,
1269 sizeof(source_str));
1270 zlog_err(
1271 "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s",
1272 __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str,
1273 ifp->name);
1274 close(join_fd);
1275 return 0;
1276 }
1277
1278 ij->sock_fd = join_fd;
1279 ij->group_addr = group_addr;
1280 ij->source_addr = source_addr;
1281 ij->sock_creation = pim_time_monotonic_sec();
1282
1283 listnode_add(pim_ifp->igmp_join_list, ij);
1284
1285 return ij;
1286 }
1287
1288 ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
1289 struct in_addr source_addr)
1290 {
1291 struct pim_interface *pim_ifp;
1292 struct igmp_join *ij;
1293
1294 pim_ifp = ifp->info;
1295 if (!pim_ifp) {
1296 return ferr_cfg_invalid("multicast not enabled on interface %s",
1297 ifp->name);
1298 }
1299
1300 if (!pim_ifp->igmp_join_list) {
1301 pim_ifp->igmp_join_list = list_new();
1302 if (!pim_ifp->igmp_join_list) {
1303 return ferr_cfg_invalid("Insufficient memory");
1304 }
1305 pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
1306 }
1307
1308 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1309
1310 /* This interface has already been configured to join this IGMP group
1311 */
1312 if (ij) {
1313 return ferr_ok();
1314 }
1315
1316 ij = igmp_join_new(ifp, group_addr, source_addr);
1317 if (!ij) {
1318 return ferr_cfg_invalid(
1319 "Failure to create new join data structure, see log file for more information");
1320 }
1321
1322 if (PIM_DEBUG_IGMP_EVENTS) {
1323 char group_str[INET_ADDRSTRLEN];
1324 char source_str[INET_ADDRSTRLEN];
1325 pim_inet4_dump("<grp?>", group_addr, group_str,
1326 sizeof(group_str));
1327 pim_inet4_dump("<src?>", source_addr, source_str,
1328 sizeof(source_str));
1329 zlog_debug(
1330 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1331 __PRETTY_FUNCTION__, source_str, group_str, ifp->name);
1332 }
1333
1334 return ferr_ok();
1335 }
1336
1337
1338 int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
1339 struct in_addr source_addr)
1340 {
1341 struct pim_interface *pim_ifp;
1342 struct igmp_join *ij;
1343
1344 pim_ifp = ifp->info;
1345 if (!pim_ifp) {
1346 zlog_warn("%s: multicast not enabled on interface %s",
1347 __PRETTY_FUNCTION__, ifp->name);
1348 return -1;
1349 }
1350
1351 if (!pim_ifp->igmp_join_list) {
1352 zlog_warn("%s: no IGMP join on interface %s",
1353 __PRETTY_FUNCTION__, ifp->name);
1354 return -2;
1355 }
1356
1357 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1358 if (!ij) {
1359 char group_str[INET_ADDRSTRLEN];
1360 char source_str[INET_ADDRSTRLEN];
1361 pim_inet4_dump("<grp?>", group_addr, group_str,
1362 sizeof(group_str));
1363 pim_inet4_dump("<src?>", source_addr, source_str,
1364 sizeof(source_str));
1365 zlog_warn(
1366 "%s: could not find IGMP group %s source %s on interface %s",
1367 __PRETTY_FUNCTION__, group_str, source_str, ifp->name);
1368 return -3;
1369 }
1370
1371 if (close(ij->sock_fd)) {
1372 char group_str[INET_ADDRSTRLEN];
1373 char source_str[INET_ADDRSTRLEN];
1374 pim_inet4_dump("<grp?>", group_addr, group_str,
1375 sizeof(group_str));
1376 pim_inet4_dump("<src?>", source_addr, source_str,
1377 sizeof(source_str));
1378 zlog_warn(
1379 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1380 __PRETTY_FUNCTION__, ij->sock_fd, group_str, source_str,
1381 ifp->name, errno, safe_strerror(errno));
1382 /* warning only */
1383 }
1384 listnode_delete(pim_ifp->igmp_join_list, ij);
1385 igmp_join_free(ij);
1386 if (listcount(pim_ifp->igmp_join_list) < 1) {
1387 list_delete_and_null(&pim_ifp->igmp_join_list);
1388 pim_ifp->igmp_join_list = 0;
1389 }
1390
1391 return 0;
1392 }
1393
1394 static void pim_if_igmp_join_del_all(struct interface *ifp)
1395 {
1396 struct pim_interface *pim_ifp;
1397 struct listnode *node;
1398 struct listnode *nextnode;
1399 struct igmp_join *ij;
1400
1401 pim_ifp = ifp->info;
1402 if (!pim_ifp) {
1403 zlog_warn("%s: multicast not enabled on interface %s",
1404 __PRETTY_FUNCTION__, ifp->name);
1405 return;
1406 }
1407
1408 if (!pim_ifp->igmp_join_list)
1409 return;
1410
1411 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij))
1412 pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);
1413 }
1414
1415 /*
1416 RFC 4601
1417
1418 Transitions from "I am Assert Loser" State
1419
1420 Current Winner's GenID Changes or NLT Expires
1421
1422 The Neighbor Liveness Timer associated with the current winner
1423 expires or we receive a Hello message from the current winner
1424 reporting a different GenID from the one it previously reported.
1425 This indicates that the current winner's interface or router has
1426 gone down (and may have come back up), and so we must assume it no
1427 longer knows it was the winner.
1428 */
1429 void pim_if_assert_on_neighbor_down(struct interface *ifp,
1430 struct in_addr neigh_addr)
1431 {
1432 struct pim_interface *pim_ifp;
1433 struct pim_ifchannel *ch;
1434
1435 pim_ifp = ifp->info;
1436 zassert(pim_ifp);
1437
1438 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1439 /* Is (S,G,I) assert loser ? */
1440 if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
1441 continue;
1442 /* Dead neighbor was winner ? */
1443 if (ch->ifassert_winner.s_addr != neigh_addr.s_addr)
1444 continue;
1445
1446 assert_action_a5(ch);
1447 }
1448 }
1449
1450 void pim_if_update_join_desired(struct pim_interface *pim_ifp)
1451 {
1452 struct pim_ifchannel *ch;
1453
1454 /* clear off flag from interface's upstreams */
1455 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1456 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1457 ch->upstream->flags);
1458 }
1459
1460 /* scan per-interface (S,G,I) state on this I interface */
1461 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1462 struct pim_upstream *up = ch->upstream;
1463
1464 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
1465 continue;
1466
1467 /* update join_desired for the global (S,G) state */
1468 pim_upstream_update_join_desired(pim_ifp->pim, up);
1469 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags);
1470 }
1471 }
1472
1473 void pim_if_update_assert_tracking_desired(struct interface *ifp)
1474 {
1475 struct pim_interface *pim_ifp;
1476 struct pim_ifchannel *ch;
1477
1478 pim_ifp = ifp->info;
1479 if (!pim_ifp)
1480 return;
1481
1482 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1483 pim_ifchannel_update_assert_tracking_desired(ch);
1484 }
1485 }
1486
1487 /*
1488 * PIM wants to have an interface pointer for everything it does.
1489 * The pimreg is a special interface that we have that is not
1490 * quite an inteface but a VIF is created for it.
1491 */
1492 void pim_if_create_pimreg(struct pim_instance *pim)
1493 {
1494 char pimreg_name[INTERFACE_NAMSIZ];
1495
1496 if (!pim->regiface) {
1497 if (pim->vrf_id == VRF_DEFAULT)
1498 strlcpy(pimreg_name, "pimreg", sizeof(pimreg_name));
1499 else
1500 snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
1501 pim->vrf->data.l.table_id);
1502
1503 pim->regiface = if_create(pimreg_name, pim->vrf_id);
1504 pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
1505
1506 pim_if_new(pim->regiface, 0, 0);
1507 }
1508 }
1509
1510 int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
1511 {
1512 struct listnode *cnode;
1513 struct connected *c;
1514 struct prefix p;
1515
1516 if (!ifp)
1517 return 0;
1518
1519 p.family = AF_INET;
1520 p.u.prefix4 = src;
1521 p.prefixlen = IPV4_MAX_BITLEN;
1522
1523 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
1524 if ((c->address->family == AF_INET)
1525 && prefix_match(CONNECTED_PREFIX(c), &p)) {
1526 return 1;
1527 }
1528 }
1529
1530 return 0;
1531 }
1532
1533 int pim_if_is_loopback(struct pim_instance *pim, struct interface *ifp)
1534 {
1535 if (if_is_loopback(ifp))
1536 return 1;
1537
1538 if (strcmp(ifp->name, pim->vrf->name) == 0)
1539 return 1;
1540
1541 return 0;
1542 }
1543
1544 int pim_if_is_vrf_device(struct interface *ifp)
1545 {
1546 struct vrf *vrf;
1547
1548 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1549 if (strncmp(ifp->name, vrf->name, strlen(ifp->name)) == 0)
1550 return 1;
1551 }
1552
1553 return 0;
1554 }
1555
1556 int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
1557 {
1558 struct pim_ifchannel *ch;
1559 int count = 0;
1560
1561 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1562 count++;
1563 }
1564
1565 return count;
1566 }