|
@@ -281,7 +281,7 @@ size_t ovs_key_attr_size(void)
|
|
/* Whenever adding new OVS_KEY_ FIELDS, we should consider
|
|
/* Whenever adding new OVS_KEY_ FIELDS, we should consider
|
|
* updating this function.
|
|
* updating this function.
|
|
*/
|
|
*/
|
|
- BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 22);
|
|
|
|
|
|
+ BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 24);
|
|
|
|
|
|
return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
|
|
return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
|
|
+ nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
|
|
+ nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
|
|
@@ -290,6 +290,8 @@ size_t ovs_key_attr_size(void)
|
|
+ nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
|
|
+ nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
|
|
+ nla_total_size(4) /* OVS_KEY_ATTR_DP_HASH */
|
|
+ nla_total_size(4) /* OVS_KEY_ATTR_DP_HASH */
|
|
+ nla_total_size(4) /* OVS_KEY_ATTR_RECIRC_ID */
|
|
+ nla_total_size(4) /* OVS_KEY_ATTR_RECIRC_ID */
|
|
|
|
+ + nla_total_size(1) /* OVS_KEY_ATTR_CT_STATE */
|
|
|
|
+ + nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */
|
|
+ nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
|
|
+ nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
|
|
+ nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
|
|
+ nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
|
|
+ nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
|
|
+ nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
|
|
@@ -339,6 +341,8 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
|
|
[OVS_KEY_ATTR_TUNNEL] = { .len = OVS_ATTR_NESTED,
|
|
[OVS_KEY_ATTR_TUNNEL] = { .len = OVS_ATTR_NESTED,
|
|
.next = ovs_tunnel_key_lens, },
|
|
.next = ovs_tunnel_key_lens, },
|
|
[OVS_KEY_ATTR_MPLS] = { .len = sizeof(struct ovs_key_mpls) },
|
|
[OVS_KEY_ATTR_MPLS] = { .len = sizeof(struct ovs_key_mpls) },
|
|
|
|
+ [OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u8) },
|
|
|
|
+ [OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) },
|
|
};
|
|
};
|
|
|
|
|
|
static bool is_all_zero(const u8 *fp, size_t size)
|
|
static bool is_all_zero(const u8 *fp, size_t size)
|
|
@@ -768,6 +772,21 @@ static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
*attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
|
|
*attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
|
|
|
|
+ ovs_ct_verify(OVS_KEY_ATTR_CT_STATE)) {
|
|
|
|
+ u8 ct_state = nla_get_u8(a[OVS_KEY_ATTR_CT_STATE]);
|
|
|
|
+
|
|
|
|
+ SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask);
|
|
|
|
+ *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
|
|
|
|
+ }
|
|
|
|
+ if (*attrs & (1 << OVS_KEY_ATTR_CT_ZONE) &&
|
|
|
|
+ ovs_ct_verify(OVS_KEY_ATTR_CT_ZONE)) {
|
|
|
|
+ u16 ct_zone = nla_get_u16(a[OVS_KEY_ATTR_CT_ZONE]);
|
|
|
|
+
|
|
|
|
+ SW_FLOW_KEY_PUT(match, ct.zone, ct_zone, is_mask);
|
|
|
|
+ *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ZONE);
|
|
|
|
+ }
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1266,6 +1285,7 @@ int ovs_nla_get_flow_metadata(const struct nlattr *attr,
|
|
memset(&match, 0, sizeof(match));
|
|
memset(&match, 0, sizeof(match));
|
|
match.key = key;
|
|
match.key = key;
|
|
|
|
|
|
|
|
+ memset(&key->ct, 0, sizeof(key->ct));
|
|
key->phy.in_port = DP_MAX_PORTS;
|
|
key->phy.in_port = DP_MAX_PORTS;
|
|
|
|
|
|
return metadata_from_nlattrs(&match, &attrs, a, false, log);
|
|
return metadata_from_nlattrs(&match, &attrs, a, false, log);
|
|
@@ -1314,6 +1334,9 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
|
|
if (nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, output->phy.skb_mark))
|
|
if (nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, output->phy.skb_mark))
|
|
goto nla_put_failure;
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
+ if (ovs_ct_put_key(output, skb))
|
|
|
|
+ goto nla_put_failure;
|
|
|
|
+
|
|
nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
|
|
nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
|
|
if (!nla)
|
|
if (!nla)
|
|
goto nla_put_failure;
|
|
goto nla_put_failure;
|
|
@@ -1574,6 +1597,9 @@ void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
|
|
case OVS_ACTION_ATTR_SET:
|
|
case OVS_ACTION_ATTR_SET:
|
|
ovs_nla_free_set_action(a);
|
|
ovs_nla_free_set_action(a);
|
|
break;
|
|
break;
|
|
|
|
+ case OVS_ACTION_ATTR_CT:
|
|
|
|
+ ovs_ct_free_action(a);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1647,8 +1673,8 @@ static struct nlattr *__add_action(struct sw_flow_actions **sfa,
|
|
return a;
|
|
return a;
|
|
}
|
|
}
|
|
|
|
|
|
-static int add_action(struct sw_flow_actions **sfa, int attrtype,
|
|
|
|
- void *data, int len, bool log)
|
|
|
|
|
|
+int ovs_nla_add_action(struct sw_flow_actions **sfa, int attrtype, void *data,
|
|
|
|
+ int len, bool log)
|
|
{
|
|
{
|
|
struct nlattr *a;
|
|
struct nlattr *a;
|
|
|
|
|
|
@@ -1663,7 +1689,7 @@ static inline int add_nested_action_start(struct sw_flow_actions **sfa,
|
|
int used = (*sfa)->actions_len;
|
|
int used = (*sfa)->actions_len;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
- err = add_action(sfa, attrtype, NULL, 0, log);
|
|
|
|
|
|
+ err = ovs_nla_add_action(sfa, attrtype, NULL, 0, log);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
@@ -1679,12 +1705,12 @@ static inline void add_nested_action_end(struct sw_flow_actions *sfa,
|
|
a->nla_len = sfa->actions_len - st_offset;
|
|
a->nla_len = sfa->actions_len - st_offset;
|
|
}
|
|
}
|
|
|
|
|
|
-static int __ovs_nla_copy_actions(const struct nlattr *attr,
|
|
|
|
|
|
+static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
|
|
const struct sw_flow_key *key,
|
|
const struct sw_flow_key *key,
|
|
int depth, struct sw_flow_actions **sfa,
|
|
int depth, struct sw_flow_actions **sfa,
|
|
__be16 eth_type, __be16 vlan_tci, bool log);
|
|
__be16 eth_type, __be16 vlan_tci, bool log);
|
|
|
|
|
|
-static int validate_and_copy_sample(const struct nlattr *attr,
|
|
|
|
|
|
+static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
|
|
const struct sw_flow_key *key, int depth,
|
|
const struct sw_flow_key *key, int depth,
|
|
struct sw_flow_actions **sfa,
|
|
struct sw_flow_actions **sfa,
|
|
__be16 eth_type, __be16 vlan_tci, bool log)
|
|
__be16 eth_type, __be16 vlan_tci, bool log)
|
|
@@ -1716,15 +1742,15 @@ static int validate_and_copy_sample(const struct nlattr *attr,
|
|
start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE, log);
|
|
start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE, log);
|
|
if (start < 0)
|
|
if (start < 0)
|
|
return start;
|
|
return start;
|
|
- err = add_action(sfa, OVS_SAMPLE_ATTR_PROBABILITY,
|
|
|
|
- nla_data(probability), sizeof(u32), log);
|
|
|
|
|
|
+ err = ovs_nla_add_action(sfa, OVS_SAMPLE_ATTR_PROBABILITY,
|
|
|
|
+ nla_data(probability), sizeof(u32), log);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
st_acts = add_nested_action_start(sfa, OVS_SAMPLE_ATTR_ACTIONS, log);
|
|
st_acts = add_nested_action_start(sfa, OVS_SAMPLE_ATTR_ACTIONS, log);
|
|
if (st_acts < 0)
|
|
if (st_acts < 0)
|
|
return st_acts;
|
|
return st_acts;
|
|
|
|
|
|
- err = __ovs_nla_copy_actions(actions, key, depth + 1, sfa,
|
|
|
|
|
|
+ err = __ovs_nla_copy_actions(net, actions, key, depth + 1, sfa,
|
|
eth_type, vlan_tci, log);
|
|
eth_type, vlan_tci, log);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
@@ -2058,7 +2084,7 @@ static int copy_action(const struct nlattr *from,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int __ovs_nla_copy_actions(const struct nlattr *attr,
|
|
|
|
|
|
+static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
|
|
const struct sw_flow_key *key,
|
|
const struct sw_flow_key *key,
|
|
int depth, struct sw_flow_actions **sfa,
|
|
int depth, struct sw_flow_actions **sfa,
|
|
__be16 eth_type, __be16 vlan_tci, bool log)
|
|
__be16 eth_type, __be16 vlan_tci, bool log)
|
|
@@ -2082,7 +2108,8 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr,
|
|
[OVS_ACTION_ATTR_SET] = (u32)-1,
|
|
[OVS_ACTION_ATTR_SET] = (u32)-1,
|
|
[OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
|
|
[OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
|
|
[OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
|
|
[OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
|
|
- [OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash)
|
|
|
|
|
|
+ [OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
|
|
|
|
+ [OVS_ACTION_ATTR_CT] = (u32)-1,
|
|
};
|
|
};
|
|
const struct ovs_action_push_vlan *vlan;
|
|
const struct ovs_action_push_vlan *vlan;
|
|
int type = nla_type(a);
|
|
int type = nla_type(a);
|
|
@@ -2189,13 +2216,20 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr,
|
|
break;
|
|
break;
|
|
|
|
|
|
case OVS_ACTION_ATTR_SAMPLE:
|
|
case OVS_ACTION_ATTR_SAMPLE:
|
|
- err = validate_and_copy_sample(a, key, depth, sfa,
|
|
|
|
|
|
+ err = validate_and_copy_sample(net, a, key, depth, sfa,
|
|
eth_type, vlan_tci, log);
|
|
eth_type, vlan_tci, log);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
skip_copy = true;
|
|
skip_copy = true;
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case OVS_ACTION_ATTR_CT:
|
|
|
|
+ err = ovs_ct_copy_action(net, a, key, sfa, log);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+ skip_copy = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
OVS_NLERR(log, "Unknown Action type %d", type);
|
|
OVS_NLERR(log, "Unknown Action type %d", type);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -2214,7 +2248,7 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr,
|
|
}
|
|
}
|
|
|
|
|
|
/* 'key' must be the masked key. */
|
|
/* 'key' must be the masked key. */
|
|
-int ovs_nla_copy_actions(const struct nlattr *attr,
|
|
|
|
|
|
+int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
|
|
const struct sw_flow_key *key,
|
|
const struct sw_flow_key *key,
|
|
struct sw_flow_actions **sfa, bool log)
|
|
struct sw_flow_actions **sfa, bool log)
|
|
{
|
|
{
|
|
@@ -2225,7 +2259,7 @@ int ovs_nla_copy_actions(const struct nlattr *attr,
|
|
return PTR_ERR(*sfa);
|
|
return PTR_ERR(*sfa);
|
|
|
|
|
|
(*sfa)->orig_len = nla_len(attr);
|
|
(*sfa)->orig_len = nla_len(attr);
|
|
- err = __ovs_nla_copy_actions(attr, key, 0, sfa, key->eth.type,
|
|
|
|
|
|
+ err = __ovs_nla_copy_actions(net, attr, key, 0, sfa, key->eth.type,
|
|
key->eth.tci, log);
|
|
key->eth.tci, log);
|
|
if (err)
|
|
if (err)
|
|
ovs_nla_free_flow_actions(*sfa);
|
|
ovs_nla_free_flow_actions(*sfa);
|
|
@@ -2350,6 +2384,13 @@ int ovs_nla_put_actions(const struct nlattr *attr, int len, struct sk_buff *skb)
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
break;
|
|
break;
|
|
|
|
+
|
|
|
|
+ case OVS_ACTION_ATTR_CT:
|
|
|
|
+ err = ovs_ct_action_to_attr(nla_data(a), skb);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
if (nla_put(skb, type, nla_len(a), nla_data(a)))
|
|
if (nla_put(skb, type, nla_len(a), nla_data(a)))
|
|
return -EMSGSIZE;
|
|
return -EMSGSIZE;
|