sharpd: support backup nexthops

Add cli and zapi support for backup nexthops for sharpd routes.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2019-11-15 16:33:34 -05:00
parent 0a8881b4b5
commit 1df3b1dc65
5 changed files with 92 additions and 11 deletions

View File

@ -1500,6 +1500,7 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
znh->type = nh->type; znh->type = nh->type;
znh->vrf_id = nh->vrf_id; znh->vrf_id = nh->vrf_id;
znh->weight = nh->weight;
znh->ifindex = nh->ifindex; znh->ifindex = nh->ifindex;
znh->gate = nh->gate; znh->gate = nh->gate;

View File

@ -28,9 +28,11 @@ struct sharp_routes {
/* The original prefix for route installation */ /* The original prefix for route installation */
struct prefix orig_prefix; struct prefix orig_prefix;
/* The nexthop group we are using for installation */ /* The nexthop info we are using for installation */
struct nexthop nhop; struct nexthop nhop;
struct nexthop backup_nhop;
struct nexthop_group nhop_group; struct nexthop_group nhop_group;
struct nexthop_group backup_nhop_group;
uint32_t total_routes; uint32_t total_routes;
uint32_t installed_routes; uint32_t installed_routes;

View File

@ -162,7 +162,12 @@ DEFPY (install_routes_data_dump,
DEFPY (install_routes, DEFPY (install_routes,
install_routes_cmd, install_routes_cmd,
"sharp install routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NHGNAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]", "sharp install routes [vrf NAME$vrf_name]\
<A.B.C.D$start4|X:X::X:X$start6>\
<nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|\
nexthop-group NHGNAME$nexthop_group>\
[backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
(1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n" "Sharp routing Protocol\n"
"install some routes\n" "install some routes\n"
"Routes to install\n" "Routes to install\n"
@ -175,6 +180,9 @@ DEFPY (install_routes,
"V6 Nexthop address to use\n" "V6 Nexthop address to use\n"
"Nexthop-Group to use\n" "Nexthop-Group to use\n"
"The Name of the nexthop-group\n" "The Name of the nexthop-group\n"
"Backup nexthop to use(Can be an IPv4 or IPv6 address)\n"
"Backup V4 Nexthop address to use\n"
"Backup V6 Nexthop address to use\n"
"How many to create\n" "How many to create\n"
"Instance to use\n" "Instance to use\n"
"Instance\n" "Instance\n"
@ -197,6 +205,8 @@ DEFPY (install_routes,
memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix)); memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
memset(&sg.r.nhop, 0, sizeof(sg.r.nhop)); memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group)); memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
if (start4.s_addr != 0) { if (start4.s_addr != 0) {
prefix.family = AF_INET; prefix.family = AF_INET;
@ -219,6 +229,12 @@ DEFPY (install_routes,
return CMD_WARNING; return CMD_WARNING;
} }
/* Explicit backup not available with named nexthop-group */
if (backup && nexthop_group) {
vty_out(vty, "%% Invalid: cannot specify both nexthop-group and backup\n");
return CMD_WARNING;
}
if (nexthop_group) { if (nexthop_group) {
struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group); struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
if (!nhgc) { if (!nhgc) {
@ -229,6 +245,22 @@ DEFPY (install_routes,
} }
sg.r.nhop_group.nexthop = nhgc->nhg.nexthop; sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
/* Use group's backup nexthop info if present */
if (nhgc->backup_list_name[0]) {
struct nexthop_group_cmd *bnhgc =
nhgc_find(nhgc->backup_list_name);
if (!bnhgc) {
vty_out(vty, "%% Backup group %s not found for group %s\n",
nhgc->backup_list_name,
nhgc->name);
return CMD_WARNING;
}
sg.r.backup_nhop.vrf_id = vrf->vrf_id;
sg.r.backup_nhop_group.nexthop = bnhgc->nhg.nexthop;
}
} else { } else {
if (nexthop4.s_addr != INADDR_ANY) { if (nexthop4.s_addr != INADDR_ANY) {
sg.r.nhop.gate.ipv4 = nexthop4; sg.r.nhop.gate.ipv4 = nexthop4;
@ -242,11 +274,30 @@ DEFPY (install_routes,
sg.r.nhop_group.nexthop = &sg.r.nhop; sg.r.nhop_group.nexthop = &sg.r.nhop;
} }
/* Use single backup nexthop if specified */
if (backup) {
/* Set flag and index in primary nexthop */
SET_FLAG(sg.r.nhop.flags, NEXTHOP_FLAG_HAS_BACKUP);
sg.r.nhop.backup_idx = 0;
if (backup_nexthop4.s_addr != INADDR_ANY) {
sg.r.backup_nhop.gate.ipv4 = backup_nexthop4;
sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV4;
} else {
sg.r.backup_nhop.gate.ipv6 = backup_nexthop6;
sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV6;
}
sg.r.backup_nhop.vrf_id = vrf->vrf_id;
sg.r.backup_nhop_group.nexthop = &sg.r.backup_nhop;
}
sg.r.inst = instance; sg.r.inst = instance;
sg.r.vrf_id = vrf->vrf_id; sg.r.vrf_id = vrf->vrf_id;
rts = routes; rts = routes;
sharp_install_routes_helper(&prefix, sg.r.vrf_id, sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst,
sg.r.inst, &sg.r.nhop_group, rts); &sg.r.nhop_group, &sg.r.backup_nhop_group,
rts);
return CMD_SUCCESS; return CMD_SUCCESS;
} }

View File

@ -143,7 +143,9 @@ int sharp_install_lsps_helper(bool install_p, const struct prefix *p,
} }
void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
uint8_t instance, struct nexthop_group *nhg, uint8_t instance,
const struct nexthop_group *nhg,
const struct nexthop_group *backup_nhg,
uint32_t routes) uint32_t routes)
{ {
uint32_t temp, i; uint32_t temp, i;
@ -157,9 +159,13 @@ void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
} else } else
temp = ntohl(p->u.val32[3]); 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); monotime(&sg.r.t_start);
for (i = 0; i < routes; i++) { for (i = 0; i < routes; i++) {
route_add(p, vrf_id, (uint8_t)instance, nhg); route_add(p, vrf_id, (uint8_t)instance, nhg, backup_nhg);
if (v4) if (v4)
p->u.prefix4.s_addr = htonl(++temp); p->u.prefix4.s_addr = htonl(++temp);
else else
@ -209,6 +215,7 @@ static void handle_repeated(bool installed)
sg.r.installed_routes = 0; sg.r.installed_routes = 0;
sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst, sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
&sg.r.nhop_group, &sg.r.nhop_group,
&sg.r.backup_nhop_group,
sg.r.total_routes); sg.r.total_routes);
} }
} }
@ -276,8 +283,9 @@ 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); zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
} }
void route_add(struct prefix *p, vrf_id_t vrf_id, void route_add(const struct prefix *p, vrf_id_t vrf_id,
uint8_t instance, struct nexthop_group *nhg) uint8_t instance, const struct nexthop_group *nhg,
const struct nexthop_group *backup_nhg)
{ {
struct zapi_route api; struct zapi_route api;
struct zapi_nexthop *api_nh; struct zapi_nexthop *api_nh;
@ -298,10 +306,27 @@ void route_add(struct prefix *p, vrf_id_t vrf_id,
api_nh = &api.nexthops[i]; api_nh = &api.nexthops[i];
zapi_nexthop_from_nexthop(api_nh, nh); zapi_nexthop_from_nexthop(api_nh, nh);
i++; i++;
} }
api.nexthop_num = 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); zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
} }

View File

@ -25,15 +25,17 @@
extern void sharp_zebra_init(void); extern void sharp_zebra_init(void);
extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label); extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
extern void route_add(struct prefix *p, vrf_id_t, uint8_t instance, extern void route_add(const struct prefix *p, vrf_id_t, uint8_t instance,
struct nexthop_group *nhg); const struct nexthop_group *nhg,
const struct nexthop_group *backup_nhg);
extern void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance); extern void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance);
extern void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, extern void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id,
bool import, bool watch, bool connected); bool import, bool watch, bool connected);
extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
uint8_t instance, uint8_t instance,
struct nexthop_group *nhg, const struct nexthop_group *nhg,
const struct nexthop_group *backup_nhg,
uint32_t routes); uint32_t routes);
extern void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id, extern void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
uint8_t instance, uint32_t routes); uint8_t instance, uint32_t routes);