All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3 1/5] um: Add legacy tap support and rename existing vector to hybrid
@ 2019-07-22  7:30 anton.ivanov
  2019-07-22  7:30 ` [PATCHv3 2/5] um: Added support for unix socket transports and bess transport anton.ivanov
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: anton.ivanov @ 2019-07-22  7:30 UTC (permalink / raw)
  To: linux-um; +Cc: richard, Anton Ivanov

From: Anton Ivanov <anton.ivanov@cambridgegreys.com>

1. Adds legacy tap support
2. Renames tap+raw as hybrid

Signed-off-by: Anton Ivanov <anton.ivanov@cambridgegreys.com>
---
 arch/um/drivers/vector_kern.c       |   2 +
 arch/um/drivers/vector_transports.c |  29 +++++-
 arch/um/drivers/vector_user.c       | 203 +++++++++++++++++++++---------------
 arch/um/drivers/vector_user.h       |   4 +-
 4 files changed, 151 insertions(+), 87 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 046fa9ea0ccc..e314a60cdc98 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -186,6 +186,8 @@ static int get_transport_options(struct arglist *def)
 
 
 	if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
+		return 0;
+	if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
 		return (vec_rx | VECTOR_BPF);
 	if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
 		return (vec_rx | vec_tx | VECTOR_QDISC_BYPASS);
diff --git a/arch/um/drivers/vector_transports.c b/arch/um/drivers/vector_transports.c
index 77e4ebc206ae..2999f3bd1781 100644
--- a/arch/um/drivers/vector_transports.c
+++ b/arch/um/drivers/vector_transports.c
@@ -418,7 +418,7 @@ static int build_raw_transport_data(struct vector_private *vp)
 	return 0;
 }
 
-static int build_tap_transport_data(struct vector_private *vp)
+static int build_hybrid_transport_data(struct vector_private *vp)
 {
 	if (uml_raw_enable_vnet_headers(vp->fds->rx_fd)) {
 		vp->form_header = &raw_form_header;
@@ -432,7 +432,7 @@ static int build_tap_transport_data(struct vector_private *vp)
 				NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
 		netdev_info(
 			vp->dev,
-			"tap/raw: using vnet headers for tso and tx/rx checksum"
+			"tap/raw hybrid: using vnet headers for tso and tx/rx checksum"
 		);
 	} else {
 		return 0; /* do not try to enable tap too if raw failed */
@@ -442,6 +442,29 @@ static int build_tap_transport_data(struct vector_private *vp)
 	return -1;
 }
 
+static int build_tap_transport_data(struct vector_private *vp)
+{
+	/* "Pure" tap uses the same fd for rx and tx */
+	if (uml_tap_enable_vnet_headers(vp->fds->tx_fd)) {
+		vp->form_header = &raw_form_header;
+		vp->verify_header = &raw_verify_header;
+		vp->header_size = sizeof(struct virtio_net_hdr);
+		vp->rx_header_size = sizeof(struct virtio_net_hdr);
+		vp->dev->hw_features |=
+			(NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
+		vp->dev->features |=
+			(NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
+				NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
+		netdev_info(
+			vp->dev,
+			"tap: using vnet headers for tso and tx/rx checksum"
+		);
+		return 0;
+	}
+	return -1;
+}
+
+
 int build_transport_data(struct vector_private *vp)
 {
 	char *transport = uml_vector_fetch_arg(vp->parsed, "transport");
@@ -454,6 +477,8 @@ int build_transport_data(struct vector_private *vp)
 		return build_raw_transport_data(vp);
 	if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
 		return build_tap_transport_data(vp);
+	if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
+		return build_hybrid_transport_data(vp);
 	return 0;
 }
 
diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c
index 3d8cdbdb4e66..af1a1da432ca 100644
--- a/arch/um/drivers/vector_user.c
+++ b/arch/um/drivers/vector_user.c
@@ -115,12 +115,76 @@ struct arglist *uml_parse_vector_ifspec(char *arg)
 
 #define PATH_NET_TUN "/dev/net/tun"
 
-static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
+
+static int create_tap_fd(char *iface)
 {
 	struct ifreq ifr;
 	int fd = -1;
-	struct sockaddr_ll sock;
 	int err = -ENOMEM, offload;
+
+	fd = open(PATH_NET_TUN, O_RDWR);
+	if (fd < 0) {
+		printk(UM_KERN_ERR "uml_tap: failed to open tun device\n");
+		goto tap_fd_cleanup;
+	}
+	memset(&ifr, 0, sizeof(ifr));
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
+	strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
+
+	err = ioctl(fd, TUNSETIFF, (void *) &ifr);
+	if (err != 0) {
+		printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n");
+		goto tap_fd_cleanup;
+	}
+
+	offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
+	ioctl(fd, TUNSETOFFLOAD, offload);
+	return fd;
+tap_fd_cleanup:
+	if (fd >= 0)
+		os_close_file(fd);
+	return err;
+}
+
+static int create_raw_fd(char *iface, int flags, int proto)
+{
+	struct ifreq ifr;
+	int fd = -1;
+	struct sockaddr_ll sock;
+	int err = -ENOMEM;
+
+	fd = socket(AF_PACKET, SOCK_RAW, flags);
+	if (fd == -1) {
+		err = -errno;
+		goto raw_fd_cleanup;
+	}
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
+	if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
+		err = -errno;
+		goto raw_fd_cleanup;
+	}
+
+	sock.sll_family = AF_PACKET;
+	sock.sll_protocol = htons(proto);
+	sock.sll_ifindex = ifr.ifr_ifindex;
+
+	if (bind(fd,
+		(struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
+		err = -errno;
+		goto raw_fd_cleanup;
+	}
+	return fd;
+raw_fd_cleanup:
+	printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
+	if (fd >= 0)
+		os_close_file(fd);
+	return err;
+}
+
+static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
+{
+	int fd = -1;
 	char *iface;
 	struct vector_fds *result = NULL;
 
@@ -142,117 +206,88 @@ static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
 
 	/* TAP */
 
-	fd = open(PATH_NET_TUN, O_RDWR);
+	fd = create_tap_fd(iface);
 	if (fd < 0) {
-		printk(UM_KERN_ERR "uml_tap: failed to open tun device\n");
+		printk(UM_KERN_ERR "uml_tap: failed to create tun interface\n");
 		goto tap_cleanup;
 	}
 	result->tx_fd = fd;
-	memset(&ifr, 0, sizeof(ifr));
-	ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
-	strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
+	result->rx_fd = fd;
+	return result;
+tap_cleanup:
+	printk(UM_KERN_ERR "user_init_tap: init failed, error %d", fd);
+	if (result != NULL)
+		kfree(result);
+	return NULL;
+}
 
-	err = ioctl(fd, TUNSETIFF, (void *) &ifr);
-	if (err != 0) {
-		printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n");
-		goto tap_cleanup;
+static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec)
+{
+	char *iface;
+	struct vector_fds *result = NULL;
+
+	iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
+	if (iface == NULL) {
+		printk(UM_KERN_ERR "uml_tap: failed to parse interface spec\n");
+		goto hybrid_cleanup;
 	}
 
-	offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
-	ioctl(fd, TUNSETOFFLOAD, offload);
+	result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
+	if (result == NULL) {
+		printk(UM_KERN_ERR "uml_tap: failed to allocate file descriptors\n");
+		goto hybrid_cleanup;
+	}
+	result->rx_fd = -1;
+	result->tx_fd = -1;
+	result->remote_addr = NULL;
+	result->remote_addr_size = 0;
 
-	/* RAW */
+	/* TAP */
 
-	fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-	if (fd == -1) {
-		printk(UM_KERN_ERR
-			"uml_tap: failed to create socket: %i\n", -errno);
-		goto tap_cleanup;
-	}
-	result->rx_fd = fd;
-	memset(&ifr, 0, sizeof(ifr));
-	strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
-	if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
-		printk(UM_KERN_ERR
-			"uml_tap: failed to set interface: %i\n", -errno);
-		goto tap_cleanup;
+	result->tx_fd = create_tap_fd(iface);
+	if (result->tx_fd < 0) {
+		printk(UM_KERN_ERR "uml_tap: failed to create tun interface: %i\n", result->tx_fd);
+		goto hybrid_cleanup;
 	}
 
-	sock.sll_family = AF_PACKET;
-	sock.sll_protocol = htons(ETH_P_ALL);
-	sock.sll_ifindex = ifr.ifr_ifindex;
+	/* RAW */
 
-	if (bind(fd,
-		(struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
+	result->rx_fd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
+	if (result->rx_fd == -1) {
 		printk(UM_KERN_ERR
-			"user_init_tap: failed to bind raw pair, err %d\n",
-				-errno);
-		goto tap_cleanup;
+			"uml_tap: failed to create paired raw socket: %i\n", result->rx_fd);
+		goto hybrid_cleanup;
 	}
 	return result;
-tap_cleanup:
-	printk(UM_KERN_ERR "user_init_tap: init failed, error %d", err);
-	if (result != NULL) {
-		if (result->rx_fd >= 0)
-			os_close_file(result->rx_fd);
-		if (result->tx_fd >= 0)
-			os_close_file(result->tx_fd);
+hybrid_cleanup:
+	printk(UM_KERN_ERR "user_init_hybrid: init failed");
+	if (result != NULL)
 		kfree(result);
-	}
 	return NULL;
 }
 
 
 static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
 {
-	struct ifreq ifr;
 	int rxfd = -1, txfd = -1;
-	struct sockaddr_ll sock;
 	int err = -ENOMEM;
 	char *iface;
 	struct vector_fds *result = NULL;
 
 	iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
 	if (iface == NULL)
-		goto cleanup;
+		goto raw_cleanup;
 
-	rxfd = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL);
+	rxfd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
 	if (rxfd == -1) {
 		err = -errno;
-		goto cleanup;
+		goto raw_cleanup;
 	}
-	txfd = socket(AF_PACKET, SOCK_RAW, 0); /* Turn off RX on this fd */
+	txfd = create_raw_fd(iface, 0, ETH_P_IP); /* Turn off RX on this fd */
 	if (txfd == -1) {
 		err = -errno;
-		goto cleanup;
-	}
-	memset(&ifr, 0, sizeof(ifr));
-	strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
-	if (ioctl(rxfd, SIOCGIFINDEX, (void *) &ifr) < 0) {
-		err = -errno;
-		goto cleanup;
-	}
-
-	sock.sll_family = AF_PACKET;
-	sock.sll_protocol = htons(ETH_P_ALL);
-	sock.sll_ifindex = ifr.ifr_ifindex;
-
-	if (bind(rxfd,
-		(struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
-		err = -errno;
-		goto cleanup;
+		goto raw_cleanup;
 	}
-
-	sock.sll_family = AF_PACKET;
-	sock.sll_protocol = htons(ETH_P_IP);
-	sock.sll_ifindex = ifr.ifr_ifindex;
-
-	if (bind(txfd,
-		(struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
-		err = -errno;
-		goto cleanup;
-	}
-
 	result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
 	if (result != NULL) {
 		result->rx_fd = rxfd;
@@ -261,13 +296,10 @@ static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
 		result->remote_addr_size = 0;
 	}
 	return result;
-cleanup:
+raw_cleanup:
 	printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
-	if (rxfd >= 0)
-		os_close_file(rxfd);
-	if (txfd >= 0)
-		os_close_file(txfd);
-	kfree(result);
+	if (result != NULL)
+		kfree(result);
 	return NULL;
 }
 
@@ -457,6 +489,8 @@ struct vector_fds *uml_vector_user_open(
 	}
 	if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
 		return user_init_raw_fds(parsed);
+	if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
+		return user_init_hybrid_fds(parsed);
 	if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
 		return user_init_tap_fds(parsed);
 	if (strncmp(transport, TRANS_GRE, TRANS_GRE_LEN) == 0)
@@ -483,8 +517,9 @@ int uml_vector_sendmsg(int fd, void *hdr, int flags)
 int uml_vector_recvmsg(int fd, void *hdr, int flags)
 {
 	int n;
+	struct msghdr *msg = (struct msghdr *) hdr;
 
-	CATCH_EINTR(n = recvmsg(fd, (struct msghdr *) hdr,  flags));
+	CATCH_EINTR(n = readv(fd, msg->msg_iov, msg->msg_iovlen));
 	if ((n < 0) && (errno == EAGAIN))
 		return 0;
 	if (n >= 0)
diff --git a/arch/um/drivers/vector_user.h b/arch/um/drivers/vector_user.h
index d7cbff73b7ff..6bf50cf78ad0 100644
--- a/arch/um/drivers/vector_user.h
+++ b/arch/um/drivers/vector_user.h
@@ -16,13 +16,15 @@
 #define TRANS_TAP "tap"
 #define TRANS_TAP_LEN strlen(TRANS_TAP)
 
-
 #define TRANS_GRE "gre"
 #define TRANS_GRE_LEN strlen(TRANS_RAW)
 
 #define TRANS_L2TPV3 "l2tpv3"
 #define TRANS_L2TPV3_LEN strlen(TRANS_L2TPV3)
 
+#define TRANS_HYBRID "hybrid"
+#define TRANS_HYBRID_LEN strlen(TRANS_HYBRID)
+
 #ifndef IPPROTO_GRE
 #define IPPROTO_GRE 0x2F
 #endif
-- 
2.11.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCHv3 2/5] um: Added support for unix socket transports and bess transport
  2019-07-22  7:30 [PATCHv3 1/5] um: Add legacy tap support and rename existing vector to hybrid anton.ivanov
@ 2019-07-22  7:30 ` anton.ivanov
  2019-07-22  7:30 ` [PATCHv3 3/5] um: Add checks to mtu parameter parsing anton.ivanov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: anton.ivanov @ 2019-07-22  7:30 UTC (permalink / raw)
  To: linux-um; +Cc: richard, Anton Ivanov

From: Anton Ivanov <anton.ivanov@cambridgegreys.com>

This adds support for the UNIX domain socket transports in
general and implements a Netsys::BESS compatible transport
interface.
For details on Netsys::BESS see https://github.com/NetSys/bess

Signed-off-by: Anton Ivanov <anton.ivanov@cambridgegreys.com>
---
 arch/um/drivers/vector_transports.c | 11 +++++
 arch/um/drivers/vector_user.c       | 88 ++++++++++++++++++++++++++++++++++++-
 arch/um/drivers/vector_user.h       |  3 ++
 3 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/arch/um/drivers/vector_transports.c b/arch/um/drivers/vector_transports.c
index 2999f3bd1781..a43310cd84fb 100644
--- a/arch/um/drivers/vector_transports.c
+++ b/arch/um/drivers/vector_transports.c
@@ -465,6 +465,15 @@ static int build_tap_transport_data(struct vector_private *vp)
 }
 
 
+static int build_bess_transport_data(struct vector_private *vp)
+{
+	vp->form_header = NULL;
+	vp->verify_header = NULL;
+	vp->header_size = 0;
+	vp->rx_header_size = 0;
+	return 0;
+}
+
 int build_transport_data(struct vector_private *vp)
 {
 	char *transport = uml_vector_fetch_arg(vp->parsed, "transport");
@@ -479,6 +488,8 @@ int build_transport_data(struct vector_private *vp)
 		return build_tap_transport_data(vp);
 	if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
 		return build_hybrid_transport_data(vp);
+	if (strncmp(transport, TRANS_BESS, TRANS_BESS_LEN) == 0)
+		return build_bess_transport_data(vp);
 	return 0;
 }
 
diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c
index af1a1da432ca..6dd9b4379507 100644
--- a/arch/um/drivers/vector_user.c
+++ b/arch/um/drivers/vector_user.c
@@ -18,6 +18,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <net/ethernet.h>
 #include <netinet/ip.h>
 #include <netinet/ether.h>
@@ -34,7 +35,8 @@
 
 #define ID_GRE 0
 #define ID_L2TPV3 1
-#define ID_MAX 1
+#define ID_BESS 2
+#define ID_MAX 2
 
 #define TOKEN_IFNAME "ifname"
 
@@ -44,8 +46,11 @@
 #define VNET_HDR_FAIL "could not enable vnet headers on fd %d"
 #define TUN_GET_F_FAIL "tapraw: TUNGETFEATURES failed: %s"
 #define L2TPV3_BIND_FAIL "l2tpv3_open : could not bind socket err=%i"
+#define UNIX_BIND_FAIL "unix_open : could not bind socket err=%i"
 #define BPF_ATTACH_FAIL "Failed to attach filter size %d to %d, err %d\n"
 
+#define MAX_UN_LEN 107
+
 /* This is very ugly and brute force lookup, but it is done
  * only once at initialization so not worth doing hashes or
  * anything more intelligent
@@ -266,6 +271,85 @@ static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec)
 	return NULL;
 }
 
+static struct vector_fds *user_init_unix_fds(struct arglist *ifspec, int id)
+{
+	int fd = -1;
+	int socktype;
+	char *src, *dst;
+	struct vector_fds *result = NULL;
+	struct sockaddr_un *local_addr = NULL, *remote_addr = NULL;
+
+	src = uml_vector_fetch_arg(ifspec, "src");
+	dst = uml_vector_fetch_arg(ifspec, "dst");
+	result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
+	if (result == NULL) {
+		printk(UM_KERN_ERR "unix open:cannot allocate remote addr");
+		goto unix_cleanup;
+	}
+	remote_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
+	if (remote_addr == NULL) {
+		printk(UM_KERN_ERR "unix open:cannot allocate remote addr");
+		goto unix_cleanup;
+	}
+
+	switch (id) {
+	case ID_BESS:
+		socktype = SOCK_SEQPACKET;
+		if ((src != NULL) && (strlen(src) <= MAX_UN_LEN)) {
+			local_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
+			if (local_addr == NULL) {
+				printk(UM_KERN_ERR "bess open:cannot allocate local addr");
+				goto unix_cleanup;
+			}
+			local_addr->sun_family = AF_UNIX;
+			memcpy(local_addr->sun_path, src, strlen(src) + 1);
+		}
+		if ((dst == NULL) || (strlen(dst) > MAX_UN_LEN))
+			goto unix_cleanup;
+		remote_addr->sun_family = AF_UNIX;
+		memcpy(remote_addr->sun_path, dst, strlen(dst) + 1);
+		break;
+	default:
+		printk(KERN_ERR "Unsupported unix socket type\n");
+		return NULL;
+	}
+
+	fd = socket(AF_UNIX, socktype, 0);
+	if (fd == -1) {
+		printk(UM_KERN_ERR
+			"unix open: could not open socket, error = %d",
+			-errno
+		);
+		goto unix_cleanup;
+	}
+	if (local_addr != NULL) {
+		if (bind(fd, (struct sockaddr *) local_addr, sizeof(struct sockaddr_un))) {
+			printk(UM_KERN_ERR UNIX_BIND_FAIL, errno);
+			goto unix_cleanup;
+		}
+	}
+	switch (id) {
+	case ID_BESS:
+		if (connect(fd, remote_addr, sizeof(struct sockaddr_un)) < 0) {
+			printk(UM_KERN_ERR "bess open:cannot connect to %s %i", remote_addr->sun_path, -errno);
+			goto unix_cleanup;
+		}
+		break;
+	}
+	result->rx_fd = fd;
+	result->tx_fd = fd;
+	result->remote_addr_size = sizeof(struct sockaddr_un);
+	result->remote_addr = remote_addr;
+	return result;
+unix_cleanup:
+	if (fd >= 0)
+		os_close_file(fd);
+	if (remote_addr != NULL)
+		kfree(remote_addr);
+	if (result != NULL)
+		kfree(result);
+	return NULL;
+}
 
 static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
 {
@@ -497,6 +581,8 @@ struct vector_fds *uml_vector_user_open(
 		return user_init_socket_fds(parsed, ID_GRE);
 	if (strncmp(transport, TRANS_L2TPV3, TRANS_L2TPV3_LEN) == 0)
 		return user_init_socket_fds(parsed, ID_L2TPV3);
+	if (strncmp(transport, TRANS_BESS, TRANS_BESS_LEN) == 0)
+		return user_init_unix_fds(parsed, ID_BESS);
 	return NULL;
 }
 
diff --git a/arch/um/drivers/vector_user.h b/arch/um/drivers/vector_user.h
index 6bf50cf78ad0..0a13ca9592d1 100644
--- a/arch/um/drivers/vector_user.h
+++ b/arch/um/drivers/vector_user.h
@@ -25,6 +25,9 @@
 #define TRANS_HYBRID "hybrid"
 #define TRANS_HYBRID_LEN strlen(TRANS_HYBRID)
 
+#define TRANS_BESS "bess"
+#define TRANS_BESS_LEN strlen(TRANS_BESS)
+
 #ifndef IPPROTO_GRE
 #define IPPROTO_GRE 0x2F
 #endif
-- 
2.11.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCHv3 3/5] um: Add checks to mtu parameter parsing
  2019-07-22  7:30 [PATCHv3 1/5] um: Add legacy tap support and rename existing vector to hybrid anton.ivanov
  2019-07-22  7:30 ` [PATCHv3 2/5] um: Added support for unix socket transports and bess transport anton.ivanov
