Commit a85311bf authored by Pravin B Shelar's avatar Pravin B Shelar

openvswitch: Avoid NULL mask check while building mask

OVS does mask validation even if it does not need to convert
netlink mask attributes to mask structure.  ovs_nla_get_match()
caller can pass NULL mask structure pointer if the caller does
not need mask.  Therefore NULL check is required in SW_FLOW_KEY*
macros.  Following patch does not convert mask netlink attributes
if mask pointer is NULL, so we do not need these checks in
SW_FLOW_KEY* macro.
Signed-off-by: default avatarPravin B Shelar <pshelar@nicira.com>
Acked-by: default avatarDaniele Di Proietto <ddiproietto@vmware.com>
Acked-by: default avatarAndy Zhou <azhou@nicira.com>
parent 2fdb957d
...@@ -50,21 +50,18 @@ ...@@ -50,21 +50,18 @@
#include "flow_netlink.h" #include "flow_netlink.h"
static void update_range__(struct sw_flow_match *match, static void update_range(struct sw_flow_match *match,
size_t offset, size_t size, bool is_mask) size_t offset, size_t size, bool is_mask)
{ {
struct sw_flow_key_range *range = NULL; struct sw_flow_key_range *range;
size_t start = rounddown(offset, sizeof(long)); size_t start = rounddown(offset, sizeof(long));
size_t end = roundup(offset + size, sizeof(long)); size_t end = roundup(offset + size, sizeof(long));
if (!is_mask) if (!is_mask)
range = &match->range; range = &match->range;
else if (match->mask) else
range = &match->mask->range; range = &match->mask->range;
if (!range)
return;
if (range->start == range->end) { if (range->start == range->end) {
range->start = start; range->start = start;
range->end = end; range->end = end;
...@@ -80,22 +77,20 @@ static void update_range__(struct sw_flow_match *match, ...@@ -80,22 +77,20 @@ static void update_range__(struct sw_flow_match *match,
#define SW_FLOW_KEY_PUT(match, field, value, is_mask) \ #define SW_FLOW_KEY_PUT(match, field, value, is_mask) \
do { \ do { \
update_range__(match, offsetof(struct sw_flow_key, field), \ update_range(match, offsetof(struct sw_flow_key, field), \
sizeof((match)->key->field), is_mask); \ sizeof((match)->key->field), is_mask); \
if (is_mask) { \ if (is_mask) \
if ((match)->mask) \ (match)->mask->key.field = value; \
(match)->mask->key.field = value; \ else \
} else { \
(match)->key->field = value; \ (match)->key->field = value; \
} \
} while (0) } while (0)
#define SW_FLOW_KEY_MEMCPY_OFFSET(match, offset, value_p, len, is_mask) \ #define SW_FLOW_KEY_MEMCPY_OFFSET(match, offset, value_p, len, is_mask) \
do { \ do { \
update_range__(match, offset, len, is_mask); \ update_range(match, offset, len, is_mask); \
if (is_mask) \ if (is_mask) \
memcpy((u8 *)&(match)->mask->key + offset, value_p, \ memcpy((u8 *)&(match)->mask->key + offset, value_p, \
len); \ len); \
else \ else \
memcpy((u8 *)(match)->key + offset, value_p, len); \ memcpy((u8 *)(match)->key + offset, value_p, len); \
} while (0) } while (0)
...@@ -104,18 +99,16 @@ static void update_range__(struct sw_flow_match *match, ...@@ -104,18 +99,16 @@ static void update_range__(struct sw_flow_match *match,
SW_FLOW_KEY_MEMCPY_OFFSET(match, offsetof(struct sw_flow_key, field), \ SW_FLOW_KEY_MEMCPY_OFFSET(match, offsetof(struct sw_flow_key, field), \
value_p, len, is_mask) value_p, len, is_mask)
#define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask) \ #define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask) \
do { \ do { \
update_range__(match, offsetof(struct sw_flow_key, field), \ update_range(match, offsetof(struct sw_flow_key, field), \
sizeof((match)->key->field), is_mask); \ sizeof((match)->key->field), is_mask); \
if (is_mask) { \ if (is_mask) \
if ((match)->mask) \ memset((u8 *)&(match)->mask->key.field, value, \
memset((u8 *)&(match)->mask->key.field, value,\ sizeof((match)->mask->key.field)); \
sizeof((match)->mask->key.field)); \ else \
} else { \
memset((u8 *)&(match)->key->field, value, \ memset((u8 *)&(match)->key->field, value, \
sizeof((match)->key->field)); \ sizeof((match)->key->field)); \
} \
} while (0) } while (0)
static bool match_validate(const struct sw_flow_match *match, static bool match_validate(const struct sw_flow_match *match,
...@@ -677,8 +670,7 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs, ...@@ -677,8 +670,7 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
SW_FLOW_KEY_PUT(match, eth.tci, tci, is_mask); SW_FLOW_KEY_PUT(match, eth.tci, tci, is_mask);
attrs &= ~(1 << OVS_KEY_ATTR_VLAN); attrs &= ~(1 << OVS_KEY_ATTR_VLAN);
} else if (!is_mask) }
SW_FLOW_KEY_PUT(match, eth.tci, htons(0xffff), true);
if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) { if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
__be16 eth_type; __be16 eth_type;
...@@ -903,8 +895,8 @@ static void mask_set_nlattr(struct nlattr *attr, u8 val) ...@@ -903,8 +895,8 @@ static void mask_set_nlattr(struct nlattr *attr, u8 val)
* attribute specifies the mask field of the wildcarded flow. * attribute specifies the mask field of the wildcarded flow.
*/ */
int ovs_nla_get_match(struct sw_flow_match *match, int ovs_nla_get_match(struct sw_flow_match *match,
const struct nlattr *key, const struct nlattr *nla_key,
const struct nlattr *mask) const struct nlattr *nla_mask)
{ {
const struct nlattr *a[OVS_KEY_ATTR_MAX + 1]; const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
const struct nlattr *encap; const struct nlattr *encap;
...@@ -914,7 +906,7 @@ int ovs_nla_get_match(struct sw_flow_match *match, ...@@ -914,7 +906,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
bool encap_valid = false; bool encap_valid = false;
int err; int err;
err = parse_flow_nlattrs(key, a, &key_attrs); err = parse_flow_nlattrs(nla_key, a, &key_attrs);
if (err) if (err)
return err; return err;
...@@ -955,36 +947,43 @@ int ovs_nla_get_match(struct sw_flow_match *match, ...@@ -955,36 +947,43 @@ int ovs_nla_get_match(struct sw_flow_match *match,
if (err) if (err)
return err; return err;
if (match->mask && !mask) { if (match->mask) {
/* Create an exact match mask. We need to set to 0xff all the if (!nla_mask) {
* 'match->mask' fields that have been touched in 'match->key'. /* Create an exact match mask. We need to set to 0xff
* We cannot simply memset 'match->mask', because padding bytes * all the 'match->mask' fields that have been touched
* and fields not specified in 'match->key' should be left to 0. * in 'match->key'. We cannot simply memset
* Instead, we use a stream of netlink attributes, copied from * 'match->mask', because padding bytes and fields not
* 'key' and set to 0xff: ovs_key_from_nlattrs() will take care * specified in 'match->key' should be left to 0.
* of filling 'match->mask' appropriately. * Instead, we use a stream of netlink attributes,
*/ * copied from 'key' and set to 0xff.
newmask = kmemdup(key, nla_total_size(nla_len(key)), * ovs_key_from_nlattrs() will take care of filling
GFP_KERNEL); * 'match->mask' appropriately.
if (!newmask) */
return -ENOMEM; newmask = kmemdup(nla_key,
nla_total_size(nla_len(nla_key)),
GFP_KERNEL);
if (!newmask)
return -ENOMEM;
mask_set_nlattr(newmask, 0xff); mask_set_nlattr(newmask, 0xff);
/* The userspace does not send tunnel attributes that are 0, /* The userspace does not send tunnel attributes that
* but we should not wildcard them nonetheless. * are 0, but we should not wildcard them nonetheless.
*/ */
if (match->key->tun_key.ipv4_dst) if (match->key->tun_key.ipv4_dst)
SW_FLOW_KEY_MEMSET_FIELD(match, tun_key, 0xff, true); SW_FLOW_KEY_MEMSET_FIELD(match, tun_key,
0xff, true);
mask = newmask; nla_mask = newmask;
} }
if (mask) { err = parse_flow_mask_nlattrs(nla_mask, a, &mask_attrs);
err = parse_flow_mask_nlattrs(mask, a, &mask_attrs);
if (err) if (err)
goto free_newmask; goto free_newmask;
/* Always match on tci. */
SW_FLOW_KEY_PUT(match, eth.tci, htons(0xffff), true);
if (mask_attrs & 1 << OVS_KEY_ATTR_ENCAP) { if (mask_attrs & 1 << OVS_KEY_ATTR_ENCAP) {
__be16 eth_type = 0; __be16 eth_type = 0;
__be16 tci = 0; __be16 tci = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment