Skip to content

Commit

Permalink
enic: Use VF mac set by IFLA_VF_MAC in port profile provisioning data
Browse files Browse the repository at this point in the history
This patch adds support in enic 802.1Qbh port profile provisioning code
to use the mac address set by IFLA_VF_MAC. For now we handle this mac as a
special case for a VM mac address sent to us by libvirt. The VM mac address
is sent to the switch along with the rest of the port profile provisioning
data. This patch also adds calls to register and deregister the mac address
during port profile association/deassociation.

Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David Wang <dwang2@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Roopa Prabhu authored and David S. Miller committed Dec 10, 2010
1 parent 0b1c00f commit 2963905
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 23 deletions.
1 change: 1 addition & 0 deletions drivers/net/enic/enic.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct enic_port_profile {
u8 instance_uuid[PORT_UUID_MAX];
u8 host_uuid[PORT_UUID_MAX];
u8 vf_mac[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
};

/* Per-instance private data structure */
Expand Down
79 changes: 56 additions & 23 deletions drivers/net/enic/enic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1278,9 +1278,14 @@ static int enic_set_port_profile(struct enic *enic, u8 *mac)
VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
strlen(enic->pp.name) + 1, enic->pp.name);

vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
ETH_ALEN, mac);
if (!is_zero_ether_addr(enic->pp.mac_addr))
vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
ETH_ALEN, enic->pp.mac_addr);
else
vic_provinfo_add_tlv(vp,
VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
ETH_ALEN, mac);

if (enic->pp.set & ENIC_SET_INSTANCE) {
sprintf(uuid_str, "%pUB", enic->pp.instance_uuid);
Expand All @@ -1300,68 +1305,90 @@ static int enic_set_port_profile(struct enic *enic, u8 *mac)
vic_provinfo_free(vp);
if (err)
return err;

enic->pp.set |= ENIC_SET_APPLIED;
break;

case PORT_REQUEST_DISASSOCIATE:
enic->pp.set &= ~ENIC_SET_APPLIED;
break;

default:
return -EINVAL;
}

enic->pp.set |= ENIC_SET_APPLIED;
return 0;
}

static int enic_set_vf_port(struct net_device *netdev, int vf,
struct nlattr *port[])
{
struct enic *enic = netdev_priv(netdev);
struct enic_port_profile new_pp;
int err = 0;

memset(&enic->pp, 0, sizeof(enic->pp));
memset(&new_pp, 0, sizeof(new_pp));

if (port[IFLA_PORT_REQUEST]) {
enic->pp.set |= ENIC_SET_REQUEST;
enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
new_pp.set |= ENIC_SET_REQUEST;
new_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]),
new_pp.set |= ENIC_SET_NAME;
memcpy(new_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,
new_pp.set |= ENIC_SET_INSTANCE;
memcpy(new_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,
new_pp.set |= ENIC_SET_HOST;
memcpy(new_pp.host_uuid,
nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
}

/* don't support VFs, yet */
if (vf != PORT_SELF_VF)
return -EOPNOTSUPP;

if (!(enic->pp.set & ENIC_SET_REQUEST))
if (!(new_pp.set & ENIC_SET_REQUEST))
return -EOPNOTSUPP;

if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {

/* If the interface mac addr hasn't been assigned,
* assign a random mac addr before setting port-
* profile.
*/
if (new_pp.request == PORT_REQUEST_ASSOCIATE) {
/* Special case handling */
if (!is_zero_ether_addr(enic->pp.vf_mac))
memcpy(new_pp.mac_addr, enic->pp.vf_mac, ETH_ALEN);

if (is_zero_ether_addr(netdev->dev_addr))
random_ether_addr(netdev->dev_addr);
} else if (new_pp.request == PORT_REQUEST_DISASSOCIATE) {
if (!is_zero_ether_addr(enic->pp.mac_addr))
enic_dev_del_addr(enic, enic->pp.mac_addr);
}

return enic_set_port_profile(enic, netdev->dev_addr);
memcpy(&enic->pp, &new_pp, sizeof(struct enic_port_profile));

err = enic_set_port_profile(enic, netdev->dev_addr);
if (err)
goto set_port_profile_cleanup;

if (!is_zero_ether_addr(enic->pp.mac_addr))
enic_dev_add_addr(enic, enic->pp.mac_addr);

set_port_profile_cleanup:
memset(enic->pp.vf_mac, 0, ETH_ALEN);

if (err || enic->pp.request == PORT_REQUEST_DISASSOCIATE) {
memset(netdev->dev_addr, 0, ETH_ALEN);
memset(enic->pp.mac_addr, 0, ETH_ALEN);
}

return err;
}

static int enic_get_vf_port(struct net_device *netdev, int vf,
Expand Down Expand Up @@ -1941,7 +1968,10 @@ static int enic_open(struct net_device *netdev)
for (i = 0; i < enic->rq_count; i++)
vnic_rq_enable(&enic->rq[i]);

enic_dev_add_station_addr(enic);
if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr))
enic_dev_add_addr(enic, enic->pp.mac_addr);
else
enic_dev_add_station_addr(enic);
enic_set_rx_mode(netdev);

netif_wake_queue(netdev);
Expand Down Expand Up @@ -1989,7 +2019,10 @@ static int enic_stop(struct net_device *netdev)

netif_carrier_off(netdev);
netif_tx_disable(netdev);
enic_dev_del_station_addr(enic);
if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr))
enic_dev_del_addr(enic, enic->pp.mac_addr);
else
enic_dev_del_station_addr(enic);

for (i = 0; i < enic->wq_count; i++) {
err = vnic_wq_disable(&enic->wq[i]);
Expand Down

0 comments on commit 2963905

Please sign in to comment.