@ 2019-07-22  7:30 ` anton.ivanov
  2019-07-22  7:30 ` [PATCHv3 4/5] um: Fix off by one error in IRQ enumeration anton.ivanov
  2019-07-22  7:30 ` [PATCHv3 5/5] um: Error handling fixes in vector drivers anton.ivanov
  3 siblings, 0 replies; 6+ messages in thread
From: anton.ivanov @ 2019-07-22  7:30 UTC (permalink / raw)
  To: linux-um; +Cc: richard, Anton Ivanov

From: Anton Ivanov <anton.ivanov@cambridgegreys.com>

Adds a sanity check to the parsing of mtu command line param

Signed-off-by: Anton Ivanov <anton.ivanov@cambridgegreys.com>
---
 arch/um/drivers/vector_kern.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index e314a60cdc98..e79cd1dcb018 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -121,7 +121,8 @@ static int get_mtu(struct arglist *def)
 
 	if (mtu != NULL) {
 		if (kstrtoul(mtu, 10, &result) == 0)
-			return result;
+			if ((result < (1 << 16) - 1) && (result >= 576))
+				return result;
 	}
 	return ETH_MAX_PACKET;
 }
-- 
2.11.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCHv3 4/5] um: Fix off by one error in IRQ enumeration
  2019-07-22  7:30 [PATCHv3 1/5] um: Add legacy tap support and rename existing vector to hybrid anton.ivanov
  2019-07-22  7:30 ` [PATCHv3 2/5] um: Added support for unix socket transports and bess transport anton.ivanov
  2019-07-22  7:30 ` [PATCHv3 3/5] um: Add checks to mtu parameter parsing anton.ivanov
@ 2019-07-22  7:30 ` anton.ivanov
  2019-07-30  6:56   ` Johannes Berg
  2019-07-22  7:30 ` [PATCHv3 5/5] um: Error handling fixes in vector drivers anton.ivanov
  3 siblings, 1 reply; 6+ messages in thread
