提交 08f382eb 编写于 作者: S Scott Feldman 提交者: David S. Miller

enic: bug fix: make the set/get netlink VF_PORT support symmetrical

To make get/set netlink VF_PORT truly symmetrical, we need to keep track
of what items are set and only return those items on get.  Previously, the
driver wasn't differentiating between a set of attr with a NULL string,
for example, and not setting the attr at all.  We only want to return
the NULL string if the attr was actually set with a NULL string.  Otherwise,
don't return the attr.
Signed-off-by: NScott Feldman <scofeldm@cisco.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 f048fa9c
...@@ -74,7 +74,14 @@ struct enic_msix_entry { ...@@ -74,7 +74,14 @@ struct enic_msix_entry {
void *devid; void *devid;
}; };
#define ENIC_SET_APPLIED (1 << 0)
#define ENIC_SET_REQUEST (1 << 1)
#define ENIC_SET_NAME (1 << 2)
#define ENIC_SET_INSTANCE (1 << 3)
#define ENIC_SET_HOST (1 << 4)
struct enic_port_profile { struct enic_port_profile {
u32 set;
u8 request; u8 request;
char name[PORT_PROFILE_MAX]; char name[PORT_PROFILE_MAX];
u8 instance_uuid[PORT_UUID_MAX]; u8 instance_uuid[PORT_UUID_MAX];
......
...@@ -1029,8 +1029,7 @@ static int enic_dev_init_done(struct enic *enic, int *done, int *error) ...@@ -1029,8 +1029,7 @@ static int enic_dev_init_done(struct enic *enic, int *done, int *error)
return err; return err;
} }
static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac, static int enic_set_port_profile(struct enic *enic, u8 *mac)
char *name, u8 *instance_uuid, u8 *host_uuid)
{ {
struct vic_provinfo *vp; struct vic_provinfo *vp;
u8 oui[3] = VIC_PROVINFO_CISCO_OUI; u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
...@@ -1040,97 +1039,112 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac, ...@@ -1040,97 +1039,112 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
"%02X%02X-%02X%02X%02X%02X%0X%02X"; "%02X%02X-%02X%02X%02X%02X%0X%02X";
int err; int err;
if (!name) err = enic_vnic_dev_deinit(enic);
return -EINVAL; if (err)
return err;
if (!is_valid_ether_addr(mac)) switch (enic->pp.request) {
return -EADDRNOTAVAIL;
vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE); case PORT_REQUEST_ASSOCIATE:
if (!vp)
return -ENOMEM;
vic_provinfo_add_tlv(vp, if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR, return -EINVAL;
strlen(name) + 1, name);
vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
ETH_ALEN, mac);
if (instance_uuid) {
uuid = instance_uuid;
sprintf(uuid_str, uuid_fmt,
uuid[0], uuid[1], uuid[2], uuid[3],
uuid[4], uuid[5], uuid[6], uuid[7],
uuid[8], uuid[9], uuid[10], uuid[11],
uuid[12], uuid[13], uuid[14], uuid[15]);
vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
sizeof(uuid_str), uuid_str);
}
if (host_uuid) { if (!is_valid_ether_addr(mac))
uuid = host_uuid; return -EADDRNOTAVAIL;
sprintf(uuid_str, uuid_fmt,
uuid[0], uuid[1], uuid[2], uuid[3],
uuid[4], uuid[5], uuid[6], uuid[7],
uuid[8], uuid[9], uuid[10], uuid[11],
uuid[12], uuid[13], uuid[14], uuid[15]);
vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_HOST_UUID_STR,
sizeof(uuid_str), uuid_str);
}
err = enic_vnic_dev_deinit(enic); vp = vic_provinfo_alloc(GFP_KERNEL, oui,
if (err) VIC_PROVINFO_LINUX_TYPE);
goto err_out; if (!vp)
return -ENOMEM;
memset(&enic->pp, 0, sizeof(enic->pp)); vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
strlen(enic->pp.name) + 1, enic->pp.name);
err = enic_dev_init_prov(enic, vp); vic_provinfo_add_tlv(vp,
if (err) VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
goto err_out; ETH_ALEN, mac);
if (enic->pp.set & ENIC_SET_INSTANCE) {
uuid = enic->pp.instance_uuid;
sprintf(uuid_str, uuid_fmt,
uuid[0], uuid[1], uuid[2], uuid[3],
uuid[4], uuid[5], uuid[6], uuid[7],
uuid[8], uuid[9], uuid[10], uuid[11],
uuid[12], uuid[13], uuid[14], uuid[15]);
vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
sizeof(uuid_str), uuid_str);
}
enic->pp.request = request; if (enic->pp.set & ENIC_SET_HOST) {
memcpy(enic->pp.name, name, PORT_PROFILE_MAX); uuid = enic->pp.host_uuid;
if (instance_uuid) sprintf(uuid_str, uuid_fmt,
memcpy(enic->pp.instance_uuid, uuid[0], uuid[1], uuid[2], uuid[3],
instance_uuid, PORT_UUID_MAX); uuid[4], uuid[5], uuid[6], uuid[7],
if (host_uuid) uuid[8], uuid[9], uuid[10], uuid[11],
memcpy(enic->pp.host_uuid, uuid[12], uuid[13], uuid[14], uuid[15]);
host_uuid, PORT_UUID_MAX); vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_HOST_UUID_STR,
sizeof(uuid_str), uuid_str);
}
err_out: err = enic_dev_init_prov(enic, vp);
vic_provinfo_free(vp); vic_provinfo_free(vp);
if (err)
return err;
break;
return err; case PORT_REQUEST_DISASSOCIATE:
} break;
static int enic_unset_port_profile(struct enic *enic) default:
{ return -EINVAL;
memset(&enic->pp, 0, sizeof(enic->pp)); }
return enic_vnic_dev_deinit(enic);
enic->pp.set |= ENIC_SET_APPLIED;
return 0;
} }
static int enic_set_vf_port(struct net_device *netdev, int vf, static int enic_set_vf_port(struct net_device *netdev, int vf,
struct nlattr *port[]) struct nlattr *port[])
{ {
struct enic *enic = netdev_priv(netdev); struct enic *enic = netdev_priv(netdev);
char *name = NULL;
u8 *instance_uuid = NULL; memset(&enic->pp, 0, sizeof(enic->pp));
u8 *host_uuid = NULL;
u8 request = PORT_REQUEST_DISASSOCIATE; if (port[IFLA_PORT_REQUEST]) {
enic->pp.set |= ENIC_SET_REQUEST;
enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
}
if (port[IFLA_PORT_PROFILE]) {
enic->pp.set |= ENIC_SET_NAME;
memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
PORT_PROFILE_MAX);
}
if (port[IFLA_PORT_INSTANCE_UUID]) {
enic->pp.set |= ENIC_SET_INSTANCE;
memcpy(enic->pp.instance_uuid,
nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
}
if (port[IFLA_PORT_HOST_UUID]) {
enic->pp.set |= ENIC_SET_HOST;
memcpy(enic->pp.host_uuid,
nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
}
/* don't support VFs, yet */ /* don't support VFs, yet */
if (vf != PORT_SELF_VF) if (vf != PORT_SELF_VF)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (port[IFLA_PORT_REQUEST]) if (!(enic->pp.set & ENIC_SET_REQUEST))
request = nla_get_u8(port[IFLA_PORT_REQUEST]); return -EOPNOTSUPP;
switch (request) { if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {
case PORT_REQUEST_ASSOCIATE:
/* If the interface mac addr hasn't been assigned, /* If the interface mac addr hasn't been assigned,
* assign a random mac addr before setting port- * assign a random mac addr before setting port-
...@@ -1139,30 +1153,9 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, ...@@ -1139,30 +1153,9 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
if (is_zero_ether_addr(netdev->dev_addr)) if (is_zero_ether_addr(netdev->dev_addr))
random_ether_addr(netdev->dev_addr); random_ether_addr(netdev->dev_addr);
if (port[IFLA_PORT_PROFILE])
name = nla_data(port[IFLA_PORT_PROFILE]);
if (port[IFLA_PORT_INSTANCE_UUID])
instance_uuid =
nla_data(port[IFLA_PORT_INSTANCE_UUID]);
if (port[IFLA_PORT_HOST_UUID])
host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]);
return enic_set_port_profile(enic, request,
netdev->dev_addr, name,
instance_uuid, host_uuid);
case PORT_REQUEST_DISASSOCIATE:
return enic_unset_port_profile(enic);
default:
break;
} }
return -EOPNOTSUPP; return enic_set_port_profile(enic, netdev->dev_addr);
} }
static int enic_get_vf_port(struct net_device *netdev, int vf, static int enic_get_vf_port(struct net_device *netdev, int vf,
...@@ -1172,14 +1165,12 @@ static int enic_get_vf_port(struct net_device *netdev, int vf, ...@@ -1172,14 +1165,12 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
int err, error, done; int err, error, done;
u16 response = PORT_PROFILE_RESPONSE_SUCCESS; u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
/* don't support VFs, yet */ if (!(enic->pp.set & ENIC_SET_APPLIED))
if (vf != PORT_SELF_VF) return -ENODATA;
return -EOPNOTSUPP;
err = enic_dev_init_done(enic, &done, &error); err = enic_dev_init_done(enic, &done, &error);
if (err) if (err)
return err; error = err;
switch (error) { switch (error) {
case ERR_SUCCESS: case ERR_SUCCESS:
...@@ -1202,12 +1193,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf, ...@@ -1202,12 +1193,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request); NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response); NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX, if (enic->pp.set & ENIC_SET_NAME)
enic->pp.name); NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, enic->pp.name);
enic->pp.instance_uuid); if (enic->pp.set & ENIC_SET_INSTANCE)
NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX, NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
enic->pp.host_uuid); enic->pp.instance_uuid);
if (enic->pp.set & ENIC_SET_HOST)
NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
enic->pp.host_uuid);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册