]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Switchoff for MPLS in kernel.
authorMaria Jan Matejka <mq@jmq.cz>
Mon, 25 Sep 2017 11:00:05 +0000 (13:00 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Sun, 10 Dec 2017 17:30:00 +0000 (18:30 +0100)
aclocal.m4
configure.ac
sysdep/linux/lwtunnel.h [deleted file]
sysdep/linux/netlink.c
sysdep/unix/krt.c

index 365bfa81363d7ca8ae4d31f9db14bd3aca8b07ab..8160e53927ceda5fa8901f512696e63daba3caf0 100644 (file)
@@ -31,6 +31,41 @@ AC_DEFUN([BIRD_CHECK_PTHREADS],
   CFLAGS="$bird_tmp_cflags"
 ])
 
+AC_DEFUN([BIRD_CHECK_MPLS_KERNEL],
+[
+  AC_CACHE_CHECK(
+    [for Linux MPLS headers],
+    [bird_cv_mpls_kernel],
+    [
+      AC_COMPILE_IFELSE(
+       [
+         AC_LANG_PROGRAM(
+           [
+             #include <linux/lwtunnel.h>
+             #include <linux/netlink.h>
+             #include <linux/rtnetlink.h>
+             #include <sys/socket.h>
+             void t(int arg);
+           ],
+           [
+             t(AF_MPLS);
+             t(RTA_VIA);
+             t(RTA_NEWDST);
+             t(RTA_ENCAP_TYPE);
+             t(RTA_ENCAP);
+             struct rtvia rtvia;
+             t(LWTUNNEL_ENCAP_MPLS);
+           ]
+         )
+       ],
+       [bird_cv_mpls_kernel=yes],
+       [bird_cv_mpls_kernel=no]
+      )
+    ]
+  )
+])
+
+
 AC_DEFUN([BIRD_CHECK_GCC_OPTION],
 [
   bird_tmp_cflags="$CFLAGS"
index 5514fb567078dc1176341edb4421990454998403..68e68282c6276fc52439945f28803a0d369b9d76 100644 (file)
@@ -36,6 +36,12 @@ AC_ARG_ENABLE([libssh],
   [enable_libssh=try]
 )
 
+AC_ARG_ENABLE([mpls-kernel],
+  [AS_HELP_STRING([--enable-mpls-kernel], [enable MPLS support in kernel protocol @<:@try@:>@])],
+  [],
+  [enable_mpls_kernel=try]
+)
+
 AC_ARG_WITH([protocols],
   [AS_HELP_STRING([--with-protocols=LIST], [include specified routing protocols @<:@all@:>@])],
   [],
@@ -239,6 +245,20 @@ if test "$enable_libssh" != no ; then
   fi
 fi
 
+if test "$enable_mpls_kernel" != no ; then
+  BIRD_CHECK_MPLS_KERNEL
+
+  if test "$bird_cv_mpls_kernel" = yes ; then
+    AC_DEFINE([HAVE_MPLS_KERNEL], [1], [Define to 1 if kernel is MPLS capable])
+  elif test "$enable_mpls_kernel" = yes ; then
+    AC_MSG_ERROR([Kernel MPLS support not found.])
+  fi
+
+  if test "$enable_mpls_kernel" = try ; then
+    enable_mpls_kernel="$bird_cv_mpls_kernel"
+  fi
+fi
+
 all_protocols="$proto_bfd babel bgp ospf pipe radv rip $proto_rpki static"
 
 all_protocols=`echo $all_protocols | sed 's/ /,/g'`
@@ -287,18 +307,6 @@ esac
 AC_CHECK_HEADERS_ONCE([alloca.h syslog.h])
 AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [], [#include <sys/socket.h>])
 
-AC_CHECK_HEADERS([linux/lwtunnel.h],
-  [AC_DEFINE([HAVE_LWTUNNEL], [1], [Define to 1 if you have the <linux/lwtunnel.h> header file.])],
-  [],
-  [] dnl Force new AC_CHECK_HEADER semantics
-)
-
-AC_CHECK_MEMBERS([struct rtvia.rtvia_family],
-  [AC_DEFINE([HAVE_STRUCT_RTVIA], [1], [Define to 1 if you have rtvia structure.])],
-  [],
-  [#include <linux/rtnetlink.h>]
-)
-
 AC_C_BIGENDIAN(
   [AC_DEFINE([CPU_BIG_ENDIAN], [1], [Define to 1 if cpu is big endian])],
   [AC_DEFINE([CPU_LITTLE_ENDIAN], [1], [Define to 1 if cpu is little endian])],
@@ -396,6 +404,7 @@ AC_MSG_RESULT([        System configuration:        $sysdesc])
 AC_MSG_RESULT([        Debugging:              $enable_debug])
 AC_MSG_RESULT([        POSIX threads:          $enable_pthreads])
 AC_MSG_RESULT([        Routing protocols:      $protocols])
+AC_MSG_RESULT([        Kernel MPLS support:    $enable_mpls_kernel])
 AC_MSG_RESULT([        Client:                 $enable_client])
 
 rm -f $objdir/.*-stamp
diff --git a/sysdep/linux/lwtunnel.h b/sysdep/linux/lwtunnel.h
deleted file mode 100644 (file)
index 7cea3cb..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef _LWTUNNEL_H_
-#define _LWTUNNEL_H_
-
-#include <linux/types.h>
-
-enum lwtunnel_encap_types {
-       LWTUNNEL_ENCAP_NONE,
-       LWTUNNEL_ENCAP_MPLS,
-       LWTUNNEL_ENCAP_IP,
-       LWTUNNEL_ENCAP_ILA,
-       LWTUNNEL_ENCAP_IP6,
-       __LWTUNNEL_ENCAP_MAX,
-};
-
-#define LWTUNNEL_ENCAP_MAX (__LWTUNNEL_ENCAP_MAX - 1)
-
-enum lwtunnel_ip_t {
-       LWTUNNEL_IP_UNSPEC,
-       LWTUNNEL_IP_ID,
-       LWTUNNEL_IP_DST,
-       LWTUNNEL_IP_SRC,
-       LWTUNNEL_IP_TTL,
-       LWTUNNEL_IP_TOS,
-       LWTUNNEL_IP_FLAGS,
-       LWTUNNEL_IP_PAD,
-       __LWTUNNEL_IP_MAX,
-};
-
-#define LWTUNNEL_IP_MAX (__LWTUNNEL_IP_MAX - 1)
-
-enum lwtunnel_ip6_t {
-       LWTUNNEL_IP6_UNSPEC,
-       LWTUNNEL_IP6_ID,
-       LWTUNNEL_IP6_DST,
-       LWTUNNEL_IP6_SRC,
-       LWTUNNEL_IP6_HOPLIMIT,
-       LWTUNNEL_IP6_TC,
-       LWTUNNEL_IP6_FLAGS,
-       LWTUNNEL_IP6_PAD,
-       __LWTUNNEL_IP6_MAX,
-};
-
-#define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1)
-
-#endif /* _LWTUNNEL_H_ */
index ca5c79a414539e85174e5ca3f3c581968dc7d7ee..afb9dc8ba083a198f772b11ca75c89cacf077f87 100644 (file)
 
 #include <asm/types.h>
 #include <linux/if.h>
-#ifdef HAVE_LWTUNNEL
-#include <linux/lwtunnel.h>
-#else
-#include "sysdep/linux/lwtunnel.h"
-#endif
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 
+#ifdef HAVE_MPLS_KERNEL
+#include <linux/lwtunnel.h>
+#endif
 
 #ifndef MSG_TRUNC                      /* Hack: Several versions of glibc miss this one :( */
 #define MSG_TRUNC 0x20
 #define RTA_VIA         18
 #endif
 
-#ifndef HAVE_STRUCT_RTVIA
-struct rtvia {
-       unsigned short  rtvia_family;
-       u8              rtvia_addr[0];
-};
-#endif
-
 #ifndef RTA_NEWDST
 #define RTA_NEWDST  19
 #endif
@@ -361,9 +352,11 @@ static struct nl_want_attrs nexthop_attr_want6[BIRD_RTA_MAX] = {
   [RTA_ENCAP]    = { 1, 0, 0 },
 };
 
+#ifdef HAVE_MPLS_KERNEL
 static struct nl_want_attrs encap_mpls_want[BIRD_RTA_MAX] = {
   [RTA_DST]       = { 1, 0, 0 },
 };
+#endif
 
 static struct nl_want_attrs rtm_attr_want4[BIRD_RTA_MAX] = {
   [RTA_DST]      = { 1, 1, sizeof(ip4_addr) },
@@ -394,6 +387,7 @@ static struct nl_want_attrs rtm_attr_want6[BIRD_RTA_MAX] = {
   [RTA_ENCAP]    = { 1, 0, 0 },
 };
 
+#ifdef HAVE_MPLS_KERNEL
 static struct nl_want_attrs rtm_attr_want_mpls[BIRD_RTA_MAX] = {
   [RTA_DST]      = { 1, 1, sizeof(u32) },
   [RTA_IIF]      = { 1, 1, sizeof(u32) },
@@ -405,6 +399,7 @@ static struct nl_want_attrs rtm_attr_want_mpls[BIRD_RTA_MAX] = {
   [RTA_VIA]      = { 1, 0, 0 },
   [RTA_NEWDST]   = { 1, 0, 0 },
 };
+#endif
 
 
 static int
@@ -456,6 +451,7 @@ static inline ip_addr rta_get_ipa(struct rtattr *a)
     return ipa_from_ip6(rta_get_ip6(a));
 }
 
+#ifdef HAVE_MPLS_KERNEL
 static inline ip_addr rta_get_via(struct rtattr *a)
 {
   struct rtvia *v = RTA_DATA(a);
@@ -474,6 +470,7 @@ static inline int rta_get_mpls(struct rtattr *a, u32 *stack)
 
   return mpls_get(RTA_DATA(a), RTA_PAYLOAD(a) & ~0x3, stack);
 }
+#endif
 
 struct rtattr *
 nl_add_attr(struct nlmsghdr *h, uint bufsize, uint code, const void *data, uint dlen)
@@ -542,6 +539,7 @@ nl_add_attr_ipa(struct nlmsghdr *h, uint bufsize, int code, ip_addr ipa)
     nl_add_attr_ip6(h, bufsize, code, ipa_to_ip6(ipa));
 }
 
+#ifdef HAVE_MPLS_KERNEL
 static inline void
 nl_add_attr_mpls(struct nlmsghdr *h, uint bufsize, int code, int len, u32 *stack)
 {
@@ -583,6 +581,7 @@ nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa)
 
   nl_close_attr(h, nest);
 }
+#endif
 
 static inline struct rtnexthop *
 nl_open_nexthop(struct nlmsghdr *h, uint bufsize)
@@ -605,8 +604,9 @@ nl_close_nexthop(struct nlmsghdr *h, struct rtnexthop *nh)
 }
 
 static inline void
-nl_add_nexthop(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af)
+nl_add_nexthop(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af UNUSED)
 {
+#ifdef HAVE_MPLS_KERNEL
   if (nh->labels > 0)
     if (af == AF_MPLS)
       nl_add_attr_mpls(h, bufsize, RTA_NEWDST, nh->labels, nh->label);
@@ -618,6 +618,11 @@ nl_add_nexthop(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af)
       nl_add_attr_via(h, bufsize, nh->gw);
     else
       nl_add_attr_ipa(h, bufsize, RTA_GATEWAY, nh->gw);
+#else
+
+  if (ipa_nonzero(nh->gw))
+    nl_add_attr_ipa(h, bufsize, RTA_GATEWAY, nh->gw);
+#endif
 }
 
 static void
@@ -716,20 +721,22 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra, int af)
       else
        rv->gw = IPA_NONE;
 
+#ifdef HAVE_MPLS_KERNEL
       if (a[RTA_ENCAP_TYPE])
-       {
-         if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) {
-           log(L_WARN "KRT: Unknown encapsulation method %d in multipath", rta_get_u16(a[RTA_ENCAP_TYPE]));
-           return NULL;
-         }
-
-         struct rtattr *enca[BIRD_RTA_MAX];
-         nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]);
-         nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca));
-         rv->labels = rta_get_mpls(enca[RTA_DST], rv->label);
-         break;
+      {
+       if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) {
+         log(L_WARN "KRT: Unknown encapsulation method %d in multipath", rta_get_u16(a[RTA_ENCAP_TYPE]));
+         return NULL;
        }
 
