Blame view

net/dcb/dcbnl.c 49 KB
2f90b8657   Alexander Duyck   ixgbe: this patch...
1
  /*
698e1d23c   Mark Rustad   net: dcbnl: Updat...
2
   * Copyright (c) 2008-2011, Intel Corporation.
2f90b8657   Alexander Duyck   ixgbe: this patch...
3
4
5
6
7
8
9
10
11
12
13
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms and conditions of the GNU General Public License,
   * version 2, as published by the Free Software Foundation.
   *
   * This program is distributed in the hope it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   * more details.
   *
   * You should have received a copy of the GNU General Public License along with
c057b190b   Jeff Kirsher   net/*: Fix FSF ad...
14
   * this program; if not, see <http://www.gnu.org/licenses/>.
2f90b8657   Alexander Duyck   ixgbe: this patch...
15
   *
36b9ad808   Paul Gortmaker   net/dcb: make dcb...
16
   * Description: Data Center Bridging netlink interface
2f90b8657   Alexander Duyck   ixgbe: this patch...
17
18
19
20
21
   * Author: Lucy Liu <lucy.liu@intel.com>
   */
  
  #include <linux/netdevice.h>
  #include <linux/netlink.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
22
  #include <linux/slab.h>
2f90b8657   Alexander Duyck   ixgbe: this patch...
23
24
25
  #include <net/netlink.h>
  #include <net/rtnetlink.h>
  #include <linux/dcbnl.h>
96b99684e   John Fastabend   net_dcb: add appl...
26
  #include <net/dcbevent.h>
2f90b8657   Alexander Duyck   ixgbe: this patch...
27
  #include <linux/rtnetlink.h>
36b9ad808   Paul Gortmaker   net/dcb: make dcb...
28
  #include <linux/init.h>
2f90b8657   Alexander Duyck   ixgbe: this patch...
29
  #include <net/sock.h>
ae86b9e38   Ben Hutchings   net: Fix non-kern...
30
  /* Data Center Bridging (DCB) is a collection of Ethernet enhancements
2f90b8657   Alexander Duyck   ixgbe: this patch...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
   * intended to allow network traffic with differing requirements
   * (highly reliable, no drops vs. best effort vs. low latency) to operate
   * and co-exist on Ethernet.  Current DCB features are:
   *
   * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a
   *   framework for assigning bandwidth guarantees to traffic classes.
   *
   * Priority-based Flow Control (PFC) - provides a flow control mechanism which
   *   can work independently for each 802.1p priority.
   *
   * Congestion Notification - provides a mechanism for end-to-end congestion
   *   control for protocols which do not have built-in congestion management.
   *
   * More information about the emerging standards for these Ethernet features
   * can be found at: http://www.ieee802.org/1/pages/dcbridges.html
   *
   * This file implements an rtnetlink interface to allow configuration of DCB
   * features for capable devices.
   */
2f90b8657   Alexander Duyck   ixgbe: this patch...
50
51
52
  /**************** DCB attribute policies *************************************/
  
  /* DCB netlink attributes policy */
b54452b07   Alexey Dobriyan   const: struct nla...
53
  static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
859ee3c43   Alexander Duyck   DCB: Add support ...
54
55
56
57
58
  	[DCB_ATTR_IFNAME]      = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1},
  	[DCB_ATTR_STATE]       = {.type = NLA_U8},
  	[DCB_ATTR_PFC_CFG]     = {.type = NLA_NESTED},
  	[DCB_ATTR_PG_CFG]      = {.type = NLA_NESTED},
  	[DCB_ATTR_SET_ALL]     = {.type = NLA_U8},
2f90b8657   Alexander Duyck   ixgbe: this patch...
59
  	[DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG},
859ee3c43   Alexander Duyck   DCB: Add support ...
60
61
62
  	[DCB_ATTR_CAP]         = {.type = NLA_NESTED},
  	[DCB_ATTR_PFC_STATE]   = {.type = NLA_U8},
  	[DCB_ATTR_BCN]         = {.type = NLA_NESTED},
6fa382af6   Yi Zou   dcbnl: Add netlin...
63
  	[DCB_ATTR_APP]         = {.type = NLA_NESTED},
3e29027af   John Fastabend   dcbnl: add suppor...
64
  	[DCB_ATTR_IEEE]	       = {.type = NLA_NESTED},
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
65
  	[DCB_ATTR_DCBX]        = {.type = NLA_U8},
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
66
  	[DCB_ATTR_FEATCFG]     = {.type = NLA_NESTED},
2f90b8657   Alexander Duyck   ixgbe: this patch...
67
68
69
  };
  
  /* DCB priority flow control to User Priority nested attributes */
b54452b07   Alexey Dobriyan   const: struct nla...
70
  static const struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = {
2f90b8657   Alexander Duyck   ixgbe: this patch...
71
72
73
74
75
76
77
78
79
80
81
82
  	[DCB_PFC_UP_ATTR_0]   = {.type = NLA_U8},
  	[DCB_PFC_UP_ATTR_1]   = {.type = NLA_U8},
  	[DCB_PFC_UP_ATTR_2]   = {.type = NLA_U8},
  	[DCB_PFC_UP_ATTR_3]   = {.type = NLA_U8},
  	[DCB_PFC_UP_ATTR_4]   = {.type = NLA_U8},
  	[DCB_PFC_UP_ATTR_5]   = {.type = NLA_U8},
  	[DCB_PFC_UP_ATTR_6]   = {.type = NLA_U8},
  	[DCB_PFC_UP_ATTR_7]   = {.type = NLA_U8},
  	[DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG},
  };
  
  /* DCB priority grouping nested attributes */
b54452b07   Alexey Dobriyan   const: struct nla...
83
  static const struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = {
2f90b8657   Alexander Duyck   ixgbe: this patch...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  	[DCB_PG_ATTR_TC_0]      = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_TC_1]      = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_TC_2]      = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_TC_3]      = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_TC_4]      = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_TC_5]      = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_TC_6]      = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_TC_7]      = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_TC_ALL]    = {.type = NLA_NESTED},
  	[DCB_PG_ATTR_BW_ID_0]   = {.type = NLA_U8},
  	[DCB_PG_ATTR_BW_ID_1]   = {.type = NLA_U8},
  	[DCB_PG_ATTR_BW_ID_2]   = {.type = NLA_U8},
  	[DCB_PG_ATTR_BW_ID_3]   = {.type = NLA_U8},
  	[DCB_PG_ATTR_BW_ID_4]   = {.type = NLA_U8},
  	[DCB_PG_ATTR_BW_ID_5]   = {.type = NLA_U8},
  	[DCB_PG_ATTR_BW_ID_6]   = {.type = NLA_U8},
  	[DCB_PG_ATTR_BW_ID_7]   = {.type = NLA_U8},
  	[DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG},
  };
  
  /* DCB traffic class nested attributes. */
b54452b07   Alexey Dobriyan   const: struct nla...
105
  static const struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = {
2f90b8657   Alexander Duyck   ixgbe: this patch...
106
107
108
109
110
111
  	[DCB_TC_ATTR_PARAM_PGID]            = {.type = NLA_U8},
  	[DCB_TC_ATTR_PARAM_UP_MAPPING]      = {.type = NLA_U8},
  	[DCB_TC_ATTR_PARAM_STRICT_PRIO]     = {.type = NLA_U8},
  	[DCB_TC_ATTR_PARAM_BW_PCT]          = {.type = NLA_U8},
  	[DCB_TC_ATTR_PARAM_ALL]             = {.type = NLA_FLAG},
  };
46132188b   Alexander Duyck   DCB: Add interfac...
112
  /* DCB capabilities nested attributes. */
b54452b07   Alexey Dobriyan   const: struct nla...
113
  static const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
46132188b   Alexander Duyck   DCB: Add interfac...
114
115
116
117
118
119
120
121
  	[DCB_CAP_ATTR_ALL]     = {.type = NLA_FLAG},
  	[DCB_CAP_ATTR_PG]      = {.type = NLA_U8},
  	[DCB_CAP_ATTR_PFC]     = {.type = NLA_U8},
  	[DCB_CAP_ATTR_UP2TC]   = {.type = NLA_U8},
  	[DCB_CAP_ATTR_PG_TCS]  = {.type = NLA_U8},
  	[DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8},
  	[DCB_CAP_ATTR_GSP]     = {.type = NLA_U8},
  	[DCB_CAP_ATTR_BCN]     = {.type = NLA_U8},
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
122
  	[DCB_CAP_ATTR_DCBX]    = {.type = NLA_U8},
46132188b   Alexander Duyck   DCB: Add interfac...
123
  };
2f90b8657   Alexander Duyck   ixgbe: this patch...
124

33dbabc4a   Alexander Duyck   DCB: Add interfac...
125
  /* DCB capabilities nested attributes. */
b54452b07   Alexey Dobriyan   const: struct nla...
126
  static const struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = {
33dbabc4a   Alexander Duyck   DCB: Add interfac...
127
128
129
130
  	[DCB_NUMTCS_ATTR_ALL]     = {.type = NLA_FLAG},
  	[DCB_NUMTCS_ATTR_PG]      = {.type = NLA_U8},
  	[DCB_NUMTCS_ATTR_PFC]     = {.type = NLA_U8},
  };
859ee3c43   Alexander Duyck   DCB: Add support ...
131
  /* DCB BCN nested attributes. */
b54452b07   Alexey Dobriyan   const: struct nla...
132
  static const struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = {
859ee3c43   Alexander Duyck   DCB: Add support ...
133
134
135
136
137
138
139
140
141
  	[DCB_BCN_ATTR_RP_0]         = {.type = NLA_U8},
  	[DCB_BCN_ATTR_RP_1]         = {.type = NLA_U8},
  	[DCB_BCN_ATTR_RP_2]         = {.type = NLA_U8},
  	[DCB_BCN_ATTR_RP_3]         = {.type = NLA_U8},
  	[DCB_BCN_ATTR_RP_4]         = {.type = NLA_U8},
  	[DCB_BCN_ATTR_RP_5]         = {.type = NLA_U8},
  	[DCB_BCN_ATTR_RP_6]         = {.type = NLA_U8},
  	[DCB_BCN_ATTR_RP_7]         = {.type = NLA_U8},
  	[DCB_BCN_ATTR_RP_ALL]       = {.type = NLA_FLAG},
f4314e815   Don Skidmore   net: add DCNA att...
142
143
  	[DCB_BCN_ATTR_BCNA_0]       = {.type = NLA_U32},
  	[DCB_BCN_ATTR_BCNA_1]       = {.type = NLA_U32},
859ee3c43   Alexander Duyck   DCB: Add support ...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  	[DCB_BCN_ATTR_ALPHA]        = {.type = NLA_U32},
  	[DCB_BCN_ATTR_BETA]         = {.type = NLA_U32},
  	[DCB_BCN_ATTR_GD]           = {.type = NLA_U32},
  	[DCB_BCN_ATTR_GI]           = {.type = NLA_U32},
  	[DCB_BCN_ATTR_TMAX]         = {.type = NLA_U32},
  	[DCB_BCN_ATTR_TD]           = {.type = NLA_U32},
  	[DCB_BCN_ATTR_RMIN]         = {.type = NLA_U32},
  	[DCB_BCN_ATTR_W]            = {.type = NLA_U32},
  	[DCB_BCN_ATTR_RD]           = {.type = NLA_U32},
  	[DCB_BCN_ATTR_RU]           = {.type = NLA_U32},
  	[DCB_BCN_ATTR_WRTT]         = {.type = NLA_U32},
  	[DCB_BCN_ATTR_RI]           = {.type = NLA_U32},
  	[DCB_BCN_ATTR_C]            = {.type = NLA_U32},
  	[DCB_BCN_ATTR_ALL]          = {.type = NLA_FLAG},
  };
6fa382af6   Yi Zou   dcbnl: Add netlin...
159
  /* DCB APP nested attributes. */
