diff options
Diffstat (limited to 'staticd/static_zebra.c')
| -rw-r--r-- | staticd/static_zebra.c | 189 |
1 files changed, 87 insertions, 102 deletions
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index af153b4bc3..de07ad8ef3 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -57,6 +57,7 @@ struct static_nht_data { uint32_t refcount; uint8_t nh_num; + bool registered; }; static int static_nht_data_cmp(const struct static_nht_data *nhtd1, @@ -87,7 +88,7 @@ static struct static_nht_hash_head static_nht_hash[1]; struct zclient *zclient; uint32_t zebra_ecmp_count = MULTIPATH_NUM; -/* Inteface addition message from zebra. */ +/* Interface addition message from zebra. */ static int static_ifp_create(struct interface *ifp) { static_ifindex_update(ifp, true); @@ -175,9 +176,12 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS) return 0; } + static void zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); + + static_fixup_vrf_ids(vrf_info_lookup(VRF_DEFAULT)); } /* API to check whether the configured nexthop address is @@ -262,8 +266,12 @@ static_nht_hash_getref(const struct static_nht_data *ref) return nhtd; } -static bool static_nht_hash_decref(struct static_nht_data *nhtd) +static bool static_nht_hash_decref(struct static_nht_data **nhtd_p) { + struct static_nht_data *nhtd = *nhtd_p; + + *nhtd_p = NULL; + if (--nhtd->refcount > 0) return true; @@ -280,133 +288,110 @@ static void static_nht_hash_clear(void) XFREE(MTYPE_STATIC_NHT_DATA, nhtd); } -void static_zebra_nht_register(struct static_nexthop *nh, bool reg) +static bool static_zebra_nht_get_prefix(const struct static_nexthop *nh, + struct prefix *p) { - struct static_path *pn = nh->pn; - struct route_node *rn = pn->rn; - struct static_route_info *si = static_route_info_from_rnode(rn); - struct static_nht_data lookup; - uint32_t cmd; - struct prefix p; - afi_t afi = AFI_IP; - - cmd = (reg) ? - ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER; - - if (nh->nh_registered && reg) - return; - - if (!nh->nh_registered && !reg) - return; - - memset(&p, 0, sizeof(p)); switch (nh->type) { case STATIC_IFNAME: case STATIC_BLACKHOLE: - return; + p->family = AF_UNSPEC; + return false; + case STATIC_IPV4_GATEWAY: case STATIC_IPV4_GATEWAY_IFNAME: - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = nh->addr.ipv4; - afi = AFI_IP; - break; + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4 = nh->addr.ipv4; + return true; + case STATIC_IPV6_GATEWAY: case STATIC_IPV6_GATEWAY_IFNAME: - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = nh->addr.ipv6; - afi = AFI_IP6; - break; + p->family = AF_INET6; + p->prefixlen = IPV6_MAX_BITLEN; + p->u.prefix6 = nh->addr.ipv6; + return true; } - memset(&lookup, 0, sizeof(lookup)); - lookup.nh = p; + assertf(0, "BUG: someone forgot to add nexthop type %u", nh->type); +} + +void static_zebra_nht_register(struct static_nexthop *nh, bool reg) +{ + struct static_path *pn = nh->pn; + struct route_node *rn = pn->rn; + struct static_route_info *si = static_route_info_from_rnode(rn); + struct static_nht_data *nhtd, lookup = {}; + uint32_t cmd; + + if (!static_zebra_nht_get_prefix(nh, &lookup.nh)) + return; lookup.nh_vrf_id = nh->nh_vrf_id; lookup.safi = si->safi; - nh->nh_registered = reg; - - if (reg) { - struct static_nht_data *nhtd; + if (nh->nh_registered) { + /* nh->nh_registered means we own a reference on the nhtd */ + nhtd = static_nht_hash_find(static_nht_hash, &lookup); + assertf(nhtd, "BUG: NH %pFX registered but not in hashtable", + &lookup.nh); + } else if (reg) { nhtd = static_nht_hash_getref(&lookup); - if (nhtd->refcount > 1) { + if (nhtd->refcount > 1) DEBUGD(&static_dbg_route, - "Already registered nexthop(%pFX) for %pRN %d", - &p, rn, nhtd->nh_num); - if (nhtd->nh_num) - static_nht_update(&rn->p, &nhtd->nh, - nhtd->nh_num, afi, si->safi, - nh->nh_vrf_id); - return; - } + "Reusing registered nexthop(%pFX) for %pRN %d", + &lookup.nh, rn, nhtd->nh_num); } else { - struct static_nht_data *nhtd; + /* !reg && !nh->nh_registered */ + zlog_warn("trying to unregister nexthop %pFX twice", + &lookup.nh); + return; + } - nhtd = static_nht_hash_find(static_nht_hash, &lookup); - if (!nhtd) + nh->nh_registered = reg; + + if (reg) { + if (nhtd->nh_num) { + /* refresh with existing data */ + afi_t afi = prefix_afi(&lookup.nh); + + if (nh->state == STATIC_NOT_INSTALLED) + nh->state = STATIC_START; + static_nht_update(&rn->p, &nhtd->nh, nhtd->nh_num, afi, + si->safi, nh->nh_vrf_id); return; - if (static_nht_hash_decref(nhtd)) + } + + if (nhtd->registered) + /* have no data, but did send register */ return; - } - DEBUGD(&static_dbg_route, "%s nexthop(%pFX) for %pRN", - reg ? "Registering" : "Unregistering", &p, rn); + cmd = ZEBRA_NEXTHOP_REGISTER; + DEBUGD(&static_dbg_route, "Registering nexthop(%pFX) for %pRN", + &lookup.nh, rn); + } else { + bool was_zebra_registered; - if (zclient_send_rnh(zclient, cmd, &p, si->safi, false, false, - nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE) - zlog_warn("%s: Failure to send nexthop to zebra", __func__); -} -/* - * When nexthop gets updated via configuration then use the - * already registered NH and resend the route to zebra - */ -int static_zebra_nh_update(struct static_nexthop *nh) -{ - struct static_path *pn = nh->pn; - struct route_node *rn = pn->rn; - struct static_route_info *si = static_route_info_from_rnode(rn); - struct static_nht_data *nhtd, lookup = {}; - struct prefix p = {}; - afi_t afi = AFI_IP; + was_zebra_registered = nhtd->registered; + if (static_nht_hash_decref(&nhtd)) + /* still got references alive */ + return; - if (!nh->nh_registered) - return 0; + /* NB: nhtd is now NULL. */ + if (!was_zebra_registered) + return; - switch (nh->type) { - case STATIC_IFNAME: - case STATIC_BLACKHOLE: - return 0; - case STATIC_IPV4_GATEWAY: - case STATIC_IPV4_GATEWAY_IFNAME: - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = nh->addr.ipv4; - afi = AFI_IP; - break; - case STATIC_IPV6_GATEWAY: - case STATIC_IPV6_GATEWAY_IFNAME: - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = nh->addr.ipv6; - afi = AFI_IP6; - break; + cmd = ZEBRA_NEXTHOP_UNREGISTER; + DEBUGD(&static_dbg_route, + "Unregistering nexthop(%pFX) for %pRN", &lookup.nh, rn); } - lookup.nh = p; - lookup.nh_vrf_id = nh->nh_vrf_id; - lookup.safi = si->safi; - - nhtd = static_nht_hash_find(static_nht_hash, &lookup); - if (nhtd && nhtd->nh_num) { - nh->state = STATIC_START; - static_nht_update(&rn->p, &nhtd->nh, nhtd->nh_num, afi, - si->safi, nh->nh_vrf_id); - return 1; - } - return 0; + if (zclient_send_rnh(zclient, cmd, &lookup.nh, si->safi, false, false, + nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE) + zlog_warn("%s: Failure to send nexthop %pFX for %pRN to zebra", + __func__, &lookup.nh, rn); + else if (reg) + nhtd->registered = true; } extern void static_zebra_route_add(struct static_path *pn, bool install) |
