aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c68
1 files changed, 38 insertions, 30 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 44dfaf8f04af..00caf4b318b2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -22,7 +22,6 @@
22#include <linux/types.h> 22#include <linux/types.h>
23#include <linux/socket.h> 23#include <linux/socket.h>
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/major.h>
26#include <linux/sched.h> 25#include <linux/sched.h>
27#include <linux/timer.h> 26#include <linux/timer.h>
28#include <linux/string.h> 27#include <linux/string.h>
@@ -87,30 +86,33 @@ struct sock *rtnl;
87 86
88struct rtnetlink_link * rtnetlink_links[NPROTO]; 87struct rtnetlink_link * rtnetlink_links[NPROTO];
89 88
90static const int rtm_min[(RTM_MAX+1-RTM_BASE)/4] = 89static const int rtm_min[RTM_NR_FAMILIES] =
91{ 90{
92 NLMSG_LENGTH(sizeof(struct ifinfomsg)), 91 [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
93 NLMSG_LENGTH(sizeof(struct ifaddrmsg)), 92 [RTM_FAM(RTM_NEWADDR)] = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
94 NLMSG_LENGTH(sizeof(struct rtmsg)), 93 [RTM_FAM(RTM_NEWROUTE)] = NLMSG_LENGTH(sizeof(struct rtmsg)),
95 NLMSG_LENGTH(sizeof(struct ndmsg)), 94 [RTM_FAM(RTM_NEWNEIGH)] = NLMSG_LENGTH(sizeof(struct ndmsg)),
96 NLMSG_LENGTH(sizeof(struct rtmsg)), 95 [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct rtmsg)),
97 NLMSG_LENGTH(sizeof(struct tcmsg)), 96 [RTM_FAM(RTM_NEWQDISC)] = NLMSG_LENGTH(sizeof(struct tcmsg)),
98 NLMSG_LENGTH(sizeof(struct tcmsg)), 97 [RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)),
99 NLMSG_LENGTH(sizeof(struct tcmsg)), 98 [RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)),
100 NLMSG_LENGTH(sizeof(struct tcamsg)) 99 [RTM_FAM(RTM_NEWACTION)] = NLMSG_LENGTH(sizeof(struct tcamsg)),
100 [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
101 [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
102 [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
101}; 103};
102 104
103static const int rta_max[(RTM_MAX+1-RTM_BASE)/4] = 105static const int rta_max[RTM_NR_FAMILIES] =
104{ 106{
105 IFLA_MAX, 107 [RTM_FAM(RTM_NEWLINK)] = IFLA_MAX,
106 IFA_MAX, 108 [RTM_FAM(RTM_NEWADDR)] = IFA_MAX,
107 RTA_MAX, 109 [RTM_FAM(RTM_NEWROUTE)] = RTA_MAX,
108 NDA_MAX, 110 [RTM_FAM(RTM_NEWNEIGH)] = NDA_MAX,
109 RTA_MAX, 111 [RTM_FAM(RTM_NEWRULE)] = RTA_MAX,
110 TCA_MAX, 112 [RTM_FAM(RTM_NEWQDISC)] = TCA_MAX,
111 TCA_MAX, 113 [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX,
112 TCA_MAX, 114 [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX,
113 TCAA_MAX 115 [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX,
114}; 116};
115 117
116void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) 118void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
@@ -607,27 +609,33 @@ static inline int rtnetlink_rcv_skb(struct sk_buff *skb)
607 609
608/* 610/*
609 * rtnetlink input queue processing routine: 611 * rtnetlink input queue processing routine:
610 * - try to acquire shared lock. If it is failed, defer processing. 612 * - process as much as there was in the queue upon entry.
611 * - feed skbs to rtnetlink_rcv_skb, until it refuse a message, 613 * - feed skbs to rtnetlink_rcv_skb, until it refuse a message,
612 * that will occur, when a dump started and/or acquisition of 614 * that will occur, when a dump started.
613 * exclusive lock failed.
614 */ 615 */
615 616
616static void rtnetlink_rcv(struct sock *sk, int len) 617static void rtnetlink_rcv(struct sock *sk, int len)
617{ 618{
619 unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
620
618 do { 621 do {
619 struct sk_buff *skb; 622 struct sk_buff *skb;
620 623
621 if (rtnl_shlock_nowait()) 624 rtnl_lock();
622 return; 625
626 if (qlen > skb_queue_len(&sk->sk_receive_queue))
627 qlen = skb_queue_len(&sk->sk_receive_queue);
623 628
624 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { 629 for (; qlen; qlen--) {
630 skb = skb_dequeue(&sk->sk_receive_queue);
625 if (rtnetlink_rcv_skb(skb)) { 631 if (rtnetlink_rcv_skb(skb)) {
626 if (skb->len) 632 if (skb->len)
627 skb_queue_head(&sk->sk_receive_queue, 633 skb_queue_head(&sk->sk_receive_queue,
628 skb); 634 skb);
629 else 635 else {
630 kfree_skb(skb); 636 kfree_skb(skb);
637 qlen--;
638 }
631 break; 639 break;
632 } 640 }
633 kfree_skb(skb); 641 kfree_skb(skb);
@@ -636,10 +644,10 @@ static void rtnetlink_rcv(struct sock *sk, int len)
636 up(&rtnl_sem); 644 up(&rtnl_sem);
637 645
638 netdev_run_todo(); 646 netdev_run_todo();
639 } while (rtnl && rtnl->sk_receive_queue.qlen); 647 } while (qlen);
640} 648}
641 649
642static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] = 650static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
643{ 651{
644 [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, 652 [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
645 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, 653 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },