Skip to content

Commit 73f1071

Browse files
Andre Guedesanguy11
authored andcommitted
igc: Add support for XDP_TX action
Add support for XDP_TX action which enables XDP programs to transmit back receiving frames. I225 controller has only 4 Tx hardware queues. Since XDP programs may not even issue an XDP_TX action, this patch doesn't reserve dedicated queues just for XDP like other Intel drivers do. Instead, the queues are shared between the network stack and XDP. The netdev queue lock is used to ensure mutual exclusion. Since frames can now be transmitted via XDP_TX, the igc_tx_buffer structure is modified so we are able to save a reference to the xdp frame for later clean up once the packet is transmitted. The tx_buffer is mapped to either a skb or a xdpf so we use a union to save the skb or xdpf pointer and have a bit in tx_flags to indicate which field to use. This patch has been tested with the sample app "xdp2" located in samples/bpf/ dir. Signed-off-by: Andre Guedes <[email protected]> Signed-off-by: Vedang Patel <[email protected]> Signed-off-by: Jithu Joseph <[email protected]> Reviewed-by: Maciej Fijalkowski <[email protected]> Tested-by: Dvora Fuxbrumer <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 2657510 commit 73f1071

File tree

4 files changed

+204
-11
lines changed

4 files changed

+204
-11
lines changed

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ struct igc_ring {
111111
struct sk_buff *skb;
112112
};
113113
};
114+
115+
struct xdp_rxq_info xdp_rxq;
114116
} ____cacheline_internodealigned_in_smp;
115117

116118
/* Board specific private data structure */
@@ -375,6 +377,8 @@ enum igc_tx_flags {
375377
/* olinfo flags */
376378
IGC_TX_FLAGS_IPV4 = 0x10,
377379
IGC_TX_FLAGS_CSUM = 0x20,
380+
381+
IGC_TX_FLAGS_XDP = 0x100,
378382
};
379383

