On 12/7/2023 5:53 PM, Brett Creeley wrote:
>
>
> On 11/20/2023 6:51 PM, Yahui Cao wrote:
>> Caution: This message originated from an External Source. Use proper caution
>> when opening attachments, clicking links, or responding.
>>
>>
>> From: Lingyu Liu <lingyu....@intel.com>
>>
>> Save the virtual channel messages sent by VF on the source side during
>> runtime. The logged virtchnl messages will be transferred and loaded
>> into the device on the destination side during the device resume stage.
>>
>> For the feature which can not be migrated yet, it must be disabled or
>> blocked to prevent from being abused by VF. Otherwise, it may introduce
>> functional and security issue. Mask unsupported VF capability flags in
>> the VF-PF negotiaion stage.
>
> s/negotiaion/negotiation/
>
>>
>> Signed-off-by: Lingyu Liu <lingyu....@intel.com>
>> Signed-off-by: Yahui Cao <yahui....@intel.com>
>> ---
>> .../net/ethernet/intel/ice/ice_migration.c | 167 ++++++++++++++++++
>> .../intel/ice/ice_migration_private.h | 17 ++
>> drivers/net/ethernet/intel/ice/ice_vf_lib.h | 5 +
>> drivers/net/ethernet/intel/ice/ice_virtchnl.c | 31 ++++
>> 4 files changed, 220 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/intel/ice/ice_migration.c
>> b/drivers/net/ethernet/intel/ice/ice_migration.c
>> index 2b9b5a2ce367..18ec4ec7d147 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_migration.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_migration.c
>> @@ -3,6 +3,17 @@
>>
>> #include "ice.h"
>>
>> +struct ice_migration_virtchnl_msg_slot {
>> + u32 opcode;
>> + u16 msg_len;
>> + char msg_buffer[];
>> +};
>> +
>> +struct ice_migration_virtchnl_msg_listnode {
>> + struct list_head node;
>> + struct ice_migration_virtchnl_msg_slot msg_slot;
>> +};
>> +
>> /**
>> * ice_migration_get_pf - Get ice PF structure pointer by pdev
>> * @pdev: pointer to ice vfio pci VF pdev structure
>> @@ -22,6 +33,9 @@ EXPORT_SYMBOL(ice_migration_get_pf);
>> void ice_migration_init_vf(struct ice_vf *vf)
>> {
>> vf->migration_enabled = true;
>> + INIT_LIST_HEAD(&vf->virtchnl_msg_list);
>> + vf->virtchnl_msg_num = 0;
>> + vf->virtchnl_msg_size = 0;
>> }
>>
>> /**
>> @@ -30,10 +44,24 @@ void ice_migration_init_vf(struct ice_vf *vf)
>> */
>> void ice_migration_uninit_vf(struct ice_vf *vf)
>> {
>> + struct ice_migration_virtchnl_msg_listnode *msg_listnode;
>> + struct ice_migration_virtchnl_msg_listnode *dtmp;
>> +
>> if (!vf->migration_enabled)
>> return;
>>
>> vf->migration_enabled = false;
>> +
>> + if (list_empty(&vf->virtchnl_msg_list))
>> + return;
>> + list_for_each_entry_safe(msg_listnode, dtmp,
>> + &vf->virtchnl_msg_list,
>> + node) {
>> + list_del(&msg_listnode->node);
>> + kfree(msg_listnode);
>> + }
>> + vf->virtchnl_msg_num = 0;
>> + vf->virtchnl_msg_size = 0;
>> }
>>
>> /**
>> @@ -80,3 +108,142 @@ void ice_migration_uninit_dev(struct ice_pf *pf, int
>> vf_id)
>> ice_put_vf(vf);
>> }
>> EXPORT_SYMBOL(ice_migration_uninit_dev);
>> +
>> +/**
>> + * ice_migration_is_loggable_msg - is this message loggable or not
>> + * @v_opcode: virtchnl message operation code
>> + *
>> + * Return true if this message logging is supported, otherwise return false
>> + */
>> +static inline bool ice_migration_is_loggable_msg(u32 v_opcode)
>> +{
>> + switch (v_opcode) {
>> + case VIRTCHNL_OP_VERSION:
>> + case VIRTCHNL_OP_GET_VF_RESOURCES:
>> + case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
>> + case VIRTCHNL_OP_CONFIG_IRQ_MAP:
>> + case VIRTCHNL_OP_ADD_ETH_ADDR:
>> + case VIRTCHNL_OP_DEL_ETH_ADDR:
>> + case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
>> + case VIRTCHNL_OP_ENABLE_QUEUES:
>> + case VIRTCHNL_OP_DISABLE_QUEUES:
>> + case VIRTCHNL_OP_ADD_VLAN:
>> + case VIRTCHNL_OP_DEL_VLAN:
>> + case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
>> + case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
>> + case VIRTCHNL_OP_CONFIG_RSS_KEY:
>> + case VIRTCHNL_OP_CONFIG_RSS_LUT:
>> + case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS:
>> + return true;
>> + default:
>> + return false;
>> + }
>> +}
>> +
>> +/**
>> + * ice_migration_log_vf_msg - Log request message from VF
>> + * @vf: pointer to the VF structure
>> + * @event: pointer to the AQ event
>> + *
>> + * Log VF message for later device state loading during live migration
>> + *
>> + * Return 0 for success, negative for error
>> + */
>> +int ice_migration_log_vf_msg(struct ice_vf *vf,
>> + struct ice_rq_event_info *event)
>> +{
>> + struct ice_migration_virtchnl_msg_listnode *msg_listnode;
>> + u32 v_opcode = le32_to_cpu(event->desc.cookie_high);
>> + struct device *dev = ice_pf_to_dev(vf->pf);
>> + u16 msglen = event->msg_len;
>> + u8 *msg = event->msg_buf;
>> +
>> + if (!ice_migration_is_loggable_msg(v_opcode))
>> + return 0;
>> +
>> + if (vf->virtchnl_msg_num >= VIRTCHNL_MSG_MAX) {
>> + dev_warn(dev, "VF %d has maximum number virtual channel
>> commands\n",
>> + vf->vf_id);
>> + return -ENOMEM;
>> + }
>> +
>> + msg_listnode = (struct ice_migration_virtchnl_msg_listnode *)
>> + kzalloc(struct_size(msg_listnode,
>> + msg_slot.msg_buffer,
>> + msglen),
>> + GFP_KERNEL);
>> + if (!msg_listnode) {
>> + dev_err(dev, "VF %d failed to allocate memory for msg
>> listnode\n",
>> + vf->vf_id);
>> + return -ENOMEM;
>> + }
>> + dev_dbg(dev, "VF %d save virtual channel command, op code: %d, len:
>> %d\n",
>> + vf->vf_id, v_opcode, msglen);
>> + msg_listnode->msg_slot.opcode = v_opcode;
>> + msg_listnode->msg_slot.msg_len = msglen;
>> + memcpy(msg_listnode->msg_slot.msg_buffer, msg, msglen);
>
> It seems like this can still be abused. What if the VM/VF user sends
> hundreds of thousands of ADD_ADDR/DEL_ADDR, ADD_VLAN/DEL_VLAN,
> PROMISCUOUS, ENABLE_VLAN_STRIPPING/DISABLE_VLAN_STRIPPING, RSS_LUT,
> RSS_KEY, etc.?
>
> Shouldn't you only maintain one copy for each key/value when it makes
> sense? For example, you don't need multiple RSS_LUT and RSS_KEY messages
> logged as just the most recent one is needed.
>
> What if multiple promiscuous messages are sent? Do you need to save them
> all or just the most recent?
>
> What if you have an ADD_ADDR/DEL_ADDR for the same address? Do you need
> to save both of those messages? Seems like when you get a DEL_ADDR you
> should search for the associated ADD_ADDR and just remove it. Same
> comment applies for ADD_VLAN/DEL_VLAN.
>
I'll likely be looking to refactor this to use a new internal
representation of the VF state instead of a list of virtchnl messages.