[PATCH v2 5/5] lib/route: SRIOV Set Functionality

Jef Oliver jef.oliver at intel.com
Mon Nov 7 13:33:58 PST 2016


* This patch adds functionality to set attributes on an SRIOV
  VF object.
* This patch adds functionality to append attributes to the
  link change request sent to the kernel.

Signed-off-by: Jef Oliver <jef.oliver at intel.com>
---
 include/netlink-private/route/link/sriov.h |   1 +
 include/netlink/route/link/sriov.h         |  25 ++
 lib/route/link.c                           |   5 +
 lib/route/link/sriov.c                     | 472 ++++++++++++++++++++++++++++-
 libnl-route-3.sym                          |  13 +
 5 files changed, 515 insertions(+), 1 deletion(-)

diff --git a/include/netlink-private/route/link/sriov.h b/include/netlink-private/route/link/sriov.h
index dccee1e..ac653ed 100644
--- a/include/netlink-private/route/link/sriov.h
+++ b/include/netlink-private/route/link/sriov.h
@@ -23,6 +23,7 @@ extern "C" {
 extern int rtnl_link_sriov_clone(struct rtnl_link *, struct rtnl_link *);
 extern void rtnl_link_sriov_dump_details(struct rtnl_link *, struct nl_dump_params *);
 extern void rtnl_link_sriov_dump_stats(struct rtnl_link *, struct nl_dump_params *);
+extern int rtnl_link_sriov_fill_vflist(struct nl_msg *, struct rtnl_link *);
 extern void rtnl_link_sriov_free_data(struct rtnl_link *);
 extern int rtnl_link_sriov_parse_vflist(struct rtnl_link *, struct nlattr **);
 
diff --git a/include/netlink/route/link/sriov.h b/include/netlink/route/link/sriov.h
index 8289b80..c6963a8 100644
--- a/include/netlink/route/link/sriov.h
+++ b/include/netlink/route/link/sriov.h
@@ -20,6 +20,8 @@
 extern "C" {
 #endif
 
+#define RTNL_VF_GUID_STR_LEN 23
+
 /**
  * @ingroup sriov
  */
@@ -87,20 +89,41 @@ struct nl_vf_rate {
 	uint32_t	min_tx_rate;	/*!< New API Mix Rate in Mbps */
 };
 
+extern int rtnl_link_vf_add(struct rtnl_link *, struct rtnl_link_vf *);
 extern struct rtnl_link_vf *rtnl_link_vf_alloc(void);
 extern void rtnl_link_vf_free(struct rtnl_link_vf *);
 extern struct rtnl_link_vf *rtnl_link_vf_get(struct rtnl_link *, uint32_t);
 extern void rtnl_link_vf_put(struct rtnl_link_vf *);
+
 extern int rtnl_link_vf_get_addr(struct rtnl_link_vf *, struct nl_addr **);
+extern void rtnl_link_vf_set_addr(struct rtnl_link_vf *, struct nl_addr *);
+
+extern void rtnl_link_vf_set_ib_node_guid(struct rtnl_link_vf *, uint64_t);
+extern void rtnl_link_vf_set_ib_port_guid(struct rtnl_link_vf *, uint64_t);
+
 extern int rtnl_link_vf_get_index(struct rtnl_link_vf *, uint32_t *);
+extern void rtnl_link_vf_set_index(struct rtnl_link_vf *, uint32_t);
+
 extern int rtnl_link_vf_get_linkstate(struct rtnl_link_vf *, uint32_t *);
+extern void rtnl_link_vf_set_linkstate(struct rtnl_link_vf *, uint32_t);
+
 extern int rtnl_link_vf_get_rate(struct rtnl_link_vf *, struct nl_vf_rate *);
+extern void rtnl_link_vf_set_rate(struct rtnl_link_vf *, struct nl_vf_rate *);
+
 extern int rtnl_link_vf_get_rss_query_en(struct rtnl_link_vf *, uint32_t *);
+extern void rtnl_link_vf_set_rss_query_en(struct rtnl_link_vf *, uint32_t);
+
 extern int rtnl_link_vf_get_spoofchk(struct rtnl_link_vf *, uint32_t *);
+extern void rtnl_link_vf_set_spoofchk(struct rtnl_link_vf *, uint32_t);
+
 extern int rtnl_link_vf_get_stat(struct rtnl_link_vf *, rtnl_link_vf_stats_t,
 				 uint64_t *);
+
 extern int rtnl_link_vf_get_trust(struct rtnl_link_vf *, uint32_t *);
+extern void rtnl_link_vf_set_trust(struct rtnl_link_vf *, uint32_t);
+
 extern int rtnl_link_vf_get_vlans(struct rtnl_link_vf *, nl_vf_vlans_t **);
+extern void rtnl_link_vf_set_vlans(struct rtnl_link_vf *, nl_vf_vlans_t *);
 
 extern int rtnl_link_vf_vlan_alloc(nl_vf_vlans_t **, int);
 extern void rtnl_link_vf_vlan_put(nl_vf_vlans_t *);
@@ -112,6 +135,8 @@ extern int rtnl_link_vf_str2linkstate(const char *);
 extern char *rtnl_link_vf_vlanproto2str(uint16_t, char *, size_t);
 extern int rtnl_link_vf_str2vlanproto(const char *);
 
+extern int rtnl_link_vf_str2guid(uint64_t *, const char *);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/route/link.c b/lib/route/link.c
index 8bb9f25..57ab996 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -1529,6 +1529,11 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr,
 		nla_nest_end(msg, info);
 	}
 
+	if (link->ce_mask & LINK_ATTR_VF_LIST) {
+		if (rtnl_link_sriov_fill_vflist(msg, link) < 0)
+			goto nla_put_failure;
+	}
+
 	if (do_foreach_af(link, af_fill_pi, msg) < 0)
 		goto nla_put_failure;
 
diff --git a/lib/route/link/sriov.c b/lib/route/link/sriov.c
index d91f1da..acabf67 100644
--- a/lib/route/link/sriov.c
+++ b/lib/route/link/sriov.c
@@ -55,6 +55,8 @@
 #define SRIOV_ATTR_RSS_QUERY_EN 	(1 <<  8)
 #define SRIOV_ATTR_STATS 		(1 <<  9)
 #define SRIOV_ATTR_TRUST 		(1 << 10)
+#define SRIOV_ATTR_IB_NODE_GUID 	(1 << 11)
+#define SRIOV_ATTR_IB_PORT_GUID 	(1 << 12)
 
 static struct nla_policy sriov_info_policy[IFLA_VF_MAX+1] = {
 	[IFLA_VF_MAC]		= { .minlen = sizeof(struct ifla_vf_mac) },
@@ -316,6 +318,204 @@ static int rtnl_link_vf_vlan_info(int len, struct ifla_vf_vlan_info **vi,
 	return 0;
 }
 
+/* Fill the IFLA_VF_VLAN attribute */
+static void sriov_fill_vf_vlan(struct nl_msg *msg, nl_vf_vlan_info_t *vinfo,
+			       uint32_t index) {
+	struct ifla_vf_vlan vlan;
+
+	vlan.vf = index;
+	vlan.vlan = vinfo[0].vf_vlan;
+	vlan.qos = vinfo[0].vf_vlan_qos;
+	NLA_PUT(msg, IFLA_VF_VLAN, sizeof(vlan), &vlan);
+
+nla_put_failure:
+	return;
+}
+
+/* Fill the IFLA_VF_VLAN_LIST attribute */
+static int sriov_fill_vf_vlan_list(struct nl_msg *msg, nl_vf_vlans_t *vlans,
+				   uint32_t index) {
+	int cur = 0;
+	nl_vf_vlan_info_t *vlan_info = vlans->vlans;
+	struct ifla_vf_vlan_info vlan;
+	struct nlattr *list;
+
+	if (!(list = nla_nest_start(msg, IFLA_VF_VLAN_LIST)))
+		return -NLE_MSGSIZE;
+
+	vlan.vf = index;
+	while (cur < vlans->size) {
+		vlan.vlan = vlan_info[cur].vf_vlan;
+		vlan.qos = vlan_info[cur].vf_vlan_qos;
+		vlan.vlan_proto = vlan_info[cur].vf_vlan_proto;
+
+		NLA_PUT(msg, IFLA_VF_VLAN_INFO, sizeof(vlan), &vlan);
+
+		cur++;
+	}
+
+nla_put_failure:
+	nla_nest_end(msg, list);
+
+	return 0;
+}
+
+/* Fill individual IFLA_VF_INFO attributes */
+static int sriov_fill_vfinfo(struct nl_msg *msg,
+			     struct rtnl_link_vf *vf_data) {
+	int err = 0, new_rate = 0;
+	nl_vf_vlans_t *vlan_list;
+	nl_vf_vlan_info_t *vlan_info;
+	struct ifla_vf_guid vf_node_guid;
+	struct ifla_vf_guid vf_port_guid;
+	struct ifla_vf_link_state vf_link_state;
+	struct ifla_vf_mac vf_mac;
+	struct ifla_vf_rate new_vf_rate;
+	struct ifla_vf_rss_query_en vf_rss_query_en;
+	struct ifla_vf_spoofchk vf_spoofchk;
+	struct ifla_vf_trust vf_trust;
+	struct ifla_vf_tx_rate vf_rate;
+	struct nlattr *list;
+	uint16_t proto;
+
+	if (!(vf_data->ce_mask & SRIOV_ATTR_INDEX))
+		return -NLE_MISSING_ATTR;
+
+	if (!(list = nla_nest_start(msg, IFLA_VF_INFO)))
+		return -NLE_MSGSIZE;
+
+	/* IFLA_VF_MAC */
+	if (vf_data->ce_mask & SRIOV_ATTR_ADDR) {
+		vf_mac.vf = vf_data->vf_index;
+		memset(vf_mac.mac, 0, sizeof(vf_mac.mac));
+		memcpy(vf_mac.mac, nl_addr_get_binary_addr(vf_data->vf_lladdr),
+		       nl_addr_get_len(vf_data->vf_lladdr));
+		NLA_PUT(msg, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac);
+	}
+
+	/* IFLA_VF_VLAN IFLA_VF_VLAN_LIST */
+	if (vf_data->ce_mask & SRIOV_ATTR_VLAN) {
+		vlan_list = vf_data->vf_vlans;
+		vlan_info = vlan_list->vlans;
+		proto = vlan_info[0].vf_vlan_proto;
+		if (!proto)
+			proto = ETH_P_8021Q;
+
+		if ((vlan_list->size == 1) && (proto == ETH_P_8021Q))
+			sriov_fill_vf_vlan(msg, vlan_info, vf_data->vf_index);
+		else
+			err = sriov_fill_vf_vlan_list(msg, vlan_list,
+						      vf_data->vf_index);
+	}
+
+	/* IFLA_VF_TX_RATE */
+	if (vf_data->ce_mask & SRIOV_ATTR_TX_RATE) {
+		vf_rate.vf = vf_data->vf_index;
+		vf_rate.rate = vf_data->vf_rate;
+
+		NLA_PUT(msg, IFLA_VF_TX_RATE, sizeof(vf_rate), &vf_rate);
+	}
+
+	/* IFLA_VF_RATE */
+	new_vf_rate.min_tx_rate = 0;
+	new_vf_rate.max_tx_rate = 0;
+	new_vf_rate.vf = vf_data->vf_index;
+	if (vf_data->ce_mask & SRIOV_ATTR_RATE_MIN) {
+		new_vf_rate.min_tx_rate = vf_data->vf_min_tx_rate;
+		new_rate = 1;
+	}
+	if (vf_data->ce_mask & SRIOV_ATTR_RATE_MAX) {
+		new_vf_rate.max_tx_rate = vf_data->vf_max_tx_rate;
+		new_rate = 1;
+	}
+	if (new_rate)
+		NLA_PUT(msg, IFLA_VF_RATE, sizeof(new_vf_rate), &new_vf_rate);
+
+	/* IFLA_VF_SPOOFCHK */
+	if (vf_data->ce_mask & SRIOV_ATTR_SPOOFCHK) {
+		vf_spoofchk.vf = vf_data->vf_index;
+		vf_spoofchk.setting = vf_data->vf_spoofchk;
+
+		NLA_PUT(msg, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
+			&vf_spoofchk);
+	}
+
+	/* IFLA_VF_LINK_STATE */
+	if (vf_data->ce_mask & SRIOV_ATTR_LINK_STATE) {
+		vf_link_state.vf = vf_data->vf_index;
+		vf_link_state.link_state = vf_data->vf_linkstate;
+
+		NLA_PUT(msg, IFLA_VF_LINK_STATE, sizeof(vf_link_state),
+			&vf_link_state);
+	}
+
+	/* IFLA_VF_RSS_QUERY_EN */
+	if (vf_data->ce_mask & SRIOV_ATTR_RSS_QUERY_EN) {
+		vf_rss_query_en.vf = vf_data->vf_index;
+		vf_rss_query_en.setting = vf_data->vf_rss_query_en;
+
+		NLA_PUT(msg, IFLA_VF_RSS_QUERY_EN, sizeof(vf_rss_query_en),
+			&vf_rss_query_en);
+	}
+
+	/* IFLA_VF_TRUST */
+	if (vf_data->ce_mask & SRIOV_ATTR_TRUST) {
+		vf_trust.vf = vf_data->vf_index;
+		vf_trust.setting = vf_data->vf_trust;
+
+		NLA_PUT(msg, IFLA_VF_TRUST, sizeof(vf_trust), &vf_trust);
+	}
+
+	/* IFLA_VF_IB_NODE_GUID */
+	if (vf_data->ce_mask & SRIOV_ATTR_IB_NODE_GUID) {
+		vf_node_guid.vf = vf_data->vf_index;
+		vf_node_guid.guid = vf_data->vf_guid_node;
+
+		NLA_PUT(msg, IFLA_VF_IB_NODE_GUID, sizeof(vf_node_guid),
+			&vf_node_guid);
+	}
+
+	/* IFLA_VF_IB_PORT_GUID */
+	if (vf_data->ce_mask & SRIOV_ATTR_IB_PORT_GUID) {
+		vf_port_guid.vf = vf_data->vf_index;
+		vf_port_guid.guid = vf_data->vf_guid_port;
+
+		NLA_PUT(msg, IFLA_VF_IB_PORT_GUID, sizeof(vf_port_guid),
+			&vf_port_guid);
+	}
+
+nla_put_failure:
+	nla_nest_end(msg, list);
+
+	return err;
+}
+
+/* Fill the IFLA_VFINFO_LIST attribute */
+int rtnl_link_sriov_fill_vflist(struct nl_msg *msg, struct rtnl_link *link) {
+	int err = 0;
+	struct nlattr *data;
+	struct rtnl_link_vf *list, *vf, *next;
+
+	if (!(err = rtnl_link_has_vf_list(link)))
+		return 0;
+
+	if (!(data = nla_nest_start(msg, IFLA_VFINFO_LIST)))
+		return -NLE_MSGSIZE;
+
+	list = link->l_vf_list;
+	nl_list_for_each_entry_safe(vf, next, &list->vf_list, vf_list) {
+		if (vf->ce_mask & SRIOV_ATTR_INDEX) {
+			if ((err = sriov_fill_vfinfo(msg, vf)) < 0)
+				goto nla_nest_list_failure;
+		}
+	}
+
+nla_nest_list_failure:
+	nla_nest_end(msg, data);
+
+	return err;
+}
+
 /* Parse IFLA_VFINFO_LIST and IFLA_VF_INFO attributes */
 int rtnl_link_sriov_parse_vflist(struct rtnl_link *link, struct nlattr **tb) {
 	int err, len, list_len, list_rem;
@@ -494,6 +694,39 @@ int rtnl_link_sriov_parse_vflist(struct rtnl_link *link, struct nlattr **tb) {
  */
 
 /**
+ * Add a SRIOV VF object to a link object
+ * @param link  	Link object to add to
+ * @param vf_data 	SRIOV VF object to add
+ *
+ * @return 0 if SRIOV VF object added successfully
+ * @return -NLE_OBJ_NOTFOUND if \p link or \p vf_data not provided
+ * @return -NLE_NOMEM if out of memory
+ */
+int rtnl_link_vf_add(struct rtnl_link *link, struct rtnl_link_vf *vf_data) {
+	struct rtnl_link_vf *vf_head = NULL;
+
+	if (!link||!vf_data)
+		return -NLE_OBJ_NOTFOUND;
+
+	if (!link->l_vf_list) {
+		link->l_vf_list = rtnl_link_vf_alloc();
+		if (!link->l_vf_list)
+			return -NLE_NOMEM;
+	}
+
+	vf_head = vf_data;
+	vf_head->ce_refcnt++;
+
+	vf_head = link->l_vf_list;
+	nl_list_add_head(&vf_data->vf_list, &vf_head->vf_list);
+	link->l_vf_list = vf_head;
+
+	rtnl_link_set_vf_list(link);
+
+	return 0;
+}
+
+/**
  * Allocate a new SRIOV VF object
  *
  * @return NULL if out of memory
@@ -601,6 +834,7 @@ void rtnl_link_vf_put(struct rtnl_link_vf *vf_data) {
  * @arg addr 		Pointer to store Link Layer address
  *
  * @see rtnl_link_get_num_vf()
+ * @see rtnl_link_vf_set_addr()
  *
  * @copydoc pointer_lifetime_warning
  * @return 0 if addr is present and addr is set to pointer containing address
@@ -621,6 +855,53 @@ int rtnl_link_vf_get_addr(struct rtnl_link_vf *vf_data, struct nl_addr **addr)
 }
 
 /**
+ * Set link layer address of SRIOV Virtual Function object
+ * @param vf_data 	SRIOV VF object
+ * @param addr 		New link layer address
+ *
+ * This function increments the reference counter of the address object
+ * and overwrites any existing link layer address previously assigned.
+ *
+ * @see rtnl_link_vf_get_addr()
+ */
+void rtnl_link_vf_set_addr(struct rtnl_link_vf *vf_data, struct nl_addr *addr) {
+	if (vf_data->vf_lladdr)
+		nl_addr_put(vf_data->vf_lladdr);
+
+	nl_addr_get(addr);
+	vf_data->vf_lladdr = addr;
+	vf_data->ce_mask |= SRIOV_ATTR_ADDR;
+
+	return;
+}
+
+/**
+ * Set the Infiniband node GUID for the SRIOV Virtual Function object
+ * @param vf_data 	SRIOV VF object
+ * @param guid  	node GUID
+ */
+void rtnl_link_vf_set_ib_node_guid(struct rtnl_link_vf *vf_data,
+				   uint64_t guid) {
+	vf_data->vf_guid_node = guid;
+	vf_data->ce_mask |= SRIOV_ATTR_IB_NODE_GUID;
+
+	return;
+}
+
+/**
+ * Set the Infiniband port GUID for the SRIOV Virtual Function object
+ * @param vf_data 	SRIOV VF object
+ * @param guid  	port GUID
+ */
+void rtnl_link_vf_set_ib_port_guid(struct rtnl_link_vf *vf_data,
+				   uint64_t guid) {
+	vf_data->vf_guid_port = guid;
+	vf_data->ce_mask |= SRIOV_ATTR_IB_PORT_GUID;
+
+	return;
+}
+
+/**
  * Get index of SRIOV Virtual Function
  * @arg vf_data 	SRIOV VF object
  * @arg vf_index 	Pointer to store VF index
@@ -645,11 +926,27 @@ int rtnl_link_vf_get_index(struct rtnl_link_vf *vf_data, uint32_t *vf_index)
 }
 
 /**
+ * Set index of SRIOV Virtual Function object
+ * @param vf_data 	SRIOV VF object
+ * @param vf_index 	Index value
+ *
+ * @see rtnl_link_vf_get_index()
+ */
+void rtnl_link_vf_set_index(struct rtnl_link_vf *vf_data, uint32_t vf_index)
+{
+	vf_data->vf_index = vf_index;
+	vf_data->ce_mask |= SRIOV_ATTR_INDEX;
+
+	return;
+}
+
+/**
  * Get link state of SRIOV Virtual Function
- * @arg vf_data 	SRIOV VF object
+ * @arg vf_data  	SRIOV VF object
  * @arg vf_linkstate 	Pointer to store VF link state
  *
  * @see rtnl_link_get_num_vf()
+ * @see rtnl_link_set_linkstate()
  *
  * @return 0 if link state is present and vf_linkstate is set
  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
@@ -670,11 +967,30 @@ int rtnl_link_vf_get_linkstate(struct rtnl_link_vf *vf_data,
 }
 
 /**
+ * Set link state of SRIOV Virtual Function object
+ * @param vf_data 	SRIOV VF object
+ * @param vf_linkstate Link state value
+ *
+ * @see rtnl_link_get_linkstate()
+ *
+ * Not all hardware supports setting link state. If the feature is unsupported,
+ * the link change request will fail with -NLE_OPNOTSUPP
+ */
+void rtnl_link_vf_set_linkstate(struct rtnl_link_vf *vf_data,
+				uint32_t vf_linkstate) {
+	vf_data->vf_linkstate = vf_linkstate;
+	vf_data->ce_mask |= SRIOV_ATTR_LINK_STATE;
+
+	return;
+}
+
+/**
  * Get TX Rate Limit of SRIOV Virtual Function
  * @arg vf_data 	SRIOV VF object
  * @arg vf_rate 	Pointer to store VF rate limiting data
  *
  * @see rtnl_link_get_num_vf()
+ * @see rtnl_link_set_rate()
  *
  * When the older rate API has been implemented, the rate member of the struct
  * will be set, and the api member will be set to RTNL_LINK_VF_API_OLD.
@@ -682,6 +998,12 @@ int rtnl_link_vf_get_linkstate(struct rtnl_link_vf *vf_data,
  * and/or the minx_tx_rate will be set, and the api member will be set to
  * RTNL_LINK_VF_API_NEW.
  *
+ * Old rate API supports only a maximum TX rate.
+ *   ip link set dev vf 0 rate
+ * New rate API supports minumum and maximum TX rates.
+ *   ip link set dev vf 0 min_tx_rate
+ *   ip link set dev vf 0 max_tx_rate
+ *
  * @return 0 if rate is present and vf_rate is set
  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
  * @return -NLE_NOATTR if the VF rate is not set
@@ -728,11 +1050,53 @@ int rtnl_link_vf_get_rate(struct rtnl_link_vf *vf_data,
 }
 
 /**
+ * Set TX Rate Limit of SRIOV Virtual Function object
+ * @param vf_data 	SRIOV VF object
+ * @param vf_rate 	Rate limiting structure
+ *
+ * @see rtnl_link_vf_get_rate()
+ *
+ * When setting the rate, the API level must be specificed.
+ * Valid API levels:
+ *   RTNL_LINK_VF_RATE_API_NEW
+ *   RTNL_LINK_VF_RATE_API_OLD
+ *
+ * When using the new API, if either the min_tx_rate or
+ * max_tx_rate has been set, and the other is being changed,
+ * you must specify the currently set values to preserve
+ * them. If this is not done, that setting will be disabled.
+ *
+ * Old rate API supports only a maximum TX rate.
+ *   ip link set dev vf 0 rate
+ * New rate API supports minumum and maximum TX rates.
+ *   ip link set dev vf 0 min_tx_rate
+ *   ip link set dev vf 0 max_tx_rate
+ *
+ * Not all hardware supports min_tx_rate.
+ */
+void rtnl_link_vf_set_rate(struct rtnl_link_vf *vf_data,
+			   struct nl_vf_rate *vf_rate) {
+	if (vf_rate->api == RTNL_LINK_VF_RATE_API_OLD) {
+		vf_data->vf_rate = vf_rate->rate;
+		vf_data->ce_mask |= SRIOV_ATTR_TX_RATE;
+	} else if (vf_rate->api == RTNL_LINK_VF_RATE_API_NEW) {
+		vf_data->vf_max_tx_rate = vf_rate->max_tx_rate;
+		vf_data->ce_mask |= SRIOV_ATTR_RATE_MAX;
+
+		vf_data->vf_min_tx_rate = vf_rate->min_tx_rate;
+		vf_data->ce_mask |= SRIOV_ATTR_RATE_MIN;
+	}
+
+	return;
+}
+
+/**
  * Get RSS Query EN value of SRIOV Virtual Function
  * @arg vf_data 	SRIOV VF object
  * @arg vf_rss_query_en	Pointer to store VF RSS Query value
  *
  * @see rtnl_link_get_num_vf()
+ * @see rtnl_link_vf_set_rss_query_en()
  *
  * @return 0 if rss_query_en is present and vf_rss_query_en is set
  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
@@ -753,11 +1117,27 @@ int rtnl_link_vf_get_rss_query_en(struct rtnl_link_vf *vf_data,
 }
 
 /**
+ * Set RSS configuration querying of SRIOV Virtual Function Object
+ * @arg vf_data 	SRIOV VF object
+ * @arg vf_rss_query_en	RSS Query value
+ *
+ * @see rtnl_link_vf_get_rss_query_en()
+ */
+void rtnl_link_vf_set_rss_query_en(struct rtnl_link_vf *vf_data,
+				  uint32_t vf_rss_query_en) {
+	vf_data->vf_rss_query_en = vf_rss_query_en;
+	vf_data->ce_mask |= SRIOV_ATTR_RSS_QUERY_EN;
+
+	return;
+}
+
+/**
  * Get spoof checking value of SRIOV Virtual Function
  * @arg vf_data 	SRIOV VF object
  * @arg vf_spoofchk 	Pointer to store VF spoofchk value
  *
  * @see rtnl_link_get_num_vf()
+ * @see rtnl_link_set_spoofchk()
  *
  * @return 0 if spoofchk is present and vf_spoofchk is set
  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
@@ -778,6 +1158,21 @@ int rtnl_link_vf_get_spoofchk(struct rtnl_link_vf *vf_data,
 }
 
 /**
+ * Set spoof checking value of SRIOV Virtual Function Object
+ * @param vf_data
+ * @param vf_spoofchk
+ *
+ * @see rtnl_link_vf_get_spoofchk()
+ */
+void rtnl_link_vf_set_spoofchk(struct rtnl_link_vf *vf_data,
+			       uint32_t vf_spoofchk) {
+	vf_data->vf_spoofchk = vf_spoofchk;
+	vf_data->ce_mask |= SRIOV_ATTR_SPOOFCHK;
+
+	return;
+}
+
+/**
  * Get value of stat counter for SRIOV Virtual Function
  * @arg vf_data 	SRIOV VF object
  * @arg stat 		Identifier of statistical counter
@@ -809,6 +1204,7 @@ int rtnl_link_vf_get_stat(struct rtnl_link_vf *vf_data,
  * @arg vf_trust 	Pointer to store VF trust value
  *
  * @see rtnl_link_get_num_vf()
+ * @see rtnl_link_set_trust()
  *
  * @return 0 if trust is present and vf_trust is set
  * @return -NLE_OBJ_NOTFOUND if information for VF info is not found
@@ -828,6 +1224,20 @@ int rtnl_link_vf_get_trust(struct rtnl_link_vf *vf_data, uint32_t *vf_trust)
 }
 
 /**
+ * Set user trust setting on SRIOV Virtual Function Object
+ * @param vf_data
+ * @param vf_trust
+ *
+ * @see rtnl_link_vf_get_trust()
+ */
+void rtnl_link_vf_set_trust(struct rtnl_link_vf *vf_data, uint32_t vf_trust) {
+	vf_data->vf_trust = vf_trust;
+	vf_data->ce_mask |= SRIOV_ATTR_TRUST;
+
+	return;
+}
+
+/**
  * Get an array of VLANS on SRIOV Virtual Function
  * @arg vf_data 	SRIOV VF object
  * @arg vf_vlans 	Pointer to nl_vf_vlans_t struct to store vlan info.
@@ -860,6 +1270,30 @@ int rtnl_link_vf_get_vlans(struct rtnl_link_vf *vf_data,
 }
 
 /**
+ * Add a SRIOV VF VLANs object to the SRIOV Virtual Function Object
+ * @param vf_data 	SRIOV VF object
+ * @param vf_vlans 	SRIOV VF VLANs object
+ *
+ * @see rtnl_link_vf_get_vlans()
+ * @see rtnl_link_vf_vlan_alloc()
+ *
+ * This function assigns ownership of the SRIOV VF object \p vf_vlans
+ * to the SRIOV Virtual Function object \p vf_data. Do not use
+ * rtnl_link_vf_vlan_put() on \p vf_vlans after this.
+ */
+void rtnl_link_vf_set_vlans(struct rtnl_link_vf *vf_data,
+			    nl_vf_vlans_t *vf_vlans) {
+	if (!vf_data||!vf_vlans)
+		return;
+
+	vf_data->vf_vlans = vf_vlans;
+	vf_data->vf_vlans->ce_refcnt++;
+	vf_data->ce_mask |= SRIOV_ATTR_VLAN;
+
+	return;
+}
+
+/**
  * Allocate a SRIOV VF VLAN object
  * @param vf_vlans 	Pointer to store VLAN object at
  * @param vlan_count 	Number of VLANs that will be stored in VLAN object
@@ -977,6 +1411,42 @@ int rtnl_link_vf_str2vlanproto(const char *name)
 	return __str2type(name, vf_vlan_proto, ARRAY_SIZE(vf_vlan_proto));
 }
 
+/* Return a guid from a format checked string.
+ * Format string must be xx:xx:xx:xx:xx:xx:xx:xx where XX can be an
+ * arbitrary hex digit
+ *
+ * Function modified from original at iproute2/lib/utils.c:get_guid()
+ * Original by Eli Cohen <eli at mellanox.com>.
+ * iproute2 git commit d91fb3f4c7e4dba806541bdc90b1fb60a3581541
+ */
+int rtnl_link_vf_str2guid(uint64_t *guid, const char *guid_s) {
+	unsigned long int tmp;
+	char *endptr;
+	int i;
+
+	if (strlen(guid_s) != RTNL_VF_GUID_STR_LEN)
+		return -1;
+
+	for (i = 0; i < 7; i++) {
+		if (guid_s[2 + i * 3] != ':')
+			return -1;
+	}
+
+	*guid = 0;
+	for (i = 0; i < 8; i++) {
+		tmp = strtoul(guid_s + i * 3, &endptr, 16);
+		if (endptr != guid_s + i * 3 + 2)
+			return -1;
+
+		if (tmp > 255)
+			return -1;
+
+		*guid |= tmp << (56 - 8 * i);
+	}
+
+	return 0;
+}
+
 /** @} */
 
 /** @} */
diff --git a/libnl-route-3.sym b/libnl-route-3.sym
index a96f740..a6345d5 100644
--- a/libnl-route-3.sym
+++ b/libnl-route-3.sym
@@ -990,21 +990,33 @@ global:
 	rtnl_link_sriov_clone;
 	rtnl_link_sriov_dump_details;
 	rtnl_link_sriov_dump_stats;
+	rtnl_link_sriov_fill_vflist;
 	rtnl_link_sriov_free_data;
 	rtnl_link_sriov_parse_vflist;
+	rtnl_link_vf_add;
 	rtnl_link_vf_alloc;
 	rtnl_link_vf_free;
 	rtnl_link_vf_get;
 	rtnl_link_vf_put;
 	rtnl_link_vf_get_addr;
+	rtnl_link_vf_set_addr;
+	rtnl_link_vf_set_ib_node_guid;
+	rtnl_link_vf_set_ib_port_guid;
 	rtnl_link_vf_get_index;
+	rtnl_link_vf_set_index;
 	rtnl_link_vf_get_linkstate;
+	rtnl_link_vf_set_linkstate;
 	rtnl_link_vf_get_rate;
+	rtnl_link_vf_set_rate;
 	rtnl_link_vf_get_rss_query_en;
+	rtnl_link_vf_set_rss_query_en;
 	rtnl_link_vf_get_spoofchk;
+	rtnl_link_vf_set_spoofchk;
 	rtnl_link_vf_get_stat;
 	rtnl_link_vf_get_trust;
+	rtnl_link_vf_set_trust;
 	rtnl_link_vf_get_vlans;
+	rtnl_link_vf_set_vlans;
 	rtnl_link_vf_vlan_alloc;
 	rtnl_link_vf_vlan_free;
 	rtnl_link_vf_vlan_put;
@@ -1012,5 +1024,6 @@ global:
 	rtnl_link_vf_str2linkstate;
 	rtnl_link_vf_vlanproto2str;
 	rtnl_link_vf_str2vlanproto;
+	rtnl_link_vf_str2guid;
 } libnl_3_2_28;
 
-- 
2.10.1




More information about the libnl mailing list