b54452b07   Alexey Dobriyan   const: struct nla...
160
  static const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = {
6fa382af6   Yi Zou   dcbnl: Add netlin...
161
162
163
164
  	[DCB_APP_ATTR_IDTYPE]       = {.type = NLA_U8},
  	[DCB_APP_ATTR_ID]           = {.type = NLA_U16},
  	[DCB_APP_ATTR_PRIORITY]     = {.type = NLA_U8},
  };
3e29027af   John Fastabend   dcbnl: add suppor...
165
166
167
168
169
  /* IEEE 802.1Qaz nested attributes. */
  static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = {
  	[DCB_ATTR_IEEE_ETS]	    = {.len = sizeof(struct ieee_ets)},
  	[DCB_ATTR_IEEE_PFC]	    = {.len = sizeof(struct ieee_pfc)},
  	[DCB_ATTR_IEEE_APP_TABLE]   = {.type = NLA_NESTED},
08f10affe   Amir Vadai   net/dcb: Add an o...
170
  	[DCB_ATTR_IEEE_MAXRATE]   = {.len = sizeof(struct ieee_maxrate)},
c93682477   Shani Michaeli   net/dcb: Add IEEE...
171
172
  	[DCB_ATTR_IEEE_QCN]         = {.len = sizeof(struct ieee_qcn)},
  	[DCB_ATTR_IEEE_QCN_STATS]   = {.len = sizeof(struct ieee_qcn_stats)},
3e29027af   John Fastabend   dcbnl: add suppor...
173
174
175
176
177
  };
  
  static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
  	[DCB_ATTR_IEEE_APP]	    = {.len = sizeof(struct dcb_app)},
  };
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
178
179
180
181
182
183
184
  /* DCB number of traffic classes nested attributes. */
  static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
  	[DCB_FEATCFG_ATTR_ALL]      = {.type = NLA_FLAG},
  	[DCB_FEATCFG_ATTR_PG]       = {.type = NLA_U8},
  	[DCB_FEATCFG_ATTR_PFC]      = {.type = NLA_U8},
  	[DCB_FEATCFG_ATTR_APP]      = {.type = NLA_U8},
  };
9ab933ab2   John Fastabend   dcbnl: add applic...
185
186
  static LIST_HEAD(dcb_app_list);
  static DEFINE_SPINLOCK(dcb_lock);
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
187
188
189
190
191
192
193
194
195
196
197
198
  static struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq,
  				    u32 flags, struct nlmsghdr **nlhp)
  {
  	struct sk_buff *skb;
  	struct dcbmsg *dcb;
  	struct nlmsghdr *nlh;
  
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  	if (!skb)
  		return NULL;
  
  	nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags);
b3908e22a   Thomas Graf   dcbnl: Use BUG_ON...
199
  	BUG_ON(!nlh);
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
200
201
202
203
204
205
206
207
208
209
210
  
  	dcb = nlmsg_data(nlh);
  	dcb->dcb_family = AF_UNSPEC;
  	dcb->cmd = cmd;
  	dcb->dcb_pad = 0;
  
  	if (nlhp)
  		*nlhp = nlh;
  
  	return skb;
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
211
212
  static int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh,
  			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
213
  {
2f90b8657   Alexander Duyck   ixgbe: this patch...
214
215
  	/* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
  	if (!netdev->dcbnl_ops->getstate)
3d1f48695   Thomas Graf   dcbnl: Return con...
216
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
217

7be994138   Thomas Graf   dcbnl: Shorten al...
218
219
  	return nla_put_u8(skb, DCB_ATTR_STATE,
  			  netdev->dcbnl_ops->getstate(netdev));
2f90b8657   Alexander Duyck   ixgbe: this patch...
220
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
221
222
  static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
223
  {
2f90b8657   Alexander Duyck   ixgbe: this patch...
224
225
  	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
  	u8 value;
3d1f48695   Thomas Graf   dcbnl: Return con...
226
  	int ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
227
228
  	int i;
  	int getall = 0;
3d1f48695   Thomas Graf   dcbnl: Return con...
229
230
231
232
233
  	if (!tb[DCB_ATTR_PFC_CFG])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->getpfccfg)
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
234
235
236
237
238
  
  	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
  	                       tb[DCB_ATTR_PFC_CFG],
  	                       dcbnl_pfc_up_nest);
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
239
  		return ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
240

7be994138   Thomas Graf   dcbnl: Shorten al...
241
  	nest = nla_nest_start(skb, DCB_ATTR_PFC_CFG);
2f90b8657   Alexander Duyck   ixgbe: this patch...
242
  	if (!nest)
3d1f48695   Thomas Graf   dcbnl: Return con...
243
  		return -EMSGSIZE;
2f90b8657   Alexander Duyck   ixgbe: this patch...
244
245
246
247
248
249
250
251
252
253
  
  	if (data[DCB_PFC_UP_ATTR_ALL])
  		getall = 1;
  
  	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
  		if (!getall && !data[i])
  			continue;
  
  		netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
  		                             &value);
7be994138   Thomas Graf   dcbnl: Shorten al...
254
  		ret = nla_put_u8(skb, i, value);
2f90b8657   Alexander Duyck   ixgbe: this patch...
255
  		if (ret) {
7be994138   Thomas Graf   dcbnl: Shorten al...
256
  			nla_nest_cancel(skb, nest);
3d1f48695   Thomas Graf   dcbnl: Return con...
257
  			return ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
258
259
  		}
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
260
  	nla_nest_end(skb, nest);
2f90b8657   Alexander Duyck   ixgbe: this patch...
261
262
  
  	return 0;
2f90b8657   Alexander Duyck   ixgbe: this patch...
263
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
264
265
  static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh,
  				u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
266
  {
2f90b8657   Alexander Duyck   ixgbe: this patch...
267
  	u8 perm_addr[MAX_ADDR_LEN];
2f90b8657   Alexander Duyck   ixgbe: this patch...
268
269
  
  	if (!netdev->dcbnl_ops->getpermhwaddr)
3d1f48695   Thomas Graf   dcbnl: Return con...
270
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
271

29cd8ae0e   Mathias Krause   dcbnl: fix variou...
272
  	memset(perm_addr, 0, sizeof(perm_addr));
2f90b8657   Alexander Duyck   ixgbe: this patch...
273
  	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
7be994138   Thomas Graf   dcbnl: Shorten al...
274
  	return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr);
2f90b8657   Alexander Duyck   ixgbe: this patch...
275
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
276
277
  static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh,
  			u32 seq, struct nlattr **tb, struct sk_buff *skb)
46132188b   Alexander Duyck   DCB: Add interfac...
278
  {
46132188b   Alexander Duyck   DCB: Add interfac...
279
280
  	struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
  	u8 value;
3d1f48695   Thomas Graf   dcbnl: Return con...
281
  	int ret;
46132188b   Alexander Duyck   DCB: Add interfac...
282
283
  	int i;
  	int getall = 0;
3d1f48695   Thomas Graf   dcbnl: Return con...
284
285
286
287
288
  	if (!tb[DCB_ATTR_CAP])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->getcap)
  		return -EOPNOTSUPP;
46132188b   Alexander Duyck   DCB: Add interfac...
289
290
291
292
  
  	ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
  	                       dcbnl_cap_nest);
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
293
  		return ret;
46132188b   Alexander Duyck   DCB: Add interfac...
294

7be994138   Thomas Graf   dcbnl: Shorten al...
295
  	nest = nla_nest_start(skb, DCB_ATTR_CAP);
46132188b   Alexander Duyck   DCB: Add interfac...
296
  	if (!nest)
3d1f48695   Thomas Graf   dcbnl: Return con...
297
  		return -EMSGSIZE;
46132188b   Alexander Duyck   DCB: Add interfac...
298
299
300
301
302
303
304
305
306
  
  	if (data[DCB_CAP_ATTR_ALL])
  		getall = 1;
  
  	for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
  		if (!getall && !data[i])
  			continue;
  
  		if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
7be994138   Thomas Graf   dcbnl: Shorten al...
307
  			ret = nla_put_u8(skb, i, value);
46132188b   Alexander Duyck   DCB: Add interfac...
308
  			if (ret) {
7be994138   Thomas Graf   dcbnl: Shorten al...
309
  				nla_nest_cancel(skb, nest);
3d1f48695   Thomas Graf   dcbnl: Return con...
310
  				return ret;
46132188b   Alexander Duyck   DCB: Add interfac...
311
312
313
  			}
  		}
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
314
  	nla_nest_end(skb, nest);
46132188b   Alexander Duyck   DCB: Add interfac...
315
316
  
  	return 0;
46132188b   Alexander Duyck   DCB: Add interfac...
317
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
318
319
  static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
  			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
33dbabc4a   Alexander Duyck   DCB: Add interfac...
320
  {
33dbabc4a   Alexander Duyck   DCB: Add interfac...
321
322
  	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
  	u8 value;
3d1f48695   Thomas Graf   dcbnl: Return con...
323
  	int ret;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
324
325
  	int i;
  	int getall = 0;
3d1f48695   Thomas Graf   dcbnl: Return con...
326
327
328
329
330
  	if (!tb[DCB_ATTR_NUMTCS])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->getnumtcs)
  		return -EOPNOTSUPP;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
331
332
333
  
  	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
  	                       dcbnl_numtcs_nest);
3d1f48695   Thomas Graf   dcbnl: Return con...
334
335
  	if (ret)
  		return ret;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
336

7be994138   Thomas Graf   dcbnl: Shorten al...
337
  	nest = nla_nest_start(skb, DCB_ATTR_NUMTCS);
3d1f48695   Thomas Graf   dcbnl: Return con...
338
339
  	if (!nest)
  		return -EMSGSIZE;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
340
341
342
343
344
345
346
347
348
349
  
  	if (data[DCB_NUMTCS_ATTR_ALL])
  		getall = 1;
  
  	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
  		if (!getall && !data[i])
  			continue;
  
  		ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
  		if (!ret) {
7be994138   Thomas Graf   dcbnl: Shorten al...
350
  			ret = nla_put_u8(skb, i, value);
33dbabc4a   Alexander Duyck   DCB: Add interfac...
351
  			if (ret) {
7be994138   Thomas Graf   dcbnl: Shorten al...
352
  				nla_nest_cancel(skb, nest);
3d1f48695   Thomas Graf   dcbnl: Return con...
353
  				return ret;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
354
  			}
3d1f48695   Thomas Graf   dcbnl: Return con...
355
356
  		} else
  			return -EINVAL;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
357
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
358
  	nla_nest_end(skb, nest);
33dbabc4a   Alexander Duyck   DCB: Add interfac...
359
360
  
  	return 0;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
361
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
362
363
  static int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
  			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
33dbabc4a   Alexander Duyck   DCB: Add interfac...
364
365
  {
  	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
3d1f48695   Thomas Graf   dcbnl: Return con...
366
  	int ret;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
367
368
  	u8 value;
  	int i;
3d1f48695   Thomas Graf   dcbnl: Return con...
369
370
371
372
373
  	if (!tb[DCB_ATTR_NUMTCS])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->setnumtcs)
  		return -EOPNOTSUPP;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
374
375
376
  
  	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
  	                       dcbnl_numtcs_nest);
7be994138   Thomas Graf   dcbnl: Shorten al...
377
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
378
  		return ret;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
379
380
381
382
383
384
385
386
  
  	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
  		if (data[i] == NULL)
  			continue;
  
  		value = nla_get_u8(data[i]);
  
  		ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
33dbabc4a   Alexander Duyck   DCB: Add interfac...
387
  		if (ret)
7be994138   Thomas Graf   dcbnl: Shorten al...
388
  			break;
33dbabc4a   Alexander Duyck   DCB: Add interfac...
389
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
390
  	return nla_put_u8(skb, DCB_ATTR_NUMTCS, !!ret);
33dbabc4a   Alexander Duyck   DCB: Add interfac...
391
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
392
393
  static int dcbnl_getpfcstate(struct net_device *netdev, struct nlmsghdr *nlh,
  			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
394
  {
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
395
  	if (!netdev->dcbnl_ops->getpfcstate)
3d1f48695   Thomas Graf   dcbnl: Return con...
396
  		return -EOPNOTSUPP;
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
397

7be994138   Thomas Graf   dcbnl: Shorten al...
398
399
  	return nla_put_u8(skb, DCB_ATTR_PFC_STATE,
  			  netdev->dcbnl_ops->getpfcstate(netdev));
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
400
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
401
402
  static int dcbnl_setpfcstate(struct net_device *netdev, struct nlmsghdr *nlh,
  			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
403
  {
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
404
  	u8 value;
3d1f48695   Thomas Graf   dcbnl: Return con...
405
  	if (!tb[DCB_ATTR_PFC_STATE])
7be994138   Thomas Graf   dcbnl: Shorten al...
406
  		return -EINVAL;
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
407

3d1f48695   Thomas Graf   dcbnl: Return con...
408
409
  	if (!netdev->dcbnl_ops->setpfcstate)
  		return -EOPNOTSUPP;
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
410
411
412
  	value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
  
  	netdev->dcbnl_ops->setpfcstate(netdev, value);
7be994138   Thomas Graf   dcbnl: Shorten al...
413
  	return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 0);
0eb3aa9ba   Alexander Duyck   DCB: Add interfac...
414
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
415
416
  static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh,
  			u32 seq, struct nlattr **tb, struct sk_buff *skb)
579496865   Yi Zou   dcbnl: Add implem...
417
  {
579496865   Yi Zou   dcbnl: Add implem...
418
419
420
421
  	struct nlattr *app_nest;
  	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
  	u16 id;
  	u8 up, idtype;
3d1f48695   Thomas Graf   dcbnl: Return con...
422
  	int ret;
579496865   Yi Zou   dcbnl: Add implem...
423

3dce38a02   John Fastabend   dcbnl: make get_a...
424
  	if (!tb[DCB_ATTR_APP])
3d1f48695   Thomas Graf   dcbnl: Return con...
425
  		return -EINVAL;
579496865   Yi Zou   dcbnl: Add implem...
426
427
428
429
  
  	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
  	                       dcbnl_app_nest);
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
430
  		return ret;
579496865   Yi Zou   dcbnl: Add implem...
431

579496865   Yi Zou   dcbnl: Add implem...
432
433
434
  	/* all must be non-null */
  	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
  	    (!app_tb[DCB_APP_ATTR_ID]))
