mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 05:21:31 +00:00
zebra: delete kernel routes using an interface with no more IPv4 address
When the last IPv4 address of an interface is deleted, Linux removes all routes using this interface without any Netlink advertisement. Routes that have a IPv4 nexthop are correctly removed from the FRR RIB. However, routes that only have an interface with no more IPv4 addresses as a nexthop remains in the FRR RIB. In this situation, among the routes that this particular interface nexthop: - remove from the zebra kernel routes - reinstall the routes that have been added from FRR. It is useful when the nexthop is for example a VRF interface. Add related test cases in the zebra_netlink topotest. Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
parent
667a4e92da
commit
c6b38684bd
@ -387,10 +387,14 @@ void connected_down(struct interface *ifp, struct connected *ifc)
|
||||
.ifindex = ifp->ifindex,
|
||||
.vrf_id = ifp->vrf->vrf_id,
|
||||
};
|
||||
struct zebra_vrf *zvrf;
|
||||
uint32_t count = 0;
|
||||
struct zebra_vrf *zvrf, *zvrf_iter;
|
||||
uint32_t count_ipv4 = 0;
|
||||
struct listnode *cnode;
|
||||
struct connected *c;
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct route_entry *re, *next;
|
||||
struct vrf *vrf;
|
||||
|
||||
zvrf = ifp->vrf->info;
|
||||
if (!zvrf) {
|
||||
@ -456,12 +460,14 @@ void connected_down(struct interface *ifp, struct connected *ifc)
|
||||
prefix_copy(&cp, CONNECTED_PREFIX(c));
|
||||
apply_mask(&cp);
|
||||
|
||||
if (prefix_same(&p, &cp) &&
|
||||
!CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN))
|
||||
count++;
|
||||
if (CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN))
|
||||
continue;
|
||||
|
||||
if (count >= 1)
|
||||
if (prefix_same(&p, &cp))
|
||||
return;
|
||||
|
||||
if (cp.family == AF_INET)
|
||||
count_ipv4++;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -474,6 +480,60 @@ void connected_down(struct interface *ifp, struct connected *ifc)
|
||||
rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
|
||||
0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
|
||||
|
||||
/* When the last IPv4 address of an interface is deleted, Linux removes
|
||||
* all routes using this interface without any Netlink advertisement.
|
||||
* The removed routes include those that only have this particular
|
||||
* interface as a nexthop. Among those, remove the kernel one from the
|
||||
* FRR RIB and reinstall the other that have been added from FRR.
|
||||
*/
|
||||
if (afi == AFI_IP && count_ipv4 == 0 && if_is_operative(ifp)) {
|
||||
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
|
||||
zvrf_iter = vrf->info;
|
||||
|
||||
if (!zvrf_iter)
|
||||
continue;
|
||||
|
||||
table = zvrf_iter->table[AFI_IP][SAFI_UNICAST];
|
||||
if (!table)
|
||||
continue;
|
||||
|
||||
for (rn = route_top(table); rn;
|
||||
rn = srcdest_route_next(rn)) {
|
||||
RNODE_FOREACH_RE_SAFE (rn, re, next) {
|
||||
if (CHECK_FLAG(re->status,
|
||||
ROUTE_ENTRY_REMOVED))
|
||||
continue;
|
||||
if (re->nhe->ifp != ifp)
|
||||
continue;
|
||||
if (re->type == ZEBRA_ROUTE_KERNEL)
|
||||
rib_delete(
|
||||
afi, SAFI_UNICAST,
|
||||
zvrf_iter->vrf->vrf_id,
|
||||
re->type, 0, re->flags,
|
||||
&rn->p, NULL, &nh, 0,
|
||||
zvrf_iter->table_id,
|
||||
re->metric,
|
||||
re->distance, false);
|
||||
else if (re->type !=
|
||||
ZEBRA_ROUTE_CONNECT) {
|
||||
SET_FLAG(re->status,
|
||||
ROUTE_ENTRY_CHANGED);
|
||||
UNSET_FLAG(
|
||||
re->status,
|
||||
ROUTE_ENTRY_INSTALLED);
|
||||
rib_add(afi, SAFI_UNICAST,
|
||||
zvrf_iter->vrf->vrf_id,
|
||||
re->type, 0, 0, &rn->p,
|
||||
NULL, &nh, re->nhe_id,
|
||||
zvrf_iter->table_id,
|
||||
re->metric, 0,
|
||||
re->distance, 0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Schedule LSP forwarding entries for processing, if appropriate. */
|
||||
if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
|
||||
if (IS_ZEBRA_DEBUG_MPLS)
|
||||
|
Loading…
Reference in New Issue
Block a user