From: anton.ivanov @ 2019-07-22  7:30 UTC (permalink / raw)
  To: linux-um; +Cc: richard, Anton Ivanov

From: Anton Ivanov <anton.ivanov@cambridgegreys.com>

Fix an off-by-one in IRQ enumeration

Reported by: Dana Johnson <djohns042@gmail.com>
Signed-off-by: Anton Ivanov <anton.ivanov@cambridgegreys.com>
---
 arch/um/include/asm/irq.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/um/include/asm/irq.h b/arch/um/include/asm/irq.h
index 49ed3e35b35a..ce7a78c3bcf2 100644
--- a/arch/um/include/asm/irq.h
+++ b/arch/um/include/asm/irq.h
@@ -23,7 +23,7 @@
 #define VECTOR_BASE_IRQ		15
 #define VECTOR_IRQ_SPACE	8
 
-#define LAST_IRQ (VECTOR_IRQ_SPACE + VECTOR_BASE_IRQ)
+#define LAST_IRQ (VECTOR_IRQ_SPACE + VECTOR_BASE_IRQ - 1)
 
 #else
 
-- 
2.11.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCHv3 5/5] um: Error handling fixes in vector drivers
  2019-07-22  7:30 [PATCHv3 1/5] um: Add legacy tap support and rename existing vector to hybrid anton.ivanov
                   ` (2 preceding siblings ...)
  2019-07-22  7:30 ` [PATCHv3 4/5] um: Fix off by one error in IRQ enumeration anton.ivanov