3d1f48695   Thomas Graf   dcbnl: Return con...
435
  		return -EINVAL;
579496865   Yi Zou   dcbnl: Add implem...
436
437
438
439
440
  
  	/* either by eth type or by socket number */
  	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
  	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
  	    (idtype != DCB_APP_IDTYPE_PORTNUM))
3d1f48695   Thomas Graf   dcbnl: Return con...
441
  		return -EINVAL;
579496865   Yi Zou   dcbnl: Add implem...
442
443
  
  	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
3dce38a02   John Fastabend   dcbnl: make get_a...
444
445
  
  	if (netdev->dcbnl_ops->getapp) {
c2659479f   Anish Bhatt   Update setapp/get...
446
447
448
449
450
  		ret = netdev->dcbnl_ops->getapp(netdev, idtype, id);
  		if (ret < 0)
  			return ret;
  		else
  			up = ret;
3dce38a02   John Fastabend   dcbnl: make get_a...
451
452
453
454
455
456
457
  	} else {
  		struct dcb_app app = {
  					.selector = idtype,
  					.protocol = id,
  				     };
  		up = dcb_getapp(netdev, &app);
  	}
579496865   Yi Zou   dcbnl: Add implem...
458

7be994138   Thomas Graf   dcbnl: Shorten al...
459
  	app_nest = nla_nest_start(skb, DCB_ATTR_APP);
d3337de52   Jesper Juhl   Don't potentially...
460
  	if (!app_nest)
3d1f48695   Thomas Graf   dcbnl: Return con...
461
  		return -EMSGSIZE;
d3337de52   Jesper Juhl   Don't potentially...
462

7be994138   Thomas Graf   dcbnl: Shorten al...
463
  	ret = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, idtype);
579496865   Yi Zou   dcbnl: Add implem...
464
465
  	if (ret)
  		goto out_cancel;
7be994138   Thomas Graf   dcbnl: Shorten al...
466
  	ret = nla_put_u16(skb, DCB_APP_ATTR_ID, id);
579496865   Yi Zou   dcbnl: Add implem...
467
468
  	if (ret)
  		goto out_cancel;
7be994138   Thomas Graf   dcbnl: Shorten al...
469
  	ret = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY, up);
579496865   Yi Zou   dcbnl: Add implem...
470
471
  	if (ret)
  		goto out_cancel;
7be994138   Thomas Graf   dcbnl: Shorten al...
472
  	nla_nest_end(skb, app_nest);
579496865   Yi Zou   dcbnl: Add implem...
473

3d1f48695   Thomas Graf   dcbnl: Return con...
474
  	return 0;
579496865   Yi Zou   dcbnl: Add implem...
475
476
  
  out_cancel:
7be994138   Thomas Graf   dcbnl: Shorten al...
477
  	nla_nest_cancel(skb, app_nest);
579496865   Yi Zou   dcbnl: Add implem...
478
479
  	return ret;
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
480
481
  static int dcbnl_setapp(struct net_device *netdev, struct nlmsghdr *nlh,
  			u32 seq, struct nlattr **tb, struct sk_buff *skb)
579496865   Yi Zou   dcbnl: Add implem...
482
  {
3d1f48695   Thomas Graf   dcbnl: Return con...
483
  	int ret;
579496865   Yi Zou   dcbnl: Add implem...
484
485
486
  	u16 id;
  	u8 up, idtype;
  	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
9ab933ab2   John Fastabend   dcbnl: add applic...
487
  	if (!tb[DCB_ATTR_APP])
3d1f48695   Thomas Graf   dcbnl: Return con...
488
  		return -EINVAL;
579496865   Yi Zou   dcbnl: Add implem...
489
490
491
492
  
  	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
  	                       dcbnl_app_nest);
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
493
  		return ret;
579496865   Yi Zou   dcbnl: Add implem...
494

579496865   Yi Zou   dcbnl: Add implem...
495
496
497
498
  	/* all must be non-null */
  	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
  	    (!app_tb[DCB_APP_ATTR_ID]) ||
  	    (!app_tb[DCB_APP_ATTR_PRIORITY]))
3d1f48695   Thomas Graf   dcbnl: Return con...
499
  		return -EINVAL;
579496865   Yi Zou   dcbnl: Add implem...
500
501
502
503
504
  
  	/* either by eth type or by socket number */
  	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
  	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
  	    (idtype != DCB_APP_IDTYPE_PORTNUM))
3d1f48695   Thomas Graf   dcbnl: Return con...
505
  		return -EINVAL;
579496865   Yi Zou   dcbnl: Add implem...
506
507
508
  
  	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
  	up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
9ab933ab2   John Fastabend   dcbnl: add applic...
509
  	if (netdev->dcbnl_ops->setapp) {
3d1f48695   Thomas Graf   dcbnl: Return con...
510
  		ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
c2659479f   Anish Bhatt   Update setapp/get...
511
512
  		if (ret < 0)
  			return ret;
9ab933ab2   John Fastabend   dcbnl: add applic...
513
514
515
516
517
  	} else {
  		struct dcb_app app;
  		app.selector = idtype;
  		app.protocol = id;
  		app.priority = up;
3d1f48695   Thomas Graf   dcbnl: Return con...
518
  		ret = dcb_setapp(netdev, &app);
9ab933ab2   John Fastabend   dcbnl: add applic...
519
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
520
  	ret = nla_put_u8(skb, DCB_ATTR_APP, ret);
081579840   John Fastabend   net: dcb: add CEE...
521
  	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0);
3d1f48695   Thomas Graf   dcbnl: Return con...
522

579496865   Yi Zou   dcbnl: Add implem...
523
524
  	return ret;
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
525
526
  static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			     struct nlattr **tb, struct sk_buff *skb, int dir)
2f90b8657   Alexander Duyck   ixgbe: this patch...
527
  {
2f90b8657   Alexander Duyck   ixgbe: this patch...
528
529
530
531
  	struct nlattr *pg_nest, *param_nest, *data;
  	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
  	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
  	u8 prio, pgid, tc_pct, up_map;
3d1f48695   Thomas Graf   dcbnl: Return con...
532
  	int ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
533
534
  	int getall = 0;
  	int i;
3d1f48695   Thomas Graf   dcbnl: Return con...
535
536
537
538
  	if (!tb[DCB_ATTR_PG_CFG])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->getpgtccfgtx ||
2f90b8657   Alexander Duyck   ixgbe: this patch...
539
540
541
  	    !netdev->dcbnl_ops->getpgtccfgrx ||
  	    !netdev->dcbnl_ops->getpgbwgcfgtx ||
  	    !netdev->dcbnl_ops->getpgbwgcfgrx)
3d1f48695   Thomas Graf   dcbnl: Return con...
542
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
543
544
545
  
  	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
  	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
2f90b8657   Alexander Duyck   ixgbe: this patch...
546
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
547
  		return ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
548

7be994138   Thomas Graf   dcbnl: Shorten al...
549
  	pg_nest = nla_nest_start(skb, DCB_ATTR_PG_CFG);
2f90b8657   Alexander Duyck   ixgbe: this patch...
550
  	if (!pg_nest)
3d1f48695   Thomas Graf   dcbnl: Return con...
551
  		return -EMSGSIZE;
2f90b8657   Alexander Duyck   ixgbe: this patch...
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  
  	if (pg_tb[DCB_PG_ATTR_TC_ALL])
  		getall = 1;
  
  	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
  		if (!getall && !pg_tb[i])
  			continue;
  
  		if (pg_tb[DCB_PG_ATTR_TC_ALL])
  			data = pg_tb[DCB_PG_ATTR_TC_ALL];
  		else
  			data = pg_tb[i];
  		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
  				       data, dcbnl_tc_param_nest);
  		if (ret)
  			goto err_pg;
7be994138   Thomas Graf   dcbnl: Shorten al...
568
  		param_nest = nla_nest_start(skb, i);
2f90b8657   Alexander Duyck   ixgbe: this patch...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
  		if (!param_nest)
  			goto err_pg;
  
  		pgid = DCB_ATTR_VALUE_UNDEFINED;
  		prio = DCB_ATTR_VALUE_UNDEFINED;
  		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
  		up_map = DCB_ATTR_VALUE_UNDEFINED;
  
  		if (dir) {
  			/* Rx */
  			netdev->dcbnl_ops->getpgtccfgrx(netdev,
  						i - DCB_PG_ATTR_TC_0, &prio,
  						&pgid, &tc_pct, &up_map);
  		} else {
  			/* Tx */
  			netdev->dcbnl_ops->getpgtccfgtx(netdev,
  						i - DCB_PG_ATTR_TC_0, &prio,
  						&pgid, &tc_pct, &up_map);
  		}
  
  		if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
  		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7be994138   Thomas Graf   dcbnl: Shorten al...
591
  			ret = nla_put_u8(skb,
2f90b8657   Alexander Duyck   ixgbe: this patch...
592
593
594
595
596
597
  			                 DCB_TC_ATTR_PARAM_PGID, pgid);
  			if (ret)
  				goto err_param;
  		}
  		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
  		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7be994138   Thomas Graf   dcbnl: Shorten al...
598
  			ret = nla_put_u8(skb,
2f90b8657   Alexander Duyck   ixgbe: this patch...
599
600
601
602
603
604
  			                 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
  			if (ret)
  				goto err_param;
  		}
  		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
  		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7be994138   Thomas Graf   dcbnl: Shorten al...
605
  			ret = nla_put_u8(skb,
2f90b8657   Alexander Duyck   ixgbe: this patch...
606
607
608
609
610
611
  			                 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
  			if (ret)
  				goto err_param;
  		}
  		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
  		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7be994138   Thomas Graf   dcbnl: Shorten al...
612
  			ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT,
