diff options
Diffstat (limited to 'sharpd/sharp_zebra.c')
| -rw-r--r-- | sharpd/sharp_zebra.c | 140 |
1 files changed, 127 insertions, 13 deletions
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 286f320874..c9f333e34b 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -34,6 +34,7 @@ #include "plist.h" #include "log.h" #include "nexthop.h" +#include "nexthop_group.h" #include "sharp_zebra.h" @@ -128,13 +129,89 @@ static int interface_state_down(int command, struct zclient *zclient, return 0; } +static struct timeval t_start; +static struct timeval t_end; extern uint32_t total_routes; extern uint32_t installed_routes; extern uint32_t removed_routes; +extern int32_t repeat; +extern struct prefix orig_prefix; +extern struct nexthop_group nhop_group; +extern uint8_t inst; + +void sharp_install_routes_helper(struct prefix *p, uint8_t instance, + struct nexthop_group *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]); + + monotime(&t_start); + for (i = 0; i < routes; i++) { + route_add(p, (uint8_t)instance, nhg); + if (v4) + p->u.prefix4.s_addr = htonl(++temp); + else + p->u.val32[3] = htonl(++temp); + } +} + +void sharp_remove_routes_helper(struct prefix *p, 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(&t_start); + for (i = 0; i < routes; i++) { + route_delete(p, (uint8_t)instance); + if (v4) + p->u.prefix4.s_addr = htonl(++temp); + else + p->u.val32[3] = htonl(++temp); + } +} + +static void handle_repeated(bool installed) +{ + struct prefix p = orig_prefix; + repeat--; + + if (repeat <= 0) + return; + + if (installed) { + removed_routes = 0; + sharp_remove_routes_helper(&p, inst, total_routes); + } + + if (!installed) { + installed_routes = 0; + sharp_install_routes_helper(&p, inst, &nhop_group, + total_routes); + } +} static int route_notify_owner(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { + struct timeval r; struct prefix p; enum zapi_route_notify_owner note; uint32_t table; @@ -145,8 +222,13 @@ static int route_notify_owner(int command, struct zclient *zclient, switch (note) { case ZAPI_ROUTE_INSTALLED: installed_routes++; - if (total_routes == installed_routes) - zlog_debug("Installed All Items"); + if (total_routes == installed_routes) { + monotime(&t_end); + timersub(&t_end, &t_start, &r); + zlog_debug("Installed All Items %ld.%ld", r.tv_sec, + r.tv_usec); + handle_repeated(true); + } break; case ZAPI_ROUTE_FAIL_INSTALL: zlog_debug("Failed install of route"); @@ -156,8 +238,13 @@ static int route_notify_owner(int command, struct zclient *zclient, break; case ZAPI_ROUTE_REMOVED: removed_routes++; - if (total_routes == removed_routes) - zlog_debug("Removed all Items"); + if (total_routes == removed_routes) { + monotime(&t_end); + timersub(&t_end, &t_start, &r); + zlog_debug("Removed all Items %ld.%ld", r.tv_sec, + r.tv_usec); + handle_repeated(false); + } break; case ZAPI_ROUTE_REMOVE_FAIL: zlog_debug("Route removal Failure"); @@ -176,10 +263,12 @@ void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label) zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP); } -void route_add(struct prefix *p, uint8_t instance, struct nexthop *nh) +void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *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_DEFAULT; @@ -191,12 +280,35 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop *nh) SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api_nh = &api.nexthops[0]; - api_nh->vrf_id = VRF_DEFAULT; - api_nh->gate = nh->gate; - api_nh->type = nh->type; - api_nh->ifindex = nh->ifindex; - api.nexthop_num = 1; + for (ALL_NEXTHOPS_PTR(nhg, nh)) { + api_nh = &api.nexthops[i]; + api_nh->vrf_id = VRF_DEFAULT; + api_nh->type = nh->type; + switch (nh->type) { + case NEXTHOP_TYPE_IPV4: + api_nh->gate = nh->gate; + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + api_nh->gate = nh->gate; + api_nh->ifindex = nh->ifindex; + break; + case NEXTHOP_TYPE_IFINDEX: + api_nh->ifindex = nh->ifindex; + break; + case NEXTHOP_TYPE_IPV6: + memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + api_nh->ifindex = nh->ifindex; + memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16); + break; + case NEXTHOP_TYPE_BLACKHOLE: + api_nh->bh_type = nh->bh_type; + break; + } + i++; + } + api.nexthop_num = i; zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } @@ -223,7 +335,9 @@ void sharp_zebra_nexthop_watch(struct prefix *p, bool watch) if (!watch) command = ZEBRA_NEXTHOP_UNREGISTER; - zclient_send_rnh(zclient, command, p, true, VRF_DEFAULT); + if (zclient_send_rnh(zclient, command, p, true, VRF_DEFAULT) < 0) + zlog_warn("%s: Failure to send nexthop to zebra", + __PRETTY_FUNCTION__); } static int sharp_nexthop_update(int command, struct zclient *zclient, @@ -281,7 +395,7 @@ void sharp_zebra_init(void) { struct zclient_options opt = {.receive_notify = true}; - zclient = zclient_new_notify(master, &opt); + zclient = zclient_new(master, &opt); zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs); zclient->zebra_connected = zebra_connected; |
