libnl  3.7.0
sriov.c
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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,
661  IFLA_VF_STATS_RX_PACKETS);
662  SET_VF_STAT(link, cur, stb,
664  IFLA_VF_STATS_TX_PACKETS);
665  SET_VF_STAT(link, cur, stb,
667  IFLA_VF_STATS_RX_BYTES);
668  SET_VF_STAT(link, cur, stb,
670  IFLA_VF_STATS_TX_BYTES);
671  SET_VF_STAT(link, cur, stb,
673  IFLA_VF_STATS_BROADCAST);
674  SET_VF_STAT(link, cur, stb,
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
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 
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 
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 
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  */
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 /** @} */
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition: addr.c:935
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:993
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:211
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:487
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition: addr.c:517
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition: addr.c:947
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:533
void nl_addr_set_family(struct nl_addr *addr, int family)
Set address family.
Definition: addr.c:874
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:236
int nla_ok(const struct nlattr *nla, int remaining)
Check if the attribute header and payload can be accessed safely.
Definition: attr.c:142
struct nlattr * nla_next(const struct nlattr *nla, int *remaining)
Return next attribute in a stream of attributes.
Definition: attr.c:165
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:159
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:895
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:1013
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
Definition: attr.h:324
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition: attr.c:125
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:958
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:114
@ NLA_U64
64 bit integer
Definition: attr.h:38
@ NLA_NESTED
Nested attributes.
Definition: attr.h:42
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:1111
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:921
rtnl_link_vf_stats_t
Definition: sriov.h:34
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:873
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:1290
int rtnl_link_vf_vlan_alloc(nl_vf_vlans_t **vf_vlans, int vlan_count)
Allocate a SRIOV VF VLAN object.
Definition: sriov.c:1314
void rtnl_link_vf_put(struct rtnl_link_vf *vf_data)
Return SRIOV VF object to the owning link object.
Definition: sriov.c:820
struct rtnl_link_vf * rtnl_link_vf_alloc(void)
Allocate a new SRIOV VF object.
Definition: sriov.c:746
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:793
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:889
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:1239
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:850
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:902
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:1083
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:985
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:1132
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:1261
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:1193
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:1363
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:1173
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:1219
void rtnl_link_vf_free(struct rtnl_link_vf *vf_data)
Free SRIOV VF object.
Definition: sriov.c:764
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:1152
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:941
void rtnl_link_vf_vlan_free(nl_vf_vlans_t *vf_vlans)
Free an allocated SRIOV VF VLANs object.
Definition: sriov.c:1345
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:961
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:1017
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:711
@ RTNL_LINK_VF_STATS_TX_BYTES
Definition: sriov.h:38
@ RTNL_LINK_VF_STATS_BROADCAST
Definition: sriov.h:39
@ RTNL_LINK_VF_STATS_RX_PACKETS
Definition: sriov.h:35
@ RTNL_LINK_VF_STATS_MULTICAST
Definition: sriov.h:40
@ RTNL_LINK_VF_STATS_RX_BYTES
Definition: sriov.h:37
@ RTNL_LINK_VF_STATS_TX_PACKETS
Definition: sriov.h:36
@ RTNL_LINK_VF_RATE_API_UNSPEC
Definition: sriov.h:23
@ RTNL_LINK_VF_RATE_API_NEW
Definition: sriov.h:25
@ RTNL_LINK_VF_RATE_API_OLD
Definition: sriov.h:24
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
Definition: utils.c:163
Dumping parameters.
Definition: types.h:28
VF Rate information structure.
Definition: sriov.h:79
int api
Definition: sriov.h:80
uint32_t min_tx_rate
Definition: sriov.h:83
uint32_t max_tx_rate
Definition: sriov.h:82
uint32_t rate
Definition: sriov.h:81
SRIOV VF VFLAN settings.
Definition: sriov.h:59
uint16_t vf_vlan_proto
Definition: sriov.h:62
uint32_t vf_vlan_qos
Definition: sriov.h:61
uint32_t vf_vlan
Definition: sriov.h:60
SRIOV VF VLANs information.
Definition: sriov.h:69
int ce_refcnt
Definition: sriov.h:70
nl_vf_vlan_info_t * vlans
Definition: sriov.h:72
int size
Definition: sriov.h:71
Attribute validation policy.
Definition: attr.h:63
uint16_t minlen
Minimal length of payload required.
Definition: attr.h:68
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65