From 30eee3c450937a9bc2fd02527cff266f85a818ed Mon Sep 17 00:00:00 2001 From: Taras Pudiak Date: Tue, 31 Jan 2023 18:18:44 +0200 Subject: [PATCH] zebra: Allow one connected route per network mask on a interface Backport of 92980561382fc04380414a6e2f6ca6746c2fe5e9 from FRR repository --- zebra/connected.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/zebra/connected.c b/zebra/connected.c index 8c4ba163b..bc5941657 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -207,6 +207,9 @@ void connected_up(struct interface *ifp, struct connected *ifc) }; struct zebra_vrf *zvrf; uint32_t metric; + uint32_t count = 0; + struct listnode *cnode; + struct connected *c; zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); if (!zvrf) { @@ -251,6 +254,28 @@ void connected_up(struct interface *ifp, struct connected *ifc) metric = (ifc->metric < (uint32_t)METRIC_MAX) ? ifc->metric : ifp->metric; + + /* + * It's possible to add the same network and mask + * to an interface over and over. This would + * result in an equivalent number of connected + * routes. Just add one connected route in + * for all the addresses on an interface that + * resolve to the same network and mask + */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + struct prefix cp; + + PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); + apply_mask(&cp); + + if (prefix_same(&cp, &p)) + count++; + + if (count >= 2) + return; + } + rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0); @@ -350,6 +375,9 @@ void connected_down(struct interface *ifp, struct connected *ifc) .vrf_id = ifp->vrf_id, }; struct zebra_vrf *zvrf; + uint32_t count = 0; + struct listnode *cnode; + struct connected *c; zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); if (!zvrf) { @@ -388,6 +416,26 @@ void connected_down(struct interface *ifp, struct connected *ifc) break; } + /* + * It's possible to have X number of addresses + * on a interface that all resolve to the same + * network and mask. Find them and just + * allow the deletion when are removing the last + * one. + */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + struct prefix cp; + + PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); + apply_mask(&cp); + + if (prefix_same(&p, &cp)) + count++; + + if (count >= 2) + return; + } + /* * Same logic as for connected_up(): push the changes into the * head. -- 2.37.2