+       struct rtattr *enca[BIRD_RTA_MAX];
+       nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]);
+       nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca));
+       rv->labels = rta_get_mpls(enca[RTA_DST], rv->label);
+       break;
+      }
+#endif
+
 
       len -= NLMSG_ALIGN(nh->rtnh_len);
       nh = RTNH_NEXT(nh);
@@ -1216,12 +1223,14 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
   r->r.rtm_dst_len = net_pxlen(net->n.addr);
   r->r.rtm_protocol = RTPROT_BIRD;
   r->r.rtm_scope = RT_SCOPE_NOWHERE;
+#ifdef HAVE_MPLS_KERNEL
   if (p->af == AF_MPLS)
   {
     u32 label = net_mpls(net->n.addr);
     nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label);
   }
   else
+#endif
     nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr));
 
   /*
@@ -1490,6 +1499,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
        net_fill_ip6(&dst, IP6_NONE, 0);
       break;
 
+#ifdef HAVE_MPLS_KERNEL
     case AF_MPLS:
       if (!nl_parse_attrs(RTM_RTA(i), rtm_attr_want_mpls, a, sizeof(a)))
        return;
@@ -1502,6 +1512,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
 
       net_fill_mpls(&dst, rta_mpls_stack[0]);
       break;
+#endif
 
     default:
       return;
@@ -1595,11 +1606,17 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
          return;
        }
 
-      if ((i->rtm_family != AF_MPLS) && a[RTA_GATEWAY] || (i->rtm_family == AF_MPLS) && a[RTA_VIA])
+      if ((i->rtm_family != AF_MPLS) && a[RTA_GATEWAY]
+#ifdef HAVE_MPLS_KERNEL
+         || (i->rtm_family == AF_MPLS) && a[RTA_VIA]
+#endif
+         )
        {
+#ifdef HAVE_MPLS_KERNEL
          if (i->rtm_family == AF_MPLS)
            ra->nh.gw = rta_get_via(a[RTA_VIA]);
          else
+#endif
            ra->nh.gw = rta_get_ipa(a[RTA_GATEWAY]);
 
          /* Silently skip strange 6to4 routes */
