aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
authorGreg Rose <gregory.v.rose@intel.com>2011-06-09 21:27:09 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-06-09 23:38:07 -0400
commitc7ac8679bec9397afe8918f788cbcef88c38da54 (patch)
treec152712de4c997ea79252ef9ac72aaedb8f88c18 /net/core/rtnetlink.c
parent929dd047720785f099e12113780b3d7914ce6d9f (diff)
rtnetlink: Compute and store minimum ifinfo dump size
The message size allocated for rtnl ifinfo dumps was limited to a single page. This is not enough for additional interface info available with devices that support SR-IOV and caused a bug in which VF info would not be displayed if more than approximately 40 VFs were created per interface. Implement a new function pointer for the rtnl_register service that will calculate the amount of data required for the ifinfo dump and allocate enough data to satisfy the request. Signed-off-by: Greg Rose <gregory.v.rose@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c60
1 files changed, 49 insertions, 11 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index abd936d8a716..a798fc6f2aa1 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -56,9 +56,11 @@
56struct rtnl_link { 56struct rtnl_link {
57 rtnl_doit_func doit; 57 rtnl_doit_func doit;
58 rtnl_dumpit_func dumpit; 58 rtnl_dumpit_func dumpit;
59 rtnl_calcit_func calcit;
59}; 60};
60 61
61static DEFINE_MUTEX(rtnl_mutex); 62static DEFINE_MUTEX(rtnl_mutex);
63static u16 min_ifinfo_dump_size;
62 64
63void rtnl_lock(void) 65void rtnl_lock(void)
64{ 66{
@@ -144,12 +146,28 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
144 return tab ? tab[msgindex].dumpit : NULL; 146 return tab ? tab[msgindex].dumpit : NULL;
145} 147}
146 148
149static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
150{
151 struct rtnl_link *tab;
152
153 if (protocol <= RTNL_FAMILY_MAX)
154 tab = rtnl_msg_handlers[protocol];
155 else
156 tab = NULL;
157
158 if (tab == NULL || tab[msgindex].calcit == NULL)
159 tab = rtnl_msg_handlers[PF_UNSPEC];
160
161 return tab ? tab[msgindex].calcit : NULL;
162}
163
147/** 164/**
148 * __rtnl_register - Register a rtnetlink message type 165 * __rtnl_register - Register a rtnetlink message type
149 * @protocol: Protocol family or PF_UNSPEC 166 * @protocol: Protocol family or PF_UNSPEC
150 * @msgtype: rtnetlink message type 167 * @msgtype: rtnetlink message type
151 * @doit: Function pointer called for each request message 168 * @doit: Function pointer called for each request message
152 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message 169 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
170 * @calcit: Function pointer to calc size of dump message
153 * 171 *
154 * Registers the specified function pointers (at least one of them has 172 * Registers the specified function pointers (at least one of them has
155 * to be non-NULL) to be called whenever a request message for the 173 * to be non-NULL) to be called whenever a request message for the
@@ -162,7 +180,8 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
162 * Returns 0 on success or a negative error code. 180 * Returns 0 on success or a negative error code.
163 */ 181 */
164int __rtnl_register(int protocol, int msgtype, 182int __rtnl_register(int protocol, int msgtype,
165 rtnl_doit_func doit, rtnl_dumpit_func dumpit) 183 rtnl_doit_func doit, rtnl_dumpit_func dumpit,
184 rtnl_calcit_func calcit)
166{ 185{
167 struct rtnl_link *tab; 186 struct rtnl_link *tab;
168 int msgindex; 187 int msgindex;
@@ -185,6 +204,9 @@ int __rtnl_register(int protocol, int msgtype,
185 if (dumpit) 204 if (dumpit)
186 tab[msgindex].dumpit = dumpit; 205 tab[msgindex].dumpit = dumpit;
187 206
207 if (calcit)
208 tab[msgindex].calcit = calcit;
209
188 return 0; 210 return 0;
189} 211}
190EXPORT_SYMBOL_GPL(__rtnl_register); 212EXPORT_SYMBOL_GPL(__rtnl_register);
@@ -199,9 +221,10 @@ EXPORT_SYMBOL_GPL(__rtnl_register);
199 * of memory implies no sense in continuing. 221 * of memory implies no sense in continuing.
200 */ 222 */
201void rtnl_register(int protocol, int msgtype, 223void rtnl_register(int protocol, int msgtype,
202 rtnl_doit_func doit, rtnl_dumpit_func dumpit) 224 rtnl_doit_func doit, rtnl_dumpit_func dumpit,
225 rtnl_calcit_func calcit)
203{ 226{
204 if (__rtnl_register(protocol, msgtype, doit, dumpit) < 0) 227 if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0)
205 panic("Unable to register rtnetlink message handler, " 228 panic("Unable to register rtnetlink message handler, "
206 "protocol = %d, message type = %d\n", 229 "protocol = %d, message type = %d\n",
207 protocol, msgtype); 230 protocol, msgtype);
@@ -1818,6 +1841,11 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1818 return err; 1841 return err;
1819} 1842}
1820 1843
1844static u16 rtnl_calcit(struct sk_buff *skb)
1845{
1846 return min_ifinfo_dump_size;
1847}
1848
1821static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) 1849static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
1822{ 1850{
1823 int idx; 1851 int idx;
@@ -1847,11 +1875,14 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
1847 struct net *net = dev_net(dev); 1875 struct net *net = dev_net(dev);
1848 struct sk_buff *skb; 1876 struct sk_buff *skb;
1849 int err = -ENOBUFS; 1877 int err = -ENOBUFS;
1878 size_t if_info_size;
1850 1879
1851 skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); 1880 skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL);
1852 if (skb == NULL) 1881 if (skb == NULL)
1853 goto errout; 1882 goto errout;
1854 1883
1884 min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size);
1885
1855 err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0); 1886 err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0);
1856 if (err < 0) { 1887 if (err < 0) {
1857 /* -EMSGSIZE implies BUG in if_nlmsg_size() */ 1888 /* -EMSGSIZE implies BUG in if_nlmsg_size() */
@@ -1902,14 +1933,20 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1902 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 1933 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
1903 struct sock *rtnl; 1934 struct sock *rtnl;
1904 rtnl_dumpit_func dumpit; 1935 rtnl_dumpit_func dumpit;
1936 rtnl_calcit_func calcit;
1937 u16 min_dump_alloc = 0;
1905 1938
1906 dumpit = rtnl_get_dumpit(family, type); 1939 dumpit = rtnl_get_dumpit(family, type);
1907 if (dumpit == NULL) 1940 if (dumpit == NULL)
1908 return -EOPNOTSUPP; 1941 return -EOPNOTSUPP;
1942 calcit = rtnl_get_calcit(family, type);
1943 if (calcit)
1944 min_dump_alloc = calcit(skb);
1909 1945
1910 __rtnl_unlock(); 1946 __rtnl_unlock();
1911 rtnl = net->rtnl; 1947 rtnl = net->rtnl;
1912 err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); 1948 err = netlink_dump_start(rtnl, skb, nlh, dumpit,
1949 NULL, min_dump_alloc);
1913 rtnl_lock(); 1950 rtnl_lock();
1914 return err; 1951 return err;
1915 } 1952 }
@@ -2019,12 +2056,13 @@ void __init rtnetlink_init(void)
2019 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); 2056 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
2020 register_netdevice_notifier(&rtnetlink_dev_notifier); 2057 register_netdevice_notifier(&rtnetlink_dev_notifier);
2021 2058
2022 rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo); 2059 rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink,
2023 rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL); 2060 rtnl_dump_ifinfo, rtnl_calcit);
2024 rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL); 2061 rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL);
2025 rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL); 2062 rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL);
2063 rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL);
2026 2064
2027 rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all); 2065 rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL);
2028 rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); 2066 rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL);
2029} 2067}
2030 2068