Skip to content

Commit 8cd8a6b

Browse files
jacob-kelleranguy11
authored andcommitted
ice: move VF overflow message count into struct ice_mbx_vf_info
The ice driver has some logic in ice_vf_mbx.c used to detect potentially malicious VF behavior with regards to overflowing the PF mailbox. This logic currently stores message counts in struct ice_mbx_vf_counter.vf_cntr as an array. This array is allocated during initialization with ice_mbx_init_snapshot. This logic makes sense for SR-IOV where all VFs are allocated at once up front. However, in the future with Scalable IOV this logic will not work. VFs can be added and removed dynamically. We could try to keep the vf_cntr array for the maximum possible number of VFs, but this is a waste of memory. Use the recently introduced struct ice_mbx_vf_info structure to store the message count. Pass a pointer to the mbx_info for a VF instead of using its VF ID. Replace the array of VF message counts with a linked list that tracks all currently active mailbox tracking info structures. Signed-off-by: Jacob Keller <[email protected]> Reviewed-by: Michal Swiatkowski <[email protected]> Tested-by: Marek Szlosek <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent e4eaf89 commit 8cd8a6b

File tree

5 files changed

+69
-140
lines changed

5 files changed

+69
-140
lines changed

drivers/net/ethernet/intel/ice/ice_sriov.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,7 @@ void ice_free_vfs(struct ice_pf *pf)
204204
}
205205

206206
/* clear malicious info since the VF is getting released */
207-
ice_mbx_clear_malvf(&hw->mbx_snapshot, vf->vf_id,
208-
&vf->mbx_info);
207+
list_del(&vf->mbx_info.list_entry);
209208

210209
mutex_unlock(&vf->cfg_lock);
211210
}
@@ -1025,9 +1024,7 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs)
10251024
return -EBUSY;
10261025
}
10271026

1028-
err = ice_mbx_init_snapshot(&pf->hw, num_vfs);
1029-
if (err)
1030-
return err;
1027+
ice_mbx_init_snapshot(&pf->hw);
10311028

