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 <pshelar@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
const struct nlattr *a)
{
struct sw_flow_key recirc_key;
const struct nlattr *a)
{
struct sw_flow_key recirc_key;
- uint32_t hash = OVS_CB(skb)->pkt_key->ovs_flow_hash;
- 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;
}
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);
ovs_dp_process_packet_with_key(skb, &recirc_key, true);
return key_extract(skb, key);
}
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);
+}
tun_info->options_len = opts_len;
}
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;
struct sw_flow_key {
u8 tun_opts[255];
u8 tun_opts_len;
int ovs_flow_key_extract_userspace(const struct nlattr *attr,
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);
memset(&match, 0, sizeof(match));
match.key = key;
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->phy.in_port = DP_MAX_PORTS;
- key->ovs_flow_hash = 0;
- key->recirc_id = 0;
return metadata_from_nlattrs(&match, &attrs, a, false);
}
return metadata_from_nlattrs(&match, &attrs, a, false);
}