Commit 8416814f authored by Jesper Dangaard Brouer's avatar Jesper Dangaard Brouer Committed by Daniel Borkmann
Browse files

igc: Add XDP hints kfuncs for RX hash



This implements XDP hints kfunc for RX-hash (xmo_rx_hash).
The HW rss hash type is handled via mapping table.

This igc driver (default config) does L3 hashing for UDP packets
(excludes UDP src/dest ports in hash calc).  Meaning RSS hash type is
L3 based.  Tested that the igc_rss_type_num for UDP is either
IGC_RSS_TYPE_HASH_IPV4 or IGC_RSS_TYPE_HASH_IPV6.

This patch also updates AF_XDP zero-copy function igc_clean_rx_irq_zc()
to use the xdp_buff wrapper struct igc_xdp_buff.

Signed-off-by: default avatarJesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarSong Yoong Siang <yoong.siang.song@intel.com>
Link: https://lore.kernel.org/bpf/168182465285.616355.2701740913376314790.stgit@firesoul
parent 73b7123d
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -502,6 +502,7 @@ struct igc_rx_buffer {
/* context wrapper around xdp_buff to provide access to descriptor metadata */
/* context wrapper around xdp_buff to provide access to descriptor metadata */
struct igc_xdp_buff {
struct igc_xdp_buff {
	struct xdp_buff xdp;
	struct xdp_buff xdp;
	union igc_adv_rx_desc *rx_desc;
};
};


struct igc_q_vector {
struct igc_q_vector {
+53 −0
Original line number Original line Diff line number Diff line
@@ -2559,6 +2559,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
					 igc_rx_offset(rx_ring) + pkt_offset,
					 igc_rx_offset(rx_ring) + pkt_offset,
					 size, true);
					 size, true);
			xdp_buff_clear_frags_flag(&ctx.xdp);
			xdp_buff_clear_frags_flag(&ctx.xdp);
			ctx.rx_desc = rx_desc;


			skb = igc_xdp_run_prog(adapter, &ctx.xdp);
			skb = igc_xdp_run_prog(adapter, &ctx.xdp);
		}
		}
@@ -2685,6 +2686,15 @@ static void igc_dispatch_skb_zc(struct igc_q_vector *q_vector,
	napi_gro_receive(&q_vector->napi, skb);
	napi_gro_receive(&q_vector->napi, skb);
}
}


static struct igc_xdp_buff *xsk_buff_to_igc_ctx(struct xdp_buff *xdp)
{
	/* xdp_buff pointer used by ZC code path is alloc as xdp_buff_xsk. The
	 * igc_xdp_buff shares its layout with xdp_buff_xsk and private
	 * igc_xdp_buff fields fall into xdp_buff_xsk->cb
	 */
       return (struct igc_xdp_buff *)xdp;
}

static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
{
{
	struct igc_adapter *adapter = q_vector->adapter;
	struct igc_adapter *adapter = q_vector->adapter;
@@ -2703,6 +2713,7 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
	while (likely(total_packets < budget)) {
	while (likely(total_packets < budget)) {
		union igc_adv_rx_desc *desc;
		union igc_adv_rx_desc *desc;
		struct igc_rx_buffer *bi;
		struct igc_rx_buffer *bi;
		struct igc_xdp_buff *ctx;
		ktime_t timestamp = 0;
		ktime_t timestamp = 0;
		unsigned int size;
		unsigned int size;
		int res;
		int res;
@@ -2720,6 +2731,9 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)


		bi = &ring->rx_buffer_info[ntc];
		bi = &ring->rx_buffer_info[ntc];


		ctx = xsk_buff_to_igc_ctx(bi->xdp);
		ctx->rx_desc = desc;

		if (igc_test_staterr(desc, IGC_RXDADV_STAT_TSIP)) {
		if (igc_test_staterr(desc, IGC_RXDADV_STAT_TSIP)) {
			timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
			timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
							bi->xdp->data);
							bi->xdp->data);
@@ -6475,6 +6489,44 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg)
	return value;
	return value;
}
}


/* Mapping HW RSS Type to enum xdp_rss_hash_type */
static enum xdp_rss_hash_type igc_xdp_rss_type[IGC_RSS_TYPE_MAX_TABLE] = {
	[IGC_RSS_TYPE_NO_HASH]		= XDP_RSS_TYPE_L2,
	[IGC_RSS_TYPE_HASH_TCP_IPV4]	= XDP_RSS_TYPE_L4_IPV4_TCP,
	[IGC_RSS_TYPE_HASH_IPV4]	= XDP_RSS_TYPE_L3_IPV4,
	[IGC_RSS_TYPE_HASH_TCP_IPV6]	= XDP_RSS_TYPE_L4_IPV6_TCP,
	[IGC_RSS_TYPE_HASH_IPV6_EX]	= XDP_RSS_TYPE_L3_IPV6_EX,
	[IGC_RSS_TYPE_HASH_IPV6]	= XDP_RSS_TYPE_L3_IPV6,
	[IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_TCP_EX,
	[IGC_RSS_TYPE_HASH_UDP_IPV4]	= XDP_RSS_TYPE_L4_IPV4_UDP,
	[IGC_RSS_TYPE_HASH_UDP_IPV6]	= XDP_RSS_TYPE_L4_IPV6_UDP,
	[IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_UDP_EX,
	[10] = XDP_RSS_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW  */
	[11] = XDP_RSS_TYPE_NONE, /* keep array sized for SW bit-mask   */
	[12] = XDP_RSS_TYPE_NONE, /* to handle future HW revisons       */
	[13] = XDP_RSS_TYPE_NONE,
	[14] = XDP_RSS_TYPE_NONE,
	[15] = XDP_RSS_TYPE_NONE,
};

static int igc_xdp_rx_hash(const struct xdp_md *_ctx, u32 *hash,
			   enum xdp_rss_hash_type *rss_type)
{
	const struct igc_xdp_buff *ctx = (void *)_ctx;

	if (!(ctx->xdp.rxq->dev->features & NETIF_F_RXHASH))
		return -ENODATA;

	*hash = le32_to_cpu(ctx->rx_desc->wb.lower.hi_dword.rss);
	*rss_type = igc_xdp_rss_type[igc_rss_type(ctx->rx_desc)];

	return 0;
}

static const struct xdp_metadata_ops igc_xdp_metadata_ops = {
	.xmo_rx_hash			= igc_xdp_rx_hash,
};

/**
/**
 * igc_probe - Device Initialization Routine
 * igc_probe - Device Initialization Routine
 * @pdev: PCI device information struct
 * @pdev: PCI device information struct
@@ -6548,6 +6600,7 @@ static int igc_probe(struct pci_dev *pdev,
	hw->hw_addr = adapter->io_addr;
	hw->hw_addr = adapter->io_addr;


	netdev->netdev_ops = &igc_netdev_ops;
	netdev->netdev_ops = &igc_netdev_ops;
	netdev->xdp_metadata_ops = &igc_xdp_metadata_ops;
	igc_ethtool_set_ops(netdev);
	igc_ethtool_set_ops(netdev);
	netdev->watchdog_timeo = 5 * HZ;
	netdev->watchdog_timeo = 5 * HZ;