Skip to content

Commit 4fe8158

Browse files
Jason Xingdavem330
authored andcommitted
ixgbe: let the xdpdrv work with more than 64 cpus
Originally, ixgbe driver doesn't allow the mounting of xdpdrv if the server is equipped with more than 64 cpus online. So it turns out that the loading of xdpdrv causes the "NOMEM" failure. Actually, we can adjust the algorithm and then make it work through mapping the current cpu to some xdp ring with the protect of @tx_lock. Here are some numbers before/after applying this patch with xdp-example loaded on the eth0X: As client (tx path): Before After TCP_STREAM send-64 734.14 714.20 TCP_STREAM send-128 1401.91 1395.05 TCP_STREAM send-512 5311.67 5292.84 TCP_STREAM send-1k 9277.40 9356.22 (not stable) TCP_RR send-1 22559.75 21844.22 TCP_RR send-128 23169.54 22725.13 TCP_RR send-512 21670.91 21412.56 As server (rx path): Before After TCP_STREAM send-64 1416.49 1383.12 TCP_STREAM send-128 3141.49 3055.50 TCP_STREAM send-512 9488.73 9487.44 TCP_STREAM send-1k 9491.17 9356.22 (not stable) TCP_RR send-1 23617.74 23601.60 ... Notice: the TCP_RR mode is unstable as the official document explains. I tested many times with different parameters combined through netperf. Though the result is not that accurate, I cannot see much influence on this patch. The static key is places on the hot path, but it actually shouldn't cause a huge regression theoretically. Co-developed-by: Shujin Li <[email protected]> Signed-off-by: Shujin Li <[email protected]> Signed-off-by: Jason Xing <[email protected]> Tested-by: Sandeep Penigalapati <[email protected]> Signed-off-by: Tony Nguyen <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a3e4aba commit 4fe8158

File tree

5 files changed

+77
-24
lines changed

5 files changed

