aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-06-17 20:50:18 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-19 21:07:41 -0400
commit7d5437c709ded4f152cb8b305d17972d6707f20c (patch)
treed69da5004c4a65a0d4f60f5f8884f2aad120698f /net/openvswitch
parent74f84a5726c7d08c27745305e67474b8645c541d (diff)
openvswitch: Add tunneling interface.
Add ovs tunnel interface for set tunnel action for userspace. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Jesse Gross <jesse@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/actions.c4
-rw-r--r--net/openvswitch/datapath.c78
-rw-r--r--net/openvswitch/datapath.h3
-rw-r--r--net/openvswitch/flow.c125
-rw-r--r--net/openvswitch/flow.h19
-rw-r--r--net/openvswitch/vport-internal_dev.c2
-rw-r--r--net/openvswitch/vport-netdev.c2
-rw-r--r--net/openvswitch/vport.c4
-rw-r--r--net/openvswitch/vport.h3
9 files changed, 233 insertions, 7 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 596d6373399d..22c5f399f1cf 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -436,6 +436,10 @@ static int execute_set_action(struct sk_buff *skb,
436 skb->mark = nla_get_u32(nested_attr); 436 skb->mark = nla_get_u32(nested_attr);
437 break; 437 break;
438 438
439 case OVS_KEY_ATTR_IPV4_TUNNEL:
440 OVS_CB(skb)->tun_key = nla_data(nested_attr);
441 break;
442
439 case OVS_KEY_ATTR_ETHERNET: 443 case OVS_KEY_ATTR_ETHERNET:
440 err = set_eth_addr(skb, nla_data(nested_attr)); 444 err = set_eth_addr(skb, nla_data(nested_attr));
441 break; 445 break;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index f14816b80b80..bbd310646bc8 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -362,6 +362,14 @@ static int queue_gso_packets(struct net *net, int dp_ifindex,
362static size_t key_attr_size(void) 362static size_t key_attr_size(void)
363{ 363{
364 return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */ 364 return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
365 + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
366 + nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */
367 + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
368 + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
369 + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
370 + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
371 + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
372 + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
365 + nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */ 373 + nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */
366 + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */ 374 + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
367 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */ 375 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
@@ -600,8 +608,30 @@ static int validate_tp_port(const struct sw_flow_key *flow_key)
600 return -EINVAL; 608 return -EINVAL;
601} 609}
602 610
611static int validate_and_copy_set_tun(const struct nlattr *attr,
612 struct sw_flow_actions **sfa)
613{
614 struct ovs_key_ipv4_tunnel tun_key;
615 int err, start;
616
617 err = ovs_ipv4_tun_from_nlattr(nla_data(attr), &tun_key);
618 if (err)
619 return err;
620
621 start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET);
622 if (start < 0)
623 return start;
624
625 err = add_action(sfa, OVS_KEY_ATTR_IPV4_TUNNEL, &tun_key, sizeof(tun_key));
626 add_nested_action_end(*sfa, start);
627
628 return err;
629}
630
603static int validate_set(const struct nlattr *a, 631static int validate_set(const struct nlattr *a,
604 const struct sw_flow_key *flow_key) 632 const struct sw_flow_key *flow_key,
633 struct sw_flow_actions **sfa,
634 bool *set_tun)
605{ 635{
606 const struct nlattr *ovs_key = nla_data(a); 636 const struct nlattr *ovs_key = nla_data(a);
607 int key_type = nla_type(ovs_key); 637 int key_type = nla_type(ovs_key);
@@ -611,18 +641,27 @@ static int validate_set(const struct nlattr *a,
611 return -EINVAL; 641 return -EINVAL;
612 642
613 if (key_type > OVS_KEY_ATTR_MAX || 643 if (key_type > OVS_KEY_ATTR_MAX ||
614 nla_len(ovs_key) != ovs_key_lens[key_type]) 644 (ovs_key_lens[key_type] != nla_len(ovs_key) &&
645 ovs_key_lens[key_type] != -1))
615 return -EINVAL; 646 return -EINVAL;
616 647
617 switch (key_type) { 648 switch (key_type) {
618 const struct ovs_key_ipv4 *ipv4_key; 649 const struct ovs_key_ipv4 *ipv4_key;
619 const struct ovs_key_ipv6 *ipv6_key; 650 const struct ovs_key_ipv6 *ipv6_key;
651 int err;
620 652
621 case OVS_KEY_ATTR_PRIORITY: 653 case OVS_KEY_ATTR_PRIORITY:
622 case OVS_KEY_ATTR_SKB_MARK: 654 case OVS_KEY_ATTR_SKB_MARK:
623 case OVS_KEY_ATTR_ETHERNET: 655 case OVS_KEY_ATTR_ETHERNET:
624 break; 656 break;
625 657
658 case OVS_KEY_ATTR_TUNNEL:
659 *set_tun = true;
660 err = validate_and_copy_set_tun(a, sfa);
661 if (err)
662 return err;
663 break;
664
626 case OVS_KEY_ATTR_IPV4: 665 case OVS_KEY_ATTR_IPV4:
627 if (flow_key->eth.type != htons(ETH_P_IP)) 666 if (flow_key->eth.type != htons(ETH_P_IP))
628 return -EINVAL; 667 return -EINVAL;
@@ -771,7 +810,7 @@ static int validate_and_copy_actions(const struct nlattr *attr,
771 break; 810 break;
772 811
773 case OVS_ACTION_ATTR_SET: 812 case OVS_ACTION_ATTR_SET:
774 err = validate_set(a, key); 813 err = validate_set(a, key, sfa, &skip_copy);
775 if (err) 814 if (err)
776 return err; 815 return err;
777 break; 816 break;
@@ -993,6 +1032,33 @@ static int sample_action_to_attr(const struct nlattr *attr, struct sk_buff *skb)
993 return err; 1032 return err;
994} 1033}
995 1034
1035static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
1036{
1037 const struct nlattr *ovs_key = nla_data(a);
1038 int key_type = nla_type(ovs_key);
1039 struct nlattr *start;
1040 int err;
1041
1042 switch (key_type) {
1043 case OVS_KEY_ATTR_IPV4_TUNNEL:
1044 start = nla_nest_start(skb, OVS_ACTION_ATTR_SET);
1045 if (!start)
1046 return -EMSGSIZE;
1047
1048 err = ovs_ipv4_tun_to_nlattr(skb, nla_data(ovs_key));
1049 if (err)
1050 return err;
1051 nla_nest_end(skb, start);
1052 break;
1053 default:
1054 if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key))
1055 return -EMSGSIZE;
1056 break;
1057 }
1058
1059 return 0;
1060}
1061
996static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb) 1062static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb)
997{ 1063{
998 const struct nlattr *a; 1064 const struct nlattr *a;
@@ -1002,6 +1068,12 @@ static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *s
1002 int type = nla_type(a); 1068 int type = nla_type(a);
1003 1069
1004 switch (type) { 1070 switch (type) {
1071 case OVS_ACTION_ATTR_SET:
1072 err = set_action_to_attr(a, skb);
1073 if (err)
1074 return err;
1075 break;
1076
1005 case OVS_ACTION_ATTR_SAMPLE: 1077 case OVS_ACTION_ATTR_SAMPLE:
1006 err = sample_action_to_attr(a, skb); 1078 err = sample_action_to_attr(a, skb);
1007 if (err) 1079 if (err)
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 16b840695216..e88ebc2f1c54 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -88,9 +88,12 @@ struct datapath {
88/** 88/**
89 * struct ovs_skb_cb - OVS data in skb CB 89 * struct ovs_skb_cb - OVS data in skb CB
90 * @flow: The flow associated with this packet. May be %NULL if no flow. 90 * @flow: The flow associated with this packet. May be %NULL if no flow.
91 * @tun_key: Key for the tunnel that encapsulated this packet. NULL if the
92 * packet is not being tunneled.
91 */ 93 */
92struct ovs_skb_cb { 94struct ovs_skb_cb {
93 struct sw_flow *flow; 95 struct sw_flow *flow;
96 struct ovs_key_ipv4_tunnel *tun_key;
94}; 97};
95#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb) 98#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
96 99
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 940d4b803ff5..976a8b766a6a 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -40,6 +40,7 @@
40#include <linux/icmpv6.h> 40#include <linux/icmpv6.h>
41#include <linux/rculist.h> 41#include <linux/rculist.h>
42#include <net/ip.h> 42#include <net/ip.h>
43#include <net/ip_tunnels.h>
43#include <net/ipv6.h> 44#include <net/ipv6.h>
44#include <net/ndisc.h> 45#include <net/ndisc.h>
45 46
@@ -603,6 +604,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
603 memset(key, 0, sizeof(*key)); 604 memset(key, 0, sizeof(*key));
604 605
605 key->phy.priority = skb->priority; 606 key->phy.priority = skb->priority;
607 if (OVS_CB(skb)->tun_key)
608 memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
606 key->phy.in_port = in_port; 609 key->phy.in_port = in_port;
607 key->phy.skb_mark = skb->mark; 610 key->phy.skb_mark = skb->mark;
608 611
@@ -818,6 +821,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
818 [OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6), 821 [OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6),
819 [OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp), 822 [OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp),
820 [OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd), 823 [OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd),
824 [OVS_KEY_ATTR_TUNNEL] = -1,
821}; 825};
822 826
823static int ipv4_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_len, 827static int ipv4_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_len,
@@ -955,6 +959,105 @@ static int parse_flow_nlattrs(const struct nlattr *attr,
955 return 0; 959 return 0;
956} 960}
957 961
962int ovs_ipv4_tun_from_nlattr(const struct nlattr *attr,
963 struct ovs_key_ipv4_tunnel *tun_key)
964{
965 struct nlattr *a;
966 int rem;
967 bool ttl = false;
968
969 memset(tun_key, 0, sizeof(*tun_key));
970
971 nla_for_each_nested(a, attr, rem) {
972 int type = nla_type(a);
973 static const u32 ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
974 [OVS_TUNNEL_KEY_ATTR_ID] = sizeof(u64),
975 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = sizeof(u32),
976 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = sizeof(u32),
977 [OVS_TUNNEL_KEY_ATTR_TOS] = 1,
978 [OVS_TUNNEL_KEY_ATTR_TTL] = 1,
979 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0,
980 [OVS_TUNNEL_KEY_ATTR_CSUM] = 0,
981 };
982
983 if (type > OVS_TUNNEL_KEY_ATTR_MAX ||
984 ovs_tunnel_key_lens[type] != nla_len(a))
985 return -EINVAL;
986
987 switch (type) {
988 case OVS_TUNNEL_KEY_ATTR_ID:
989 tun_key->tun_id = nla_get_be64(a);
990 tun_key->tun_flags |= TUNNEL_KEY;
991 break;
992 case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
993 tun_key->ipv4_src = nla_get_be32(a);
994 break;
995 case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
996 tun_key->ipv4_dst = nla_get_be32(a);
997 break;
998 case OVS_TUNNEL_KEY_ATTR_TOS:
999 tun_key->ipv4_tos = nla_get_u8(a);
1000 break;
1001 case OVS_TUNNEL_KEY_ATTR_TTL:
1002 tun_key->ipv4_ttl = nla_get_u8(a);
1003 ttl = true;
1004 break;
1005 case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
1006 tun_key->tun_flags |= TUNNEL_DONT_FRAGMENT;
1007 break;
1008 case OVS_TUNNEL_KEY_ATTR_CSUM:
1009 tun_key->tun_flags |= TUNNEL_CSUM;
1010 break;
1011 default:
1012 return -EINVAL;
1013
1014 }
1015 }
1016 if (rem > 0)
1017 return -EINVAL;
1018
1019 if (!tun_key->ipv4_dst)
1020 return -EINVAL;
1021
1022 if (!ttl)
1023 return -EINVAL;
1024
1025 return 0;
1026}
1027
1028int ovs_ipv4_tun_to_nlattr(struct sk_buff *skb,
1029 const struct ovs_key_ipv4_tunnel *tun_key)
1030{
1031 struct nlattr *nla;
1032
1033 nla = nla_nest_start(skb, OVS_KEY_ATTR_TUNNEL);
1034 if (!nla)
1035 return -EMSGSIZE;
1036
1037 if (tun_key->tun_flags & TUNNEL_KEY &&
1038 nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, tun_key->tun_id))
1039 return -EMSGSIZE;
1040 if (tun_key->ipv4_src &&
1041 nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, tun_key->ipv4_src))
1042 return -EMSGSIZE;
1043 if (nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST, tun_key->ipv4_dst))
1044 return -EMSGSIZE;
1045 if (tun_key->ipv4_tos &&
1046 nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, tun_key->ipv4_tos))
1047 return -EMSGSIZE;
1048 if (nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TTL, tun_key->ipv4_ttl))
1049 return -EMSGSIZE;
1050 if ((tun_key->tun_flags & TUNNEL_DONT_FRAGMENT) &&
1051 nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT))
1052 return -EMSGSIZE;
1053 if ((tun_key->tun_flags & TUNNEL_CSUM) &&
1054 nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
1055 return -EMSGSIZE;
1056
1057 nla_nest_end(skb, nla);
1058 return 0;
1059}
1060
958/** 1061/**
959 * ovs_flow_from_nlattrs - parses Netlink attributes into a flow key. 1062 * ovs_flow_from_nlattrs - parses Netlink attributes into a flow key.
960 * @swkey: receives the extracted flow key. 1063 * @swkey: receives the extracted flow key.
@@ -997,6 +1100,14 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
997 attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK); 1100 attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
998 } 1101 }
999 1102
1103 if (attrs & (1 << OVS_KEY_ATTR_TUNNEL)) {
1104 err = ovs_ipv4_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], &swkey->tun_key);
1105 if (err)
1106 return err;
1107
1108 attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
1109 }
1110
1000 /* Data attributes. */ 1111 /* Data attributes. */
1001 if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET))) 1112 if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET)))
1002 return -EINVAL; 1113 return -EINVAL;
@@ -1135,17 +1246,21 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
1135int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, 1246int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow,
1136 const struct nlattr *attr) 1247 const struct nlattr *attr)
1137{ 1248{
1249 struct ovs_key_ipv4_tunnel *tun_key = &flow->key.tun_key;
1138 const struct nlattr *nla; 1250 const struct nlattr *nla;
1139 int rem; 1251 int rem;
1140 1252
1141 flow->key.phy.in_port = DP_MAX_PORTS; 1253 flow->key.phy.in_port = DP_MAX_PORTS;
1142 flow->key.phy.priority = 0; 1254 flow->key.phy.priority = 0;
1143 flow->key.phy.skb_mark = 0; 1255 flow->key.phy.skb_mark = 0;
1256 memset(tun_key, 0, sizeof(flow->key.tun_key));
1144 1257
1145 nla_for_each_nested(nla, attr, rem) { 1258 nla_for_each_nested(nla, attr, rem) {
1146 int type = nla_type(nla); 1259 int type = nla_type(nla);
1147 1260
1148 if (type <= OVS_KEY_ATTR_MAX && ovs_key_lens[type] > 0) { 1261 if (type <= OVS_KEY_ATTR_MAX && ovs_key_lens[type] > 0) {
1262 int err;
1263
1149 if (nla_len(nla) != ovs_key_lens[type]) 1264 if (nla_len(nla) != ovs_key_lens[type])
1150 return -EINVAL; 1265 return -EINVAL;
1151 1266
@@ -1154,6 +1269,12 @@ int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow,
1154 flow->key.phy.priority = nla_get_u32(nla); 1269 flow->key.phy.priority = nla_get_u32(nla);
1155 break; 1270 break;
1156 1271
1272 case OVS_KEY_ATTR_TUNNEL:
1273 err = ovs_ipv4_tun_from_nlattr(nla, tun_key);
1274 if (err)
1275 return err;
1276 break;
1277
1157 case OVS_KEY_ATTR_IN_PORT: 1278 case OVS_KEY_ATTR_IN_PORT:
1158 if (nla_get_u32(nla) >= DP_MAX_PORTS) 1279 if (nla_get_u32(nla) >= DP_MAX_PORTS)
1159 return -EINVAL; 1280 return -EINVAL;
@@ -1180,6 +1301,10 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
1180 nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority)) 1301 nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority))
1181 goto nla_put_failure; 1302 goto nla_put_failure;
1182 1303
1304 if (swkey->tun_key.ipv4_dst &&
1305 ovs_ipv4_tun_to_nlattr(skb, &swkey->tun_key))
1306 goto nla_put_failure;
1307
1183 if (swkey->phy.in_port != DP_MAX_PORTS && 1308 if (swkey->phy.in_port != DP_MAX_PORTS &&
1184 nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port)) 1309 nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port))
1185 goto nla_put_failure; 1310 goto nla_put_failure;
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index e370f6246ee9..aec5e43f690b 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -40,7 +40,22 @@ struct sw_flow_actions {
40 struct nlattr actions[]; 40 struct nlattr actions[];
41}; 41};
42 42
43/* Used to memset ovs_key_ipv4_tunnel padding. */
44#define OVS_TUNNEL_KEY_SIZE \
45 (offsetof(struct ovs_key_ipv4_tunnel, ipv4_ttl) + \
46 FIELD_SIZEOF(struct ovs_key_ipv4_tunnel, ipv4_ttl))
47
48struct ovs_key_ipv4_tunnel {
49 __be64 tun_id;
50 __be32 ipv4_src;
51 __be32 ipv4_dst;
52 u16 tun_flags;
53 u8 ipv4_tos;
54 u8 ipv4_ttl;
55};
56
43struct sw_flow_key { 57struct sw_flow_key {
58 struct ovs_key_ipv4_tunnel tun_key; /* Encapsulating tunnel key. */
44 struct { 59 struct {
45 u32 priority; /* Packet QoS priority. */ 60 u32 priority; /* Packet QoS priority. */
46 u32 skb_mark; /* SKB mark. */ 61 u32 skb_mark; /* SKB mark. */
@@ -179,5 +194,9 @@ u32 ovs_flow_hash(const struct sw_flow_key *key, int key_len);
179 194
180struct sw_flow *ovs_flow_tbl_next(struct flow_table *table, u32 *bucket, u32 *idx); 195struct sw_flow *ovs_flow_tbl_next(struct flow_table *table, u32 *bucket, u32 *idx);
181extern const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1]; 196extern const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1];
197int ovs_ipv4_tun_from_nlattr(const struct nlattr *attr,
198 struct ovs_key_ipv4_tunnel *tun_key);
199int ovs_ipv4_tun_to_nlattr(struct sk_buff *skb,
200 const struct ovs_key_ipv4_tunnel *tun_key);
182 201
183#endif /* flow.h */ 202#endif /* flow.h */
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index e284c7e1fec4..98d3edbbc235 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -67,7 +67,7 @@ static struct rtnl_link_stats64 *internal_dev_get_stats(struct net_device *netde
67static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) 67static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
68{ 68{
69 rcu_read_lock(); 69 rcu_read_lock();
70 ovs_vport_receive(internal_dev_priv(netdev)->vport, skb); 70 ovs_vport_receive(internal_dev_priv(netdev)->vport, skb, NULL);
71 rcu_read_unlock(); 71 rcu_read_unlock();
72 return 0; 72 return 0;
73} 73}
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 40de815b4213..5982f3f62835 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -51,7 +51,7 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
51 skb_push(skb, ETH_HLEN); 51 skb_push(skb, ETH_HLEN);
52 ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN); 52 ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
53 53
54 ovs_vport_receive(vport, skb); 54 ovs_vport_receive(vport, skb, NULL);
55 return; 55 return;
56 56
57error: 57error:
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 176d449351eb..413287a1877f 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -325,7 +325,8 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
325 * Must be called with rcu_read_lock. The packet cannot be shared and 325 * Must be called with rcu_read_lock. The packet cannot be shared and
326 * skb->data should point to the Ethernet header. 326 * skb->data should point to the Ethernet header.
327 */ 327 */
328void ovs_vport_receive(struct vport *vport, struct sk_buff *skb) 328void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
329 struct ovs_key_ipv4_tunnel *tun_key)
329{ 330{
330 struct pcpu_tstats *stats; 331 struct pcpu_tstats *stats;
331 332
@@ -335,6 +336,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
335 stats->rx_bytes += skb->len; 336 stats->rx_bytes += skb->len;
336 u64_stats_update_end(&stats->syncp); 337 u64_stats_update_end(&stats->syncp);
337 338
339 OVS_CB(skb)->tun_key = tun_key;
338 ovs_dp_process_received_packet(vport, skb); 340 ovs_dp_process_received_packet(vport, skb);
339} 341}
340 342
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 293278c4c2df..2d961aedd71d 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -184,7 +184,8 @@ static inline struct vport *vport_from_priv(const void *priv)
184 return (struct vport *)(priv - ALIGN(sizeof(struct vport), VPORT_ALIGN)); 184 return (struct vport *)(priv - ALIGN(sizeof(struct vport), VPORT_ALIGN));
185} 185}
186 186
187void ovs_vport_receive(struct vport *, struct sk_buff *); 187void ovs_vport_receive(struct vport *, struct sk_buff *,
188 struct ovs_key_ipv4_tunnel *);
188void ovs_vport_record_error(struct vport *, enum vport_err_type err_type); 189void ovs_vport_record_error(struct vport *, enum vport_err_type err_type);
189 190
190/* List of statically compiled vport implementations. Don't forget to also 191/* List of statically compiled vport implementations. Don't forget to also