zebra: increase maximum label stack depth

* Bump MPLS_MAX_LABELS from 2 to 16;
* Adjust the static_nh_label structure and the mpls_label2str() function;
* On OpenBSD, print an error message when trying to push more than one
  label at once (kernel limitation). While here, add support for MPLSv6
  FTNs in OpenBSD.

This is not the full package. We still can't pop multiple labels at once,
or do things like swap a label and push other ones. We'll address that
in the future.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2017-08-22 17:01:54 -03:00
parent 1d84515ca9
commit 5e8c8947e3
5 changed files with 63 additions and 31 deletions

View File

@ -71,6 +71,27 @@ static int sin_masklen(struct in_addr mask)
}
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
#ifdef __OpenBSD__
static int kernel_rtm_add_labels(struct nexthop_label *nh_label,
struct sockaddr_mpls *smpls)
{
if (nh_label->num_labels > 1) {
zlog_warn(
"%s: can't push %u labels at "
"once (maximum is 1)",
__func__, nh_label->num_labels);
return -1;
}
memset(smpls, 0, sizeof(*smpls));
smpls->smpls_len = sizeof(*smpls);
smpls->smpls_family = AF_MPLS;
smpls->smpls_label = htonl(nh_label->label[0] << MPLS_LABEL_OFFSET);
return 0;
}
#endif
/* Interface between zebra message and rtm message. */
static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
@ -150,15 +171,11 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
}
#ifdef __OpenBSD__
if (nexthop->nh_label) {
memset(&smpls, 0, sizeof(smpls));
smpls.smpls_len = sizeof(smpls);
smpls.smpls_family = AF_MPLS;
smpls.smpls_label =
htonl(nexthop->nh_label->label[0]
<< MPLS_LABEL_OFFSET);
smplsp = (union sockunion *)&smpls;
}
if (nexthop->nh_label
&& !kernel_rtm_add_labels(nexthop->nh_label,
&smpls))
continue;
smplsp = (union sockunion *)&smpls;
#endif
error = rtm_write(
@ -266,6 +283,10 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
{
struct sockaddr_in6 *mask;
struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
#ifdef __OpenBSD__
struct sockaddr_mpls smpls;
#endif
union sockunion *smplsp = NULL;
struct nexthop *nexthop;
int nexthop_num = 0;
ifindex_t ifindex = 0;
@ -338,10 +359,17 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
mask = &sin_mask;
}
#ifdef __OpenBSD__
if (nexthop->nh_label
&& !kernel_rtm_add_labels(nexthop->nh_label, &smpls))
continue;
smplsp = (union sockunion *)&smpls;
#endif
error = rtm_write(cmd, (union sockunion *)&sin_dest,
(union sockunion *)mask,
gate ? (union sockunion *)&sin_gate : NULL,
NULL, ifindex, re->flags, re->metric);
smplsp, ifindex, re->flags, re->metric);
#if 0
if (error)

View File

@ -1671,27 +1671,20 @@ int mpls_str2label(const char *label_str, u_int8_t *num_labels,
char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf,
int len, int pretty)
{
char *buf_ptr = buf;
char label_buf[BUFSIZ];
int i;
buf[0] = '\0';
if (pretty) {
if (num_labels == 1) {
label2str(labels[0], buf, len);
} else if (num_labels == 2) {
label2str(labels[0], buf, len);
buf_ptr += strlen(buf);
snprintf(buf_ptr, len, "/");
buf_ptr++;
label2str(labels[1], buf_ptr, len);
}
} else {
if (num_labels == 1)
snprintf(buf, len, "%u", labels[0]);
else if (num_labels == 2)
snprintf(buf, len, "%u/%u", labels[0], labels[1]);
for (i = 0; i < num_labels; i++) {
if (i != 0)
strlcat(buf, "/", len);
if (pretty)
label2str(labels[i], label_buf, sizeof(label_buf));
else
snprintf(label_buf, sizeof(label_buf), "%u", labels[i]);
strlcat(buf, label_buf, len);
}
return buf;
}

View File

@ -37,7 +37,7 @@
/* Definitions and macros. */
#define MPLS_MAX_LABELS 2 /* Maximum # labels that can be pushed. */
#define MPLS_MAX_LABELS 16 /* Maximum # labels that can be pushed. */
#define NHLFE_FAMILY(nhlfe) \
(((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \

View File

@ -256,6 +256,15 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp)
|| (action == RTM_DELETE
&& (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) {
if (nhlfe->nexthop->nh_label->num_labels > 1) {
zlog_warn(
"%s: can't push %u labels at once "
"(maximum is 1)",
__func__,
nhlfe->nexthop->nh_label->num_labels);
continue;
}
nexthop_num++;
switch (NHLFE_FAMILY(nhlfe)) {

View File

@ -22,11 +22,13 @@
#ifndef __ZEBRA_STATIC_H__
#define __ZEBRA_STATIC_H__
#include "zebra/zebra_mpls.h"
/* Static route label information */
struct static_nh_label {
u_int8_t num_labels;
u_int8_t reserved[3];
mpls_label_t label[2];
mpls_label_t label[MPLS_MAX_LABELS];
};
typedef enum {