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