pim6d: rework interface address tracking/selection

We only care about link-local addresses for IPv6 operation.  Also, MLD
needs the lowest while PIM needs the highest...

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2022-03-10 11:22:32 +01:00
parent cd6d285855
commit cfef61553f
3 changed files with 95 additions and 14 deletions

View File

@ -512,6 +512,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 +731,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 +882,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 +929,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 +951,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)

View File

@ -96,6 +96,13 @@ struct pim_interface {
uint32_t options; /* bit vector */
ifindex_t mroute_vif_index;
struct pim_instance *pim;
#if PIM_IPV == 6
/* link-locals: MLD uses lowest addr, PIM uses highest... */
pim_addr ll_lowest;
pim_addr ll_highest;
#endif
pim_addr primary_address; /* remember addr to detect change */
struct list *sec_addr_list; /* list of struct pim_secondary_addr */
pim_addr update_source; /* user can statically set the primary

View File

@ -179,8 +179,10 @@ static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
}
}
#else /* PIM_IPV != 4 */
/* unused - for now */
(void)pim_ifp;
if (p->family == PIM_AF)
pim_if_addr_add(c);
#endif
return 0;
}
@ -229,6 +231,9 @@ static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
pim_rp_setup(pim);
pim_i_am_rp_re_evaluate(pim);
}
#else
if (p->family == PIM_AF)
pim_if_addr_del(c, 0);
#endif
connected_free(&c);