Skip to content

Commit 2657510

Browse files
Andre Guedesanguy11
Andre Guedes
authored andcommitted
igc: Add initial XDP support
Add the initial XDP support to the igc driver. For now, only XDP_PASS, XDP_DROP, XDP_ABORTED actions are supported. Upcoming patches will add support for the remaining XDP actions. XDP configuration helpers are defined in a new file, igc_xdp.c. These helpers are utilized in igc_main.c to implement the ndo_bpf callback. XDP-related code that belongs to the driver's hot path is landed in igc_main.c. By default, the driver uses Rx buffers with 2 KB size. When XDP is enabled, it uses larger buffers so we have enough space to accommodate the headroom and tailroom required by XDP infrastructure. Also, the driver doesn't support XDP functionality with frames that span over multiple buffers so jumbo frames are not allowed for now. The approach implemented follows the approach implemented in other Intel drivers as much as possible for the sake of consistency across the drivers. Quick comment regarding igc_build_skb(): this patch doesn't touch it because the function is never called. It seems its support is incomplete/in progress. The function was added by commit 0507ef8 ("igc: Add transmit and receive fastpath and interrupt handlers") but ring_uses_build_skb() always return False since the IGC_RING_FLAG_RX_ BUILD_SKB_ENABLED isn't set anywhere in the driver code. This patch has been tested with the sample app "xdp1" 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 1bf33f7 commit 2657510

File tree

5 files changed

+153
-12
lines changed

5 files changed

+153
-12
lines changed

drivers/net/ethernet/intel/igc/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
obj-$(CONFIG_IGC) += igc.o
99

1010
igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \
11-
igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o
11+
igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o igc_xdp.o

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

+2
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ struct igc_adapter {
219219
ktime_t ptp_reset_start; /* Reset time in clock mono */
220220

221221
char fw_version[32];
222+
223+
struct bpf_prog *xdp_prog;
222224
};
223225

224226
void igc_up(struct igc_adapter *adapter);

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

+107-11
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,22 @@
1010
#include <linux/ip.h>
1111
#include <linux/pm_runtime.h>
1212
#include <net/pkt_sched.h>
13+
#include <linux/bpf_trace.h>
1314

1415
#include <net/ipv6.h>
1516

1617
#include "igc.h"
1718
#include "igc_hw.h"
1819
#include "igc_tsn.h"
20+
#include "igc_xdp.h"
1921

2022
#define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver"
2123

2224
#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
2325

26+
#define IGC_XDP_PASS 0
27+
#define IGC_XDP_CONSUMED BIT(0)
28+
2429
static int debug = -1;
2530

2631
MODULE_AUTHOR("Intel Corporation, <[email protected]>");
@@ -375,6 +380,8 @@ static void igc_clean_rx_ring(struct igc_ring *rx_ring)
375380
i = 0;
376381
}
377382

383+
clear_ring_uses_large_buffer(rx_ring);
384+
378385
rx_ring->next_to_alloc = 0;
379386
rx_ring->next_to_clean = 0;
380387
rx_ring->next_to_use = 0;
@@ -497,6 +504,11 @@ static int igc_setup_all_rx_resources(struct igc_adapter *adapter)
497504
return err;
498505
}
499506

507+
static bool igc_xdp_is_enabled(struct igc_adapter *adapter)
508+
{
509+
return !!adapter->xdp_prog;
510+
}
511+
500512
/**
501513
* igc_configure_rx_ring - Configure a receive ring after Reset
502514
* @adapter: board private structure
@@ -513,6 +525,9 @@ static void igc_configure_rx_ring(struct igc_adapter *adapter,
513525
u32 srrctl = 0, rxdctl = 0;
514526
u64 rdba = ring->dma;
515527

528+
if (igc_xdp_is_enabled(adapter))
529+
set_ring_uses_large_buffer(ring);
530+
516531
/* disable the queue */
517532
wr32(IGC_RXDCTL(reg_idx), 0);
518533

