Signed-off-by: Jarno Rajahalme <jarno.rajaha...@nsn.com> --- datapath/datapath.c | 19 ++++++++++++++++++- datapath/flow.c | 15 +++++++++++++-- datapath/flow.h | 5 +++-- 3 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/datapath/datapath.c b/datapath/datapath.c index 2e01740..81b1d53 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -374,8 +374,9 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex, len = sizeof(struct ovs_header); len += nla_total_size(skb->len); len += nla_total_size(FLOW_BUFSIZE); + len += 3 * nla_total_size(4); /* packet offsets */ if (upcall_info->cmd == OVS_PACKET_CMD_ACTION) - len += nla_total_size(8); + len += nla_total_size(8); /* possible USERDATA */ user_skb = genlmsg_new(len, GFP_ATOMIC); if (!user_skb) { @@ -391,6 +392,22 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex, ovs_flow_key_to_nlattrs(upcall_info->key, user_skb); nla_nest_end(user_skb, nla); + { + u32 l3_offset = skb_network_offset(skb); + u32 l4_offset = skb_transport_offset(skb); + + nla_put_u32(user_skb, OVS_PACKET_ATTR_L2_SIZE, l3_offset); + nla_put_u32(user_skb, OVS_PACKET_ATTR_L3_OFFSET, l3_offset); + + /* Set the L4 offset attribute only if transport offset is + * valid. */ + if ((upcall_info->key->eth.type == htons(ETH_P_IP) + || upcall_info->key->eth.type == htons(ETH_P_IPV6)) + && l4_offset > l3_offset) + nla_put_u32(user_skb, OVS_PACKET_ATTR_L4_OFFSET, + l4_offset); + } + if (upcall_info->userdata) nla_put_u64(user_skb, OVS_PACKET_ATTR_USERDATA, nla_get_u64(upcall_info->userdata)); diff --git a/datapath/flow.c b/datapath/flow.c index 4c85e81..e3185aa 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -856,6 +856,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { /* Not upstream. */ [OVS_KEY_ATTR_TUN_ID] = sizeof(__be64), + [OVS_KEY_ATTR_HASH] = sizeof(u32), }; static int ipv4_flow_from_nlattrs(struct sw_flow_key *swkey, @@ -1279,11 +1280,17 @@ int ovs_flow_key_from_nlattrs(struct sw_flow_key *swkey, memcpy(swkey->ipv4.arp.tha, arp_key->arp_tha, ETH_ALEN); } + /* Userspace provides the hash back to us only when the key + * has been unmodified. */ + if (attrs & (1ULL << OVS_KEY_ATTR_HASH)) { + swkey->hash = nla_get_u32(a[OVS_KEY_ATTR_HASH]); + attrs &= ~(1ULL << OVS_KEY_ATTR_HASH); + } else + swkey->hash = ovs_flow_hash(swkey, flow_key_start(swkey)); + if (attrs) return -EINVAL; - swkey->hash = ovs_flow_hash(swkey, flow_key_start(swkey)); - return 0; } @@ -1389,6 +1396,10 @@ int ovs_flow_key_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb struct ovs_key_ethernet *eth_key; struct nlattr *nla, *encap; + /* Put hash first so that it is easy to find or ignore */ + if (nla_put_u32(skb, OVS_KEY_ATTR_HASH, swkey->hash)) + goto nla_put_failure; + if (swkey->phy.priority && nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority)) goto nla_put_failure; diff --git a/datapath/flow.h b/datapath/flow.h index dc9c000..5491fd0 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -187,10 +187,11 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); * OVS_KEY_ATTR_IPV6 40 -- 4 44 * OVS_KEY_ATTR_ICMPV6 2 2 4 8 * OVS_KEY_ATTR_ND 28 -- 4 32 + * OVS_KEY_ATTR_HASH 4 -- 4 8 * ---------------------------------------------------------- - * total 220 + * total 228 */ -#define FLOW_BUFSIZE 220 +#define FLOW_BUFSIZE 228 int ovs_flow_key_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); int ovs_flow_key_from_nlattrs(struct sw_flow_key *, -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev