-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
xdp: base API for new XDP rx-queue info concept
This patch only introduce the core data structures and API functions. All XDP enabled drivers must use the API before this info can used. There is a need for XDP to know more about the RX-queue a given XDP frames have arrived on. For both the XDP bpf-prog and kernel side. Instead of extending xdp_buff each time new info is needed, the patch creates a separate read-mostly struct xdp_rxq_info, that contains this info. We stress this data/cache-line is for read-only info. This is NOT for dynamic per packet info, use the data_meta for such use-cases. The performance advantage is this info can be setup at RX-ring init time, instead of updating N-members in xdp_buff. A possible (driver level) micro optimization is that xdp_buff->rxq assignment could be done once per XDP/NAPI loop. The extra pointer deref only happens for program needing access to this info (thus, no slowdown to existing use-cases). Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
- Loading branch information
Jesper Dangaard Brouer
authored and
Alexei Starovoitov
committed
Jan 5, 2018
1 parent
5f103c5
commit aecd67b
Showing
4 changed files
with
117 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* include/net/xdp.h | ||
* | ||
* Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc. | ||
* Released under terms in GPL version 2. See COPYING. | ||
*/ | ||
#ifndef __LINUX_NET_XDP_H__ | ||
#define __LINUX_NET_XDP_H__ | ||
|
||
/** | ||
* DOC: XDP RX-queue information | ||
* | ||
* The XDP RX-queue info (xdp_rxq_info) is associated with the driver | ||
* level RX-ring queues. It is information that is specific to how | ||
* the driver have configured a given RX-ring queue. | ||
* | ||
* Each xdp_buff frame received in the driver carry a (pointer) | ||
* reference to this xdp_rxq_info structure. This provides the XDP | ||
* data-path read-access to RX-info for both kernel and bpf-side | ||
* (limited subset). | ||
* | ||
* For now, direct access is only safe while running in NAPI/softirq | ||
* context. Contents is read-mostly and must not be updated during | ||
* driver NAPI/softirq poll. | ||
* | ||
* The driver usage API is a register and unregister API. | ||
* | ||
* The struct is not directly tied to the XDP prog. A new XDP prog | ||
* can be attached as long as it doesn't change the underlying | ||
* RX-ring. If the RX-ring does change significantly, the NIC driver | ||
* naturally need to stop the RX-ring before purging and reallocating | ||
* memory. In that process the driver MUST call unregistor (which | ||
* also apply for driver shutdown and unload). The register API is | ||
* also mandatory during RX-ring setup. | ||
*/ | ||
|
||
struct xdp_rxq_info { | ||
struct net_device *dev; | ||
u32 queue_index; | ||
u32 reg_state; | ||
} ____cacheline_aligned; /* perf critical, avoid false-sharing */ | ||
|
||
int xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq, | ||
struct net_device *dev, u32 queue_index); | ||
void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq); | ||
void xdp_rxq_info_unused(struct xdp_rxq_info *xdp_rxq); | ||
|
||
#endif /* __LINUX_NET_XDP_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* net/core/xdp.c | ||
* | ||
* Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc. | ||
* Released under terms in GPL version 2. See COPYING. | ||
*/ | ||
#include <linux/types.h> | ||
#include <linux/mm.h> | ||
|
||
#include <net/xdp.h> | ||
|
||
#define REG_STATE_NEW 0x0 | ||
#define REG_STATE_REGISTERED 0x1 | ||
#define REG_STATE_UNREGISTERED 0x2 | ||
#define REG_STATE_UNUSED 0x3 | ||
|
||
void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq) | ||
{ | ||
/* Simplify driver cleanup code paths, allow unreg "unused" */ | ||
if (xdp_rxq->reg_state == REG_STATE_UNUSED) | ||
return; | ||
|
||
WARN(!(xdp_rxq->reg_state == REG_STATE_REGISTERED), "Driver BUG"); | ||
|
||
xdp_rxq->reg_state = REG_STATE_UNREGISTERED; | ||
xdp_rxq->dev = NULL; | ||
} | ||
EXPORT_SYMBOL_GPL(xdp_rxq_info_unreg); | ||
|
||
static void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq) | ||
{ | ||
memset(xdp_rxq, 0, sizeof(*xdp_rxq)); | ||
} | ||
|
||
/* Returns 0 on success, negative on failure */ | ||
int xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq, | ||
struct net_device *dev, u32 queue_index) | ||
{ | ||
if (xdp_rxq->reg_state == REG_STATE_UNUSED) { | ||
WARN(1, "Driver promised not to register this"); | ||
return -EINVAL; | ||
} | ||
|
||
if (xdp_rxq->reg_state == REG_STATE_REGISTERED) { | ||
WARN(1, "Missing unregister, handled but fix driver"); | ||
xdp_rxq_info_unreg(xdp_rxq); | ||
} | ||
|
||
if (!dev) { | ||
WARN(1, "Missing net_device from driver"); | ||
return -ENODEV; | ||
} | ||
|
||
/* State either UNREGISTERED or NEW */ | ||
xdp_rxq_info_init(xdp_rxq); | ||
xdp_rxq->dev = dev; | ||
xdp_rxq->queue_index = queue_index; | ||
|
||
xdp_rxq->reg_state = REG_STATE_REGISTERED; | ||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(xdp_rxq_info_reg); | ||
|
||
void xdp_rxq_info_unused(struct xdp_rxq_info *xdp_rxq) | ||
{ | ||
xdp_rxq->reg_state = REG_STATE_UNUSED; | ||
} | ||
EXPORT_SYMBOL_GPL(xdp_rxq_info_unused); |