Skip to content
This repository has been archived by the owner on Nov 21, 2022. It is now read-only.

Commit

Permalink
ice: switchdev slow path
Browse files Browse the repository at this point in the history
Slow path means allowing packet to go from uplink to representor
and from representor to correct VF on Rx site and from VF to
representor and to uplink on Tx site.

To accomplish this driver, has to set correct Tx descriptor. When
packet is sent from representor to VF, destination should be
set to VF VSI. When packet is sent from uplink port destination
should be uplink to bypass switch infrastructure and send packet
outside.

On Rx site driver should check source VSI field from Rx descriptor
and based on that forward packed to correct netdev. To allow
this there is a target netdevs table in control plane VSI
struct.

Co-developed-by: Michal Swiatkowski <[email protected]>
Signed-off-by: Michal Swiatkowski <[email protected]>
Signed-off-by: Grzegorz Nitka <[email protected]>
Tested-by: Sandeep Penigalapati <[email protected]>
Signed-off-by: Tony Nguyen <[email protected]>
  • Loading branch information
gnitka authored and anguy11 committed Oct 7, 2021
1 parent b3be918 commit f5396b8
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 1 deletion.
80 changes: 80 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_eswitch.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,58 @@ void ice_eswitch_update_repr(struct ice_vsi *vsi)
}
}

/**
* ice_eswitch_port_start_xmit - callback for packets transmit
* @skb: send buffer
* @netdev: network interface device structure
*
* Returns NETDEV_TX_OK if sent, else an error code
*/
netdev_tx_t
ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct ice_netdev_priv *np;
struct ice_repr *repr;
struct ice_vsi *vsi;

np = netdev_priv(netdev);
vsi = np->vsi;

if (ice_is_reset_in_progress(vsi->back->state))
return NETDEV_TX_BUSY;

repr = ice_netdev_to_repr(netdev);
skb_dst_drop(skb);
dst_hold((struct dst_entry *)repr->dst);
skb_dst_set(skb, (struct dst_entry *)repr->dst);
skb->queue_mapping = repr->vf->vf_id;

return ice_start_xmit(skb, netdev);
}

/**
* ice_eswitch_set_target_vsi - set switchdev context in Tx context descriptor
* @skb: pointer to send buffer
* @off: pointer to offload struct
*/
void
ice_eswitch_set_target_vsi(struct sk_buff *skb,
struct ice_tx_offload_params *off)
{
struct metadata_dst *dst = skb_metadata_dst(skb);
u64 cd_cmd, dst_vsi;

if (!dst) {
cd_cmd = ICE_TX_CTX_DESC_SWTCH_UPLINK << ICE_TXD_CTX_QW1_CMD_S;
off->cd_qw1 |= (cd_cmd | ICE_TX_DESC_DTYPE_CTX);
} else {
cd_cmd = ICE_TX_CTX_DESC_SWTCH_VSI << ICE_TXD_CTX_QW1_CMD_S;
dst_vsi = ((u64)dst->u.port_info.port_id <<
ICE_TXD_CTX_QW1_VSI_S) & ICE_TXD_CTX_QW1_VSI_M;
off->cd_qw1 = cd_cmd | dst_vsi | ICE_TX_DESC_DTYPE_CTX;
}
}

/**
* ice_eswitch_release_env - clear switchdev HW filters
* @pf: pointer to PF struct
Expand Down Expand Up @@ -448,6 +500,34 @@ ice_eswitch_mode_set(struct devlink *devlink, u16 mode,
return 0;
}

/**
* ice_eswitch_get_target_netdev - return port representor netdev
* @rx_ring: pointer to Rx ring
* @rx_desc: pointer to Rx descriptor
*
* When working in switchdev mode context (when control VSI is used), this
* function returns netdev of appropriate port representor. For non-switchdev
* context, regular netdev associated with Rx ring is returned.
*/
struct net_device *
ice_eswitch_get_target_netdev(struct ice_ring *rx_ring,
union ice_32b_rx_flex_desc *rx_desc)
{
struct ice_32b_rx_flex_desc_nic_2 *desc;
struct ice_vsi *vsi = rx_ring->vsi;
struct ice_vsi *control_vsi;
u16 target_vsi_id;

control_vsi = vsi->back->switchdev.control_vsi;
if (vsi != control_vsi)
return rx_ring->netdev;

desc = (struct ice_32b_rx_flex_desc_nic_2 *)rx_desc;
target_vsi_id = le16_to_cpu(desc->src_vsi);

return vsi->target_netdevs[target_vsi_id];
}

/**
* ice_eswitch_mode_get - get current eswitch mode
* @devlink: pointer to devlink structure
Expand Down
26 changes: 26 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_eswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,24 @@ bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf);
void ice_eswitch_update_repr(struct ice_vsi *vsi);

void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf);

struct net_device *
ice_eswitch_get_target_netdev(struct ice_ring *rx_ring,
union ice_32b_rx_flex_desc *rx_desc);

void ice_eswitch_set_target_vsi(struct sk_buff *skb,
struct ice_tx_offload_params *off);
netdev_tx_t
ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev);
#else /* CONFIG_ICE_SWITCHDEV */
static inline void ice_eswitch_release(struct ice_pf *pf) { }