2f90b8657   Alexander Duyck   ixgbe: this patch...
613
614
615
616
  			                 tc_pct);
  			if (ret)
  				goto err_param;
  		}
7be994138   Thomas Graf   dcbnl: Shorten al...
617
  		nla_nest_end(skb, param_nest);
2f90b8657   Alexander Duyck   ixgbe: this patch...
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
  	}
  
  	if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
  		getall = 1;
  	else
  		getall = 0;
  
  	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
  		if (!getall && !pg_tb[i])
  			continue;
  
  		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
  
  		if (dir) {
  			/* Rx */
  			netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
  					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
  		} else {
  			/* Tx */
  			netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
  					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
  		}
7be994138   Thomas Graf   dcbnl: Shorten al...
640
  		ret = nla_put_u8(skb, i, tc_pct);
2f90b8657   Alexander Duyck   ixgbe: this patch...
641
642
643
  		if (ret)
  			goto err_pg;
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
644
  	nla_nest_end(skb, pg_nest);
2f90b8657   Alexander Duyck   ixgbe: this patch...
645
646
647
648
  
  	return 0;
  
  err_param:
7be994138   Thomas Graf   dcbnl: Shorten al...
649
  	nla_nest_cancel(skb, param_nest);
2f90b8657   Alexander Duyck   ixgbe: this patch...
650
  err_pg:
7be994138   Thomas Graf   dcbnl: Shorten al...
651
  	nla_nest_cancel(skb, pg_nest);
3d1f48695   Thomas Graf   dcbnl: Return con...
652
653
  
  	return -EMSGSIZE;
2f90b8657   Alexander Duyck   ixgbe: this patch...
654
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
655
656
  static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
657
  {
7be994138   Thomas Graf   dcbnl: Shorten al...
658
  	return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 0);
2f90b8657   Alexander Duyck   ixgbe: this patch...
659
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
660
661
  static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
662
  {
7be994138   Thomas Graf   dcbnl: Shorten al...
663
  	return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 1);
2f90b8657   Alexander Duyck   ixgbe: this patch...
664
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
665
666
  static int dcbnl_setstate(struct net_device *netdev, struct nlmsghdr *nlh,
  			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
667
  {
2f90b8657   Alexander Duyck   ixgbe: this patch...
668
  	u8 value;
3d1f48695   Thomas Graf   dcbnl: Return con...
669
  	if (!tb[DCB_ATTR_STATE])
7be994138   Thomas Graf   dcbnl: Shorten al...
670
  		return -EINVAL;
2f90b8657   Alexander Duyck   ixgbe: this patch...
671

3d1f48695   Thomas Graf   dcbnl: Return con...
672
673
  	if (!netdev->dcbnl_ops->setstate)
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
674
  	value = nla_get_u8(tb[DCB_ATTR_STATE]);
7be994138   Thomas Graf   dcbnl: Shorten al...
675
676
  	return nla_put_u8(skb, DCB_ATTR_STATE,
  			  netdev->dcbnl_ops->setstate(netdev, value));
2f90b8657   Alexander Duyck   ixgbe: this patch...
677
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
678
679
  static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
680
681
682
  {
  	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
  	int i;
3d1f48695   Thomas Graf   dcbnl: Return con...
683
  	int ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
684
  	u8 value;
3d1f48695   Thomas Graf   dcbnl: Return con...
685
686
687
688
689
  	if (!tb[DCB_ATTR_PFC_CFG])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->setpfccfg)
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
690
691
692
693
694
  
  	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
  	                       tb[DCB_ATTR_PFC_CFG],
  	                       dcbnl_pfc_up_nest);
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
695
  		return ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
696
697
698
699
700
701
702
703
  
  	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
  		if (data[i] == NULL)
  			continue;
  		value = nla_get_u8(data[i]);
  		netdev->dcbnl_ops->setpfccfg(netdev,
  			data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
704
  	return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0);
2f90b8657   Alexander Duyck   ixgbe: this patch...
705
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
706
707
  static int dcbnl_setall(struct net_device *netdev, struct nlmsghdr *nlh,
  			u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
708
  {
3d1f48695   Thomas Graf   dcbnl: Return con...
709
  	int ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
710

3d1f48695   Thomas Graf   dcbnl: Return con...
711
712
713
714
715
  	if (!tb[DCB_ATTR_SET_ALL])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->setall)
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
716

7be994138   Thomas Graf   dcbnl: Shorten al...
717
718
  	ret = nla_put_u8(skb, DCB_ATTR_SET_ALL,
  			 netdev->dcbnl_ops->setall(netdev));
081579840   John Fastabend   net: dcb: add CEE...
719
  	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0);
2f90b8657   Alexander Duyck   ixgbe: this patch...
720
721
722
  
  	return ret;
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
723
724
725
  static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			     u32 seq, struct nlattr **tb, struct sk_buff *skb,
  			     int dir)
2f90b8657   Alexander Duyck   ixgbe: this patch...
726
727
728
  {
  	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
  	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
3d1f48695   Thomas Graf   dcbnl: Return con...
729
  	int ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
730
731
732
733
734
  	int i;
  	u8 pgid;
  	u8 up_map;
  	u8 prio;
  	u8 tc_pct;
3d1f48695   Thomas Graf   dcbnl: Return con...
735
736
737
738
  	if (!tb[DCB_ATTR_PG_CFG])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->setpgtccfgtx ||
2f90b8657   Alexander Duyck   ixgbe: this patch...
739
740
741
  	    !netdev->dcbnl_ops->setpgtccfgrx ||
  	    !netdev->dcbnl_ops->setpgbwgcfgtx ||
  	    !netdev->dcbnl_ops->setpgbwgcfgrx)
3d1f48695   Thomas Graf   dcbnl: Return con...
742
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
743
744
745
746
  
  	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
  	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
747
  		return ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
748
749
750
751
752
753
754
755
  
  	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
  		if (!pg_tb[i])
  			continue;
  
  		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
  		                       pg_tb[i], dcbnl_tc_param_nest);
  		if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
756
  			return ret;
2f90b8657   Alexander Duyck   ixgbe: this patch...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
  
  		pgid = DCB_ATTR_VALUE_UNDEFINED;
  		prio = DCB_ATTR_VALUE_UNDEFINED;
  		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
  		up_map = DCB_ATTR_VALUE_UNDEFINED;
  
  		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
  			prio =
  			    nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
  
  		if (param_tb[DCB_TC_ATTR_PARAM_PGID])
  			pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
  
  		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
  			tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
  
  		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
  			up_map =
  			     nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
  
  		/* dir: Tx = 0, Rx = 1 */
  		if (dir) {
  			/* Rx */
  			netdev->dcbnl_ops->setpgtccfgrx(netdev,
  				i - DCB_PG_ATTR_TC_0,
  				prio, pgid, tc_pct, up_map);
  		} else {
  			/* Tx */
  			netdev->dcbnl_ops->setpgtccfgtx(netdev,
  				i - DCB_PG_ATTR_TC_0,
  				prio, pgid, tc_pct, up_map);
  		}
  	}
  
  	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
  		if (!pg_tb[i])
  			continue;
  
  		tc_pct = nla_get_u8(pg_tb[i]);
  
  		/* dir: Tx = 0, Rx = 1 */
  		if (dir) {
  			/* Rx */
  			netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
  					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
  		} else {
  			/* Tx */
  			netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
  					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
  		}
  	}
bb1dfefdc   John Fastabend   net: dcb: fix sma...
808
  	return nla_put_u8(skb, DCB_ATTR_PG_CFG, 0);
2f90b8657   Alexander Duyck   ixgbe: this patch...
809
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
810
811
  static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
812
  {
7be994138   Thomas Graf   dcbnl: Shorten al...
813
  	return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 0);
2f90b8657   Alexander Duyck   ixgbe: this patch...
814
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
815
816
  static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
2f90b8657   Alexander Duyck   ixgbe: this patch...
817
  {
7be994138   Thomas Graf   dcbnl: Shorten al...
818
  	return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 1);
2f90b8657   Alexander Duyck   ixgbe: this patch...
819
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
820
821
  static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
859ee3c43   Alexander Duyck   DCB: Add support ...
822
  {
859ee3c43   Alexander Duyck   DCB: Add support ...
823
824
825
826
  	struct nlattr *bcn_nest;
  	struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
  	u8 value_byte;
  	u32 value_integer;
3d1f48695   Thomas Graf   dcbnl: Return con...
827
  	int ret;
859ee3c43   Alexander Duyck   DCB: Add support ...
828
829
  	bool getall = false;
  	int i;
3d1f48695   Thomas Graf   dcbnl: Return con...
830
831
832
833
  	if (!tb[DCB_ATTR_BCN])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->getbcnrp ||
859ee3c43   Alexander Duyck   DCB: Add support ...
834
  	    !netdev->dcbnl_ops->getbcncfg)
3d1f48695   Thomas Graf   dcbnl: Return con...
835
  		return -EOPNOTSUPP;
859ee3c43   Alexander Duyck   DCB: Add support ...
836
837
838
  
  	ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
  	                       tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
859ee3c43   Alexander Duyck   DCB: Add support ...
839
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
840
  		return ret;
859ee3c43   Alexander Duyck   DCB: Add support ...
841

7be994138   Thomas Graf   dcbnl: Shorten al...
842
  	bcn_nest = nla_nest_start(skb, DCB_ATTR_BCN);
859ee3c43   Alexander Duyck   DCB: Add support ...
843
  	if (!bcn_nest)
3d1f48695   Thomas Graf   dcbnl: Return con...
844
  		return -EMSGSIZE;
859ee3c43   Alexander Duyck   DCB: Add support ...
845
846
847
848
849
850
851
852
853
854
  
  	if (bcn_tb[DCB_BCN_ATTR_ALL])
  		getall = true;
  
  	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
  		if (!getall && !bcn_tb[i])
  			continue;
  
  		netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
  		                            &value_byte);
7be994138   Thomas Graf   dcbnl: Shorten al...
855
  		ret = nla_put_u8(skb, i, value_byte);
859ee3c43   Alexander Duyck   DCB: Add support ...
856
857
858
  		if (ret)
  			goto err_bcn;
  	}
f4314e815   Don Skidmore   net: add DCNA att...
859
  	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
859ee3c43   Alexander Duyck   DCB: Add support ...
860
861
862
863
864
  		if (!getall && !bcn_tb[i])
  			continue;
  
  		netdev->dcbnl_ops->getbcncfg(netdev, i,
  		                             &value_integer);
7be994138   Thomas Graf   dcbnl: Shorten al...
865
  		ret = nla_put_u32(skb, i, value_integer);
859ee3c43   Alexander Duyck   DCB: Add support ...
866
867
868
  		if (ret)
  			goto err_bcn;
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
869
  	nla_nest_end(skb, bcn_nest);
859ee3c43   Alexander Duyck   DCB: Add support ...
870
871
872
873
  
  	return 0;
  
  err_bcn:
7be994138   Thomas Graf   dcbnl: Shorten al...
874
  	nla_nest_cancel(skb, bcn_nest);
859ee3c43   Alexander Duyck   DCB: Add support ...
875
876
  	return ret;
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
877
878
  static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
859ee3c43   Alexander Duyck   DCB: Add support ...
879
880
881
  {
  	struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
  	int i;
3d1f48695   Thomas Graf   dcbnl: Return con...
882
  	int ret;
859ee3c43   Alexander Duyck   DCB: Add support ...
883
884
  	u8 value_byte;
  	u32 value_int;
3d1f48695   Thomas Graf   dcbnl: Return con...
885
886
887
888
  	if (!tb[DCB_ATTR_BCN])
  		return -EINVAL;
  
  	if (!netdev->dcbnl_ops->setbcncfg ||
f64f9e719   Joe Perches   net: Move && and ...
889
  	    !netdev->dcbnl_ops->setbcnrp)
3d1f48695   Thomas Graf   dcbnl: Return con...
890
  		return -EOPNOTSUPP;
859ee3c43   Alexander Duyck   DCB: Add support ...
891
892
893
894
895
  
  	ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
  	                       tb[DCB_ATTR_BCN],
  	                       dcbnl_pfc_up_nest);
  	if (ret)
3d1f48695   Thomas Graf   dcbnl: Return con...
896
  		return ret;
859ee3c43   Alexander Duyck   DCB: Add support ...
897
898
899
900
901
902
903
904
  
  	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
  		if (data[i] == NULL)
  			continue;
  		value_byte = nla_get_u8(data[i]);
  		netdev->dcbnl_ops->setbcnrp(netdev,
  			data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
  	}
f4314e815   Don Skidmore   net: add DCNA att...
905
  	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
859ee3c43   Alexander Duyck   DCB: Add support ...
906
907
908
909
910
911
  		if (data[i] == NULL)
  			continue;
  		value_int = nla_get_u32(data[i]);
  		netdev->dcbnl_ops->setbcncfg(netdev,
  	                                     i, value_int);
  	}
3d1f48695   Thomas Graf   dcbnl: Return con...
912
  	return nla_put_u8(skb, DCB_ATTR_BCN, 0);
859ee3c43   Alexander Duyck   DCB: Add support ...
913
  }
dc6ed1df5   Shmulik Ravid   dcbnl: add suppor...
914
915
916
  static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
  				int app_nested_type, int app_info_type,
  				int app_entry_type)
eed84713b   Shmulik Ravid   dcbnl: add suppor...
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
  {
  	struct dcb_peer_app_info info;
  	struct dcb_app *table = NULL;
  	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
  	u16 app_count;
  	int err;
  
  
  	/**
  	 * retrieve the peer app configuration form the driver. If the driver
  	 * handlers fail exit without doing anything
  	 */
  	err = ops->peer_getappinfo(netdev, &info, &app_count);
  	if (!err && app_count) {
  		table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
  		if (!table)
  			return -ENOMEM;
  
  		err = ops->peer_getapptable(netdev, table);
  	}
  
  	if (!err) {
  		u16 i;
  		struct nlattr *app;
  
  		/**
  		 * build the message, from here on the only possible failure
  		 * is due to the skb size
  		 */
  		err = -EMSGSIZE;
dc6ed1df5   Shmulik Ravid   dcbnl: add suppor...
947
  		app = nla_nest_start(skb, app_nested_type);
eed84713b   Shmulik Ravid   dcbnl: add suppor...
948
949
  		if (!app)
  			goto nla_put_failure;
1eb4c9777   David S. Miller   dcbnl: Stop using...
950
951
952
  		if (app_info_type &&
  		    nla_put(skb, app_info_type, sizeof(info), &info))
  			goto nla_put_failure;
eed84713b   Shmulik Ravid   dcbnl: add suppor...
953

1eb4c9777   David S. Miller   dcbnl: Stop using...
954
955
956
957
958
  		for (i = 0; i < app_count; i++) {
  			if (nla_put(skb, app_entry_type, sizeof(struct dcb_app),
  				    &table[i]))
  				goto nla_put_failure;
  		}
eed84713b   Shmulik Ravid   dcbnl: add suppor...
959
960
961
962
963
964
965
966
  		nla_nest_end(skb, app);
  	}
  	err = 0;
  
  nla_put_failure:
  	kfree(table);
  	return err;
  }
3e29027af   John Fastabend   dcbnl: add suppor...
967

c93682477   Shani Michaeli   net/dcb: Add IEEE...
968
  /* Handle IEEE 802.1Qaz/802.1Qau/802.1Qbb GET commands. */
314b4778e   John Fastabend   net: dcbnl, add m...
969
  static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
3e29027af   John Fastabend   dcbnl: add suppor...
970
  {
9ab933ab2   John Fastabend   dcbnl: add applic...
971
972
  	struct nlattr *ieee, *app;
  	struct dcb_app_type *itr;
3e29027af   John Fastabend   dcbnl: add suppor...
973
  	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
c7797baf9   John Fastabend   dcb: Add DCBX cap...
974
  	int dcbx;
3d1f48695   Thomas Graf   dcbnl: Return con...
975
  	int err;
3e29027af   John Fastabend   dcbnl: add suppor...
976

1eb4c9777   David S. Miller   dcbnl: Stop using...
977
  	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
3d1f48695   Thomas Graf   dcbnl: Return con...
978
  		return -EMSGSIZE;
3e29027af   John Fastabend   dcbnl: add suppor...
979
980
  	ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
  	if (!ieee)
3d1f48695   Thomas Graf   dcbnl: Return con...
981
  		return -EMSGSIZE;
3e29027af   John Fastabend   dcbnl: add suppor...
982
983
984
  
  	if (ops->ieee_getets) {
  		struct ieee_ets ets;
29cd8ae0e   Mathias Krause   dcbnl: fix variou...
985
  		memset(&ets, 0, sizeof(ets));
3e29027af   John Fastabend   dcbnl: add suppor...
986
  		err = ops->ieee_getets(netdev, &ets);
1eb4c9777   David S. Miller   dcbnl: Stop using...
987
988
  		if (!err &&
  		    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
3d1f48695   Thomas Graf   dcbnl: Return con...
989
  			return -EMSGSIZE;
3e29027af   John Fastabend   dcbnl: add suppor...
990
  	}
08f10affe   Amir Vadai   net/dcb: Add an o...
991
992
  	if (ops->ieee_getmaxrate) {
  		struct ieee_maxrate maxrate;
29cd8ae0e   Mathias Krause   dcbnl: fix variou...
993
  		memset(&maxrate, 0, sizeof(maxrate));
08f10affe   Amir Vadai   net/dcb: Add an o...
994
995
996
997
998
  		err = ops->ieee_getmaxrate(netdev, &maxrate);
  		if (!err) {
  			err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
  				      sizeof(maxrate), &maxrate);
  			if (err)
3d1f48695   Thomas Graf   dcbnl: Return con...
999
  				return -EMSGSIZE;
08f10affe   Amir Vadai   net/dcb: Add an o...
1000
1001
  		}
  	}
c93682477   Shani Michaeli   net/dcb: Add IEEE...
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  	if (ops->ieee_getqcn) {
  		struct ieee_qcn qcn;
  
  		memset(&qcn, 0, sizeof(qcn));
  		err = ops->ieee_getqcn(netdev, &qcn);
  		if (!err) {
  			err = nla_put(skb, DCB_ATTR_IEEE_QCN,
  				      sizeof(qcn), &qcn);
  			if (err)
  				return -EMSGSIZE;
  		}
  	}
  
  	if (ops->ieee_getqcnstats) {
  		struct ieee_qcn_stats qcn_stats;
  
  		memset(&qcn_stats, 0, sizeof(qcn_stats));
  		err = ops->ieee_getqcnstats(netdev, &qcn_stats);
  		if (!err) {
  			err = nla_put(skb, DCB_ATTR_IEEE_QCN_STATS,
  				      sizeof(qcn_stats), &qcn_stats);
  			if (err)
  				return -EMSGSIZE;
  		}
  	}
3e29027af   John Fastabend   dcbnl: add suppor...
1027
1028
  	if (ops->ieee_getpfc) {
  		struct ieee_pfc pfc;
29cd8ae0e   Mathias Krause   dcbnl: fix variou...
1029
  		memset(&pfc, 0, sizeof(pfc));
3e29027af   John Fastabend   dcbnl: add suppor...
1030
  		err = ops->ieee_getpfc(netdev, &pfc);
1eb4c9777   David S. Miller   dcbnl: Stop using...
1031
1032
  		if (!err &&
  		    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
3d1f48695   Thomas Graf   dcbnl: Return con...
1033
  			return -EMSGSIZE;
3e29027af   John Fastabend   dcbnl: add suppor...
1034
  	}
9ab933ab2   John Fastabend   dcbnl: add applic...
1035
1036
  	app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
  	if (!app)
3d1f48695   Thomas Graf   dcbnl: Return con...
1037
  		return -EMSGSIZE;
9ab933ab2   John Fastabend   dcbnl: add applic...
1038

52cff74ee   Anish Bhatt   dcbnl : Disable s...
1039
  	spin_lock_bh(&dcb_lock);
9ab933ab2   John Fastabend   dcbnl: add applic...
1040
  	list_for_each_entry(itr, &dcb_app_list, list) {
e290ed813   Mark Rustad   dcb: Use ifindex ...
1041
  		if (itr->ifindex == netdev->ifindex) {
70bfa2d2e   Dan Carpenter   dcb: unlock on er...
1042
1043
1044
  			err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
  					 &itr->app);
  			if (err) {
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1045
  				spin_unlock_bh(&dcb_lock);
3d1f48695   Thomas Graf   dcbnl: Return con...
1046
  				return -EMSGSIZE;
70bfa2d2e   Dan Carpenter   dcb: unlock on er...
1047
1048
  			}
  		}
9ab933ab2   John Fastabend   dcbnl: add applic...
1049
  	}
c7797baf9   John Fastabend   dcb: Add DCBX cap...
1050
1051
1052
1053
1054
  
  	if (netdev->dcbnl_ops->getdcbx)
  		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
  	else
  		dcbx = -EOPNOTSUPP;
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1055
  	spin_unlock_bh(&dcb_lock);
9ab933ab2   John Fastabend   dcbnl: add applic...
1056
  	nla_nest_end(skb, app);
eed84713b   Shmulik Ravid   dcbnl: add suppor...
1057
1058
1059
  	/* get peer info if available */
  	if (ops->ieee_peer_getets) {
  		struct ieee_ets ets;
29cd8ae0e   Mathias Krause   dcbnl: fix variou...
1060
  		memset(&ets, 0, sizeof(ets));
eed84713b   Shmulik Ravid   dcbnl: add suppor...
1061
  		err = ops->ieee_peer_getets(netdev, &ets);
1eb4c9777   David S. Miller   dcbnl: Stop using...
1062
1063
  		if (!err &&
  		    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
3d1f48695   Thomas Graf   dcbnl: Return con...
1064
  			return -EMSGSIZE;
eed84713b   Shmulik Ravid   dcbnl: add suppor...
1065
1066
1067
1068
  	}
  
  	if (ops->ieee_peer_getpfc) {
  		struct ieee_pfc pfc;
29cd8ae0e   Mathias Krause   dcbnl: fix variou...
1069
  		memset(&pfc, 0, sizeof(pfc));
eed84713b   Shmulik Ravid   dcbnl: add suppor...
1070
  		err = ops->ieee_peer_getpfc(netdev, &pfc);
1eb4c9777   David S. Miller   dcbnl: Stop using...
1071
1072
  		if (!err &&
  		    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
3d1f48695   Thomas Graf   dcbnl: Return con...
1073
  			return -EMSGSIZE;
eed84713b   Shmulik Ravid   dcbnl: add suppor...
1074
1075
1076
  	}
  
  	if (ops->peer_getappinfo && ops->peer_getapptable) {
dc6ed1df5   Shmulik Ravid   dcbnl: add suppor...
1077
1078
1079
1080
  		err = dcbnl_build_peer_app(netdev, skb,
  					   DCB_ATTR_IEEE_PEER_APP,
  					   DCB_ATTR_IEEE_APP_UNSPEC,
  					   DCB_ATTR_IEEE_APP);
eed84713b   Shmulik Ravid   dcbnl: add suppor...
1081
  		if (err)
3d1f48695   Thomas Graf   dcbnl: Return con...
1082
  			return -EMSGSIZE;
eed84713b   Shmulik Ravid   dcbnl: add suppor...
1083
  	}
3e29027af   John Fastabend   dcbnl: add suppor...
1084
  	nla_nest_end(skb, ieee);
c7797baf9   John Fastabend   dcb: Add DCBX cap...
1085
1086
1087
  	if (dcbx >= 0) {
  		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
  		if (err)
3d1f48695   Thomas Graf   dcbnl: Return con...
1088
  			return -EMSGSIZE;
c7797baf9   John Fastabend   dcb: Add DCBX cap...
1089
  	}
3e29027af   John Fastabend   dcbnl: add suppor...
1090

314b4778e   John Fastabend   net: dcbnl, add m...
1091
  	return 0;
3e29027af   John Fastabend   dcbnl: add suppor...
1092
  }
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1093
1094
1095
1096
1097
1098
1099
1100
1101
  static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
  			     int dir)
  {
  	u8 pgid, up_map, prio, tc_pct;
  	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
  	int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
  	struct nlattr *pg = nla_nest_start(skb, i);
  
  	if (!pg)
3d1f48695   Thomas Graf   dcbnl: Return con...
1102
  		return -EMSGSIZE;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1103
1104
1105
1106
1107
  
  	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
  		struct nlattr *tc_nest = nla_nest_start(skb, i);
  
  		if (!tc_nest)
3d1f48695   Thomas Graf   dcbnl: Return con...
1108
  			return -EMSGSIZE;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
  
  		pgid = DCB_ATTR_VALUE_UNDEFINED;
  		prio = DCB_ATTR_VALUE_UNDEFINED;
  		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
  		up_map = DCB_ATTR_VALUE_UNDEFINED;
  
  		if (!dir)
  			ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
  					  &prio, &pgid, &tc_pct, &up_map);
  		else
  			ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
  					  &prio, &pgid, &tc_pct, &up_map);