@ 2019-07-22  7:30 ` anton.ivanov
  3 siblings, 0 replies; 6+ messages in thread
From: anton.ivanov @ 2019-07-22  7:30 UTC (permalink / raw)
  To: linux-um; +Cc: richard, Anton Ivanov

From: Anton Ivanov <anton.ivanov@cambridgegreys.com>

With the addition of bess support which uses connection
oriented SEQPACKET sockets the vector routines can now
encounter a "remote end closed the connection" scenario.

This adds handling code to detect it in the TX path and
the legacy RX path. There is no way to detect it in the
vector RX path because that can legitimately return 0
even if the remote end has not closed the connection. As
a result the detection is delayed until the first TX
event after the close.

Signed-off-by: Anton Ivanov <anton.ivanov@cambridgegreys.com>
---
 arch/um/drivers/vector_kern.c | 37 ++++++++++++++++++++++++++++++++-----
 arch/um/drivers/vector_kern.h |  1 +
 arch/um/drivers/vector_user.c |  4 ++--
 3 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index e79cd1dcb018..165ee1636598 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -76,6 +76,7 @@ static void vector_eth_configure(int n, struct arglist *def);
 #define DEFAULT_VECTOR_SIZE 64
 #define TX_SMALL_PACKET 128
 #define MAX_IOV_SIZE (MAX_SKB_FRAGS + 1)
+#define MAX_ITERATIONS 64
 
 static const struct {
 	const char string[ETH_GSTRING_LEN];
@@ -418,6 +419,7 @@ static int vector_send(struct vector_queue *qi)
 					if (net_ratelimit())
 						netdev_err(vp->dev, "sendmmsg err=%i\n",
 							result);
+					vp->in_error = true;
 					result = send_len;
 				}
 				if (result > 0) {
@@ -845,6 +847,10 @@ static int vector_legacy_rx(struct vector_private *vp)
 	}
 
 	pkt_len = uml_vector_recvmsg(vp->fds->rx_fd, &hdr, 0);
+	if (pkt_len < 0) {
+		vp->in_error = true;
+		return pkt_len;
+	}
 
 	if (skb != NULL) {
 		if (pkt_len > vp->header_size) {
@@ -891,12 +897,16 @@ static int writev_tx(struct vector_private *vp, struct sk_buff *skb)
 
 	if (iov_count < 1)
 		goto drop;
+
 	pkt_len = uml_vector_writev(
 		vp->fds->tx_fd,
 		(struct iovec *) &iov,
 		iov_count
 	);
 
+	if (pkt_len < 0)
+		goto drop;
+
 	netif_trans_update(vp->dev);
 	netif_wake_queue(vp->dev);
 
@@ -911,6 +921,8 @@ static int writev_tx(struct vector_private *vp, struct sk_buff *skb)
 drop:
 	vp->dev->stats.tx_dropped++;
 	consume_skb(skb);
+	if (pkt_len < 0)
+		vp->in_error = true;
 	return pkt_len;
 }
 
@@ -939,6 +951,9 @@ static int vector_mmsg_rx(struct vector_private *vp)
 	packet_count = uml_vector_recvmmsg(
 		vp->fds->rx_fd, qi->mmsg_vector, qi->max_depth, 0);
 
+	if (packet_count < 0)
+		vp->in_error = true;
+
 	if (packet_count <= 0)
 		return packet_count;
 
@@ -1008,15 +1023,18 @@ static int vector_mmsg_rx(struct vector_private *vp)
 static void vector_rx(struct vector_private *vp)
 {
 	int err;
+	int iter = 0;
 
 	if ((vp->options & VECTOR_RX) > 0)
-		while ((err = vector_mmsg_rx(vp)) > 0)
-			;
+		while (((err = vector_mmsg_rx(vp)) > 0) && (iter < MAX_ITERATIONS))
+			iter++;
 	else
-		while ((err = vector_legacy_rx(vp)) > 0)
-			;
+		while (((err = vector_legacy_rx(vp)) > 0) && (iter < MAX_ITERATIONS))
+			iter++;
 	if ((err != 0) && net_ratelimit())
 		netdev_err(vp->dev, "vector_rx: error(%d)\n", err);
+	if (iter == MAX_ITERATIONS)
+		netdev_err(vp->dev, "vector_rx: device stuck, remote end may have closed the connection\n");
 }
 
 static int vector_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -1024,6 +1042,13 @@ static int vector_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct vector_private *vp = netdev_priv(dev);
 	int queue_depth = 0;
 
+	if (vp->in_error) {
+		deactivate_fd(vp->fds->rx_fd, vp->rx_irq);
+		if ((vp->fds->rx_fd != vp->fds->tx_fd) && (vp->tx_irq != 0))
+			deactivate_fd(vp->fds->tx_fd, vp->tx_irq);
+		return NETDEV_TX_BUSY;
+	}
+
 	if ((vp->options & VECTOR_TX) == 0) {
 		writev_tx(vp, skb);
 		return NETDEV_TX_OK;
@@ -1134,6 +1159,7 @@ static int vector_net_close(struct net_device *dev)
 	vp->fds = NULL;
 	spin_lock_irqsave(&vp->lock, flags);
 	vp->opened = false;
+	vp->in_error = false;
 	spin_unlock_irqrestore(&vp->lock, flags);
 	return 0;
 }
@@ -1501,7 +1527,8 @@ static void vector_eth_configure(
 		.transport_data		= NULL,
 		.in_write_poll		= false,
 		.coalesce		= 2,
-		.req_size		= get_req_size(def)
+		.req_size		= get_req_size(def),
+		.in_error		= false
 		});
 
 	dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST);
diff --git a/arch/um/drivers/vector_kern.h b/arch/um/drivers/vector_kern.h
index 0b0a767b9076..684d2e60ad86 100644
--- a/arch/um/drivers/vector_kern.h
+++ b/arch/um/drivers/vector_kern.h
@@ -116,6 +116,7 @@ struct vector_private {
 	bool rexmit_scheduled;
 	bool opened;
 	bool in_write_poll;
+	bool in_error;
 
 	/* ethtool stats */
 
diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c
index 6dd9b4379507..4e31121246b1 100644
--- a/arch/um/drivers/vector_user.c
+++ b/arch/um/drivers/vector_user.c
@@ -619,7 +619,7 @@ int uml_vector_writev(int fd, void *hdr, int iovcount)
 	int n;
 
 	CATCH_EINTR(n = writev(fd, (struct iovec *) hdr,  iovcount));
-	if ((n < 0) && (errno == EAGAIN))
+	if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS)))
 		return 0;
 	if (n >= 0)
 		return n;
@@ -636,7 +636,7 @@ int uml_vector_sendmmsg(
 	int n;
 
 	CATCH_EINTR(n = sendmmsg(fd, (struct mmsghdr *) msgvec, vlen, flags));
-	if ((n < 0) && (errno == EAGAIN))
+	if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS)))
 		return 0;
 	if (n >= 0)
 		return n;
-- 
2.11.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCHv3 4/5] um: Fix off by one error in IRQ enumeration
  2019-07-22  7:30 ` [PATCHv3 4/5] um: Fix off by one error in IRQ enumeration anton.ivanov
