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