[PATCH] Passing sk_buff metadata information to user space in TUNTAP driver.

Subsystems: networking drivers, the rest, tun/tap driver

STALE4782d

3 messages, 3 authors, 2013-08-21 · open the first message on its own page

[PATCH] Passing sk_buff metadata information to user space in TUNTAP driver.

From: Valas Valancius <hidden>
Date: 2013-08-19 20:30:36

From: Valas Valancius <redacted>

This patch introduces an optional metadata header to TUNTAP driver to pass
sk_buff information to user space. The patch currently enables passing
of skb->mark field and allows for easy expansion to add more sk_buff
fields later.

Tested: Compiled, booted. Process 1: openend TAP interface, enabled metadata
header on that interface. Process 2: opened a socket, set fwmark with SO_MARK
sock option, send packets, observed mark to propagate in Process 1.

Change-Id: I5d00522e9c4d9c1b57b4f4ac55c419a85de35dae
---
 drivers/net/tun.c           | 64 ++++++++++++++++++++++++++++++++++++++++++++-
 include/uapi/linux/if_tun.h |  7 +++++
 2 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 978d865..f997d59 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -103,6 +103,15 @@ do {								\
 
 #define GOODCOPY_LEN 128
 
+/* Metadata header structure. */
+struct tun_meta_header {
+	/* struct sk_buff.mark */
+	int mark;
+};
+
+#define TUN_META_HDR_SZ sizeof(struct tun_meta_header)
+#define TUN_META_MARK_OFFSET offsetof(struct tun_meta_header, mark)
+
 #define FLT_EXACT_COUNT 8
 struct tap_filter {
 	unsigned int    count;    /* Number of addrs. Zero means disabled */
@@ -1227,6 +1236,20 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 		total += tun->vnet_hdr_sz;
 	}
 
+	if (tun->flags & TUN_META_HDR) {
+		struct tun_meta_header meta = { 0 };
+		len -= TUN_META_HDR_SZ;
+		if (len < 0)
+			return -EINVAL;
+
+		meta.mark = skb->mark;
+
+		if (unlikely(memcpy_toiovecend(iv, (void *)&meta, total,
+					       sizeof(meta))))
+			return -EFAULT;
+		total += TUN_META_HDR_SZ;
+	}
+
 	if (!vlan_tx_tag_present(skb)) {
 		len = min_t(int, skb->len, len);
 	} else {
@@ -1487,6 +1510,9 @@ static int tun_flags(struct tun_struct *tun)
 	if (tun->flags & TUN_PERSIST)
 		flags |= IFF_PERSIST;
 
+	if (tun->flags & TUN_META_HDR)
+		flags |= IFF_META_HDR;
+
 	return flags;
 }
 
@@ -1666,6 +1692,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 	else
 		tun->flags &= ~TUN_TAP_MQ;
 
+	if (ifr->ifr_flags & IFF_META_HDR)
+		tun->flags |= TUN_META_HDR;
+	else
+		tun->flags &= ~TUN_META_HDR;
+
 	/* Make sure persistent devices do not get stuck in
 	 * xoff state.
 	 */
@@ -1815,6 +1846,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 	kgid_t group;
 	int sndbuf;
 	int vnet_hdr_sz;
+	int tun_meta_param;
+	int tun_meta_value;
 	int ret;
 
 	if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
@@ -1828,7 +1861,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		 * This is needed because we never checked for invalid flags on
 		 * TUNSETIFF. */
 		return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
-				IFF_VNET_HDR | IFF_MULTI_QUEUE,
+				IFF_VNET_HDR | IFF_MULTI_QUEUE | IFF_META_HDR,
 				(unsigned int __user*)argp);
 	} else if (cmd == TUNSETQUEUE)
 		return tun_set_queue(file, &ifr);
@@ -1996,6 +2029,35 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		tun->vnet_hdr_sz = vnet_hdr_sz;
 		break;
 
+	case TUNGETMETAPARAM:
+		if (copy_from_user(&tun_meta_param, argp,
+				   sizeof(tun_meta_param))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		ret = 0;
+		switch (tun_meta_param) {
+		case TUN_GET_META_HDR_SZ:
+			tun_meta_value = TUN_META_HDR_SZ;
+			break;
+
+		case TUN_GET_META_MARK_OFFSET:
+			tun_meta_value = TUN_META_MARK_OFFSET;
+			break;
+
+		default:
+			ret = -EINVAL;
+			break;
+		}
+
+		if (!ret)
+			if (copy_to_user(argp, &tun_meta_value,
+					 sizeof(tun_meta_value)))
+				ret = -EFAULT;
+		break;
+
+
 	case TUNATTACHFILTER:
 		/* Can be set only for TAPs */
 		ret = -EINVAL;
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 1870ee2..26e6c9e 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -36,6 +36,7 @@
 #define TUN_PERSIST 	0x0100	
 #define TUN_VNET_HDR 	0x0200
 #define TUN_TAP_MQ      0x0400
+#define TUN_META_HDR	0x0800
 
 /* Ioctl defines */
 #define TUNSETNOCSUM  _IOW('T', 200, int) 
@@ -56,10 +57,12 @@
 #define TUNGETVNETHDRSZ _IOR('T', 215, int)
 #define TUNSETVNETHDRSZ _IOW('T', 216, int)
 #define TUNSETQUEUE  _IOW('T', 217, int)
+#define TUNGETMETAPARAM _IOR('T', 218, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN		0x0001
 #define IFF_TAP		0x0002
+#define IFF_META_HDR	0x0004
 #define IFF_NO_PI	0x1000
 /* This flag has no real effect */
 #define IFF_ONE_QUEUE	0x2000
@@ -103,4 +106,8 @@ struct tun_filter {
 	__u8   addr[0][ETH_ALEN];
 };
 
+/* TUNGETMETAPARAM metadata header request types. */
+#define TUN_GET_META_HDR_SZ 0
+#define TUN_GET_META_MARK_OFFSET 1
+
 #endif /* _UAPI__IF_TUN_H */
-- 
1.8.3

Re: [PATCH] Passing sk_buff metadata information to user space in TUNTAP driver.

From: Maciej Żenczykowski <hidden>
Date: 2013-08-19 20:49:10

Acked-by: Maciej Żenczykowski <redacted>

I've already reviewed / commented on previous versions of this patch
and am hoping for comments from a wider audience.

I'm hoping this relatively generic and easily extensible way of
exposing additional per-packet metadata to userspace catches on.
Something similar would also be useful for tcpdump (ie. raw packet sockets).

- Maciej

Re: [PATCH] Passing sk_buff metadata information to user space in TUNTAP driver.

From: David Miller <davem@davemloft.net>
Date: 2013-08-21 06:28:38

From: Maciej Żenczykowski <redacted>
Date: Mon, 19 Aug 2013 13:49:08 -0700
Acked-by: Maciej Żenczykowski <redacted>

I've already reviewed / commented on previous versions of this patch
and am hoping for comments from a wider audience.

I'm hoping this relatively generic and easily extensible way of
exposing additional per-packet metadata to userspace catches on.
Something similar would also be useful for tcpdump (ie. raw packet sockets).
I'd rather people build generic infrastructure for this.

We already have a META match in the packet scheduler, and all sorts
of BPF extensions which provide SKB metadata too.  That's the right
approach, something more generic.

Therefore, putting a custom version of SKB metadata export into the
TUN driver makes absolutely no sense to me.

I'm not applying this, sorry.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help