@ 2019-07-30  6:56   ` Johannes Berg
  0 siblings, 0 replies; 6+ messages in thread
From: Johannes Berg @ 2019-07-30  6:56 UTC (permalink / raw)
  To: anton.ivanov, linux-um; +Cc: richard

On Mon, 2019-07-22 at 08:30 +0100, anton.ivanov@cambridgegreys.com
wrote:
> From: Anton Ivanov <anton.ivanov@cambridgegreys.com>
> 
> Fix an off-by-one in IRQ enumeration
> 
> Reported by: Dana Johnson <djohns042@gmail.com>

nit: "Reported-by"
 
> -#define LAST_IRQ (VECTOR_IRQ_SPACE + VECTOR_BASE_IRQ)
> +#define LAST_IRQ (VECTOR_IRQ_SPACE + VECTOR_BASE_IRQ - 1)

Somebody internally at my group just made the same patch, but came to
the cnoclusion that we also need, in arch/um/kernel/irq.c:


-   for (i = 1; i < LAST_IRQ; i++)
+   for (i = 1; i <= LAST_IRQ; i++)

in init_IRQ()?

johannes


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-07-30  6:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-22  7:30 [PATCHv3 1/5] um: Add legacy tap support and rename existing vector to hybrid anton.ivanov
2019-07-22  7:30 ` [PATCHv3 2/5] um: Added support for unix socket transports and bess transport anton.ivanov
2019-07-22  7:30 ` [PATCHv3 3/5] um: Add checks to mtu parameter parsing anton.ivanov
2019-07-22  7:30 ` [PATCHv3 4/5] um: Fix off by one error in IRQ enumeration anton.ivanov
2019-07-30  6:56   ` Johannes Berg
2019-07-22  7:30 ` [PATCHv3 5/5] um: Error handling fixes in vector drivers anton.ivanov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.