From 7f45215aec6cefab34fef548fe464f2a361e2a6f Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Tue, 5 Aug 2014 13:43:45 -0700 Subject: [PATCH] datapath: Avoid using wrong metadata for recic action. Recirc action needs to extract flow key from packet, it uses tun_info from OVS_CB for setting tunnel meta data in flow key. But tun_info can be overwritten by tunnel send action. This would result in wrong flow key for the recirculation. Following patch copies flow-key meta data from OVS_CB packet key itself thus avoids this bug. Signed-off-by: Pravin B Shelar Acked-by: Andy Zhou --- datapath/actions.c | 6 ++---- datapath/flow.c | 10 ++++++++++ datapath/flow.h | 9 +++++++++ datapath/flow_netlink.c | 7 +------ 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/datapath/actions.c b/datapath/actions.c index 5a0bfa9d3..6de65d398 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -649,17 +649,15 @@ static int execute_recirc(struct datapath *dp, struct sk_buff *skb, const struct nlattr *a) { struct sw_flow_key recirc_key; - uint32_t hash = OVS_CB(skb)->pkt_key->ovs_flow_hash; int err; - err = ovs_flow_key_extract(skb, &recirc_key); + err = ovs_flow_key_extract_recirc(nla_get_u32(a), OVS_CB(skb)->pkt_key, + skb, &recirc_key); if (err) { kfree_skb(skb); return err; } - recirc_key.ovs_flow_hash = hash; - recirc_key.recirc_id = nla_get_u32(a); ovs_dp_process_packet_with_key(skb, &recirc_key, true); diff --git a/datapath/flow.c b/datapath/flow.c index 7fdce6af5..1feca8567 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -718,3 +718,13 @@ int ovs_flow_key_extract_userspace(const struct nlattr *attr, return key_extract(skb, key); } + +int ovs_flow_key_extract_recirc(u32 recirc_id, + const struct sw_flow_key *key, + struct sk_buff *skb, + struct sw_flow_key *new_key) +{ + memcpy(new_key, key, OVS_SW_FLOW_KEY_METADATA_SIZE); + new_key->recirc_id = recirc_id; + return key_extract(skb, new_key); +} diff --git a/datapath/flow.h b/datapath/flow.h index 69664cd94..ee63b8b5a 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -87,6 +87,11 @@ static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info, tun_info->options_len = opts_len; } +#define OVS_SW_FLOW_KEY_METADATA_SIZE \ + (offsetof(struct sw_flow_key, recirc_id) + \ + FIELD_SIZEOF(struct sw_flow_key, recirc_id)) + + struct sw_flow_key { u8 tun_opts[255]; u8 tun_opts_len; @@ -222,5 +227,9 @@ int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key); int ovs_flow_key_extract_userspace(const struct nlattr *attr, struct sk_buff *skb, struct sw_flow_key *key); +int ovs_flow_key_extract_recirc(u32 recirc_id, + const struct sw_flow_key *key, + struct sk_buff *skb, + struct sw_flow_key *new_key); #endif /* flow.h */ diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index ada21aece..75172dede 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -1016,13 +1016,8 @@ int ovs_nla_get_flow_metadata(const struct nlattr *attr, memset(&match, 0, sizeof(match)); match.key = key; - key->tun_opts_len = 0; - memset(&key->tun_key, 0, sizeof(key->tun_key)); - key->phy.priority = 0; - key->phy.skb_mark = 0; + memset(key, 0, OVS_SW_FLOW_KEY_METADATA_SIZE); key->phy.in_port = DP_MAX_PORTS; - key->ovs_flow_hash = 0; - key->recirc_id = 0; return metadata_from_nlattrs(&match, &attrs, a, false); } -- 2.20.1