]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/dcb/dcbnl.c
Merge branch 'fixes-for-linus' of git://git.linaro.org/people/mszyprowski/linux-dma...
[karo-tx-linux.git] / net / dcb / dcbnl.c
1 /*
2  * Copyright (c) 2008-2011, Intel Corporation.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15  * Place - Suite 330, Boston, MA 02111-1307 USA.
16  *
17  * Author: Lucy Liu <lucy.liu@intel.com>
18  */
19
20 #include <linux/netdevice.h>
21 #include <linux/netlink.h>
22 #include <linux/slab.h>
23 #include <net/netlink.h>
24 #include <net/rtnetlink.h>
25 #include <linux/dcbnl.h>
26 #include <net/dcbevent.h>
27 #include <linux/rtnetlink.h>
28 #include <linux/module.h>
29 #include <net/sock.h>
30
31 /**
32  * Data Center Bridging (DCB) is a collection of Ethernet enhancements
33  * intended to allow network traffic with differing requirements
34  * (highly reliable, no drops vs. best effort vs. low latency) to operate
35  * and co-exist on Ethernet.  Current DCB features are:
36  *
37  * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a
38  *   framework for assigning bandwidth guarantees to traffic classes.
39  *
40  * Priority-based Flow Control (PFC) - provides a flow control mechanism which
41  *   can work independently for each 802.1p priority.
42  *
43  * Congestion Notification - provides a mechanism for end-to-end congestion
44  *   control for protocols which do not have built-in congestion management.
45  *
46  * More information about the emerging standards for these Ethernet features
47  * can be found at: http://www.ieee802.org/1/pages/dcbridges.html
48  *
49  * This file implements an rtnetlink interface to allow configuration of DCB
50  * features for capable devices.
51  */
52
53 MODULE_AUTHOR("Lucy Liu, <lucy.liu@intel.com>");
54 MODULE_DESCRIPTION("Data Center Bridging netlink interface");
55 MODULE_LICENSE("GPL");
56
57 /**************** DCB attribute policies *************************************/
58
59 /* DCB netlink attributes policy */
60 static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
61         [DCB_ATTR_IFNAME]      = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1},
62         [DCB_ATTR_STATE]       = {.type = NLA_U8},
63         [DCB_ATTR_PFC_CFG]     = {.type = NLA_NESTED},
64         [DCB_ATTR_PG_CFG]      = {.type = NLA_NESTED},
65         [DCB_ATTR_SET_ALL]     = {.type = NLA_U8},
66         [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG},
67         [DCB_ATTR_CAP]         = {.type = NLA_NESTED},
68         [DCB_ATTR_PFC_STATE]   = {.type = NLA_U8},
69         [DCB_ATTR_BCN]         = {.type = NLA_NESTED},
70         [DCB_ATTR_APP]         = {.type = NLA_NESTED},
71         [DCB_ATTR_IEEE]        = {.type = NLA_NESTED},
72         [DCB_ATTR_DCBX]        = {.type = NLA_U8},
73         [DCB_ATTR_FEATCFG]     = {.type = NLA_NESTED},
74 };
75
76 /* DCB priority flow control to User Priority nested attributes */
77 static const struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = {
78         [DCB_PFC_UP_ATTR_0]   = {.type = NLA_U8},
79         [DCB_PFC_UP_ATTR_1]   = {.type = NLA_U8},
80         [DCB_PFC_UP_ATTR_2]   = {.type = NLA_U8},
81         [DCB_PFC_UP_ATTR_3]   = {.type = NLA_U8},
82         [DCB_PFC_UP_ATTR_4]   = {.type = NLA_U8},
83         [DCB_PFC_UP_ATTR_5]   = {.type = NLA_U8},
84         [DCB_PFC_UP_ATTR_6]   = {.type = NLA_U8},
85         [DCB_PFC_UP_ATTR_7]   = {.type = NLA_U8},
86         [DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG},
87 };
88
89 /* DCB priority grouping nested attributes */
90 static const struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = {
91         [DCB_PG_ATTR_TC_0]      = {.type = NLA_NESTED},
92         [DCB_PG_ATTR_TC_1]      = {.type = NLA_NESTED},
93         [DCB_PG_ATTR_TC_2]      = {.type = NLA_NESTED},
94         [DCB_PG_ATTR_TC_3]      = {.type = NLA_NESTED},
95         [DCB_PG_ATTR_TC_4]      = {.type = NLA_NESTED},
96         [DCB_PG_ATTR_TC_5]      = {.type = NLA_NESTED},
97         [DCB_PG_ATTR_TC_6]      = {.type = NLA_NESTED},
98         [DCB_PG_ATTR_TC_7]      = {.type = NLA_NESTED},
99         [DCB_PG_ATTR_TC_ALL]    = {.type = NLA_NESTED},
100         [DCB_PG_ATTR_BW_ID_0]   = {.type = NLA_U8},
101         [DCB_PG_ATTR_BW_ID_1]   = {.type = NLA_U8},
102         [DCB_PG_ATTR_BW_ID_2]   = {.type = NLA_U8},
103         [DCB_PG_ATTR_BW_ID_3]   = {.type = NLA_U8},
104         [DCB_PG_ATTR_BW_ID_4]   = {.type = NLA_U8},
105         [DCB_PG_ATTR_BW_ID_5]   = {.type = NLA_U8},
106         [DCB_PG_ATTR_BW_ID_6]   = {.type = NLA_U8},
107         [DCB_PG_ATTR_BW_ID_7]   = {.type = NLA_U8},
108         [DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG},
109 };
110
111 /* DCB traffic class nested attributes. */
112 static const struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = {
113         [DCB_TC_ATTR_PARAM_PGID]            = {.type = NLA_U8},
114         [DCB_TC_ATTR_PARAM_UP_MAPPING]      = {.type = NLA_U8},
115         [DCB_TC_ATTR_PARAM_STRICT_PRIO]     = {.type = NLA_U8},
116         [DCB_TC_ATTR_PARAM_BW_PCT]          = {.type = NLA_U8},
117         [DCB_TC_ATTR_PARAM_ALL]             = {.type = NLA_FLAG},
118 };
119
120 /* DCB capabilities nested attributes. */
121 static const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
122         [DCB_CAP_ATTR_ALL]     = {.type = NLA_FLAG},
123         [DCB_CAP_ATTR_PG]      = {.type = NLA_U8},
124         [DCB_CAP_ATTR_PFC]     = {.type = NLA_U8},
125         [DCB_CAP_ATTR_UP2TC]   = {.type = NLA_U8},
126         [DCB_CAP_ATTR_PG_TCS]  = {.type = NLA_U8},
127         [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8},
128         [DCB_CAP_ATTR_GSP]     = {.type = NLA_U8},
129         [DCB_CAP_ATTR_BCN]     = {.type = NLA_U8},
130         [DCB_CAP_ATTR_DCBX]    = {.type = NLA_U8},
131 };
132
133 /* DCB capabilities nested attributes. */
134 static const struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = {
135         [DCB_NUMTCS_ATTR_ALL]     = {.type = NLA_FLAG},
136         [DCB_NUMTCS_ATTR_PG]      = {.type = NLA_U8},
137         [DCB_NUMTCS_ATTR_PFC]     = {.type = NLA_U8},
138 };
139
140 /* DCB BCN nested attributes. */
141 static const struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = {
142         [DCB_BCN_ATTR_RP_0]         = {.type = NLA_U8},
143         [DCB_BCN_ATTR_RP_1]         = {.type = NLA_U8},
144         [DCB_BCN_ATTR_RP_2]         = {.type = NLA_U8},
145         [DCB_BCN_ATTR_RP_3]         = {.type = NLA_U8},
146         [DCB_BCN_ATTR_RP_4]         = {.type = NLA_U8},
147         [DCB_BCN_ATTR_RP_5]         = {.type = NLA_U8},
148         [DCB_BCN_ATTR_RP_6]         = {.type = NLA_U8},
149         [DCB_BCN_ATTR_RP_7]         = {.type = NLA_U8},
150         [DCB_BCN_ATTR_RP_ALL]       = {.type = NLA_FLAG},
151         [DCB_BCN_ATTR_BCNA_0]       = {.type = NLA_U32},
152         [DCB_BCN_ATTR_BCNA_1]       = {.type = NLA_U32},
153         [DCB_BCN_ATTR_ALPHA]        = {.type = NLA_U32},
154         [DCB_BCN_ATTR_BETA]         = {.type = NLA_U32},
155         [DCB_BCN_ATTR_GD]           = {.type = NLA_U32},
156         [DCB_BCN_ATTR_GI]           = {.type = NLA_U32},
157         [DCB_BCN_ATTR_TMAX]         = {.type = NLA_U32},
158         [DCB_BCN_ATTR_TD]           = {.type = NLA_U32},
159         [DCB_BCN_ATTR_RMIN]         = {.type = NLA_U32},
160         [DCB_BCN_ATTR_W]            = {.type = NLA_U32},
161         [DCB_BCN_ATTR_RD]           = {.type = NLA_U32},
162         [DCB_BCN_ATTR_RU]           = {.type = NLA_U32},
163         [DCB_BCN_ATTR_WRTT]         = {.type = NLA_U32},
164         [DCB_BCN_ATTR_RI]           = {.type = NLA_U32},
165         [DCB_BCN_ATTR_C]            = {.type = NLA_U32},
166         [DCB_BCN_ATTR_ALL]          = {.type = NLA_FLAG},
167 };
168
169 /* DCB APP nested attributes. */
170 static const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = {
171         [DCB_APP_ATTR_IDTYPE]       = {.type = NLA_U8},
172         [DCB_APP_ATTR_ID]           = {.type = NLA_U16},
173         [DCB_APP_ATTR_PRIORITY]     = {.type = NLA_U8},
174 };
175
176 /* IEEE 802.1Qaz nested attributes. */
177 static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = {
178         [DCB_ATTR_IEEE_ETS]         = {.len = sizeof(struct ieee_ets)},
179         [DCB_ATTR_IEEE_PFC]         = {.len = sizeof(struct ieee_pfc)},
180         [DCB_ATTR_IEEE_APP_TABLE]   = {.type = NLA_NESTED},
181         [DCB_ATTR_IEEE_MAXRATE]   = {.len = sizeof(struct ieee_maxrate)},
182 };
183
184 static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
185         [DCB_ATTR_IEEE_APP]         = {.len = sizeof(struct dcb_app)},
186 };
187
188 /* DCB number of traffic classes nested attributes. */
189 static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
190         [DCB_FEATCFG_ATTR_ALL]      = {.type = NLA_FLAG},
191         [DCB_FEATCFG_ATTR_PG]       = {.type = NLA_U8},
192         [DCB_FEATCFG_ATTR_PFC]      = {.type = NLA_U8},
193         [DCB_FEATCFG_ATTR_APP]      = {.type = NLA_U8},
194 };
195
196 static LIST_HEAD(dcb_app_list);
197 static DEFINE_SPINLOCK(dcb_lock);
198
199 /* standard netlink reply call */
200 static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
201                        u32 seq, u16 flags)
202 {
203         struct sk_buff *dcbnl_skb;
204         struct dcbmsg *dcb;
205         struct nlmsghdr *nlh;
206         int ret = -EINVAL;
207
208         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
209         if (!dcbnl_skb)
210                 return ret;
211
212         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags);
213
214         dcb = NLMSG_DATA(nlh);
215         dcb->dcb_family = AF_UNSPEC;
216         dcb->cmd = cmd;
217         dcb->dcb_pad = 0;
218
219         ret = nla_put_u8(dcbnl_skb, attr, value);
220         if (ret)
221                 goto err;
222
223         /* end the message, assign the nlmsg_len. */
224         nlmsg_end(dcbnl_skb, nlh);
225         ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
226         if (ret)
227                 return -EINVAL;
228
229         return 0;
230 nlmsg_failure:
231 err:
232         kfree_skb(dcbnl_skb);
233         return ret;
234 }
235
236 static int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb,
237                           u32 pid, u32 seq, u16 flags)
238 {
239         int ret = -EINVAL;
240
241         /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
242         if (!netdev->dcbnl_ops->getstate)
243                 return ret;
244
245         ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB,
246                           DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags);
247
248         return ret;
249 }
250
251 static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
252                            u32 pid, u32 seq, u16 flags)
253 {
254         struct sk_buff *dcbnl_skb;
255         struct nlmsghdr *nlh;
256         struct dcbmsg *dcb;
257         struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
258         u8 value;
259         int ret = -EINVAL;
260         int i;
261         int getall = 0;
262
263         if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg)
264                 return ret;
265
266         ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
267                                tb[DCB_ATTR_PFC_CFG],
268                                dcbnl_pfc_up_nest);
269         if (ret)
270                 goto err_out;
271
272         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
273         if (!dcbnl_skb)
274                 goto err_out;
275
276         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
277
278         dcb = NLMSG_DATA(nlh);
279         dcb->dcb_family = AF_UNSPEC;
280         dcb->cmd = DCB_CMD_PFC_GCFG;
281
282         nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG);
283         if (!nest)
284                 goto err;
285
286         if (data[DCB_PFC_UP_ATTR_ALL])
287                 getall = 1;
288
289         for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
290                 if (!getall && !data[i])
291                         continue;
292
293                 netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
294                                              &value);
295                 ret = nla_put_u8(dcbnl_skb, i, value);
296
297                 if (ret) {
298                         nla_nest_cancel(dcbnl_skb, nest);
299                         goto err;
300                 }
301         }
302         nla_nest_end(dcbnl_skb, nest);
303
304         nlmsg_end(dcbnl_skb, nlh);
305
306         ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
307         if (ret)
308                 goto err_out;
309
310         return 0;
311 nlmsg_failure:
312 err:
313         kfree_skb(dcbnl_skb);
314 err_out:
315         return -EINVAL;
316 }
317
318 static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
319                                 u32 pid, u32 seq, u16 flags)
320 {
321         struct sk_buff *dcbnl_skb;
322         struct nlmsghdr *nlh;
323         struct dcbmsg *dcb;
324         u8 perm_addr[MAX_ADDR_LEN];
325         int ret = -EINVAL;
326
327         if (!netdev->dcbnl_ops->getpermhwaddr)
328                 return ret;
329
330         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
331         if (!dcbnl_skb)
332                 goto err_out;
333
334         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
335
336         dcb = NLMSG_DATA(nlh);
337         dcb->dcb_family = AF_UNSPEC;
338         dcb->cmd = DCB_CMD_GPERM_HWADDR;
339
340         netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
341
342         ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr),
343                       perm_addr);
344
345         nlmsg_end(dcbnl_skb, nlh);
346
347         ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
348         if (ret)
349                 goto err_out;
350
351         return 0;
352
353 nlmsg_failure:
354         kfree_skb(dcbnl_skb);
355 err_out:
356         return -EINVAL;
357 }
358
359 static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
360                         u32 pid, u32 seq, u16 flags)
361 {
362         struct sk_buff *dcbnl_skb;
363         struct nlmsghdr *nlh;
364         struct dcbmsg *dcb;
365         struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
366         u8 value;
367         int ret = -EINVAL;
368         int i;
369         int getall = 0;
370
371         if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap)
372                 return ret;
373
374         ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
375                                dcbnl_cap_nest);
376         if (ret)
377                 goto err_out;
378
379         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
380         if (!dcbnl_skb)
381                 goto err_out;
382
383         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
384
385         dcb = NLMSG_DATA(nlh);
386         dcb->dcb_family = AF_UNSPEC;
387         dcb->cmd = DCB_CMD_GCAP;
388
389         nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP);
390         if (!nest)
391                 goto err;
392
393         if (data[DCB_CAP_ATTR_ALL])
394                 getall = 1;
395
396         for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
397                 if (!getall && !data[i])
398                         continue;
399
400                 if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
401                         ret = nla_put_u8(dcbnl_skb, i, value);
402
403                         if (ret) {
404                                 nla_nest_cancel(dcbnl_skb, nest);
405                                 goto err;
406                         }
407                 }
408         }
409         nla_nest_end(dcbnl_skb, nest);
410
411         nlmsg_end(dcbnl_skb, nlh);
412
413         ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
414         if (ret)
415                 goto err_out;
416
417         return 0;
418 nlmsg_failure:
419 err:
420         kfree_skb(dcbnl_skb);
421 err_out:
422         return -EINVAL;
423 }
424
425 static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
426                            u32 pid, u32 seq, u16 flags)
427 {
428         struct sk_buff *dcbnl_skb;
429         struct nlmsghdr *nlh;
430         struct dcbmsg *dcb;
431         struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
432         u8 value;
433         int ret = -EINVAL;
434         int i;
435         int getall = 0;
436
437         if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs)
438                 return ret;
439
440         ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
441                                dcbnl_numtcs_nest);
442         if (ret) {
443                 ret = -EINVAL;
444                 goto err_out;
445         }
446
447         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
448         if (!dcbnl_skb) {
449                 ret = -EINVAL;
450                 goto err_out;
451         }
452
453         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
454
455         dcb = NLMSG_DATA(nlh);
456         dcb->dcb_family = AF_UNSPEC;
457         dcb->cmd = DCB_CMD_GNUMTCS;
458
459         nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS);
460         if (!nest) {
461                 ret = -EINVAL;
462                 goto err;
463         }
464
465         if (data[DCB_NUMTCS_ATTR_ALL])
466                 getall = 1;
467
468         for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
469                 if (!getall && !data[i])
470                         continue;
471
472                 ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
473                 if (!ret) {
474                         ret = nla_put_u8(dcbnl_skb, i, value);
475
476                         if (ret) {
477                                 nla_nest_cancel(dcbnl_skb, nest);
478                                 ret = -EINVAL;
479                                 goto err;
480                         }
481                 } else {
482                         goto err;
483                 }
484         }
485         nla_nest_end(dcbnl_skb, nest);
486
487         nlmsg_end(dcbnl_skb, nlh);
488
489         ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
490         if (ret) {
491                 ret = -EINVAL;
492                 goto err_out;
493         }
494
495         return 0;
496 nlmsg_failure:
497 err:
498         kfree_skb(dcbnl_skb);
499 err_out:
500         return ret;
501 }
502
503 static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb,
504                            u32 pid, u32 seq, u16 flags)
505 {
506         struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
507         int ret = -EINVAL;
508         u8 value;
509         int i;
510
511         if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs)
512                 return ret;
513
514         ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
515                                dcbnl_numtcs_nest);
516
517         if (ret) {
518                 ret = -EINVAL;
519                 goto err;
520         }
521
522         for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
523                 if (data[i] == NULL)
524                         continue;
525
526                 value = nla_get_u8(data[i]);
527
528                 ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
529
530                 if (ret)
531                         goto operr;
532         }
533
534 operr:
535         ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS,
536                           DCB_ATTR_NUMTCS, pid, seq, flags);
537
538 err:
539         return ret;
540 }
541
542 static int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb,
543                              u32 pid, u32 seq, u16 flags)
544 {
545         int ret = -EINVAL;
546
547         if (!netdev->dcbnl_ops->getpfcstate)
548                 return ret;
549
550         ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB,
551                           DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE,
552                           pid, seq, flags);
553
554         return ret;
555 }
556
557 static int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb,
558                              u32 pid, u32 seq, u16 flags)
559 {
560         int ret = -EINVAL;
561         u8 value;
562
563         if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate)
564                 return ret;
565
566         value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
567
568         netdev->dcbnl_ops->setpfcstate(netdev, value);
569
570         ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE,
571                           pid, seq, flags);
572
573         return ret;
574 }
575
576 static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
577                         u32 pid, u32 seq, u16 flags)
578 {
579         struct sk_buff *dcbnl_skb;
580         struct nlmsghdr *nlh;
581         struct dcbmsg *dcb;
582         struct nlattr *app_nest;
583         struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
584         u16 id;
585         u8 up, idtype;
586         int ret = -EINVAL;
587
588         if (!tb[DCB_ATTR_APP])
589                 goto out;
590
591         ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
592                                dcbnl_app_nest);
593         if (ret)
594                 goto out;
595
596         ret = -EINVAL;
597         /* all must be non-null */
598         if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
599             (!app_tb[DCB_APP_ATTR_ID]))
600                 goto out;
601
602         /* either by eth type or by socket number */
603         idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
604         if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
605             (idtype != DCB_APP_IDTYPE_PORTNUM))
606                 goto out;
607
608         id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
609
610         if (netdev->dcbnl_ops->getapp) {
611                 up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
612         } else {
613                 struct dcb_app app = {
614                                         .selector = idtype,
615                                         .protocol = id,
616                                      };
617                 up = dcb_getapp(netdev, &app);
618         }
619
620         /* send this back */
621         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
622         if (!dcbnl_skb)
623                 goto out;
624
625         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
626         dcb = NLMSG_DATA(nlh);
627         dcb->dcb_family = AF_UNSPEC;
628         dcb->cmd = DCB_CMD_GAPP;
629
630         app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP);
631         if (!app_nest)
632                 goto out_cancel;
633
634         ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype);
635         if (ret)
636                 goto out_cancel;
637
638         ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id);
639         if (ret)
640                 goto out_cancel;
641
642         ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up);
643         if (ret)
644                 goto out_cancel;
645
646         nla_nest_end(dcbnl_skb, app_nest);
647         nlmsg_end(dcbnl_skb, nlh);
648
649         ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
650         if (ret)
651                 goto nlmsg_failure;
652
653         goto out;
654
655 out_cancel:
656         nla_nest_cancel(dcbnl_skb, app_nest);
657 nlmsg_failure:
658         kfree_skb(dcbnl_skb);
659 out:
660         return ret;
661 }
662
663 static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
664                         u32 pid, u32 seq, u16 flags)
665 {
666         int err, ret = -EINVAL;
667         u16 id;
668         u8 up, idtype;
669         struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
670
671         if (!tb[DCB_ATTR_APP])
672                 goto out;
673
674         ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
675                                dcbnl_app_nest);
676         if (ret)
677                 goto out;
678
679         ret = -EINVAL;
680         /* all must be non-null */
681         if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
682             (!app_tb[DCB_APP_ATTR_ID]) ||
683             (!app_tb[DCB_APP_ATTR_PRIORITY]))
684                 goto out;
685
686         /* either by eth type or by socket number */
687         idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
688         if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
689             (idtype != DCB_APP_IDTYPE_PORTNUM))
690                 goto out;
691
692         id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
693         up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
694
695         if (netdev->dcbnl_ops->setapp) {
696                 err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
697         } else {
698                 struct dcb_app app;
699                 app.selector = idtype;
700                 app.protocol = id;
701                 app.priority = up;
702                 err = dcb_setapp(netdev, &app);
703         }
704
705         ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
706                           pid, seq, flags);
707         dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0);
708 out:
709         return ret;
710 }
711
712 static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
713                              u32 pid, u32 seq, u16 flags, int dir)
714 {
715         struct sk_buff *dcbnl_skb;
716         struct nlmsghdr *nlh;
717         struct dcbmsg *dcb;
718         struct nlattr *pg_nest, *param_nest, *data;
719         struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
720         struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
721         u8 prio, pgid, tc_pct, up_map;
722         int ret  = -EINVAL;
723         int getall = 0;
724         int i;
725
726         if (!tb[DCB_ATTR_PG_CFG] ||
727             !netdev->dcbnl_ops->getpgtccfgtx ||
728             !netdev->dcbnl_ops->getpgtccfgrx ||
729             !netdev->dcbnl_ops->getpgbwgcfgtx ||
730             !netdev->dcbnl_ops->getpgbwgcfgrx)
731                 return ret;
732
733         ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
734                                tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
735
736         if (ret)
737                 goto err_out;
738
739         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
740         if (!dcbnl_skb)
741                 goto err_out;
742
743         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
744
745         dcb = NLMSG_DATA(nlh);
746         dcb->dcb_family = AF_UNSPEC;
747         dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG;
748
749         pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG);
750         if (!pg_nest)
751                 goto err;
752
753         if (pg_tb[DCB_PG_ATTR_TC_ALL])
754                 getall = 1;
755
756         for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
757                 if (!getall && !pg_tb[i])
758                         continue;
759
760                 if (pg_tb[DCB_PG_ATTR_TC_ALL])
761                         data = pg_tb[DCB_PG_ATTR_TC_ALL];
762                 else
763                         data = pg_tb[i];
764                 ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
765                                        data, dcbnl_tc_param_nest);
766                 if (ret)
767                         goto err_pg;
768
769                 param_nest = nla_nest_start(dcbnl_skb, i);
770                 if (!param_nest)
771                         goto err_pg;
772
773                 pgid = DCB_ATTR_VALUE_UNDEFINED;
774                 prio = DCB_ATTR_VALUE_UNDEFINED;
775                 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
776                 up_map = DCB_ATTR_VALUE_UNDEFINED;
777
778                 if (dir) {
779                         /* Rx */
780                         netdev->dcbnl_ops->getpgtccfgrx(netdev,
781                                                 i - DCB_PG_ATTR_TC_0, &prio,
782                                                 &pgid, &tc_pct, &up_map);
783                 } else {
784                         /* Tx */
785                         netdev->dcbnl_ops->getpgtccfgtx(netdev,
786                                                 i - DCB_PG_ATTR_TC_0, &prio,
787                                                 &pgid, &tc_pct, &up_map);
788                 }
789
790                 if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
791                     param_tb[DCB_TC_ATTR_PARAM_ALL]) {
792                         ret = nla_put_u8(dcbnl_skb,
793                                          DCB_TC_ATTR_PARAM_PGID, pgid);
794                         if (ret)
795                                 goto err_param;
796                 }
797                 if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
798                     param_tb[DCB_TC_ATTR_PARAM_ALL]) {
799                         ret = nla_put_u8(dcbnl_skb,
800                                          DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
801                         if (ret)
802                                 goto err_param;
803                 }
804                 if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
805                     param_tb[DCB_TC_ATTR_PARAM_ALL]) {
806                         ret = nla_put_u8(dcbnl_skb,
807                                          DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
808                         if (ret)
809                                 goto err_param;
810                 }
811                 if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
812                     param_tb[DCB_TC_ATTR_PARAM_ALL]) {
813                         ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT,
814                                          tc_pct);
815                         if (ret)
816                                 goto err_param;
817                 }
818                 nla_nest_end(dcbnl_skb, param_nest);
819         }
820
821         if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
822                 getall = 1;
823         else
824                 getall = 0;
825
826         for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
827                 if (!getall && !pg_tb[i])
828                         continue;
829
830                 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
831
832                 if (dir) {
833                         /* Rx */
834                         netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
835                                         i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
836                 } else {
837                         /* Tx */
838                         netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
839                                         i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
840                 }
841                 ret = nla_put_u8(dcbnl_skb, i, tc_pct);
842
843                 if (ret)
844                         goto err_pg;
845         }
846
847         nla_nest_end(dcbnl_skb, pg_nest);
848
849         nlmsg_end(dcbnl_skb, nlh);
850
851         ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
852         if (ret)
853                 goto err_out;
854
855         return 0;
856
857 err_param:
858         nla_nest_cancel(dcbnl_skb, param_nest);
859 err_pg:
860         nla_nest_cancel(dcbnl_skb, pg_nest);
861 nlmsg_failure:
862 err:
863         kfree_skb(dcbnl_skb);
864 err_out:
865         ret  = -EINVAL;
866         return ret;
867 }
868
869 static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb,
870                              u32 pid, u32 seq, u16 flags)
871 {
872         return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0);
873 }
874
875 static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb,
876                              u32 pid, u32 seq, u16 flags)
877 {
878         return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1);
879 }
880
881 static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb,
882                           u32 pid, u32 seq, u16 flags)
883 {
884         int ret = -EINVAL;
885         u8 value;
886
887         if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate)
888                 return ret;
889
890         value = nla_get_u8(tb[DCB_ATTR_STATE]);
891
892         ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value),
893                           RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
894                           pid, seq, flags);
895
896         return ret;
897 }
898
899 static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb,
900                            u32 pid, u32 seq, u16 flags)
901 {
902         struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
903         int i;
904         int ret = -EINVAL;
905         u8 value;
906
907         if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg)
908                 return ret;
909
910         ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
911                                tb[DCB_ATTR_PFC_CFG],
912                                dcbnl_pfc_up_nest);
913         if (ret)
914                 goto err;
915
916         for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
917                 if (data[i] == NULL)
918                         continue;
919                 value = nla_get_u8(data[i]);
920                 netdev->dcbnl_ops->setpfccfg(netdev,
921                         data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
922         }
923
924         ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG,
925                           pid, seq, flags);
926 err:
927         return ret;
928 }
929
930 static int dcbnl_setall(struct net_device *netdev, struct nlattr **tb,
931                         u32 pid, u32 seq, u16 flags)
932 {
933         int ret = -EINVAL;
934
935         if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall)
936                 return ret;
937
938         ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB,
939                           DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags);
940         dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0);
941
942         return ret;
943 }
944
945 static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb,
946                              u32 pid, u32 seq, u16 flags, int dir)
947 {
948         struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
949         struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
950         int ret = -EINVAL;
951         int i;
952         u8 pgid;
953         u8 up_map;
954         u8 prio;
955         u8 tc_pct;
956
957         if (!tb[DCB_ATTR_PG_CFG] ||
958             !netdev->dcbnl_ops->setpgtccfgtx ||
959             !netdev->dcbnl_ops->setpgtccfgrx ||
960             !netdev->dcbnl_ops->setpgbwgcfgtx ||
961             !netdev->dcbnl_ops->setpgbwgcfgrx)
962                 return ret;
963
964         ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
965                                tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
966         if (ret)
967                 goto err;
968
969         for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
970                 if (!pg_tb[i])
971                         continue;
972
973                 ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
974                                        pg_tb[i], dcbnl_tc_param_nest);
975                 if (ret)
976                         goto err;
977
978                 pgid = DCB_ATTR_VALUE_UNDEFINED;
979                 prio = DCB_ATTR_VALUE_UNDEFINED;
980                 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
981                 up_map = DCB_ATTR_VALUE_UNDEFINED;
982
983                 if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
984                         prio =
985                             nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
986
987                 if (param_tb[DCB_TC_ATTR_PARAM_PGID])
988                         pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
989
990                 if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
991                         tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
992
993                 if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
994                         up_map =
995                              nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
996
997                 /* dir: Tx = 0, Rx = 1 */
998                 if (dir) {
999                         /* Rx */
1000                         netdev->dcbnl_ops->setpgtccfgrx(netdev,
1001                                 i - DCB_PG_ATTR_TC_0,
1002                                 prio, pgid, tc_pct, up_map);
1003                 } else {
1004                         /* Tx */
1005                         netdev->dcbnl_ops->setpgtccfgtx(netdev,
1006                                 i - DCB_PG_ATTR_TC_0,
1007                                 prio, pgid, tc_pct, up_map);
1008                 }
1009         }
1010
1011         for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
1012                 if (!pg_tb[i])
1013                         continue;
1014
1015                 tc_pct = nla_get_u8(pg_tb[i]);
1016
1017                 /* dir: Tx = 0, Rx = 1 */
1018                 if (dir) {
1019                         /* Rx */
1020                         netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
1021                                          i - DCB_PG_ATTR_BW_ID_0, tc_pct);
1022                 } else {
1023                         /* Tx */
1024                         netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
1025                                          i - DCB_PG_ATTR_BW_ID_0, tc_pct);
1026                 }
1027         }
1028
1029         ret = dcbnl_reply(0, RTM_SETDCB,
1030                           (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG),
1031                           DCB_ATTR_PG_CFG, pid, seq, flags);
1032
1033 err:
1034         return ret;
1035 }
1036
1037 static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb,
1038                              u32 pid, u32 seq, u16 flags)
1039 {
1040         return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0);
1041 }
1042
1043 static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb,
1044                              u32 pid, u32 seq, u16 flags)
1045 {
1046         return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1);
1047 }
1048
1049 static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb,
1050                             u32 pid, u32 seq, u16 flags)
1051 {
1052         struct sk_buff *dcbnl_skb;
1053         struct nlmsghdr *nlh;
1054         struct dcbmsg *dcb;
1055         struct nlattr *bcn_nest;
1056         struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
1057         u8 value_byte;
1058         u32 value_integer;
1059         int ret  = -EINVAL;
1060         bool getall = false;
1061         int i;
1062
1063         if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp ||
1064             !netdev->dcbnl_ops->getbcncfg)
1065                 return ret;
1066
1067         ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
1068                                tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
1069
1070         if (ret)
1071                 goto err_out;
1072
1073         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1074         if (!dcbnl_skb)
1075                 goto err_out;
1076
1077         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1078
1079         dcb = NLMSG_DATA(nlh);
1080         dcb->dcb_family = AF_UNSPEC;
1081         dcb->cmd = DCB_CMD_BCN_GCFG;
1082
1083         bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN);
1084         if (!bcn_nest)
1085                 goto err;
1086
1087         if (bcn_tb[DCB_BCN_ATTR_ALL])
1088                 getall = true;
1089
1090         for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1091                 if (!getall && !bcn_tb[i])
1092                         continue;
1093
1094                 netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
1095                                             &value_byte);
1096                 ret = nla_put_u8(dcbnl_skb, i, value_byte);
1097                 if (ret)
1098                         goto err_bcn;
1099         }
1100
1101         for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1102                 if (!getall && !bcn_tb[i])
1103                         continue;
1104
1105                 netdev->dcbnl_ops->getbcncfg(netdev, i,
1106                                              &value_integer);
1107                 ret = nla_put_u32(dcbnl_skb, i, value_integer);
1108                 if (ret)
1109                         goto err_bcn;
1110         }
1111
1112         nla_nest_end(dcbnl_skb, bcn_nest);
1113
1114         nlmsg_end(dcbnl_skb, nlh);
1115
1116         ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
1117         if (ret)
1118                 goto err_out;
1119
1120         return 0;
1121
1122 err_bcn:
1123         nla_nest_cancel(dcbnl_skb, bcn_nest);
1124 nlmsg_failure:
1125 err:
1126         kfree_skb(dcbnl_skb);
1127 err_out:
1128         ret  = -EINVAL;
1129         return ret;
1130 }
1131
1132 static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb,
1133                             u32 pid, u32 seq, u16 flags)
1134 {
1135         struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
1136         int i;
1137         int ret = -EINVAL;
1138         u8 value_byte;
1139         u32 value_int;
1140
1141         if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg ||
1142             !netdev->dcbnl_ops->setbcnrp)
1143                 return ret;
1144
1145         ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
1146                                tb[DCB_ATTR_BCN],
1147                                dcbnl_pfc_up_nest);
1148         if (ret)
1149                 goto err;
1150
1151         for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1152                 if (data[i] == NULL)
1153                         continue;
1154                 value_byte = nla_get_u8(data[i]);
1155                 netdev->dcbnl_ops->setbcnrp(netdev,
1156                         data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
1157         }
1158
1159         for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1160                 if (data[i] == NULL)
1161                         continue;
1162                 value_int = nla_get_u32(data[i]);
1163                 netdev->dcbnl_ops->setbcncfg(netdev,
1164                                              i, value_int);
1165         }
1166
1167         ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN,
1168                           pid, seq, flags);
1169 err:
1170         return ret;
1171 }
1172
1173 static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
1174                                 int app_nested_type, int app_info_type,
1175                                 int app_entry_type)
1176 {
1177         struct dcb_peer_app_info info;
1178         struct dcb_app *table = NULL;
1179         const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1180         u16 app_count;
1181         int err;
1182
1183
1184         /**
1185          * retrieve the peer app configuration form the driver. If the driver
1186          * handlers fail exit without doing anything
1187          */
1188         err = ops->peer_getappinfo(netdev, &info, &app_count);
1189         if (!err && app_count) {
1190                 table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
1191                 if (!table)
1192                         return -ENOMEM;
1193
1194                 err = ops->peer_getapptable(netdev, table);
1195         }
1196
1197         if (!err) {
1198                 u16 i;
1199                 struct nlattr *app;
1200
1201                 /**
1202                  * build the message, from here on the only possible failure
1203                  * is due to the skb size
1204                  */
1205                 err = -EMSGSIZE;
1206
1207                 app = nla_nest_start(skb, app_nested_type);
1208                 if (!app)
1209                         goto nla_put_failure;
1210
1211                 if (app_info_type &&
1212                     nla_put(skb, app_info_type, sizeof(info), &info))
1213                         goto nla_put_failure;
1214
1215                 for (i = 0; i < app_count; i++) {
1216                         if (nla_put(skb, app_entry_type, sizeof(struct dcb_app),
1217                                     &table[i]))
1218                                 goto nla_put_failure;
1219                 }
1220                 nla_nest_end(skb, app);
1221         }
1222         err = 0;
1223
1224 nla_put_failure:
1225         kfree(table);
1226         return err;
1227 }
1228
1229 /* Handle IEEE 802.1Qaz GET commands. */
1230 static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
1231 {
1232         struct nlattr *ieee, *app;
1233         struct dcb_app_type *itr;
1234         const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1235         int dcbx;
1236         int err = -EMSGSIZE;
1237
1238         if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
1239                 goto nla_put_failure;
1240         ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
1241         if (!ieee)
1242                 goto nla_put_failure;
1243
1244         if (ops->ieee_getets) {
1245                 struct ieee_ets ets;
1246                 err = ops->ieee_getets(netdev, &ets);
1247                 if (!err &&
1248                     nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
1249                         goto nla_put_failure;
1250         }
1251
1252         if (ops->ieee_getmaxrate) {
1253                 struct ieee_maxrate maxrate;
1254                 err = ops->ieee_getmaxrate(netdev, &maxrate);
1255                 if (!err) {
1256                         err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
1257                                       sizeof(maxrate), &maxrate);
1258                         if (err)
1259                                 goto nla_put_failure;
1260                 }
1261         }
1262
1263         if (ops->ieee_getpfc) {
1264                 struct ieee_pfc pfc;
1265                 err = ops->ieee_getpfc(netdev, &pfc);
1266                 if (!err &&
1267                     nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
1268                         goto nla_put_failure;
1269         }
1270
1271         app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
1272         if (!app)
1273                 goto nla_put_failure;
1274
1275         spin_lock(&dcb_lock);
1276         list_for_each_entry(itr, &dcb_app_list, list) {
1277                 if (itr->ifindex == netdev->ifindex) {
1278                         err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
1279                                          &itr->app);
1280                         if (err) {
1281                                 spin_unlock(&dcb_lock);
1282                                 goto nla_put_failure;
1283                         }
1284                 }
1285         }
1286
1287         if (netdev->dcbnl_ops->getdcbx)
1288                 dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1289         else
1290                 dcbx = -EOPNOTSUPP;
1291
1292         spin_unlock(&dcb_lock);
1293         nla_nest_end(skb, app);
1294
1295         /* get peer info if available */
1296         if (ops->ieee_peer_getets) {
1297                 struct ieee_ets ets;
1298                 err = ops->ieee_peer_getets(netdev, &ets);
1299                 if (!err &&
1300                     nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
1301                         goto nla_put_failure;
1302         }
1303
1304         if (ops->ieee_peer_getpfc) {
1305                 struct ieee_pfc pfc;
1306                 err = ops->ieee_peer_getpfc(netdev, &pfc);
1307                 if (!err &&
1308                     nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
1309                         goto nla_put_failure;
1310         }
1311
1312         if (ops->peer_getappinfo && ops->peer_getapptable) {
1313                 err = dcbnl_build_peer_app(netdev, skb,
1314                                            DCB_ATTR_IEEE_PEER_APP,
1315                                            DCB_ATTR_IEEE_APP_UNSPEC,
1316                                            DCB_ATTR_IEEE_APP);
1317                 if (err)
1318                         goto nla_put_failure;
1319         }
1320
1321         nla_nest_end(skb, ieee);
1322         if (dcbx >= 0) {
1323                 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1324                 if (err)
1325                         goto nla_put_failure;
1326         }
1327
1328         return 0;
1329
1330 nla_put_failure:
1331         return err;
1332 }
1333
1334 static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
1335                              int dir)
1336 {
1337         u8 pgid, up_map, prio, tc_pct;
1338         const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1339         int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
1340         struct nlattr *pg = nla_nest_start(skb, i);
1341
1342         if (!pg)
1343                 goto nla_put_failure;
1344
1345         for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
1346                 struct nlattr *tc_nest = nla_nest_start(skb, i);
1347
1348                 if (!tc_nest)
1349                         goto nla_put_failure;
1350
1351                 pgid = DCB_ATTR_VALUE_UNDEFINED;
1352                 prio = DCB_ATTR_VALUE_UNDEFINED;
1353                 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
1354                 up_map = DCB_ATTR_VALUE_UNDEFINED;
1355
1356                 if (!dir)
1357                         ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
1358                                           &prio, &pgid, &tc_pct, &up_map);
1359                 else
1360                         ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
1361                                           &prio, &pgid, &tc_pct, &up_map);
1362
1363                 if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) ||
1364                     nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) ||
1365                     nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) ||
1366                     nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct))
1367                         goto nla_put_failure;
1368                 nla_nest_end(skb, tc_nest);
1369         }
1370
1371         for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
1372                 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
1373
1374                 if (!dir)
1375                         ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
1376                                            &tc_pct);
1377                 else
1378                         ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
1379                                            &tc_pct);
1380                 if (nla_put_u8(skb, i, tc_pct))
1381                         goto nla_put_failure;
1382         }
1383         nla_nest_end(skb, pg);
1384         return 0;
1385
1386 nla_put_failure:
1387         return -EMSGSIZE;
1388 }
1389
1390 static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1391 {
1392         struct nlattr *cee, *app;
1393         struct dcb_app_type *itr;
1394         const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1395         int dcbx, i, err = -EMSGSIZE;
1396         u8 value;
1397
1398         if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
1399                 goto nla_put_failure;
1400         cee = nla_nest_start(skb, DCB_ATTR_CEE);
1401         if (!cee)
1402                 goto nla_put_failure;
1403
1404         /* local pg */
1405         if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
1406                 err = dcbnl_cee_pg_fill(skb, netdev, 1);
1407                 if (err)
1408                         goto nla_put_failure;
1409         }
1410
1411         if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
1412                 err = dcbnl_cee_pg_fill(skb, netdev, 0);
1413                 if (err)
1414                         goto nla_put_failure;
1415         }
1416
1417         /* local pfc */
1418         if (ops->getpfccfg) {
1419                 struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
1420
1421                 if (!pfc_nest)
1422                         goto nla_put_failure;
1423
1424                 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
1425                         ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
1426                         if (nla_put_u8(skb, i, value))
1427                                 goto nla_put_failure;
1428                 }
1429                 nla_nest_end(skb, pfc_nest);
1430         }
1431
1432         /* local app */
1433         spin_lock(&dcb_lock);
1434         app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
1435         if (!app)
1436                 goto dcb_unlock;
1437
1438         list_for_each_entry(itr, &dcb_app_list, list) {
1439                 if (itr->ifindex == netdev->ifindex) {
1440                         struct nlattr *app_nest = nla_nest_start(skb,
1441                                                                  DCB_ATTR_APP);
1442                         if (!app_nest)
1443                                 goto dcb_unlock;
1444
1445                         err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
1446                                          itr->app.selector);
1447                         if (err)
1448                                 goto dcb_unlock;
1449
1450                         err = nla_put_u16(skb, DCB_APP_ATTR_ID,
1451                                           itr->app.protocol);
1452                         if (err)
1453                                 goto dcb_unlock;
1454
1455                         err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
1456                                          itr->app.priority);
1457                         if (err)
1458                                 goto dcb_unlock;
1459
1460                         nla_nest_end(skb, app_nest);
1461                 }
1462         }
1463         nla_nest_end(skb, app);
1464
1465         if (netdev->dcbnl_ops->getdcbx)
1466                 dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1467         else
1468                 dcbx = -EOPNOTSUPP;
1469
1470         spin_unlock(&dcb_lock);
1471
1472         /* features flags */
1473         if (ops->getfeatcfg) {
1474                 struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
1475                 if (!feat)
1476                         goto nla_put_failure;
1477
1478                 for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
1479                      i++)
1480                         if (!ops->getfeatcfg(netdev, i, &value) &&
1481                             nla_put_u8(skb, i, value))
1482                                 goto nla_put_failure;
1483
1484                 nla_nest_end(skb, feat);
1485         }
1486
1487         /* peer info if available */
1488         if (ops->cee_peer_getpg) {
1489                 struct cee_pg pg;
1490                 err = ops->cee_peer_getpg(netdev, &pg);
1491                 if (!err &&
1492                     nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
1493                         goto nla_put_failure;
1494         }
1495
1496         if (ops->cee_peer_getpfc) {
1497                 struct cee_pfc pfc;
1498                 err = ops->cee_peer_getpfc(netdev, &pfc);
1499                 if (!err &&
1500                     nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
1501                         goto nla_put_failure;
1502         }
1503
1504         if (ops->peer_getappinfo && ops->peer_getapptable) {
1505                 err = dcbnl_build_peer_app(netdev, skb,
1506                                            DCB_ATTR_CEE_PEER_APP_TABLE,
1507                                            DCB_ATTR_CEE_PEER_APP_INFO,
1508                                            DCB_ATTR_CEE_PEER_APP);
1509                 if (err)
1510                         goto nla_put_failure;
1511         }
1512         nla_nest_end(skb, cee);
1513
1514         /* DCBX state */
1515         if (dcbx >= 0) {
1516                 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1517                 if (err)
1518                         goto nla_put_failure;
1519         }
1520         return 0;
1521
1522 dcb_unlock:
1523         spin_unlock(&dcb_lock);
1524 nla_put_failure:
1525         return err;
1526 }
1527
1528 static int dcbnl_notify(struct net_device *dev, int event, int cmd,
1529                         u32 seq, u32 pid, int dcbx_ver)
1530 {
1531         struct net *net = dev_net(dev);
1532         struct sk_buff *skb;
1533         struct nlmsghdr *nlh;
1534         struct dcbmsg *dcb;
1535         const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1536         int err;
1537
1538         if (!ops)
1539                 return -EOPNOTSUPP;
1540
1541         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1542         if (!skb)
1543                 return -ENOBUFS;
1544
1545         nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
1546         if (nlh == NULL) {
1547                 nlmsg_free(skb);
1548                 return -EMSGSIZE;
1549         }
1550
1551         dcb = NLMSG_DATA(nlh);
1552         dcb->dcb_family = AF_UNSPEC;
1553         dcb->cmd = cmd;
1554
1555         if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
1556                 err = dcbnl_ieee_fill(skb, dev);
1557         else
1558                 err = dcbnl_cee_fill(skb, dev);
1559
1560         if (err < 0) {
1561                 /* Report error to broadcast listeners */
1562                 nlmsg_cancel(skb, nlh);
1563                 kfree_skb(skb);
1564                 rtnl_set_sk_err(net, RTNLGRP_DCB, err);
1565         } else {
1566                 /* End nlmsg and notify broadcast listeners */
1567                 nlmsg_end(skb, nlh);
1568                 rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
1569         }
1570
1571         return err;
1572 }
1573
1574 int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
1575                       u32 seq, u32 pid)
1576 {
1577         return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_IEEE);
1578 }
1579 EXPORT_SYMBOL(dcbnl_ieee_notify);
1580
1581 int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
1582                      u32 seq, u32 pid)
1583 {
1584         return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_CEE);
1585 }
1586 EXPORT_SYMBOL(dcbnl_cee_notify);
1587
1588 /* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1589  * be completed the entire msg is aborted and error value is returned.
1590  * No attempt is made to reconcile the case where only part of the
1591  * cmd can be completed.
1592  */
1593 static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1594                           u32 pid, u32 seq, u16 flags)
1595 {
1596         const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1597         struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1598         int err = -EOPNOTSUPP;
1599
1600         if (!ops)
1601                 return err;
1602
1603         if (!tb[DCB_ATTR_IEEE])
1604                 return -EINVAL;
1605
1606         err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1607                                tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1608         if (err)
1609                 return err;
1610
1611         if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1612                 struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1613                 err = ops->ieee_setets(netdev, ets);
1614                 if (err)
1615                         goto err;
1616         }
1617
1618         if (ieee[DCB_ATTR_IEEE_MAXRATE] && ops->ieee_setmaxrate) {
1619                 struct ieee_maxrate *maxrate =
1620                         nla_data(ieee[DCB_ATTR_IEEE_MAXRATE]);
1621                 err = ops->ieee_setmaxrate(netdev, maxrate);
1622                 if (err)
1623                         goto err;
1624         }
1625
1626         if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1627                 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1628                 err = ops->ieee_setpfc(netdev, pfc);
1629                 if (err)
1630                         goto err;
1631         }
1632
1633         if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1634                 struct nlattr *attr;
1635                 int rem;
1636
1637                 nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1638                         struct dcb_app *app_data;
1639                         if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1640                                 continue;
1641                         app_data = nla_data(attr);
1642                         if (ops->ieee_setapp)
1643                                 err = ops->ieee_setapp(netdev, app_data);
1644                         else
1645                                 err = dcb_ieee_setapp(netdev, app_data);
1646                         if (err)
1647                                 goto err;
1648                 }
1649         }
1650
1651 err:
1652         dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
1653                     pid, seq, flags);
1654         dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
1655         return err;
1656 }
1657
1658 static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1659                           u32 pid, u32 seq, u16 flags)
1660 {
1661         struct net *net = dev_net(netdev);
1662         struct sk_buff *skb;
1663         struct nlmsghdr *nlh;
1664         struct dcbmsg *dcb;
1665         const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1666         int err;
1667
1668         if (!ops)
1669                 return -EOPNOTSUPP;
1670
1671         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1672         if (!skb)
1673                 return -ENOBUFS;
1674
1675         nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1676         if (nlh == NULL) {
1677                 nlmsg_free(skb);
1678                 return -EMSGSIZE;
1679         }
1680
1681         dcb = NLMSG_DATA(nlh);
1682         dcb->dcb_family = AF_UNSPEC;
1683         dcb->cmd = DCB_CMD_IEEE_GET;
1684
1685         err = dcbnl_ieee_fill(skb, netdev);
1686
1687         if (err < 0) {
1688                 nlmsg_cancel(skb, nlh);
1689                 kfree_skb(skb);
1690         } else {
1691                 nlmsg_end(skb, nlh);
1692                 err = rtnl_unicast(skb, net, pid);
1693         }
1694
1695         return err;
1696 }
1697
1698 static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
1699                           u32 pid, u32 seq, u16 flags)
1700 {
1701         const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1702         struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1703         int err = -EOPNOTSUPP;
1704
1705         if (!ops)
1706                 return -EOPNOTSUPP;
1707
1708         if (!tb[DCB_ATTR_IEEE])
1709                 return -EINVAL;
1710
1711         err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1712                                tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1713         if (err)
1714                 return err;
1715
1716         if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1717                 struct nlattr *attr;
1718                 int rem;
1719
1720                 nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1721                         struct dcb_app *app_data;
1722
1723                         if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1724                                 continue;
1725                         app_data = nla_data(attr);
1726                         if (ops->ieee_delapp)
1727                                 err = ops->ieee_delapp(netdev, app_data);
1728                         else
1729                                 err = dcb_ieee_delapp(netdev, app_data);
1730                         if (err)
1731                                 goto err;
1732                 }
1733         }
1734
1735 err:
1736         dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
1737                     pid, seq, flags);
1738         dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
1739         return err;
1740 }
1741
1742
1743 /* DCBX configuration */
1744 static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
1745                          u32 pid, u32 seq, u16 flags)
1746 {
1747         int ret;
1748
1749         if (!netdev->dcbnl_ops->getdcbx)
1750                 return -EOPNOTSUPP;
1751
1752         ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB,
1753                           DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags);
1754
1755         return ret;
1756 }
1757
1758 static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb,
1759                          u32 pid, u32 seq, u16 flags)
1760 {
1761         int ret;
1762         u8 value;
1763
1764         if (!netdev->dcbnl_ops->setdcbx)
1765                 return -EOPNOTSUPP;
1766
1767         if (!tb[DCB_ATTR_DCBX])
1768                 return -EINVAL;
1769
1770         value = nla_get_u8(tb[DCB_ATTR_DCBX]);
1771
1772         ret = dcbnl_reply(netdev->dcbnl_ops->setdcbx(netdev, value),
1773                           RTM_SETDCB, DCB_CMD_SDCBX, DCB_ATTR_DCBX,
1774                           pid, seq, flags);
1775
1776         return ret;
1777 }
1778
1779 static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
1780                             u32 pid, u32 seq, u16 flags)
1781 {
1782         struct sk_buff *dcbnl_skb;
1783         struct nlmsghdr *nlh;
1784         struct dcbmsg *dcb;
1785         struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
1786         u8 value;
1787         int ret, i;
1788         int getall = 0;
1789
1790         if (!netdev->dcbnl_ops->getfeatcfg)
1791                 return -EOPNOTSUPP;
1792
1793         if (!tb[DCB_ATTR_FEATCFG])
1794                 return -EINVAL;
1795
1796         ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1797                                dcbnl_featcfg_nest);
1798         if (ret)
1799                 goto err_out;
1800
1801         dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1802         if (!dcbnl_skb) {
1803                 ret = -ENOBUFS;
1804                 goto err_out;
1805         }
1806
1807         nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1808
1809         dcb = NLMSG_DATA(nlh);
1810         dcb->dcb_family = AF_UNSPEC;
1811         dcb->cmd = DCB_CMD_GFEATCFG;
1812
1813         nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG);
1814         if (!nest) {
1815                 ret = -EMSGSIZE;
1816                 goto nla_put_failure;
1817         }
1818
1819         if (data[DCB_FEATCFG_ATTR_ALL])
1820                 getall = 1;
1821
1822         for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1823                 if (!getall && !data[i])
1824                         continue;
1825
1826                 ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
1827                 if (!ret)
1828                         ret = nla_put_u8(dcbnl_skb, i, value);
1829
1830                 if (ret) {
1831                         nla_nest_cancel(dcbnl_skb, nest);
1832                         goto nla_put_failure;
1833                 }
1834         }
1835         nla_nest_end(dcbnl_skb, nest);
1836
1837         nlmsg_end(dcbnl_skb, nlh);
1838
1839         return rtnl_unicast(dcbnl_skb, &init_net, pid);
1840 nla_put_failure:
1841         nlmsg_cancel(dcbnl_skb, nlh);
1842 nlmsg_failure:
1843         kfree_skb(dcbnl_skb);
1844 err_out:
1845         return ret;
1846 }
1847
1848 static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb,
1849                             u32 pid, u32 seq, u16 flags)
1850 {
1851         struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
1852         int ret, i;
1853         u8 value;
1854
1855         if (!netdev->dcbnl_ops->setfeatcfg)
1856                 return -ENOTSUPP;
1857
1858         if (!tb[DCB_ATTR_FEATCFG])
1859                 return -EINVAL;
1860
1861         ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1862                                dcbnl_featcfg_nest);
1863
1864         if (ret)
1865                 goto err;
1866
1867         for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1868                 if (data[i] == NULL)
1869                         continue;
1870
1871                 value = nla_get_u8(data[i]);
1872
1873                 ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value);
1874
1875                 if (ret)
1876                         goto err;
1877         }
1878 err:
1879         dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG,
1880                     pid, seq, flags);
1881
1882         return ret;
1883 }
1884
1885 /* Handle CEE DCBX GET commands. */
1886 static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1887                          u32 pid, u32 seq, u16 flags)
1888 {
1889         struct net *net = dev_net(netdev);
1890         struct sk_buff *skb;
1891         struct nlmsghdr *nlh;
1892         struct dcbmsg *dcb;
1893         const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1894         int err;
1895
1896         if (!ops)
1897                 return -EOPNOTSUPP;
1898
1899         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1900         if (!skb)
1901                 return -ENOBUFS;
1902
1903         nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1904         if (nlh == NULL) {
1905                 nlmsg_free(skb);
1906                 return -EMSGSIZE;
1907         }
1908
1909         dcb = NLMSG_DATA(nlh);
1910         dcb->dcb_family = AF_UNSPEC;
1911         dcb->cmd = DCB_CMD_CEE_GET;
1912
1913         err = dcbnl_cee_fill(skb, netdev);
1914
1915         if (err < 0) {
1916                 nlmsg_cancel(skb, nlh);
1917                 nlmsg_free(skb);
1918         } else {
1919                 nlmsg_end(skb, nlh);
1920                 err = rtnl_unicast(skb, net, pid);
1921         }
1922         return err;
1923 }
1924
1925 static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1926 {
1927         struct net *net = sock_net(skb->sk);
1928         struct net_device *netdev;
1929         struct dcbmsg  *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
1930         struct nlattr *tb[DCB_ATTR_MAX + 1];
1931         u32 pid = skb ? NETLINK_CB(skb).pid : 0;
1932         int ret = -EINVAL;
1933
1934         if (!net_eq(net, &init_net))
1935                 return -EINVAL;
1936
1937         ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
1938                           dcbnl_rtnl_policy);
1939         if (ret < 0)
1940                 return ret;
1941
1942         if (!tb[DCB_ATTR_IFNAME])
1943                 return -EINVAL;
1944
1945         netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
1946         if (!netdev)
1947                 return -EINVAL;
1948
1949         if (!netdev->dcbnl_ops)
1950                 goto errout;
1951
1952         switch (dcb->cmd) {
1953         case DCB_CMD_GSTATE:
1954                 ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
1955                                      nlh->nlmsg_flags);
1956                 goto out;
1957         case DCB_CMD_PFC_GCFG:
1958                 ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
1959                                       nlh->nlmsg_flags);
1960                 goto out;
1961         case DCB_CMD_GPERM_HWADDR:
1962                 ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
1963                                            nlh->nlmsg_flags);
1964                 goto out;
1965         case DCB_CMD_PGTX_GCFG:
1966                 ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1967                                         nlh->nlmsg_flags);
1968                 goto out;
1969         case DCB_CMD_PGRX_GCFG:
1970                 ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1971                                         nlh->nlmsg_flags);
1972                 goto out;
1973         case DCB_CMD_BCN_GCFG:
1974                 ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1975                                        nlh->nlmsg_flags);
1976                 goto out;
1977         case DCB_CMD_SSTATE:
1978                 ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
1979                                      nlh->nlmsg_flags);
1980                 goto out;
1981         case DCB_CMD_PFC_SCFG:
1982                 ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
1983                                       nlh->nlmsg_flags);
1984                 goto out;
1985
1986         case DCB_CMD_SET_ALL:
1987                 ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
1988                                    nlh->nlmsg_flags);
1989                 goto out;
1990         case DCB_CMD_PGTX_SCFG:
1991                 ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
1992                                         nlh->nlmsg_flags);
1993                 goto out;
1994         case DCB_CMD_PGRX_SCFG:
1995                 ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
1996                                         nlh->nlmsg_flags);
1997                 goto out;
1998         case DCB_CMD_GCAP:
1999                 ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
2000                                    nlh->nlmsg_flags);
2001                 goto out;
2002         case DCB_CMD_GNUMTCS:
2003                 ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
2004                                       nlh->nlmsg_flags);
2005                 goto out;
2006         case DCB_CMD_SNUMTCS:
2007                 ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
2008                                       nlh->nlmsg_flags);
2009                 goto out;
2010         case DCB_CMD_PFC_GSTATE:
2011                 ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
2012                                         nlh->nlmsg_flags);
2013                 goto out;
2014         case DCB_CMD_PFC_SSTATE:
2015                 ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
2016                                         nlh->nlmsg_flags);
2017                 goto out;
2018         case DCB_CMD_BCN_SCFG:
2019                 ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
2020                                        nlh->nlmsg_flags);
2021                 goto out;
2022         case DCB_CMD_GAPP:
2023                 ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq,
2024                                    nlh->nlmsg_flags);
2025                 goto out;
2026         case DCB_CMD_SAPP:
2027                 ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
2028                                    nlh->nlmsg_flags);
2029                 goto out;
2030         case DCB_CMD_IEEE_SET:
2031                 ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
2032                                      nlh->nlmsg_flags);
2033                 goto out;
2034         case DCB_CMD_IEEE_GET:
2035                 ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
2036                                      nlh->nlmsg_flags);
2037                 goto out;
2038         case DCB_CMD_IEEE_DEL:
2039                 ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
2040                                      nlh->nlmsg_flags);
2041                 goto out;
2042         case DCB_CMD_GDCBX:
2043                 ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
2044                                     nlh->nlmsg_flags);
2045                 goto out;
2046         case DCB_CMD_SDCBX:
2047                 ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq,
2048                                     nlh->nlmsg_flags);
2049                 goto out;
2050         case DCB_CMD_GFEATCFG:
2051                 ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
2052                                        nlh->nlmsg_flags);
2053                 goto out;
2054         case DCB_CMD_SFEATCFG:
2055                 ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
2056                                        nlh->nlmsg_flags);
2057                 goto out;
2058         case DCB_CMD_CEE_GET:
2059                 ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq,
2060                                     nlh->nlmsg_flags);
2061                 goto out;
2062         default:
2063                 goto errout;
2064         }
2065 errout:
2066         ret = -EINVAL;
2067 out:
2068         dev_put(netdev);
2069         return ret;
2070 }
2071
2072 /**
2073  * dcb_getapp - retrieve the DCBX application user priority
2074  *
2075  * On success returns a non-zero 802.1p user priority bitmap
2076  * otherwise returns 0 as the invalid user priority bitmap to
2077  * indicate an error.
2078  */
2079 u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
2080 {
2081         struct dcb_app_type *itr;
2082         u8 prio = 0;
2083
2084         spin_lock(&dcb_lock);
2085         list_for_each_entry(itr, &dcb_app_list, list) {
2086                 if (itr->app.selector == app->selector &&
2087                     itr->app.protocol == app->protocol &&
2088                     itr->ifindex == dev->ifindex) {
2089                         prio = itr->app.priority;
2090                         break;
2091                 }
2092         }
2093         spin_unlock(&dcb_lock);
2094
2095         return prio;
2096 }
2097 EXPORT_SYMBOL(dcb_getapp);
2098
2099 /**
2100  * dcb_setapp - add CEE dcb application data to app list
2101  *
2102  * Priority 0 is an invalid priority in CEE spec. This routine
2103  * removes applications from the app list if the priority is
2104  * set to zero.
2105  */
2106 int dcb_setapp(struct net_device *dev, struct dcb_app *new)
2107 {
2108         struct dcb_app_type *itr;
2109         struct dcb_app_type event;
2110
2111         event.ifindex = dev->ifindex;
2112         memcpy(&event.app, new, sizeof(event.app));
2113         if (dev->dcbnl_ops->getdcbx)
2114                 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
2115
2116         spin_lock(&dcb_lock);
2117         /* Search for existing match and replace */
2118         list_for_each_entry(itr, &dcb_app_list, list) {
2119                 if (itr->app.selector == new->selector &&
2120                     itr->app.protocol == new->protocol &&
2121                     itr->ifindex == dev->ifindex) {
2122                         if (new->priority)
2123                                 itr->app.priority = new->priority;
2124                         else {
2125                                 list_del(&itr->list);
2126                                 kfree(itr);
2127                         }
2128                         goto out;
2129                 }
2130         }
2131         /* App type does not exist add new application type */
2132         if (new->priority) {
2133                 struct dcb_app_type *entry;
2134                 entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
2135                 if (!entry) {
2136                         spin_unlock(&dcb_lock);
2137                         return -ENOMEM;
2138                 }
2139
2140                 memcpy(&entry->app, new, sizeof(*new));
2141                 entry->ifindex = dev->ifindex;
2142                 list_add(&entry->list, &dcb_app_list);
2143         }
2144 out:
2145         spin_unlock(&dcb_lock);
2146         call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2147         return 0;
2148 }
2149 EXPORT_SYMBOL(dcb_setapp);
2150
2151 /**
2152  * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
2153  *
2154  * Helper routine which on success returns a non-zero 802.1Qaz user
2155  * priority bitmap otherwise returns 0 to indicate the dcb_app was
2156  * not found in APP list.
2157  */
2158 u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
2159 {
2160         struct dcb_app_type *itr;
2161         u8 prio = 0;
2162
2163         spin_lock(&dcb_lock);
2164         list_for_each_entry(itr, &dcb_app_list, list) {
2165                 if (itr->app.selector == app->selector &&
2166                     itr->app.protocol == app->protocol &&
2167                     itr->ifindex == dev->ifindex) {
2168                         prio |= 1 << itr->app.priority;
2169                 }
2170         }
2171         spin_unlock(&dcb_lock);
2172
2173         return prio;
2174 }
2175 EXPORT_SYMBOL(dcb_ieee_getapp_mask);
2176
2177 /**
2178  * dcb_ieee_setapp - add IEEE dcb application data to app list
2179  *
2180  * This adds Application data to the list. Multiple application
2181  * entries may exists for the same selector and protocol as long
2182  * as the priorities are different.
2183  */
2184 int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
2185 {
2186         struct dcb_app_type *itr, *entry;
2187         struct dcb_app_type event;
2188         int err = 0;
2189
2190         event.ifindex = dev->ifindex;
2191         memcpy(&event.app, new, sizeof(event.app));
2192         if (dev->dcbnl_ops->getdcbx)
2193                 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
2194
2195         spin_lock(&dcb_lock);
2196         /* Search for existing match and abort if found */
2197         list_for_each_entry(itr, &dcb_app_list, list) {
2198                 if (itr->app.selector == new->selector &&
2199                     itr->app.protocol == new->protocol &&
2200                     itr->app.priority == new->priority &&
2201                     itr->ifindex == dev->ifindex) {
2202                         err = -EEXIST;
2203                         goto out;
2204                 }
2205         }
2206
2207         /* App entry does not exist add new entry */
2208         entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
2209         if (!entry) {
2210                 err = -ENOMEM;
2211                 goto out;
2212         }
2213
2214         memcpy(&entry->app, new, sizeof(*new));
2215         entry->ifindex = dev->ifindex;
2216         list_add(&entry->list, &dcb_app_list);
2217 out:
2218         spin_unlock(&dcb_lock);
2219         if (!err)
2220                 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2221         return err;
2222 }
2223 EXPORT_SYMBOL(dcb_ieee_setapp);
2224
2225 /**
2226  * dcb_ieee_delapp - delete IEEE dcb application data from list
2227  *
2228  * This removes a matching APP data from the APP list
2229  */
2230 int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
2231 {
2232         struct dcb_app_type *itr;
2233         struct dcb_app_type event;
2234         int err = -ENOENT;
2235
2236         event.ifindex = dev->ifindex;
2237         memcpy(&event.app, del, sizeof(event.app));
2238         if (dev->dcbnl_ops->getdcbx)
2239                 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
2240
2241         spin_lock(&dcb_lock);
2242         /* Search for existing match and remove it. */
2243         list_for_each_entry(itr, &dcb_app_list, list) {
2244                 if (itr->app.selector == del->selector &&
2245                     itr->app.protocol == del->protocol &&
2246                     itr->app.priority == del->priority &&
2247                     itr->ifindex == dev->ifindex) {
2248                         list_del(&itr->list);
2249                         kfree(itr);
2250                         err = 0;
2251                         goto out;
2252                 }
2253         }
2254
2255 out:
2256         spin_unlock(&dcb_lock);
2257         if (!err)
2258                 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2259         return err;
2260 }
2261 EXPORT_SYMBOL(dcb_ieee_delapp);
2262
2263 static void dcb_flushapp(void)
2264 {
2265         struct dcb_app_type *app;
2266         struct dcb_app_type *tmp;
2267
2268         spin_lock(&dcb_lock);
2269         list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
2270                 list_del(&app->list);
2271                 kfree(app);
2272         }
2273         spin_unlock(&dcb_lock);
2274 }
2275
2276 static int __init dcbnl_init(void)
2277 {
2278         INIT_LIST_HEAD(&dcb_app_list);
2279
2280         rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
2281         rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
2282
2283         return 0;
2284 }
2285 module_init(dcbnl_init);
2286
2287 static void __exit dcbnl_exit(void)
2288 {
2289         rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
2290         rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
2291         dcb_flushapp();
2292 }
2293 module_exit(dcbnl_exit);