forked from Mirror/frr
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:
parent
0d60f61f18
commit
c9e5adba73
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue