diff options
Diffstat (limited to 'net/sched/em_meta.c')
| -rw-r--r-- | net/sched/em_meta.c | 237 | 
1 files changed, 159 insertions, 78 deletions
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 34da5e29ea1..9b8c0b0e60d 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -47,7 +47,7 @@   * 	on the meta type. Obviously, the length of the data must also   * 	be provided for non-numeric types.   * - * 	Additionaly, type dependant modifiers such as shift operators + * 	Additionally, type dependent modifiers such as shift operators   * 	or mask may be applied to extend the functionaliy. As of now,   * 	the variable length type supports shifting the byte string to   * 	the right, eating up any number of octets and thus supporting @@ -73,21 +73,18 @@  #include <net/pkt_cls.h>  #include <net/sock.h> -struct meta_obj -{ +struct meta_obj {  	unsigned long		value;  	unsigned int		len;  }; -struct meta_value -{ +struct meta_value {  	struct tcf_meta_val	hdr;  	unsigned long		val;  	unsigned int		len;  }; -struct meta_match -{ +struct meta_match {  	struct meta_value	lvalue;  	struct meta_value	rvalue;  }; @@ -225,7 +222,7 @@ META_COLLECTOR(int_maclen)  META_COLLECTOR(int_rxhash)  { -	dst->value = skb_get_rxhash(skb); +	dst->value = skb_get_hash(skb);  }  /************************************************************************** @@ -255,7 +252,7 @@ META_COLLECTOR(int_rtclassid)  	if (unlikely(skb_dst(skb) == NULL))  		*err = -1;  	else -#ifdef CONFIG_NET_CLS_ROUTE +#ifdef CONFIG_IP_ROUTE_CLASSID  		dst->value = skb_dst(skb)->tclassid;  #else  		dst->value = 0; @@ -267,47 +264,59 @@ META_COLLECTOR(int_rtiif)  	if (unlikely(skb_rtable(skb) == NULL))  		*err = -1;  	else -		dst->value = skb_rtable(skb)->fl.iif; +		dst->value = inet_iif(skb);  }  /**************************************************************************   * Socket Attributes   **************************************************************************/ -#define SKIP_NONLOCAL(skb)			\ -	if (unlikely(skb->sk == NULL)) {	\ -		*err = -1;			\ -		return;				\ -	} +#define skip_nonlocal(skb) \ +	(unlikely(skb->sk == NULL))  META_COLLECTOR(int_sk_family)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_family;  }  META_COLLECTOR(int_sk_state)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_state;  }  META_COLLECTOR(int_sk_reuse)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_reuse;  }  META_COLLECTOR(int_sk_bound_if)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	/* No error if bound_dev_if is 0, legal userspace check */  	dst->value = skb->sk->sk_bound_dev_if;  }  META_COLLECTOR(var_sk_bound_if)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	if (skb->sk->sk_bound_dev_if == 0) {  		dst->value = (unsigned long) "any"; @@ -325,157 +334,226 @@ META_COLLECTOR(var_sk_bound_if)  META_COLLECTOR(int_sk_refcnt)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = atomic_read(&skb->sk->sk_refcnt);  }  META_COLLECTOR(int_sk_rcvbuf)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_rcvbuf;  }  META_COLLECTOR(int_sk_shutdown)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_shutdown;  }  META_COLLECTOR(int_sk_proto)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_protocol;  }  META_COLLECTOR(int_sk_type)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_type;  }  META_COLLECTOR(int_sk_rmem_alloc)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = sk_rmem_alloc_get(skb->sk);  }  META_COLLECTOR(int_sk_wmem_alloc)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = sk_wmem_alloc_get(skb->sk);  }  META_COLLECTOR(int_sk_omem_alloc)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = atomic_read(&skb->sk->sk_omem_alloc);  }  META_COLLECTOR(int_sk_rcv_qlen)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_receive_queue.qlen;  }  META_COLLECTOR(int_sk_snd_qlen)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_write_queue.qlen;  }  META_COLLECTOR(int_sk_wmem_queued)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_wmem_queued;  }  META_COLLECTOR(int_sk_fwd_alloc)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_forward_alloc;  }  META_COLLECTOR(int_sk_sndbuf)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_sndbuf;  }  META_COLLECTOR(int_sk_alloc)  { -	SKIP_NONLOCAL(skb); -	dst->value = skb->sk->sk_allocation; -} - -META_COLLECTOR(int_sk_route_caps) -{ -	SKIP_NONLOCAL(skb); -	dst->value = skb->sk->sk_route_caps; +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	} +	dst->value = (__force int) skb->sk->sk_allocation;  }  META_COLLECTOR(int_sk_hash)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_hash;  }  META_COLLECTOR(int_sk_lingertime)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_lingertime / HZ;  }  META_COLLECTOR(int_sk_err_qlen)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_error_queue.qlen;  }  META_COLLECTOR(int_sk_ack_bl)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_ack_backlog;  }  META_COLLECTOR(int_sk_max_ack_bl)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_max_ack_backlog;  }  META_COLLECTOR(int_sk_prio)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_priority;  }  META_COLLECTOR(int_sk_rcvlowat)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_rcvlowat;  }  META_COLLECTOR(int_sk_rcvtimeo)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_rcvtimeo / HZ;  }  META_COLLECTOR(int_sk_sndtimeo)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_sndtimeo / HZ;  }  META_COLLECTOR(int_sk_sendmsg_off)  { -	SKIP_NONLOCAL(skb); -	dst->value = skb->sk->sk_sndmsg_off; +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	} +	dst->value = skb->sk->sk_frag.offset;  }  META_COLLECTOR(int_sk_write_pend)  { -	SKIP_NONLOCAL(skb); +	if (skip_nonlocal(skb)) { +		*err = -1; +		return; +	}  	dst->value = skb->sk->sk_write_pending;  } @@ -483,8 +561,7 @@ META_COLLECTOR(int_sk_write_pend)   * Meta value collectors assignment table   **************************************************************************/ -struct meta_ops -{ +struct meta_ops {  	void		(*get)(struct sk_buff *, struct tcf_pkt_info *,  			       struct meta_value *, struct meta_obj *, int *);  }; @@ -494,7 +571,7 @@ struct meta_ops  /* Meta value operations table listing all meta value collectors and   * assigns them to a type and meta id. */ -static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { +static struct meta_ops __meta_ops[TCF_META_TYPE_MAX + 1][TCF_META_ID_MAX + 1] = {  	[TCF_META_TYPE_VAR] = {  		[META_ID(DEV)]			= META_FUNC(var_dev),  		[META_ID(SK_BOUND_IF)] 		= META_FUNC(var_sk_bound_if), @@ -534,7 +611,6 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {  		[META_ID(SK_ERR_QLEN)]		= META_FUNC(int_sk_err_qlen),  		[META_ID(SK_FORWARD_ALLOCS)]	= META_FUNC(int_sk_fwd_alloc),  		[META_ID(SK_ALLOCS)]		= META_FUNC(int_sk_alloc), -		[META_ID(SK_ROUTE_CAPS)]	= META_FUNC(int_sk_route_caps),  		[META_ID(SK_HASH)]		= META_FUNC(int_sk_hash),  		[META_ID(SK_LINGERTIME)]	= META_FUNC(int_sk_lingertime),  		[META_ID(SK_ACK_BACKLOG)]	= META_FUNC(int_sk_ack_bl), @@ -550,7 +626,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {  	}  }; -static inline struct meta_ops * meta_ops(struct meta_value *val) +static inline struct meta_ops *meta_ops(struct meta_value *val)  {  	return &__meta_ops[meta_type(val)][meta_id(val)];  } @@ -596,8 +672,9 @@ static void meta_var_apply_extras(struct meta_value *v,  static int meta_var_dump(struct sk_buff *skb, struct meta_value *v, int tlv)  { -	if (v->val && v->len) -		NLA_PUT(skb, tlv, v->len, (void *) v->val); +	if (v->val && v->len && +	    nla_put(skb, tlv, v->len, (void *) v->val)) +		goto nla_put_failure;  	return 0;  nla_put_failure: @@ -647,10 +724,12 @@ static void meta_int_apply_extras(struct meta_value *v,  static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv)  { -	if (v->len == sizeof(unsigned long)) -		NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val); -	else if (v->len == sizeof(u32)) { -		NLA_PUT_U32(skb, tlv, v->val); +	if (v->len == sizeof(unsigned long)) { +		if (nla_put(skb, tlv, sizeof(unsigned long), &v->val)) +			goto nla_put_failure; +	} else if (v->len == sizeof(u32)) { +		if (nla_put_u32(skb, tlv, v->val)) +			goto nla_put_failure;  	}  	return 0; @@ -663,8 +742,7 @@ nla_put_failure:   * Type specific operations table   **************************************************************************/ -struct meta_type_ops -{ +struct meta_type_ops {  	void	(*destroy)(struct meta_value *);  	int	(*compare)(struct meta_obj *, struct meta_obj *);  	int	(*change)(struct meta_value *, struct nlattr *); @@ -672,7 +750,7 @@ struct meta_type_ops  	int	(*dump)(struct sk_buff *, struct meta_value *, int);  }; -static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = { +static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX + 1] = {  	[TCF_META_TYPE_VAR] = {  		.destroy = meta_var_destroy,  		.compare = meta_var_compare, @@ -688,7 +766,7 @@ static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = {  	}  }; -static inline struct meta_type_ops * meta_type_ops(struct meta_value *v) +static inline struct meta_type_ops *meta_type_ops(struct meta_value *v)  {  	return &__meta_type_ops[meta_type(v)];  } @@ -713,7 +791,7 @@ static int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info,  		return err;  	if (meta_type_ops(v)->apply_extras) -	    meta_type_ops(v)->apply_extras(v, dst); +		meta_type_ops(v)->apply_extras(v, dst);  	return 0;  } @@ -732,12 +810,12 @@ static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m,  	r = meta_type_ops(&meta->lvalue)->compare(&l_value, &r_value);  	switch (meta->lvalue.hdr.op) { -		case TCF_EM_OPND_EQ: -			return !r; -		case TCF_EM_OPND_LT: -			return r < 0; -		case TCF_EM_OPND_GT: -			return r > 0; +	case TCF_EM_OPND_EQ: +		return !r; +	case TCF_EM_OPND_LT: +		return r < 0; +	case TCF_EM_OPND_GT: +		return r > 0;  	}  	return 0; @@ -771,7 +849,7 @@ static inline int meta_change_data(struct meta_value *dst, struct nlattr *nla)  static inline int meta_is_supported(struct meta_value *val)  { -	return (!meta_id(val) || meta_ops(val)->get); +	return !meta_id(val) || meta_ops(val)->get;  }  static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = { @@ -802,8 +880,10 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len,  		goto errout;  	meta = kzalloc(sizeof(*meta), GFP_KERNEL); -	if (meta == NULL) +	if (meta == NULL) { +		err = -ENOMEM;  		goto errout; +	}  	memcpy(&meta->lvalue.hdr, &hdr->left, sizeof(hdr->left));  	memcpy(&meta->rvalue.hdr, &hdr->right, sizeof(hdr->right)); @@ -844,7 +924,8 @@ static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em)  	memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left));  	memcpy(&hdr.right, &meta->rvalue.hdr, sizeof(hdr.right)); -	NLA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr); +	if (nla_put(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr)) +		goto nla_put_failure;  	ops = meta_type_ops(&meta->lvalue);  	if (ops->dump(skb, &meta->lvalue, TCA_EM_META_LVALUE) < 0 ||  | 
