1. 06 5月, 2022 1 次提交
  2. 27 4月, 2022 1 次提交
    • J
      ice: fix use-after-free when deinitializing mailbox snapshot · b668f4cd
      Jacob Keller 提交于
      During ice_sriov_configure, if num_vfs is 0, we are being asked by the
      kernel to remove all VFs.
      
      The driver first de-initializes the snapshot before freeing all the VFs.
      This results in a use-after-free BUG detected by KASAN. The bug occurs
      because the snapshot can still be accessed until all VFs are removed.
      
      Fix this by freeing all the VFs first before calling
      ice_mbx_deinit_snapshot.
      
      [  +0.032591] ==================================================================
      [  +0.000021] BUG: KASAN: use-after-free in ice_mbx_vf_state_handler+0x1c3/0x410 [ice]
      [  +0.000315] Write of size 28 at addr ffff889908eb6f28 by task kworker/55:2/1530996
      
      [  +0.000029] CPU: 55 PID: 1530996 Comm: kworker/55:2 Kdump: loaded Tainted: G S        I       5.17.0-dirty #1
      [  +0.000022] Hardware name: Dell Inc. PowerEdge R740/0923K0, BIOS 1.6.13 12/17/2018
      [  +0.000013] Workqueue: ice ice_service_task [ice]
      [  +0.000279] Call Trace:
      [  +0.000012]  <TASK>
      [  +0.000011]  dump_stack_lvl+0x33/0x42
      [  +0.000030]  print_report.cold.13+0xb2/0x6b3
      [  +0.000028]  ? ice_mbx_vf_state_handler+0x1c3/0x410 [ice]
      [  +0.000295]  kasan_report+0xa5/0x120
      [  +0.000026]  ? __switch_to_asm+0x21/0x70
      [  +0.000024]  ? ice_mbx_vf_state_handler+0x1c3/0x410 [ice]
      [  +0.000298]  kasan_check_range+0x183/0x1e0
      [  +0.000019]  memset+0x1f/0x40
      [  +0.000018]  ice_mbx_vf_state_handler+0x1c3/0x410 [ice]
      [  +0.000304]  ? ice_conv_link_speed_to_virtchnl+0x160/0x160 [ice]
      [  +0.000297]  ? ice_vsi_dis_spoofchk+0x40/0x40 [ice]
      [  +0.000305]  ice_is_malicious_vf+0x1aa/0x250 [ice]
      [  +0.000303]  ? ice_restore_all_vfs_msi_state+0x160/0x160 [ice]
      [  +0.000297]  ? __mutex_unlock_slowpath.isra.15+0x410/0x410
      [  +0.000022]  ? ice_debug_cq+0xb7/0x230 [ice]
      [  +0.000273]  ? __kasan_slab_alloc+0x2f/0x90
      [  +0.000022]  ? memset+0x1f/0x40
      [  +0.000017]  ? do_raw_spin_lock+0x119/0x1d0
      [  +0.000022]  ? rwlock_bug.part.2+0x60/0x60
      [  +0.000024]  __ice_clean_ctrlq+0x3a6/0xd60 [ice]
      [  +0.000273]  ? newidle_balance+0x5b1/0x700
      [  +0.000026]  ? ice_print_link_msg+0x2f0/0x2f0 [ice]
      [  +0.000271]  ? update_cfs_group+0x1b/0x140
      [  +0.000018]  ? load_balance+0x1260/0x1260
      [  +0.000022]  ? ice_process_vflr_event+0x27/0x130 [ice]
      [  +0.000301]  ice_service_task+0x136e/0x1470 [ice]
      [  +0.000281]  process_one_work+0x3b4/0x6c0
      [  +0.000030]  worker_thread+0x65/0x660
      [  +0.000023]  ? __kthread_parkme+0xe4/0x100
      [  +0.000021]  ? process_one_work+0x6c0/0x6c0
      [  +0.000020]  kthread+0x179/0x1b0
      [  +0.000018]  ? kthread_complete_and_exit+0x20/0x20
      [  +0.000022]  ret_from_fork+0x22/0x30
      [  +0.000026]  </TASK>
      
      [  +0.000018] Allocated by task 10742:
      [  +0.000013]  kasan_save_stack+0x1c/0x40
      [  +0.000018]  __kasan_kmalloc+0x84/0xa0
      [  +0.000016]  kmem_cache_alloc_trace+0x16c/0x2e0
      [  +0.000015]  intel_iommu_probe_device+0xeb/0x860
      [  +0.000015]  __iommu_probe_device+0x9a/0x2f0
      [  +0.000016]  iommu_probe_device+0x43/0x270
      [  +0.000015]  iommu_bus_notifier+0xa7/0xd0
      [  +0.000015]  blocking_notifier_call_chain+0x90/0xc0
      [  +0.000017]  device_add+0x5f3/0xd70
      [  +0.000014]  pci_device_add+0x404/0xa40
      [  +0.000015]  pci_iov_add_virtfn+0x3b0/0x550
      [  +0.000016]  sriov_enable+0x3bb/0x600
      [  +0.000013]  ice_ena_vfs+0x113/0xa79 [ice]
      [  +0.000293]  ice_sriov_configure.cold.17+0x21/0xe0 [ice]
      [  +0.000291]  sriov_numvfs_store+0x160/0x200
      [  +0.000015]  kernfs_fop_write_iter+0x1db/0x270
      [  +0.000018]  new_sync_write+0x21d/0x330
      [  +0.000013]  vfs_write+0x376/0x410
      [  +0.000013]  ksys_write+0xba/0x150
      [  +0.000012]  do_syscall_64+0x3a/0x80
      [  +0.000012]  entry_SYSCALL_64_after_hwframe+0x44/0xae
      
      [  +0.000028] Freed by task 10742:
      [  +0.000011]  kasan_save_stack+0x1c/0x40
      [  +0.000015]  kasan_set_track+0x21/0x30
      [  +0.000016]  kasan_set_free_info+0x20/0x30
      [  +0.000012]  __kasan_slab_free+0x104/0x170
      [  +0.000016]  kfree+0x9b/0x470
      [  +0.000013]  devres_destroy+0x1c/0x20
      [  +0.000015]  devm_kfree+0x33/0x40
      [  +0.000012]  ice_mbx_deinit_snapshot+0x39/0x70 [ice]
      [  +0.000295]  ice_sriov_configure+0xb0/0x260 [ice]
      [  +0.000295]  sriov_numvfs_store+0x1bc/0x200
      [  +0.000015]  kernfs_fop_write_iter+0x1db/0x270
      [  +0.000016]  new_sync_write+0x21d/0x330
      [  +0.000012]  vfs_write+0x376/0x410
      [  +0.000012]  ksys_write+0xba/0x150
      [  +0.000012]  do_syscall_64+0x3a/0x80
      [  +0.000012]  entry_SYSCALL_64_after_hwframe+0x44/0xae
      
      [  +0.000024] Last potentially related work creation:
      [  +0.000010]  kasan_save_stack+0x1c/0x40
      [  +0.000016]  __kasan_record_aux_stack+0x98/0xa0
      [  +0.000013]  insert_work+0x34/0x160
      [  +0.000015]  __queue_work+0x20e/0x650
      [  +0.000016]  queue_work_on+0x4c/0x60
      [  +0.000015]  nf_nat_masq_schedule+0x297/0x2e0 [nf_nat]
      [  +0.000034]  masq_device_event+0x5a/0x60 [nf_nat]
      [  +0.000031]  raw_notifier_call_chain+0x5f/0x80
      [  +0.000017]  dev_close_many+0x1d6/0x2c0
      [  +0.000015]  unregister_netdevice_many+0x4e3/0xa30
      [  +0.000015]  unregister_netdevice_queue+0x192/0x1d0
      [  +0.000014]  iavf_remove+0x8f9/0x930 [iavf]
      [  +0.000058]  pci_device_remove+0x65/0x110
      [  +0.000015]  device_release_driver_internal+0xf8/0x190
      [  +0.000017]  pci_stop_bus_device+0xb5/0xf0
      [  +0.000014]  pci_stop_and_remove_bus_device+0xe/0x20
      [  +0.000016]  pci_iov_remove_virtfn+0x19c/0x230
      [  +0.000015]  sriov_disable+0x4f/0x170
      [  +0.000014]  ice_free_vfs+0x9a/0x490 [ice]
      [  +0.000306]  ice_sriov_configure+0xb8/0x260 [ice]
      [  +0.000294]  sriov_numvfs_store+0x1bc/0x200
      [  +0.000015]  kernfs_fop_write_iter+0x1db/0x270
      [  +0.000016]  new_sync_write+0x21d/0x330
      [  +0.000012]  vfs_write+0x376/0x410
      [  +0.000012]  ksys_write+0xba/0x150
      [  +0.000012]  do_syscall_64+0x3a/0x80
      [  +0.000012]  entry_SYSCALL_64_after_hwframe+0x44/0xae
      
      [  +0.000025] The buggy address belongs to the object at ffff889908eb6f00
                     which belongs to the cache kmalloc-96 of size 96
      [  +0.000016] The buggy address is located 40 bytes inside of
                     96-byte region [ffff889908eb6f00, ffff889908eb6f60)
      
      [  +0.000026] The buggy address belongs to the physical page:
      [  +0.000010] page:00000000b7e99a2e refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1908eb6
      [  +0.000016] flags: 0x57ffffc0000200(slab|node=1|zone=2|lastcpupid=0x1fffff)
      [  +0.000024] raw: 0057ffffc0000200 ffffea0069d9fd80 dead000000000002 ffff88810004c780
      [  +0.000015] raw: 0000000000000000 0000000000200020 00000001ffffffff 0000000000000000
      [  +0.000009] page dumped because: kasan: bad access detected
      
      [  +0.000016] Memory state around the buggy address:
      [  +0.000012]  ffff889908eb6e00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
      [  +0.000014]  ffff889908eb6e80: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
      [  +0.000014] >ffff889908eb6f00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
      [  +0.000011]                                   ^
      [  +0.000013]  ffff889908eb6f80: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
      [  +0.000013]  ffff889908eb7000: fa fb fb fb fb fb fb fb fc fc fc fc fa fb fb fb
      [  +0.000012] ==================================================================
      
      Fixes: 0891c896 ("ice: warn about potentially malicious VFs")
      Reported-by: NSlawomir Laba <slawomirx.laba@intel.com>
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      b668f4cd
  3. 16 3月, 2022 10 次提交
  4. 15 3月, 2022 9 次提交
    • J
      ice: use ice_is_vf_trusted helper function · 1261691d
      Jacob Keller 提交于
      The ice_vc_cfg_promiscuous_mode_msg function directly checks
      ICE_VIRTCHNL_VF_CAP_PRIVILEGE, instead of using the existing helper
      function ice_is_vf_trusted. Switch this to use the helper function so
      that all trusted checks are consistent. This aids in any potential
      future refactor by ensuring consistent code.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      1261691d
    • J
      ice: log an error message when eswitch fails to configure · 2b369448
      Jacob Keller 提交于
      When ice_eswitch_configure fails, print an error message to make it more
      obvious why VF initialization did not succeed.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NSandeep Penigalapati <sandeep.penigalapati@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      2b369448
    • J
      ice: cleanup error logging for ice_ena_vfs · 94ab2488
      Jacob Keller 提交于
      The ice_ena_vfs function and some of its sub-functions like
      ice_set_per_vf_res use a "if (<function>) { <print error> ; <exit> }"
      flow. This flow discards specialized errors reported by the called
      function.
      
      This style is generally not preferred as it makes tracing error sources
      more difficult. It also means we cannot log the actual error received
      properly.
      
      Refactor several calls in the ice_ena_vfs function that do this to catch
      the error in the 'ret' variable. Report this in the messages, and then
      return the more precise error value.
      
      Doing this reveals that ice_set_per_vf_res returns -EINVAL or -EIO in
      places where -ENOSPC makes more sense. Fix these calls up to return the
      more appropriate value.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      94ab2488
    • J
      ice: move ice_set_vf_port_vlan near other .ndo ops · 346f7aa3
      Jacob Keller 提交于
      The ice_set_vf_port_vlan function is located in ice_sriov.c very far
      away from the other .ndo operations that it is similar to. Move this so
      that its located near the other .ndo operation definitions.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      346f7aa3
    • J
      ice: refactor spoofchk control code in ice_sriov.c · a8ea6d86
      Jacob Keller 提交于
      The API to control the VSI spoof checking for a VF VSI has three
      functions: enable, disable, and set. The set function takes the VSI and
      the VF and decides whether to call enable or disable based on the
      vf->spoofchk field.
      
      In some flows, vf->spoofchk is not yet set, such as the function used to
      control the setting for a VF. (vf->spoofchk is only updated after a
      success).
      
      Simplify this API by refactoring ice_vf_set_spoofchk_cfg to be
      "ice_vsi_apply_spoofchk" which takes the boolean and allows all callers
      to avoid having to determine whether to call enable or disable
      themselves.
      
      This matches the expected callers better, and will prevent the need to
      export more than one function when this code must be called from another
      file.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      a8ea6d86
    • J
      ice: rename ICE_MAX_VF_COUNT to avoid confusion · dc36796e
      Jacob Keller 提交于
      The ICE_MAX_VF_COUNT field is defined in ice_sriov.h. This count is true
      for SR-IOV but will not be true for all VF implementations, such as when
      the ice driver supports Scalable IOV.
      
      Rename this definition to clearly indicate ICE_MAX_SRIOV_VFS.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      dc36796e
    • J
      ice: remove unused definitions from ice_sriov.h · 00a57e29
      Jacob Keller 提交于
      A few more macros exist in ice_sriov.h which are not used anywhere.
      These can be safely removed. Note that ICE_VIRTCHNL_VF_CAP_L2 capability
      is set but never checked anywhere in the driver. Thus it is also safe to
      remove.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      00a57e29
    • J
      ice: convert vf->vc_ops to a const pointer · a7e11710
      Jacob Keller 提交于
      The vc_ops structure is used to allow different handlers for virtchnl
      commands when the driver is in representor mode. The current
      implementation uses a copy of the ops table in each VF, and modifies
      this copy dynamically.
      
      The usual practice in kernel code is to store the ops table in a
      constant structure and point to different versions. This has a number of
      advantages:
      
        1. Reduced memory usage. Each VF merely points to the correct table,
           so they're able to re-use the same constant lookup table in memory.
        2. Consistency. It becomes more difficult to accidentally update or
           edit only one op call. Instead, the code switches to the correct
           able by a single pointer write. In general this is atomic, either
           the pointer is updated or its not.
        3. Code Layout. The VF structure can store a pointer to the table
           without needing to have the full structure definition defined prior
           to the VF structure definition. This will aid in future refactoring
           of code by allowing the VF pointer to be kept in ice_vf_lib.h while
           the virtchnl ops table can be maintained in ice_virtchnl.h
      
      There is one major downside in the case of the vc_ops structure. Most of
      the operations in the table are the same between the two current
      implementations. This can appear to lead to duplication since each
      implementation must now fill in the complete table. It could make
      spotting the differences in the representor mode more challenging.
      Unfortunately, methods to make this less error prone either add
      complexity overhead (macros using CPP token concatenation) or don't work
      on all compilers we support (constant initializer from another constant
      structure).
      
      The cost of maintaining two structures does not out weigh the benefits
      of the constant table model.
      
      While we're making these changes, go ahead and rename the structure and
      implementations with "virtchnl" instead of "vc_vf_". This will more
      closely align with the planned file renaming, and avoid similar names when
      we later introduce a "vf ops" table for separating Scalable IOV and
      Single Root IOV implementations.
      
      Leave the accessor/assignment functions in order to avoid issues with
      compiling with options disabled. The interface makes it easier to handle
      when CONFIG_PCI_IOV is disabled in the kernel.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NSandeep Penigalapati <sandeep.penigalapati@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      a7e11710
    • J
      ice: rename ice_virtchnl_pf.c to ice_sriov.c · 0deb0bf7
      Jacob Keller 提交于
      The ice_virtchnl_pf.c and ice_virtchnl_pf.h files are where most of the
      code for implementing Single Root IOV virtualization resides. This code
      includes support for bringing up and tearing down VFs, hooks into the
      kernel SR-IOV netdev operations, and for handling virtchnl messages from
      VFs.
      
      In the future, we plan to support Scalable IOV in addition to Single
      Root IOV as an alternative virtualization scheme. This implementation
      will re-use some but not all of the code in ice_virtchnl_pf.c
      
      To prepare for this future, we want to refactor and split up the code in
      ice_virtchnl_pf.c into the following scheme:
      
       * ice_vf_lib.[ch]
      
         Basic VF structures and accessors. This is where scheme-independent
         code will reside.
      
       * ice_virtchnl.[ch]
      
         Virtchnl message handling. This is where the bulk of the logic for
         processing messages from VFs using the virtchnl messaging scheme will
         reside. This is separated from ice_vf_lib.c because it is distinct
         and has a bulk of the processing code.
      
       * ice_sriov.[ch]
      
         Single Root IOV implementation, including initialization and the
         routines for interacting with SR-IOV based netdev operations.
      
       * (future) ice_siov.[ch]
      
         Scalable IOV implementation.
      
      As a first step, lets assume that all of the code in
      ice_virtchnl_pf.[ch] is for Single Root IOV. Rename this file to
      ice_sriov.c and its header to ice_sriov.h
      
      Future changes will further split out the code in these files following
      the plan outlined here.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      0deb0bf7
  5. 09 3月, 2022 1 次提交
    • J
      ice: stop disabling VFs due to PF error responses · 79498d5a
      Jacob Keller 提交于
      The ice_vc_send_msg_to_vf function has logic to detect "failure"
      responses being sent to a VF. If a VF is sent more than
      ICE_DFLT_NUM_INVAL_MSGS_ALLOWED then the VF is marked as disabled.
      Almost identical logic also existed in the i40e driver.
      
      This logic was added to the ice driver in commit 1071a835 ("ice:
      Implement virtchnl commands for AVF support") which itself copied from
      the i40e implementation in commit 5c3c48ac ("i40e: implement virtual
      device interface").
      
      Neither commit provides a proper explanation or justification of the
      check. In fact, later commits to i40e changed the logic to allow
      bypassing the check in some specific instances.
      
      The "logic" for this seems to be that error responses somehow indicate a
      malicious VF. This is not really true. The PF might be sending an error
      for any number of reasons such as lack of resources, etc.
      
      Additionally, this causes the PF to log an info message for every failed
      VF response which may confuse users, and can spam the kernel log.
      
      This behavior is not documented as part of any requirement for our
      products and other operating system drivers such as the FreeBSD
      implementation of our drivers do not include this type of check.
      
      In fact, the change from dev_err to dev_info in i40e commit 18b7af57
      ("i40e: Lower some message levels") explains that these messages
      typically don't actually indicate a real issue. It is quite likely that
      a user who hits this in practice will be very confused as the VF will be
      disabled without an obvious way to recover.
      
      We already have robust malicious driver detection logic using actual
      hardware detection mechanisms that detect and prevent invalid device
      usage. Remove the logic since its not a documented requirement and the
      behavior is not intuitive.
      
      Fixes: 1071a835 ("ice: Implement virtchnl commands for AVF support")
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      79498d5a
  6. 04 3月, 2022 10 次提交
    • J
      ice: convert VF storage to hash table with krefs and RCU · 3d5985a1
      Jacob Keller 提交于
      The ice driver stores VF structures in a simple array which is allocated
      once at the time of VF creation. The VF structures are then accessed
      from the array by their VF ID. The ID must be between 0 and the number
      of allocated VFs.
      
      Multiple threads can access this table:
      
       * .ndo operations such as .ndo_get_vf_cfg or .ndo_set_vf_trust
       * interrupts, such as due to messages from the VF using the virtchnl
         communication
       * processing such as device reset
       * commands to add or remove VFs
      
      The current implementation does not keep track of when all threads are
      done operating on a VF and can potentially result in use-after-free
      issues caused by one thread accessing a VF structure after it has been
      released when removing VFs. Some of these are prevented with various
      state flags and checks.
      
      In addition, this structure is quite static and does not support a
      planned future where virtualization can be more dynamic. As we begin to
      look at supporting Scalable IOV with the ice driver (as opposed to just
      supporting Single Root IOV), this structure is not sufficient.
      
      In the future, VFs will be able to be added and removed individually and
      dynamically.
      
      To allow for this, and to better protect against a whole class of
      use-after-free bugs, replace the VF storage with a combination of a hash
      table and krefs to reference track all of the accesses to VFs through
      the hash table.
      
      A hash table still allows efficient look up of the VF given its ID, but
      also allows adding and removing VFs. It does not require contiguous VF
      IDs.
      
      The use of krefs allows the cleanup of the VF memory to be delayed until
      after all threads have released their reference (by calling ice_put_vf).
      
      To prevent corruption of the hash table, a combination of RCU and the
      mutex table_lock are used. Addition and removal from the hash table use
      the RCU-aware hash macros. This allows simple read-only look ups that
      iterate to locate a single VF can be fast using RCU. Accesses which
      modify the hash table, or which can't take RCU because they sleep, will
      hold the mutex lock.
      
      By using this design, we have a stronger guarantee that the VF structure
      can't be released until after all threads are finished operating on it.
      We also pave the way for the more dynamic Scalable IOV implementation in
      the future.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      3d5985a1
    • J
      ice: introduce VF accessor functions · fb916db1
      Jacob Keller 提交于
      Before we switch the VF data structure storage mechanism to a hash,
      introduce new accessor functions to define the new interface.
      
      * ice_get_vf_by_id is a function used to obtain a reference to a VF from
        the table based on its VF ID
      * ice_has_vfs is used to quickly check if any VFs are configured
      * ice_get_num_vfs is used to get an exact count of how many VFs are
        configured
      
      We can drop the old ice_validate_vf_id function, since every caller was
      just going to immediately access the VF table to get a reference
      anyways. This way we simply use the single ice_get_vf_by_id to both
      validate the VF ID is within range and that there exists a VF with that
      ID.
      
      This change enables us to more easily convert the codebase to the hash
      table since most callers now properly use the interface.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      fb916db1
    • J
      ice: factor VF variables to separate structure · 000773c0
      Jacob Keller 提交于
      We maintain a number of values for VFs within the ice_pf structure. This
      includes the VF table, the number of allocated VFs, the maximum number
      of supported SR-IOV VFs, the number of queue pairs per VF, the number of
      MSI-X vectors per VF, and a bitmap of the VFs with detected MDD events.
      
      We're about to add a few more variables to this list. Clean this up
      first by extracting these members out into a new ice_vfs structure
      defined in ice_virtchnl_pf.h
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      000773c0
    • J
      ice: convert ice_for_each_vf to include VF entry iterator · c4c2c7db
      Jacob Keller 提交于
      The ice_for_each_vf macro is intended to be used to loop over all VFs.
      The current implementation relies on an iterator that is the index into
      the VF array in the PF structure. This forces all users to perform a
      look up themselves.
      
      This abstraction forces a lot of duplicate work on callers and leaks the
      interface implementation to the caller. Replace this with an
      implementation that includes the VF pointer the primary iterator. This
      version simplifies callers which just want to iterate over every VF, as
      they no longer need to perform their own lookup.
      
      The "i" iterator value is replaced with a new unsigned int "bkt"
      parameter, as this will match the necessary interface for replacing
      the VF array with a hash table. For now, the bkt is the VF ID, but in
      the future it will simply be the hash bucket index. Document that it
      should not be treated as a VF ID.
      
      This change aims to simplify switching from the array to a hash table. I
      considered alternative implementations such as an xarray but decided
      that the hash table was the simplest and most suitable implementation. I
      also looked at methods to hide the bkt iterator entirely, but I couldn't
      come up with a feasible solution that worked for hash table iterators.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      c4c2c7db
    • J
      ice: use ice_for_each_vf for iteration during removal · 19281e86
      Jacob Keller 提交于
      When removing VFs, the driver takes a weird approach of assigning
      pf->num_alloc_vfs to 0 before iterating over the VFs using a temporary
      variable.
      
      This logic has been in the driver for a long time, and seems to have
      been carried forward from i40e.
      
      We want to refactor the way VFs are stored, and iterating over the data
      structure without the ice_for_each_vf interface impedes this work.
      
      The logic relies on implicitly using the num_alloc_vfs as a sort of
      "safe guard" for accessing VF data.
      
      While this sort of guard makes sense for Single Root IOV where all VFs
      are added at once, the data structures don't work for VFs which can be
      added and removed dynamically. We also have a separate state flag,
      ICE_VF_DEINIT_IN_PROGRESS which is a stronger protection against
      concurrent removal and access.
      
      Avoid the custom tmp iteration and replace it with the standard
      ice_for_each_vf iterator. Delay the assignment of num_alloc_vfs until
      after this loop finishes.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      19281e86
    • J
      ice: remove checks in ice_vc_send_msg_to_vf · 59e1f857
      Jacob Keller 提交于
      The ice_vc_send_msg_to_vf function is used by the PF to send a response
      to a VF. This function has overzealous checks to ensure its not passed a
      NULL VF pointer and to ensure that the passed in struct ice_vf has a
      valid vf_id sub-member.
      
      These checks have existed since commit 1071a835 ("ice: Implement
      virtchnl commands for AVF support") and function as simple sanity
      checks.
      
      We are planning to refactor the ice driver to use a hash table along
      with appropriate locks in a future refactor. This change will modify how
      the ice_validate_vf_id function works. Instead of a simple >= check to
      ensure the VF ID is between some range, it will check the hash table to
      see if the specified VF ID is actually in the table. This requires that
      the function properly lock the table to prevent race conditions.
      
      The checks may seem ok at first glance, but they don't really provide
      much benefit.
      
      In order for ice_vc_send_msg_to_vf to have these checks fail, the
      callers must either (1) pass NULL as the VF, (2) construct an invalid VF
      pointer manually, or (3) be using a VF pointer which becomes invalid
      after they obtain it properly using ice_get_vf_by_id.
      
      For (1), a cursory glance over callers of ice_vc_send_msg_to_vf can show
      that in most cases the functions already operate assuming their VF
      pointer is valid, such as by derferencing vf->pf or other members.
      
      They obtain the VF pointer by accessing the VF array using the VF ID,
      which can never produce a NULL value (since its a simple address
      operation on the array it will not be NULL.
      
      The sole exception for (1) is that ice_vc_process_vf_msg will forward a
      NULL VF pointer to this function as part of its goto error handler
      logic. This requires some minor cleanup to simply exit immediately when
      an invalid VF ID is detected (Rather than use the same error flow as
      the rest of the function).
      
      For (2), it is unexpected for a flow to construct a VF pointer manually
      instead of accessing the VF array. Defending against this is likely to
      just hide bad programming.
      
      For (3), it is definitely true that VF pointers could become invalid,
      for example if a thread is processing a VF message while the VF gets
      removed. However, the correct solution is not to add additional checks
      like this which do not guarantee to prevent the race. Instead we plan to
      solve the root of the problem by preventing the possibility entirely.
      
      This solution will require the change to a hash table with proper
      locking and reference counts of the VF structures. When this is done,
      ice_validate_vf_id will require locking of the hash table. This will be
      problematic because all of the callers of ice_vc_send_msg_to_vf will
      already have to take the lock to obtain the VF pointer anyways. With a
      mutex, this leads to a double lock that could hang the kernel thread.
      
      Avoid this by removing the checks which don't provide much value, so
      that we can safely add the necessary protections properly.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      59e1f857
    • J
      ice: move VFLR acknowledge during ice_free_vfs · 44efe75f
      Jacob Keller 提交于
      After removing all VFs, the driver clears the VFLR indication for VFs.
      This has been in ice since the beginning of SR-IOV support in the ice
      driver.
      
      The implementation was copied from i40e, and the motivation for the VFLR
      indication clearing is described in the commit f7414531 ("i40e:
      acknowledge VFLR when disabling SR-IOV")
      
      The commit explains that we need to clear the VFLR indication because
      the virtual function undergoes a VFLR event. If we don't indicate that
      it is complete it can cause an issue when VFs are re-enabled due to
      a "phantom" VFLR.
      
      The register block read was added under a pci_vfs_assigned check
      originally. This was done because we added the check after calling
      pci_disable_sriov. This was later moved to disable SRIOV earlier in the
      flow so that the VF drivers could be torn down before we removed
      functionality.
      
      Move the VFLR acknowledge into the main loop that tears down VF
      resources. This avoids using the tmp value for iterating over VFs
      multiple times. The result will make it easier to refactor the VF array
      in a future change.
      
      It's possible we might want to modify this flow to also stop checking
      pci_vfs_assigned. However, it seems reasonable to keep this change: we
      should only clear the VFLR if we actually disabled SR-IOV.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      44efe75f
    • J
      ice: move clear_malvf call in ice_free_vfs · 294627a6
      Jacob Keller 提交于
      The ice_mbx_clear_malvf function is used to clear the indication and
      count of how many times a VF was detected as malicious. During
      ice_free_vfs, we use this function to ensure that all removed VFs are
      reset to a clean state.
      
      The call currently is done at the end of ice_free_vfs() using a tmp
      value to iterate over all of the entries in the bitmap.
      
      This separate iteration using tmp is problematic for a planned refactor
      of the VF array data structure. To avoid this, lets move the call
      slightly higher into the function inside the loop where we teardown all
      of the VFs. This avoids one use of the tmp value used for iteration.
      We'll fix the other user in a future change.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      294627a6
    • J
      ice: pass num_vfs to ice_set_per_vf_res() · cd0f4f3b
      Jacob Keller 提交于
      We are planning to replace the simple array structure tracking VFs with
      a hash table. This change will also remove the "num_alloc_vfs" variable.
      
      Instead, new access functions to use the hash table as the source of
      truth will be introduced. These will generally be equivalent to existing
      checks, except during VF initialization.
      
      Specifically, ice_set_per_vf_res() cannot use the hash table as it will
      be operating prior to VF structures being inserted into the hash table.
      
      Instead of using pf->num_alloc_vfs, simply pass the num_vfs value in
      from the caller.
      
      Note that a sub-function of ice_set_per_vf_res, ice_determine_res, also
      implicitly depends on pf->num_alloc_vfs. Replace ice_determine_res with
      a simpler inline implementation based on rounddown_pow_of_two. Note that
      we must explicitly check that the argument is non-zero since it does not
      play well with zero as a value.
      
      Instead of using the function and while loop, simply calculate the
      number of queues we have available by dividing by num_vfs. Check if the
      desired queues are available. If not, round down to the nearest power of
      2 that fits within our available queues.
      
      This matches the behavior of ice_determine_res but is easier to follow
      as simple in-line logic. Remove ice_determine_res entirely.
      
      With this change, we no longer depend on the pf->num_alloc_vfs during
      the initialization phase of VFs. This will allow us to safely remove it
      in a future planned refactor of the VF data structures.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      cd0f4f3b
    • J
      ice: store VF pointer instead of VF ID · b03d519d
      Jacob Keller 提交于
      The VSI structure contains a vf_id field used to associate a VSI with a
      VF. This is used mainly for ICE_VSI_VF as well as partially for
      ICE_VSI_CTRL associated with the VFs.
      
      This API was designed with the idea that VFs are stored in a simple
      array that was expected to be static throughout most of the driver's
      life.
      
      We plan on refactoring VF storage in a few key ways:
      
        1) converting from a simple static array to a hash table
        2) using krefs to track VF references obtained from the hash table
        3) use RCU to delay release of VF memory until after all references
           are dropped
      
      This is motivated by the goal to ensure that the lifetime of VF
      structures is accounted for, and prevent various use-after-free bugs.
      
      With the existing vsi->vf_id, the reference tracking for VFs would
      become somewhat convoluted, because each VSI maintains a vf_id field
      which will then require performing a look up. This means all these flows
      will require reference tracking and proper usage of rcu_read_lock, etc.
      
      We know that the VF VSI will always be backed by a valid VF structure,
      because the VSI is created during VF initialization and removed before
      the VF is destroyed. Rely on this and store a reference to the VF in the
      VSI structure instead of storing a VF ID. This will simplify the usage
      and avoid the need to perform lookups on the hash table in the future.
      
      For ICE_VSI_VF, it is expected that vsi->vf is always non-NULL after
      ice_vsi_alloc succeeds. Because of this, use WARN_ON when checking if a
      vsi->vf pointer is valid when dealing with VF VSIs. This will aid in
      debugging code which violates this assumption and avoid more disastrous
      panics.
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      b03d519d
  7. 19 2月, 2022 1 次提交
    • J
      ice: fix concurrent reset and removal of VFs · fadead80
      Jacob Keller 提交于
      Commit c503e632 ("ice: Stop processing VF messages during teardown")
      introduced a driver state flag, ICE_VF_DEINIT_IN_PROGRESS, which is
      intended to prevent some issues with concurrently handling messages from
      VFs while tearing down the VFs.
      
      This change was motivated by crashes caused while tearing down and
      bringing up VFs in rapid succession.
      
      It turns out that the fix actually introduces issues with the VF driver
      caused because the PF no longer responds to any messages sent by the VF
      during its .remove routine. This results in the VF potentially removing
      its DMA memory before the PF has shut down the device queues.
      
      Additionally, the fix doesn't actually resolve concurrency issues within
      the ice driver. It is possible for a VF to initiate a reset just prior
      to the ice driver removing VFs. This can result in the remove task
      concurrently operating while the VF is being reset. This results in
      similar memory corruption and panics purportedly fixed by that commit.
      
      Fix this concurrency at its root by protecting both the reset and
      removal flows using the existing VF cfg_lock. This ensures that we
      cannot remove the VF while any outstanding critical tasks such as a
      virtchnl message or a reset are occurring.
      
      This locking change also fixes the root cause originally fixed by commit
      c503e632 ("ice: Stop processing VF messages during teardown"), so we
      can simply revert it.
      
      Note that I kept these two changes together because simply reverting the
      original commit alone would leave the driver vulnerable to worse race
      conditions.
      
      Fixes: c503e632 ("ice: Stop processing VF messages during teardown")
      Signed-off-by: NJacob Keller <jacob.e.keller@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      fadead80
  8. 10 2月, 2022 7 次提交
    • B
      ice: Add ability for PF admin to enable VF VLAN pruning · f1da5a08
      Brett Creeley 提交于
      VFs by default are able to see all tagged traffic regardless of trust
      and VLAN filters. Based on legacy devices (i.e. ixgbe, i40e), customers
      expect VFs to receive all VLAN tagged traffic with a matching
      destination MAC.
      
      Add an ethtool private flag 'vf-vlan-pruning' and set the default to
      off so VFs will receive all VLAN traffic directed towards them. When
      the flag is turned on, VF will only be able to receive untagged
      traffic or traffic with VLAN tags it has created interfaces for.
      
      Also, the flag cannot be changed while any VFs are allocated. This was
      done to simplify the implementation. So, if this flag is needed, then
      the PF admin must enable it. If the user tries to enable the flag while
      VFs are active, then print an unsupported message with the
      vf-vlan-pruning flag included. In case multiple flags were specified, this
      makes it clear to the user which flag failed.
      Signed-off-by: NBrett Creeley <brett.creeley@intel.com>
      Tested-by: NGurucharan G <gurucharanx.g@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      f1da5a08
    • B
      ice: Add support for 802.1ad port VLANs VF · cbc8b564
      Brett Creeley 提交于
      Currently there is only support for 802.1Q port VLANs on SR-IOV VFs. Add
      support to also allow 802.1ad port VLANs when double VLAN mode is
      enabled.
      Signed-off-by: NBrett Creeley <brett.creeley@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      cbc8b564
    • B
      ice: Add support for VIRTCHNL_VF_OFFLOAD_VLAN_V2 · cc71de8f
      Brett Creeley 提交于
      Add support for the VF driver to be able to request
      VIRTCHNL_VF_OFFLOAD_VLAN_V2, negotiate its VLAN capabilities via
      VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS, add/delete VLAN filters, and
      enable/disable VLAN offloads.
      
      VFs supporting VIRTCHNL_OFFLOAD_VLAN_V2 will be able to use the
      following virtchnl opcodes:
      
      VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS
      VIRTCHNL_OP_ADD_VLAN_V2
      VIRTCHNL_OP_DEL_VLAN_V2
      VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2
      VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2
      VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2
      VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2
      
      Legacy VF drivers may expect the initial VLAN stripping settings to be
      configured by the PF, so the PF initializes VLAN stripping based on the
      VIRTCHNL_OP_GET_VF_RESOURCES opcode. However, with VLAN support via
      VIRTCHNL_VF_OFFLOAD_VLAN_V2, this function is only expected to be used
      for VFs that only support VIRTCHNL_VF_OFFLOAD_VLAN, which will only
      be supported when a port VLAN is configured. Update the function
      based on the new expectations. Also, change the message when the PF
      can't enable/disable VLAN stripping to a dev_dbg() as this isn't fatal.
      
      When a VF isn't in a port VLAN and it only supports
      VIRTCHNL_VF_OFFLOAD_VLAN when Double VLAN Mode (DVM) is enabled, then
      the PF needs to reject the VIRTCHNL_VF_OFFLOAD_VLAN capability and
      configure the VF in software only VLAN mode. To do this add the new
      function ice_vf_vsi_cfg_legacy_vlan_mode(), which updates the VF's
      inner and outer ice_vsi_vlan_ops functions and sets up software only
      VLAN mode.
      Signed-off-by: NBrett Creeley <brett.creeley@intel.com>
      Tested-by: NKonrad Jankowski <konrad0.jankowski@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      cc71de8f
    • B
      ice: Add outer_vlan_ops and VSI specific VLAN ops implementations · c31af68a
      Brett Creeley 提交于
      Add a new outer_vlan_ops member to the ice_vsi structure as outer VLAN
      ops are only available when the device is in Double VLAN Mode (DVM).
      Depending on the VSI type, the requirements for what operations to
      use/allow differ.
      
      By default all VSI's have unsupported inner and outer VSI VLAN ops. This
      implementation was chosen to prevent unexpected crashes due to null
      pointer dereferences. Instead, if a VSI calls an unsupported op, it will
      just return -EOPNOTSUPP.
      
      Add implementations to support modifying outer VLAN fields for VSI
      context. This includes the ability to modify VLAN stripping, insertion,
      and the port VLAN based on the outer VLAN handling fields of the VSI
      context.
      
      These functions should only ever be used if DVM is enabled because that
      means the firmware supports the outer VLAN fields in the VSI context. If
      the device is in DVM, then always use the outer_vlan_ops, else use the
      vlan_ops since the device is in Single VLAN Mode (SVM).
      
      Also, move adding the untagged VLAN 0 filter from ice_vsi_setup() to
      ice_vsi_vlan_setup() as the latter function is specific to the PF and
      all other VSI types that need an untagged VLAN 0 filter already do this
      in their specific flows. Without this change, Flow Director is failing
      to initialize because it does not implement any VSI VLAN ops.
      Signed-off-by: NBrett Creeley <brett.creeley@intel.com>
      Tested-by: NGurucharan G <gurucharanx.g@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      c31af68a
    • B
      ice: Use the proto argument for VLAN ops · 2bfefa2d
      Brett Creeley 提交于
      Currently the proto argument is unused. This is because the driver only
      supports 802.1Q VLAN filtering. This policy is enforced via netdev
      features that the driver sets up when configuring the netdev, so the
      proto argument won't ever be anything other than 802.1Q. However, this
      will allow for future iterations of the driver to seemlessly support
      802.1ad filtering. Begin using the proto argument and extend the related
      structures to support its use.
      Signed-off-by: NBrett Creeley <brett.creeley@intel.com>
      Tested-by: NGurucharan G <gurucharanx.g@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      2bfefa2d
    • B
      ice: Refactor vf->port_vlan_info to use ice_vlan · a19d7f7f
      Brett Creeley 提交于
      The current vf->port_vlan_info variable is a packed u16 that contains
      the port VLAN ID and QoS/prio value. This is fine, but changes are
      incoming that allow for an 802.1ad port VLAN. Add flexibility by
      changing the vf->port_vlan_info member to be an ice_vlan structure.
      Signed-off-by: NBrett Creeley <brett.creeley@intel.com>
      Tested-by: NGurucharan G <gurucharanx.g@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      a19d7f7f
    • B
      ice: Introduce ice_vlan struct · fb05ba12
      Brett Creeley 提交于
      Add a new struct for VLAN related information. Currently this holds
      VLAN ID and priority values, but will be expanded to hold TPID value.
      This reduces the changes necessary if any other values are added in
      future. Remove the action argument from these calls as it's always
      ICE_FWD_VSI.
      Signed-off-by: NBrett Creeley <brett.creeley@intel.com>
      Tested-by: NGurucharan G <gurucharanx.g@intel.com>
      Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
      fb05ba12