@@ -1581,12 +1596,12 @@ static struct sk_buff *igc_build_skb(struct igc_ring *rx_ring,
15811596

15821597
static struct sk_buff *igc_construct_skb(struct igc_ring *rx_ring,
15831598
struct igc_rx_buffer *rx_buffer,
1584-
unsigned int size, int pkt_offset,
1599+
struct xdp_buff *xdp,
15851600
ktime_t timestamp)
15861601
{
1587-
void *va = page_address(rx_buffer->page) + rx_buffer->page_offset +
1588-
pkt_offset;
1602+
unsigned int size = xdp->data_end - xdp->data;
15891603
unsigned int truesize = igc_get_rx_frame_truesize(rx_ring, size);
1604+
void *va = xdp->data;
15901605
unsigned int headlen;
15911606
struct sk_buff *skb;
15921607

@@ -1730,6 +1745,10 @@ static bool igc_cleanup_headers(struct igc_ring *rx_ring,
17301745
union igc_adv_rx_desc *rx_desc,
17311746
struct sk_buff *skb)
17321747
{
1748+
/* XDP packets use error pointer so abort at this point */
1749+
if (IS_ERR(skb))
1750+
return true;
1751+
17331752
if (unlikely(igc_test_staterr(rx_desc, IGC_RXDEXT_STATERR_RXE))) {
17341753
struct net_device *netdev = rx_ring->netdev;
17351754

@@ -1769,7 +1788,14 @@ static void igc_put_rx_buffer(struct igc_ring *rx_ring,
17691788

17701789
static inline unsigned int igc_rx_offset(struct igc_ring *rx_ring)
17711790
{
1772-
return ring_uses_build_skb(rx_ring) ? IGC_SKB_PAD : 0;
1791+
struct igc_adapter *adapter = rx_ring->q_vector->adapter;
1792+
1793+
if (ring_uses_build_skb(rx_ring))
1794+
return IGC_SKB_PAD;
1795+
if (igc_xdp_is_enabled(adapter))
1796+
return XDP_PACKET_HEADROOM;
1797+
1798+
return 0;
17731799
}
17741800

17751801
static bool igc_alloc_mapped_page(struct igc_ring *rx_ring,
@@ -1883,6 +1909,42 @@ static void igc_alloc_rx_buffers(struct igc_ring *rx_ring, u16 cleaned_count)
18831909
}
18841910
}
18851911

1912+
static struct sk_buff *igc_xdp_run_prog(struct igc_adapter *adapter,
1913+
struct xdp_buff *xdp)
1914+
{
1915+
struct bpf_prog *prog;
1916+
int res;
1917+
u32 act;
1918+
1919+
rcu_read_lock();
1920+
1921+
prog = READ_ONCE(adapter->xdp_prog);
1922+
if (!prog) {
1923+
res = IGC_XDP_PASS;
1924+
goto unlock;
1925+
}
1926+
1927+
act = bpf_prog_run_xdp(prog, xdp);
1928+
switch (act) {
1929+
case XDP_PASS:
1930+
res = IGC_XDP_PASS;
1931+
break;
1932+
default:
1933+
bpf_warn_invalid_xdp_action(act);
1934+
fallthrough;
1935+
case XDP_ABORTED:
1936+
trace_xdp_exception(adapter->netdev, prog, act);
1937+
fallthrough;
1938+
case XDP_DROP:
1939+
res = IGC_XDP_CONSUMED;
1940+
break;
1941+
}
1942+
1943+
unlock:
1944+
rcu_read_unlock();
1945+
return ERR_PTR(-res);
1946+
}
1947+
18861948
static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
18871949
{
18881950
unsigned int total_bytes = 0, total_packets = 0;
@@ -1894,8 +1956,10 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
18941956
union igc_adv_rx_desc *rx_desc;
18951957
struct igc_rx_buffer *rx_buffer;
18961958
ktime_t timestamp = 0;
1959+
struct xdp_buff xdp;
18971960
int pkt_offset = 0;
18981961
unsigned int size;
1962+
void *pktbuf;
18991963

19001964
/* return some buffers to hardware, one at a time is too slow */
19011965
if (cleaned_count >= IGC_RX_BUFFER_WRITE) {
@@ -1916,24 +1980,38 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
19161980

19171981
rx_buffer = igc_get_rx_buffer(rx_ring, size);
19181982

1919-
if (igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP)) {
1920-
void *pktbuf = page_address(rx_buffer->page) +
1921-
rx_buffer->page_offset;
1983+
pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;
19221984

1985+
if (igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP)) {
19231986
timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
19241987
pktbuf);
19251988
pkt_offset = IGC_TS_HDR_LEN;
19261989
size -= IGC_TS_HDR_LEN;
19271990
}
19281991

1929-
/* retrieve a buffer from the ring */
1930-
if (skb)
1992+
if (!skb) {
1993+
struct igc_adapter *adapter = q_vector->adapter;
1994+
1995+
xdp.data = pktbuf + pkt_offset;
1996+
xdp.data_end = xdp.data + size;
1997+
xdp.data_hard_start = pktbuf - igc_rx_offset(rx_ring);
1998+
xdp_set_data_meta_invalid(&xdp);
1999+
xdp.frame_sz = igc_get_rx_frame_truesize(rx_ring, size);
2000+
2001+
skb = igc_xdp_run_prog(adapter, &xdp);
2002+
}
2003+
2004+
if (IS_ERR(skb)) {
2005+
rx_buffer->pagecnt_bias++;
2006+
total_packets++;
2007+
total_bytes += size;
2008+
} else if (skb)
19312009
igc_add_rx_frag(rx_ring, rx_buffer, skb, size);
19322010
else if (ring_uses_build_skb(rx_ring))
19332011
skb = igc_build_skb(rx_ring, rx_buffer, rx_desc, size);
19342012
else
1935-
skb = igc_construct_skb(rx_ring, rx_buffer, size,
1936-
pkt_offset, timestamp);
2013+
skb = igc_construct_skb(rx_ring, rx_buffer, &xdp,
2014+
timestamp);
19372015

19382016
/* exit if we failed to retrieve a buffer */
19392017
if (!skb) {
@@ -3874,6 +3952,11 @@ static int igc_change_mtu(struct net_device *netdev, int new_mtu)
38743952
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
38753953
struct igc_adapter *adapter = netdev_priv(netdev);
38763954

3955+
if (igc_xdp_is_enabled(adapter) && new_mtu > ETH_DATA_LEN) {
3956+
netdev_dbg(netdev, "Jumbo frames not supported with XDP");
3957+
return -EINVAL;
3958+
}
3959+
38773960
/* adjust max frame to be at least the size of a standard frame */
38783961
if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
38793962
max_frame = ETH_FRAME_LEN + ETH_FCS_LEN;
@@ -4860,6 +4943,18 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
48604943
}
48614944
}
48624945

4946+
static int igc_bpf(struct net_device *dev, struct netdev_bpf *bpf)
4947+
{
4948+
struct igc_adapter *adapter = netdev_priv(dev);
4949+
4950+
switch (bpf->command) {
4951+
case XDP_SETUP_PROG:
4952+
return igc_xdp_set_prog(adapter, bpf->prog, bpf->extack);
4953+
default:
4954+
return -EOPNOTSUPP;
4955+
}
4956+
}
4957+
48634958
static const struct net_device_ops igc_netdev_ops = {
48644959
.ndo_open = igc_open,
48654960
.ndo_stop = igc_close,
@@ -4873,6 +4968,7 @@ static const struct net_device_ops igc_netdev_ops = {
48734968
.ndo_features_check = igc_features_check,
48744969
.ndo_do_ioctl = igc_ioctl,
48754970
.ndo_setup_tc = igc_setup_tc,
4971+
.ndo_bpf = igc_bpf,
48764972
};
48774973

48784974
/* PCIe configuration access */
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2020, Intel Corporation. */
3+
4+
#include "igc.h"
5+
#include "igc_xdp.h"
6+
7+
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
8+
struct netlink_ext_ack *extack)
9+
{
10+
struct net_device *dev = adapter->netdev;
11+
bool if_running = netif_running(dev);
12+
struct bpf_prog *old_prog;
13+
14+
if (dev->mtu > ETH_DATA_LEN) {
15+
/* For now, the driver doesn't support XDP functionality with
16+
* jumbo frames so we return error.
17+
*/
18+
NL_SET_ERR_MSG_MOD(extack, "Jumbo frames not supported");
19+
return -EOPNOTSUPP;
20+
}
21+
22+
if (if_running)
23+
igc_close(dev);
24+
25+
old_prog = xchg(&adapter->xdp_prog, prog);
26+
if (old_prog)
27+
bpf_prog_put(old_prog);
28+
29+
if (if_running)
30+
igc_open(dev);
31+
32+
return 0;
33+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2020, Intel Corporation. */
3+
4+
#ifndef _IGC_XDP_H_
5+
#define _IGC_XDP_H_
6+
7+
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
8+
struct netlink_ext_ack *extack);
9+
10+
#endif /* _IGC_XDP_H_ */

0 commit comments

Comments
 (0)