forked from Minki/linux
Merge branch 'generic-xdp-followups'
Daniel Borkmann says: ==================== Two generic xdp related follow-ups Two follow-ups for the generic XDP API, would be great if both could still be considered, since the XDP API is not frozen yet. For details please see individual patches. v1 -> v2: - Implemented feedback from Jakub Kicinski (reusing attribute on dump), thanks! - Rest as is. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4e3c60ed2f
@ -3296,11 +3296,15 @@ int dev_get_phys_port_id(struct net_device *dev,
|
||||
int dev_get_phys_port_name(struct net_device *dev,
|
||||
char *name, size_t len);
|
||||
int dev_change_proto_down(struct net_device *dev, bool proto_down);
|
||||
int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
|
||||
int fd, u32 flags);
|
||||
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 netdev_queue *txq, int *ret);
|
||||
|
||||
typedef int (*xdp_op_t)(struct net_device *dev, struct netdev_xdp *xdp);
|
||||
int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
|
||||
int fd, u32 flags);
|
||||
bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op);
|
||||
|
||||
int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
|
||||
int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
|
||||
bool is_skb_forwardable(const struct net_device *dev,
|
||||
|
@ -888,9 +888,18 @@ enum {
|
||||
/* XDP section */
|
||||
|
||||
#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0)
|
||||
#define XDP_FLAGS_SKB_MODE (2U << 0)
|
||||
#define XDP_FLAGS_SKB_MODE (1U << 1)
|
||||
#define XDP_FLAGS_DRV_MODE (1U << 2)
|
||||
#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \
|
||||
XDP_FLAGS_SKB_MODE)
|
||||
XDP_FLAGS_SKB_MODE | \
|
||||
XDP_FLAGS_DRV_MODE)
|
||||
|
||||
/* These are stored into IFLA_XDP_ATTACHED on dump. */
|
||||
enum {
|
||||
XDP_ATTACHED_NONE = 0,
|
||||
XDP_ATTACHED_DRV,
|
||||
XDP_ATTACHED_SKB,
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_XDP_UNSPEC,
|
||||
|
@ -6852,6 +6852,32 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
|
||||
}
|
||||
EXPORT_SYMBOL(dev_change_proto_down);
|
||||
|
||||
bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op)
|
||||
{
|
||||
struct netdev_xdp xdp;
|
||||
|
||||
memset(&xdp, 0, sizeof(xdp));
|
||||
xdp.command = XDP_QUERY_PROG;
|
||||
|
||||
/* Query must always succeed. */
|
||||
WARN_ON(xdp_op(dev, &xdp) < 0);
|
||||
return xdp.prog_attached;
|
||||
}
|
||||
|
||||
static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
|
||||
struct netlink_ext_ack *extack,
|
||||
struct bpf_prog *prog)
|
||||
{
|
||||
struct netdev_xdp xdp;
|
||||
|
||||
memset(&xdp, 0, sizeof(xdp));
|
||||
xdp.command = XDP_SETUP_PROG;
|
||||
xdp.extack = extack;
|
||||
xdp.prog = prog;
|
||||
|
||||
return xdp_op(dev, &xdp);
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_change_xdp_fd - set or clear a bpf program for a device rx path
|
||||
* @dev: device
|
||||
@ -6864,41 +6890,34 @@ EXPORT_SYMBOL(dev_change_proto_down);
|
||||
int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
|
||||
int fd, u32 flags)
|
||||
{
|
||||
int (*xdp_op)(struct net_device *dev, struct netdev_xdp *xdp);
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
struct bpf_prog *prog = NULL;
|
||||
struct netdev_xdp xdp;
|
||||
xdp_op_t xdp_op, xdp_chk;
|
||||
int err;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
xdp_op = ops->ndo_xdp;
|
||||
xdp_op = xdp_chk = ops->ndo_xdp;
|
||||
if (!xdp_op && (flags & XDP_FLAGS_DRV_MODE))
|
||||
return -EOPNOTSUPP;
|
||||
if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE))
|
||||
xdp_op = generic_xdp_install;
|
||||
if (xdp_op == xdp_chk)
|
||||
xdp_chk = generic_xdp_install;
|
||||
|
||||
if (fd >= 0) {
|
||||
if (flags & XDP_FLAGS_UPDATE_IF_NOEXIST) {
|
||||
memset(&xdp, 0, sizeof(xdp));
|
||||
xdp.command = XDP_QUERY_PROG;
|
||||
|
||||
err = xdp_op(dev, &xdp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (xdp.prog_attached)
|
||||
return -EBUSY;
|
||||
}
|
||||
if (xdp_chk && __dev_xdp_attached(dev, xdp_chk))
|
||||
return -EEXIST;
|
||||
if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
|
||||
__dev_xdp_attached(dev, xdp_op))
|
||||
return -EBUSY;
|
||||
|
||||
prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
|
||||
if (IS_ERR(prog))
|
||||
return PTR_ERR(prog);
|
||||
}
|
||||
|
||||
memset(&xdp, 0, sizeof(xdp));
|
||||
xdp.command = XDP_SETUP_PROG;
|
||||
xdp.extack = extack;
|
||||
xdp.prog = prog;
|
||||
|
||||
err = xdp_op(dev, &xdp);
|
||||
err = dev_xdp_install(dev, xdp_op, extack, prog);
|
||||
if (err < 0 && prog)
|
||||
bpf_prog_put(prog);
|
||||
|
||||
|
@ -899,8 +899,7 @@ static size_t rtnl_port_size(const struct net_device *dev,
|
||||
static size_t rtnl_xdp_size(void)
|
||||
{
|
||||
size_t xdp_size = nla_total_size(0) + /* nest IFLA_XDP */
|
||||
nla_total_size(1) + /* XDP_ATTACHED */
|
||||
nla_total_size(4); /* XDP_FLAGS */
|
||||
nla_total_size(1); /* XDP_ATTACHED */
|
||||
|
||||
return xdp_size;
|
||||
}
|
||||
@ -1247,37 +1246,34 @@ static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 rtnl_xdp_attached_mode(struct net_device *dev)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (rcu_access_pointer(dev->xdp_prog))
|
||||
return XDP_ATTACHED_SKB;
|
||||
if (ops->ndo_xdp && __dev_xdp_attached(dev, ops->ndo_xdp))
|
||||
return XDP_ATTACHED_DRV;
|
||||
|
||||
return XDP_ATTACHED_NONE;
|
||||
}
|
||||
|
||||
static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct nlattr *xdp;
|
||||
u32 xdp_flags = 0;
|
||||
u8 val = 0;
|
||||
int err;
|
||||
|
||||
xdp = nla_nest_start(skb, IFLA_XDP);
|
||||
if (!xdp)
|
||||
return -EMSGSIZE;
|
||||
if (rcu_access_pointer(dev->xdp_prog)) {
|
||||
xdp_flags = XDP_FLAGS_SKB_MODE;
|
||||
val = 1;
|
||||
} else if (dev->netdev_ops->ndo_xdp) {
|
||||
struct netdev_xdp xdp_op = {};
|
||||
|
||||
xdp_op.command = XDP_QUERY_PROG;
|
||||
err = dev->netdev_ops->ndo_xdp(dev, &xdp_op);
|
||||
if (err)
|
||||
goto err_cancel;
|
||||
val = xdp_op.prog_attached;
|
||||
}
|
||||
err = nla_put_u8(skb, IFLA_XDP_ATTACHED, val);
|
||||
err = nla_put_u8(skb, IFLA_XDP_ATTACHED,
|
||||
rtnl_xdp_attached_mode(dev));
|
||||
if (err)
|
||||
goto err_cancel;
|
||||
|
||||
if (xdp_flags) {
|
||||
err = nla_put_u32(skb, IFLA_XDP_FLAGS, xdp_flags);
|
||||
if (err)
|
||||
goto err_cancel;
|
||||
}
|
||||
nla_nest_end(skb, xdp);
|
||||
return 0;
|
||||
|
||||
@ -2199,6 +2195,11 @@ static int do_setlink(const struct sk_buff *skb,
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
if ((xdp_flags & XDP_FLAGS_SKB_MODE) &&
|
||||
(xdp_flags & XDP_FLAGS_DRV_MODE)) {
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
if (xdp[IFLA_XDP_FD]) {
|
||||
|
@ -62,13 +62,14 @@ static void usage(const char *prog)
|
||||
fprintf(stderr,
|
||||
"usage: %s [OPTS] IFINDEX\n\n"
|
||||
"OPTS:\n"
|
||||
" -S use skb-mode\n",
|
||||
" -S use skb-mode\n"
|
||||
" -N enforce native mode\n",
|
||||
prog);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *optstr = "S";
|
||||
const char *optstr = "SN";
|
||||
char filename[256];
|
||||
int opt;
|
||||
|
||||
@ -77,6 +78,9 @@ int main(int argc, char **argv)
|
||||
case 'S':
|
||||
xdp_flags |= XDP_FLAGS_SKB_MODE;
|
||||
break;
|
||||
case 'N':
|
||||
xdp_flags |= XDP_FLAGS_DRV_MODE;
|
||||
break;
|
||||
default:
|
||||
usage(basename(argv[0]));
|
||||
return 1;
|
||||
|
@ -79,6 +79,8 @@ static void usage(const char *cmd)
|
||||
printf(" -m <dest-MAC> Used in sending the IP Tunneled pkt\n");
|
||||
printf(" -T <stop-after-X-seconds> Default: 0 (forever)\n");
|
||||
printf(" -P <IP-Protocol> Default is TCP\n");
|
||||
printf(" -S use skb-mode\n");
|
||||
printf(" -N enforce native mode\n");
|
||||
printf(" -h Display this help\n");
|
||||
}
|
||||
|
||||
@ -138,7 +140,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
unsigned char opt_flags[256] = {};
|
||||
unsigned int kill_after_s = 0;
|
||||
const char *optstr = "i:a:p:s:d:m:T:P:Sh";
|
||||
const char *optstr = "i:a:p:s:d:m:T:P:SNh";
|
||||
int min_port = 0, max_port = 0;
|
||||
struct iptnl_info tnl = {};
|
||||
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
|
||||
@ -206,6 +208,9 @@ int main(int argc, char **argv)
|
||||
case 'S':
|
||||
xdp_flags |= XDP_FLAGS_SKB_MODE;
|
||||
break;
|
||||
case 'N':
|
||||
xdp_flags |= XDP_FLAGS_DRV_MODE;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user