@@ -5871,6 +5871,26 @@ static void i40e_verify_eeprom(struct i40e_pf *pf)
58715871 }
58725872}
58735873
5874+ /**
5875+ * i40e_config_bridge_mode - Configure the HW bridge mode
5876+ * @veb: pointer to the bridge instance
5877+ *
5878+ * Configure the loop back mode for the LAN VSI that is downlink to the
5879+ * specified HW bridge instance. It is expected this function is called
5880+ * when a new HW bridge is instantiated.
5881+ **/
5882+ static void i40e_config_bridge_mode (struct i40e_veb * veb )
5883+ {
5884+ struct i40e_pf * pf = veb -> pf ;
5885+
5886+ dev_info (& pf -> pdev -> dev , "enabling bridge mode: %s\n" ,
5887+ veb -> bridge_mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB" );
5888+ if (veb -> bridge_mode & BRIDGE_MODE_VEPA )
5889+ i40e_disable_pf_switch_lb (pf );
5890+ else
5891+ i40e_enable_pf_switch_lb (pf );
5892+ }
5893+
58745894/**
58755895 * i40e_reconstitute_veb - rebuild the VEB and anything connected to it
58765896 * @veb: pointer to the VEB instance
@@ -5917,8 +5937,7 @@ static int i40e_reconstitute_veb(struct i40e_veb *veb)
59175937 if (ret )
59185938 goto end_reconstitute ;
59195939
5920- /* Enable LB mode for the main VSI now that it is on a VEB */
5921- i40e_enable_pf_switch_lb (pf );
5940+ i40e_config_bridge_mode (veb );
59225941
59235942 /* create the remaining VSIs attached to this VEB */
59245943 for (v = 0 ; v < pf -> num_alloc_vsi ; v ++ ) {
@@ -7737,6 +7756,118 @@ static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
77377756 return err ;
77387757}
77397758
7759+ #ifdef HAVE_BRIDGE_ATTRIBS
7760+ /**
7761+ * i40e_ndo_bridge_setlink - Set the hardware bridge mode
7762+ * @dev: the netdev being configured
7763+ * @nlh: RTNL message
7764+ *
7765+ * Inserts a new hardware bridge if not already created and
7766+ * enables the bridging mode requested (VEB or VEPA). If the
7767+ * hardware bridge has already been inserted and the request
7768+ * is to change the mode then that requires a PF reset to
7769+ * allow rebuild of the components with required hardware
7770+ * bridge mode enabled.
7771+ **/
7772+ static int i40e_ndo_bridge_setlink (struct net_device * dev ,
7773+ struct nlmsghdr * nlh )
7774+ {
7775+ struct i40e_netdev_priv * np = netdev_priv (dev );
7776+ struct i40e_vsi * vsi = np -> vsi ;
7777+ struct i40e_pf * pf = vsi -> back ;
7778+ struct i40e_veb * veb = NULL ;
7779+ struct nlattr * attr , * br_spec ;
7780+ int i , rem ;
7781+
7782+ /* Only for PF VSI for now */
7783+ if (vsi -> seid != pf -> vsi [pf -> lan_vsi ]-> seid )
7784+ return - EOPNOTSUPP ;
7785+
7786+ /* Find the HW bridge for PF VSI */
7787+ for (i = 0 ; i < I40E_MAX_VEB && !veb ; i ++ ) {
7788+ if (pf -> veb [i ] && pf -> veb [i ]-> seid == vsi -> uplink_seid )
7789+ veb = pf -> veb [i ];
7790+ }
7791+
7792+ br_spec = nlmsg_find_attr (nlh , sizeof (struct ifinfomsg ), IFLA_AF_SPEC );
7793+
7794+ nla_for_each_nested (attr , br_spec , rem ) {
7795+ __u16 mode ;
7796+
7797+ if (nla_type (attr ) != IFLA_BRIDGE_MODE )
7798+ continue ;
7799+
7800+ mode = nla_get_u16 (attr );
7801+ if ((mode != BRIDGE_MODE_VEPA ) &&
7802+ (mode != BRIDGE_MODE_VEB ))
7803+ return - EINVAL ;
7804+
7805+ /* Insert a new HW bridge */
7806+ if (!veb ) {
7807+ veb = i40e_veb_setup (pf , 0 , vsi -> uplink_seid , vsi -> seid ,
7808+ vsi -> tc_config .enabled_tc );
7809+ if (veb ) {
7810+ veb -> bridge_mode = mode ;
7811+ i40e_config_bridge_mode (veb );
7812+ } else {
7813+ /* No Bridge HW offload available */
7814+ return - ENOENT ;
7815+ }
7816+ break ;
7817+ } else if (mode != veb -> bridge_mode ) {
7818+ /* Existing HW bridge but different mode needs reset */
7819+ veb -> bridge_mode = mode ;
7820+ i40e_do_reset (pf , (1 << __I40E_PF_RESET_REQUESTED ));
7821+ break ;
7822+ }
7823+ }
7824+
7825+ return 0 ;
7826+ }
7827+
7828+ /**
7829+ * i40e_ndo_bridge_getlink - Get the hardware bridge mode
7830+ * @skb: skb buff
7831+ * @pid: process id
7832+ * @seq: RTNL message seq #
7833+ * @dev: the netdev being configured
7834+ * @filter_mask: unused
7835+ *
7836+ * Return the mode in which the hardware bridge is operating in
7837+ * i.e VEB or VEPA.
7838+ **/
7839+ #ifdef HAVE_BRIDGE_FILTER
7840+ static int i40e_ndo_bridge_getlink (struct sk_buff * skb , u32 pid , u32 seq ,
7841+ struct net_device * dev ,
7842+ u32 __always_unused filter_mask )
7843+ #else
7844+ static int i40e_ndo_bridge_getlink (struct sk_buff * skb , u32 pid , u32 seq ,
7845+ struct net_device * dev )
7846+ #endif /* HAVE_BRIDGE_FILTER */
7847+ {
7848+ struct i40e_netdev_priv * np = netdev_priv (dev );
7849+ struct i40e_vsi * vsi = np -> vsi ;
7850+ struct i40e_pf * pf = vsi -> back ;
7851+ struct i40e_veb * veb = NULL ;
7852+ int i ;
7853+
7854+ /* Only for PF VSI for now */
7855+ if (vsi -> seid != pf -> vsi [pf -> lan_vsi ]-> seid )
7856+ return - EOPNOTSUPP ;
7857+
7858+ /* Find the HW bridge for the PF VSI */
7859+ for (i = 0 ; i < I40E_MAX_VEB && !veb ; i ++ ) {
7860+ if (pf -> veb [i ] && pf -> veb [i ]-> seid == vsi -> uplink_seid )
7861+ veb = pf -> veb [i ];
7862+ }
7863+
7864+ if (!veb )
7865+ return 0 ;
7866+
7867+ return ndo_dflt_bridge_getlink (skb , pid , seq , dev , veb -> bridge_mode );
7868+ }
7869+ #endif /* HAVE_BRIDGE_ATTRIBS */
7870+
77407871const struct net_device_ops i40e_netdev_ops = {
77417872 .ndo_open = i40e_open ,
77427873 .ndo_stop = i40e_close ,
@@ -7771,6 +7902,10 @@ const struct net_device_ops i40e_netdev_ops = {
77717902#endif
77727903 .ndo_get_phys_port_id = i40e_get_phys_port_id ,
77737904 .ndo_fdb_add = i40e_ndo_fdb_add ,
7905+ #ifdef HAVE_BRIDGE_ATTRIBS
7906+ .ndo_bridge_getlink = i40e_ndo_bridge_getlink ,
7907+ .ndo_bridge_setlink = i40e_ndo_bridge_setlink ,
7908+ #endif /* HAVE_BRIDGE_ATTRIBS */
77747909};
77757910
77767911/**
@@ -7882,6 +8017,30 @@ static void i40e_vsi_delete(struct i40e_vsi *vsi)
78828017 i40e_aq_delete_element (& vsi -> back -> hw , vsi -> seid , NULL );
78838018}
78848019
8020+ /**
8021+ * i40e_is_vsi_uplink_mode_veb - Check if the VSI's uplink bridge mode is VEB
8022+ * @vsi: the VSI being queried
8023+ *
8024+ * Returns 1 if HW bridge mode is VEB and return 0 in case of VEPA mode
8025+ **/
8026+ int i40e_is_vsi_uplink_mode_veb (struct i40e_vsi * vsi )
8027+ {
8028+ struct i40e_veb * veb ;
8029+ struct i40e_pf * pf = vsi -> back ;
8030+
8031+ /* Uplink is not a bridge so default to VEB */
8032+ if (vsi -> veb_idx == I40E_NO_VEB )
8033+ return 1 ;
8034+
8035+ veb = pf -> veb [vsi -> veb_idx ];
8036+ /* Uplink is a bridge in VEPA mode */
8037+ if (veb && (veb -> bridge_mode & BRIDGE_MODE_VEPA ))
8038+ return 0 ;
8039+
8040+ /* Uplink is a bridge in VEB mode */
8041+ return 1 ;
8042+ }
8043+
78858044/**
78868045 * i40e_add_vsi - Add a VSI to the switch
78878046 * @vsi: the VSI being configured
@@ -7969,10 +8128,12 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
79698128 ctxt .uplink_seid = vsi -> uplink_seid ;
79708129 ctxt .connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL ;
79718130 ctxt .flags = I40E_AQ_VSI_TYPE_PF ;
7972- ctxt .info .valid_sections |=
8131+ if (i40e_is_vsi_uplink_mode_veb (vsi )) {
8132+ ctxt .info .valid_sections |=
79738133 cpu_to_le16 (I40E_AQ_VSI_PROP_SWITCH_VALID );
7974- ctxt .info .switch_id =
8134+ ctxt .info .switch_id =
79758135 cpu_to_le16 (I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB );
8136+ }
79768137 i40e_vsi_setup_queue_map (vsi , & ctxt , enabled_tc , true);
79778138 break ;
79788139
@@ -7983,13 +8144,15 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
79838144 ctxt .connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL ;
79848145 ctxt .flags = I40E_AQ_VSI_TYPE_VMDQ2 ;
79858146
7986- ctxt .info .valid_sections |= cpu_to_le16 (I40E_AQ_VSI_PROP_SWITCH_VALID );
7987-
79888147 /* This VSI is connected to VEB so the switch_id
79898148 * should be set to zero by default.
79908149 */
7991- ctxt .info .switch_id = 0 ;
7992- ctxt .info .switch_id |= cpu_to_le16 (I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB );
8150+ if (i40e_is_vsi_uplink_mode_veb (vsi )) {
8151+ ctxt .info .valid_sections |=
8152+ cpu_to_le16 (I40E_AQ_VSI_PROP_SWITCH_VALID );
8153+ ctxt .info .switch_id =
8154+ cpu_to_le16 (I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB );
8155+ }
79938156
79948157 /* Setup the VSI tx/rx queue map for TC0 only for now */
79958158 i40e_vsi_setup_queue_map (vsi , & ctxt , enabled_tc , true);
@@ -8002,12 +8165,15 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
80028165 ctxt .connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL ;
80038166 ctxt .flags = I40E_AQ_VSI_TYPE_VF ;
80048167
8005- ctxt .info .valid_sections |= cpu_to_le16 (I40E_AQ_VSI_PROP_SWITCH_VALID );
8006-
80078168 /* This VSI is connected to VEB so the switch_id
80088169 * should be set to zero by default.
80098170 */
8010- ctxt .info .switch_id = cpu_to_le16 (I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB );
8171+ if (i40e_is_vsi_uplink_mode_veb (vsi )) {
8172+ ctxt .info .valid_sections |=
8173+ cpu_to_le16 (I40E_AQ_VSI_PROP_SWITCH_VALID );
8174+ ctxt .info .switch_id =
8175+ cpu_to_le16 (I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB );
8176+ }
80118177
80128178 ctxt .info .valid_sections |= cpu_to_le16 (I40E_AQ_VSI_PROP_VLAN_VALID );
80138179 ctxt .info .port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL ;
@@ -8365,7 +8531,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
83658531 __func__ );
83668532 return NULL ;
83678533 }
8368- i40e_enable_pf_switch_lb ( pf );
8534+ i40e_config_bridge_mode ( veb );
83698535 }
83708536 for (i = 0 ; i < I40E_MAX_VEB && !veb ; i ++ ) {
83718537 if (pf -> veb [i ] && pf -> veb [i ]-> seid == vsi -> uplink_seid )
0 commit comments