diff --git a/.travis.yml b/.travis.yml index b66f8212715..4dfe15e58ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ before_install: ./.travis/prepare.sh env: - OPTS="--disable-ssl" - - TESTSUITE=1 KERNEL=1 OPTS="--with-linux=./linux-3.14.7" + - TESTSUITE=1 KERNEL=1 OPTS="--with-linux=./linux-3.16.2" - KERNEL=1 DPDK=1 OPTS="--with-dpdk=./dpdk-1.7.0/build" script: ./.travis/build.sh $OPTS diff --git a/.travis/build.sh b/.travis/build.sh index ecdd39fd576..3872893b87e 100755 --- a/.travis/build.sh +++ b/.travis/build.sh @@ -7,9 +7,9 @@ CFLAGS="-Werror" function install_kernel() { - wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.14.7.tar.gz - tar xzvf linux-3.14.7.tar.gz > /dev/null - cd linux-3.14.7 + wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.16.2.tar.gz + tar xzvf linux-3.16.2.tar.gz > /dev/null + cd linux-3.16.2 make allmodconfig make net/openvswitch/ KERNELSRC=$(pwd) diff --git a/acinclude.m4 b/acinclude.m4 index e3a694be200..6e31d88b383 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [ AC_MSG_RESULT([$kversion]) if test "$version" -ge 3; then - if test "$version" = 3 && test "$patchlevel" -le 14; then + if test "$version" = 3 && test "$patchlevel" -le 17; then : # Linux 3.x else - AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 3.14.x is not supported (please refer to the FAQ for advice)]) + AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 3.17.x is not supported (please refer to the FAQ for advice)]) fi else if test "$version" -le 1 || test "$patchlevel" -le 5 || test "$sublevel" -le 31; then @@ -370,6 +370,14 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/linux/openvswitch.h], [openvswitch_handle_frame_hook], [OVS_DEFINE([HAVE_RHEL_OVS_HOOK])]) + OVS_GREP_IFELSE([$KSRC/include/net/vxlan.h], [bool xnet], + [OVS_DEFINE([HAVE_VXLAN_XMIT_SKB_XNET_ARG])]) + OVS_GREP_IFELSE([$KSRC/include/net/udp.h], [udp_flow_src_port], + [OVS_DEFINE([HAVE_UDP_FLOW_SRC_PORT])]) + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [ignore_df:1], + [OVS_DEFINE([HAVE_IGNORE_DF_RENAME])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/netdevice.h], [NET_NAME_UNKNOWN], + [OVS_DEFINE([HAVE_NET_NAME_UNKNOWN])]) OVS_CHECK_LOG2_H diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index f7c64e266dd..274b1f1667c 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -72,6 +72,7 @@ openvswitch_headers += \ linux/compat/include/net/ipv6.h \ linux/compat/include/net/net_namespace.h \ linux/compat/include/net/netlink.h \ + linux/compat/include/net/udp.h \ linux/compat/include/net/sock.h \ linux/compat/include/net/vxlan.h \ linux/compat/include/net/sctp/checksum.h diff --git a/datapath/linux/compat/include/linux/if.h b/datapath/linux/compat/include/linux/if.h index c4c656ce315..3beb61df1bd 100644 --- a/datapath/linux/compat/include/linux/if.h +++ b/datapath/linux/compat/include/linux/if.h @@ -3,16 +3,4 @@ #include_next -#ifndef IFF_TX_SKB_SHARING -#define IFF_TX_SKB_SHARING 0 -#endif - -#ifndef IFF_OVS_DATAPATH -#define IFF_OVS_DATAPATH 0 -#endif - -#ifndef IFF_LIVE_ADDR_CHANGE -#define IFF_LIVE_ADDR_CHANGE 0 -#endif - #endif diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h index 35b04d0c7a8..679c8616f3e 100644 --- a/datapath/linux/compat/include/linux/netdevice.h +++ b/datapath/linux/compat/include/linux/netdevice.h @@ -8,10 +8,31 @@ struct net; #include +#ifndef IFF_TX_SKB_SHARING +#define IFF_TX_SKB_SHARING 0 +#endif + +#ifndef IFF_OVS_DATAPATH +#define IFF_OVS_DATAPATH 0 +#else +#define HAVE_OVS_DATAPATH +#endif + +#ifndef IFF_LIVE_ADDR_CHANGE +#define IFF_LIVE_ADDR_CHANGE 0 +#endif + #ifndef to_net_dev #define to_net_dev(class) container_of(class, struct net_device, NETDEV_DEV_MEMBER) #endif +#ifndef HAVE_NET_NAME_UNKNOWN +#undef alloc_netdev +#define NET_NAME_UNKNOWN 0 +#define alloc_netdev(sizeof_priv, name, name_assign_type, setup) \ + alloc_netdev_mqs(sizeof_priv, name, setup, 1, 1) +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) extern void unregister_netdevice_queue(struct net_device *dev, struct list_head *head); diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index 9abd5822414..18e75d6ee60 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -6,6 +6,10 @@ #include #include +#ifndef HAVE_IGNORE_DF_RENAME +#define ignore_df local_df +#endif + #ifndef HAVE_SKB_COPY_FROM_LINEAR_DATA_OFFSET static inline void skb_copy_from_linear_data_offset(const struct sk_buff *skb, const int offset, void *to, diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index 2a6470a791f..5d0267df184 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -4,6 +4,18 @@ #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) #include_next + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) +static inline int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, + struct sk_buff *skb, __be32 src, + __be32 dst, __u8 proto, __u8 tos, + __u8 ttl, __be16 df, bool xnet) +{ + return iptunnel_xmit(rt, skb, src, dst, proto, tos, ttl, df, xnet); +} +#define iptunnel_xmit rpl_iptunnel_xmit +#endif + #else #include @@ -36,7 +48,7 @@ struct tnl_ptk_info { #define PACKET_RCVD 0 #define PACKET_REJECT 1 -int iptunnel_xmit(struct rtable *rt, +int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, __be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl, __be16 df, bool xnet); diff --git a/datapath/linux/compat/include/net/udp.h b/datapath/linux/compat/include/net/udp.h new file mode 100644 index 00000000000..88174aebe2f --- /dev/null +++ b/datapath/linux/compat/include/net/udp.h @@ -0,0 +1,37 @@ +#ifndef __NET_UDP_WRAPPER_H +#define __NET_UDP_WRAPPER_H 1 + +#include_next + +#ifndef HAVE_UDP_FLOW_SRC_PORT +static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb, + int min, int max, bool use_eth) +{ + u32 hash; + + if (min >= max) { + /* Use default range */ + inet_get_local_port_range(net, &min, &max); + } + + hash = skb_get_hash(skb); + if (unlikely(!hash) && use_eth) { + /* Can't find a normal hash, caller has indicated an Ethernet + * packet so use that to compute a hash. + */ + hash = jhash(skb->data, 2 * ETH_ALEN, + (__force u32) skb->protocol); + } + + /* Since this is being sent on the wire obfuscate hash a bit + * to minimize possbility that any useful information to an + * attacker is leaked. Only upper 16 bits are relevant in the + * computation for 16 bit port value. + */ + hash ^= hash << 16; + + return htons((((u64) hash * (max - min)) >> 32) + min); +} +#endif + +#endif diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h index d64630b4560..2e56a9bda14 100644 --- a/datapath/linux/compat/include/net/vxlan.h +++ b/datapath/linux/compat/include/net/vxlan.h @@ -19,8 +19,13 @@ static inline int rpl_vxlan_xmit_skb(struct vxlan_sock *vs, return -ENOSYS; } +#ifdef HAVE_VXLAN_XMIT_SKB_XNET_ARG + return vxlan_xmit_skb(vs, rt, skb, src, dst, tos, ttl, df, + src_port, dst_port, vni, false); +#else return vxlan_xmit_skb(vs, rt, skb, src, dst, tos, ttl, df, src_port, dst_port, vni); +#endif } #define vxlan_xmit_skb rpl_vxlan_xmit_skb diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c index a70aefc6a18..549df3d9ead 100644 --- a/datapath/linux/compat/ip_tunnels_core.c +++ b/datapath/linux/compat/ip_tunnels_core.c @@ -37,7 +37,7 @@ #include "compat.h" #include "gso.h" -int iptunnel_xmit(struct rtable *rt, +int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, __be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl, __be16 df, bool xnet) diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c index b8b8fa762d7..9278c376e96 100644 --- a/datapath/linux/compat/vxlan.c +++ b/datapath/linux/compat/vxlan.c @@ -226,7 +226,8 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, if (err) return err; - return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, false); + return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP, + tos, ttl, df, false); } static void rcu_free_vs(struct rcu_head *rcu) diff --git a/datapath/vport-geneve.c b/datapath/vport-geneve.c index ce5b5097ace..6ed1e1f0a7e 100644 --- a/datapath/vport-geneve.c +++ b/datapath/vport-geneve.c @@ -132,12 +132,13 @@ static void geneve_build_header(const struct vport *vport, struct sk_buff *skb) { struct geneve_port *geneve_port = geneve_vport(vport); + struct net *net = ovs_dp_get_net(vport->dp); struct udphdr *udph = udp_hdr(skb); struct genevehdr *geneveh = (struct genevehdr *)(udph + 1); const struct ovs_tunnel_info *tun_info = OVS_CB(skb)->egress_tun_info; udph->dest = inet_sport(geneve_port->sock->sk); - udph->source = vxlan_src_port(1, USHRT_MAX, skb); + udph->source = udp_flow_src_port(net, skb, 0, 0, true); udph->check = 0; udph->len = htons(skb->len - skb_transport_offset(skb)); @@ -423,7 +424,7 @@ static int geneve_send(struct vport *vport, struct sk_buff *skb) df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; - sent_len = iptunnel_xmit(rt, skb, + sent_len = iptunnel_xmit(skb->sk, rt, skb, saddr, tun_key->ipv4_dst, IPPROTO_UDP, tun_key->ipv4_tos, tun_key->ipv4_ttl, @@ -447,6 +448,7 @@ static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, struct ovs_tunnel_info *egress_tun_info) { struct geneve_port *geneve_port = geneve_vport(vport); + struct net *net = ovs_dp_get_net(vport->dp); /* * Get tp_src and tp_dst, refert to geneve_build_header(). @@ -455,7 +457,7 @@ static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, ovs_dp_get_net(vport->dp), OVS_CB(skb)->egress_tun_info, IPPROTO_UDP, skb->mark, - vxlan_src_port(1, USHRT_MAX, skb), + udp_flow_src_port(net, skb, 0, 0, true), inet_sport(geneve_port->sock->sk)); } diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c index ce203b8c584..41c025db476 100644 --- a/datapath/vport-gre.c +++ b/datapath/vport-gre.c @@ -192,9 +192,9 @@ static int __send(struct vport *vport, struct sk_buff *skb, } df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; - skb->local_df = 1; + skb->ignore_df = 1; - return iptunnel_xmit(rt, skb, saddr, + return iptunnel_xmit(skb->sk, rt, skb, saddr, tun_key->ipv4_dst, IPPROTO_GRE, tun_key->ipv4_tos, tun_key->ipv4_ttl, df, false); diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c index 8a454df8450..3a38138a42d 100644 --- a/datapath/vport-internal_dev.c +++ b/datapath/vport-internal_dev.c @@ -151,7 +151,7 @@ static void do_setup(struct net_device *netdev) netdev->priv_flags &= ~IFF_TX_SKB_SHARING; netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; netdev->destructor = internal_dev_destructor; - SET_ETHTOOL_OPS(netdev, &internal_dev_ethtool_ops); + netdev->ethtool_ops = &internal_dev_ethtool_ops; netdev->tx_queue_len = 0; netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | @@ -189,7 +189,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) netdev_vport = netdev_vport_priv(vport); netdev_vport->dev = alloc_netdev(sizeof(struct internal_dev), - parms->name, do_setup); + parms->name, NET_NAME_UNKNOWN, do_setup); if (!netdev_vport->dev) { err = -ENOMEM; goto error_free_vport; diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c index 3335aa561aa..ad5cd23e3e0 100644 --- a/datapath/vport-lisp.c +++ b/datapath/vport-lisp.c @@ -495,10 +495,10 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb) if (err) goto err_free_rt; - skb->local_df = 1; + skb->ignore_df = 1; df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; - sent_len = iptunnel_xmit(rt, skb, + sent_len = iptunnel_xmit(skb->sk, rt, skb, saddr, tun_key->ipv4_dst, IPPROTO_UDP, tun_key->ipv4_tos, tun_key->ipv4_ttl, df, false); diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c index c15923b2048..a00276b006e 100644 --- a/datapath/vport-netdev.c +++ b/datapath/vport-netdev.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -255,7 +256,7 @@ struct vport *ovs_netdev_get_vport(struct net_device *dev) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) || \ defined HAVE_RHEL_OVS_HOOK -#if IFF_OVS_DATAPATH != 0 +#ifdef HAVE_OVS_DATAPATH if (likely(dev->priv_flags & IFF_OVS_DATAPATH)) #else if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook)) diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c index 34dd919aeab..8689853b8b3 100644 --- a/datapath/vport-vxlan.c +++ b/datapath/vport-vxlan.c @@ -149,8 +149,6 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) __be16 src_port; __be32 saddr; __be16 df; - int port_min; - int port_max; int err; if (unlikely(!OVS_CB(skb)->egress_tun_info)) { @@ -172,10 +170,9 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) } df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; - skb->local_df = 1; + skb->ignore_df = 1; - inet_get_local_port_range(net, &port_min, &port_max); - src_port = vxlan_src_port(port_min, port_max, skb); + src_port = udp_flow_src_port(net, skb, 0, 0, true); err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, saddr, tun_key->ipv4_dst, @@ -196,11 +193,8 @@ static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, struct vxlan_port *vxlan_port = vxlan_vport(vport); __be16 dst_port = inet_sport(vxlan_port->vs->sock->sk); __be16 src_port; - int port_min; - int port_max; - inet_get_local_port_range(net, &port_min, &port_max); - src_port = vxlan_src_port(port_min, port_max, skb); + src_port = udp_flow_src_port(net, skb, 0, 0, true); return ovs_tunnel_get_egress_info(egress_tun_info, net, OVS_CB(skb)->egress_tun_info,