lib, zebra: enhance the MPLS zapi messages

* Add ability to specify the nexthop type;
* Add ability to install or not a FTN (in addition to an LSP).

These two additions will be useful to install local SR Prefix-SIDs
configured with the no-PHP option.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2019-08-08 15:51:05 -03:00
parent 635a039eef
commit b3c49d0e77
5 changed files with 145 additions and 95 deletions

View file

@ -121,25 +121,48 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
(cmd == ZEBRA_MPLS_LABELS_ADD) ? "add" : "delete");
zl.type = ZEBRA_LSP_LDP;
zl.prefix.family = kr->af;
zl.prefix.prefixlen = kr->prefixlen;
zl.local_label = kr->local_label;
/* Set prefix. */
SET_FLAG(zl.message, ZAPI_LABELS_FTN);
zl.route.prefix.family = kr->af;
switch (kr->af) {
case AF_INET:
zl.prefix.u.prefix4 = kr->prefix.v4;
zl.nexthop.ipv4 = kr->nexthop.v4;
zl.route.prefix.u.prefix4 = kr->prefix.v4;
break;
case AF_INET6:
zl.prefix.u.prefix6 = kr->prefix.v6;
zl.nexthop.ipv6 = kr->nexthop.v6;
zl.route.prefix.u.prefix6 = kr->prefix.v6;
break;
default:
fatalx("kr_change: unknown af");
fatalx("ldp_zebra_send_mpls_labels: unknown af");
}
zl.ifindex = kr->ifindex;
zl.route_type = kr->route_type;
zl.route_instance = kr->route_instance;
zl.local_label = kr->local_label;
zl.remote_label = kr->remote_label;
zl.route.prefix.prefixlen = kr->prefixlen;
zl.route.type = kr->route_type;
zl.route.instance = kr->route_instance;
/* Set nexthop. */
switch (kr->af) {
case AF_INET:
zl.nexthop.family = AF_INET;
zl.nexthop.address.ipv4 = kr->nexthop.v4;
if (kr->ifindex)
zl.nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
else
zl.nexthop.type = NEXTHOP_TYPE_IPV4;
break;
case AF_INET6:
zl.nexthop.family = AF_INET6;
zl.nexthop.address.ipv6 = kr->nexthop.v6;
if (kr->ifindex)
zl.nexthop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
else
zl.nexthop.type = NEXTHOP_TYPE_IPV6;
break;
default:
break;
}
zl.nexthop.ifindex = kr->ifindex;
zl.nexthop.label = kr->remote_label;
return zebra_send_mpls_labels(zclient, cmd, &zl);
}

View file

