• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2016 Intel Corp. All rights reserved.
4  * Copyright (c) 2016 Jef Oliver <jef.oliver@intel.com>
5  */
6 
7 /**
8  * @ingroup link
9  * @defgroup sriov SRIOV
10  * SR-IOV VF link module
11  *
12  * @details
13  * SR-IOV (Single Root Input/Output Virtualization) is a network interface
14  * that allows for the isolation of the PCI Express resources. In a virtual
15  * environment, SR-IOV allows multiple virtual machines can share a single
16  * PCI Express hardware interface. This is done via VFs (Virtual Functions),
17  * virtual hardware devices with their own PCI address.
18  *
19  * @{
20  */
21 
22 #include <netlink-private/netlink.h>
23 #include <netlink-private/route/link/api.h>
24 #include <netlink/netlink.h>
25 #include <netlink/route/link.h>
26 
27 #include <linux/if_ether.h>
28 #include <linux/if_link.h>
29 #include <netlink-private/route/link/sriov.h>
30 #include <netlink/route/link/sriov.h>
31 
32 /** @cond SKIP */
33 
34 #define SRIOVON "on"
35 #define SRIOVOFF "off"
36 
37 #define SET_VF_STAT(link, vf_num, stb, stat, attr) \
38 	vf_data->vf_stats[stat] = nla_get_u64(stb[attr])
39 
40 /* SRIOV-VF Attributes */
41 #define SRIOV_ATTR_INDEX 		(1 <<  0)
42 #define SRIOV_ATTR_ADDR 		(1 <<  1)
43 #define SRIOV_ATTR_VLAN 		(1 <<  2)
44 #define SRIOV_ATTR_TX_RATE 		(1 <<  3)
45 #define SRIOV_ATTR_SPOOFCHK 		(1 <<  4)
46 #define SRIOV_ATTR_RATE_MAX 		(1 <<  5)
47 #define SRIOV_ATTR_RATE_MIN 		(1 <<  6)
48 #define SRIOV_ATTR_LINK_STATE 		(1 <<  7)
49 #define SRIOV_ATTR_RSS_QUERY_EN 	(1 <<  8)
50 #define SRIOV_ATTR_STATS 		(1 <<  9)
51 #define SRIOV_ATTR_TRUST 		(1 << 10)
52 #define SRIOV_ATTR_IB_NODE_GUID 	(1 << 11)
53 #define SRIOV_ATTR_IB_PORT_GUID 	(1 << 12)
54 
55 static struct nla_policy sriov_info_policy[IFLA_VF_MAX+1] = {
56 	[IFLA_VF_MAC]		= { .minlen = sizeof(struct ifla_vf_mac) },
57 	[IFLA_VF_VLAN]		= { .minlen = sizeof(struct ifla_vf_vlan) },
58 	[IFLA_VF_VLAN_LIST]     = { .type = NLA_NESTED },
59 	[IFLA_VF_TX_RATE]	= { .minlen = sizeof(struct ifla_vf_tx_rate) },
60 	[IFLA_VF_SPOOFCHK]	= { .minlen = sizeof(struct ifla_vf_spoofchk) },
61 	[IFLA_VF_RATE]		= { .minlen = sizeof(struct ifla_vf_rate) },
62 	[IFLA_VF_LINK_STATE]	= { .minlen = sizeof(struct ifla_vf_link_state) },
63 	[IFLA_VF_RSS_QUERY_EN]	= { .minlen = sizeof(struct ifla_vf_rss_query_en) },
64 	[IFLA_VF_STATS]		= { .type = NLA_NESTED },
65 	[IFLA_VF_TRUST]		= { .minlen = sizeof(struct ifla_vf_trust) },
66 	[IFLA_VF_IB_NODE_GUID]	= { .minlen = sizeof(struct ifla_vf_guid) },
67 	[IFLA_VF_IB_PORT_GUID]	= { .minlen = sizeof(struct ifla_vf_guid) },
68 };
69 
70 static struct nla_policy sriov_stats_policy[IFLA_VF_STATS_MAX+1] = {
71 	[IFLA_VF_STATS_RX_PACKETS]	= { .type = NLA_U64 },
72 	[IFLA_VF_STATS_TX_PACKETS]	= { .type = NLA_U64 },
73 	[IFLA_VF_STATS_RX_BYTES]	= { .type = NLA_U64 },
74 	[IFLA_VF_STATS_TX_BYTES]	= { .type = NLA_U64 },
75 	[IFLA_VF_STATS_BROADCAST]	= { .type = NLA_U64 },
76 	[IFLA_VF_STATS_MULTICAST]	= { .type = NLA_U64 },
77 };
78 
79 /** @endcond */
80 
81 /* Clone SRIOV VF list in link object */
rtnl_link_sriov_clone(struct rtnl_link * dst,struct rtnl_link * src)82 int rtnl_link_sriov_clone(struct rtnl_link *dst, struct rtnl_link *src) {
83 	int err = 0;
84 	struct nl_addr *vf_addr;
85 	struct rtnl_link_vf *s_list, *d_vf, *s_vf, *next, *dest_h = NULL;
86 	nl_vf_vlans_t *src_vlans = NULL, *dst_vlans = NULL;
87 	nl_vf_vlan_info_t *src_vlan_info = NULL, *dst_vlan_info = NULL;
88 
89 	if (!rtnl_link_has_vf_list(src))
90 		return 0;
91 
92 	dst->l_vf_list = rtnl_link_vf_alloc();
93 	if (!dst->l_vf_list)
94 		return -NLE_NOMEM;
95 	dest_h = dst->l_vf_list;
96 	s_list = src->l_vf_list;
97 
98 	nl_list_for_each_entry_safe(s_vf, next, &s_list->vf_list, vf_list) {
99 		if (!(d_vf = rtnl_link_vf_alloc()))
100 			return -NLE_NOMEM;
101 
102 		memcpy(d_vf, s_vf, sizeof(*s_vf));
103 
104 		if (s_vf->ce_mask & SRIOV_ATTR_ADDR) {
105 			vf_addr = nl_addr_clone(s_vf->vf_lladdr);
106 			if (!vf_addr) {
107 				rtnl_link_vf_put(d_vf);
108 				return -NLE_NOMEM;
109 			}
110 			d_vf->vf_lladdr = vf_addr;
111 		}
112 
113 		if (s_vf->ce_mask & SRIOV_ATTR_VLAN) {
114 			src_vlans = s_vf->vf_vlans;
115 			src_vlan_info = src_vlans->vlans;
116 
117 			err = rtnl_link_vf_vlan_alloc(&dst_vlans,
118 						      src_vlans->size);
119 			if (err < 0) {
120 				rtnl_link_vf_put(d_vf);
121 				return err;
122 			}
123 			dst_vlan_info = dst_vlans->vlans;
124 			memcpy(dst_vlans, src_vlans, sizeof(nl_vf_vlans_t));
125 			memcpy(dst_vlan_info, src_vlan_info,
126 			       dst_vlans->size * sizeof(*dst_vlan_info));
127 			d_vf->vf_vlans = dst_vlans;
128 		}
129 
130 		nl_list_add_head(&d_vf->vf_list, &dest_h->vf_list);
131 		dest_h = d_vf;
132 	}
133 
134 	return 0;
135 }
136 
137 /* Dump VLAN details for each SRIOV VF */
dump_sriov_vlans(nl_vf_vlans_t * vlans,struct nl_dump_params * p)138 static void dump_sriov_vlans(nl_vf_vlans_t *vlans,
139 			     struct nl_dump_params *p) {
140 	char buf[64];
141 	int cur = 0;
142 	nl_vf_vlan_info_t *vlan_data;
143 	uint16_t prot;
144 
145 	vlan_data = vlans->vlans;
146 	nl_dump(p, "\t      VLANS:\n");
147 	while (cur < vlans->size) {
148 		nl_dump(p, "\t      vlan %u", vlan_data[cur].vf_vlan);
149 		if (vlan_data[cur].vf_vlan_qos)
150 			nl_dump(p, " qos %u", vlan_data[cur].vf_vlan_qos);
151 		if (vlan_data[cur].vf_vlan_proto) {
152 			prot = vlan_data[cur].vf_vlan_proto;
153 			nl_dump(p, " proto %s",
154 				rtnl_link_vf_vlanproto2str(prot, buf,
155 							   sizeof(buf)));
156 		}
157 		nl_dump(p, "\n");
158 		cur++;
159 	}
160 
161 	return;
162 }
163 
164 /* Dump details for each SRIOV VF */
dump_vf_details(struct rtnl_link_vf * vf_data,struct nl_dump_params * p)165 static void dump_vf_details(struct rtnl_link_vf *vf_data,
166 			    struct nl_dump_params *p) {
167 	char buf[64];
168 	int err = 0;
169 	struct nl_vf_rate vf_rate;
170 	uint32_t v = 0;
171 
172 	nl_dump(p, "\tvf %u: ", vf_data->vf_index);
173 	if (vf_data->ce_mask & SRIOV_ATTR_LINK_STATE) {
174 		v = vf_data->vf_linkstate;
175 		nl_dump(p, "state %s ",
176 			rtnl_link_vf_linkstate2str(v, buf, sizeof(buf)));
177 	}
178 	if (vf_data->ce_mask & SRIOV_ATTR_ADDR) {
179 		nl_dump(p, "addr %s ",
180 			nl_addr2str(vf_data->vf_lladdr, buf, sizeof(buf)));
181 	}
182 	nl_dump(p, "\n");
183 
184 	v = vf_data->vf_spoofchk;
185 	nl_dump(p, "\t      spoofchk %s ", v ? SRIOVON : SRIOVOFF);
186 	v = vf_data->vf_trust;
187 	nl_dump(p, "trust %s ", v ? SRIOVON : SRIOVOFF);
188 	v = vf_data->vf_rss_query_en;
189 	nl_dump(p, "rss_query %s\n", v ? SRIOVON : SRIOVOFF);
190 
191 	err = rtnl_link_vf_get_rate(vf_data, &vf_rate);
192 	if (!err) {
193 		if (vf_rate.api == RTNL_LINK_VF_RATE_API_OLD)
194 			nl_dump(p, "\t      rate_api old rate %u\n",
195 				vf_rate.rate);
196 		else if (vf_rate.api == RTNL_LINK_VF_RATE_API_NEW)
197 			nl_dump(p, "\t      rate_api new min_rate %u "
198 					"max_rate %u\n", vf_rate.min_tx_rate,
199 				vf_rate.max_tx_rate);
200 	}
201 	if (vf_data->ce_mask & SRIOV_ATTR_VLAN)
202 		dump_sriov_vlans(vf_data->vf_vlans, p);
203 
204 	return;
205 }
206 
207 /* Loop through SRIOV VF list dump details */
rtnl_link_sriov_dump_details(struct rtnl_link * link,struct nl_dump_params * p)208 void rtnl_link_sriov_dump_details(struct rtnl_link *link,
209 				  struct nl_dump_params *p) {
210 	struct rtnl_link_vf *vf_data, *list, *next;
211 
212 	if (!rtnl_link_has_vf_list(link))
213 		BUG();
214 
215 	nl_dump(p, "    SRIOV VF List\n");
216 	list = link->l_vf_list;
217 	nl_list_for_each_entry_safe(vf_data, next, &list->vf_list, vf_list) {
218 		if (vf_data->ce_mask & SRIOV_ATTR_INDEX)
219 			dump_vf_details(vf_data, p);
220 	}
221 
222 	return;
223 }
224 
225 /* Dump stats for each SRIOV VF */
dump_vf_stats(struct rtnl_link_vf * vf_data,struct nl_dump_params * p)226 static void dump_vf_stats(struct rtnl_link_vf *vf_data,
227 			  struct nl_dump_params *p) {
228 	char *unit;
229 	float res;
230 
231 	nl_dump(p, "    VF %u Stats:\n", vf_data->vf_index);
232 	nl_dump_line(p, "\tRX:    %-14s %-10s   %-10s %-10s\n",
233 		     "bytes", "packets", "multicast", "broadcast");
234 
235 	res = nl_cancel_down_bytes(vf_data->vf_stats[RTNL_LINK_VF_STATS_RX_BYTES],
236 				   &unit);
237 
238 	nl_dump_line(p,
239 		"\t%10.2f %3s   %10" PRIu64 "   %10" PRIu64 " %10" PRIu64 "\n",
240 		res, unit,
241 		vf_data->vf_stats[RTNL_LINK_VF_STATS_RX_PACKETS],
242 		vf_data->vf_stats[RTNL_LINK_VF_STATS_MULTICAST],
243 		vf_data->vf_stats[RTNL_LINK_VF_STATS_BROADCAST]);
244 
245 	nl_dump_line(p, "\tTX:    %-14s %-10s\n", "bytes", "packets");
246 
247 	res = nl_cancel_down_bytes(vf_data->vf_stats[RTNL_LINK_VF_STATS_TX_BYTES],
248 				   &unit);
249 
250 	nl_dump_line(p, "\t%10.2f %3s   %10" PRIu64 "\n", res, unit,
251 		vf_data->vf_stats[RTNL_LINK_VF_STATS_TX_PACKETS]);
252 
253 	return;
254 }
255 
256 /* Loop through SRIOV VF list dump stats */
rtnl_link_sriov_dump_stats(struct rtnl_link * link,struct nl_dump_params * p)257 void rtnl_link_sriov_dump_stats(struct rtnl_link *link,
258 				struct nl_dump_params *p) {
259 	struct rtnl_link_vf *vf_data, *list, *next;
260 
261 	list = link->l_vf_list;
262 	nl_list_for_each_entry_safe(vf_data, next, &list->vf_list, vf_list) {
263 		if (vf_data->ce_mask & SRIOV_ATTR_INDEX)
264 			dump_vf_stats(vf_data, p);
265 	}
266 	nl_dump(p, "\n");
267 
268 	return;
269 }
270 
271 /* Free stored SRIOV VF data */
rtnl_link_sriov_free_data(struct rtnl_link * link)272 void rtnl_link_sriov_free_data(struct rtnl_link *link) {
273 	struct rtnl_link_vf *list, *vf, *next;
274 
275 	if (!rtnl_link_has_vf_list(link))
276 		return;
277 
278 	list = link->l_vf_list;
279 	nl_list_for_each_entry_safe(vf, next, &list->vf_list, vf_list) {
280 		nl_list_del(&vf->vf_list);
281 		rtnl_link_vf_put(vf);
282 	}
283 
284 	rtnl_link_vf_put(link->l_vf_list);
285 
286 	return;
287 }
288 
289 /* Fill VLAN info array */
rtnl_link_vf_vlan_info(int len,struct ifla_vf_vlan_info ** vi,nl_vf_vlans_t ** nvi)290 static int rtnl_link_vf_vlan_info(int len, struct ifla_vf_vlan_info **vi,
291 				  nl_vf_vlans_t **nvi) {
292 	int cur = 0, err;
293 	nl_vf_vlans_t *vlans;
294 
295 	if (len <= 0)
296 		return 0;
297 
298 	if ((err = rtnl_link_vf_vlan_alloc(&vlans, len)) < 0)
299 		return err;
300 
301 	cur = 0;
302 	while (cur < len) {
303 		vlans->vlans[cur].vf_vlan = vi[cur]->vlan ? vi[cur]->vlan : 0;
304 		vlans->vlans[cur].vf_vlan_qos = vi[cur]->qos ? vi[cur]->qos : 0;
305 		if (vi[cur]->vlan_proto) {
306 			vlans->vlans[cur].vf_vlan_proto = ntohs(vi[cur]->vlan_proto);
307 		} else {
308 			vlans->vlans[cur].vf_vlan_proto = ETH_P_8021Q;
309 		}
310 		cur++;
311 	}
312 
313 	*nvi = vlans;
314 	return 0;
315 }
316 
317 /* Fill the IFLA_VF_VLAN attribute */
sriov_fill_vf_vlan(struct nl_msg * msg,nl_vf_vlan_info_t * vinfo,uint32_t index)318 static void sriov_fill_vf_vlan(struct nl_msg *msg, nl_vf_vlan_info_t *vinfo,
319 			       uint32_t index) {
320 	struct ifla_vf_vlan vlan;
321 
322 	vlan.vf = index;
323 	vlan.vlan = vinfo[0].vf_vlan;
324 	vlan.qos = vinfo[0].vf_vlan_qos;
325 	NLA_PUT(msg, IFLA_VF_VLAN, sizeof(vlan), &vlan);
326 
327 nla_put_failure:
328 	return;
329 }
330 
331 /* Fill the IFLA_VF_VLAN_LIST attribute */
sriov_fill_vf_vlan_list(struct nl_msg * msg,nl_vf_vlans_t * vlans,uint32_t index)332 static int sriov_fill_vf_vlan_list(struct nl_msg *msg, nl_vf_vlans_t *vlans,
333 				   uint32_t index) {
334 	int cur = 0;
335 	nl_vf_vlan_info_t *vlan_info = vlans->vlans;
336 	struct ifla_vf_vlan_info vlan;
337 	struct nlattr *list;
338 
339 	if (!(list = nla_nest_start(msg, IFLA_VF_VLAN_LIST)))
340 		return -NLE_MSGSIZE;
341 
342 	vlan.vf = index;
343 	while (cur < vlans->size) {
344 		vlan.vlan = vlan_info[cur].vf_vlan;
345 		vlan.qos = vlan_info[cur].vf_vlan_qos;
346 		vlan.vlan_proto = vlan_info[cur].vf_vlan_proto;
347 
348 		NLA_PUT(msg, IFLA_VF_VLAN_INFO, sizeof(vlan), &vlan);
349 
350 		cur++;
351 	}
352 
353 nla_put_failure:
354 	nla_nest_end(msg, list);
355 
356 	return 0;
357 }
358 
359 /* Fill individual IFLA_VF_INFO attributes */
sriov_fill_vfinfo(struct nl_msg * msg,struct rtnl_link_vf * vf_data)360 static int sriov_fill_vfinfo(struct nl_msg *msg,
361 			     struct rtnl_link_vf *vf_data) {
362 	int err = 0, new_rate = 0;
363 	nl_vf_vlans_t *vlan_list;
364 	nl_vf_vlan_info_t *vlan_info;
365 	struct ifla_vf_guid vf_node_guid;
366 	struct ifla_vf_guid vf_port_guid;
367 	struct ifla_vf_link_state vf_link_state;
368 	struct ifla_vf_mac vf_mac;
369 	struct ifla_vf_rate new_vf_rate;
370 	struct ifla_vf_rss_query_en vf_rss_query_en;
371 	struct ifla_vf_spoofchk vf_spoofchk;
372 	struct ifla_vf_trust vf_trust;
373 	struct ifla_vf_tx_rate vf_rate;
374 	struct nlattr *list;
375 	uint16_t proto;
376 
377 	if (!(vf_data->ce_mask & SRIOV_ATTR_INDEX))
378 		return -NLE_MISSING_ATTR;
379 
380 	if (!(list = nla_nest_start(msg, IFLA_VF_INFO)))
381 		return -NLE_MSGSIZE;
382 
383 	/* IFLA_VF_MAC */
384 	if (vf_data->ce_mask & SRIOV_ATTR_ADDR) {
385 		vf_mac.vf = vf_data->vf_index;
386 		memset(vf_mac.mac, 0, sizeof(vf_mac.mac));
387 		memcpy(vf_mac.mac, nl_addr_get_binary_addr(vf_data->vf_lladdr),
388 		       nl_addr_get_len(vf_data->vf_lladdr));
389 		NLA_PUT(msg, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac);
390 	}
391 
392 	/* IFLA_VF_VLAN IFLA_VF_VLAN_LIST */
393 	if (vf_data->ce_mask & SRIOV_ATTR_VLAN) {
394 		vlan_list = vf_data->vf_vlans;
395 		vlan_info = vlan_list->vlans;
396 		proto = vlan_info[0].vf_vlan_proto;
397 		if (!proto)
398 			proto = ETH_P_8021Q;
399 
400 		if ((vlan_list->size == 1) && (proto == ETH_P_8021Q))
401 			sriov_fill_vf_vlan(msg, vlan_info, vf_data->vf_index);
402 		else
403 			err = sriov_fill_vf_vlan_list(msg, vlan_list,
404 						      vf_data->vf_index);
405 	}
406 
407 	/* IFLA_VF_TX_RATE */
408 	if (vf_data->ce_mask & SRIOV_ATTR_TX_RATE) {
409 		vf_rate.vf = vf_data->vf_index;
410 		vf_rate.rate = vf_data->vf_rate;
411 
412 		NLA_PUT(msg, IFLA_VF_TX_RATE, sizeof(vf_rate), &vf_rate);
413 	}
414 
415 	/* IFLA_VF_RATE */
416 	new_vf_rate.min_tx_rate = 0;
417 	new_vf_rate.max_tx_rate = 0;
418 	new_vf_rate.vf = vf_data->vf_index;
419 	if (vf_data->ce_mask & SRIOV_ATTR_RATE_MIN) {
420 		new_vf_rate.min_tx_rate = vf_data->vf_min_tx_rate;
421 		new_rate = 1;
422 	}
423 	if (vf_data->ce_mask & SRIOV_ATTR_RATE_MAX) {
424 		new_vf_rate.max_tx_rate = vf_data->vf_max_tx_rate;
425 		new_rate = 1;
426 	}
427 	if (new_rate)
428 		NLA_PUT(msg, IFLA_VF_RATE, sizeof(new_vf_rate), &new_vf_rate);
429 
430 	/* IFLA_VF_SPOOFCHK */
431 	if (vf_data->ce_mask & SRIOV_ATTR_SPOOFCHK) {
432 		vf_spoofchk.vf = vf_data->vf_index;
433 		vf_spoofchk.setting = vf_data->vf_spoofchk;
434 
435 		NLA_PUT(msg, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
436 			&vf_spoofchk);
437 	}
438 
439 	/* IFLA_VF_LINK_STATE */
440 	if (vf_data->ce_mask & SRIOV_ATTR_LINK_STATE) {
441 		vf_link_state.vf = vf_data->vf_index;
442 		vf_link_state.link_state = vf_data->vf_linkstate;
443 
444 		NLA_PUT(msg, IFLA_VF_LINK_STATE, sizeof(vf_link_state),
445 			&vf_link_state);
446 	}
447 
448 	/* IFLA_VF_RSS_QUERY_EN */
449 	if (vf_data->ce_mask & SRIOV_ATTR_RSS_QUERY_EN) {
450 		vf_rss_query_en.vf = vf_data->vf_index;
451 		vf_rss_query_en.setting = vf_data->vf_rss_query_en;
452 
453 		NLA_PUT(msg, IFLA_VF_RSS_QUERY_EN, sizeof(vf_rss_query_en),
454 			&vf_rss_query_en);
455 	}
456 
457 	/* IFLA_VF_TRUST */
458 	if (vf_data->ce_mask & SRIOV_ATTR_TRUST) {
459 		vf_trust.vf = vf_data->vf_index;
460 		vf_trust.setting = vf_data->vf_trust;
461 
462 		NLA_PUT(msg, IFLA_VF_TRUST, sizeof(vf_trust), &vf_trust);
463 	}
464 
465 	/* IFLA_VF_IB_NODE_GUID */
466 	if (vf_data->ce_mask & SRIOV_ATTR_IB_NODE_GUID) {
467 		vf_node_guid.vf = vf_data->vf_index;
468 		vf_node_guid.guid = vf_data->vf_guid_node;
469 
470 		NLA_PUT(msg, IFLA_VF_IB_NODE_GUID, sizeof(vf_node_guid),
471 			&vf_node_guid);
472 	}
473 
474 	/* IFLA_VF_IB_PORT_GUID */
475 	if (vf_data->ce_mask & SRIOV_ATTR_IB_PORT_GUID) {
476 		vf_port_guid.vf = vf_data->vf_index;
477 		vf_port_guid.guid = vf_data->vf_guid_port;
478 
479 		NLA_PUT(msg, IFLA_VF_IB_PORT_GUID, sizeof(vf_port_guid),
480 			&vf_port_guid);
481 	}
482 
483 nla_put_failure:
484 	nla_nest_end(msg, list);
485 
486 	return err;
487 }
488 
489 /* Fill the IFLA_VFINFO_LIST attribute */
rtnl_link_sriov_fill_vflist(struct nl_msg * msg,struct rtnl_link * link)490 int rtnl_link_sriov_fill_vflist(struct nl_msg *msg, struct rtnl_link *link) {
491 	int err = 0;
492 	struct nlattr *data;
493 	struct rtnl_link_vf *list, *vf, *next;
494 
495 	if (!(err = rtnl_link_has_vf_list(link)))
496 		return 0;
497 
498 	if (!(data = nla_nest_start(msg, IFLA_VFINFO_LIST)))
499 		return -NLE_MSGSIZE;
500 
501 	list = link->l_vf_list;
502 	nl_list_for_each_entry_safe(vf, next, &list->vf_list, vf_list) {
503 		if (vf->ce_mask & SRIOV_ATTR_INDEX) {
504 			if ((err = sriov_fill_vfinfo(msg, vf)) < 0)
505 				goto nla_nest_list_failure;
506 		}
507 	}
508 
509 nla_nest_list_failure:
510 	nla_nest_end(msg, data);
511 
512 	return err;
513 }
514 
515 /* Parse IFLA_VFINFO_LIST and IFLA_VF_INFO attributes */
rtnl_link_sriov_parse_vflist(struct rtnl_link * link,struct nlattr ** tb)516 int rtnl_link_sriov_parse_vflist(struct rtnl_link *link, struct nlattr **tb) {
517 	int err, len, list_len, list_rem;
518 	struct ifla_vf_mac *vf_lladdr;
519 	struct ifla_vf_vlan *vf_vlan;
520 	struct ifla_vf_vlan_info *vf_vlan_info[MAX_VLAN_LIST_LEN];
521 	struct ifla_vf_tx_rate *vf_tx_rate;
522 	struct ifla_vf_spoofchk *vf_spoofchk;
523 	struct ifla_vf_link_state *vf_linkstate;
524 	struct ifla_vf_rate *vf_rate;
525 	struct ifla_vf_rss_query_en *vf_rss_query;
526 	struct ifla_vf_trust *vf_trust;
527 	struct nlattr *nla, *nla_list, *t[IFLA_VF_MAX+1],
528 		*stb[RTNL_LINK_VF_STATS_MAX+1];
529 	nl_vf_vlans_t *vf_vlans = NULL;
530 	struct rtnl_link_vf *vf_data, *vf_head = NULL;
531 
532 	len = nla_len(tb[IFLA_VFINFO_LIST]);
533 	link->l_vf_list = rtnl_link_vf_alloc();
534 	if (!link->l_vf_list)
535 		return -NLE_NOMEM;
536 	vf_head = link->l_vf_list;
537 
538 	for (nla = nla_data(tb[IFLA_VFINFO_LIST]); nla_ok(nla, len);
539 	     nla = nla_next(nla, &len)) {
540 		err = nla_parse(t, IFLA_VF_MAX, nla_data(nla), nla_len(nla),
541 				sriov_info_policy);
542 		if (err < 0)
543 			return err;
544 
545 		vf_data = rtnl_link_vf_alloc();
546 		if (!vf_data)
547 			return -NLE_NOMEM;
548 
549 		if (t[IFLA_VF_MAC]) {
550 			vf_lladdr = nla_data(t[IFLA_VF_MAC]);
551 
552 			vf_data->vf_index = vf_lladdr->vf;
553 			vf_data->ce_mask |= SRIOV_ATTR_INDEX;
554 
555 			vf_data->vf_lladdr = nl_addr_build(AF_LLC,
556 							   vf_lladdr->mac, 6);
557 			if (vf_data->vf_lladdr == NULL) {
558 				rtnl_link_vf_put(vf_data);
559 				return -NLE_NOMEM;
560 			}
561 			nl_addr_set_family(vf_data->vf_lladdr, AF_LLC);
562 			vf_data->ce_mask |= SRIOV_ATTR_ADDR;
563 		}
564 
565 		if (t[IFLA_VF_VLAN_LIST]) {
566 			list_len = 0;
567 			nla_for_each_nested(nla_list, t[IFLA_VF_VLAN_LIST],
568 					    list_rem) {
569 				if (list_len >= MAX_VLAN_LIST_LEN)
570 					break;
571 				vf_vlan_info[list_len] = nla_data(nla_list);
572 				list_len++;
573 			}
574 
575 			err = rtnl_link_vf_vlan_info(list_len, vf_vlan_info,
576 						     &vf_vlans);
577 			if (err < 0) {
578 				rtnl_link_vf_put(vf_data);
579 				return err;
580 			}
581 
582 			vf_data->vf_vlans = vf_vlans;
583 			vf_data->ce_mask |= SRIOV_ATTR_VLAN;
584 		} else if (t[IFLA_VF_VLAN]) {
585 			vf_vlan = nla_data(t[IFLA_VF_VLAN]);
586 
587 			if (vf_vlan->vlan) {
588 				err = rtnl_link_vf_vlan_alloc(&vf_vlans, 1);
589 				if (err < 0) {
590 					rtnl_link_vf_put(vf_data);
591 					return err;
592 				}
593 
594 				vf_vlans->vlans[0].vf_vlan = vf_vlan->vlan;
595 				vf_vlans->vlans[0].vf_vlan_qos = vf_vlan->qos;
596 				vf_vlans->vlans[0].vf_vlan_proto = ETH_P_8021Q;
597 
598 				vf_data->vf_vlans = vf_vlans;
599 				vf_data->ce_mask |= SRIOV_ATTR_VLAN;
600 			}
601 		}
602 
603 		if (t[IFLA_VF_TX_RATE]) {
604 			vf_tx_rate = nla_data(t[IFLA_VF_TX_RATE]);
605 
606 			if (vf_tx_rate->rate) {
607 				vf_data->vf_rate = vf_tx_rate->rate;
608 				vf_data->ce_mask |= SRIOV_ATTR_TX_RATE;
609 			}
610 		}
611 
612 		if (t[IFLA_VF_SPOOFCHK]) {
613 			vf_spoofchk = nla_data(t[IFLA_VF_SPOOFCHK]);
614 
615 			if (vf_spoofchk->setting != -1) {
616 				vf_data->vf_spoofchk = vf_spoofchk->setting ? 1 : 0;
617 				vf_data->ce_mask |= SRIOV_ATTR_SPOOFCHK;
618 			}
619 		}
620 
621 		if (t[IFLA_VF_LINK_STATE]) {
622 			vf_linkstate = nla_data(t[IFLA_VF_LINK_STATE]);
623 
624 			vf_data->vf_linkstate = vf_linkstate->link_state;
625 			vf_data->ce_mask |= SRIOV_ATTR_LINK_STATE;
626 		}
627 
628 		if (t[IFLA_VF_RATE]) {
629 			vf_rate = nla_data(t[IFLA_VF_RATE]);
630 
631 			if (vf_rate->max_tx_rate) {
632 				vf_data->vf_max_tx_rate = vf_rate->max_tx_rate;
633 				vf_data->ce_mask |= SRIOV_ATTR_RATE_MAX;
634 			}
635 			if (vf_rate->min_tx_rate) {
636 				vf_data->vf_min_tx_rate = vf_rate->min_tx_rate;
637 				vf_data->ce_mask |= SRIOV_ATTR_RATE_MIN;
638 			}
639 		}
640 
641 		if (t[IFLA_VF_RSS_QUERY_EN]) {
642 			vf_rss_query = nla_data(t[IFLA_VF_RSS_QUERY_EN]);
643 
644 			if (vf_rss_query->setting != -1) {
645 				vf_data->vf_rss_query_en = vf_rss_query->setting ? 1 : 0;
646 				vf_data->ce_mask |= SRIOV_ATTR_RSS_QUERY_EN;
647 			}
648 		}
649 
650 		if (t[IFLA_VF_STATS]) {
651 			err = nla_parse_nested(stb, RTNL_LINK_VF_STATS_MAX,
652 					       t[IFLA_VF_STATS],
653 					       sriov_stats_policy);
654 			if (err < 0) {
655 				rtnl_link_vf_put(vf_data);
656 				return err;
657 			}
658 
659 			SET_VF_STAT(link, cur, stb,
660 				    RTNL_LINK_VF_STATS_RX_PACKETS,
661 				    IFLA_VF_STATS_RX_PACKETS);
662 			SET_VF_STAT(link, cur, stb,
663 				    RTNL_LINK_VF_STATS_TX_PACKETS,
664 				    IFLA_VF_STATS_TX_PACKETS);
665 			SET_VF_STAT(link, cur, stb,
666 				    RTNL_LINK_VF_STATS_RX_BYTES,
667 				    IFLA_VF_STATS_RX_BYTES);
668 			SET_VF_STAT(link, cur, stb,
669 				    RTNL_LINK_VF_STATS_TX_BYTES,
670 				    IFLA_VF_STATS_TX_BYTES);
671 			SET_VF_STAT(link, cur, stb,
672 				    RTNL_LINK_VF_STATS_BROADCAST,
673 				    IFLA_VF_STATS_BROADCAST);
674 			SET_VF_STAT(link, cur, stb,
675 				    RTNL_LINK_VF_STATS_MULTICAST,
676 				    IFLA_VF_STATS_MULTICAST);
677 
678 			vf_data->ce_mask |= SRIOV_ATTR_STATS;
679 		}
680 
681 		if (t[IFLA_VF_TRUST]) {
682 			vf_trust = nla_data(t[IFLA_VF_TRUST]);
683 
684 			if (vf_trust->setting != -1) {
685 				vf_data->vf_trust = vf_trust->setting ? 1 : 0;
686 				vf_data->ce_mask |= SRIOV_ATTR_TRUST;
687 			}
688 		}
689 
690 		nl_list_add_head(&vf_data->vf_list, &vf_head->vf_list);
691 		vf_head = vf_data;
692 	}
693 
694 	return 0;
695 }
696 
697 /**
698  * @name SR-IOV Sub-Object
699  * @{
700  */
701 
702 /**
703  * Add a SRIOV VF object to a link object
704  * @param link  	Link object to add to
705  * @param vf_data 	SRIOV VF object to add
706  *
707  * @return 0 if SRIOV VF object added successfully
708  * @return -NLE_OBJ_NOTFOUND if \p link or \p vf_data not provided
709  * @return -NLE_NOMEM if out of memory
710  */
rtnl_link_vf_add(struct rtnl_link * link,struct rtnl_link_vf * vf_data)711 int rtnl_link_vf_add(struct rtnl_link *link, struct rtnl_link_vf *vf_data) {
712 	struct rtnl_link_vf *vf_head = NULL;
713 
714 	if (!link||!vf_data)
715 		return -NLE_OBJ_NOTFOUND;
716 
717 	if (!link->l_vf_list) {
718 		link->l_vf_list = rtnl_link_vf_alloc();
719 		if (!link->l_vf_list)
720 			return -NLE_NOMEM;
721 	}
722 
723 	vf_head = vf_data;
724 	vf_head->ce_refcnt++;
725 
726 	vf_head = link->l_vf_list;
727 	nl_list_add_head(&vf_data->vf_list, &vf_head->vf_list);
728 	link->l_vf_list = vf_head;
729 
730 	rtnl_link_set_vf_list(link);
731 
732 	return 0;
733 }
734 
735 /**
736  * Allocate a new SRIOV VF object
737  *
738  * @return NULL if out of memory
739  * @return New VF Object
740  *
741  * @see rtnl_link_vf_put()
742  *
743  * The SRIOV VF object must be returned to the link object with
744  * rtnl_link_vf_put() when operations are done to prevent memory leaks.
745  */
rtnl_link_vf_alloc(void)746 struct rtnl_link_vf *rtnl_link_vf_alloc(void) {
747 	struct rtnl_link_vf *vf;
748 
749 	if (!(vf = calloc(1, sizeof(*vf))))
750 		return NULL;
751 
752 	NL_INIT_LIST_HEAD(&vf->vf_list);
753 	vf->ce_refcnt = 1;
754 
755 	NL_DBG(4, "Allocated new SRIOV VF object %p\n", vf);
756 
757 	return vf;
758 }
759 
760 /**
761  * Free SRIOV VF object.
762  * @arg vf_data 	SRIOV VF data object
763  */
rtnl_link_vf_free(struct rtnl_link_vf * vf_data)764 void rtnl_link_vf_free(struct rtnl_link_vf *vf_data) {
765 	if (!vf_data)
766 		return;
767 
768 	if (vf_data->ce_refcnt > 0)
769 		NL_DBG(1, "Warning: Freeing SRIOV VF object in use...\n");
770 
771 	if (vf_data->ce_mask & SRIOV_ATTR_ADDR)
772 		nl_addr_put(vf_data->vf_lladdr);
773 	if (vf_data->ce_mask & SRIOV_ATTR_VLAN)
774 		rtnl_link_vf_vlan_put(vf_data->vf_vlans);
775 
776 	NL_DBG(4, "Freed SRIOV VF object %p\n", vf_data);
777 	free(vf_data);
778 
779 	return;
780 }
781 
782 /**
783  * Lookup SRIOV VF in link object by VF index.
784  *
785  * @return NULL if VF not found
786  * @return VF Object
787  *
788  * @see rtnl_link_vf_put()
789  *
790  * The SRIOV VF object must be returned to the link object with
791  * rtnl_link_vf_put() when operations are done to prevent memory leaks.
792  */
rtnl_link_vf_get(struct rtnl_link * link,uint32_t vf_num)793 struct rtnl_link_vf *rtnl_link_vf_get(struct rtnl_link *link, uint32_t vf_num) {
794 	struct rtnl_link_vf *list, *vf, *next, *ret = NULL;
795 
796 	list = link->l_vf_list;
797 	nl_list_for_each_entry_safe(vf, next, &list->vf_list, vf_list) {
798 		if (vf->vf_index == vf_num) {
799 			ret = vf;
800 			break;
801 		}
802 	}
803 
804 	if (ret) {
805 		ret->ce_refcnt++;
806 		NL_DBG(4, "New reference to SRIOV VF object %p, total %i\n",
807 		       ret, ret->ce_refcnt);
808 	}
809 
810 	return ret;
811 }
812 
813 /**
814  * Return SRIOV VF object to the owning link object.
815  * @arg vf_data 	SRIOV VF data object
816  *
817  * @see rtnl_link_vf_alloc()
818  * @see rtnl_link_vf_get()
819  */
rtnl_link_vf_put(struct rtnl_link_vf * vf_data)820 void rtnl_link_vf_put(struct rtnl_link_vf *vf_data) {
821 	if (!vf_data)
822 		return;
823 
824 	vf_data->ce_refcnt--;
825 	NL_DBG(4, "Returned SRIOV VF object reference %p, %i remaining\n",
826 	       vf_data, vf_data->ce_refcnt);
827 
828 	if (vf_data->ce_refcnt < 0)
829 		BUG();
830 
831 	if (vf_data->ce_refcnt <= 0)
832 		rtnl_link_vf_free(vf_data);
833 
834 	return;
835 }
836 
837 /**
838  * Get link layer address of SRIOV Virtual Function
839  * @arg vf_data 	SRIOV VF object
840  * @arg addr 		Pointer to store Link Layer address
841  *
842  * @see rtnl_link_get_num_vf()
843  * @see rtnl_link_vf_set_addr()
844  *
845  * @copydoc pointer_lifetime_warning
846  * @return 0 if addr is present and addr is set to pointer containing address
847  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
848  * @return -NLE_NOATTR if the link layer address is not set
849  */
rtnl_link_vf_get_addr(struct rtnl_link_vf * vf_data,struct nl_addr ** addr)850 int rtnl_link_vf_get_addr(struct rtnl_link_vf *vf_data, struct nl_addr **addr)
851 {
852 	if (!vf_data)
853 		return -NLE_OBJ_NOTFOUND;
854 
855 	if (vf_data->ce_mask & SRIOV_ATTR_ADDR)
856 		*addr = vf_data->vf_lladdr;
857 	else
858 		return -NLE_NOATTR;
859 
860 	return 0;
861 }
862 
863 /**
864  * Set link layer address of SRIOV Virtual Function object
865  * @param vf_data 	SRIOV VF object
866  * @param addr 		New link layer address
867  *
868  * This function increments the reference counter of the address object
869  * and overwrites any existing link layer address previously assigned.
870  *
871  * @see rtnl_link_vf_get_addr()
872  */
rtnl_link_vf_set_addr(struct rtnl_link_vf * vf_data,struct nl_addr * addr)873 void rtnl_link_vf_set_addr(struct rtnl_link_vf *vf_data, struct nl_addr *addr) {
874 	if (vf_data->vf_lladdr)
875 		nl_addr_put(vf_data->vf_lladdr);
876 
877 	nl_addr_get(addr);
878 	vf_data->vf_lladdr = addr;
879 	vf_data->ce_mask |= SRIOV_ATTR_ADDR;
880 
881 	return;
882 }
883 
884 /**
885  * Set the Infiniband node GUID for the SRIOV Virtual Function object
886  * @param vf_data 	SRIOV VF object
887  * @param guid  	node GUID
888  */
rtnl_link_vf_set_ib_node_guid(struct rtnl_link_vf * vf_data,uint64_t guid)889 void rtnl_link_vf_set_ib_node_guid(struct rtnl_link_vf *vf_data,
890 				   uint64_t guid) {
891 	vf_data->vf_guid_node = guid;
892 	vf_data->ce_mask |= SRIOV_ATTR_IB_NODE_GUID;
893 
894 	return;
895 }
896 
897 /**
898  * Set the Infiniband port GUID for the SRIOV Virtual Function object
899  * @param vf_data 	SRIOV VF object
900  * @param guid  	port GUID
901  */
rtnl_link_vf_set_ib_port_guid(struct rtnl_link_vf * vf_data,uint64_t guid)902 void rtnl_link_vf_set_ib_port_guid(struct rtnl_link_vf *vf_data,
903 				   uint64_t guid) {
904 	vf_data->vf_guid_port = guid;
905 	vf_data->ce_mask |= SRIOV_ATTR_IB_PORT_GUID;
906 
907 	return;
908 }
909 
910 /**
911  * Get index of SRIOV Virtual Function
912  * @arg vf_data 	SRIOV VF object
913  * @arg vf_index 	Pointer to store VF index
914  *
915  * @see rtnl_link_get_num_vf()
916  *
917  * @return 0 if index is present and vf_index is set
918  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
919  * @return -NLE_NOATTR if the VF index is not set
920  */
rtnl_link_vf_get_index(struct rtnl_link_vf * vf_data,uint32_t * vf_index)921 int rtnl_link_vf_get_index(struct rtnl_link_vf *vf_data, uint32_t *vf_index)
922 {
923 	if (!vf_data)
924 		return -NLE_OBJ_NOTFOUND;
925 
926 	if (vf_data->ce_mask & SRIOV_ATTR_INDEX)
927 		*vf_index = vf_data->vf_index;
928 	else
929 		return -NLE_NOATTR;
930 
931 	return 0;
932 }
933 
934 /**
935  * Set index of SRIOV Virtual Function object
936  * @param vf_data 	SRIOV VF object
937  * @param vf_index 	Index value
938  *
939  * @see rtnl_link_vf_get_index()
940  */
rtnl_link_vf_set_index(struct rtnl_link_vf * vf_data,uint32_t vf_index)941 void rtnl_link_vf_set_index(struct rtnl_link_vf *vf_data, uint32_t vf_index)
942 {
943 	vf_data->vf_index = vf_index;
944 	vf_data->ce_mask |= SRIOV_ATTR_INDEX;
945 
946 	return;
947 }
948 
949 /**
950  * Get link state of SRIOV Virtual Function
951  * @arg vf_data  	SRIOV VF object
952  * @arg vf_linkstate 	Pointer to store VF link state
953  *
954  * @see rtnl_link_get_num_vf()
955  * @see rtnl_link_set_linkstate()
956  *
957  * @return 0 if link state is present and vf_linkstate is set
958  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
959  * @return -NLE_NOATTR if the VF link state is not set
960  */
rtnl_link_vf_get_linkstate(struct rtnl_link_vf * vf_data,uint32_t * vf_linkstate)961 int rtnl_link_vf_get_linkstate(struct rtnl_link_vf *vf_data,
962 			       uint32_t *vf_linkstate)
963 {
964 	if (!vf_data)
965 		return -NLE_OBJ_NOTFOUND;
966 
967 	if (vf_data->ce_mask & SRIOV_ATTR_LINK_STATE)
968 		*vf_linkstate = vf_data->vf_linkstate;
969 	else
970 		return -NLE_NOATTR;
971 
972 	return 0;
973 }
974 
975 /**
976  * Set link state of SRIOV Virtual Function object
977  * @param vf_data 	SRIOV VF object
978  * @param vf_linkstate Link state value
979  *
980  * @see rtnl_link_get_linkstate()
981  *
982  * Not all hardware supports setting link state. If the feature is unsupported,
983  * the link change request will fail with -NLE_OPNOTSUPP
984  */
rtnl_link_vf_set_linkstate(struct rtnl_link_vf * vf_data,uint32_t vf_linkstate)985 void rtnl_link_vf_set_linkstate(struct rtnl_link_vf *vf_data,
986 				uint32_t vf_linkstate) {
987 	vf_data->vf_linkstate = vf_linkstate;
988 	vf_data->ce_mask |= SRIOV_ATTR_LINK_STATE;
989 
990 	return;
991 }
992 
993 /**
994  * Get TX Rate Limit of SRIOV Virtual Function
995  * @arg vf_data 	SRIOV VF object
996  * @arg vf_rate 	Pointer to store VF rate limiting data
997  *
998  * @see rtnl_link_get_num_vf()
999  * @see rtnl_link_set_rate()
1000  *
1001  * When the older rate API has been implemented, the rate member of the struct
1002  * will be set, and the api member will be set to RTNL_LINK_VF_API_OLD.
1003  * When the newer rate API has been implemented, the max_tx_rate
1004  * and/or the minx_tx_rate will be set, and the api member will be set to
1005  * RTNL_LINK_VF_API_NEW.
1006  *
1007  * Old rate API supports only a maximum TX rate.
1008  *   ip link set dev vf 0 rate
1009  * New rate API supports minumum and maximum TX rates.
1010  *   ip link set dev vf 0 min_tx_rate
1011  *   ip link set dev vf 0 max_tx_rate
1012  *
1013  * @return 0 if rate is present and vf_rate is set
1014  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
1015  * @return -NLE_NOATTR if the VF rate is not set
1016  */
rtnl_link_vf_get_rate(struct rtnl_link_vf * vf_data,struct nl_vf_rate * vf_rate)1017 int rtnl_link_vf_get_rate(struct rtnl_link_vf *vf_data,
1018 			  struct nl_vf_rate *vf_rate)
1019 {
1020 	int set = 0;
1021 
1022 	if (!vf_data)
1023 		return -NLE_OBJ_NOTFOUND;
1024 
1025 	vf_rate->api = RTNL_LINK_VF_RATE_API_UNSPEC;
1026 	vf_rate->rate = 0;
1027 	vf_rate->max_tx_rate = 0;
1028 	vf_rate->min_tx_rate = 0;
1029 
1030 	if (vf_data->ce_mask & SRIOV_ATTR_RATE_MAX) {
1031 		if (vf_data->vf_max_tx_rate) {
1032 			vf_rate->api = RTNL_LINK_VF_RATE_API_NEW;
1033 			vf_rate->max_tx_rate = vf_data->vf_max_tx_rate;
1034 			set = 1;
1035 		}
1036 	}
1037 	if (vf_data->ce_mask & SRIOV_ATTR_RATE_MIN) {
1038 		if (vf_data->vf_min_tx_rate) {
1039 			vf_rate->api = RTNL_LINK_VF_RATE_API_NEW;
1040 			vf_rate->min_tx_rate = vf_data->vf_min_tx_rate;
1041 			set = 1;
1042 		}
1043 	}
1044 	if ((!set) && (vf_data->ce_mask & SRIOV_ATTR_TX_RATE)) {
1045 		if (vf_data->vf_rate) {
1046 			vf_rate->api = RTNL_LINK_VF_RATE_API_OLD;
1047 			vf_rate->rate = vf_data->vf_rate;
1048 			set = 1;
1049 		}
1050 	}
1051 
1052 	if (!set)
1053 		return -NLE_NOATTR;
1054 
1055 	return 0;
1056 }
1057 
1058 /**
1059  * Set TX Rate Limit of SRIOV Virtual Function object
1060  * @param vf_data 	SRIOV VF object
1061  * @param vf_rate 	Rate limiting structure
1062  *
1063  * @see rtnl_link_vf_get_rate()
1064  *
1065  * When setting the rate, the API level must be specificed.
1066  * Valid API levels:
1067  *   RTNL_LINK_VF_RATE_API_NEW
1068  *   RTNL_LINK_VF_RATE_API_OLD
1069  *
1070  * When using the new API, if either the min_tx_rate or
1071  * max_tx_rate has been set, and the other is being changed,
1072  * you must specify the currently set values to preserve
1073  * them. If this is not done, that setting will be disabled.
1074  *
1075  * Old rate API supports only a maximum TX rate.
1076  *   ip link set dev vf 0 rate
1077  * New rate API supports minumum and maximum TX rates.
1078  *   ip link set dev vf 0 min_tx_rate
1079  *   ip link set dev vf 0 max_tx_rate
1080  *
1081  * Not all hardware supports min_tx_rate.
1082  */
rtnl_link_vf_set_rate(struct rtnl_link_vf * vf_data,struct nl_vf_rate * vf_rate)1083 void rtnl_link_vf_set_rate(struct rtnl_link_vf *vf_data,
1084 			   struct nl_vf_rate *vf_rate) {
1085 	if (vf_rate->api == RTNL_LINK_VF_RATE_API_OLD) {
1086 		vf_data->vf_rate = vf_rate->rate;
1087 		vf_data->ce_mask |= SRIOV_ATTR_TX_RATE;
1088 	} else if (vf_rate->api == RTNL_LINK_VF_RATE_API_NEW) {
1089 		vf_data->vf_max_tx_rate = vf_rate->max_tx_rate;
1090 		vf_data->ce_mask |= SRIOV_ATTR_RATE_MAX;
1091 
1092 		vf_data->vf_min_tx_rate = vf_rate->min_tx_rate;
1093 		vf_data->ce_mask |= SRIOV_ATTR_RATE_MIN;
1094 	}
1095 
1096 	return;
1097 }
1098 
1099 /**
1100  * Get RSS Query EN value of SRIOV Virtual Function
1101  * @arg vf_data 	SRIOV VF object
1102  * @arg vf_rss_query_en	Pointer to store VF RSS Query value
1103  *
1104  * @see rtnl_link_get_num_vf()
1105  * @see rtnl_link_vf_set_rss_query_en()
1106  *
1107  * @return 0 if rss_query_en is present and vf_rss_query_en is set
1108  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
1109  * @return -NLE_NOATTR if the VF RSS Query EN value is not set
1110  */
rtnl_link_vf_get_rss_query_en(struct rtnl_link_vf * vf_data,uint32_t * vf_rss_query_en)1111 int rtnl_link_vf_get_rss_query_en(struct rtnl_link_vf *vf_data,
1112 				  uint32_t *vf_rss_query_en)
1113 {
1114 	if (!vf_data)
1115 		return -NLE_OBJ_NOTFOUND;
1116 
1117 	if (vf_data->ce_mask & SRIOV_ATTR_RSS_QUERY_EN)
1118 		*vf_rss_query_en = vf_data->vf_rss_query_en;
1119 	else
1120 		return -NLE_NOATTR;
1121 
1122 	return 0;
1123 }
1124 
1125 /**
1126  * Set RSS configuration querying of SRIOV Virtual Function Object
1127  * @arg vf_data 	SRIOV VF object
1128  * @arg vf_rss_query_en	RSS Query value
1129  *
1130  * @see rtnl_link_vf_get_rss_query_en()
1131  */
rtnl_link_vf_set_rss_query_en(struct rtnl_link_vf * vf_data,uint32_t vf_rss_query_en)1132 void rtnl_link_vf_set_rss_query_en(struct rtnl_link_vf *vf_data,
1133 				  uint32_t vf_rss_query_en) {
1134 	vf_data->vf_rss_query_en = vf_rss_query_en;
1135 	vf_data->ce_mask |= SRIOV_ATTR_RSS_QUERY_EN;
1136 
1137 	return;
1138 }
1139 
1140 /**
1141  * Get spoof checking value of SRIOV Virtual Function
1142  * @arg vf_data 	SRIOV VF object
1143  * @arg vf_spoofchk 	Pointer to store VF spoofchk value
1144  *
1145  * @see rtnl_link_get_num_vf()
1146  * @see rtnl_link_set_spoofchk()
1147  *
1148  * @return 0 if spoofchk is present and vf_spoofchk is set
1149  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
1150  * @return -NLE_NOATTR if the VF spoofcheck is not set
1151  */
rtnl_link_vf_get_spoofchk(struct rtnl_link_vf * vf_data,uint32_t * vf_spoofchk)1152 int rtnl_link_vf_get_spoofchk(struct rtnl_link_vf *vf_data,
1153 			      uint32_t *vf_spoofchk)
1154 {
1155 	if (!vf_data)
1156 		return -NLE_OBJ_NOTFOUND;
1157 
1158 	if (vf_data->ce_mask & SRIOV_ATTR_SPOOFCHK)
1159 		*vf_spoofchk = vf_data->vf_spoofchk;
1160 	else
1161 		return -NLE_NOATTR;
1162 
1163 	return 0;
1164 }
1165 
1166 /**
1167  * Set spoof checking value of SRIOV Virtual Function Object
1168  * @param vf_data
1169  * @param vf_spoofchk
1170  *
1171  * @see rtnl_link_vf_get_spoofchk()
1172  */
rtnl_link_vf_set_spoofchk(struct rtnl_link_vf * vf_data,uint32_t vf_spoofchk)1173 void rtnl_link_vf_set_spoofchk(struct rtnl_link_vf *vf_data,
1174 			       uint32_t vf_spoofchk) {
1175 	vf_data->vf_spoofchk = vf_spoofchk;
1176 	vf_data->ce_mask |= SRIOV_ATTR_SPOOFCHK;
1177 
1178 	return;
1179 }
1180 
1181 /**
1182  * Get value of stat counter for SRIOV Virtual Function
1183  * @arg vf_data 	SRIOV VF object
1184  * @arg stat 		Identifier of statistical counter
1185  * @arg vf_stat 	Pointer to store VF stat value in
1186  *
1187  * @see rtnl_link_get_num_vf()
1188  *
1189  * @return 0 if stat is present and vf_stat is set
1190  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
1191  * @return -NLE_NOATTR if the VF stat is not set
1192  */
rtnl_link_vf_get_stat(struct rtnl_link_vf * vf_data,rtnl_link_vf_stats_t stat,uint64_t * vf_stat)1193 int rtnl_link_vf_get_stat(struct rtnl_link_vf *vf_data,
1194 			  rtnl_link_vf_stats_t stat, uint64_t *vf_stat)
1195 {
1196 	if (!vf_data)
1197 		return -NLE_OBJ_NOTFOUND;
1198 
1199 	if (vf_data->ce_mask & SRIOV_ATTR_STATS)
1200 		*vf_stat = vf_data->vf_stats[stat];
1201 	else
1202 		return -NLE_NOATTR;
1203 
1204 	return 0;
1205 }
1206 
1207 /**
1208  * Get trust setting of SRIOV Virtual Function
1209  * @arg vf_data 	SRIOV VF object
1210  * @arg vf_trust 	Pointer to store VF trust value
1211  *
1212  * @see rtnl_link_get_num_vf()
1213  * @see rtnl_link_set_trust()
1214  *
1215  * @return 0 if trust is present and vf_trust is set
1216  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
1217  * @return -NLE_NOATTR if the VF trust setting is not set
1218  */
rtnl_link_vf_get_trust(struct rtnl_link_vf * vf_data,uint32_t * vf_trust)1219 int rtnl_link_vf_get_trust(struct rtnl_link_vf *vf_data, uint32_t *vf_trust)
1220 {
1221 	if (!vf_data)
1222 		return -NLE_OBJ_NOTFOUND;
1223 
1224 	if (vf_data->ce_mask & SRIOV_ATTR_TRUST)
1225 		*vf_trust = vf_data->vf_trust;
1226 	else
1227 		return -NLE_NOATTR;
1228 
1229 	return 0;
1230 }
1231 
1232 /**
1233  * Set user trust setting on SRIOV Virtual Function Object
1234  * @param vf_data
1235  * @param vf_trust
1236  *
1237  * @see rtnl_link_vf_get_trust()
1238  */
rtnl_link_vf_set_trust(struct rtnl_link_vf * vf_data,uint32_t vf_trust)1239 void rtnl_link_vf_set_trust(struct rtnl_link_vf *vf_data, uint32_t vf_trust) {
1240 	vf_data->vf_trust = vf_trust;
1241 	vf_data->ce_mask |= SRIOV_ATTR_TRUST;
1242 
1243 	return;
1244 }
1245 
1246 /**
1247  * Get an array of VLANS on SRIOV Virtual Function
1248  * @arg vf_data 	SRIOV VF object
1249  * @arg vf_vlans 	Pointer to nl_vf_vlans_t struct to store vlan info.
1250  *
1251  * @see rtnl_link_get_num_vf()
1252  *
1253  * The SRIOV VF VLANs object must be returned to the SRIOV VF object with
1254  * rtnl_link_vf_vlans_put() when operations are done to prevent memory leaks.
1255  *
1256  * @copydoc pointer_lifetime_warning
1257  * @return 0 if VLAN info is present and vf_vlans is set
1258  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
1259  * @return -NLE_NOATTR if the VF vlans is not set
1260  */
rtnl_link_vf_get_vlans(struct rtnl_link_vf * vf_data,nl_vf_vlans_t ** vf_vlans)1261 int rtnl_link_vf_get_vlans(struct rtnl_link_vf *vf_data,
1262 			   nl_vf_vlans_t **vf_vlans) {
1263 	nl_vf_vlans_t *vf;
1264 
1265 	if (!vf_data)
1266 		return -NLE_OBJ_NOTFOUND;
1267 
1268 	if (vf_data->ce_mask & SRIOV_ATTR_VLAN) {
1269 		vf = vf_data->vf_vlans;
1270 		vf->ce_refcnt++;
1271 		*vf_vlans = vf;
1272 	} else
1273 		return -NLE_NOATTR;
1274 
1275 	return 0;
1276 }
1277 
1278 /**
1279  * Add a SRIOV VF VLANs object to the SRIOV Virtual Function Object
1280  * @param vf_data 	SRIOV VF object
1281  * @param vf_vlans 	SRIOV VF VLANs object
1282  *
1283  * @see rtnl_link_vf_get_vlans()
1284  * @see rtnl_link_vf_vlan_alloc()
1285  *
1286  * This function assigns ownership of the SRIOV VF object \p vf_vlans
1287  * to the SRIOV Virtual Function object \p vf_data. Do not use
1288  * rtnl_link_vf_vlan_put() on \p vf_vlans after this.
1289  */
rtnl_link_vf_set_vlans(struct rtnl_link_vf * vf_data,nl_vf_vlans_t * vf_vlans)1290 void rtnl_link_vf_set_vlans(struct rtnl_link_vf *vf_data,
1291 			    nl_vf_vlans_t *vf_vlans) {
1292 	if (!vf_data||!vf_vlans)
1293 		return;
1294 
1295 	vf_data->vf_vlans = vf_vlans;
1296 	vf_data->vf_vlans->ce_refcnt++;
1297 	vf_data->ce_mask |= SRIOV_ATTR_VLAN;
1298 
1299 	return;
1300 }
1301 
1302 /**
1303  * Allocate a SRIOV VF VLAN object
1304  * @param vf_vlans 	Pointer to store VLAN object at
1305  * @param vlan_count 	Number of VLANs that will be stored in VLAN object
1306  *
1307  * The SRIOV VF VLANs object must be returned to the sRIOV VF object with
1308  * rtnl_link_vf_vlan_put() when operations are done to prevent memory leaks.
1309  *
1310  * @return 0 if VLAN object is created and vf_vlans is set.
1311  * @return -NLE_NOMEM if object could not be allocated.
1312  * @return -NLE_INVAL if vlan_count is more than supported by SRIOV VF
1313  */
rtnl_link_vf_vlan_alloc(nl_vf_vlans_t ** vf_vlans,int vlan_count)1314 int rtnl_link_vf_vlan_alloc(nl_vf_vlans_t **vf_vlans, int vlan_count) {
1315 	nl_vf_vlans_t *vlans;
1316 	nl_vf_vlan_info_t *vlan_info;
1317 
1318 	if (vlan_count > MAX_VLAN_LIST_LEN)
1319 		return -NLE_INVAL;
1320 
1321 	vlans = calloc(1, sizeof(*vlans));
1322 	if (!vlans)
1323 		return -NLE_NOMEM;
1324 
1325 	vlan_info = calloc(vlan_count+1, sizeof(*vlan_info));
1326 	if (!vlan_info) {
1327 		free(vlans);
1328 		return -NLE_NOMEM;
1329 	}
1330 
1331 	NL_DBG(4, "Allocated new SRIOV VF VLANs object %p\n", vlans);
1332 
1333 	vlans->ce_refcnt = 1;
1334 	vlans->size = vlan_count;
1335 	vlans->vlans = vlan_info;
1336 	*vf_vlans = vlans;
1337 
1338 	return 0;
1339 }
1340 
1341 /**
1342  * Free an allocated SRIOV VF VLANs object
1343  * @param vf_vlans 	SRIOV VF VLANs object
1344  */
rtnl_link_vf_vlan_free(nl_vf_vlans_t * vf_vlans)1345 void rtnl_link_vf_vlan_free(nl_vf_vlans_t *vf_vlans) {
1346 	if (!vf_vlans)
1347 		return;
1348 
1349 	if (vf_vlans->ce_refcnt > 0)
1350 		NL_DBG(1, "Warning: Freeing SRIOV VF VLANs object in use...\n");
1351 
1352 	NL_DBG(4, "Freed SRIOV VF object %p\n", vf_vlans);
1353 	free(vf_vlans->vlans);
1354 	free(vf_vlans);
1355 
1356 	return;
1357 }
1358 
1359 /**
1360  * Return SRIOV VF VLANs object to the owning SRIOV VF object.
1361  * @param vf_vlans 	SRIOV VF VLANs object
1362  */
rtnl_link_vf_vlan_put(nl_vf_vlans_t * vf_vlans)1363 void rtnl_link_vf_vlan_put(nl_vf_vlans_t *vf_vlans) {
1364 	if (!vf_vlans)
1365 		return;
1366 
1367 	vf_vlans->ce_refcnt--;
1368 	NL_DBG(4, "Returned SRIOV VF VLANs object reference %p, %i remaining\n",
1369 	       vf_vlans, vf_vlans->ce_refcnt);
1370 
1371 	if (vf_vlans->ce_refcnt < 0)
1372 		BUG();
1373 
1374 	if (vf_vlans->ce_refcnt <= 0)
1375 		rtnl_link_vf_vlan_free(vf_vlans);
1376 
1377 	return;
1378 }
1379 
1380 /** @} */
1381 
1382 /**
1383  * @name Utilities
1384  * @{
1385  */
1386 
1387 static const struct trans_tbl vf_link_states[] = {
1388 	__ADD(IFLA_VF_LINK_STATE_AUTO, autodetect),
1389 	__ADD(IFLA_VF_LINK_STATE_ENABLE, up),
1390 	__ADD(IFLA_VF_LINK_STATE_DISABLE, down),
1391 };
1392 
rtnl_link_vf_linkstate2str(uint32_t ls,char * buf,size_t len)1393 char *rtnl_link_vf_linkstate2str(uint32_t ls, char *buf, size_t len)
1394 {
1395 	return __type2str(ls, buf, len, vf_link_states,
1396 			  ARRAY_SIZE(vf_link_states));
1397 }
1398 
rtnl_link_vf_str2linkstate(const char * name)1399 int rtnl_link_vf_str2linkstate(const char *name)
1400 {
1401 	return __str2type(name, vf_link_states, ARRAY_SIZE(vf_link_states));
1402 }
1403 
1404 static const struct trans_tbl vf_vlan_proto[] = {
1405 	__ADD(ETH_P_8021Q, 8021Q),
1406 	__ADD(ETH_P_8021AD, 8021AD),
1407 };
1408 
rtnl_link_vf_vlanproto2str(uint16_t proto,char * buf,size_t len)1409 char *rtnl_link_vf_vlanproto2str(uint16_t proto, char *buf, size_t len)
1410 {
1411 	return __type2str(proto, buf, len, vf_vlan_proto,
1412 			  ARRAY_SIZE(vf_vlan_proto));
1413 }
1414 
rtnl_link_vf_str2vlanproto(const char * name)1415 int rtnl_link_vf_str2vlanproto(const char *name)
1416 {
1417 	return __str2type(name, vf_vlan_proto, ARRAY_SIZE(vf_vlan_proto));
1418 }
1419 
1420 /* Return a guid from a format checked string.
1421  * Format string must be xx:xx:xx:xx:xx:xx:xx:xx where XX can be an
1422  * arbitrary hex digit
1423  *
1424  * Function modified from original at iproute2/lib/utils.c:get_guid()
1425  * Original by Eli Cohen <eli@mellanox.com>.
1426  * iproute2 git commit d91fb3f4c7e4dba806541bdc90b1fb60a3581541
1427  */
rtnl_link_vf_str2guid(uint64_t * guid,const char * guid_s)1428 int rtnl_link_vf_str2guid(uint64_t *guid, const char *guid_s) {
1429 	unsigned long int tmp;
1430 	char *endptr;
1431 	int i;
1432 
1433 	if (strlen(guid_s) != RTNL_VF_GUID_STR_LEN)
1434 		return -1;
1435 
1436 	for (i = 0; i < 7; i++) {
1437 		if (guid_s[2 + i * 3] != ':')
1438 			return -1;
1439 	}
1440 
1441 	*guid = 0;
1442 	for (i = 0; i < 8; i++) {
1443 		tmp = strtoul(guid_s + i * 3, &endptr, 16);
1444 		if (endptr != guid_s + i * 3 + 2)
1445 			return -1;
1446 
1447 		if (tmp > 255)
1448 			return -1;
1449 
1450 		*guid |= tmp << (56 - 8 * i);
1451 	}
1452 
1453 	return 0;
1454 }
1455 
1456 /** @} */
1457 
1458 /** @} */
1459