sharpd: add support for install/remove lsps

First round of support for exercising the lsp and ftn paths
using sharpd. This supports lsp-only, and binding to
ipv4 prefix. Also use the common lib nexthop-to-zapi
helper api instead of sharpd's open-coded version.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2020-02-07 16:50:01 -05:00
parent 0d60f61f18
commit c9e5adba73
4 changed files with 198 additions and 37 deletions

View file

@ -86,3 +86,20 @@ keyword. At present, no sharp commands will be preserved in the config.
Allow end user to dump associated data with the nexthop tracking that Allow end user to dump associated data with the nexthop tracking that
may have been turned on. may have been turned on.
.. index:: sharp lsp
.. clicmd:: sharp lsp (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]]
Install an LSP using the specified in-label, with nexthops as
listed in nexthop-group ``NAME``. The LSP is installed as type
ZEBRA_LSP_SHARP. If ``prefix`` is specified, an existing route with
type ``TYPE`` (and optional ``instance`` id) will be updated to use
the LSP.
.. index:: sharp remove lsp
.. clicmd:: sharp remove lsp (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]]
Remove a SHARPD LSP that uses the specified in-label, where the
nexthops are specified in nexthop-group ``NAME``. If ``prefix`` is
specified, remove label bindings from the route of type ``TYPE``
also.

View file

