Skip to content

Commit 33fdc82

Browse files
John FastabendJeff Kirsher
authored andcommitted
ixgbe: add support for XDP_TX action
A couple design choices were made here. First I use a new ring pointer structure xdp_ring[] in the adapter struct instead of pushing the newly allocated XDP TX rings into the tx_ring[] structure. This means we have to duplicate loops around rings in places we want to initialize both TX rings and XDP rings. But by making it explicit it is obvious when we are using XDP rings and when we are using TX rings. Further we don't have to do ring arithmatic which is error prone. As a proof point for doing this my first patches used only a single ring structure and introduced bugs in FCoE code and macvlan code paths. Second I am aware this is not the most optimized version of this code possible. I want to get baseline support in using the most readable format possible and then once this series is included I will optimize the TX path in another series of patches. Signed-off-by: John Fastabend <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 9247080 commit 33fdc82

File tree

4 files changed

+348
-53
lines changed

4 files changed

+348
-53
lines changed

drivers/net/ethernet/intel/ixgbe/ixgbe.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,11 @@ struct vf_macvlans {
235235
struct ixgbe_tx_buffer {
236236
union ixgbe_adv_tx_desc *next_to_watch;
237237
unsigned long time_stamp;
238-
struct sk_buff *skb;
238+
union {
239+
struct sk_buff *skb;
240+
/* XDP uses address ptr on irq_clean */
241+
void *data;
242+
};
239243
unsigned int bytecount;
240244
unsigned short gso_segs;
241245
__be16 protocol;
@@ -288,6 +292,7 @@ enum ixgbe_ring_state_t {
288292
__IXGBE_TX_XPS_INIT_DONE,
289293
__IXGBE_TX_DETECT_HANG,
290294
__IXGBE_HANG_CHECK_ARMED,
295+
__IXGBE_TX_XDP_RING,
291296
};
292297

293298
#define ring_uses_build_skb(ring) \
@@ -314,6 +319,12 @@ struct ixgbe_fwd_adapter {
314319
set_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
315320
#define clear_ring_rsc_enabled(ring) \
316321
clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
322+
#define ring_is_xdp(ring) \
323+
test_bit(__IXGBE_TX_XDP_RING, &(ring)->state)
324+
#define set_ring_xdp(ring) \
325+
set_bit(__IXGBE_TX_XDP_RING, &(ring)->state)
326+
#define clear_ring_xdp(ring) \
327+
clear_bit(__IXGBE_TX_XDP_RING, &(ring)->state)
317328
struct ixgbe_ring {
318329
struct ixgbe_ring *next; /* pointer to next ring in q_vector */
319330
struct ixgbe_q_vector *q_vector; /* backpointer to host q_vector */
@@ -380,6 +391,7 @@ enum ixgbe_ring_f_enum {
380391
#define IXGBE_MAX_FCOE_INDICES 8
381392
#define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
382393
#define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
394+
#define MAX_XDP_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
383395
#define IXGBE_MAX_L2A_QUEUES 4
384396
#define IXGBE_BAD_L2A_QUEUE 3
385397
#define IXGBE_MAX_MACVLANS 31
@@ -623,6 +635,10 @@ struct ixgbe_adapter {
623635
__be16 vxlan_port;
624636
__be16 geneve_port;
625637

638+
/* XDP */
639+
int num_xdp_queues;
640+
struct ixgbe_ring *xdp_ring[MAX_XDP_QUEUES];
641+
626642
/* TX */
627643
struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp;
628644

@@ -669,6 +685,7 @@ struct ixgbe_adapter {
669685

670686
u64 tx_busy;
671687
unsigned int tx_ring_count;
688+
unsigned int xdp_ring_count;
672689
unsigned int rx_ring_count;
673690

674691
u32 link_speed;

drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,15 +1071,19 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
10711071
if (!netif_running(adapter->netdev)) {
10721072
for (i = 0; i < adapter->num_tx_queues; i++)
10731073
adapter->tx_ring[i]->count = new_tx_count;
1074+
for (i = 0; i < adapter->num_xdp_queues; i++)
1075+
adapter->xdp_ring[i]->count = new_tx_count;
10741076
for (i = 0; i < adapter->num_rx_queues; i++)
10751077
adapter->rx_ring[i]->count = new_rx_count;
10761078
adapter->tx_ring_count = new_tx_count;
1079+
adapter->xdp_ring_count = new_tx_count;
10771080
adapter->rx_ring_count = new_rx_count;
10781081
goto clear_reset;
10791082
}
10801083

10811084
/* allocate temporary buffer to store rings in */
10821085
i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues);
1086+
i = max_t(int, i, adapter->num_xdp_queues);
10831087
temp_ring = vmalloc(i * sizeof(struct ixgbe_ring));
10841088

10851089
if (!temp_ring) {
@@ -1111,12 +1115,33 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
11111115
}
11121116
}
11131117

1118+
for (i = 0; i < adapter->num_xdp_queues; i++) {
1119+
memcpy(&temp_ring[i], adapter->xdp_ring[i],
1120+
sizeof(struct ixgbe_ring));
1121+
1122+
temp_ring[i].count = new_tx_count;
1123+
err = ixgbe_setup_tx_resources(&temp_ring[i]);
1124+
if (err) {
1125+
while (i) {
1126+
i--;
1127+
ixgbe_free_tx_resources(&temp_ring[i]);
1128+
}
1129+
goto err_setup;
1130+
}
1131+
}
1132+
11141133
for (i = 0; i < adapter->num_tx_queues; i++) {
11151134
ixgbe_free_tx_resources(adapter->tx_ring[i]);
11161135

11171136
memcpy(adapter->tx_ring[i], &temp_ring[i],
11181137
sizeof(struct ixgbe_ring));
11191138
}
1139+
for (i = 0; i < adapter->num_xdp_queues; i++) {
1140+
ixgbe_free_tx_resources(adapter->xdp_ring[i]);
1141+
1142+
memcpy(adapter->xdp_ring[i], &temp_ring[i],
1143+
sizeof(struct ixgbe_ring));
1144+
}
11201145

11211146
adapter->tx_ring_count = new_tx_count;
11221147
}

drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,14 @@ static bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter)
267267
**/
268268
static bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter)
269269
{
270-
int i;
270+
int i, reg_idx;
271271

272272
for (i = 0; i < adapter->num_rx_queues; i++)
273273
adapter->rx_ring[i]->reg_idx = i;
274-
for (i = 0; i < adapter->num_tx_queues; i++)
275-
adapter->tx_ring[i]->reg_idx = i;
274+
for (i = 0, reg_idx = 0; i < adapter->num_tx_queues; i++, reg_idx++)
275+
adapter->tx_ring[i]->reg_idx = reg_idx;
276+
for (i = 0; i < adapter->num_xdp_queues; i++, reg_idx++)
277+
adapter->xdp_ring[i]->reg_idx = reg_idx;
276278

277279
return true;
278280
}
@@ -308,6 +310,11 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
308310
ixgbe_cache_ring_rss(adapter);
309311
}
310312

313+
static int ixgbe_xdp_queues(struct ixgbe_adapter *adapter)
314+
{
315+
return adapter->xdp_prog ? nr_cpu_ids : 0;
316+
}
317+
311318
#define IXGBE_RSS_64Q_MASK 0x3F
312319
#define IXGBE_RSS_16Q_MASK 0xF
313320
#define IXGBE_RSS_8Q_MASK 0x7
@@ -382,6 +389,7 @@ static bool ixgbe_set_dcb_sriov_queues(struct ixgbe_adapter *adapter)
382389
adapter->num_rx_queues_per_pool = tcs;
383390

384391
adapter->num_tx_queues = vmdq_i * tcs;
392+
adapter->num_xdp_queues = 0;
385393
adapter->num_rx_queues = vmdq_i * tcs;
386394

387395
#ifdef IXGBE_FCOE
@@ -479,6 +487,7 @@ static bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
479487
netdev_set_tc_queue(dev, i, rss_i, rss_i * i);
480488

481489
adapter->num_tx_queues = rss_i * tcs;
490+
adapter->num_xdp_queues = 0;
482491
adapter->num_rx_queues = rss_i * tcs;
483492

484493
return true;
@@ -549,6 +558,7 @@ static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)
549558

