diff options
author | Jiri Benc <jbenc@redhat.com> | 2015-10-05 07:09:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-07 07:17:59 -0400 |
commit | 00a93babd06aaad31d23384cda576ede0f586a8c (patch) | |
tree | 2fd12c2f928eae294ae0892e99562ac1f2d9997e | |
parent | 4917a1548ff41e53d863d6845b4da1884e4282b4 (diff) |
openvswitch: add tunnel protocol to sw_flow_key
Store tunnel protocol (AF_INET or AF_INET6) in sw_flow_key. This field now
also acts as an indicator whether the flow contains tunnel data (this was
previously indicated by tun_key.u.ipv4.dst being set but with IPv6 addresses
in an union with IPv4 ones this won't work anymore).
The new field was added to a hole in sw_flow_key.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/openvswitch/flow.c | 4 | ||||
-rw-r--r-- | net/openvswitch/flow.h | 1 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.c | 10 | ||||
-rw-r--r-- | net/openvswitch/flow_table.c | 2 |
4 files changed, 12 insertions, 5 deletions
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index c8db44ab2ee7..0ea128eeeab2 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
@@ -698,8 +698,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, | |||
698 | { | 698 | { |
699 | /* Extract metadata from packet. */ | 699 | /* Extract metadata from packet. */ |
700 | if (tun_info) { | 700 | if (tun_info) { |
701 | if (ip_tunnel_info_af(tun_info) != AF_INET) | 701 | key->tun_proto = ip_tunnel_info_af(tun_info); |
702 | return -EINVAL; | ||
703 | memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key)); | 702 | memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key)); |
704 | 703 | ||
705 | if (tun_info->options_len) { | 704 | if (tun_info->options_len) { |
@@ -714,6 +713,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, | |||
714 | key->tun_opts_len = 0; | 713 | key->tun_opts_len = 0; |
715 | } | 714 | } |
716 | } else { | 715 | } else { |
716 | key->tun_proto = 0; | ||
717 | key->tun_opts_len = 0; | 717 | key->tun_opts_len = 0; |
718 | memset(&key->tun_key, 0, sizeof(key->tun_key)); | 718 | memset(&key->tun_key, 0, sizeof(key->tun_key)); |
719 | } | 719 | } |
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index fe527d2dd4b7..5688e33e2de6 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h | |||
@@ -63,6 +63,7 @@ struct sw_flow_key { | |||
63 | u32 skb_mark; /* SKB mark. */ | 63 | u32 skb_mark; /* SKB mark. */ |
64 | u16 in_port; /* Input switch port (or DP_MAX_PORTS). */ | 64 | u16 in_port; /* Input switch port (or DP_MAX_PORTS). */ |
65 | } __packed phy; /* Safe when right after 'tun_key'. */ | 65 | } __packed phy; /* Safe when right after 'tun_key'. */ |
66 | u8 tun_proto; /* Protocol of encapsulating tunnel. */ | ||
66 | u32 ovs_flow_hash; /* Datapath computed hash value. */ | 67 | u32 ovs_flow_hash; /* Datapath computed hash value. */ |
67 | u32 recirc_id; /* Recirculation ID. */ | 68 | u32 recirc_id; /* Recirculation ID. */ |
68 | struct { | 69 | struct { |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 5c030a4d7338..6be701f6b31b 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -643,6 +643,10 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr, | |||
643 | } | 643 | } |
644 | 644 | ||
645 | SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask); | 645 | SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask); |
646 | if (is_mask) | ||
647 | SW_FLOW_KEY_MEMSET_FIELD(match, tun_proto, 0xff, true); | ||
648 | else | ||
649 | SW_FLOW_KEY_PUT(match, tun_proto, AF_INET, false); | ||
646 | 650 | ||
647 | if (rem > 0) { | 651 | if (rem > 0) { |
648 | OVS_NLERR(log, "IPv4 tunnel attribute has %d unknown bytes.", | 652 | OVS_NLERR(log, "IPv4 tunnel attribute has %d unknown bytes.", |
@@ -1194,7 +1198,7 @@ int ovs_nla_get_match(struct net *net, struct sw_flow_match *match, | |||
1194 | /* The userspace does not send tunnel attributes that | 1198 | /* The userspace does not send tunnel attributes that |
1195 | * are 0, but we should not wildcard them nonetheless. | 1199 | * are 0, but we should not wildcard them nonetheless. |
1196 | */ | 1200 | */ |
1197 | if (match->key->tun_key.u.ipv4.dst) | 1201 | if (match->key->tun_proto) |
1198 | SW_FLOW_KEY_MEMSET_FIELD(match, tun_key, | 1202 | SW_FLOW_KEY_MEMSET_FIELD(match, tun_key, |
1199 | 0xff, true); | 1203 | 0xff, true); |
1200 | 1204 | ||
@@ -1367,7 +1371,7 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey, | |||
1367 | if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority)) | 1371 | if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority)) |
1368 | goto nla_put_failure; | 1372 | goto nla_put_failure; |
1369 | 1373 | ||
1370 | if ((swkey->tun_key.u.ipv4.dst || is_mask)) { | 1374 | if ((swkey->tun_proto || is_mask)) { |
1371 | const void *opts = NULL; | 1375 | const void *opts = NULL; |
1372 | 1376 | ||
1373 | if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT) | 1377 | if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT) |
@@ -1913,6 +1917,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, | |||
1913 | 1917 | ||
1914 | tun_info = &tun_dst->u.tun_info; | 1918 | tun_info = &tun_dst->u.tun_info; |
1915 | tun_info->mode = IP_TUNNEL_INFO_TX; | 1919 | tun_info->mode = IP_TUNNEL_INFO_TX; |
1920 | if (key.tun_proto == AF_INET6) | ||
1921 | tun_info->mode |= IP_TUNNEL_INFO_IPV6; | ||
1916 | tun_info->key = key.tun_key; | 1922 | tun_info->key = key.tun_key; |
1917 | 1923 | ||
1918 | /* We need to store the options in the action itself since | 1924 | /* We need to store the options in the action itself since |
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index f2ea83ba4763..95dbcedf0bd4 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c | |||
@@ -427,7 +427,7 @@ static u32 flow_hash(const struct sw_flow_key *key, | |||
427 | 427 | ||
428 | static int flow_key_start(const struct sw_flow_key *key) | 428 | static int flow_key_start(const struct sw_flow_key *key) |
429 | { | 429 | { |
430 | if (key->tun_key.u.ipv4.dst) | 430 | if (key->tun_proto) |
431 | return 0; | 431 | return 0; |
432 | else | 432 | else |
433 | return rounddown(offsetof(struct sw_flow_key, phy), | 433 | return rounddown(offsetof(struct sw_flow_key, phy), |