Skip to content

Commit

Permalink
datapath: support upstream ndo_udp_tunnel_add in net_device_ops
Browse files Browse the repository at this point in the history
It makes datapath can support both ndo_add_udp_tunnel_port and
ndo_add_vxlan/geneve_port. The newer kernels don't support vxlan/geneve
specific NDO's anymore

Signed-off-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Reviewed-by: Greg Rose <gvrose8192@gmail.com>
Tested-by: Greg Rose <gvrose8192@gmail.com>
  • Loading branch information
wenxu authored and blp committed Aug 7, 2018
1 parent 274e04f commit e2e11c8
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 6 deletions.
1 change: 1 addition & 0 deletions acinclude.m4
Expand Up @@ -553,6 +553,7 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
[OVS_DEFINE([USE_UPSTREAM_TUNNEL_GSO])])
OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [ndo_add_vxlan_port])
OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [ndo_add_geneve_port])
OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [ndo_udp_tunnel_add])
OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [netdev_features_t])
dnl Ubuntu kernel 3.13 has defined this struct but not used for netdev->tstats.
dnl So check type of tstats.
Expand Down
41 changes: 38 additions & 3 deletions datapath/linux/compat/geneve.c
Expand Up @@ -432,6 +432,14 @@ static void geneve_notify_add_rx_port(struct geneve_sock *gs)
if (dev->netdev_ops->ndo_add_geneve_port)
dev->netdev_ops->ndo_add_geneve_port(dev, sa_family,
port);
#elif defined(HAVE_NDO_UDP_TUNNEL_ADD)
struct udp_tunnel_info ti;
ti.type = UDP_TUNNEL_TYPE_GENEVE;
ti.sa_family = sa_family;
ti.port = inet_sk(sk)->inet_sport;

if (dev->netdev_ops->ndo_udp_tunnel_add)
dev->netdev_ops->ndo_udp_tunnel_add(dev, &ti);
#endif
}
rcu_read_unlock();
Expand All @@ -452,6 +460,14 @@ static void geneve_notify_del_rx_port(struct geneve_sock *gs)
if (dev->netdev_ops->ndo_del_geneve_port)
dev->netdev_ops->ndo_del_geneve_port(dev, sa_family,
port);
#elif defined(HAVE_NDO_UDP_TUNNEL_ADD)
struct udp_tunnel_info ti;
ti.type = UDP_TUNNEL_TYPE_GENEVE;
ti.port = inet_sk(sk)->inet_sport;
ti.sa_family = sa_family;

if (dev->netdev_ops->ndo_udp_tunnel_del)
dev->netdev_ops->ndo_udp_tunnel_del(dev, &ti);
#endif
}

Expand Down Expand Up @@ -1301,9 +1317,9 @@ static struct device_type geneve_type = {
.name = "geneve",
};

/* Calls the ndo_add_geneve_port of the caller in order to
* supply the listening GENEVE udp ports. Callers are expected
* to implement the ndo_add_geneve_port.
/* Calls the ndo_add_geneve_port or ndo_udp_tunnel_add of the caller
* in order to supply the listening GENEVE udp ports. Callers are
* expected to implement the ndo_add_geneve_port.
*/
static void geneve_push_rx_ports(struct net_device *dev)
{
Expand All @@ -1326,6 +1342,25 @@ static void geneve_push_rx_ports(struct net_device *dev)
dev->netdev_ops->ndo_add_geneve_port(dev, sa_family, port);
}
rcu_read_unlock();
#elif defined(HAVE_NDO_UDP_TUNNEL_ADD)
struct net *net = dev_net(dev);
struct geneve_net *gn = net_generic(net, geneve_net_id);
struct geneve_sock *gs;
struct sock *sk;

if (!dev->netdev_ops->ndo_udp_tunnel_add)
return;

rcu_read_lock();
list_for_each_entry_rcu(gs, &gn->sock_list, list) {
struct udp_tunnel_info ti;
ti.type = UDP_TUNNEL_TYPE_GENEVE;
sk = gs->sock->sk;
ti.port = inet_sk(sk)->inet_sport;
ti.sa_family = sk->sk_family;
dev->netdev_ops->ndo_udp_tunnel_add(dev, &ti);
}
rcu_read_unlock();
#endif
}

Expand Down
14 changes: 14 additions & 0 deletions datapath/linux/compat/include/net/udp_tunnel.h
Expand Up @@ -43,6 +43,20 @@ struct udp_port_cfg {
ipv6_v6only:1;
};

