summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zebra/rt_socket.c48
-rw-r--r--zebra/zebra_mpls.c31
-rw-r--r--zebra/zebra_mpls.h2
-rw-r--r--zebra/zebra_mpls_openbsd.c9
-rw-r--r--zebra/zebra_static.h4
5 files changed, 63 insertions, 31 deletions
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 4e4d726b46..32ae41b917 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -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)
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 47cf7a3cbf..cee3a03858 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -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;
- 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);
+ char label_buf[BUFSIZ];
+ int i;
- 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]);
+ buf[0] = '\0';
+ 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;
}
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index c8dab39210..6bddc4d00f 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -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 \
diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c
index 119cd5b700..33f0d49d4d 100644
--- a/zebra/zebra_mpls_openbsd.c
+++ b/zebra/zebra_mpls_openbsd.c
@@ -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)) {
diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h
index 6ab47094a1..ff9f0f59e7 100644
--- a/zebra/zebra_static.h
+++ b/zebra/zebra_static.h
@@ -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 {