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