net/qede/base: add handling of malicious VF
Receive indication that VFs are malicious and pass it to the caller/clients and stop serving those VF's additional resource requests. Signed-off-by: Rasesh Mody <rasesh.mody@cavium.com>
This commit is contained in:
parent
830aba26d9
commit
47b302d646
@ -323,6 +323,7 @@ u32 qede_find_first_zero_bit(unsigned long *, u32);
|
||||
#define OSAL_VF_SEND_MSG2PF(dev, done, msg, reply_addr, msg_size, reply_size) 0
|
||||
#define OSAL_VF_CQE_COMPLETION(_dev_p, _cqe, _protocol) (0)
|
||||
#define OSAL_PF_VF_MSG(hwfn, vfid) 0
|
||||
#define OSAL_PF_VF_MALICIOUS(hwfn, vfid) nothing
|
||||
#define OSAL_IOV_CHK_UCAST(hwfn, vfid, params) 0
|
||||
#define OSAL_IOV_POST_START_VPORT(hwfn, vf, vport_id, opaque_fid) nothing
|
||||
#define OSAL_IOV_VF_ACQUIRE(hwfn, vfid) 0
|
||||
|
@ -52,6 +52,7 @@ enum ecore_iov_pf_to_vf_status {
|
||||
PFVF_STATUS_NOT_SUPPORTED,
|
||||
PFVF_STATUS_NO_RESOURCE,
|
||||
PFVF_STATUS_FORCED,
|
||||
PFVF_STATUS_MALICIOUS,
|
||||
};
|
||||
|
||||
struct ecore_mcp_link_params;
|
||||
@ -301,12 +302,13 @@ bool ecore_iov_is_vf_pending_flr(struct ecore_hwfn *p_hwfn,
|
||||
* @param p_hwfn
|
||||
* @param rel_vf_id - Relative VF ID
|
||||
* @param b_enabled_only - consider only enabled VF
|
||||
* @param b_non_malicious - true iff we want to validate vf isn't malicious.
|
||||
*
|
||||
* @return bool - true for valid VF ID
|
||||
*/
|
||||
bool ecore_iov_is_valid_vfid(struct ecore_hwfn *p_hwfn,
|
||||
int rel_vf_id,
|
||||
bool b_enabled_only);
|
||||
bool b_enabled_only, bool b_non_malicious);
|
||||
|
||||
/**
|
||||
* @brief Get VF's public info structure
|
||||
|
@ -36,9 +36,9 @@ ecore_sp_eth_vport_start(struct ecore_hwfn *p_hwfn,
|
||||
struct vport_start_ramrod_data *p_ramrod = OSAL_NULL;
|
||||
struct ecore_spq_entry *p_ent = OSAL_NULL;
|
||||
struct ecore_sp_init_data init_data;
|
||||
u16 rx_mode = 0, tx_err = 0;
|
||||
u8 abs_vport_id = 0;
|
||||
enum _ecore_status_t rc = ECORE_NOTIMPL;
|
||||
u16 rx_mode = 0;
|
||||
|
||||
rc = ecore_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id);
|
||||
if (rc != ECORE_SUCCESS)
|
||||
@ -71,6 +71,30 @@ ecore_sp_eth_vport_start(struct ecore_hwfn *p_hwfn,
|
||||
|
||||
p_ramrod->rx_mode.state = OSAL_CPU_TO_LE16(rx_mode);
|
||||
|
||||
/* Handle requests for strict behavior on transmission errors */
|
||||
SET_FIELD(tx_err, ETH_TX_ERR_VALS_ILLEGAL_VLAN_MODE,
|
||||
p_params->b_err_illegal_vlan_mode ?
|
||||
ETH_TX_ERR_ASSERT_MALICIOUS : 0);
|
||||
SET_FIELD(tx_err, ETH_TX_ERR_VALS_PACKET_TOO_SMALL,
|
||||
p_params->b_err_small_pkt ?
|
||||
ETH_TX_ERR_ASSERT_MALICIOUS : 0);
|
||||
SET_FIELD(tx_err, ETH_TX_ERR_VALS_ANTI_SPOOFING_ERR,
|
||||
p_params->b_err_anti_spoof ?
|
||||
ETH_TX_ERR_ASSERT_MALICIOUS : 0);
|
||||
SET_FIELD(tx_err, ETH_TX_ERR_VALS_ILLEGAL_INBAND_TAGS,
|
||||
p_params->b_err_illegal_inband_mode ?
|
||||
ETH_TX_ERR_ASSERT_MALICIOUS : 0);
|
||||
SET_FIELD(tx_err, ETH_TX_ERR_VALS_VLAN_INSERTION_W_INBAND_TAG,
|
||||
p_params->b_err_vlan_insert_with_inband ?
|
||||
ETH_TX_ERR_ASSERT_MALICIOUS : 0);
|
||||
SET_FIELD(tx_err, ETH_TX_ERR_VALS_MTU_VIOLATION,
|
||||
p_params->b_err_big_pkt ?
|
||||
ETH_TX_ERR_ASSERT_MALICIOUS : 0);
|
||||
SET_FIELD(tx_err, ETH_TX_ERR_VALS_ILLEGAL_CONTROL_FRAME,
|
||||
p_params->b_err_ctrl_frame ?
|
||||
ETH_TX_ERR_ASSERT_MALICIOUS : 0);
|
||||
p_ramrod->tx_err_behav.values = OSAL_CPU_TO_LE16(tx_err);
|
||||
|
||||
/* TPA related fields */
|
||||
OSAL_MEMSET(&p_ramrod->tpa_param, 0,
|
||||
sizeof(struct eth_vport_tpa_param));
|
||||
|
@ -274,6 +274,15 @@ struct ecore_sp_vport_start_params {
|
||||
bool zero_placement_offset;
|
||||
bool check_mac;
|
||||
bool check_ethtype;
|
||||
|
||||
/* Strict behavior on transmission errors */
|
||||
bool b_err_illegal_vlan_mode;
|
||||
bool b_err_illegal_inband_mode;
|
||||
bool b_err_vlan_insert_with_inband;
|
||||
bool b_err_small_pkt;
|
||||
bool b_err_big_pkt;
|
||||
bool b_err_anti_spoof;
|
||||
bool b_err_ctrl_frame;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -146,7 +146,7 @@ static enum _ecore_status_t ecore_sp_vf_stop(struct ecore_hwfn *p_hwfn,
|
||||
}
|
||||
|
||||
bool ecore_iov_is_valid_vfid(struct ecore_hwfn *p_hwfn, int rel_vf_id,
|
||||
bool b_enabled_only)
|
||||
bool b_enabled_only, bool b_non_malicious)
|
||||
{
|
||||
if (!p_hwfn->pf_iov_info) {
|
||||
DP_NOTICE(p_hwfn->p_dev, true, "No iov info\n");
|
||||
@ -161,6 +161,10 @@ bool ecore_iov_is_valid_vfid(struct ecore_hwfn *p_hwfn, int rel_vf_id,
|
||||
b_enabled_only)
|
||||
return false;
|
||||
|
||||
if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) &&
|
||||
b_non_malicious)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -175,7 +179,8 @@ struct ecore_vf_info *ecore_iov_get_vf_info(struct ecore_hwfn *p_hwfn,
|
||||
return OSAL_NULL;
|
||||
}
|
||||
|
||||
if (ecore_iov_is_valid_vfid(p_hwfn, relative_vf_id, b_enabled_only))
|
||||
if (ecore_iov_is_valid_vfid(p_hwfn, relative_vf_id,
|
||||
b_enabled_only, false))
|
||||
vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id];
|
||||
else
|
||||
DP_ERR(p_hwfn, "ecore_iov_get_vf_info: VF[%d] is not enabled\n",
|
||||
@ -612,7 +617,8 @@ enum _ecore_status_t ecore_iov_hw_info(struct ecore_hwfn *p_hwfn)
|
||||
return ECORE_SUCCESS;
|
||||
}
|
||||
|
||||
bool ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid)
|
||||
bool _ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid,
|
||||
bool b_fail_malicious)
|
||||
{
|
||||
/* Check PF supports sriov */
|
||||
if (IS_VF(p_hwfn->p_dev) || !IS_ECORE_SRIOV(p_hwfn->p_dev) ||
|
||||
@ -620,12 +626,17 @@ bool ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid)
|
||||
return false;
|
||||
|
||||
/* Check VF validity */
|
||||
if (!ecore_iov_is_valid_vfid(p_hwfn, vfid, true))
|
||||
if (!ecore_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid)
|
||||
{
|
||||
return _ecore_iov_pf_sanity_check(p_hwfn, vfid, true);
|
||||
}
|
||||
|
||||
void ecore_iov_set_vf_to_disable(struct ecore_dev *p_dev,
|
||||
u16 rel_vf_id, u8 to_disable)
|
||||
{
|
||||
@ -746,6 +757,9 @@ ecore_iov_enable_vf_access(struct ecore_hwfn *p_hwfn,
|
||||
|
||||
ecore_iov_vf_igu_reset(p_hwfn, p_ptt, vf);
|
||||
|
||||
/* It's possible VF was previously considered malicious */
|
||||
vf->b_malicious = false;
|
||||
|
||||
rc = ecore_mcp_config_vf_msix(p_hwfn, p_ptt,
|
||||
vf->abs_vf_id, vf->num_sbs);
|
||||
if (rc != ECORE_SUCCESS)
|
||||
@ -3227,7 +3241,8 @@ void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn,
|
||||
p_vf, mbx->first_tlv.tl.type);
|
||||
|
||||
/* check if tlv type is known */
|
||||
if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type)) {
|
||||
if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type) &&
|
||||
!p_vf->b_malicious) {
|
||||
/* switch on the opcode */
|
||||
switch (mbx->first_tlv.tl.type) {
|
||||
case CHANNEL_TLV_ACQUIRE:
|
||||
@ -3270,6 +3285,27 @@ void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn,
|
||||
ecore_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf);
|
||||
break;
|
||||
}
|
||||
} else if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type)) {
|
||||
/* If we've received a message from a VF we consider malicious
|
||||
* we ignore the messasge unless it's one for RELEASE, in which
|
||||
* case we'll let it have the benefit of doubt, allowing the
|
||||
* next loaded driver to start again.
|
||||
*/
|
||||
if (mbx->first_tlv.tl.type == CHANNEL_TLV_RELEASE) {
|
||||
/* TODO - initiate FLR, remove malicious indication */
|
||||
DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
|
||||
"VF [%02x] - considered malicious, but wanted to RELEASE. TODO\n",
|
||||
p_vf->abs_vf_id);
|
||||
} else {
|
||||
DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
|
||||
"VF [%02x] - considered malicious; Ignoring TLV [%04x]\n",
|
||||
p_vf->abs_vf_id, mbx->first_tlv.tl.type);
|
||||
}
|
||||
|
||||
ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
|
||||
mbx->first_tlv.tl.type,
|
||||
sizeof(struct pfvf_def_resp_tlv),
|
||||
PFVF_STATUS_MALICIOUS);
|
||||
} else {
|
||||
/* unknown TLV - this may belong to a VF driver from the future
|
||||
* - a version written after this PF driver was written, which
|
||||
@ -3334,21 +3370,31 @@ void ecore_iov_pf_get_and_clear_pending_events(struct ecore_hwfn *p_hwfn,
|
||||
sizeof(u64) * ECORE_VF_ARRAY_LENGTH);
|
||||
}
|
||||
|
||||
static struct ecore_vf_info *
|
||||
ecore_sriov_get_vf_from_absid(struct ecore_hwfn *p_hwfn, u16 abs_vfid)
|
||||
{
|
||||
u8 min = (u8)p_hwfn->p_dev->p_iov_info->first_vf_in_pf;
|
||||
|
||||
if (!_ecore_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) {
|
||||
DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
|
||||
"Got indication for VF [abs 0x%08x] that cannot be"
|
||||
" handled by PF\n",
|
||||
abs_vfid);
|
||||
return OSAL_NULL;
|
||||
}
|
||||
|
||||
return &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min];
|
||||
}
|
||||
|
||||
static enum _ecore_status_t ecore_sriov_vfpf_msg(struct ecore_hwfn *p_hwfn,
|
||||
u16 abs_vfid,
|
||||
struct regpair *vf_msg)
|
||||
{
|
||||
u8 min = (u8)p_hwfn->p_dev->p_iov_info->first_vf_in_pf;
|
||||
struct ecore_vf_info *p_vf;
|
||||
struct ecore_vf_info *p_vf = ecore_sriov_get_vf_from_absid(p_hwfn,
|
||||
abs_vfid);
|
||||
|
||||
if (!ecore_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min)) {
|
||||
DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
|
||||
"Got a message from VF [abs 0x%08x] that cannot be"
|
||||
" handled by PF\n",
|
||||
abs_vfid);
|
||||
if (!p_vf)
|
||||
return ECORE_SUCCESS;
|
||||
}
|
||||
p_vf = &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min];
|
||||
|
||||
/* List the physical address of the request so that handler
|
||||
* could later on copy the message from it.
|
||||
@ -3358,6 +3404,25 @@ static enum _ecore_status_t ecore_sriov_vfpf_msg(struct ecore_hwfn *p_hwfn,
|
||||
return OSAL_PF_VF_MSG(p_hwfn, p_vf->relative_vf_id);
|
||||
}
|
||||
|
||||
static void ecore_sriov_vfpf_malicious(struct ecore_hwfn *p_hwfn,
|
||||
struct malicious_vf_eqe_data *p_data)
|
||||
{
|
||||
struct ecore_vf_info *p_vf;
|
||||
|
||||
p_vf = ecore_sriov_get_vf_from_absid(p_hwfn, p_data->vfId);
|
||||
|
||||
if (!p_vf)
|
||||
return;
|
||||
|
||||
DP_INFO(p_hwfn,
|
||||
"VF [%d] - Malicious behavior [%02x]\n",
|
||||
p_vf->abs_vf_id, p_data->errId);
|
||||
|
||||
p_vf->b_malicious = true;
|
||||
|
||||
OSAL_PF_VF_MALICIOUS(p_hwfn, p_vf->relative_vf_id);
|
||||
}
|
||||
|
||||
enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
|
||||
u8 opcode,
|
||||
__le16 echo,
|
||||
@ -3371,6 +3436,9 @@ enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
|
||||
DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
|
||||
"VF-FLR is still not supported\n");
|
||||
return ECORE_SUCCESS;
|
||||
case COMMON_EVENT_MALICIOUS_VF:
|
||||
ecore_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf);
|
||||
return ECORE_SUCCESS;
|
||||
default:
|
||||
DP_INFO(p_hwfn->p_dev, "Unknown sriov eqe event 0x%02x\n",
|
||||
opcode);
|
||||
@ -3393,7 +3461,7 @@ u16 ecore_iov_get_next_active_vf(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
|
||||
goto out;
|
||||
|
||||
for (i = rel_vf_id; i < p_iov->total_vfs; i++)
|
||||
if (ecore_iov_is_valid_vfid(p_hwfn, rel_vf_id, true))
|
||||
if (ecore_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false))
|
||||
return i;
|
||||
|
||||
out:
|
||||
@ -3439,6 +3507,12 @@ void ecore_iov_bulletin_set_forced_mac(struct ecore_hwfn *p_hwfn,
|
||||
"Can not set forced MAC, invalid vfid [%d]\n", vfid);
|
||||
return;
|
||||
}
|
||||
if (vf_info->b_malicious) {
|
||||
DP_NOTICE(p_hwfn->p_dev, false,
|
||||
"Can't set forced MAC to malicious VF [%d]\n",
|
||||
vfid);
|
||||
return;
|
||||
}
|
||||
|
||||
feature = 1 << MAC_ADDR_FORCED;
|
||||
OSAL_MEMCPY(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN);
|
||||
@ -3463,6 +3537,12 @@ enum _ecore_status_t ecore_iov_bulletin_set_mac(struct ecore_hwfn *p_hwfn,
|
||||
"Can not set MAC, invalid vfid [%d]\n", vfid);
|
||||
return ECORE_INVAL;
|
||||
}
|
||||
if (vf_info->b_malicious) {
|
||||
DP_NOTICE(p_hwfn->p_dev, false,
|
||||
"Can't set MAC to malicious VF [%d]\n",
|
||||
vfid);
|
||||
return ECORE_INVAL;
|
||||
}
|
||||
|
||||
if (vf_info->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED)) {
|
||||
DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
|
||||
@ -3488,7 +3568,14 @@ ecore_iov_bulletin_set_forced_untagged_default(struct ecore_hwfn *p_hwfn,
|
||||
vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
|
||||
if (!vf_info) {
|
||||
DP_NOTICE(p_hwfn->p_dev, true,
|
||||
"Can not set forced MAC, invalid vfid [%d]\n", vfid);
|
||||
"Can not set untagged default, invalid vfid [%d]\n",
|
||||
vfid);
|
||||
return ECORE_INVAL;
|
||||
}
|
||||
if (vf_info->b_malicious) {
|
||||
DP_NOTICE(p_hwfn->p_dev, false,
|
||||
"Can't set untagged default to malicious VF [%d]\n",
|
||||
vfid);
|
||||
return ECORE_INVAL;
|
||||
}
|
||||
|
||||
@ -3553,6 +3640,12 @@ void ecore_iov_bulletin_set_forced_vlan(struct ecore_hwfn *p_hwfn,
|
||||
vfid);
|
||||
return;
|
||||
}
|
||||
if (vf_info->b_malicious) {
|
||||
DP_NOTICE(p_hwfn->p_dev, false,
|
||||
"Can't set forced vlan to malicious VF [%d]\n",
|
||||
vfid);
|
||||
return;
|
||||
}
|
||||
|
||||
feature = 1 << VLAN_ADDR_FORCED;
|
||||
vf_info->bulletin.p_virt->pvid = pvid;
|
||||
|
@ -97,6 +97,7 @@ struct ecore_vf_info {
|
||||
struct ecore_iov_vf_mbx vf_mbx;
|
||||
enum vf_state state;
|
||||
bool b_init;
|
||||
bool b_malicious;
|
||||
u8 to_disable;
|
||||
|
||||
struct ecore_bulletin bulletin;
|
||||
|
Loading…
Reference in New Issue
Block a user