1eb4c9777   David S. Miller   dcbnl: Stop using...
1121
1122
1123
1124
  		if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) ||
  		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) ||
  		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) ||
  		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct))
3d1f48695   Thomas Graf   dcbnl: Return con...
1125
  			return -EMSGSIZE;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
  		nla_nest_end(skb, tc_nest);
  	}
  
  	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
  		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
  
  		if (!dir)
  			ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
  					   &tc_pct);
  		else
  			ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
  					   &tc_pct);
1eb4c9777   David S. Miller   dcbnl: Stop using...
1138
  		if (nla_put_u8(skb, i, tc_pct))
3d1f48695   Thomas Graf   dcbnl: Return con...
1139
  			return -EMSGSIZE;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1140
1141
1142
  	}
  	nla_nest_end(skb, pg);
  	return 0;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1143
1144
1145
1146
1147
1148
1149
1150
1151
  }
  
  static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
  {
  	struct nlattr *cee, *app;
  	struct dcb_app_type *itr;
  	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
  	int dcbx, i, err = -EMSGSIZE;
  	u8 value;
1eb4c9777   David S. Miller   dcbnl: Stop using...
1152
1153
  	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
  		goto nla_put_failure;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
  	cee = nla_nest_start(skb, DCB_ATTR_CEE);
  	if (!cee)
  		goto nla_put_failure;
  
  	/* local pg */
  	if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
  		err = dcbnl_cee_pg_fill(skb, netdev, 1);
  		if (err)
  			goto nla_put_failure;
  	}
  
  	if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
  		err = dcbnl_cee_pg_fill(skb, netdev, 0);
  		if (err)
  			goto nla_put_failure;
  	}
  
  	/* local pfc */
  	if (ops->getpfccfg) {
  		struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
  
  		if (!pfc_nest)
  			goto nla_put_failure;
  
  		for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
  			ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
1eb4c9777   David S. Miller   dcbnl: Stop using...
1180
1181
  			if (nla_put_u8(skb, i, value))
  				goto nla_put_failure;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1182
1183
1184
1185
1186
  		}
  		nla_nest_end(skb, pfc_nest);
  	}
  
  	/* local app */
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1187
  	spin_lock_bh(&dcb_lock);
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1188
1189
  	app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
  	if (!app)
40f5d72a4   Dan Carpenter   dcbnl: unlock on ...
1190
  		goto dcb_unlock;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1191
1192
  
  	list_for_each_entry(itr, &dcb_app_list, list) {
e290ed813   Mark Rustad   dcb: Use ifindex ...
1193
  		if (itr->ifindex == netdev->ifindex) {
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
  			struct nlattr *app_nest = nla_nest_start(skb,
  								 DCB_ATTR_APP);
  			if (!app_nest)
  				goto dcb_unlock;
  
  			err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
  					 itr->app.selector);
  			if (err)
  				goto dcb_unlock;
  
  			err = nla_put_u16(skb, DCB_APP_ATTR_ID,
  					  itr->app.protocol);
  			if (err)
  				goto dcb_unlock;
  
  			err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
  					 itr->app.priority);
  			if (err)
  				goto dcb_unlock;
  
  			nla_nest_end(skb, app_nest);
  		}
  	}
  	nla_nest_end(skb, app);
  
  	if (netdev->dcbnl_ops->getdcbx)
  		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
  	else
  		dcbx = -EOPNOTSUPP;
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1223
  	spin_unlock_bh(&dcb_lock);
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1224
1225
1226
1227
1228
1229
1230
1231
1232
  
  	/* features flags */
  	if (ops->getfeatcfg) {
  		struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
  		if (!feat)
  			goto nla_put_failure;
  
  		for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
  		     i++)
1eb4c9777   David S. Miller   dcbnl: Stop using...
1233
1234
1235
  			if (!ops->getfeatcfg(netdev, i, &value) &&
  			    nla_put_u8(skb, i, value))
  				goto nla_put_failure;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1236
1237
1238
1239
1240
1241
1242
  
  		nla_nest_end(skb, feat);
  	}
  
  	/* peer info if available */
  	if (ops->cee_peer_getpg) {
  		struct cee_pg pg;
29cd8ae0e   Mathias Krause   dcbnl: fix variou...
1243
  		memset(&pg, 0, sizeof(pg));
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1244
  		err = ops->cee_peer_getpg(netdev, &pg);
1eb4c9777   David S. Miller   dcbnl: Stop using...
1245
1246
1247
  		if (!err &&
  		    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
  			goto nla_put_failure;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1248
1249
1250
1251
  	}
  
  	if (ops->cee_peer_getpfc) {
  		struct cee_pfc pfc;
29cd8ae0e   Mathias Krause   dcbnl: fix variou...
1252
  		memset(&pfc, 0, sizeof(pfc));
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1253
  		err = ops->cee_peer_getpfc(netdev, &pfc);
1eb4c9777   David S. Miller   dcbnl: Stop using...
1254
1255
1256
  		if (!err &&
  		    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
  			goto nla_put_failure;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
  	}
  
  	if (ops->peer_getappinfo && ops->peer_getapptable) {
  		err = dcbnl_build_peer_app(netdev, skb,
  					   DCB_ATTR_CEE_PEER_APP_TABLE,
  					   DCB_ATTR_CEE_PEER_APP_INFO,
  					   DCB_ATTR_CEE_PEER_APP);
  		if (err)
  			goto nla_put_failure;
  	}
  	nla_nest_end(skb, cee);
  
  	/* DCBX state */
  	if (dcbx >= 0) {
  		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
  		if (err)
  			goto nla_put_failure;
  	}
  	return 0;
  
  dcb_unlock:
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1278
  	spin_unlock_bh(&dcb_lock);
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1279
  nla_put_failure:
c66ebf2db   Pan Bian   net: dcb: set err...
1280
  	err = -EMSGSIZE;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1281
1282
1283
1284
  	return err;
  }
  
  static int dcbnl_notify(struct net_device *dev, int event, int cmd,
15e473046   Eric W. Biederman   netlink: Rename p...
1285
  			u32 seq, u32 portid, int dcbx_ver)
314b4778e   John Fastabend   net: dcbnl, add m...
1286
1287
1288
1289
  {
  	struct net *net = dev_net(dev);
  	struct sk_buff *skb;
  	struct nlmsghdr *nlh;
314b4778e   John Fastabend   net: dcbnl, add m...
1290
1291
1292
1293
1294
  	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
  	int err;
  
  	if (!ops)
  		return -EOPNOTSUPP;
15e473046   Eric W. Biederman   netlink: Rename p...
1295
  	skb = dcbnl_newmsg(event, cmd, portid, seq, 0, &nlh);
314b4778e   John Fastabend   net: dcbnl, add m...
1296
1297
  	if (!skb)
  		return -ENOBUFS;
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1298
1299
1300
1301
  	if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
  		err = dcbnl_ieee_fill(skb, dev);
  	else
  		err = dcbnl_cee_fill(skb, dev);
314b4778e   John Fastabend   net: dcbnl, add m...
1302
1303
  	if (err < 0) {
  		/* Report error to broadcast listeners */
ab6d47073   Thomas Graf   dcbnl: Use dcbnl_...
1304
  		nlmsg_free(skb);
314b4778e   John Fastabend   net: dcbnl, add m...
1305
1306
1307
1308
1309
1310
1311
1312
1313
  		rtnl_set_sk_err(net, RTNLGRP_DCB, err);
  	} else {
  		/* End nlmsg and notify broadcast listeners */
  		nlmsg_end(skb, nlh);
  		rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
  	}
  
  	return err;
  }
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1314
1315
  
  int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
15e473046   Eric W. Biederman   netlink: Rename p...
1316
  		      u32 seq, u32 portid)
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1317
  {
15e473046   Eric W. Biederman   netlink: Rename p...
1318
  	return dcbnl_notify(dev, event, cmd, seq, portid, DCB_CAP_DCBX_VER_IEEE);
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1319
1320
1321
1322
  }
  EXPORT_SYMBOL(dcbnl_ieee_notify);
  
  int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
15e473046   Eric W. Biederman   netlink: Rename p...
1323
  		     u32 seq, u32 portid)
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1324
  {
15e473046   Eric W. Biederman   netlink: Rename p...
1325
  	return dcbnl_notify(dev, event, cmd, seq, portid, DCB_CAP_DCBX_VER_CEE);
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1326
1327
  }
  EXPORT_SYMBOL(dcbnl_cee_notify);
314b4778e   John Fastabend   net: dcbnl, add m...
1328

c93682477   Shani Michaeli   net/dcb: Add IEEE...
1329
1330
1331
  /* Handle IEEE 802.1Qaz/802.1Qau/802.1Qbb SET commands.
   * If any requested operation can not be completed
   * the entire msg is aborted and error value is returned.
314b4778e   John Fastabend   net: dcbnl, add m...
1332
1333
1334
   * No attempt is made to reconcile the case where only part of the
   * cmd can be completed.
   */
7be994138   Thomas Graf   dcbnl: Shorten al...
1335
1336
  static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
  			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
314b4778e   John Fastabend   net: dcbnl, add m...
1337
1338
1339
  {
  	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
  	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
3d1f48695   Thomas Graf   dcbnl: Return con...
1340
  	int err;
314b4778e   John Fastabend   net: dcbnl, add m...
1341
1342
  
  	if (!ops)
3d1f48695   Thomas Graf   dcbnl: Return con...
1343
  		return -EOPNOTSUPP;
314b4778e   John Fastabend   net: dcbnl, add m...
1344

4003b6587   John Fastabend   dcb: Add missing ...
1345
1346
  	if (!tb[DCB_ATTR_IEEE])
  		return -EINVAL;
314b4778e   John Fastabend   net: dcbnl, add m...
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
  	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
  			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
  	if (err)
  		return err;
  
  	if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
  		struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
  		err = ops->ieee_setets(netdev, ets);
  		if (err)
  			goto err;
  	}
08f10affe   Amir Vadai   net/dcb: Add an o...
1358
1359
1360
1361
1362
1363
1364
  	if (ieee[DCB_ATTR_IEEE_MAXRATE] && ops->ieee_setmaxrate) {
  		struct ieee_maxrate *maxrate =
  			nla_data(ieee[DCB_ATTR_IEEE_MAXRATE]);
  		err = ops->ieee_setmaxrate(netdev, maxrate);
  		if (err)
  			goto err;
  	}
c93682477   Shani Michaeli   net/dcb: Add IEEE...
1365
1366
1367
1368
1369
1370
1371
1372
  	if (ieee[DCB_ATTR_IEEE_QCN] && ops->ieee_setqcn) {
  		struct ieee_qcn *qcn =
  			nla_data(ieee[DCB_ATTR_IEEE_QCN]);
  
  		err = ops->ieee_setqcn(netdev, qcn);
  		if (err)
  			goto err;
  	}
