@ -50,21 +50,18 @@
# include "flow_netlink.h"
static void update_range__ ( struct sw_flow_match * match ,
size_t offset , size_t size , bool is_mask )
static void update_range ( struct sw_flow_match * match ,
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 end = roundup ( offset + size , sizeof ( long ) ) ;
if ( ! is_mask )
range = & match - > range ;
else if ( match - > mask )
else
range = & match - > mask - > range ;
if ( ! range )
return ;
if ( range - > start = = range - > end ) {
range - > start = start ;
range - > end = end ;
@ -80,22 +77,20 @@ static void update_range__(struct sw_flow_match *match,
# define SW_FLOW_KEY_PUT(match, field, value, is_mask) \
do { \
update_range__ ( match , offsetof ( struct sw_flow_key , field ) , \
sizeof ( ( match ) - > key - > field ) , is_mask ) ; \
if ( is_mask ) { \
if ( ( match ) - > mask ) \
( match ) - > mask - > key . field = value ; \
} else { \
update_range ( match , offsetof ( struct sw_flow_key , field ) , \
sizeof ( ( match ) - > key - > field ) , is_mask ) ; \
if ( is_mask ) \
( match ) - > mask - > key . field = value ; \
else \
( match ) - > key - > field = value ; \
} \
} while ( 0 )
# define SW_FLOW_KEY_MEMCPY_OFFSET(match, offset, value_p, len, is_mask) \
do { \
update_range__ ( match , offset , len , is_mask ) ; \
update_range ( match , offset , len , is_mask ) ; \
if ( is_mask ) \
memcpy ( ( u8 * ) & ( match ) - > mask - > key + offset , value_p , \
len ) ; \
len ) ; \
else \
memcpy ( ( u8 * ) ( match ) - > key + offset , value_p , len ) ; \
} while ( 0 )
@ -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 ) , \
value_p , len , is_mask )
# define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask) \
do { \
update_range__ ( match , offsetof ( struct sw_flow_key , field ) , \
sizeof ( ( match ) - > key - > field ) , is_mask ) ; \
if ( is_mask ) { \
if ( ( match ) - > mask ) \
memset ( ( u8 * ) & ( match ) - > mask - > key . field , value , \
sizeof ( ( match ) - > mask - > key . field ) ) ; \
} else { \
# define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask) \
do { \
update_range ( match , offsetof ( struct sw_flow_key , field ) , \
sizeof ( ( match ) - > key - > field ) , is_mask ) ; \
if ( is_mask ) \
memset ( ( u8 * ) & ( match ) - > mask - > key . field , value , \
sizeof ( ( match ) - > mask - > key . field ) ) ; \
else \
memset ( ( u8 * ) & ( match ) - > key - > field , value , \
sizeof ( ( match ) - > key - > field ) ) ; \
} \
} while ( 0 )
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,
SW_FLOW_KEY_PUT ( match , eth . tci , tci , is_mask ) ;
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 ) ) {
__be16 eth_type ;
@ -903,8 +895,8 @@ static void mask_set_nlattr(struct nlattr *attr, u8 val)
* attribute specifies the mask field of the wildcarded flow .
*/
int ovs_nla_get_match ( struct sw_flow_match * match ,
const struct nlattr * key ,
const struct nlattr * mask )
const struct nlattr * nla_ key,
const struct nlattr * nla_ mask)
{
const struct nlattr * a [ OVS_KEY_ATTR_MAX + 1 ] ;
const struct nlattr * encap ;
@ -914,7 +906,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
bool encap_valid = false ;
int err ;
err = parse_flow_nlattrs ( key , a , & key_attrs ) ;
err = parse_flow_nlattrs ( nla_ key, a , & key_attrs ) ;
if ( err )
return err ;
@ -955,36 +947,43 @@ int ovs_nla_get_match(struct sw_flow_match *match,
if ( err )
return err ;
if ( match - > mask & & ! mask ) {
/* Create an exact match mask. We need to set to 0xff all the
* ' match - > mask ' fields that have been touched in ' match - > key ' .
* We cannot simply memset ' match - > mask ' , because padding bytes
* and fields not specified in ' match - > key ' should be left to 0.
* Instead , we use a stream of netlink attributes , copied from
* ' key ' and set to 0xff : ovs_key_from_nlattrs ( ) will take care
* of filling ' match - > mask ' appropriately .
*/
newmask = kmemdup ( key , nla_total_size ( nla_len ( key ) ) ,
GFP_KERNEL ) ;
if ( ! newmask )
return - ENOMEM ;
if ( match - > mask ) {
if ( ! nla_mask ) {
/* Create an exact match mask. We need to set to 0xff
* all the ' match - > mask ' fields that have been touched
* in ' match - > key ' . We cannot simply memset
* ' match - > mask ' , because padding bytes and fields not
* specified in ' match - > key ' should be left to 0.
* Instead , we use a stream of netlink attributes ,
* copied from ' key ' and set to 0xff .
* ovs_key_from_nlattrs ( ) will take care of filling
* ' match - > mask ' appropriately .
*/
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,
* but we should not wildcard them nonetheless .
*/
if ( match - > key - > tun_key . ipv4_dst )
SW_FLOW_KEY_MEMSET_FIELD ( match , tun_key , 0xff , true ) ;
/* The userspace does not send tunnel attributes that
* are 0 , but we should not wildcard them nonetheless .
*/
if ( match - > key - > tun_key . ipv4_dst )
SW_FLOW_KEY_MEMSET_FIELD ( match , tun_key ,
0xff , true ) ;
mask = newmask ;
}
nla_ mask = newmask ;
}
if ( mask ) {
err = parse_flow_mask_nlattrs ( mask , a , & mask_attrs ) ;
err = parse_flow_mask_nlattrs ( nla_mask , a , & mask_attrs ) ;
if ( err )
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 ) {
__be16 eth_type = 0 ;
__be16 tci = 0 ;