380384
enum igc_boards {
@@ -397,7 +401,10 @@ enum igc_boards {
397401
struct igc_tx_buffer {
398402
union igc_adv_tx_desc *next_to_watch;
399403
unsigned long time_stamp;
400-
struct sk_buff *skb;
404+
union {
405+
struct sk_buff *skb;
406+
struct xdp_frame *xdpf;
407+
};
401408
unsigned int bytecount;
402409
u16 gso_segs;
403410
__be16 protocol;

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 166 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#define IGC_XDP_PASS 0
2727
#define IGC_XDP_CONSUMED BIT(0)
28+
#define IGC_XDP_TX BIT(1)
2829

2930
static int debug = -1;
3031

@@ -181,8 +182,10 @@ static void igc_clean_tx_ring(struct igc_ring *tx_ring)
181182
while (i != tx_ring->next_to_use) {
182183
union igc_adv_tx_desc *eop_desc, *tx_desc;
183184

184-
/* Free all the Tx ring sk_buffs */
185-
dev_kfree_skb_any(tx_buffer->skb);
185+
if (tx_buffer->tx_flags & IGC_TX_FLAGS_XDP)
186+
xdp_return_frame(tx_buffer->xdpf);
187+
else
188+
dev_kfree_skb_any(tx_buffer->skb);
186189

187190
/* unmap skb header data */
188191
dma_unmap_single(tx_ring->dev,
@@ -410,6 +413,8 @@ void igc_free_rx_resources(struct igc_ring *rx_ring)
410413
{
411414
igc_clean_rx_ring(rx_ring);
412415

416+
igc_xdp_unregister_rxq_info(rx_ring);
417+
413418
vfree(rx_ring->rx_buffer_info);
414419
rx_ring->rx_buffer_info = NULL;
415420

@@ -447,7 +452,11 @@ int igc_setup_rx_resources(struct igc_ring *rx_ring)
447452
{
448453
struct net_device *ndev = rx_ring->netdev;
449454
struct device *dev = rx_ring->dev;
450-
int size, desc_len;
455+
int size, desc_len, res;
456+
457+
res = igc_xdp_register_rxq_info(rx_ring);
458+
if (res < 0)
459+
return res;
451460

452461
size = sizeof(struct igc_rx_buffer) * rx_ring->count;
453462
rx_ring->rx_buffer_info = vzalloc(size);
@@ -473,6 +482,7 @@ int igc_setup_rx_resources(struct igc_ring *rx_ring)
473482
return 0;
474483

475484
err:
485+
igc_xdp_unregister_rxq_info(rx_ring);
476486
vfree(rx_ring->rx_buffer_info);
477487
rx_ring->rx_buffer_info = NULL;
478488
netdev_err(ndev, "Unable to allocate memory for Rx descriptor ring\n");
@@ -1909,6 +1919,101 @@ static void igc_alloc_rx_buffers(struct igc_ring *rx_ring, u16 cleaned_count)
19091919
}
19101920
}
19111921

1922+
static int igc_xdp_init_tx_buffer(struct igc_tx_buffer *buffer,
1923+
struct xdp_frame *xdpf,
1924+
struct igc_ring *ring)
1925+
{
1926+
dma_addr_t dma;
1927+
1928+
dma = dma_map_single(ring->dev, xdpf->data, xdpf->len, DMA_TO_DEVICE);
1929+
if (dma_mapping_error(ring->dev, dma)) {
1930+
netdev_err_once(ring->netdev, "Failed to map DMA for TX\n");
1931+
return -ENOMEM;
1932+
}
1933+
1934+
buffer->xdpf = xdpf;
1935+
buffer->tx_flags = IGC_TX_FLAGS_XDP;
1936+
buffer->protocol = 0;
1937+
buffer->bytecount = xdpf->len;
1938+
buffer->gso_segs = 1;
1939+
buffer->time_stamp = jiffies;
1940+
dma_unmap_len_set(buffer, len, xdpf->len);
1941+
dma_unmap_addr_set(buffer, dma, dma);
1942+
return 0;
1943+
}
1944+
1945+
/* This function requires __netif_tx_lock is held by the caller. */
1946+
static int igc_xdp_init_tx_descriptor(struct igc_ring *ring,
1947+
struct xdp_frame *xdpf)
1948+
{
1949+
struct igc_tx_buffer *buffer;
1950+
union igc_adv_tx_desc *desc;
1951+
u32 cmd_type, olinfo_status;
1952+
int err;
1953+
1954+
if (!igc_desc_unused(ring))
1955+
return -EBUSY;
1956+
1957+
buffer = &ring->tx_buffer_info[ring->next_to_use];
1958+
err = igc_xdp_init_tx_buffer(buffer, xdpf, ring);
1959+
if (err)
1960+
return err;
1961+
1962+
cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT |
1963+
IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD |
1964+
buffer->bytecount;
1965+
olinfo_status = buffer->bytecount << IGC_ADVTXD_PAYLEN_SHIFT;
1966+
1967+
desc = IGC_TX_DESC(ring, ring->next_to_use);
1968+
desc->read.cmd_type_len = cpu_to_le32(cmd_type);
1969+
desc->read.olinfo_status = cpu_to_le32(olinfo_status);
1970+
desc->read.buffer_addr = cpu_to_le64(dma_unmap_addr(buffer, dma));
1971+
1972+
netdev_tx_sent_queue(txring_txq(ring), buffer->bytecount);
1973+
1974+
buffer->next_to_watch = desc;
1975+
1976+
ring->next_to_use++;
1977+
if (ring->next_to_use == ring->count)
1978+
ring->next_to_use = 0;
1979+
1980+
return 0;
1981+
}
1982+
1983+
static struct igc_ring *igc_xdp_get_tx_ring(struct igc_adapter *adapter,
1984+
int cpu)
1985+
{
1986+
int index = cpu;
1987+
1988+
if (unlikely(index < 0))
1989+
index = 0;
1990+
1991+
while (index >= adapter->num_tx_queues)
1992+
index -= adapter->num_tx_queues;
1993+
1994+
return adapter->tx_ring[index];
1995+
}
1996+
1997+
static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp)
1998+
{
1999+
struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp);
2000+
int cpu = smp_processor_id();
2001+
struct netdev_queue *nq;
2002+
struct igc_ring *ring;
2003+
int res;
2004+
2005+
if (unlikely(!xdpf))
2006+
return -EFAULT;
2007+
2008+
ring = igc_xdp_get_tx_ring(adapter, cpu);
2009+
nq = txring_txq(ring);
2010+
2011+
__netif_tx_lock(nq, cpu);
2012+
res = igc_xdp_init_tx_descriptor(ring, xdpf);
2013+
__netif_tx_unlock(nq);
2014+
return res;
2015+
}
2016+
19122017
static struct sk_buff *igc_xdp_run_prog(struct igc_adapter *adapter,
19132018
struct xdp_buff *xdp)
19142019
{
@@ -1929,6 +2034,12 @@ static struct sk_buff *igc_xdp_run_prog(struct igc_adapter *adapter,
19292034
case XDP_PASS:
19302035
res = IGC_XDP_PASS;
19312036
break;
2037+
case XDP_TX:
2038+
if (igc_xdp_xmit_back(adapter, xdp) < 0)
2039+
res = IGC_XDP_CONSUMED;
2040+
else
2041+
res = IGC_XDP_TX;
2042+
break;
19322043
default:
19332044
bpf_warn_invalid_xdp_action(act);
19342045
fallthrough;
@@ -1945,20 +2056,49 @@ static struct sk_buff *igc_xdp_run_prog(struct igc_adapter *adapter,
19452056
return ERR_PTR(-res);
19462057
}
19472058

2059+
/* This function assumes __netif_tx_lock is held by the caller. */
2060+
static void igc_flush_tx_descriptors(struct igc_ring *ring)
2061+
{
2062+
/* Once tail pointer is updated, hardware can fetch the descriptors
2063+
* any time so we issue a write membar here to ensure all memory
2064+
* writes are complete before the tail pointer is updated.
2065+
*/
2066+
wmb();
2067+
writel(ring->next_to_use, ring->tail);
2068+
}
2069+
2070+
static void igc_finalize_xdp(struct igc_adapter *adapter, int status)
2071+
{
2072+
int cpu = smp_processor_id();
2073+
struct netdev_queue *nq;
2074+
struct igc_ring *ring;
2075+
2076+
if (status & IGC_XDP_TX) {
2077+
ring = igc_xdp_get_tx_ring(adapter, cpu);
2078+
nq = txring_txq(ring);
2079+
2080+
__netif_tx_lock(nq, cpu);
2081+
igc_flush_tx_descriptors(ring);
2082+
__netif_tx_unlock(nq);
2083+
}
2084+
}
2085+
19482086
static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
19492087
{
19502088
unsigned int total_bytes = 0, total_packets = 0;
2089+
struct igc_adapter *adapter = q_vector->adapter;
19512090
struct igc_ring *rx_ring = q_vector->rx.ring;
19522091
struct sk_buff *skb = rx_ring->skb;
19532092
u16 cleaned_count = igc_desc_unused(rx_ring);
2093+
int xdp_status = 0;
19542094

19552095
while (likely(total_packets < budget)) {
19562096
union igc_adv_rx_desc *rx_desc;
19572097
struct igc_rx_buffer *rx_buffer;
2098+
unsigned int size, truesize;
19582099
ktime_t timestamp = 0;
19592100
struct xdp_buff xdp;
19602101
int pkt_offset = 0;
1961-
unsigned int size;
19622102
void *pktbuf;
19632103

19642104
/* return some buffers to hardware, one at a time is too slow */
@@ -1979,6 +2119,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
19792119
dma_rmb();
19802120

19812121
rx_buffer = igc_get_rx_buffer(rx_ring, size);
2122+
truesize = igc_get_rx_frame_truesize(rx_ring, size);
19822123

19832124
pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;
19842125

@@ -1990,19 +2131,29 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
19902131
}
19912132

19922133
if (!skb) {
1993-
struct igc_adapter *adapter = q_vector->adapter;
1994-
19952134
xdp.data = pktbuf + pkt_offset;
19962135
xdp.data_end = xdp.data + size;
19972136
xdp.data_hard_start = pktbuf - igc_rx_offset(rx_ring);
19982137
xdp_set_data_meta_invalid(&xdp);
1999-
xdp.frame_sz = igc_get_rx_frame_truesize(rx_ring, size);
2138+
xdp.frame_sz = truesize;
2139+
xdp.rxq = &rx_ring->xdp_rxq;
20002140

20012141
skb = igc_xdp_run_prog(adapter, &xdp);
20022142
}
20032143

20042144
if (IS_ERR(skb)) {
2005-
rx_buffer->pagecnt_bias++;
2145+
unsigned int xdp_res = -PTR_ERR(skb);
2146+
2147+
switch (xdp_res) {
2148+
case IGC_XDP_CONSUMED:
2149+
rx_buffer->pagecnt_bias++;
2150+
break;
2151+
case IGC_XDP_TX:
2152+
igc_rx_buffer_flip(rx_buffer, truesize);
2153+
xdp_status |= xdp_res;
2154+
break;
2155+
}
2156+
20062157
total_packets++;
20072158
total_bytes += size;
20082159
} else if (skb)
@@ -2048,6 +2199,9 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
20482199
total_packets++;
20492200
}
20502201

2202+
if (xdp_status)
2203+
igc_finalize_xdp(adapter, xdp_status);
2204+
20512205
/* place incomplete frames back on ring for completion */
20522206
rx_ring->skb = skb;
20532207

@@ -2109,8 +2263,10 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
21092263
total_bytes += tx_buffer->bytecount;
21102264
total_packets += tx_buffer->gso_segs;
21112265

2112-
/* free the skb */
2113-
napi_consume_skb(tx_buffer->skb, napi_budget);
2266+
if (tx_buffer->tx_flags & IGC_TX_FLAGS_XDP)
2267+
xdp_return_frame(tx_buffer->xdpf);
2268+
else
2269+
napi_consume_skb(tx_buffer->skb, napi_budget);
21142270

21152271
/* unmap skb header data */
21162272
dma_unmap_single(tx_ring->dev,

drivers/net/ethernet/intel/igc/igc_xdp.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,30 @@ int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
3131

3232
return 0;
3333
}
34+
35+
int igc_xdp_register_rxq_info(struct igc_ring *ring)
36+
{
37+
struct net_device *dev = ring->netdev;
38+
int err;
39+
40+
err = xdp_rxq_info_reg(&ring->xdp_rxq, dev, ring->queue_index, 0);
41+
if (err) {
42+
netdev_err(dev, "Failed to register xdp rxq info\n");
43+
return err;
44+
}
45+
46+
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, MEM_TYPE_PAGE_SHARED,
47+
NULL);
48+
if (err) {
49+
netdev_err(dev, "Failed to register xdp rxq mem model\n");
50+
xdp_rxq_info_unreg(&ring->xdp_rxq);
51+
return err;
52+
}
53+
54+
return 0;
55+
}
56+
57+
void igc_xdp_unregister_rxq_info(struct igc_ring *ring)
58+
{
59+
xdp_rxq_info_unreg(&ring->xdp_rxq);
60+
}

drivers/net/ethernet/intel/igc/igc_xdp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@
77
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
88
struct netlink_ext_ack *extack);
99

10+
int igc_xdp_register_rxq_info(struct igc_ring *ring);
11+
void igc_xdp_unregister_rxq_info(struct igc_ring *ring);
12+
1013
#endif /* _IGC_XDP_H_ */

0 commit comments

Comments
 (0)