Skip to content

Commit 9cbc948

Browse files
svenauhagenanguy11
authored andcommitted
igb: add XDP support
Add XDP support to the IGB driver. The implementation follows the IXGBE XDP implementation closely and I used the following patches as basis: 1. commit 9247080 ("ixgbe: add XDP support for pass and drop actions") 2. commit 33fdc82 ("ixgbe: add support for XDP_TX action") 3. commit ed93a39 ("ixgbe: tweak page counting for XDP_REDIRECT") Due to the hardware constraints of the devices using the IGB driver we must share the TX queues with XDP which means locking the TX queue for XDP. I ran tests on an older device to get better numbers. Test machine: Intel(R) Atom(TM) CPU C2338 @ 1.74GHz (2 Cores) 2x Intel I211 Routing Original Driver Network Stack: 382 Kpps Routing XDP Redirect (xdp_fwd_kern): 1.48 Mpps XDP Drop: 1.48 Mpps Using XDP we can achieve line rate forwarding even on an older Intel Atom CPU. Signed-off-by: Sven Auhagen <[email protected]> Tested-by: Sandeep Penigalapati <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent bcbf1be commit 9cbc948

File tree

3 files changed

+481
-36
lines changed

3 files changed

+481
-36
lines changed

drivers/net/ethernet/intel/igb/igb.h

+74-6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <linux/pci.h>
2020
#include <linux/mdio.h>
2121

22+
#include <net/xdp.h>
23+
2224
struct igb_adapter;
2325

2426
#define E1000_PCS_CFG_IGN_SD 1
@@ -79,6 +81,12 @@ struct igb_adapter;
7981
#define IGB_I210_RX_LATENCY_100 2213
8082
#define IGB_I210_RX_LATENCY_1000 448
8183