10321029
err = ice_pci_sriov_ena(pf, num_vfs);
10331030
if (err) {
@@ -1818,7 +1815,7 @@ ice_is_malicious_vf(struct ice_pf *pf, struct ice_rq_event_info *event,
18181815
mbxdata.async_watermark_val = ICE_MBX_OVERFLOW_WATERMARK;
18191816

18201817
/* check to see if we have a malicious VF */
1821-
status = ice_mbx_vf_state_handler(&pf->hw, &mbxdata, vf_id, &malvf);
1818+
status = ice_mbx_vf_state_handler(&pf->hw, &mbxdata, &vf->mbx_info, &malvf);
18221819
if (status)
18231820
goto out_put_vf;
18241821

drivers/net/ethernet/intel/ice/ice_type.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -784,20 +784,14 @@ struct ice_mbx_snap_buffer_data {
784784
u16 max_num_msgs_mbx;
785785
};
786786

787-
/* Structure to track messages sent by VFs on mailbox:
788-
* 1. vf_cntr: a counter array of VFs to track the number of
789-
* asynchronous messages sent by each VF
790-
* 2. vfcntr_len: number of entries in VF counter array
791-
*/
792-
struct ice_mbx_vf_counter {
793-
u32 *vf_cntr;
794-
u32 vfcntr_len;
795-
};
796-
797787
/* Structure used to track a single VF's messages on the mailbox:
798-
* 1. malicious: whether this VF has been detected as malicious before
788+
* 1. list_entry: linked list entry node
789+
* 2. msg_count: the number of asynchronous messages sent by this VF
790+
* 3. malicious: whether this VF has been detected as malicious before
799791
*/
800792
struct ice_mbx_vf_info {
793+
struct list_head list_entry;
794+
u32 msg_count;
801795
u8 malicious : 1;
802796
};
803797

@@ -806,7 +800,7 @@ struct ice_mbx_vf_info {
806800
*/
807801
struct ice_mbx_snapshot {
808802
struct ice_mbx_snap_buffer_data mbx_buf;
809-
struct ice_mbx_vf_counter mbx_vf;
803+
struct list_head mbx_vf;
810804
};
811805

812806
/* Structure to hold data to be used for capturing or updating a

drivers/net/ethernet/intel/ice/ice_vf_lib.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,7 @@ void ice_reset_all_vfs(struct ice_pf *pf)
496496

497497
/* clear all malicious info if the VFs are getting reset */
498498
ice_for_each_vf(pf, bkt, vf)
499-
ice_mbx_clear_malvf(&hw->mbx_snapshot, vf->vf_id,
500-
&vf->mbx_info);
499+
ice_mbx_clear_malvf(&vf->mbx_info);
501500

502501
/* If VFs have been disabled, there is no need to reset */
503502
if (test_and_set_bit(ICE_VF_DIS, pf->state)) {
@@ -599,12 +598,10 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
599598
struct ice_pf *pf = vf->pf;
600599
struct ice_vsi *vsi;
601600
struct device *dev;
602-
struct ice_hw *hw;
603601
int err = 0;
604602
bool rsd;
605603

606604
dev = ice_pf_to_dev(pf);
607-
hw = &pf->hw;
608605

609606
if (flags & ICE_VF_RESET_NOTIFY)
610607
ice_notify_vf_reset(vf);
@@ -703,7 +700,7 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
703700
ice_eswitch_replay_vf_mac_rule(vf);
704701

705702
/* if the VF has been reset allow it to come up again */
706-
ice_mbx_clear_malvf(&hw->mbx_snapshot, vf->vf_id, &vf->mbx_info);
703+
ice_mbx_clear_malvf(&vf->mbx_info);
707704

708705
out_unlock:
709706
if (flags & ICE_VF_RESET_LOCK)

drivers/net/ethernet/intel/ice/ice_vf_mbx.c

Lines changed: 55 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -93,36 +93,31 @@ u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
9393
*
9494
* 2. When the caller starts processing its mailbox queue in response to an
9595
* interrupt, the structure ice_mbx_snapshot is expected to be cleared before
96-
* the algorithm can be run for the first time for that interrupt. This can be
97-
* done via ice_mbx_reset_snapshot().
96+
* the algorithm can be run for the first time for that interrupt. This
97+
* requires calling ice_mbx_reset_snapshot() as well as calling
98+
* ice_mbx_reset_vf_info() for each VF tracking structure.
9899
*
99100
* 3. For every message read by the caller from the MBX Queue, the caller must
100101
* call the detection algorithm's entry function ice_mbx_vf_state_handler().
101102
* Before every call to ice_mbx_vf_state_handler() the struct ice_mbx_data is
102103
* filled as it is required to be passed to the algorithm.
103104
*
104-
* 4. Every time a message is read from the MBX queue, a VFId is received which
105-
* is passed to the state handler. The boolean output is_malvf of the state
106-
* handler ice_mbx_vf_state_handler() serves as an indicator to the caller
107-
* whether this VF is malicious or not.
105+
* 4. Every time a message is read from the MBX queue, a tracking structure
106+
* for the VF must be passed to the state handler. The boolean output
107+
* report_malvf from ice_mbx_vf_state_handler() serves as an indicator to the
108+
* caller whether it must report this VF as malicious or not.
108109
*
109110
* 5. When a VF is identified to be malicious, the caller can send a message
110-
* to the system administrator. The caller can invoke ice_mbx_report_malvf()
111-
* to help determine if a malicious VF is to be reported or not. This function
112-
* requires the caller to maintain a global bitmap to track all malicious VFs
113-
* and pass that to ice_mbx_report_malvf() along with the VFID which was identified
114-
* to be malicious by ice_mbx_vf_state_handler().
111+
* to the system administrator.
115112
*
116-
* 6. The global bitmap maintained by PF can be cleared completely if PF is in
117-
* reset or the bit corresponding to a VF can be cleared if that VF is in reset.
118-
* When a VF is shut down and brought back up, we assume that the new VF
119-
* brought up is not malicious and hence report it if found malicious.
113+
* 6. The PF is responsible for maintaining the struct ice_mbx_vf_info
114+
* structure for each VF. The PF should clear the VF tracking structure if the
115+
* VF is reset. When a VF is shut down and brought back up, we will then
116+
* assume that the new VF is not malicious and may report it again if we
117+
* detect it again.
120118
*
121119
* 7. The function ice_mbx_reset_snapshot() is called to reset the information
122120
* in ice_mbx_snapshot for every new mailbox interrupt handled.
123-
*
124-
* 8. The memory allocated for variables in ice_mbx_snapshot is de-allocated
125-
* when driver is unloaded.
126121
*/
127122
#define ICE_RQ_DATA_MASK(rq_data) ((rq_data) & PF_MBX_ARQH_ARQH_M)
128123
/* Using the highest value for an unsigned 16-bit value 0xFFFF to indicate that
@@ -132,26 +127,21 @@ u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
132127

133128
/**
134129
* ice_mbx_reset_snapshot - Reset mailbox snapshot structure
135-
* @snap: pointer to mailbox snapshot structure in the ice_hw struct
136-
*
137-
* Reset the mailbox snapshot structure and clear VF counter array.
130+
* @snap: pointer to the mailbox snapshot
138131
*/
139132
static void ice_mbx_reset_snapshot(struct ice_mbx_snapshot *snap)
140133
{
141-
u32 vfcntr_len;
142-
143-
if (!snap || !snap->mbx_vf.vf_cntr)
144-
return;
134+
struct ice_mbx_vf_info *vf_info;
145135

146-
/* Clear VF counters. */
147-
vfcntr_len = snap->mbx_vf.vfcntr_len;
148-
if (vfcntr_len)
149-
memset(snap->mbx_vf.vf_cntr, 0,
150-
(vfcntr_len * sizeof(*snap->mbx_vf.vf_cntr)));
151-
152-
/* Reset mailbox snapshot for a new capture. */
136+
/* Clear mbx_buf in the mailbox snaphot structure and setting the
137+
* mailbox snapshot state to a new capture.
138+
*/
153139
memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf));
154140
snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
141+
142+
/* Reset message counts for all VFs to zero */
143+
list_for_each_entry(vf_info, &snap->mbx_vf, list_entry)
144+
vf_info->msg_count = 0;
155145
}
156146

157147
/**
@@ -195,7 +185,7 @@ ice_mbx_traverse(struct ice_hw *hw,
195185
/**
196186
* ice_mbx_detect_malvf - Detect malicious VF in snapshot
197187
* @hw: pointer to the HW struct
198-
* @vf_id: relative virtual function ID
188+
* @vf_info: mailbox tracking structure for a VF
199189
* @new_state: new algorithm state
200190
* @is_malvf: boolean output to indicate if VF is malicious
201191
*
@@ -204,19 +194,14 @@ ice_mbx_traverse(struct ice_hw *hw,
204194
* the permissible number of messages to send.
205195
*/
206196
static int
207-
ice_mbx_detect_malvf(struct ice_hw *hw, u16 vf_id,
197+
ice_mbx_detect_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info,
208198
enum ice_mbx_snapshot_state *new_state,
209199
bool *is_malvf)
210200
{
211-
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
201+
/* increment the message count for this VF */
202+
vf_info->msg_count++;
212203

213-
if (vf_id >= snap->mbx_vf.vfcntr_len)
214-
return -EIO;
215-
216-
/* increment the message count in the VF array */
217-
snap->mbx_vf.vf_cntr[vf_id]++;
218-
219-
if (snap->mbx_vf.vf_cntr[vf_id] >= ICE_ASYNC_VF_MSG_THRESHOLD)
204+
if (vf_info->msg_count >= ICE_ASYNC_VF_MSG_THRESHOLD)
220205
*is_malvf = true;
221206

222207
/* continue to iterate through the mailbox snapshot */
@@ -229,7 +214,7 @@ ice_mbx_detect_malvf(struct ice_hw *hw, u16 vf_id,
229214
* ice_mbx_vf_state_handler - Handle states of the overflow algorithm
230215
* @hw: pointer to the HW struct
231216
* @mbx_data: pointer to structure containing mailbox data
232-
* @vf_id: relative virtual function (VF) ID
217+
* @vf_info: mailbox tracking structure for the VF in question
233218
* @is_malvf: boolean output to indicate if VF is malicious
234219
*
235220
* The function serves as an entry point for the malicious VF
@@ -250,7 +235,8 @@ ice_mbx_detect_malvf(struct ice_hw *hw, u16 vf_id,
250235
*/
251236
int
252237
ice_mbx_vf_state_handler(struct ice_hw *hw,
253-
struct ice_mbx_data *mbx_data, u16 vf_id,
238+
struct ice_mbx_data *mbx_data,
239+
struct ice_mbx_vf_info *vf_info,
254240
bool *is_malvf)
255241
{
256242
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
@@ -315,7 +301,8 @@ ice_mbx_vf_state_handler(struct ice_hw *hw,
315301
if (snap_buf->num_pending_arq >=
316302
mbx_data->async_watermark_val) {
317303
new_state = ICE_MAL_VF_DETECT_STATE_DETECT;
318-
status = ice_mbx_detect_malvf(hw, vf_id, &new_state, is_malvf);
304+
status = ice_mbx_detect_malvf(hw, vf_info, &new_state,
305+
is_malvf);
319306
} else {
320307
new_state = ICE_MAL_VF_DETECT_STATE_TRAVERSE;
321308
ice_mbx_traverse(hw, &new_state);
@@ -329,7 +316,8 @@ ice_mbx_vf_state_handler(struct ice_hw *hw,
329316

330317
case ICE_MAL_VF_DETECT_STATE_DETECT:
331318
new_state = ICE_MAL_VF_DETECT_STATE_DETECT;
332-
status = ice_mbx_detect_malvf(hw, vf_id, &new_state, is_malvf);
319+
status = ice_mbx_detect_malvf(hw, vf_info, &new_state,
320+
is_malvf);
333321
break;
334322

335323
default:
@@ -367,90 +355,49 @@ ice_mbx_report_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info,
367355
}
368356

369357
/**
370-
* ice_mbx_clear_malvf - Clear VF bitmap and counter for VF ID
371-
* @snap: pointer to the mailbox snapshot structure
372-
* @vf_id: relative virtual function ID of the malicious VF
373-
* @vf_info: mailbox tracking structure for this VF
358+
* ice_mbx_clear_malvf - Clear VF mailbox info
359+
* @vf_info: the mailbox tracking structure for a VF
374360
*
375-
* In case of a VF reset, this function shall be called to clear the VF's
376-
* current mailbox tracking state.
377-
*/
378-
void
379-
ice_mbx_clear_malvf(struct ice_mbx_snapshot *snap, u16 vf_id,
380-
struct ice_mbx_vf_info *vf_info)
361+
* In case of a VF reset, this function shall be called to clear the VF's
362+
* current mailbox tracking state.
363+
*/
364+
void ice_mbx_clear_malvf(struct ice_mbx_vf_info *vf_info)
381365
{
382-
if (WARN_ON(!snap))
383-
return;
384-
385-
/* Ensure VF ID value is not larger than bitmap or VF counter length */
386-
if (WARN_ON(vf_id >= snap->mbx_vf.vfcntr_len))
387-
return;
388-
389366
vf_info->malicious = 0;
390-
391-
/* Clear the VF counter in the mailbox snapshot structure for that VF ID.
392-
* This is to ensure that if a VF is unloaded and a new one brought back
393-
* up with the same VF ID for a snapshot currently in traversal or detect
394-
* state the counter for that VF ID does not increment on top of existing
395-
* values in the mailbox overflow detection algorithm.
396-
*/
397-
snap->mbx_vf.vf_cntr[vf_id] = 0;
367+
vf_info->msg_count = 0;
398368
}
399369

400370
/**
401371
* ice_mbx_init_vf_info - Initialize a new VF mailbox tracking info
402372
* @hw: pointer to the hardware structure
403373
* @vf_info: the mailbox tracking info structure for a VF
404374
*
405-
* Initialize a VF mailbox tracking info structure.
375+
* Initialize a VF mailbox tracking info structure and insert it into the
376+
* snapshot list.
377+
*
378+
* If you remove the VF, you must also delete the associated VF info structure
379+
* from the linked list.
406380
*/
407381
void ice_mbx_init_vf_info(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info)
408382
{
409-
vf_info->malicious = 0;
383+
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
384+
385+
ice_mbx_clear_malvf(vf_info);
386+
list_add(&vf_info->list_entry, &snap->mbx_vf);
410387
}
411388

412389
/**
413-
* ice_mbx_init_snapshot - Initialize mailbox snapshot structure
390+
* ice_mbx_init_snapshot - Initialize mailbox snapshot data
414391
* @hw: pointer to the hardware structure
415-
* @vf_count: number of VFs allocated on a PF
416-
*
417-
* Clear the mailbox snapshot structure and allocate memory
418-
* for the VF counter array based on the number of VFs allocated
419-
* on that PF.
420392
*
421-
* Assumption: This function will assume ice_get_caps() has already been
422-
* called to ensure that the vf_count can be compared against the number
423-
* of VFs supported as defined in the functional capabilities of the device.
393+
* Clear the mailbox snapshot structure and initialize the VF mailbox list.
424394
*/
425-
int ice_mbx_init_snapshot(struct ice_hw *hw, u16 vf_count)
395+
void ice_mbx_init_snapshot(struct ice_hw *hw)
426396
{
427397
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
428398

429-
/* Ensure that the number of VFs allocated is non-zero and
430-
* is not greater than the number of supported VFs defined in
431-
* the functional capabilities of the PF.
432-
*/
433-
if (!vf_count || vf_count > hw->func_caps.num_allocd_vfs)
434-
return -EINVAL;
435-
436-
snap->mbx_vf.vf_cntr = devm_kcalloc(ice_hw_to_dev(hw), vf_count,
437-
sizeof(*snap->mbx_vf.vf_cntr),
438-
GFP_KERNEL);
439-
if (!snap->mbx_vf.vf_cntr)
440-
return -ENOMEM;
441-
442-
/* Setting the VF counter length to the number of allocated
443-
* VFs for given PF's functional capabilities.
444-
*/
445-
snap->mbx_vf.vfcntr_len = vf_count;
446-
447-
/* Clear mbx_buf in the mailbox snaphot structure and setting the
448-
* mailbox snapshot state to a new capture.
449-
*/
450-
memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf));
451-
snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
452-
453-
return 0;
399+
INIT_LIST_HEAD(&snap->mbx_vf);
400+
ice_mbx_reset_snapshot(snap);
454401
}
455402

456403
/**
@@ -463,10 +410,6 @@ void ice_mbx_deinit_snapshot(struct ice_hw *hw)
463410
{
464411
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
465412

466-
/* Free VF counter array and reset VF counter length */
467-
devm_kfree(ice_hw_to_dev(hw), snap->mbx_vf.vf_cntr);
468-
snap->mbx_vf.vfcntr_len = 0;
469-
470413
/* Clear mbx_buf in the mailbox snaphot structure */
471414
memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf));
472415
}

drivers/net/ethernet/intel/ice/ice_vf_mbx.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,10 @@ ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
2121
u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed);
2222
int
2323
ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data,
24-
u16 vf_id, bool *is_mal_vf);
25-
void
26-
ice_mbx_clear_malvf(struct ice_mbx_snapshot *snap, u16 vf_id,
27-
struct ice_mbx_vf_info *vf_info);
24+
struct ice_mbx_vf_info *vf_info, bool *is_mal_vf);
25+
void ice_mbx_clear_malvf(struct ice_mbx_vf_info *vf_info);
2826
void ice_mbx_init_vf_info(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info);
29-
int ice_mbx_init_snapshot(struct ice_hw *hw, u16 vf_count);
27+
void ice_mbx_init_snapshot(struct ice_hw *hw);
3028
void ice_mbx_deinit_snapshot(struct ice_hw *hw);
3129
int
3230
ice_mbx_report_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info,

0 commit comments

Comments
 (0)