550559
adapter->num_rx_queues = vmdq_i * rss_i;
551560
adapter->num_tx_queues = vmdq_i * rss_i;
561+
adapter->num_xdp_queues = 0;
552562

553563
/* disable ATR as it is not supported when VMDq is enabled */
554564
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
@@ -669,6 +679,7 @@ static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter)
669679
#endif /* IXGBE_FCOE */
670680
adapter->num_rx_queues = rss_i;
671681
adapter->num_tx_queues = rss_i;
682+
adapter->num_xdp_queues = ixgbe_xdp_queues(adapter);
672683

673684
return true;
674685
}
@@ -689,6 +700,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
689700
/* Start with base case */
690701
adapter->num_rx_queues = 1;
691702
adapter->num_tx_queues = 1;
703+
adapter->num_xdp_queues = 0;
692704
adapter->num_rx_pools = adapter->num_rx_queues;
693705
adapter->num_rx_queues_per_pool = 1;
694706

@@ -719,8 +731,11 @@ static int ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter)
719731
struct ixgbe_hw *hw = &adapter->hw;
720732
int i, vectors, vector_threshold;
721733

722-
/* We start by asking for one vector per queue pair */
734+
/* We start by asking for one vector per queue pair with XDP queues
735+
* being stacked with TX queues.
736+
*/
723737
vectors = max(adapter->num_rx_queues, adapter->num_tx_queues);
738+
vectors = max(vectors, adapter->num_xdp_queues);
724739

