summaryrefslogtreecommitdiff
path: root/pimd/pim_iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_iface.c')
-rw-r--r--pimd/pim_iface.c124
1 files changed, 97 insertions, 27 deletions
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 5425aec233..d1b4966ec9 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -127,7 +127,6 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
pim_ifp->pim = ifp->vrf->info;
pim_ifp->mroute_vif_index = -1;
-#if PIM_IPV == 4
pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
pim_ifp->gm_default_robustness_variable =
IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
@@ -153,10 +152,12 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
if (pim)
PIM_IF_DO_PIM(pim_ifp->options);
+#if PIM_IPV == 4
if (igmp)
PIM_IF_DO_IGMP(pim_ifp->options);
PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options);
+#endif
pim_ifp->gm_join_list = NULL;
pim_ifp->pim_neighbor_list = NULL;
@@ -186,10 +187,11 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
ifp->info = pim_ifp;
+#if PIM_IPV == 4
pim_sock_reset(ifp);
+#endif
pim_if_add_vif(ifp, ispimreg, is_vxlan_term);
-#endif
pim_ifp->pim->mcast_if_count++;
return pim_ifp;
@@ -208,9 +210,12 @@ void pim_if_delete(struct interface *ifp)
if (pim_ifp->gm_join_list) {
pim_if_igmp_join_del_all(ifp);
}
+#endif
pim_ifchannel_delete_all(ifp);
+#if PIM_IPV == 4
igmp_sock_delete_all(ifp);
+#endif
pim_neighbor_delete_all(ifp, "Interface removed from configuration");
@@ -224,7 +229,6 @@ void pim_if_delete(struct interface *ifp)
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
-#endif
ifp->info = NULL;
}
@@ -512,6 +516,26 @@ void pim_if_addr_add(struct connected *ifc)
CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
? "secondary"
: "primary");
+#if PIM_IPV != 4
+ if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) ||
+ IN6_IS_ADDR_LOOPBACK(&ifc->address->u.prefix6)) {
+ if (IN6_IS_ADDR_UNSPECIFIED(&pim_ifp->ll_lowest))
+ pim_ifp->ll_lowest = ifc->address->u.prefix6;
+ else if (IPV6_ADDR_CMP(&ifc->address->u.prefix6,
+ &pim_ifp->ll_lowest) < 0)
+ pim_ifp->ll_lowest = ifc->address->u.prefix6;
+
+ if (IPV6_ADDR_CMP(&ifc->address->u.prefix6,
+ &pim_ifp->ll_highest) > 0)
+ pim_ifp->ll_highest = ifc->address->u.prefix6;
+
+ if (PIM_DEBUG_ZEBRA)
+ zlog_debug(
+ "%s: new link-local %pI6, lowest now %pI6, highest %pI6",
+ ifc->ifp->name, &ifc->address->u.prefix6,
+ &pim_ifp->ll_lowest, &pim_ifp->ll_highest);
+ }
+#endif
detect_address_change(ifp, 0, __func__);
@@ -711,6 +735,43 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
? "secondary"
: "primary");
+#if PIM_IPV == 6
+ struct pim_interface *pim_ifp = ifc->ifp->info;
+
+ if (pim_ifp &&
+ (!IPV6_ADDR_CMP(&ifc->address->u.prefix6, &pim_ifp->ll_lowest) ||
+ !IPV6_ADDR_CMP(&ifc->address->u.prefix6, &pim_ifp->ll_highest))) {
+ struct listnode *cnode;
+ struct connected *cc;
+
+ memset(&pim_ifp->ll_lowest, 0xff, sizeof(pim_ifp->ll_lowest));
+ memset(&pim_ifp->ll_highest, 0, sizeof(pim_ifp->ll_highest));
+
+ for (ALL_LIST_ELEMENTS_RO(ifc->ifp->connected, cnode, cc)) {
+ if (!IN6_IS_ADDR_LINKLOCAL(&cc->address->u.prefix6) &&
+ !IN6_IS_ADDR_LOOPBACK(&cc->address->u.prefix6))
+ continue;
+
+ if (IPV6_ADDR_CMP(&cc->address->u.prefix6,
+ &pim_ifp->ll_lowest) < 0)
+ pim_ifp->ll_lowest = cc->address->u.prefix6;
+ if (IPV6_ADDR_CMP(&cc->address->u.prefix6,
+ &pim_ifp->ll_highest) > 0)
+ pim_ifp->ll_highest = cc->address->u.prefix6;
+ }
+
+ if (pim_ifp->ll_lowest.s6_addr[0] == 0xff)
+ memset(&pim_ifp->ll_lowest, 0,
+ sizeof(pim_ifp->ll_lowest));
+
+ if (PIM_DEBUG_ZEBRA)
+ zlog_debug(
+ "%s: removed link-local %pI6, lowest now %pI6, highest %pI6",
+ ifc->ifp->name, &ifc->address->u.prefix6,
+ &pim_ifp->ll_lowest, &pim_ifp->ll_highest);
+ }
+#endif
+
detect_address_change(ifp, force_prim_as_any, __func__);
pim_if_addr_del_igmp(ifc);
@@ -825,17 +886,36 @@ pim_addr pim_find_primary_addr(struct interface *ifp)
{
struct connected *ifc;
struct listnode *node;
- int v4_addrs = 0;
- int v6_addrs = 0;
struct pim_interface *pim_ifp = ifp->info;
- if (pim_ifp && !pim_addr_is_any(pim_ifp->update_source)) {
+ if (pim_ifp && !pim_addr_is_any(pim_ifp->update_source))
return pim_ifp->update_source;
- }
+
+#if PIM_IPV == 6
+ if (pim_ifp)
+ return pim_ifp->ll_highest;
+
+ pim_addr best_addr = PIMADDR_ANY;
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
pim_addr addr;
+ if (ifc->address->family != AF_INET6)
+ continue;
+
+ addr = pim_addr_from_prefix(ifc->address);
+ if (!IN6_IS_ADDR_LINKLOCAL(&addr))
+ continue;
+ if (pim_addr_cmp(addr, best_addr) > 0)
+ best_addr = addr;
+ }
+
+ return best_addr;
+#else
+ int v4_addrs = 0;
+ int v6_addrs = 0;
+
+ for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
switch (ifc->address->family) {
case AF_INET:
v4_addrs++;
@@ -853,16 +933,9 @@ pim_addr pim_find_primary_addr(struct interface *ifp)
if (ifc->address->family != PIM_AF)
continue;
- addr = pim_addr_from_prefix(ifc->address);
-
-#if PIM_IPV == 6
- if (!IN6_IS_ADDR_LINKLOCAL(&addr))
- continue;
-#endif
- return addr;
+ return pim_addr_from_prefix(ifc->address);
}
-#if PIM_IPV == 4
/*
* If we have no v4_addrs and v6 is configured
* We probably are using unnumbered
@@ -882,8 +955,8 @@ pim_addr pim_find_primary_addr(struct interface *ifp)
if (lo_ifp && (lo_ifp != ifp))
return pim_find_primary_addr(lo_ifp);
}
-#endif
return PIMADDR_ANY;
+#endif
}
static int pim_iface_next_vif_index(struct interface *ifp)
@@ -1549,7 +1622,6 @@ static int pim_ifp_create(struct interface *ifp)
*/
if (pim_ifp)
pim_ifp->pim = pim;
-#if PIM_IPV == 4
pim_if_addr_add_all(ifp);
/*
@@ -1561,7 +1633,6 @@ static int pim_ifp_create(struct interface *ifp)
* this is a no-op if it's already been done.
*/
pim_if_create_pimreg(pim);
-#endif
}
#if PIM_IPV == 4
@@ -1599,6 +1670,7 @@ static int pim_ifp_create(struct interface *ifp)
static int pim_ifp_up(struct interface *ifp)
{
+ uint32_t table_id;
struct pim_interface *pim_ifp;
struct pim_instance *pim;
@@ -1621,9 +1693,6 @@ static int pim_ifp_up(struct interface *ifp)
if (pim_ifp)
pim_ifp->pim = pim;
-#if PIM_IPV == 4
- uint32_t table_id;
-
/*
pim_if_addr_add_all() suffices for bringing up both IGMP and
PIM
@@ -1652,7 +1721,6 @@ static int pim_ifp_up(struct interface *ifp)
}
}
}
-#endif
return 0;
}
@@ -1666,7 +1734,6 @@ static int pim_ifp_down(struct interface *ifp)
ifp->mtu, if_is_operative(ifp));
}
-#if PIM_IPV == 4
if (!if_is_operative(ifp)) {
pim_ifchannel_delete_all(ifp);
/*
@@ -1675,6 +1742,7 @@ static int pim_ifp_down(struct interface *ifp)
*/
pim_if_addr_del_all(ifp);
+#if PIM_IPV == 4
/*
pim_sock_delete() closes the socket, stops read and timer
threads,
@@ -1683,13 +1751,15 @@ static int pim_ifp_down(struct interface *ifp)
if (ifp->info) {
pim_sock_delete(ifp, "link down");
}
+#endif
}
if (ifp->info) {
pim_if_del_vif(ifp);
+#if PIM_IPV == 4
pim_ifstat_reset(ifp);
- }
#endif
+ }
return 0;
}
@@ -1704,12 +1774,12 @@ static int pim_ifp_destroy(struct interface *ifp)
ifp->mtu, if_is_operative(ifp));
}
-#if PIM_IPV == 4
- struct pim_instance *pim;
-
if (!if_is_operative(ifp))
pim_if_addr_del_all(ifp);
+#if PIM_IPV == 4
+ struct pim_instance *pim;
+
pim = ifp->vrf->info;
if (pim && pim->vxlan.term_if == ifp)
pim_vxlan_del_term_dev(pim);