diff options
Diffstat (limited to 'sharpd/sharp_zebra.c')
-rw-r--r-- | sharpd/sharp_zebra.c | 108 |
1 files changed, 83 insertions, 25 deletions
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index c095fec..133da91 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -251,8 +251,7 @@ static bool route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance, /* Only send via ID if nhgroup has been successfully installed */ if (nhgid && sharp_nhgroup_id_is_installed(nhgid)) { - SET_FLAG(api.message, ZAPI_MESSAGE_NHG); - api.nhgid = nhgid; + zapi_route_set_nhg_id(&api, &nhgid); } else { for (ALL_NEXTHOPS_PTR(nhg, nh)) { /* Check if we set a VNI label */ @@ -512,6 +511,7 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS) static void zebra_connected(struct zclient *zclient) { + zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST, zclient, true); zclient_send_reg_requests(zclient, VRF_DEFAULT); /* @@ -562,6 +562,12 @@ void nhg_add(uint32_t id, const struct nexthop_group *nhg, } if (api_nhg.nexthop_num == 0) { + if (sharp_nhgroup_id_is_installed(id)) { + zlog_debug("%s: nhg %u: no nexthops, deleting nexthop group", __func__, + id); + zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg); + return; + } zlog_debug("%s: nhg %u not sent: no valid nexthops", __func__, id); is_valid = false; @@ -666,27 +672,20 @@ static int sharp_debug_nexthops(struct zapi_route *api) return i; } -static int sharp_nexthop_update(ZAPI_CALLBACK_ARGS) + +static void sharp_nexthop_update(struct vrf *vrf, struct prefix *matched, + struct zapi_route *nhr) { struct sharp_nh_tracker *nht; - struct zapi_route nhr; - struct prefix matched; - - if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) { - zlog_err("%s: Decode of update failed", __func__); - return 0; - } zlog_debug("Received update for %pFX actual match: %pFX metric: %u", - &matched, &nhr.prefix, nhr.metric); + matched, &nhr->prefix, nhr->metric); - nht = sharp_nh_tracker_get(&matched); - nht->nhop_num = nhr.nexthop_num; + nht = sharp_nh_tracker_get(matched); + nht->nhop_num = nhr->nexthop_num; nht->updates++; - sharp_debug_nexthops(&nhr); - - return 0; + sharp_debug_nexthops(nhr); } static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS) @@ -705,10 +704,11 @@ static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS) return 0; } -void sharp_redistribute_vrf(struct vrf *vrf, int type) +void sharp_redistribute_vrf(struct vrf *vrf, int type, bool turn_on) { - zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, - 0, vrf->vrf_id); + zebra_redistribute_send(turn_on ? ZEBRA_REDISTRIBUTE_ADD + : ZEBRA_REDISTRIBUTE_DELETE, + zclient, AFI_IP, type, 0, vrf->vrf_id); } static zclient_handler *const sharp_opaque_handlers[] = { @@ -934,6 +934,7 @@ static int nhg_notify_owner(ZAPI_CALLBACK_ARGS) zlog_debug("Failed install of nhg %u", id); break; case ZAPI_NHG_REMOVED: + sharp_nhgroup_id_set_installed(id, false); zlog_debug("Removed nhg %u", id); break; case ZAPI_NHG_REMOVE_FAIL: @@ -989,6 +990,41 @@ static int sharp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS) return 0; } +static int sharp_zebra_process_neigh(ZAPI_CALLBACK_ARGS) +{ + union sockunion addr = {}, lladdr = {}; + struct zapi_neigh_ip api = {}; + struct interface *ifp; + + zlog_debug("Received a neighbor event"); + zclient_neigh_ip_decode(zclient->ibuf, &api); + + if (api.ip_in.ipa_type == AF_UNSPEC) + return 0; + + sockunion_family(&addr) = api.ip_in.ipa_type; + memcpy((uint8_t *)sockunion_get_addr(&addr), &api.ip_in.ip.addr, + family2addrsize(api.ip_in.ipa_type)); + + sockunion_family(&lladdr) = api.ip_out.ipa_type; + if (api.ip_out.ipa_type != AF_UNSPEC) + memcpy((uint8_t *)sockunion_get_addr(&lladdr), + &api.ip_out.ip.addr, + family2addrsize(api.ip_out.ipa_type)); + ifp = if_lookup_by_index(api.index, vrf_id); + if (!ifp) { + zlog_debug("Failed to lookup interface for neighbor entry: %u for %u", + api.index, vrf_id); + return 0; + } + + zlog_debug("Received: %s %pSU dev %s lladr %pSU", + (cmd == ZEBRA_NEIGH_ADDED) ? "NEW" : "DEL", &addr, ifp->name, + &lladdr); + + return 0; +} + int sharp_zebra_send_interface_protodown(struct interface *ifp, bool down) { zlog_debug("Sending zebra to set %s protodown %s", ifp->name, @@ -1059,11 +1095,16 @@ int sharp_zebra_send_tc_filter_rate(struct interface *ifp, return 0; } +void sharp_zebra_register_neigh(vrf_id_t vrf_id, afi_t afi, bool reg) +{ + zclient_register_neigh(zclient, vrf_id, afi, reg); +} + + static zclient_handler *const sharp_handlers[] = { [ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add, [ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete, [ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner, - [ZEBRA_NEXTHOP_UPDATE] = sharp_nexthop_update, [ZEBRA_NHG_NOTIFY_OWNER] = nhg_notify_owner, [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = sharp_redistribute_route, [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = sharp_redistribute_route, @@ -1071,19 +1112,36 @@ static zclient_handler *const sharp_handlers[] = { [ZEBRA_OPAQUE_NOTIFY] = sharp_opq_notify_handler, [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = sharp_zebra_process_srv6_locator_chunk, + [ZEBRA_NEIGH_ADDED] = sharp_zebra_process_neigh, + [ZEBRA_NEIGH_REMOVED] = sharp_zebra_process_neigh, }; void sharp_zebra_init(void) { - struct zclient_options opt = {.receive_notify = true}; + hook_register_prio(if_real, 0, sharp_ifp_create); + hook_register_prio(if_up, 0, sharp_ifp_up); + hook_register_prio(if_down, 0, sharp_ifp_down); + hook_register_prio(if_unreal, 0, sharp_ifp_destroy); - if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up, sharp_ifp_down, - sharp_ifp_destroy); - - zclient = zclient_new(master, &opt, sharp_handlers, + zclient = zclient_new(master, &zclient_options_default, sharp_handlers, array_size(sharp_handlers)); zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs); zclient->zebra_connected = zebra_connected; zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready; + zclient->nexthop_update = sharp_nexthop_update; +} + +void sharp_zebra_terminate(void) +{ + struct sharp_zclient *node = sharp_clients_head; + + while (node) { + sharp_zclient_delete(node->client->session_id); + + node = sharp_clients_head; + } + + zclient_stop(zclient); + zclient_free(zclient); } |