@@ -1637,6 +1654,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
       return;
     }
 
+#ifdef HAVE_MPLS_KERNEL
   int labels = 0;
   if ((i->rtm_family == AF_MPLS) && a[RTA_NEWDST] && !ra->nh.next)
     labels = rta_get_mpls(a[RTA_NEWDST], ra->nh.label);
@@ -1666,6 +1684,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
   }
   else
     ra->nh.labels = labels;
+#endif
 
   rte *e = rte_get_temp(ra);
   e->net = net;
@@ -1816,6 +1835,7 @@ krt_do_scan(struct krt_proto *p UNUSED)   /* CONFIG_ALL_TABLES_AT_ONCE => p is NUL
       log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
   nl_parse_end(&s);
 
+#ifdef HAVE_MPLS_KERNEL
   nl_parse_begin(&s, 1, 1);
   nl_request_dump(AF_MPLS, RTM_GETROUTE);
   while (h = nl_get_scan())
@@ -1824,6 +1844,7 @@ krt_do_scan(struct krt_proto *p UNUSED)   /* CONFIG_ALL_TABLES_AT_ONCE => p is NUL
     else
       log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
   nl_parse_end(&s);
+#endif
 }
 
 /*
index 052f210a88bde5990aa11c876ab46b53bf18ed41..29d2d01eea7157edc3e460746c1dd7ae967553c5 100644 (file)
@@ -1211,7 +1211,11 @@ struct protocol proto_unix_kernel = {
   .template =          "kernel%d",
   .attr_class =                EAP_KRT,
   .preference =                DEF_PREF_INHERITED,
+#ifdef HAVE_MPLS_KERNEL
   .channel_mask =      NB_IP | NB_MPLS,
+#else
+  .channel_mask =      NB_IP,
+#endif
   .proto_size =                sizeof(struct krt_proto),
   .config_size =       sizeof(struct krt_config),
   .preconfig =         krt_preconfig,