qed: PF enforce MAC limitation of VFs

The only limitation relating to MACs the PF enforce today on its VFs
is in case it has a forced-unicast MAC address for them, in which case
they can't configure other unicast addresses.
Specifically, the PF isn't enforcing the number of MAC addresse a VF can
configure regardless of the nubmer of such filters agreed upon by PF and
VF during the acquisition process.

PF's shadow-config is now extended to also contain information about its
VFs' unicast addresses configuration, allowing such enforcement.

Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Yuval Mintz 2016-06-05 13:11:15 +03:00 committed by David S. Miller
parent 5040acf537
commit 8246d0b48b
2 changed files with 79 additions and 6 deletions

View File

@ -2309,15 +2309,12 @@ static void qed_iov_vf_mbx_vport_update(struct qed_hwfn *p_hwfn,
qed_iov_send_response(p_hwfn, p_ptt, vf, length, status);
}
static int qed_iov_vf_update_unicast_shadow(struct qed_hwfn *p_hwfn,
static int qed_iov_vf_update_vlan_shadow(struct qed_hwfn *p_hwfn,
struct qed_vf_info *p_vf,
struct qed_filter_ucast *p_params)
{
int i;
if (p_params->type == QED_FILTER_MAC)
return 0;
/* First remove entries and then add new ones */
if (p_params->opcode == QED_FILTER_REMOVE) {
for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++)
@ -2370,6 +2367,80 @@ static int qed_iov_vf_update_unicast_shadow(struct qed_hwfn *p_hwfn,
return 0;
}
static int qed_iov_vf_update_mac_shadow(struct qed_hwfn *p_hwfn,
struct qed_vf_info *p_vf,
struct qed_filter_ucast *p_params)
{
int i;
/* If we're in forced-mode, we don't allow any change */
if (p_vf->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED))
return 0;
/* First remove entries and then add new ones */
if (p_params->opcode == QED_FILTER_REMOVE) {
for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) {
if (ether_addr_equal(p_vf->shadow_config.macs[i],
p_params->mac)) {
memset(p_vf->shadow_config.macs[i], 0,
ETH_ALEN);
break;
}
}
if (i == QED_ETH_VF_NUM_MAC_FILTERS) {
DP_VERBOSE(p_hwfn, QED_MSG_IOV,
"MAC isn't configured\n");
return -EINVAL;
}
} else if (p_params->opcode == QED_FILTER_REPLACE ||
p_params->opcode == QED_FILTER_FLUSH) {
for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++)
memset(p_vf->shadow_config.macs[i], 0, ETH_ALEN);
}
/* List the new MAC address */
if (p_params->opcode != QED_FILTER_ADD &&
p_params->opcode != QED_FILTER_REPLACE)
return 0;
for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) {
if (is_zero_ether_addr(p_vf->shadow_config.macs[i])) {
ether_addr_copy(p_vf->shadow_config.macs[i],
p_params->mac);
DP_VERBOSE(p_hwfn, QED_MSG_IOV,
"Added MAC at %d entry in shadow\n", i);
break;
}
}
if (i == QED_ETH_VF_NUM_MAC_FILTERS) {
DP_VERBOSE(p_hwfn, QED_MSG_IOV, "No available place for MAC\n");
return -EINVAL;
}
return 0;
}
static int
qed_iov_vf_update_unicast_shadow(struct qed_hwfn *p_hwfn,
struct qed_vf_info *p_vf,
struct qed_filter_ucast *p_params)
{
int rc = 0;
if (p_params->type == QED_FILTER_MAC) {
rc = qed_iov_vf_update_mac_shadow(p_hwfn, p_vf, p_params);
if (rc)
return rc;
}
if (p_params->type == QED_FILTER_VLAN)
rc = qed_iov_vf_update_vlan_shadow(p_hwfn, p_vf, p_params);
return rc;
}
int qed_iov_chk_ucast(struct qed_hwfn *hwfn,
int vfid, struct qed_filter_ucast *params)
{

View File

@ -120,6 +120,8 @@ struct qed_vf_shadow_config {
/* Shadow copy of all guest vlans */
struct qed_vf_vlan_shadow vlans[QED_ETH_VF_NUM_VLAN_FILTERS + 1];
/* Shadow copy of all configured MACs; Empty if forcing MACs */
u8 macs[QED_ETH_VF_NUM_MAC_FILTERS][ETH_ALEN];
u8 inner_vlan_removal;
};