Skip to content

Commit

Permalink
openvswitch: Add support for Geneve tunneling.
Browse files Browse the repository at this point in the history
The Openvswitch implementation is completely agnostic to the options
that are in use and can handle newly defined options without
further work. It does this by simply matching on a byte array
of options and allowing userspace to setup flows on this array.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Singed-off-by: Ansis Atteka <aatteka@nicira.com>
Signed-off-by: Andy Zhou <azhou@nicira.com>
Acked-by: Thomas Graf <tgraf@noironetworks.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
jessegross authored and davem330 committed Oct 6, 2014
1 parent 6b205b2 commit f579668
Show file tree
Hide file tree
Showing 13 changed files with 461 additions and 42 deletions.
21 changes: 11 additions & 10 deletions include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,18 @@ struct ip_tunnel {
struct gro_cells gro_cells;
};

#define TUNNEL_CSUM __cpu_to_be16(0x01)
#define TUNNEL_ROUTING __cpu_to_be16(0x02)
#define TUNNEL_KEY __cpu_to_be16(0x04)
#define TUNNEL_SEQ __cpu_to_be16(0x08)
#define TUNNEL_STRICT __cpu_to_be16(0x10)
#define TUNNEL_REC __cpu_to_be16(0x20)
#define TUNNEL_VERSION __cpu_to_be16(0x40)
#define TUNNEL_NO_KEY __cpu_to_be16(0x80)
#define TUNNEL_CSUM __cpu_to_be16(0x01)
#define TUNNEL_ROUTING __cpu_to_be16(0x02)
#define TUNNEL_KEY __cpu_to_be16(0x04)
#define TUNNEL_SEQ __cpu_to_be16(0x08)
#define TUNNEL_STRICT __cpu_to_be16(0x10)
#define TUNNEL_REC __cpu_to_be16(0x20)
#define TUNNEL_VERSION __cpu_to_be16(0x40)
#define TUNNEL_NO_KEY __cpu_to_be16(0x80)
#define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100)
#define TUNNEL_OAM __cpu_to_be16(0x0200)
#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400)
#define TUNNEL_OAM __cpu_to_be16(0x0200)
#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400)
#define TUNNEL_OPTIONS_PRESENT __cpu_to_be16(0x0800)

struct tnl_ptk_info {
__be16 flags;
Expand Down
2 changes: 2 additions & 0 deletions include/uapi/linux/openvswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ enum ovs_vport_type {
OVS_VPORT_TYPE_INTERNAL, /* network device implemented by datapath */
OVS_VPORT_TYPE_GRE, /* GRE tunnel. */
OVS_VPORT_TYPE_VXLAN, /* VXLAN tunnel. */
OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */
__OVS_VPORT_TYPE_MAX
};

Expand Down Expand Up @@ -310,6 +311,7 @@ enum ovs_tunnel_key_attr {
OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT, /* No argument, set DF. */
OVS_TUNNEL_KEY_ATTR_CSUM, /* No argument. CSUM packet. */
OVS_TUNNEL_KEY_ATTR_OAM, /* No argument. OAM frame. */
OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, /* Array of Geneve options. */
__OVS_TUNNEL_KEY_ATTR_MAX
};

Expand Down
11 changes: 11 additions & 0 deletions net/openvswitch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,14 @@ config OPENVSWITCH_VXLAN
Say N to exclude this support and reduce the binary size.

If unsure, say Y.

config OPENVSWITCH_GENEVE
bool "Open vSwitch Geneve tunneling support"
depends on INET
depends on OPENVSWITCH
depends on GENEVE && !(OPENVSWITCH=y && GENEVE=m)
default y
---help---
If you say Y here, then the Open vSwitch will be able create geneve vport.

Say N to exclude this support and reduce the binary size.
4 changes: 4 additions & 0 deletions net/openvswitch/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ openvswitch-y := \
vport-internal_dev.o \
vport-netdev.o

ifneq ($(CONFIG_OPENVSWITCH_GENEVE),)
openvswitch-y += vport-geneve.o
endif

ifneq ($(CONFIG_OPENVSWITCH_VXLAN),)
openvswitch-y += vport-vxlan.o
endif
Expand Down
5 changes: 4 additions & 1 deletion net/openvswitch/datapath.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ static size_t key_attr_size(void)
+ nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
+ nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
+ nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
+ nla_total_size(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
+ nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */
+ nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
+ nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
Expand Down Expand Up @@ -556,10 +557,12 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)

err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS],
&flow->key, 0, &acts);
rcu_assign_pointer(flow->sf_acts, acts);
if (err)
goto err_flow_free;

rcu_assign_pointer(flow->sf_acts, acts);

OVS_CB(packet)->egress_tun_info = NULL;
OVS_CB(packet)->flow = flow;
packet->priority = flow->key.phy.priority;
packet->mark = flow->key.phy.skb_mark;
Expand Down
20 changes: 18 additions & 2 deletions net/openvswitch/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
int error;
struct ethhdr *eth;

/* Flags are always used as part of stats */
key->tp.flags = 0;

skb_reset_mac_header(skb);

/* Link layer. We are guaranteed to have at least the 14 byte Ethernet
Expand Down Expand Up @@ -646,10 +649,23 @@ int ovs_flow_key_extract(struct ovs_tunnel_info *tun_info,
struct sk_buff *skb, struct sw_flow_key *key)
{
/* Extract metadata from packet. */
if (tun_info)
if (tun_info) {
memcpy(&key->tun_key, &tun_info->tunnel, sizeof(key->tun_key));
else

if (tun_info->options) {
BUILD_BUG_ON((1 << (sizeof(tun_info->options_len) *
8)) - 1
> sizeof(key->tun_opts));
memcpy(GENEVE_OPTS(key, tun_info->options_len),
tun_info->options, tun_info->options_len);
key->tun_opts_len = tun_info->options_len;
} else {
key->tun_opts_len = 0;
}
} else {
key->tun_opts_len = 0;
memset(&key->tun_key, 0, sizeof(key->tun_key));
}

key->phy.priority = skb->priority;
key->phy.in_port = OVS_CB(skb)->input_vport->port_no;
Expand Down
20 changes: 19 additions & 1 deletion net/openvswitch/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,24 @@ struct ovs_key_ipv4_tunnel {

struct ovs_tunnel_info {
struct ovs_key_ipv4_tunnel tunnel;
struct geneve_opt *options;
u8 options_len;
};

/* Store options at the end of the array if they are less than the
* maximum size. This allows us to get the benefits of variable length
* matching for small options.
*/
#define GENEVE_OPTS(flow_key, opt_len) \
((struct geneve_opt *)((flow_key)->tun_opts + \
FIELD_SIZEOF(struct sw_flow_key, tun_opts) - \
opt_len))

static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
const struct iphdr *iph,
__be64 tun_id, __be16 tun_flags)
__be64 tun_id, __be16 tun_flags,
struct geneve_opt *opts,
u8 opts_len)
{
tun_info->tunnel.tun_id = tun_id;
tun_info->tunnel.ipv4_src = iph->saddr;
Expand All @@ -67,9 +80,14 @@ static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
/* clear struct padding. */
memset((unsigned char *)&tun_info->tunnel + OVS_TUNNEL_KEY_SIZE, 0,
sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);

tun_info->options = opts;
tun_info->options_len = opts_len;
}

struct sw_flow_key {
u8 tun_opts[255];
u8 tun_opts_len;
struct ovs_key_ipv4_tunnel tun_key; /* Encapsulating tunnel key. */
struct {
u32 priority; /* Packet QoS priority. */
Expand Down
Loading

0 comments on commit f579668

Please sign in to comment.