net: add ndo to setup/query xdp prog in adapter rx

Add one new netdev op for drivers implementing the BPF_PROG_TYPE_XDP
filter. The single op is used for both setup/query of the xdp program,
modelled after ndo_setup_tc.

Signed-off-by: Brenden Blanco <bblanco@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Brenden Blanco 2016-07-19 12:16:48 -07:00 committed by David S. Miller
parent 6a773a15a1
commit a7862b4584
2 changed files with 67 additions and 0 deletions

View File

@ -63,6 +63,7 @@ struct wpan_dev;
struct mpls_dev; struct mpls_dev;
/* UDP Tunnel offloads */ /* UDP Tunnel offloads */
struct udp_tunnel_info; struct udp_tunnel_info;
struct bpf_prog;
void netdev_set_default_ethtool_ops(struct net_device *dev, void netdev_set_default_ethtool_ops(struct net_device *dev,
const struct ethtool_ops *ops); const struct ethtool_ops *ops);
@ -799,6 +800,33 @@ struct tc_to_netdev {
}; };
}; };
/* These structures hold the attributes of xdp state that are being passed
* to the netdevice through the xdp op.
*/
enum xdp_netdev_command {
/* Set or clear a bpf program used in the earliest stages of packet
* rx. The prog will have been loaded as BPF_PROG_TYPE_XDP. The callee
* is responsible for calling bpf_prog_put on any old progs that are
* stored. In case of error, the callee need not release the new prog
* reference, but on success it takes ownership and must bpf_prog_put
* when it is no longer used.
*/
XDP_SETUP_PROG,
/* Check if a bpf program is set on the device. The callee should
* return true if a program is currently attached and running.
*/
XDP_QUERY_PROG,
};
struct netdev_xdp {
enum xdp_netdev_command command;
union {
/* XDP_SETUP_PROG */
struct bpf_prog *prog;
/* XDP_QUERY_PROG */
bool prog_attached;
};
};
/* /*
* This structure defines the management hooks for network devices. * This structure defines the management hooks for network devices.
@ -1087,6 +1115,9 @@ struct tc_to_netdev {
* appropriate rx headroom value allows avoiding skb head copy on * appropriate rx headroom value allows avoiding skb head copy on
* forward. Setting a negative value resets the rx headroom to the * forward. Setting a negative value resets the rx headroom to the
* default value. * default value.
* int (*ndo_xdp)(struct net_device *dev, struct netdev_xdp *xdp);
* This function is used to set or query state related to XDP on the
* netdevice. See definition of enum xdp_netdev_command for details.
* *
*/ */
struct net_device_ops { struct net_device_ops {
@ -1271,6 +1302,8 @@ struct net_device_ops {
struct sk_buff *skb); struct sk_buff *skb);
void (*ndo_set_rx_headroom)(struct net_device *dev, void (*ndo_set_rx_headroom)(struct net_device *dev,
int needed_headroom); int needed_headroom);
int (*ndo_xdp)(struct net_device *dev,
struct netdev_xdp *xdp);
}; };
/** /**
@ -3257,6 +3290,7 @@ int dev_get_phys_port_id(struct net_device *dev,
int dev_get_phys_port_name(struct net_device *dev, int dev_get_phys_port_name(struct net_device *dev,
char *name, size_t len); char *name, size_t len);
int dev_change_proto_down(struct net_device *dev, bool proto_down); int dev_change_proto_down(struct net_device *dev, bool proto_down);
int dev_change_xdp_fd(struct net_device *dev, int fd);
struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev); struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev);
struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
struct netdev_queue *txq, int *ret); struct netdev_queue *txq, int *ret);

View File

@ -94,6 +94,7 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/bpf.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/busy_poll.h> #include <net/busy_poll.h>
@ -6614,6 +6615,38 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
} }
EXPORT_SYMBOL(dev_change_proto_down); EXPORT_SYMBOL(dev_change_proto_down);
/**
* dev_change_xdp_fd - set or clear a bpf program for a device rx path
* @dev: device
* @fd: new program fd or negative value to clear
*
* Set or clear a bpf program for a device
*/
int dev_change_xdp_fd(struct net_device *dev, int fd)
{
const struct net_device_ops *ops = dev->netdev_ops;
struct bpf_prog *prog = NULL;
struct netdev_xdp xdp = {};
int err;
if (!ops->ndo_xdp)
return -EOPNOTSUPP;
if (fd >= 0) {
prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
if (IS_ERR(prog))
return PTR_ERR(prog);
}
xdp.command = XDP_SETUP_PROG;
xdp.prog = prog;
err = ops->ndo_xdp(dev, &xdp);
if (err < 0 && prog)
bpf_prog_put(prog);
return err;
}
EXPORT_SYMBOL(dev_change_xdp_fd);
/** /**
* dev_new_index - allocate an ifindex * dev_new_index - allocate an ifindex
* @net: the applicable net namespace * @net: the applicable net namespace