#ifdef HAVE_NDO_UDP_TUNNEL_ADD
enum udp_parsable_tunnel_type {
UDP_TUNNEL_TYPE_VXLAN, /* RFC 7348 */
UDP_TUNNEL_TYPE_GENEVE, /* draft-ietf-nvo3-geneve */
UDP_TUNNEL_TYPE_VXLAN_GPE, /* draft-ietf-nvo3-vxlan-gpe */
};

struct udp_tunnel_info {
unsigned short type;
sa_family_t sa_family;
__be16 port;
};
#endif

#define udp_sock_create4 rpl_udp_sock_create4
int rpl_udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
struct socket **sockp);
Expand Down
52 changes: 49 additions & 3 deletions datapath/linux/compat/vxlan.c
Expand Up @@ -396,6 +396,17 @@ static void vxlan_notify_add_rx_port(struct vxlan_sock *vs)
if (dev->netdev_ops->ndo_add_vxlan_port)
dev->netdev_ops->ndo_add_vxlan_port(dev, sa_family,
port);
#elif defined(HAVE_NDO_UDP_TUNNEL_ADD)
struct udp_tunnel_info ti;
if (vs->flags & VXLAN_F_GPE)
ti.type = UDP_TUNNEL_TYPE_VXLAN_GPE;
else
ti.type = UDP_TUNNEL_TYPE_VXLAN;
ti.sa_family = sa_family;
ti.port = inet_sk(sk)->inet_sport;

if (dev->netdev_ops->ndo_udp_tunnel_add)
dev->netdev_ops->ndo_udp_tunnel_add(dev, &ti);
#endif
}
rcu_read_unlock();
Expand All @@ -417,6 +428,17 @@ static void vxlan_notify_del_rx_port(struct vxlan_sock *vs)
if (dev->netdev_ops->ndo_del_vxlan_port)
dev->netdev_ops->ndo_del_vxlan_port(dev, sa_family,
port);
#elif defined(HAVE_NDO_UDP_TUNNEL_ADD)
struct udp_tunnel_info ti;
if (vs->flags & VXLAN_F_GPE)
ti.type = UDP_TUNNEL_TYPE_VXLAN_GPE;
else
ti.type = UDP_TUNNEL_TYPE_VXLAN;
ti.port = inet_sk(sk)->inet_sport;
ti.sa_family = sa_family;

if (dev->netdev_ops->ndo_udp_tunnel_del)
dev->netdev_ops->ndo_udp_tunnel_del(dev, &ti);
#endif
}
rcu_read_unlock();
Expand Down Expand Up @@ -1528,9 +1550,9 @@ static struct device_type vxlan_type = {
.name = "vxlan",
};

/* Calls the ndo_add_vxlan_port of the caller in order to
* supply the listening VXLAN udp ports. Callers are expected
* to implement the ndo_add_vxlan_port.
/* Calls the ndo_add_vxlan_port or ndo_udp_tunnel_add of the caller
* in order to supply the listening VXLAN udp ports. Callers are
* expected to implement the ndo_add_vxlan_port.
*/
static void vxlan_push_rx_ports(struct net_device *dev)
{
Expand All @@ -1555,6 +1577,30 @@ static void vxlan_push_rx_ports(struct net_device *dev)
}
}
spin_unlock(&vn->sock_lock);
#elif defined(HAVE_NDO_UDP_TUNNEL_ADD)
struct vxlan_sock *vs;
struct net *net = dev_net(dev);
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
unsigned int i;

if (!dev->netdev_ops->ndo_udp_tunnel_add)
return;

spin_lock(&vn->sock_lock);
for (i = 0; i < PORT_HASH_SIZE; ++i) {
hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) {
struct udp_tunnel_info ti;
if (vs->flags & VXLAN_F_GPE)
ti.type = UDP_TUNNEL_TYPE_VXLAN_GPE;
else
ti.type = UDP_TUNNEL_TYPE_VXLAN;
ti.port = inet_sk(vs->sock->sk)->inet_sport;
ti.sa_family = vxlan_get_sk_family(vs);

dev->netdev_ops->ndo_udp_tunnel_add(dev, &ti);
}
}
spin_unlock(&vn->sock_lock);
#endif
}

Expand Down

0 comments on commit e2e11c8

Please sign in to comment.