diff --git a/zebra/connected.c b/zebra/connected.c index c885c533e6..70c78060a9 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -209,6 +209,9 @@ void connected_up(struct interface *ifp, struct connected *ifc) struct zebra_vrf *zvrf; uint32_t metric; uint32_t flags = 0; + uint32_t count = 0; + struct listnode *cnode; + struct connected *c; zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); if (!zvrf) { @@ -251,6 +254,27 @@ void connected_up(struct interface *ifp, struct connected *ifc) break; } + /* + * 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; + } + metric = (ifc->metric < (uint32_t)METRIC_MAX) ? ifc->metric : ifp->metric; @@ -359,6 +383,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) { @@ -397,6 +424,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.