@ -337,11 +337,129 @@ DEFUN_NOSH (show_debugging_sharpd,
DEBUG_STR DEBUG_STR
"Sharp Information\n") "Sharp Information\n")
{ {
vty_out(vty, "Sharp debugging status\n"); vty_out(vty, "Sharp debugging status:\n");
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFPY(sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
"sharp lsp (0-100000)$inlabel\
nexthop-group NHGNAME$nhgname\
[prefix A.B.C.D/M$pfx\
" FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]",
"Sharp Routing Protocol\n"
"Add an LSP\n"
"The ingress label to use\n"
"Use nexthops from a nexthop-group\n"
"The nexthop-group name\n"
"Label a prefix\n"
"The v4 prefix to label\n"
FRR_IP_REDIST_HELP_STR_SHARPD
"Instance to use\n"
"Instance\n")
{
struct nexthop_group_cmd *nhgc = NULL;
struct prefix p = {};
int type = 0;
/* We're offered a v4 prefix */
if (pfx->family > 0 && type_str) {
p.family = pfx->family;
p.prefixlen = pfx->prefixlen;
p.u.prefix4 = pfx->prefix;
type = proto_redistnum(AFI_IP, type_str);
if (type < 0) {
vty_out(vty, "%% Unknown route type '%s'\n", type_str);
return CMD_WARNING;
}
} else if (pfx->family > 0 || type_str) {
vty_out(vty, "%% Must supply both prefix and type\n");
return CMD_WARNING;
}
nhgc = nhgc_find(nhgname);
if (!nhgc) {
vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
nhgname);
return CMD_WARNING;
}
if (nhgc->nhg.nexthop == NULL) {
vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
return CMD_WARNING;
}
if (sharp_install_lsps_helper(true, pfx->family > 0 ? &p : NULL,
type, instance, inlabel,
&(nhgc->nhg)) == 0)
return CMD_SUCCESS;
else {
vty_out(vty, "%% LSP install failed!\n");
return CMD_WARNING;
}
}
DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
"sharp remove lsp \
(0-100000)$inlabel\
nexthop-group NHGNAME$nhgname\
[prefix A.B.C.D/M$pfx\
" FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]",
"Sharp Routing Protocol\n"
"Remove data\n"
"Remove an LSP\n"
"The ingress label\n"
"Use nexthops from a nexthop-group\n"
"The nexthop-group name\n"
"Specify a v4 prefix\n"
"The v4 prefix to label\n"
FRR_IP_REDIST_HELP_STR_SHARPD
"Routing instance\n"
"Instance to use\n")
{
struct nexthop_group_cmd *nhgc = NULL;
struct prefix p = {};
int type = 0;
/* We're offered a v4 prefix */
if (pfx->family > 0 && type_str) {
p.family = pfx->family;
p.prefixlen = pfx->prefixlen;
p.u.prefix4 = pfx->prefix;
type = proto_redistnum(AFI_IP, type_str);
if (type < 0) {
vty_out(vty, "%% Unknown route type '%s'\n", type_str);
return CMD_WARNING;
}
} else if (pfx->family > 0 || type_str) {
vty_out(vty, "%% Must supply both prefix and type\n");
return CMD_WARNING;
}
nhgc = nhgc_find(nhgname);
if (!nhgc) {
vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
nhgname);
return CMD_WARNING;
}
if (nhgc->nhg.nexthop == NULL) {
vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
return CMD_WARNING;
}
if (sharp_install_lsps_helper(false, pfx->family > 0 ? &p : NULL,
type, instance, inlabel,
&(nhgc->nhg)) == 0)
return CMD_SUCCESS;
else {
vty_out(vty, "%% LSP remove failed!\n");
return CMD_WARNING;
}
}
void sharp_vty_init(void) void sharp_vty_init(void)
{ {
install_element(ENABLE_NODE, &install_routes_data_dump_cmd); install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
@ -351,6 +469,8 @@ void sharp_vty_init(void)
install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd); install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
install_element(ENABLE_NODE, &watch_nexthop_v6_cmd); install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
install_element(ENABLE_NODE, &watch_nexthop_v4_cmd); install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
install_element(VIEW_NODE, &show_debugging_sharpd_cmd); install_element(VIEW_NODE, &show_debugging_sharpd_cmd);

View file

@ -87,6 +87,61 @@ static int sharp_ifp_down(struct interface *ifp)
return 0; return 0;
} }
int sharp_install_lsps_helper(bool install_p, const struct prefix *p,
uint8_t type, int instance, uint32_t in_label,
const struct nexthop_group *nhg)
{
struct zapi_labels zl = {};
struct zapi_nexthop *znh;
const struct nexthop *nh;
int i, ret;
zl.type = ZEBRA_LSP_SHARP;
zl.local_label = in_label;
if (p) {
SET_FLAG(zl.message, ZAPI_LABELS_FTN);
prefix_copy(&zl.route.prefix, p);
zl.route.type = type;
zl.route.instance = instance;
}
i = 0;
for (ALL_NEXTHOPS_PTR(nhg, nh)) {
znh = &zl.nexthops[i];
/* Must have labels to be useful */
if (nh->nh_label == NULL || nh->nh_label->num_labels == 0)
continue;
if (nh->type == NEXTHOP_TYPE_IFINDEX ||
nh->type == NEXTHOP_TYPE_BLACKHOLE)
/* Hmm - can't really deal with these types */
continue;
ret = zapi_nexthop_from_nexthop(znh, nh);
if (ret < 0)
return -1;
i++;
}
/* Whoops - no nexthops isn't very useful */
if (i == 0)
return -1;
zl.nexthop_num = i;
if (install_p)
ret = zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_ADD,
&zl);
else
ret = zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE,
&zl);
return ret;
}
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, struct nexthop_group *nhg,
uint32_t routes) uint32_t routes)
@ -241,43 +296,8 @@ void route_add(struct prefix *p, vrf_id_t vrf_id,
for (ALL_NEXTHOPS_PTR(nhg, nh)) { for (ALL_NEXTHOPS_PTR(nhg, nh)) {
api_nh = &api.nexthops[i]; api_nh = &api.nexthops[i];
api_nh->vrf_id = nh->vrf_id;
api_nh->type = nh->type;
api_nh->weight = nh->weight;
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;
}
if (nh->nh_label && nh->nh_label->num_labels > 0) {
int j;
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
api_nh->label_num = nh->nh_label->num_labels;
for (j = 0; j < nh->nh_label->num_labels; j++)
api_nh->labels[j] = nh->nh_label->label[j];
}
zapi_nexthop_from_nexthop(api_nh, nh);
i++; i++;
} }
api.nexthop_num = i; api.nexthop_num = i;

View file

@ -37,4 +37,8 @@ extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
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);
int sharp_install_lsps_helper(bool install_p, const struct prefix *p,
uint8_t type, int instance, uint32_t in_label,
const struct nexthop_group *nhg);
#endif #endif