diff options
Diffstat (limited to 'net/core/rtnetlink.c')
| -rw-r--r-- | net/core/rtnetlink.c | 67 | 
1 files changed, 38 insertions, 29 deletions
| diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d8c198e42f90..00caf4b318b2 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -86,30 +86,33 @@ struct sock *rtnl;  struct rtnetlink_link * rtnetlink_links[NPROTO]; -static const int rtm_min[(RTM_MAX+1-RTM_BASE)/4] = +static const int rtm_min[RTM_NR_FAMILIES] =  { -	NLMSG_LENGTH(sizeof(struct ifinfomsg)), -	NLMSG_LENGTH(sizeof(struct ifaddrmsg)), -	NLMSG_LENGTH(sizeof(struct rtmsg)), -	NLMSG_LENGTH(sizeof(struct ndmsg)), -	NLMSG_LENGTH(sizeof(struct rtmsg)), -	NLMSG_LENGTH(sizeof(struct tcmsg)), -	NLMSG_LENGTH(sizeof(struct tcmsg)), -	NLMSG_LENGTH(sizeof(struct tcmsg)), -	NLMSG_LENGTH(sizeof(struct tcamsg)) +	[RTM_FAM(RTM_NEWLINK)]      = NLMSG_LENGTH(sizeof(struct ifinfomsg)), +	[RTM_FAM(RTM_NEWADDR)]      = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), +	[RTM_FAM(RTM_NEWROUTE)]     = NLMSG_LENGTH(sizeof(struct rtmsg)), +	[RTM_FAM(RTM_NEWNEIGH)]     = NLMSG_LENGTH(sizeof(struct ndmsg)), +	[RTM_FAM(RTM_NEWRULE)]      = NLMSG_LENGTH(sizeof(struct rtmsg)), +	[RTM_FAM(RTM_NEWQDISC)]     = NLMSG_LENGTH(sizeof(struct tcmsg)), +	[RTM_FAM(RTM_NEWTCLASS)]    = NLMSG_LENGTH(sizeof(struct tcmsg)), +	[RTM_FAM(RTM_NEWTFILTER)]   = NLMSG_LENGTH(sizeof(struct tcmsg)), +	[RTM_FAM(RTM_NEWACTION)]    = NLMSG_LENGTH(sizeof(struct tcamsg)), +	[RTM_FAM(RTM_NEWPREFIX)]    = NLMSG_LENGTH(sizeof(struct rtgenmsg)), +	[RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), +	[RTM_FAM(RTM_GETANYCAST)]   = NLMSG_LENGTH(sizeof(struct rtgenmsg)),  }; -static const int rta_max[(RTM_MAX+1-RTM_BASE)/4] = +static const int rta_max[RTM_NR_FAMILIES] =  { -	IFLA_MAX, -	IFA_MAX, -	RTA_MAX, -	NDA_MAX, -	RTA_MAX, -	TCA_MAX, -	TCA_MAX, -	TCA_MAX, -	TCAA_MAX +	[RTM_FAM(RTM_NEWLINK)]      = IFLA_MAX, +	[RTM_FAM(RTM_NEWADDR)]      = IFA_MAX, +	[RTM_FAM(RTM_NEWROUTE)]     = RTA_MAX, +	[RTM_FAM(RTM_NEWNEIGH)]     = NDA_MAX, +	[RTM_FAM(RTM_NEWRULE)]      = RTA_MAX, +	[RTM_FAM(RTM_NEWQDISC)]     = TCA_MAX, +	[RTM_FAM(RTM_NEWTCLASS)]    = TCA_MAX, +	[RTM_FAM(RTM_NEWTFILTER)]   = TCA_MAX, +	[RTM_FAM(RTM_NEWACTION)]    = TCAA_MAX,  };  void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) @@ -606,27 +609,33 @@ static inline int rtnetlink_rcv_skb(struct sk_buff *skb)  /*   *  rtnetlink input queue processing routine: - *	- try to acquire shared lock. If it is failed, defer processing. + *	- process as much as there was in the queue upon entry.   *	- feed skbs to rtnetlink_rcv_skb, until it refuse a message, - *	  that will occur, when a dump started and/or acquisition of - *	  exclusive lock failed. + *	  that will occur, when a dump started.   */  static void rtnetlink_rcv(struct sock *sk, int len)  { +	unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); +  	do {  		struct sk_buff *skb; -		if (rtnl_shlock_nowait()) -			return; +		rtnl_lock(); + +		if (qlen > skb_queue_len(&sk->sk_receive_queue)) +			qlen = skb_queue_len(&sk->sk_receive_queue); -		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { +		for (; qlen; qlen--) { +			skb = skb_dequeue(&sk->sk_receive_queue);  			if (rtnetlink_rcv_skb(skb)) {  				if (skb->len)  					skb_queue_head(&sk->sk_receive_queue,  						       skb); -				else +				else {  					kfree_skb(skb); +					qlen--; +				}  				break;  			}  			kfree_skb(skb); @@ -635,10 +644,10 @@ static void rtnetlink_rcv(struct sock *sk, int len)  		up(&rtnl_sem);  		netdev_run_todo(); -	} while (rtnl && rtnl->sk_receive_queue.qlen); +	} while (qlen);  } -static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] = +static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =  {  	[RTM_GETLINK  - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },  	[RTM_SETLINK  - RTM_BASE] = { .doit   = do_setlink	      }, | 
