forked from Mirror/frr
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:
parent
635a039eef
commit
b3c49d0e77
|
@ -121,25 +121,48 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
|
||||||
(cmd == ZEBRA_MPLS_LABELS_ADD) ? "add" : "delete");
|
(cmd == ZEBRA_MPLS_LABELS_ADD) ? "add" : "delete");
|
||||||
|
|
||||||
zl.type = ZEBRA_LSP_LDP;
|
zl.type = ZEBRA_LSP_LDP;
|
||||||
zl.prefix.family = kr->af;
|
zl.local_label = kr->local_label;
|
||||||
zl.prefix.prefixlen = kr->prefixlen;
|
|
||||||
|
/* Set prefix. */
|
||||||
|
SET_FLAG(zl.message, ZAPI_LABELS_FTN);
|
||||||
|
zl.route.prefix.family = kr->af;
|
||||||
switch (kr->af) {
|
switch (kr->af) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
zl.prefix.u.prefix4 = kr->prefix.v4;
|
zl.route.prefix.u.prefix4 = kr->prefix.v4;
|
||||||
zl.nexthop.ipv4 = kr->nexthop.v4;
|
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
zl.prefix.u.prefix6 = kr->prefix.v6;
|
zl.route.prefix.u.prefix6 = kr->prefix.v6;
|
||||||
zl.nexthop.ipv6 = kr->nexthop.v6;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fatalx("kr_change: unknown af");
|
fatalx("ldp_zebra_send_mpls_labels: unknown af");
|
||||||
}
|
}
|
||||||
zl.ifindex = kr->ifindex;
|
zl.route.prefix.prefixlen = kr->prefixlen;
|
||||||
zl.route_type = kr->route_type;
|
zl.route.type = kr->route_type;
|
||||||
zl.route_instance = kr->route_instance;
|
zl.route.instance = kr->route_instance;
|
||||||
zl.local_label = kr->local_label;
|
|
||||||
zl.remote_label = kr->remote_label;
|
/* 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);
|
return zebra_send_mpls_labels(zclient, cmd, &zl);
|
||||||
}
|
}
|
||||||
|
|
108
lib/zclient.c
108
lib/zclient.c
|
@ -2464,25 +2464,31 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
|
||||||
stream_reset(s);
|
stream_reset(s);
|
||||||
|
|
||||||
zclient_create_header(s, cmd, VRF_DEFAULT);
|
zclient_create_header(s, cmd, VRF_DEFAULT);
|
||||||
|
stream_putc(s, zl->message);
|
||||||
stream_putc(s, zl->type);
|
stream_putc(s, zl->type);
|
||||||
stream_putw(s, zl->prefix.family);
|
stream_putl(s, zl->local_label);
|
||||||
stream_put_prefix(s, &zl->prefix);
|
|
||||||
switch (zl->prefix.family) {
|
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:
|
case AF_INET:
|
||||||
stream_put_in_addr(s, &zl->nexthop.ipv4);
|
stream_put_in_addr(s, &zl->nexthop.address.ipv4);
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
stream_write(s, (uint8_t *)&zl->nexthop.ipv6, 16);
|
stream_write(s, (uint8_t *)&zl->nexthop.address.ipv6, 16);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
flog_err(EC_LIB_ZAPI_ENCODE, "%s: unknown af", __func__);
|
break;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
stream_putl(s, zl->ifindex);
|
stream_putl(s, zl->nexthop.ifindex);
|
||||||
stream_putc(s, zl->route_type);
|
stream_putl(s, zl->nexthop.label);
|
||||||
stream_putw(s, zl->route_instance);
|
|
||||||
stream_putl(s, zl->local_label);
|
|
||||||
stream_putl(s, zl->remote_label);
|
|
||||||
|
|
||||||
/* Put length at the first point of the stream. */
|
/* Put length at the first point of the stream. */
|
||||||
stream_putw_at(s, 0, stream_get_endp(s));
|
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)
|
int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
|
||||||
{
|
{
|
||||||
size_t psize;
|
|
||||||
|
|
||||||
memset(zl, 0, sizeof(*zl));
|
memset(zl, 0, sizeof(*zl));
|
||||||
|
|
||||||
/* Get data. */
|
/* Get data. */
|
||||||
|
STREAM_GETC(s, zl->message);
|
||||||
STREAM_GETC(s, zl->type);
|
STREAM_GETC(s, zl->type);
|
||||||
STREAM_GETW(s, zl->prefix.family);
|
STREAM_GETL(s, zl->local_label);
|
||||||
STREAM_GETC(s, zl->prefix.prefixlen);
|
|
||||||
psize = PSIZE(zl->prefix.prefixlen);
|
|
||||||
|
|
||||||
switch (zl->prefix.family) {
|
if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
|
||||||
case AF_INET:
|
size_t psize;
|
||||||
if (zl->prefix.prefixlen > IPV4_MAX_BITLEN) {
|
|
||||||
zlog_debug(
|
STREAM_GETW(s, zl->route.prefix.family);
|
||||||
"%s: Specified prefix length %d is greater than a v4 address can support",
|
STREAM_GETC(s, zl->route.prefix.prefixlen);
|
||||||
__PRETTY_FUNCTION__, zl->prefix.prefixlen);
|
|
||||||
|
psize = PSIZE(zl->route.prefix.prefixlen);
|
||||||
|
switch (zl->route.prefix.family) {
|
||||||
|
case AF_INET:
|
||||||
|
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->route.prefix.prefixlen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
STREAM_GET(&zl->route.prefix.u.prefix4.s_addr, s,
|
||||||
|
psize);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
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->route.prefix.prefixlen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
STREAM_GET(&zl->route.prefix.u.prefix6, s, psize);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
flog_err(EC_LIB_ZAPI_ENCODE,
|
||||||
|
"%s: Specified family %u is not v4 or v6",
|
||||||
|
__PRETTY_FUNCTION__, zl->route.prefix.family);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
STREAM_GET(&zl->prefix.u.prefix4.s_addr, s, psize);
|
|
||||||
STREAM_GET(&zl->nexthop.ipv4.s_addr, s, IPV4_MAX_BYTELEN);
|
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;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
if (zl->prefix.prefixlen > IPV6_MAX_BITLEN) {
|
STREAM_GET(&zl->nexthop.address.ipv6, s, 16);
|
||||||
zlog_debug(
|
|
||||||
"%s: Specified prefix length %d is greater than a v6 address can support",
|
|
||||||
__PRETTY_FUNCTION__, zl->prefix.prefixlen);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
STREAM_GET(&zl->prefix.u.prefix6, s, psize);
|
|
||||||
STREAM_GET(&zl->nexthop.ipv6, s, 16);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
zlog_debug("%s: Specified AF %d is not supported for this call",
|
break;
|
||||||
__PRETTY_FUNCTION__, zl->prefix.family);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
STREAM_GETL(s, zl->ifindex);
|
STREAM_GETL(s, zl->nexthop.ifindex);
|
||||||
STREAM_GETC(s, zl->route_type);
|
STREAM_GETL(s, zl->nexthop.label);
|
||||||
STREAM_GETW(s, zl->route_instance);
|
|
||||||
STREAM_GETL(s, zl->local_label);
|
|
||||||
STREAM_GETL(s, zl->remote_label);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
stream_failure:
|
stream_failure:
|
||||||
|
|
|
@ -396,14 +396,22 @@ struct zapi_route {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zapi_labels {
|
struct zapi_labels {
|
||||||
|
uint8_t message;
|
||||||
|
#define ZAPI_LABELS_FTN 0x01
|
||||||
enum lsp_types_t type;
|
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 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 {
|
struct zapi_pw {
|
||||||
|
|
|
@ -618,15 +618,20 @@ static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe)
|
||||||
nhlfe.prefv4.prefixlen, nhlfe.ifindex);
|
nhlfe.prefv4.prefixlen, nhlfe.ifindex);
|
||||||
|
|
||||||
zl.type = ZEBRA_LSP_OSPF_SR;
|
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.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);
|
return zebra_send_mpls_labels(zclient, cmd, &zl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1753,7 +1753,6 @@ static void zread_mpls_labels(ZAPI_HANDLER_ARGS)
|
||||||
{
|
{
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
struct zapi_labels zl;
|
struct zapi_labels zl;
|
||||||
enum nexthop_types_t gtype;
|
|
||||||
|
|
||||||
/* Get input stream. */
|
/* Get input stream. */
|
||||||
s = msg;
|
s = msg;
|
||||||
|
@ -1764,38 +1763,27 @@ static void zread_mpls_labels(ZAPI_HANDLER_ARGS)
|
||||||
return;
|
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)
|
if (!mpls_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (hdr->command == ZEBRA_MPLS_LABELS_ADD) {
|
if (hdr->command == ZEBRA_MPLS_LABELS_ADD) {
|
||||||
mpls_lsp_install(zvrf, zl.type, zl.local_label, zl.remote_label,
|
mpls_lsp_install(zvrf, zl.type, zl.local_label,
|
||||||
gtype, &zl.nexthop, zl.ifindex);
|
zl.nexthop.label, zl.nexthop.type,
|
||||||
mpls_ftn_update(1, zvrf, zl.type, &zl.prefix, gtype,
|
&zl.nexthop.address, zl.nexthop.ifindex);
|
||||||
&zl.nexthop, zl.ifindex, zl.route_type,
|
if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
|
||||||
zl.route_instance, zl.remote_label);
|
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) {
|
} else if (hdr->command == ZEBRA_MPLS_LABELS_DELETE) {
|
||||||
mpls_lsp_uninstall(zvrf, zl.type, zl.local_label, gtype,
|
mpls_lsp_uninstall(zvrf, zl.type, zl.local_label,
|
||||||
&zl.nexthop, zl.ifindex);
|
zl.nexthop.type, &zl.nexthop.address,
|
||||||
mpls_ftn_update(0, zvrf, zl.type, &zl.prefix, gtype,
|
zl.nexthop.ifindex);
|
||||||
&zl.nexthop, zl.ifindex, zl.route_type,
|
if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
|
||||||
zl.route_instance, zl.remote_label);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue