net_sched: optimize tcf_match_indev()
tcf_match_indev() is called in fast path, it is not wise to search for a netdev by ifindex and then compare by its name, just compare the ifindex. Also, dev->name could be changed by user-space, therefore the match would be always fail, but dev->ifindex could be consistent. BTW, this will also save some bytes from the core struct of u32. Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								832d1d5bfa
							
						
					
				
			
			
				commit
				
					
						2519a602c2
					
				
			
		
					 3 changed files with 41 additions and 31 deletions
				
			
		|  | @ -338,27 +338,27 @@ static inline int tcf_valid_offset(const struct sk_buff *skb, | |||
| #include <net/net_namespace.h> | ||||
| 
 | ||||
| static inline int | ||||
| tcf_change_indev(struct tcf_proto *tp, char *indev, struct nlattr *indev_tlv) | ||||
| { | ||||
| 	if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) | ||||
| 		return -EINVAL; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| tcf_match_indev(struct sk_buff *skb, char *indev) | ||||
| tcf_change_indev(struct net *net, struct nlattr *indev_tlv) | ||||
| { | ||||
| 	char indev[IFNAMSIZ]; | ||||
| 	struct net_device *dev; | ||||
| 
 | ||||
| 	if (indev[0]) { | ||||
| 		if  (!skb->skb_iif) | ||||
| 			return 0; | ||||
| 		dev = __dev_get_by_index(dev_net(skb->dev), skb->skb_iif); | ||||
| 		if (!dev || strcmp(indev, dev->name)) | ||||
| 			return 0; | ||||
| 	} | ||||
| 	if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) | ||||
| 		return -EINVAL; | ||||
| 	dev = __dev_get_by_name(net, indev); | ||||
| 	if (!dev) | ||||
| 		return -ENODEV; | ||||
| 	return dev->ifindex; | ||||
| } | ||||
| 
 | ||||
| 	return 1; | ||||
| static inline bool | ||||
| tcf_match_indev(struct sk_buff *skb, int ifindex) | ||||
| { | ||||
| 	if (!ifindex) | ||||
| 		return true; | ||||
| 	if  (!skb->skb_iif) | ||||
| 		return false; | ||||
| 	return ifindex == skb->skb_iif; | ||||
| } | ||||
| #endif /* CONFIG_NET_CLS_IND */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ struct fw_filter { | |||
| 	u32			id; | ||||
| 	struct tcf_result	res; | ||||
| #ifdef CONFIG_NET_CLS_IND | ||||
| 	char			indev[IFNAMSIZ]; | ||||
| 	int			ifindex; | ||||
| #endif /* CONFIG_NET_CLS_IND */ | ||||
| 	struct tcf_exts		exts; | ||||
| }; | ||||
|  | @ -86,7 +86,7 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp, | |||
| 			if (f->id == id) { | ||||
| 				*res = f->res; | ||||
| #ifdef CONFIG_NET_CLS_IND | ||||
| 				if (!tcf_match_indev(skb, f->indev)) | ||||
| 				if (!tcf_match_indev(skb, f->ifindex)) | ||||
| 					continue; | ||||
| #endif /* CONFIG_NET_CLS_IND */ | ||||
| 				r = tcf_exts_exec(skb, &f->exts, res); | ||||
|  | @ -207,9 +207,11 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f, | |||
| 
 | ||||
| #ifdef CONFIG_NET_CLS_IND | ||||
| 	if (tb[TCA_FW_INDEV]) { | ||||
| 		err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV]); | ||||
| 		if (err < 0) | ||||
| 		int ret; | ||||
| 		ret = tcf_change_indev(net, tb[TCA_FW_INDEV]); | ||||
| 		if (ret < 0) | ||||
| 			goto errout; | ||||
| 		f->ifindex = ret; | ||||
| 	} | ||||
| #endif /* CONFIG_NET_CLS_IND */ | ||||
| 
 | ||||
|  | @ -348,9 +350,12 @@ static int fw_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, | |||
| 	    nla_put_u32(skb, TCA_FW_CLASSID, f->res.classid)) | ||||
| 		goto nla_put_failure; | ||||
| #ifdef CONFIG_NET_CLS_IND | ||||
| 	if (strlen(f->indev) && | ||||
| 	    nla_put_string(skb, TCA_FW_INDEV, f->indev)) | ||||
| 		goto nla_put_failure; | ||||
| 	if (f->ifindex) { | ||||
| 		struct net_device *dev; | ||||
| 		dev = __dev_get_by_index(net, f->ifindex); | ||||
| 		if (dev && nla_put_string(skb, TCA_FW_INDEV, dev->name)) | ||||
| 			goto nla_put_failure; | ||||
| 	} | ||||
| #endif /* CONFIG_NET_CLS_IND */ | ||||
| 	if (head->mask != 0xFFFFFFFF && | ||||
| 	    nla_put_u32(skb, TCA_FW_MASK, head->mask)) | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ struct tc_u_knode { | |||
| 	struct tc_u_hnode	*ht_up; | ||||
| 	struct tcf_exts		exts; | ||||
| #ifdef CONFIG_NET_CLS_IND | ||||
| 	char                     indev[IFNAMSIZ]; | ||||
| 	int			ifindex; | ||||
| #endif | ||||
| 	u8			fshift; | ||||
| 	struct tcf_result	res; | ||||
|  | @ -152,7 +152,7 @@ check_terminal: | |||
| 
 | ||||
| 				*res = n->res; | ||||
| #ifdef CONFIG_NET_CLS_IND | ||||
| 				if (!tcf_match_indev(skb, n->indev)) { | ||||
| 				if (!tcf_match_indev(skb, n->ifindex)) { | ||||
| 					n = n->next; | ||||
| 					goto next_knode; | ||||
| 				} | ||||
|  | @ -527,9 +527,11 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp, | |||
| 
 | ||||
| #ifdef CONFIG_NET_CLS_IND | ||||
| 	if (tb[TCA_U32_INDEV]) { | ||||
| 		err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV]); | ||||
| 		if (err < 0) | ||||
| 		int ret; | ||||
| 		ret = tcf_change_indev(net, tb[TCA_U32_INDEV]); | ||||
| 		if (ret < 0) | ||||
| 			goto errout; | ||||
| 		n->ifindex = ret; | ||||
| 	} | ||||
| #endif | ||||
| 	tcf_exts_change(tp, &n->exts, &e); | ||||
|  | @ -760,9 +762,12 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, | |||
| 			goto nla_put_failure; | ||||
| 
 | ||||
| #ifdef CONFIG_NET_CLS_IND | ||||
| 		if (strlen(n->indev) && | ||||
| 		    nla_put_string(skb, TCA_U32_INDEV, n->indev)) | ||||
| 			goto nla_put_failure; | ||||
| 		if (n->ifindex) { | ||||
| 			struct net_device *dev; | ||||
| 			dev = __dev_get_by_index(net, n->ifindex); | ||||
| 			if (dev && nla_put_string(skb, TCA_U32_INDEV, dev->name)) | ||||
| 				goto nla_put_failure; | ||||
| 		} | ||||
| #endif | ||||
| #ifdef CONFIG_CLS_U32_PERF | ||||
| 		if (nla_put(skb, TCA_U32_PCNT, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 WANG Cong
				WANG Cong