725740
/* It is easy to be greedy for MSI-X vectors. However, it really
726741
* doesn't do much good if we have a lot more vectors than CPUs. We'll
@@ -800,6 +815,8 @@ static void ixgbe_add_ring(struct ixgbe_ring *ring,
800815
* @v_idx: index of vector in adapter struct
801816
* @txr_count: total number of Tx rings to allocate
802817
* @txr_idx: index of first Tx ring to allocate
818+
* @xdp_count: total number of XDP rings to allocate
819+
* @xdp_idx: index of first XDP ring to allocate
803820
* @rxr_count: total number of Rx rings to allocate
804821
* @rxr_idx: index of first Rx ring to allocate
805822
*
@@ -808,6 +825,7 @@ static void ixgbe_add_ring(struct ixgbe_ring *ring,
808825
static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
809826
int v_count, int v_idx,
810827
int txr_count, int txr_idx,
828+
int xdp_count, int xdp_idx,
811829
int rxr_count, int rxr_idx)
812830
{
813831
struct ixgbe_q_vector *q_vector;
@@ -817,7 +835,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
817835
int ring_count, size;
818836
u8 tcs = netdev_get_num_tc(adapter->netdev);
819837

820-
ring_count = txr_count + rxr_count;
838+
ring_count = txr_count + rxr_count + xdp_count;
821839
size = sizeof(struct ixgbe_q_vector) +
822840
(sizeof(struct ixgbe_ring) * ring_count);
823841

@@ -909,6 +927,33 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
909927
ring++;
910928
}
911929

930+
while (xdp_count) {
931+
/* assign generic ring traits */
932+
ring->dev = &adapter->pdev->dev;
933+
ring->netdev = adapter->netdev;
934+
935+
/* configure backlink on ring */
936+
ring->q_vector = q_vector;
937+
938+
/* update q_vector Tx values */
939+
ixgbe_add_ring(ring, &q_vector->tx);
940+
941+
/* apply Tx specific ring traits */
942+
ring->count = adapter->tx_ring_count;
943+
ring->queue_index = xdp_idx;
944+
set_ring_xdp(ring);
945+
946+
/* assign ring to adapter */
947+
adapter->xdp_ring[xdp_idx] = ring;
948+
949+
/* update count and index */
950+
xdp_count--;
951+
xdp_idx++;
952+
953+
/* push pointer to next ring */
954+
ring++;
955+
}
956+
912957
while (rxr_count) {
913958
/* assign generic ring traits */
914959
ring->dev = &adapter->pdev->dev;
@@ -1002,17 +1047,18 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
10021047
int q_vectors = adapter->num_q_vectors;
10031048
int rxr_remaining = adapter->num_rx_queues;
10041049
int txr_remaining = adapter->num_tx_queues;
1005-
int rxr_idx = 0, txr_idx = 0, v_idx = 0;
1050+
int xdp_remaining = adapter->num_xdp_queues;
1051+
int rxr_idx = 0, txr_idx = 0, xdp_idx = 0, v_idx = 0;
10061052
int err;
10071053

10081054
/* only one q_vector if MSI-X is disabled. */
10091055
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
10101056
q_vectors = 1;
10111057

1012-
if (q_vectors >= (rxr_remaining + txr_remaining)) {
1058+
if (q_vectors >= (rxr_remaining + txr_remaining + xdp_remaining)) {
10131059
for (; rxr_remaining; v_idx++) {
10141060
err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
1015-
0, 0, 1, rxr_idx);
1061+
0, 0, 0, 0, 1, rxr_idx);
10161062

10171063
if (err)
10181064
goto err_out;
@@ -1026,8 +1072,11 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
10261072
for (; v_idx < q_vectors; v_idx++) {
10271073
int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);
10281074
int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);
1075+
int xqpv = DIV_ROUND_UP(xdp_remaining, q_vectors - v_idx);
1076+
10291077
err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
10301078
tqpv, txr_idx,
1079+
xqpv, xdp_idx,
10311080
rqpv, rxr_idx);
10321081

