diff --git a/aclocal.m4 b/aclocal.m4 index 365bfa81..8160e539 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -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 + #include + #include + #include + 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" diff --git a/configure.ac b/configure.ac index 5514fb56..68e68282 100644 --- a/configure.ac +++ b/configure.ac @@ -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 ]) -AC_CHECK_HEADERS([linux/lwtunnel.h], - [AC_DEFINE([HAVE_LWTUNNEL], [1], [Define to 1 if you have the 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 ] -) - 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 index 7cea3cbf..00000000 --- a/sysdep/linux/lwtunnel.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _LWTUNNEL_H_ -#define _LWTUNNEL_H_ - -#include - -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_ */ diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index ca5c79a4..afb9dc8b 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -30,14 +30,12 @@ #include #include -#ifdef HAVE_LWTUNNEL -#include -#else -#include "sysdep/linux/lwtunnel.h" -#endif #include #include +#ifdef HAVE_MPLS_KERNEL +#include +#endif #ifndef MSG_TRUNC /* Hack: Several versions of glibc miss this one :( */ #define MSG_TRUNC 0x20 @@ -59,13 +57,6 @@ #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 } /* diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 052f210a..29d2d01e 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -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,