+77
-24
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ struct ixgbe_ring {
351351
};
352352
u16 rx_offset;
353353
struct xdp_rxq_info xdp_rxq;
354+
spinlock_t tx_lock; /* used in XDP mode */
354355
struct xsk_buff_pool *xsk_pool;
355356
u16 ring_idx; /* {rx,tx,xdp}_ring back reference idx */
356357
u16 rx_buf_len;
@@ -375,11 +376,13 @@ enum ixgbe_ring_f_enum {
375376
#define IXGBE_MAX_FCOE_INDICES 8
376377
#define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
377378
#define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
378-
#define MAX_XDP_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
379+
#define IXGBE_MAX_XDP_QS (IXGBE_MAX_FDIR_INDICES + 1)
379380
#define IXGBE_MAX_L2A_QUEUES 4
380381
#define IXGBE_BAD_L2A_QUEUE 3
381382
#define IXGBE_MAX_MACVLANS 63
382383

384+
DECLARE_STATIC_KEY_FALSE(ixgbe_xdp_locking_key);
385+
383386
struct ixgbe_ring_feature {
384387
u16 limit; /* upper limit on feature indices */
385388
u16 indices; /* current value of indices */
@@ -629,7 +632,7 @@ struct ixgbe_adapter {
629632

630633
/* XDP */
631634
int num_xdp_queues;
632-
struct ixgbe_ring *xdp_ring[MAX_XDP_QUEUES];
635+
struct ixgbe_ring *xdp_ring[IXGBE_MAX_XDP_QS];
633636
unsigned long *af_xdp_zc_qps; /* tracks AF_XDP ZC enabled rings */
634637

635638
/* TX */
@@ -772,6 +775,22 @@ struct ixgbe_adapter {
772775
#endif /* CONFIG_IXGBE_IPSEC */
773776
};
774777

778+
static inline int ixgbe_determine_xdp_q_idx(int cpu)
779+
{
780+
if (static_key_enabled(&ixgbe_xdp_locking_key))
781+
return cpu % IXGBE_MAX_XDP_QS;
782+
else
783+
return cpu;
784+
}
785+
786+
static inline
787+
struct ixgbe_ring *ixgbe_determine_xdp_ring(struct ixgbe_adapter *adapter)
788+
{
789+
int index = ixgbe_determine_xdp_q_idx(smp_processor_id());
790+
791+
return adapter->xdp_ring[index];
792+
}
793+
775794
static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter)
776795
{
777796
switch (adapter->hw.mac.type) {

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,10 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
299299

300300
static int ixgbe_xdp_queues(struct ixgbe_adapter *adapter)
301301
{
302-
return adapter->xdp_prog ? nr_cpu_ids : 0;
302+
int queues;
303+
304+
queues = min_t(int, IXGBE_MAX_XDP_QS, nr_cpu_ids);
305+
return adapter->xdp_prog ? queues : 0;
303306
}
304307

305308
#define IXGBE_RSS_64Q_MASK 0x3F
@@ -947,6 +950,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
947950
ring->count = adapter->tx_ring_count;
948951
ring->queue_index = xdp_idx;
949952
set_ring_xdp(ring);
953+
spin_lock_init(&ring->tx_lock);
950954

951955
/* assign ring to adapter */
952956
WRITE_ONCE(adapter->xdp_ring[xdp_idx], ring);
@@ -1032,6 +1036,9 @@ static void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx)
10321036
adapter->q_vector[v_idx] = NULL;
10331037
__netif_napi_del(&q_vector->napi);
10341038

1039+
if (static_key_enabled(&ixgbe_xdp_locking_key))
1040+
static_branch_dec(&ixgbe_xdp_locking_key);
1041+
10351042
/*
10361043
* after a call to __netif_napi_del() napi may still be used and
10371044
* ixgbe_get_stats64() might access the rings on this vector,

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

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ MODULE_AUTHOR("Intel Corporation, <[email protected]>");
165165
MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
166166
MODULE_LICENSE("GPL v2");
167167

168+
DEFINE_STATIC_KEY_FALSE(ixgbe_xdp_locking_key);
169+
EXPORT_SYMBOL(ixgbe_xdp_locking_key);
170+
168171
static struct workqueue_struct *ixgbe_wq;
169172

170173
static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev);
@@ -2197,6 +2200,7 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
21972200
{
21982201
int err, result = IXGBE_XDP_PASS;
21992202
struct bpf_prog *xdp_prog;
2203+
struct ixgbe_ring *ring;
22002204
struct xdp_frame *xdpf;
22012205
u32 act;
22022206

@@ -2215,7 +2219,12 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
22152219
xdpf = xdp_convert_buff_to_frame(xdp);
22162220
if (unlikely(!xdpf))
22172221
goto out_failure;
2218-
result = ixgbe_xmit_xdp_ring(adapter, xdpf);
2222+
ring = ixgbe_determine_xdp_ring(adapter);
2223+
if (static_branch_unlikely(&ixgbe_xdp_locking_key))
2224+
spin_lock(&ring->tx_lock);
2225+
result = ixgbe_xmit_xdp_ring(ring, xdpf);
2226+
if (static_branch_unlikely(&ixgbe_xdp_locking_key))
2227+
spin_unlock(&ring->tx_lock);
22192228
if (result == IXGBE_XDP_CONSUMED)
22202229
goto out_failure;
22212230
break;
@@ -2422,13 +2431,9 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
24222431
xdp_do_flush_map();
24232432

24242433
if (xdp_xmit & IXGBE_XDP_TX) {
2425-
struct ixgbe_ring *ring = adapter->xdp_ring[smp_processor_id()];
2434+
struct ixgbe_ring *ring = ixgbe_determine_xdp_ring(adapter);
24262435

2427-
/* Force memory writes to complete before letting h/w
2428-
* know there are new descriptors to fetch.
2429-
*/
2430-
wmb();
2431-
writel(ring->next_to_use, ring->tail);
2436+
ixgbe_xdp_ring_update_tail_locked(ring);
24322437
}
24332438

24342439
u64_stats_update_begin(&rx_ring->syncp);
@@ -6320,7 +6325,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
63206325
if (ixgbe_init_rss_key(adapter))
63216326
return -ENOMEM;
63226327

6323-
adapter->af_xdp_zc_qps = bitmap_zalloc(MAX_XDP_QUEUES, GFP_KERNEL);
6328+
adapter->af_xdp_zc_qps = bitmap_zalloc(IXGBE_MAX_XDP_QS, GFP_KERNEL);
63246329
if (!adapter->af_xdp_zc_qps)
63256330
return -ENOMEM;
63266331

@@ -8536,10 +8541,9 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
85368541
}
85378542

85388543
#endif
8539-
int ixgbe_xmit_xdp_ring(struct ixgbe_adapter *adapter,
8544+
int ixgbe_xmit_xdp_ring(struct ixgbe_ring *ring,
85408545
struct xdp_frame *xdpf)
85418546
{
8542-
struct ixgbe_ring *ring = adapter->xdp_ring[smp_processor_id()];
85438547
struct ixgbe_tx_buffer *tx_buffer;
85448548
union ixgbe_adv_tx_desc *tx_desc;
85458549
u32 len, cmd_type;
@@ -10130,8 +10134,13 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
1013010134
return -EINVAL;
1013110135
}
1013210136

10133-
if (nr_cpu_ids > MAX_XDP_QUEUES)
10137+
/* if the number of cpus is much larger than the maximum of queues,
10138+
* we should stop it and then return with ENOMEM like before.
10139+
*/
10140+
if (nr_cpu_ids > IXGBE_MAX_XDP_QS * 2)
1013410141
return -ENOMEM;
10142+
else if (nr_cpu_ids > IXGBE_MAX_XDP_QS)
10143+
static_branch_inc(&ixgbe_xdp_locking_key);
1013510144

1013610145
old_prog = xchg(&adapter->xdp_prog, prog);
1013710146
need_reset = (!!prog != !!old_prog);
@@ -10195,6 +10204,15 @@ void ixgbe_xdp_ring_update_tail(struct ixgbe_ring *ring)
1019510204
writel(ring->next_to_use, ring->tail);
1019610205
}
1019710206

10207+
void ixgbe_xdp_ring_update_tail_locked(struct ixgbe_ring *ring)
10208+
{
10209+
if (static_branch_unlikely(&ixgbe_xdp_locking_key))
10210+
spin_lock(&ring->tx_lock);
10211+
ixgbe_xdp_ring_update_tail(ring);
10212+
if (static_branch_unlikely(&ixgbe_xdp_locking_key))
10213+
spin_unlock(&ring->tx_lock);
10214+
}
10215+
1019810216
static int ixgbe_xdp_xmit(struct net_device *dev, int n,
1019910217
struct xdp_frame **frames, u32 flags)
1020010218
{
@@ -10212,18 +10230,21 @@ static int ixgbe_xdp_xmit(struct net_device *dev, int n,
1021210230
/* During program transitions its possible adapter->xdp_prog is assigned
1021310231
* but ring has not been configured yet. In this case simply abort xmit.
1021410232
*/
10215-
ring = adapter->xdp_prog ? adapter->xdp_ring[smp_processor_id()] : NULL;
10233+
ring = adapter->xdp_prog ? ixgbe_determine_xdp_ring(adapter) : NULL;
1021610234
if (unlikely(!ring))
1021710235
return -ENXIO;
1021810236

1021910237
if (unlikely(test_bit(__IXGBE_TX_DISABLED, &ring->state)))
1022010238
return -ENXIO;
1022110239

10240+
if (static_branch_unlikely(&ixgbe_xdp_locking_key))
10241+
spin_lock(&ring->tx_lock);
10242+
1022210243
for (i = 0; i < n; i++) {
1022310244
struct xdp_frame *xdpf = frames[i];
1022410245
int err;
1022510246

10226-
err = ixgbe_xmit_xdp_ring(adapter, xdpf);
10247+
err = ixgbe_xmit_xdp_ring(ring, xdpf);
1022710248
if (err != IXGBE_XDP_TX)
1022810249
break;
1022910250
nxmit++;
@@ -10232,6 +10253,9 @@ static int ixgbe_xdp_xmit(struct net_device *dev, int n,
1023210253
if (unlikely(flags & XDP_XMIT_FLUSH))
1023310254
ixgbe_xdp_ring_update_tail(ring);
1023410255

10256+
if (static_branch_unlikely(&ixgbe_xdp_locking_key))
10257+
spin_unlock(&ring->tx_lock);
10258+
1023510259
return nxmit;
1023610260
}
1023710261

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#define IXGBE_TXD_CMD (IXGBE_TXD_CMD_EOP | \
1313
IXGBE_TXD_CMD_RS)
1414

15-
int ixgbe_xmit_xdp_ring(struct ixgbe_adapter *adapter,
15+
int ixgbe_xmit_xdp_ring(struct ixgbe_ring *ring,
1616
struct xdp_frame *xdpf);
1717
bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
1818
union ixgbe_adv_rx_desc *rx_desc,
@@ -23,6 +23,7 @@ void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
2323
void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector,
2424
struct sk_buff *skb);
2525
void ixgbe_xdp_ring_update_tail(struct ixgbe_ring *ring);
26+
void ixgbe_xdp_ring_update_tail_locked(struct ixgbe_ring *ring);
2627
void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter, u64 qmask);
2728

2829
void ixgbe_txrx_ring_disable(struct ixgbe_adapter *adapter, int ring);

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ static int ixgbe_run_xdp_zc(struct ixgbe_adapter *adapter,
100100
{
101101
int err, result = IXGBE_XDP_PASS;
102102
struct bpf_prog *xdp_prog;
103+
struct ixgbe_ring *ring;
103104
struct xdp_frame *xdpf;
104105
u32 act;
105106

@@ -120,7 +121,12 @@ static int ixgbe_run_xdp_zc(struct ixgbe_adapter *adapter,
120121
xdpf = xdp_convert_buff_to_frame(xdp);
121122
if (unlikely(!xdpf))
122123
goto out_failure;
123-
result = ixgbe_xmit_xdp_ring(adapter, xdpf);
124+
ring = ixgbe_determine_xdp_ring(adapter);
125+
if (static_branch_unlikely(&ixgbe_xdp_locking_key))
126+
spin_lock(&ring->tx_lock);
127+
result = ixgbe_xmit_xdp_ring(ring, xdpf);
128+
if (static_branch_unlikely(&ixgbe_xdp_locking_key))
129+
spin_unlock(&ring->tx_lock);
124130
if (result == IXGBE_XDP_CONSUMED)
125131
goto out_failure;
126132
break;
@@ -334,13 +340,9 @@ int ixgbe_clean_rx_irq_zc(struct ixgbe_q_vector *q_vector,
334340
xdp_do_flush_map();
335341

336342
if (xdp_xmit & IXGBE_XDP_TX) {
337-
struct ixgbe_ring *ring = adapter->xdp_ring[smp_processor_id()];
343+
struct ixgbe_ring *ring = ixgbe_determine_xdp_ring(adapter);
338344

339-
/* Force memory writes to complete before letting h/w
340-
* know there are new descriptors to fetch.
341-
*/
342-
wmb();
343-
writel(ring->next_to_use, ring->tail);
345+
ixgbe_xdp_ring_update_tail_locked(ring);
344346
}
345347

346348
u64_stats_update_begin(&rx_ring->syncp);

0 commit comments

Comments
 (0)