314b4778e   John Fastabend   net: dcbnl, add m...
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
  	if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
  		struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
  		err = ops->ieee_setpfc(netdev, pfc);
  		if (err)
  			goto err;
  	}
  
  	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
  		struct nlattr *attr;
  		int rem;
  
  		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
  			struct dcb_app *app_data;
  			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
  				continue;
  			app_data = nla_data(attr);
  			if (ops->ieee_setapp)
  				err = ops->ieee_setapp(netdev, app_data);
  			else
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1392
  				err = dcb_ieee_setapp(netdev, app_data);
314b4778e   John Fastabend   net: dcbnl, add m...
1393
1394
1395
1396
1397
1398
  			if (err)
  				goto err;
  		}
  	}
  
  err:
7be994138   Thomas Graf   dcbnl: Shorten al...
1399
  	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1400
  	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
314b4778e   John Fastabend   net: dcbnl, add m...
1401
1402
  	return err;
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
1403
1404
  static int dcbnl_ieee_get(struct net_device *netdev, struct nlmsghdr *nlh,
  			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
314b4778e   John Fastabend   net: dcbnl, add m...
1405
  {
314b4778e   John Fastabend   net: dcbnl, add m...
1406
  	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
314b4778e   John Fastabend   net: dcbnl, add m...
1407
1408
1409
  
  	if (!ops)
  		return -EOPNOTSUPP;
7be994138   Thomas Graf   dcbnl: Shorten al...
1410
  	return dcbnl_ieee_fill(skb, netdev);
314b4778e   John Fastabend   net: dcbnl, add m...
1411
  }
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1412

7be994138   Thomas Graf   dcbnl: Shorten al...
1413
1414
  static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh,
  			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1415
1416
1417
  {
  	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
  	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
3d1f48695   Thomas Graf   dcbnl: Return con...
1418
  	int err;
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
  
  	if (!ops)
  		return -EOPNOTSUPP;
  
  	if (!tb[DCB_ATTR_IEEE])
  		return -EINVAL;
  
  	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
  			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
  	if (err)
  		return err;
  
  	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
  		struct nlattr *attr;
  		int rem;
  
  		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
  			struct dcb_app *app_data;
  
  			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
  				continue;
  			app_data = nla_data(attr);
  			if (ops->ieee_delapp)
  				err = ops->ieee_delapp(netdev, app_data);
  			else
  				err = dcb_ieee_delapp(netdev, app_data);
  			if (err)
  				goto err;
  		}
  	}
  
  err:
7be994138   Thomas Graf   dcbnl: Shorten al...
1451
  	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);
5b7f76267   Shmulik Ravid   dcbnl: Add CEE no...
1452
  	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1453
1454
  	return err;
  }
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1455
  /* DCBX configuration */
7be994138   Thomas Graf   dcbnl: Shorten al...
1456
1457
  static int dcbnl_getdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
  			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1458
  {
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1459
  	if (!netdev->dcbnl_ops->getdcbx)
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1460
  		return -EOPNOTSUPP;
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1461

7be994138   Thomas Graf   dcbnl: Shorten al...
1462
1463
  	return nla_put_u8(skb, DCB_ATTR_DCBX,
  			  netdev->dcbnl_ops->getdcbx(netdev));
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1464
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
1465
1466
  static int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
  			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1467
  {
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1468
  	u8 value;
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1469
1470
1471
1472
1473
  	if (!netdev->dcbnl_ops->setdcbx)
  		return -EOPNOTSUPP;
  
  	if (!tb[DCB_ATTR_DCBX])
  		return -EINVAL;
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1474
1475
  
  	value = nla_get_u8(tb[DCB_ATTR_DCBX]);
7be994138   Thomas Graf   dcbnl: Shorten al...
1476
1477
  	return nla_put_u8(skb, DCB_ATTR_DCBX,
  			  netdev->dcbnl_ops->setdcbx(netdev, value));
6241b6259   Shmulik Ravid   dcbnl: adding DCB...
1478
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
1479
1480
  static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1481
  {
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1482
1483
  	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
  	u8 value;
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1484
  	int ret, i;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1485
  	int getall = 0;
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1486
1487
1488
1489
1490
  	if (!netdev->dcbnl_ops->getfeatcfg)
  		return -EOPNOTSUPP;
  
  	if (!tb[DCB_ATTR_FEATCFG])
  		return -EINVAL;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1491
1492
1493
  
  	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
  			       dcbnl_featcfg_nest);
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1494
  	if (ret)
7be994138   Thomas Graf   dcbnl: Shorten al...
1495
  		return ret;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1496

7be994138   Thomas Graf   dcbnl: Shorten al...
1497
1498
1499
  	nest = nla_nest_start(skb, DCB_ATTR_FEATCFG);
  	if (!nest)
  		return -EMSGSIZE;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1500
1501
1502
1503
1504
1505
1506
1507
1508
  
  	if (data[DCB_FEATCFG_ATTR_ALL])
  		getall = 1;
  
  	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
  		if (!getall && !data[i])
  			continue;
  
  		ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1509
  		if (!ret)
7be994138   Thomas Graf   dcbnl: Shorten al...
1510
  			ret = nla_put_u8(skb, i, value);
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1511

7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1512
  		if (ret) {
7be994138   Thomas Graf   dcbnl: Shorten al...
1513
  			nla_nest_cancel(skb, nest);
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1514
1515
  			goto nla_put_failure;
  		}
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1516
  	}
7be994138   Thomas Graf   dcbnl: Shorten al...
1517
  	nla_nest_end(skb, nest);
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1518

7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1519
  nla_put_failure:
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1520
1521
  	return ret;
  }
7be994138   Thomas Graf   dcbnl: Shorten al...
1522
1523
  static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
  			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1524
1525
  {
  	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1526
  	int ret, i;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1527
  	u8 value;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1528

7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1529
1530
1531
1532
1533
  	if (!netdev->dcbnl_ops->setfeatcfg)
  		return -ENOTSUPP;
  
  	if (!tb[DCB_ATTR_FEATCFG])
  		return -EINVAL;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1534
1535
1536
  
  	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
  			       dcbnl_featcfg_nest);
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1537
  	if (ret)
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1538
  		goto err;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
  
  	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
  		if (data[i] == NULL)
  			continue;
  
  		value = nla_get_u8(data[i]);
  
  		ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value);
  
  		if (ret)
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1549
  			goto err;
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1550
  	}
ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1551
  err:
7be994138   Thomas Graf   dcbnl: Shorten al...
1552
  	ret = nla_put_u8(skb, DCB_ATTR_FEATCFG, ret);
7f891cf1f   Shmulik Ravid   dcbnl: more infor...
1553

ea45fe4e1   Shmulik Ravid   dcbnl: adding DCB...
1554
1555
  	return ret;
  }
dc6ed1df5   Shmulik Ravid   dcbnl: add suppor...
1556
  /* Handle CEE DCBX GET commands. */
7be994138   Thomas Graf   dcbnl: Shorten al...
1557
1558
  static int dcbnl_cee_get(struct net_device *netdev, struct nlmsghdr *nlh,
  			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
dc6ed1df5   Shmulik Ravid   dcbnl: add suppor...
1559
  {
dc6ed1df5   Shmulik Ravid   dcbnl: add suppor...
1560
  	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
dc6ed1df5   Shmulik Ravid   dcbnl: add suppor...
1561
1562
1563
  
  	if (!ops)
  		return -EOPNOTSUPP;
7be994138   Thomas Graf   dcbnl: Shorten al...
1564
  	return dcbnl_cee_fill(skb, netdev);
dc6ed1df5   Shmulik Ravid   dcbnl: add suppor...
1565
  }
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
  struct reply_func {
  	/* reply netlink message type */
  	int	type;
  
  	/* function to fill message contents */
  	int   (*cb)(struct net_device *, struct nlmsghdr *, u32,
  		    struct nlattr **, struct sk_buff *);
  };
  
  static const struct reply_func reply_funcs[DCB_CMD_MAX+1] = {
7be994138   Thomas Graf   dcbnl: Shorten al...
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
  	[DCB_CMD_GSTATE]	= { RTM_GETDCB, dcbnl_getstate },
  	[DCB_CMD_SSTATE]	= { RTM_SETDCB, dcbnl_setstate },
  	[DCB_CMD_PFC_GCFG]	= { RTM_GETDCB, dcbnl_getpfccfg },
  	[DCB_CMD_PFC_SCFG]	= { RTM_SETDCB, dcbnl_setpfccfg },
  	[DCB_CMD_GPERM_HWADDR]	= { RTM_GETDCB, dcbnl_getperm_hwaddr },
  	[DCB_CMD_GCAP]		= { RTM_GETDCB, dcbnl_getcap },
  	[DCB_CMD_GNUMTCS]	= { RTM_GETDCB, dcbnl_getnumtcs },
  	[DCB_CMD_SNUMTCS]	= { RTM_SETDCB, dcbnl_setnumtcs },
  	[DCB_CMD_PFC_GSTATE]	= { RTM_GETDCB, dcbnl_getpfcstate },
  	[DCB_CMD_PFC_SSTATE]	= { RTM_SETDCB, dcbnl_setpfcstate },
  	[DCB_CMD_GAPP]		= { RTM_GETDCB, dcbnl_getapp },
  	[DCB_CMD_SAPP]		= { RTM_SETDCB, dcbnl_setapp },
  	[DCB_CMD_PGTX_GCFG]	= { RTM_GETDCB, dcbnl_pgtx_getcfg },
  	[DCB_CMD_PGTX_SCFG]	= { RTM_SETDCB, dcbnl_pgtx_setcfg },
  	[DCB_CMD_PGRX_GCFG]	= { RTM_GETDCB, dcbnl_pgrx_getcfg },
  	[DCB_CMD_PGRX_SCFG]	= { RTM_SETDCB, dcbnl_pgrx_setcfg },
  	[DCB_CMD_SET_ALL]	= { RTM_SETDCB, dcbnl_setall },
  	[DCB_CMD_BCN_GCFG]	= { RTM_GETDCB, dcbnl_bcn_getcfg },
  	[DCB_CMD_BCN_SCFG]	= { RTM_SETDCB, dcbnl_bcn_setcfg },
  	[DCB_CMD_IEEE_GET]	= { RTM_GETDCB, dcbnl_ieee_get },
  	[DCB_CMD_IEEE_SET]	= { RTM_SETDCB, dcbnl_ieee_set },
  	[DCB_CMD_IEEE_DEL]	= { RTM_SETDCB, dcbnl_ieee_del },
  	[DCB_CMD_GDCBX]		= { RTM_GETDCB, dcbnl_getdcbx },
  	[DCB_CMD_SDCBX]		= { RTM_SETDCB, dcbnl_setdcbx },
  	[DCB_CMD_GFEATCFG]	= { RTM_GETDCB, dcbnl_getfeatcfg },
  	[DCB_CMD_SFEATCFG]	= { RTM_SETDCB, dcbnl_setfeatcfg },
  	[DCB_CMD_CEE_GET]	= { RTM_GETDCB, dcbnl_cee_get },
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
1603
  };
661d2967b   Thomas Graf   rtnetlink: Remove...
1604
  static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh)
