@@ -25,6 +25,7 @@
* application.
*/
#define XDP_USE_NEED_WAKEUP (1 << 3)
+#define XDP_CHECK_NATIVE_MODE (1 << 4)
/* Flags for xsk_umem_config flags */
#define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0)
@@ -764,7 +764,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
flags = sxdp->sxdp_flags;
if (flags & ~(XDP_SHARED_UMEM | XDP_COPY | XDP_ZEROCOPY |
- XDP_USE_NEED_WAKEUP))
+ XDP_USE_NEED_WAKEUP | XDP_CHECK_NATIVE_MODE))
return -EINVAL;
rtnl_lock();
@@ -792,7 +792,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
struct socket *sock;
if ((flags & XDP_COPY) || (flags & XDP_ZEROCOPY) ||
- (flags & XDP_USE_NEED_WAKEUP)) {
+ (flags & XDP_USE_NEED_WAKEUP) || (flags & XDP_CHECK_NATIVE_MODE)) {
/* Cannot specify flags for shared sockets. */
err = -EINVAL;
goto out_unlock;
@@ -123,7 +123,7 @@ static void xp_disable_drv_zc(struct xsk_buff_pool *pool)
static int __xp_assign_dev(struct xsk_buff_pool *pool,
struct net_device *netdev, u16 queue_id, u16 flags)
{
- bool force_zc, force_copy;
+ bool force_zc, force_copy, force_check;
struct netdev_bpf bpf;
int err = 0;
@@ -131,10 +131,24 @@ static int __xp_assign_dev(struct xsk_buff_pool *pool,
force_zc = flags & XDP_ZEROCOPY;
force_copy = flags & XDP_COPY;
+ force_check = flags & XDP_CHECK_NATIVE_MODE;
+
if (force_zc && force_copy)
return -EINVAL;
+ if (!(flags & XDP_SHARED_UMEM)) {
+ if (force_check) {
+ /* forbid driver mode without full XDP support */
+ if (!(XDP_F_REDIRECT & netdev->xdp_properties))
+ return -EOPNOTSUPP;
+ } else {
+ /* forbid skb mode and zero copy */
+ if (force_zc)
+ return -EINVAL;
+ }
+ }
+
if (xsk_get_pool_from_qid(netdev, queue_id))
return -EBUSY;
@@ -204,6 +218,7 @@ int xp_assign_dev_shared(struct xsk_buff_pool *pool, struct xdp_umem *umem,
return -EINVAL;
flags = umem->zc ? XDP_ZEROCOPY : XDP_COPY;
+ flags |= XDP_SHARED_UMEM;
if (pool->uses_need_wakeup)
flags |= XDP_USE_NEED_WAKEUP;
@@ -25,6 +25,7 @@
* application.
*/
#define XDP_USE_NEED_WAKEUP (1 << 3)
+#define XDP_CHECK_NATIVE_MODE (1 << 4)
/* Flags for xsk_umem_config flags */
#define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0)
@@ -18,6 +18,7 @@
#include <linux/ethtool.h>
#include <linux/filter.h>
#include <linux/if_ether.h>
+#include <linux/if_link.h>
#include <linux/if_packet.h>
#include <linux/if_xdp.h>
#include <linux/kernel.h>
@@ -901,6 +902,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
sxdp.sxdp_shared_umem_fd = umem->fd;
} else {
sxdp.sxdp_flags = xsk->config.bind_flags;
+ if (xsk->config.xdp_flags & XDP_FLAGS_DRV_MODE)
+ sxdp.sxdp_flags |= XDP_CHECK_NATIVE_MODE;
}
err = bind(xsk->fd, (struct sockaddr *)&sxdp, sizeof(sxdp));