On 10/7/2025 9:40 AM, Ertman, David M wrote:
>> -----Original Message-----
>> From: Keller, Jacob E <[email protected]>
>> Sent: Monday, October 6, 2025 3:59 PM
>> To: Ertman, David M <[email protected]>; intel-wired-
>> [email protected]
>> Subject: Re: [Intel-wired-lan] [PATCH iwl-net] ice: Add lport/MAC rules for 
>> PF
>> traffic in bonds
>>
>>
>>
>> On 10/3/2025 9:27 AM, Dave Ertman wrote:
>>> When two E8XX interfaces are placed into a bond, and are correctly
>>> configured for supporting SRIOV traffic over the bonded interfaces,
>>> there is a problem with traffic aimed directly at the bond netdev.  By
>>> conjoining both interfaces onto a single switch black in the NIC, all
>>> unicast and broadcast traffic is being directed to the primary interface's
>>> set of resources no matter which interface is the active/targeting one.
>>>
>>> To fix this, add a set of rules into the switch block that combines both
>>> target MAC address and source logical port to direct packets to the
>>> active/targeted VSI.  This change will not touch traffic directed to SRIOV
>>> VF targets.
>>>
>>> Fixes: ec5a6c5f79ed ("ice: process events created by lag netdev event
>> handler")
>>> Signed-off-by: Dave Ertman <[email protected]>
>>> ---
>>>  drivers/net/ethernet/intel/ice/ice_lag.c | 101 +++++++++++++++++++++++
>>>  drivers/net/ethernet/intel/ice/ice_lag.h |   5 ++
>>>  2 files changed, 106 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c
>> b/drivers/net/ethernet/intel/ice/ice_lag.c
>>> index d2576d606e10..7773d5b9bae9 100644
>>> --- a/drivers/net/ethernet/intel/ice/ice_lag.c
>>> +++ b/drivers/net/ethernet/intel/ice/ice_lag.c
>>> @@ -17,6 +17,7 @@ static const u8 lacp_train_pkt[ICE_TRAIN_PKT_LEN] = {
>> 0, 0, 0, 0, 0, 0,
>>>  static const u8 act_act_train_pkt[ICE_TRAIN_PKT_LEN] = { 0, 0, 0, 0, 0, 0,
>>>                                                      0, 0, 0, 0, 0, 0,
>>>                                                      0, 0, 0, 0 };
>>> +static u8 mac_train_pkt[ICE_TRAIN_PKT_LEN] = { 0 };
>>>
>>
>> Is there any way this static global variable could be either allocated
>> or made part of the LAG structure or something?
>>
>> You're using it as some sort of storage from what I can tell, but I
>> really don't like that its a driver global and open to a lot of
>> potential race conditions.
>>
>> For that matter, its only accessed a couple of times, and each time its
>> used to copy a value into it and then copy that into something else..
>> Can you explain whats going on with that and why it even needs a global
>> variable like this??
>>
>>>  #define ICE_RECIPE_LEN                     64
>>>  #define ICE_LAG_SRIOV_CP_RECIPE            10
>>> @@ -29,6 +30,10 @@ static const u8 ice_lport_rcp[ICE_RECIPE_LEN] = {
>>>     0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
>>>     0x85, 0, 0x16, 0, 0, 0, 0xff, 0xff, 0x07, 0, 0, 0, 0, 0, 0, 0,
>>>     0, 0, 0, 0, 0, 0, 0x30 };
>>> +static const u8 ice_pfmac_rcp[ICE_RECIPE_LEN] = {
>>> +   0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x85, 0, 0x16,
>>> +   0x05, 0x06, 0x07, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff,
>>> +   0xff, 0xff, 0, 0, 0, 0, 0, 0, 0x30 };
>>>
>>>  /**
>>>   * ice_lag_set_primary - set PF LAG state as Primary
>>> @@ -1336,6 +1341,89 @@ ice_lag_reclaim_vf_nodes(struct ice_lag *lag,
>> struct ice_hw *src_hw)
>>>                             ice_lag_reclaim_vf_tc(lag, src_hw, i, tc);
>>>  }
>>>
>>> +/**
>>> + * ice_lag_cfg_pfmac_fltrs
>>> + * @lag: local lag info struct
>>> + * @link: is this a linking action
>>> + *
>>> + * Configure lport/MAC filters for this interfaces PF traffic in the
>>> + * current interfaces SWID
>>> + */
>>> +static void ice_lag_cfg_pfmac_fltrs(struct ice_lag *lag, bool link)
>>> +{
>>> +   u8 lport = lag->pf->hw.port_info->lport;
>>> +   struct ice_sw_rule_lkup_rx_tx *s_rule;
>>> +   struct ice_vsi *vsi = lag->pf->vsi[0];
>>> +   struct ice_hw *hw = &lag->pf->hw;
>>> +   u16 s_rule_sz;
>>> +   u32 act;
>>> +
>>> +   act = ICE_FWD_TO_VSI | ICE_SINGLE_ACT_LAN_ENABLE |
>> ICE_SINGLE_ACT_VALID_BIT |
>>> +           FIELD_PREP(ICE_SINGLE_ACT_VSI_ID_M, vsi->vsi_num);
>>> +
>>> +   s_rule_sz = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule,
>> ICE_TRAIN_PKT_LEN);
>>> +   s_rule = kzalloc(s_rule_sz, GFP_KERNEL);
>>> +   if (!s_rule) {
>>> +           netdev_warn(lag->netdev, "-ENOMEM error configuring
>> PFMAC filters\n");
>>> +           return;
>>> +   }
>>> +
>>> +   if (link) {
>>> +           u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
>>> +
>>> +           /* unicast */
>>> +           ether_addr_copy(mac_train_pkt, lag->upper_netdev-
>>> dev_addr);
>>> +           memcpy(s_rule->hdr_data, mac_train_pkt,
>> ICE_TRAIN_PKT_LEN);
>>
>> Here, you copy dev_addr into it, then you copy that back into
>> s_rule->hdr_data...
>>
>>> +           s_rule->recipe_id = cpu_to_le16(lag->pfmac_recipe);
>>> +           s_rule->src = cpu_to_le16(lport);
>>> +           s_rule->act = cpu_to_le32(act);
>>> +           s_rule->hdr_len = cpu_to_le16(ICE_TRAIN_PKT_LEN);
>>> +           s_rule->hdr.type =
>> cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
>>> +
>>> +           if (ice_aq_sw_rules(hw, s_rule, s_rule_sz, 1,
>>> +                               ice_aqc_opc_add_sw_rules, NULL)) {
>>> +                   netdev_warn(lag->netdev, "Error ADDING Unicast
>> PFMAC rule for aggregate\n");
>>> +                   goto err_pfmac_free;
>>> +           }
>>> +
>>> +           lag->pfmac_unicst_idx = le16_to_cpu(s_rule->index);
>>> +
>>> +           /* broadast */
>>> +           ether_addr_copy(mac_train_pkt, broadcast);
>>> +           memcpy(s_rule->hdr_data, mac_train_pkt,
>> ICE_TRAIN_PKT_LEN);
>>
>> And here, you copy the broadcast into it, and then copy that into the
>> s_rule_hdr_data...
>>
>> But why not just copy directly into the s_rule->hdr_data instead of
>> copying twice? Literally nothing else interacts with mac_train_pkt
>> introduced in this patch, so we needlessly copy, and result in using a
>> value that could be modified by another thread possibly even on another
>> PF since its a global variable...
>>
>> Please fix this.
> 
> 
> Yeah - I think you are right.  I originally wrote this following the pattern 
> already
> Present in the code, but with this packet starting with all zeros there is no 
> need for
> It to be a const.
> 
> Will rewrite this using a local variable.
> 
> DaveE

I still don't understand why you can't just do this:

ether_addr_copy(s_rule->hdr_data, broadcast)

and

ether_addr_copy(s_rule->hdr_data, lag->upper_netdev->dev_addr)

without the extra temporary buffer?

The memcpy is using ICE_TRAIN_PKT_LEN.. is that not the same size as the
dev_addr? Is it because ICE_TRAIN_PKT_LEN is 16 bytes, and you're
copying a bunch of zeros over as well?

But why not just memset and then copy the address in?

memset(s_rule->hdr_data, 0, sizeof(s_rule->hdr_data));
ether_addr_copy(s_rule->hdr_data, lag->upper_netdev->dev_addr);

Thanks,
Jake

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to