summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/openvswitch/datapath.c2
-rw-r--r--net/openvswitch/flow.c21
-rw-r--r--net/openvswitch/flow.h2
3 files changed, 14 insertions, 11 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 2aa13bd7f2b2..aa0a5f2794f1 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1266,7 +1266,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(acts))
goto error;
- ovs_flow_key_mask(&masked_key, &key, &mask);
+ ovs_flow_key_mask(&masked_key, &key, true, &mask);
error = validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS],
&masked_key, 0, &acts);
if (error) {
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 410db90db73d..b5d58cfa4fdc 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -373,18 +373,21 @@ static bool icmp6hdr_ok(struct sk_buff *skb)
}
void ovs_flow_key_mask(struct sw_flow_key *dst, const struct sw_flow_key *src,
- const struct sw_flow_mask *mask)
+ bool full, const struct sw_flow_mask *mask)
{
- const long *m = (long *)((u8 *)&mask->key + mask->range.start);
- const long *s = (long *)((u8 *)src + mask->range.start);
- long *d = (long *)((u8 *)dst + mask->range.start);
+ int start = full ? 0 : mask->range.start;
+ int len = full ? sizeof *dst : range_n_bytes(&mask->range);
+ const long *m = (const long *)((const u8 *)&mask->key + start);
+ const long *s = (const long *)((const u8 *)src + start);
+ long *d = (long *)((u8 *)dst + start);
int i;
- /* The memory outside of the 'mask->range' are not set since
- * further operations on 'dst' only uses contents within
- * 'mask->range'.
+ /* If 'full' is true then all of 'dst' is fully initialized. Otherwise,
+ * if 'full' is false the memory outside of the 'mask->range' is left
+ * uninitialized. This can be used as an optimization when further
+ * operations on 'dst' only use contents within 'mask->range'.
*/
- for (i = 0; i < range_n_bytes(&mask->range); i += sizeof(long))
+ for (i = 0; i < len; i += sizeof(long))
*d++ = *s++ & *m++;
}
@@ -1085,7 +1088,7 @@ static struct sw_flow *ovs_masked_flow_lookup(struct flow_table *table,
u32 hash;
struct sw_flow_key masked_key;
- ovs_flow_key_mask(&masked_key, unmasked, mask);
+ ovs_flow_key_mask(&masked_key, unmasked, false, mask);
hash = ovs_flow_hash(&masked_key, key_start, key_end);
head = find_bucket(table, hash);
hlist_for_each_entry_rcu(flow, head, hash_node[table->node_ver]) {
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 212fbf7510c4..a5da8e1ab854 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -255,5 +255,5 @@ void ovs_sw_flow_mask_insert(struct flow_table *, struct sw_flow_mask *);
struct sw_flow_mask *ovs_sw_flow_mask_find(const struct flow_table *,
const struct sw_flow_mask *);
void ovs_flow_key_mask(struct sw_flow_key *dst, const struct sw_flow_key *src,
- const struct sw_flow_mask *mask);
+ bool full, const struct sw_flow_mask *mask);
#endif /* flow.h */