2f90b8657   Alexander Duyck   ixgbe: this patch...
1605
1606
1607
  {
  	struct net *net = sock_net(skb->sk);
  	struct net_device *netdev;
7a282bc37   Thomas Graf   dcbnl: Use type s...
1608
  	struct dcbmsg *dcb = nlmsg_data(nlh);
2f90b8657   Alexander Duyck   ixgbe: this patch...
1609
  	struct nlattr *tb[DCB_ATTR_MAX + 1];
15e473046   Eric W. Biederman   netlink: Rename p...
1610
  	u32 portid = skb ? NETLINK_CB(skb).portid : 0;
2f90b8657   Alexander Duyck   ixgbe: this patch...
1611
  	int ret = -EINVAL;
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
1612
  	struct sk_buff *reply_skb;
39912f9cf   Thomas Graf   dcbnl: Silence ha...
1613
  	struct nlmsghdr *reply_nlh = NULL;
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
1614
  	const struct reply_func *fn;
2f90b8657   Alexander Duyck   ixgbe: this patch...
1615

90f62cf30   Eric W. Biederman   net: Use netlink_...
1616
  	if ((nlh->nlmsg_type == RTM_SETDCB) && !netlink_capable(skb, CAP_NET_ADMIN))
dfc47ef86   Eric W. Biederman   net: Push capable...
1617
  		return -EPERM;
2f90b8657   Alexander Duyck   ixgbe: this patch...
1618
1619
1620
1621
  	ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
  			  dcbnl_rtnl_policy);
  	if (ret < 0)
  		return ret;
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
1622
1623
1624
1625
1626
1627
1628
  	if (dcb->cmd > DCB_CMD_MAX)
  		return -EINVAL;
  
  	/* check if a reply function has been defined for the command */
  	fn = &reply_funcs[dcb->cmd];
  	if (!fn->cb)
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
1629
1630
  	if (!tb[DCB_ATTR_IFNAME])
  		return -EINVAL;
d9ac62be5   Ying Xue   dcb: use __dev_ge...
1631
  	netdev = __dev_get_by_name(net, nla_data(tb[DCB_ATTR_IFNAME]));
2f90b8657   Alexander Duyck   ixgbe: this patch...
1632
  	if (!netdev)
3d1f48695   Thomas Graf   dcbnl: Return con...
1633
  		return -ENODEV;
2f90b8657   Alexander Duyck   ixgbe: this patch...
1634

d9ac62be5   Ying Xue   dcb: use __dev_ge...
1635
1636
  	if (!netdev->dcbnl_ops)
  		return -EOPNOTSUPP;
2f90b8657   Alexander Duyck   ixgbe: this patch...
1637

15e473046   Eric W. Biederman   netlink: Rename p...
1638
  	reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, portid, nlh->nlmsg_seq,
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
1639
  				 nlh->nlmsg_flags, &reply_nlh);
d9ac62be5   Ying Xue   dcb: use __dev_ge...
1640
1641
  	if (!reply_skb)
  		return -ENOBUFS;
33a03aadb   Thomas Graf   dcbnl: Prepare fr...
1642
1643
1644
1645
1646
1647
1648
1649
  
  	ret = fn->cb(netdev, nlh, nlh->nlmsg_seq, tb, reply_skb);
  	if (ret < 0) {
  		nlmsg_free(reply_skb);
  		goto out;
  	}
  
  	nlmsg_end(reply_skb, reply_nlh);
7c77ab24e   John Fastabend   net: Allow DCBnl ...
1650
  	ret = rtnl_unicast(reply_skb, net, portid);
2f90b8657   Alexander Duyck   ixgbe: this patch...
1651
  out:
2f90b8657   Alexander Duyck   ixgbe: this patch...
1652
1653
  	return ret;
  }
716b31abb   Thomas Graf   dcbnl: Move dcb a...
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
  static struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app,
  					   int ifindex, int prio)
  {
  	struct dcb_app_type *itr;
  
  	list_for_each_entry(itr, &dcb_app_list, list) {
  		if (itr->app.selector == app->selector &&
  		    itr->app.protocol == app->protocol &&
  		    itr->ifindex == ifindex &&
  		    (!prio || itr->app.priority == prio))
  			return itr;
  	}
  
  	return NULL;
  }
4e4f2f697   Thomas Graf   dcbnl: Move dcb a...
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
  static int dcb_app_add(const struct dcb_app *app, int ifindex)
  {
  	struct dcb_app_type *entry;
  
  	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
  	if (!entry)
  		return -ENOMEM;
  
  	memcpy(&entry->app, app, sizeof(*app));
  	entry->ifindex = ifindex;
  	list_add(&entry->list, &dcb_app_list);
  
  	return 0;
  }
9ab933ab2   John Fastabend   dcbnl: add applic...
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
  /**
   * dcb_getapp - retrieve the DCBX application user priority
   *
   * On success returns a non-zero 802.1p user priority bitmap
   * otherwise returns 0 as the invalid user priority bitmap to
   * indicate an error.
   */
  u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
  {
  	struct dcb_app_type *itr;
  	u8 prio = 0;
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1694
  	spin_lock_bh(&dcb_lock);
716b31abb   Thomas Graf   dcbnl: Move dcb a...
1695
1696
  	if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
  		prio = itr->app.priority;
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1697
  	spin_unlock_bh(&dcb_lock);
9ab933ab2   John Fastabend   dcbnl: add applic...
1698
1699
1700
1701
1702
1703
  
  	return prio;
  }
  EXPORT_SYMBOL(dcb_getapp);
  
  /**
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1704
   * dcb_setapp - add CEE dcb application data to app list
9ab933ab2   John Fastabend   dcbnl: add applic...
1705
   *
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1706
1707
   * Priority 0 is an invalid priority in CEE spec. This routine
   * removes applications from the app list if the priority is
16eecd9be   Anish Bhatt   dcbnl : Fix misle...
1708
   * set to zero. Priority is expected to be 8-bit 802.1p user priority bitmap
9ab933ab2   John Fastabend   dcbnl: add applic...
1709
   */
ab6baf980   John Fastabend   dcb: fix return t...
1710
  int dcb_setapp(struct net_device *dev, struct dcb_app *new)
9ab933ab2   John Fastabend   dcbnl: add applic...
1711
1712
  {
  	struct dcb_app_type *itr;
7ec79270d   John Fastabend   net: dcb: applica...
1713
  	struct dcb_app_type event;
4e4f2f697   Thomas Graf   dcbnl: Move dcb a...
1714
  	int err = 0;
7ec79270d   John Fastabend   net: dcb: applica...
1715

e290ed813   Mark Rustad   dcb: Use ifindex ...
1716
  	event.ifindex = dev->ifindex;
7ec79270d   John Fastabend   net: dcb: applica...
1717
  	memcpy(&event.app, new, sizeof(event.app));
6bd0e1cb1   John Fastabend   dcb: add DCBX mod...
1718
1719
  	if (dev->dcbnl_ops->getdcbx)
  		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
9ab933ab2   John Fastabend   dcbnl: add applic...
1720

52cff74ee   Anish Bhatt   dcbnl : Disable s...
1721
  	spin_lock_bh(&dcb_lock);
9ab933ab2   John Fastabend   dcbnl: add applic...
1722
  	/* Search for existing match and replace */
716b31abb   Thomas Graf   dcbnl: Move dcb a...
1723
1724
1725
1726
1727
1728
  	if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) {
  		if (new->priority)
  			itr->app.priority = new->priority;
  		else {
  			list_del(&itr->list);
  			kfree(itr);
9ab933ab2   John Fastabend   dcbnl: add applic...
1729
  		}
716b31abb   Thomas Graf   dcbnl: Move dcb a...
1730
  		goto out;
9ab933ab2   John Fastabend   dcbnl: add applic...
1731
1732
  	}
  	/* App type does not exist add new application type */
4e4f2f697   Thomas Graf   dcbnl: Move dcb a...
1733
1734
  	if (new->priority)
  		err = dcb_app_add(new, dev->ifindex);
9ab933ab2   John Fastabend   dcbnl: add applic...
1735
  out:
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1736
  	spin_unlock_bh(&dcb_lock);
4e4f2f697   Thomas Graf   dcbnl: Move dcb a...
1737
1738
1739
  	if (!err)
  		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
  	return err;
9ab933ab2   John Fastabend   dcbnl: add applic...
1740
1741
  }
  EXPORT_SYMBOL(dcb_setapp);
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1742
  /**
a364c8cf8   John Fastabend   dcb: Add dcb_ieee...
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
   * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
   *
   * Helper routine which on success returns a non-zero 802.1Qaz user
   * priority bitmap otherwise returns 0 to indicate the dcb_app was
   * not found in APP list.
   */
  u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
  {
  	struct dcb_app_type *itr;
  	u8 prio = 0;
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1753
  	spin_lock_bh(&dcb_lock);
716b31abb   Thomas Graf   dcbnl: Move dcb a...
1754
1755
  	if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
  		prio |= 1 << itr->app.priority;
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1756
  	spin_unlock_bh(&dcb_lock);
a364c8cf8   John Fastabend   dcb: Add dcb_ieee...
1757
1758
1759
1760
1761
1762
  
  	return prio;
  }
  EXPORT_SYMBOL(dcb_ieee_getapp_mask);
  
  /**
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1763
1764
1765
1766
   * dcb_ieee_setapp - add IEEE dcb application data to app list
   *
   * This adds Application data to the list. Multiple application
   * entries may exists for the same selector and protocol as long
16eecd9be   Anish Bhatt   dcbnl : Fix misle...
1767
1768
   * as the priorities are different. Priority is expected to be a
   * 3-bit unsigned integer
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1769
1770
1771
   */
  int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
  {
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1772
1773
  	struct dcb_app_type event;
  	int err = 0;
e290ed813   Mark Rustad   dcb: Use ifindex ...
1774
  	event.ifindex = dev->ifindex;
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1775
  	memcpy(&event.app, new, sizeof(event.app));
6bd0e1cb1   John Fastabend   dcb: add DCBX mod...
1776
1777
  	if (dev->dcbnl_ops->getdcbx)
  		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1778

52cff74ee   Anish Bhatt   dcbnl : Disable s...
1779
  	spin_lock_bh(&dcb_lock);
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1780
  	/* Search for existing match and abort if found */
716b31abb   Thomas Graf   dcbnl: Move dcb a...
1781
1782
1783
  	if (dcb_app_lookup(new, dev->ifindex, new->priority)) {
  		err = -EEXIST;
  		goto out;
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1784
  	}
4e4f2f697   Thomas Graf   dcbnl: Move dcb a...
1785
  	err = dcb_app_add(new, dev->ifindex);
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1786
  out:
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1787
  	spin_unlock_bh(&dcb_lock);
b6db2174c   John Fastabend   dcb: Add ieee_dcb...
1788
1789
1790
1791
1792
  	if (!err)
  		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
  	return err;
  }
  EXPORT_SYMBOL(dcb_ieee_setapp);
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
  /**
   * dcb_ieee_delapp - delete IEEE dcb application data from list
   *
   * This removes a matching APP data from the APP list
   */
  int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
  {
  	struct dcb_app_type *itr;
  	struct dcb_app_type event;
  	int err = -ENOENT;
e290ed813   Mark Rustad   dcb: Use ifindex ...
1803
  	event.ifindex = dev->ifindex;
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1804
  	memcpy(&event.app, del, sizeof(event.app));
6bd0e1cb1   John Fastabend   dcb: add DCBX mod...
1805
1806
  	if (dev->dcbnl_ops->getdcbx)
  		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1807

52cff74ee   Anish Bhatt   dcbnl : Disable s...
1808
  	spin_lock_bh(&dcb_lock);
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1809
  	/* Search for existing match and remove it. */
716b31abb   Thomas Graf   dcbnl: Move dcb a...
1810
1811
1812
1813
  	if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) {
  		list_del(&itr->list);
  		kfree(itr);
  		err = 0;
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1814
  	}
52cff74ee   Anish Bhatt   dcbnl : Disable s...
1815
  	spin_unlock_bh(&dcb_lock);
f9ae7e4b5   John Fastabend   dcb: Add ieee_dcb...
1816
1817
1818
1819
1820
  	if (!err)
  		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
  	return err;
  }
  EXPORT_SYMBOL(dcb_ieee_delapp);
2f90b8657   Alexander Duyck   ixgbe: this patch...
1821
1822
  static int __init dcbnl_init(void)
  {
9ab933ab2   John Fastabend   dcbnl: add applic...
1823
  	INIT_LIST_HEAD(&dcb_app_list);
c7ac8679b   Greg Rose   rtnetlink: Comput...
1824
1825
  	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
  	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
2f90b8657   Alexander Duyck   ixgbe: this patch...
1826
1827
1828
  
  	return 0;
  }
36b9ad808   Paul Gortmaker   net/dcb: make dcb...
1829
  device_initcall(dcbnl_init);