static inline void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf) { }

static inline void
ice_eswitch_set_target_vsi(struct sk_buff *skb,
struct ice_tx_offload_params *off) { }

static inline void ice_eswitch_update_repr(struct ice_vsi *vsi) { }

static inline int ice_eswitch_configure(struct ice_pf *pf)
Expand Down Expand Up @@ -53,5 +66,18 @@ static inline bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf)
{
return false;
}

static inline struct net_device *
ice_eswitch_get_target_netdev(struct ice_ring *rx_ring,
union ice_32b_rx_flex_desc *rx_desc)
{
return rx_ring->netdev;
}

static inline netdev_tx_t
ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
return NETDEV_TX_BUSY;
}
#endif /* CONFIG_ICE_SWITCHDEV */
#endif /* _ICE_ESWITCH_H_ */
43 changes: 43 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,46 @@ struct ice_32b_rx_flex_desc_nic {
} flex_ts;
};

/* Rx Flex Descriptor NIC Profile
* RxDID Profile ID 6
* Flex-field 0: RSS hash lower 16-bits
* Flex-field 1: RSS hash upper 16-bits
* Flex-field 2: Flow ID lower 16-bits
* Flex-field 3: Source VSI
* Flex-field 4: reserved, VLAN ID taken from L2Tag
*/
struct ice_32b_rx_flex_desc_nic_2 {
/* Qword 0 */
u8 rxdid;
u8 mir_id_umb_cast;
__le16 ptype_flexi_flags0;
__le16 pkt_len;
__le16 hdr_len_sph_flex_flags1;

/* Qword 1 */
__le16 status_error0;
__le16 l2tag1;
__le32 rss_hash;

/* Qword 2 */
__le16 status_error1;
u8 flexi_flags2;
u8 ts_low;
__le16 l2tag2_1st;
__le16 l2tag2_2nd;

/* Qword 3 */
__le16 flow_id;
__le16 src_vsi;
union {
struct {
__le16 rsvd;
__le16 flow_id_ipv6;
} flex;
__le32 ts_high;
} flex_ts;
};

/* Receive Flex Descriptor profile IDs: There are a total
* of 64 profiles where profile IDs 0/1 are for legacy; and
* profiles 2-63 are flex profiles that can be programmed
Expand Down Expand Up @@ -529,6 +569,9 @@ struct ice_tx_ctx_desc {

#define ICE_TXD_CTX_QW1_MSS_S 50

#define ICE_TXD_CTX_QW1_VSI_S 50
#define ICE_TXD_CTX_QW1_VSI_M (0x3FFULL << ICE_TXD_CTX_QW1_VSI_S)

enum ice_tx_ctx_desc_cmd_bits {
ICE_TX_CTX_DESC_TSO = 0x01,
ICE_TX_CTX_DESC_TSYN = 0x02,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice_repr.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ static const struct net_device_ops ice_repr_netdev_ops = {
.ndo_get_phys_port_name = ice_repr_get_phys_port_name,
.ndo_open = ice_repr_open,
.ndo_stop = ice_repr_stop,
.ndo_start_xmit = ice_eswitch_port_start_xmit,
.ndo_get_devlink_port = ice_repr_get_devlink_port,
};

Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "ice_trace.h"
#include "ice_dcb_lib.h"
#include "ice_xsk.h"
#include "ice_eswitch.h"

#define ICE_RX_HDR_SIZE 256

Expand Down Expand Up @@ -2246,6 +2247,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring)
ICE_TXD_CTX_QW1_CMD_S);

ice_tstamp(tx_ring, skb, first, &offload);
if (ice_is_switchdev_running(vsi->back))
ice_eswitch_set_target_vsi(skb, &offload);

if (offload.cd_qw1 & ICE_TX_DESC_DTYPE_CTX) {
struct ice_tx_ctx_desc *cdesc;
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/ethernet/intel/ice/ice_txrx_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* Copyright (c) 2019, Intel Corporation. */

#include "ice_txrx_lib.h"
#include "ice_eswitch.h"

/**
* ice_release_rx_desc - Store the new tail and head values
Expand Down Expand Up @@ -185,7 +186,8 @@ ice_process_skb_fields(struct ice_ring *rx_ring,
ice_rx_hash(rx_ring, rx_desc, skb, ptype);

/* modifies the skb - consumes the enet header */
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
skb->protocol = eth_type_trans(skb, ice_eswitch_get_target_netdev
(rx_ring, rx_desc));

ice_rx_csum(rx_ring, skb, rx_desc, ptype);

Expand Down

0 comments on commit f5396b8

Please sign in to comment.