diff options
Diffstat (limited to 'sharpd/sharp_zebra.c')
| -rw-r--r-- | sharpd/sharp_zebra.c | 290 |
1 files changed, 195 insertions, 95 deletions
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 231de6403d..627caea37d 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -211,66 +211,217 @@ int sharp_install_lsps_helper(bool install_p, bool update_p, cmd = ZEBRA_MPLS_LABELS_DELETE; } - ret = zebra_send_mpls_labels(zclient, cmd, &zl); + if (zebra_send_mpls_labels(zclient, cmd, &zl) == ZCLIENT_SEND_FAILURE) + return -1; - return ret; + return 0; } -void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, - uint8_t instance, uint32_t nhgid, - const struct nexthop_group *nhg, - const struct nexthop_group *backup_nhg, - uint32_t routes) +enum where_to_restart { + SHARP_INSTALL_ROUTES_RESTART, + SHARP_DELETE_ROUTES_RESTART, +}; + +struct buffer_delay { + struct prefix p; + uint32_t count; + uint32_t routes; + vrf_id_t vrf_id; + uint8_t instance; + uint32_t nhgid; + const struct nexthop_group *nhg; + const struct nexthop_group *backup_nhg; + enum where_to_restart restart; +} wb; + +/* + * route_add - Encodes a route to zebra + * + * This function returns true when the route was buffered + * by the underlying stream system + */ +static bool route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance, + uint32_t nhgid, const struct nexthop_group *nhg, + const struct nexthop_group *backup_nhg) +{ + struct zapi_route api; + struct zapi_nexthop *api_nh; + struct nexthop *nh; + int i = 0; + + memset(&api, 0, sizeof(api)); + api.vrf_id = vrf_id; + api.type = ZEBRA_ROUTE_SHARP; + api.instance = instance; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); + + SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + + /* 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; + } else { + for (ALL_NEXTHOPS_PTR(nhg, nh)) { + api_nh = &api.nexthops[i]; + + zapi_nexthop_from_nexthop(api_nh, nh); + + i++; + } + api.nexthop_num = i; + } + + /* Include backup nexthops, if present */ + if (backup_nhg && backup_nhg->nexthop) { + SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS); + + i = 0; + for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) { + api_nh = &api.backup_nexthops[i]; + + zapi_backup_nexthop_from_nexthop(api_nh, nh); + + i++; + } + + api.backup_nexthop_num = i; + } + + if (zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api) + == ZCLIENT_SEND_BUFFERED) + return true; + else + return false; +} + +/* + * route_delete - Encodes a route for deletion to zebra + * + * This function returns true when the route sent was + * buffered by the underlying stream system. + */ +static bool route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance) +{ + struct zapi_route api; + + memset(&api, 0, sizeof(api)); + api.vrf_id = vrf_id; + api.type = ZEBRA_ROUTE_SHARP; + api.safi = SAFI_UNICAST; + api.instance = instance; + memcpy(&api.prefix, p, sizeof(*p)); + + if (zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api) + == ZCLIENT_SEND_BUFFERED) + return true; + else + return false; +} + +static void sharp_install_routes_restart(struct prefix *p, uint32_t count, + vrf_id_t vrf_id, uint8_t instance, + uint32_t nhgid, + const struct nexthop_group *nhg, + const struct nexthop_group *backup_nhg, + uint32_t routes) { uint32_t temp, i; bool v4 = false; - zlog_debug("Inserting %u routes", routes); - if (p->family == AF_INET) { v4 = true; temp = ntohl(p->u.prefix4.s_addr); } else temp = ntohl(p->u.val32[3]); - /* Only use backup route/nexthops if present */ - if (backup_nhg && (backup_nhg->nexthop == NULL)) - backup_nhg = NULL; - - monotime(&sg.r.t_start); - for (i = 0; i < routes; i++) { - route_add(p, vrf_id, (uint8_t)instance, nhgid, nhg, backup_nhg); + for (i = count; i < routes; i++) { + bool buffered = route_add(p, vrf_id, (uint8_t)instance, nhgid, + nhg, backup_nhg); if (v4) p->u.prefix4.s_addr = htonl(++temp); else p->u.val32[3] = htonl(++temp); + + if (buffered) { + wb.p = *p; + wb.count = i+1; + wb.routes = routes; + wb.vrf_id = vrf_id; + wb.instance = instance; + wb.nhgid = nhgid; + wb.nhg = nhg; + wb.backup_nhg = backup_nhg; + wb.restart = SHARP_INSTALL_ROUTES_RESTART; + + return; + } } } -void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id, - uint8_t instance, uint32_t routes) +void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, uint32_t nhgid, + const struct nexthop_group *nhg, + const struct nexthop_group *backup_nhg, + uint32_t routes) +{ + zlog_debug("Inserting %u routes", routes); + + /* Only use backup route/nexthops if present */ + if (backup_nhg && (backup_nhg->nexthop == NULL)) + backup_nhg = NULL; + + monotime(&sg.r.t_start); + sharp_install_routes_restart(p, 0, vrf_id, instance, nhgid, nhg, + backup_nhg, routes); +} + +static void sharp_remove_routes_restart(struct prefix *p, uint32_t count, + vrf_id_t vrf_id, uint8_t instance, + uint32_t routes) { uint32_t temp, i; bool v4 = false; - zlog_debug("Removing %u routes", routes); - if (p->family == AF_INET) { v4 = true; temp = ntohl(p->u.prefix4.s_addr); } else temp = ntohl(p->u.val32[3]); - monotime(&sg.r.t_start); - for (i = 0; i < routes; i++) { - route_delete(p, vrf_id, (uint8_t)instance); + for (i = count; i < routes; i++) { + bool buffered = route_delete(p, vrf_id, (uint8_t)instance); + if (v4) p->u.prefix4.s_addr = htonl(++temp); else p->u.val32[3] = htonl(++temp); + + if (buffered) { + wb.p = *p; + wb.count = i + 1; + wb.vrf_id = vrf_id; + wb.instance = instance; + wb.routes = routes; + wb.restart = SHARP_DELETE_ROUTES_RESTART; + + return; + } } } +void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, uint32_t routes) +{ + zlog_debug("Removing %u routes", routes); + + monotime(&sg.r.t_start); + + sharp_remove_routes_restart(p, 0, vrf_id, instance, routes); +} + static void handle_repeated(bool installed) { struct prefix p = sg.r.orig_prefix; @@ -294,6 +445,21 @@ static void handle_repeated(bool installed) } } +static void sharp_zclient_buffer_ready(void) +{ + switch (wb.restart) { + case SHARP_INSTALL_ROUTES_RESTART: + sharp_install_routes_restart(&wb.p, wb.count, wb.vrf_id, + wb.instance, wb.nhgid, wb.nhg, + wb.backup_nhg, wb.routes); + return; + case SHARP_DELETE_ROUTES_RESTART: + sharp_remove_routes_restart(&wb.p, wb.count, wb.vrf_id, + wb.instance, wb.routes); + return; + } +} + static int route_notify_owner(ZAPI_CALLBACK_ARGS) { struct timeval r; @@ -301,7 +467,8 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS) enum zapi_route_notify_owner note; uint32_t table; - if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e)) + if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e, + NULL, NULL)) return -1; switch (note) { @@ -407,74 +574,6 @@ void nhg_del(uint32_t id) zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg); } -void route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance, - uint32_t nhgid, const struct nexthop_group *nhg, - const struct nexthop_group *backup_nhg) -{ - struct zapi_route api; - struct zapi_nexthop *api_nh; - struct nexthop *nh; - int i = 0; - - memset(&api, 0, sizeof(api)); - api.vrf_id = vrf_id; - api.type = ZEBRA_ROUTE_SHARP; - api.instance = instance; - api.safi = SAFI_UNICAST; - memcpy(&api.prefix, p, sizeof(*p)); - - SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - - /* 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; - } else { - for (ALL_NEXTHOPS_PTR(nhg, nh)) { - api_nh = &api.nexthops[i]; - - zapi_nexthop_from_nexthop(api_nh, nh); - - i++; - } - api.nexthop_num = i; - } - - /* Include backup nexthops, if present */ - if (backup_nhg && backup_nhg->nexthop) { - SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS); - - i = 0; - for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) { - api_nh = &api.backup_nexthops[i]; - - zapi_backup_nexthop_from_nexthop(api_nh, nh); - - i++; - } - - api.backup_nexthop_num = i; - } - - zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); -} - -void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance) -{ - struct zapi_route api; - - memset(&api, 0, sizeof(api)); - api.vrf_id = vrf_id; - api.type = ZEBRA_ROUTE_SHARP; - api.safi = SAFI_UNICAST; - api.instance = instance; - memcpy(&api.prefix, p, sizeof(*p)); - zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); - - return; -} - void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, bool watch, bool connected) { @@ -492,7 +591,8 @@ void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, command = ZEBRA_IMPORT_ROUTE_UNREGISTER; } - if (zclient_send_rnh(zclient, command, p, connected, vrf_id) < 0) + if (zclient_send_rnh(zclient, command, p, connected, vrf_id) + == ZCLIENT_SEND_FAILURE) zlog_warn("%s: Failure to send nexthop to zebra", __func__); } @@ -678,7 +778,7 @@ void sharp_opaque_send(uint32_t type, uint32_t proto, uint32_t instance, ret = zclient_send_opaque_unicast(zclient, type, proto, instance, session_id, buf, sizeof(buf)); - if (ret < 0) { + if (ret == ZCLIENT_SEND_FAILURE) { zlog_debug("%s: send_opaque() failed => %d", __func__, ret); break; @@ -767,7 +867,7 @@ void sharp_zebra_init(void) zclient->nexthop_update = sharp_nexthop_update; zclient->import_check_update = sharp_nexthop_update; zclient->nhg_notify_owner = nhg_notify_owner; - + zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready; zclient->redistribute_route_add = sharp_redistribute_route; zclient->redistribute_route_del = sharp_redistribute_route; zclient->opaque_msg_handler = sharp_opaque_handler; |