10331082
if (err)
@@ -1036,14 +1085,17 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
10361085
/* update counts and index */
10371086
rxr_remaining -= rqpv;
10381087
txr_remaining -= tqpv;
1088+
xdp_remaining -= xqpv;
10391089
rxr_idx++;
10401090
txr_idx++;
1091+
xdp_idx += xqpv;
10411092
}
10421093

10431094
return 0;
10441095

10451096
err_out:
10461097
adapter->num_tx_queues = 0;
1098+
adapter->num_xdp_queues = 0;
10471099
adapter->num_rx_queues = 0;
10481100
adapter->num_q_vectors = 0;
10491101

@@ -1066,6 +1118,7 @@ static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter)
10661118
int v_idx = adapter->num_q_vectors;
10671119

10681120
adapter->num_tx_queues = 0;
1121+
adapter->num_xdp_queues = 0;
10691122
adapter->num_rx_queues = 0;
10701123
adapter->num_q_vectors = 0;
10711124

@@ -1172,9 +1225,10 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
11721225

11731226
ixgbe_cache_ring_register(adapter);
11741227

1175-
e_dev_info("Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u\n",
1228+
e_dev_info("Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u XDP Queue count = %u\n",
11761229
(adapter->num_rx_queues > 1) ? "Enabled" : "Disabled",
1177-
adapter->num_rx_queues, adapter->num_tx_queues);
1230+
adapter->num_rx_queues, adapter->num_tx_queues,
1231+
adapter->num_xdp_queues);
11781232

11791233
set_bit(__IXGBE_DOWN, &adapter->state);
11801234

@@ -1195,6 +1249,7 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
11951249
void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
11961250
{
11971251
adapter->num_tx_queues = 0;
1252+
adapter->num_xdp_queues = 0;
11981253
adapter->num_rx_queues = 0;
11991254

12001255
ixgbe_free_q_vectors(adapter);

0 commit comments

Comments
 (0)