@ -2464,25 +2464,31 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
stream_reset(s);
zclient_create_header(s, cmd, VRF_DEFAULT);
stream_putc(s, zl->message);
stream_putc(s, zl->type);
stream_putw(s, zl->prefix.family);
stream_put_prefix(s, &zl->prefix);
switch (zl->prefix.family) {
stream_putl(s, zl->local_label);
if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
stream_putw(s, zl->route.prefix.family);
stream_put_prefix(s, &zl->route.prefix);
stream_putc(s, zl->route.type);
stream_putw(s, zl->route.instance);
}
stream_putc(s, zl->nexthop.type);
stream_putw(s, zl->nexthop.family);
switch (zl->nexthop.family) {
case AF_INET:
stream_put_in_addr(s, &zl->nexthop.ipv4);
stream_put_in_addr(s, &zl->nexthop.address.ipv4);
break;
case AF_INET6:
stream_write(s, (uint8_t *)&zl->nexthop.ipv6, 16);
stream_write(s, (uint8_t *)&zl->nexthop.address.ipv6, 16);
break;
default:
flog_err(EC_LIB_ZAPI_ENCODE, "%s: unknown af", __func__);
return -1;
break;
}
stream_putl(s, zl->ifindex);
stream_putc(s, zl->route_type);
stream_putw(s, zl->route_instance);
stream_putl(s, zl->local_label);
stream_putl(s, zl->remote_label);
stream_putl(s, zl->nexthop.ifindex);
stream_putl(s, zl->nexthop.label);
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
@ -2492,47 +2498,67 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
{
size_t psize;
memset(zl, 0, sizeof(*zl));
/* Get data. */
STREAM_GETC(s, zl->message);
STREAM_GETC(s, zl->type);
STREAM_GETW(s, zl->prefix.family);
STREAM_GETC(s, zl->prefix.prefixlen);
psize = PSIZE(zl->prefix.prefixlen);
STREAM_GETL(s, zl->local_label);
switch (zl->prefix.family) {
if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
size_t psize;
STREAM_GETW(s, zl->route.prefix.family);
STREAM_GETC(s, zl->route.prefix.prefixlen);
psize = PSIZE(zl->route.prefix.prefixlen);
switch (zl->route.prefix.family) {
case AF_INET:
if (zl->prefix.prefixlen > IPV4_MAX_BITLEN) {
if (zl->route.prefix.prefixlen > IPV4_MAX_BITLEN) {
zlog_debug(
"%s: Specified prefix length %d is greater than a v4 address can support",
__PRETTY_FUNCTION__, zl->prefix.prefixlen);
__PRETTY_FUNCTION__,
zl->route.prefix.prefixlen);
return -1;
}
STREAM_GET(&zl->prefix.u.prefix4.s_addr, s, psize);
STREAM_GET(&zl->nexthop.ipv4.s_addr, s, IPV4_MAX_BYTELEN);
STREAM_GET(&zl->route.prefix.u.prefix4.s_addr, s,
psize);
break;
case AF_INET6:
if (zl->prefix.prefixlen > IPV6_MAX_BITLEN) {
if (zl->route.prefix.prefixlen > IPV6_MAX_BITLEN) {
zlog_debug(
"%s: Specified prefix length %d is greater than a v6 address can support",
__PRETTY_FUNCTION__, zl->prefix.prefixlen);
__PRETTY_FUNCTION__,
zl->route.prefix.prefixlen);
return -1;
}
STREAM_GET(&zl->prefix.u.prefix6, s, psize);
STREAM_GET(&zl->nexthop.ipv6, s, 16);
STREAM_GET(&zl->route.prefix.u.prefix6, s, psize);
break;
default:
zlog_debug("%s: Specified AF %d is not supported for this call",
__PRETTY_FUNCTION__, zl->prefix.family);
flog_err(EC_LIB_ZAPI_ENCODE,
"%s: Specified family %u is not v4 or v6",
__PRETTY_FUNCTION__, zl->route.prefix.family);
return -1;
}
STREAM_GETL(s, zl->ifindex);
STREAM_GETC(s, zl->route_type);
STREAM_GETW(s, zl->route_instance);
STREAM_GETL(s, zl->local_label);
STREAM_GETL(s, zl->remote_label);
STREAM_GETC(s, zl->route.type);
STREAM_GETW(s, zl->route.instance);
}
STREAM_GETC(s, zl->nexthop.type);
STREAM_GETW(s, zl->nexthop.family);
switch (zl->nexthop.family) {
case AF_INET:
STREAM_GET(&zl->nexthop.address.ipv4.s_addr, s, IPV4_MAX_BYTELEN);
break;
case AF_INET6:
STREAM_GET(&zl->nexthop.address.ipv6, s, 16);
break;
default:
break;
}
STREAM_GETL(s, zl->nexthop.ifindex);
STREAM_GETL(s, zl->nexthop.label);
return 0;
stream_failure:

View file

@ -396,14 +396,22 @@ struct zapi_route {
};
struct zapi_labels {
uint8_t message;
#define ZAPI_LABELS_FTN 0x01
enum lsp_types_t type;
struct prefix prefix;
union g_addr nexthop;
ifindex_t ifindex;
uint8_t route_type;
unsigned short route_instance;
mpls_label_t local_label;
mpls_label_t remote_label;
struct {
struct prefix prefix;
uint8_t type;
unsigned short instance;
} route;
struct {
enum nexthop_types_t type;
int family;
union g_addr address;
ifindex_t ifindex;
mpls_label_t label;
} nexthop;
};
struct zapi_pw {

View file

@ -618,15 +618,20 @@ static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe)
nhlfe.prefv4.prefixlen, nhlfe.ifindex);
zl.type = ZEBRA_LSP_OSPF_SR;
zl.prefix.family = nhlfe.prefv4.family;
zl.prefix.prefixlen = nhlfe.prefv4.prefixlen;
zl.prefix.u.prefix4 = nhlfe.prefv4.prefix;
zl.nexthop.ipv4 = nhlfe.nexthop;
zl.ifindex = nhlfe.ifindex;
zl.route_type = ZEBRA_ROUTE_OSPF;
zl.route_instance = 0;
zl.local_label = nhlfe.label_in;
zl.remote_label = nhlfe.label_out;
SET_FLAG(zl.message, ZAPI_LABELS_FTN);
zl.route.prefix.family = nhlfe.prefv4.family;
zl.route.prefix.prefixlen = nhlfe.prefv4.prefixlen;
zl.route.prefix.u.prefix4 = nhlfe.prefv4.prefix;
zl.route.type = ZEBRA_ROUTE_OSPF;
zl.route.instance = 0;
zl.nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
zl.nexthop.family = AF_INET;
zl.nexthop.address.ipv4 = nhlfe.nexthop;
zl.nexthop.ifindex = nhlfe.ifindex;
zl.nexthop.label = nhlfe.label_out;
return zebra_send_mpls_labels(zclient, cmd, &zl);
}

