}
#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)
}
#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(
{
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;
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)
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;
}
/* 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 \
|| (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)) {
#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 {