2018-01-03 11:25:13 +01:00
/* 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 .
*/
2018-04-17 16:45:26 +02:00
enum xdp_mem_type {
MEM_TYPE_PAGE_SHARED = 0 , /* Split-page refcnt based model */
MEM_TYPE_PAGE_ORDER0 , /* Orig XDP full page model */
MEM_TYPE_MAX ,
} ;
struct xdp_mem_info {
u32 type ; /* enum xdp_mem_type, but known size type */
} ;
2018-01-03 11:25:13 +01:00
struct xdp_rxq_info {
struct net_device * dev ;
u32 queue_index ;
u32 reg_state ;
2018-04-17 16:45:26 +02:00
struct xdp_mem_info mem ;
2018-01-03 11:25:13 +01:00
} ____cacheline_aligned ; /* perf critical, avoid false-sharing */
2018-04-17 16:45:37 +02:00
struct xdp_buff {
void * data ;
void * data_end ;
void * data_meta ;
void * data_hard_start ;
struct xdp_rxq_info * rxq ;
} ;
2018-04-17 16:45:26 +02:00
static inline
void xdp_return_frame ( void * data , struct xdp_mem_info * mem )
{
if ( mem - > type = = MEM_TYPE_PAGE_SHARED )
page_frag_free ( data ) ;
if ( mem - > type = = MEM_TYPE_PAGE_ORDER0 ) {
struct page * page = virt_to_page ( data ) ; /* Assumes order0 page*/
put_page ( page ) ;
}
}
2018-01-03 11:25:13 +01:00
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 ) ;
2018-01-03 11:25:34 +01:00
bool xdp_rxq_info_is_reg ( struct xdp_rxq_info * xdp_rxq ) ;
2018-04-17 16:45:26 +02:00
int xdp_rxq_info_reg_mem_model ( struct xdp_rxq_info * xdp_rxq ,
enum xdp_mem_type type , void * allocator ) ;
2018-01-03 11:25:13 +01:00
2018-04-17 16:45:37 +02:00
/* Drivers not supporting XDP metadata can use this helper, which
* rejects any room expansion for metadata as a result .
*/
static __always_inline void
xdp_set_data_meta_invalid ( struct xdp_buff * xdp )
{
xdp - > data_meta = xdp - > data + 1 ;
}
static __always_inline bool
xdp_data_meta_unsupported ( const struct xdp_buff * xdp )
{
return unlikely ( xdp - > data_meta > xdp - > data ) ;
}
2018-01-03 11:25:13 +01:00
# endif /* __LINUX_NET_XDP_H__ */