Skip to content

Commit

Permalink
datapath: Provide compatibility for kernels up to 3.17
Browse files Browse the repository at this point in the history
Port datapath to work with kernrels up to 3.17 and use 3.16.2 as
the new kernel for CI testing.

Tested with 3.14, 3.16.2, and net-next (3.17).

Signed-off-by: Thomas Graf <tgraf@noironetworks.com>
Co-authored-by: Madhu Challa <challa@noironetworks.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
  • Loading branch information
2 people authored and Pravin B Shelar committed Sep 21, 2014
1 parent 3b2bbce commit f6a0c89
Show file tree
Hide file tree
Showing 18 changed files with 114 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions .travis/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 10 additions & 2 deletions acinclude.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions datapath/linux/Modules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 0 additions & 12 deletions datapath/linux/compat/include/linux/if.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,4 @@

#include_next <linux/if.h>

#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
21 changes: 21 additions & 0 deletions datapath/linux/compat/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,31 @@ struct net;

#include <linux/version.h>

#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);
Expand Down
4 changes: 4 additions & 0 deletions datapath/linux/compat/include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include <linux/jhash.h>
#include <linux/version.h>

#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,
Expand Down
14 changes: 13 additions & 1 deletion datapath/linux/compat/include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)
#include_next <net/ip_tunnels.h>

#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 <linux/if_tunnel.h>
Expand Down Expand Up @@ -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);
Expand Down
37 changes: 37 additions & 0 deletions datapath/linux/compat/include/net/udp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef __NET_UDP_WRAPPER_H
#define __NET_UDP_WRAPPER_H 1

#include_next <net/udp.h>

#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
5 changes: 5 additions & 0 deletions datapath/linux/compat/include/net/vxlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion datapath/linux/compat/ip_tunnels_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion datapath/linux/compat/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 5 additions & 3 deletions datapath/vport-geneve.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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,
Expand All @@ -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().
Expand All @@ -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));

}
Expand Down
4 changes: 2 additions & 2 deletions datapath/vport-gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions datapath/vport-internal_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions datapath/vport-lisp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion datapath/vport-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/openvswitch.h>
#include <linux/netdevice.h>

#include <net/llc.h>

Expand Down Expand Up @@ -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))
Expand Down
12 changes: 3 additions & 9 deletions datapath/vport-vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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,
Expand All @@ -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,
Expand Down

0 comments on commit f6a0c89

Please sign in to comment.