View file

@ -1753,7 +1753,6 @@ static void zread_mpls_labels(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_labels zl;
enum nexthop_types_t gtype;
/* Get input stream. */
s = msg;
@ -1764,38 +1763,27 @@ static void zread_mpls_labels(ZAPI_HANDLER_ARGS)
return;
}
switch (zl.prefix.family) {
case AF_INET:
if (zl.ifindex)
gtype = NEXTHOP_TYPE_IPV4_IFINDEX;
else
gtype = NEXTHOP_TYPE_IPV4;
break;
case AF_INET6:
if (zl.ifindex)
gtype = NEXTHOP_TYPE_IPV6_IFINDEX;
else
gtype = NEXTHOP_TYPE_IPV6;
break;
default:
return;
}
if (!mpls_enabled)
return;
if (hdr->command == ZEBRA_MPLS_LABELS_ADD) {
mpls_lsp_install(zvrf, zl.type, zl.local_label, zl.remote_label,
gtype, &zl.nexthop, zl.ifindex);
mpls_ftn_update(1, zvrf, zl.type, &zl.prefix, gtype,
&zl.nexthop, zl.ifindex, zl.route_type,
zl.route_instance, zl.remote_label);
mpls_lsp_install(zvrf, zl.type, zl.local_label,
zl.nexthop.label, zl.nexthop.type,
&zl.nexthop.address, zl.nexthop.ifindex);
if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
mpls_ftn_update(1, zvrf, zl.type, &zl.route.prefix,
zl.nexthop.type, &zl.nexthop.address,
zl.nexthop.ifindex, zl.route.type,
zl.route.instance, zl.nexthop.label);
} else if (hdr->command == ZEBRA_MPLS_LABELS_DELETE) {
mpls_lsp_uninstall(zvrf, zl.type, zl.local_label, gtype,
&zl.nexthop, zl.ifindex);
mpls_ftn_update(0, zvrf, zl.type, &zl.prefix, gtype,
&zl.nexthop, zl.ifindex, zl.route_type,
zl.route_instance, zl.remote_label);
mpls_lsp_uninstall(zvrf, zl.type, zl.local_label,
zl.nexthop.type, &zl.nexthop.address,
zl.nexthop.ifindex);
if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
mpls_ftn_update(0, zvrf, zl.type, &zl.route.prefix,
zl.nexthop.type, &zl.nexthop.address,
zl.nexthop.ifindex, zl.route.type,
zl.route.instance, zl.nexthop.label);
}
}