summaryrefslogtreecommitdiff
path: root/sharpd/sharp_zebra.c
diff options
context:
space:
mode:
Diffstat (limited to 'sharpd/sharp_zebra.c')
-rw-r--r--sharpd/sharp_zebra.c140
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;