openvswitch: Per cpu flow stats.
With mega flow implementation ovs flow can be shared between multiple CPUs which makes stats updates highly contended operation. This patch uses per-CPU stats in cases where a flow is likely to be shared (if there is a wildcard in the 5-tuple and therefore likely to be spread by RSS). In other situations, it uses the current strategy, saving memory and allocation time. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: Jesse Gross <jesse@nicira.com>
This commit is contained in:
committed by
Jesse Gross
parent
795449d8b8
commit
e298e50570
@@ -266,6 +266,20 @@ static bool is_all_zero(const u8 *fp, size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_all_set(const u8 *fp, size_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
if (fp[i] != 0xff)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int __parse_flow_nlattrs(const struct nlattr *attr,
|
||||
const struct nlattr *a[],
|
||||
u64 *attrsp, bool nz)
|
||||
@@ -487,8 +501,9 @@ static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
const struct nlattr **a, bool is_mask)
|
||||
static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple,
|
||||
u64 attrs, const struct nlattr **a,
|
||||
bool is_mask)
|
||||
{
|
||||
int err;
|
||||
u64 orig_attrs = attrs;
|
||||
@@ -545,6 +560,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
|
||||
}
|
||||
|
||||
if (is_mask && exact_5tuple) {
|
||||
if (match->mask->key.eth.type != htons(0xffff))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
|
||||
const struct ovs_key_ipv4 *ipv4_key;
|
||||
|
||||
@@ -567,6 +587,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
|
||||
ipv4_key->ipv4_dst, is_mask);
|
||||
attrs &= ~(1 << OVS_KEY_ATTR_IPV4);
|
||||
|
||||
if (is_mask && exact_5tuple && *exact_5tuple) {
|
||||
if (ipv4_key->ipv4_proto != 0xff ||
|
||||
ipv4_key->ipv4_src != htonl(0xffffffff) ||
|
||||
ipv4_key->ipv4_dst != htonl(0xffffffff))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
|
||||
@@ -598,6 +625,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
is_mask);
|
||||
|
||||
attrs &= ~(1 << OVS_KEY_ATTR_IPV6);
|
||||
|
||||
if (is_mask && exact_5tuple && *exact_5tuple) {
|
||||
if (ipv6_key->ipv6_proto != 0xff ||
|
||||
!is_all_set((u8 *)ipv6_key->ipv6_src, sizeof(match->key->ipv6.addr.src)) ||
|
||||
!is_all_set((u8 *)ipv6_key->ipv6_dst, sizeof(match->key->ipv6.addr.dst)))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_ARP)) {
|
||||
@@ -640,6 +674,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
tcp_key->tcp_dst, is_mask);
|
||||
}
|
||||
attrs &= ~(1 << OVS_KEY_ATTR_TCP);
|
||||
|
||||
if (is_mask && exact_5tuple && *exact_5tuple &&
|
||||
(tcp_key->tcp_src != htons(0xffff) ||
|
||||
tcp_key->tcp_dst != htons(0xffff)))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) {
|
||||
@@ -671,6 +710,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
udp_key->udp_dst, is_mask);
|
||||
}
|
||||
attrs &= ~(1 << OVS_KEY_ATTR_UDP);
|
||||
|
||||
if (is_mask && exact_5tuple && *exact_5tuple &&
|
||||
(udp_key->udp_src != htons(0xffff) ||
|
||||
udp_key->udp_dst != htons(0xffff)))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_SCTP)) {
|
||||
@@ -756,6 +800,7 @@ static void sw_flow_mask_set(struct sw_flow_mask *mask,
|
||||
* attribute specifies the mask field of the wildcarded flow.
|
||||
*/
|
||||
int ovs_nla_get_match(struct sw_flow_match *match,
|
||||
bool *exact_5tuple,
|
||||
const struct nlattr *key,
|
||||
const struct nlattr *mask)
|
||||
{
|
||||
@@ -803,10 +848,13 @@ int ovs_nla_get_match(struct sw_flow_match *match,
|
||||
}
|
||||
}
|
||||
|
||||
err = ovs_key_from_nlattrs(match, key_attrs, a, false);
|
||||
err = ovs_key_from_nlattrs(match, NULL, key_attrs, a, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (exact_5tuple)
|
||||
*exact_5tuple = true;
|
||||
|
||||
if (mask) {
|
||||
err = parse_flow_mask_nlattrs(mask, a, &mask_attrs);
|
||||
if (err)
|
||||
@@ -844,7 +892,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
|
||||
}
|
||||
}
|
||||
|
||||
err = ovs_key_from_nlattrs(match, mask_attrs, a, true);
|
||||
err = ovs_key_from_nlattrs(match, exact_5tuple, mask_attrs, a, true);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user