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