.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) {
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++;
}
/*
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)