84+
/* XDP */
85+
#define IGB_XDP_PASS 0
86+
#define IGB_XDP_CONSUMED BIT(0)
87+
#define IGB_XDP_TX BIT(1)
88+
#define IGB_XDP_REDIR BIT(2)
89+
8290
struct vf_data_storage {
8391
unsigned char vf_mac_addresses[ETH_ALEN];
8492
u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES];
@@ -132,17 +140,62 @@ struct vf_mac_filter {
132140

133141
/* Supported Rx Buffer Sizes */
134142
#define IGB_RXBUFFER_256 256
143+
#define IGB_RXBUFFER_1536 1536
135144
#define IGB_RXBUFFER_2048 2048
136145
#define IGB_RXBUFFER_3072 3072
137146
#define IGB_RX_HDR_LEN IGB_RXBUFFER_256
138147
#define IGB_TS_HDR_LEN 16
139148

140-
#define IGB_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
149+
/* Attempt to maximize the headroom available for incoming frames. We
150+
* use a 2K buffer for receives and need 1536/1534 to store the data for
151+
* the frame. This leaves us with 512 bytes of room. From that we need
152+
* to deduct the space needed for the shared info and the padding needed
153+
* to IP align the frame.
154+
*
155+
* Note: For cache line sizes 256 or larger this value is going to end
156+
* up negative. In these cases we should fall back to the 3K
157+
* buffers.
158+
*/
141159
#if (PAGE_SIZE < 8192)
142-
#define IGB_MAX_FRAME_BUILD_SKB \
143-
(SKB_WITH_OVERHEAD(IGB_RXBUFFER_2048) - IGB_SKB_PAD - IGB_TS_HDR_LEN)
160+
#define IGB_MAX_FRAME_BUILD_SKB (IGB_RXBUFFER_1536 - NET_IP_ALIGN)
161+
#define IGB_2K_TOO_SMALL_WITH_PADDING \
162+
((NET_SKB_PAD + IGB_TS_HDR_LEN + IGB_RXBUFFER_1536) > SKB_WITH_OVERHEAD(IGB_RXBUFFER_2048))
163+
164+
static inline int igb_compute_pad(int rx_buf_len)
165+
{
166+
int page_size, pad_size;
167+
168+
page_size = ALIGN(rx_buf_len, PAGE_SIZE / 2);
169+
pad_size = SKB_WITH_OVERHEAD(page_size) - rx_buf_len;
170+
171+
return pad_size;
172+
}
173+
174+
static inline int igb_skb_pad(void)
175+
{
176+
int rx_buf_len;
177+
178+
/* If a 2K buffer cannot handle a standard Ethernet frame then
179+
* optimize padding for a 3K buffer instead of a 1.5K buffer.
180+
*
181+
* For a 3K buffer we need to add enough padding to allow for
182+
* tailroom due to NET_IP_ALIGN possibly shifting us out of
183+
* cache-line alignment.
184+
*/
185+
if (IGB_2K_TOO_SMALL_WITH_PADDING)
186+
rx_buf_len = IGB_RXBUFFER_3072 + SKB_DATA_ALIGN(NET_IP_ALIGN);
187+
else
188+
rx_buf_len = IGB_RXBUFFER_1536;
189+
190+
/* if needed make room for NET_IP_ALIGN */
191+
rx_buf_len -= NET_IP_ALIGN;
192+
193+
return igb_compute_pad(rx_buf_len);
194+
}
195+
196+
#define IGB_SKB_PAD igb_skb_pad()
144197
#else
145-
#define IGB_MAX_FRAME_BUILD_SKB (IGB_RXBUFFER_2048 - IGB_TS_HDR_LEN)
198+
#define IGB_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
146199
#endif
147200

148201
/* How many Rx Buffers do we bundle into one write to the hardware ? */
@@ -194,13 +247,22 @@ enum igb_tx_flags {
194247
#define IGB_SFF_ADDRESSING_MODE 0x4
195248
#define IGB_SFF_8472_UNSUP 0x00
196249

250+
enum igb_tx_buf_type {
251+
IGB_TYPE_SKB = 0,
252+
IGB_TYPE_XDP,
253+
};
254+
197255
/* wrapper around a pointer to a socket buffer,
198256
* so a DMA handle can be stored along with the buffer
199257
*/
200258
struct igb_tx_buffer {
201259
union e1000_adv_tx_desc *next_to_watch;
202260
unsigned long time_stamp;
203-
struct sk_buff *skb;
261+
enum igb_tx_buf_type type;
262+
union {
263+
struct sk_buff *skb;
264+
struct xdp_frame *xdpf;
265+
};
204266
unsigned int bytecount;
205267
u16 gso_segs;
206268
__be16 protocol;
@@ -248,6 +310,7 @@ struct igb_ring_container {
248310
struct igb_ring {
249311
struct igb_q_vector *q_vector; /* backlink to q_vector */
250312
struct net_device *netdev; /* back pointer to net_device */
313+
struct bpf_prog *xdp_prog;
251314
struct device *dev; /* device pointer for dma mapping */
252315
union { /* array of buffer info structs */
253316
struct igb_tx_buffer *tx_buffer_info;
@@ -288,6 +351,7 @@ struct igb_ring {
288351
struct u64_stats_sync rx_syncp;
289352
};
290353
};
354+
struct xdp_rxq_info xdp_rxq;
291355
} ____cacheline_internodealigned_in_smp;
292356

293357
struct igb_q_vector {
@@ -339,7 +403,7 @@ static inline unsigned int igb_rx_bufsz(struct igb_ring *ring)
339403
return IGB_RXBUFFER_3072;
340404

341405
if (ring_uses_build_skb(ring))
342-
return IGB_MAX_FRAME_BUILD_SKB + IGB_TS_HDR_LEN;
406+
return IGB_MAX_FRAME_BUILD_SKB;
343407
#endif
344408
return IGB_RXBUFFER_2048;
345409
}
@@ -467,6 +531,7 @@ struct igb_adapter {
467531
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
468532

469533
struct net_device *netdev;
534+
struct bpf_prog *xdp_prog;
470535

471536
unsigned long state;
472537
unsigned int flags;
@@ -643,6 +708,9 @@ enum igb_boards {
643708

644709
extern char igb_driver_name[];
645710

711+
int igb_xmit_xdp_ring(struct igb_adapter *adapter,
712+
struct igb_ring *ring,
713+
struct xdp_frame *xdpf);
646714
int igb_open(struct net_device *netdev);
647715
int igb_close(struct net_device *netdev);
648716
int igb_up(struct igb_adapter *);

drivers/net/ethernet/intel/igb/igb_ethtool.c

+4
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,10 @@ static int igb_set_ringparam(struct net_device *netdev,
961961
memcpy(&temp_ring[i], adapter->rx_ring[i],
962962
sizeof(struct igb_ring));
963963

964+
/* Clear copied XDP RX-queue info */
965+
memset(&temp_ring[i].xdp_rxq, 0,
966+
sizeof(temp_ring[i].xdp_rxq));
967+
964968
temp_ring[i].count = new_rx_count;
965969
err = igb_setup_rx_resources(&temp_ring[i]);
966970
if (err) {

0 commit comments

Comments
 (0)