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