linux-um archives
 help / color / mirror / Atom feed
From: "Anton Ivanov (antivano)" <antivano@cisco.com>
To: "anton.ivanov@kot-begemot.co.uk" <anton.ivanov@kot-begemot.co.uk>,
	"user-mode-linux-devel@lists.sourceforge.net"
	<user-mode-linux-devel@lists.sourceforge.net>
Subject: Re: [uml-devel] [PATCH 03/10] High performance networking subsystem
Date: Sat, 30 Aug 2014 07:35:50 +0000	[thread overview]
Message-ID: <54017ED4.1000408@cisco.com> (raw)
In-Reply-To: <1409295915-130538-3-git-send-email-anton.ivanov@kot-begemot.co.uk>

Hi Richard, hi list,

some notes on this patchset: we have had the multipacket rx portion of 
this stable and in use for quite a while (nearly a year).

The tx portion is new and it looks like it has some issues which did not 
show up before I ported it to a more recent kernel (I would not be 
surprised if I introduced them when porting this from 3.3.y/OpenWRT to 
3.12.y/Stock).

If I do not figure out what exactly is going on with the tx by end of 
next week I am going to resubmit an older version of this patch (and its 
corresponding transports) which has only multi-packet rx (which is 
stable) and leave TX for a later incremental.

A.


On 29/08/14 08:05, anton.ivanov@kot-begemot.co.uk wrote:
> From: Anton Ivanov <antivano@cisco.com>
>
> Support for multi-packet vector IO - multiple packets
> read in one syscall and written in one syscall. Should work with
> legacy UML, thorough tested only for the epoll based IRQ controller
>
> Minimal host kernel version for RX - 2.6.32
> Minimal host kernel version for TX - 3.0
>
> Tested on Debian 7.0/Ubuntu 12.x LTS which have the relevant
> syscalls, but do not have the appropriate glibc routine for TX
> (this is why it is a direct syscall).
>
> Signed-off-by: Anton Ivanov <antivano@cisco.com>
> ---
>   arch/um/drivers/Makefile          |    2 +-
>   arch/um/drivers/net_kern.c        |   63 ++++++++++++++++++++++++-------------
>   arch/um/include/asm/irq.h         |   26 +++++++++------
>   arch/um/include/shared/net_kern.h |   24 ++++++++++++++
>   arch/um/include/shared/net_user.h |   24 ++++++++++++++
>   arch/um/kernel/irq.c              |    3 ++
>   6 files changed, 109 insertions(+), 33 deletions(-)
>
> diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
> index e7582e1..836baaf 100644
> --- a/arch/um/drivers/Makefile
> +++ b/arch/um/drivers/Makefile
> @@ -10,7 +10,7 @@ slip-objs := slip_kern.o slip_user.o
>   slirp-objs := slirp_kern.o slirp_user.o
>   daemon-objs := daemon_kern.o daemon_user.o
>   umcast-objs := umcast_kern.o umcast_user.o
> -net-objs := net_kern.o net_user.o
> +net-objs := net_kern.o net_user.o net_extra_user.o net_extra_kern.o
>   mconsole-objs := mconsole_kern.o mconsole_user.o
>   hostaudio-objs := hostaudio_kern.o
>   ubd-objs := ubd_kern.o ubd_user.o
> diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
> index 64d8426..1d253fa 100644
> --- a/arch/um/drivers/net_kern.c
> +++ b/arch/um/drivers/net_kern.c
> @@ -1,4 +1,5 @@
>   /*
> + * Copyright (C) 2012 - 2014 Cisco Systems
>    * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
>    * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
>    * James Leu (jleu@mindspring.net).
> @@ -29,6 +30,7 @@
>   
>   static DEFINE_SPINLOCK(opened_lock);
>   static LIST_HEAD(opened);
> +static int rr_counter = 0;
>   
>   /*
>    * The drop_skb is used when we can't allocate an skb.  The
> @@ -42,6 +44,7 @@ static DEFINE_SPINLOCK(drop_lock);
>   static struct sk_buff *drop_skb;
>   static int drop_max;
>   
> +
>   static int update_drop_skb(int max)
>   {
>   	struct sk_buff *new;
> @@ -77,24 +80,38 @@ static int uml_net_rx(struct net_device *dev)
>   	struct sk_buff *skb;
>   
>   	/* If we can't allocate memory, try again next round. */
> -	skb = dev_alloc_skb(lp->max_packet);
> -	if (skb == NULL) {
> -		drop_skb->dev = dev;
> -		/* Read a packet into drop_skb and don't do anything with it. */
> -		(*lp->read)(lp->fd, drop_skb, lp);
> -		dev->stats.rx_dropped++;
> +	if (lp->options & UML_NET_USE_SKB_READ) {
> +	    /* we expect a full formed, well behaved skb from zero copy drivers here */
> +	    skb = (*lp->skb_read)(lp);
> +	    if (skb == NULL) {
>   		return 0;
> -	}
> -
> -	skb->dev = dev;
> -	skb_put(skb, lp->max_packet);
> -	skb_reset_mac_header(skb);
> -	pkt_len = (*lp->read)(lp->fd, skb, lp);
> -
> -	if (pkt_len > 0) {
> +	    }
> +	    pkt_len = skb->len;
> +	} else {
> +	    skb = dev_alloc_skb(lp->max_packet + 32);
> +	    if (skb == NULL) {
> +		    drop_skb->dev = dev;
> +		    /* Read a packet into drop_skb and don't do anything with it. */
> +		    (*lp->read)(lp->fd, drop_skb, lp);
> +		    dev->stats.rx_dropped++;
> +		    return 0;
> +	    }
> +
> +	    skb_reserve(skb,32);
> +	    skb->dev = dev;
> +	    skb_put(skb, lp->max_packet);
> +	    skb_reset_mac_header(skb);
> +
> +	    // Mark that virtual devices cannot provide required checksum.
> +	    skb->ip_summed = CHECKSUM_NONE;
> +	    pkt_len = (*lp->read)(lp->fd, skb, lp);
> +	    if (pkt_len > 0) {
>   		skb_trim(skb, pkt_len);
>   		skb->protocol = (*lp->protocol)(skb);
> +	    }
> +	}
>   
> +	if (pkt_len > 0) {
>   		dev->stats.rx_bytes += skb->len;
>   		dev->stats.rx_packets++;
>   		netif_rx(skb);
> @@ -192,8 +209,9 @@ static int uml_net_close(struct net_device *dev)
>   	struct uml_net_private *lp = netdev_priv(dev);
>   
>   	netif_stop_queue(dev);
> +	deactivate_fd(lp->fd, dev->irq);
>   
> -	um_free_irq(dev->irq, dev);
> +	free_irq(dev->irq, dev);
>   	if (lp->close != NULL)
>   		(*lp->close)(lp->fd, &lp->user);
>   	lp->fd = -1;
> @@ -216,7 +234,6 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
>   	spin_lock_irqsave(&lp->lock, flags);
>   
>   	len = (*lp->write)(lp->fd, skb, lp);
> -	skb_tx_timestamp(skb);
>   
>   	if (len == skb->len) {
>   		dev->stats.tx_packets++;
> @@ -273,14 +290,13 @@ static void uml_net_poll_controller(struct net_device *dev)
>   static void uml_net_get_drvinfo(struct net_device *dev,
>   				struct ethtool_drvinfo *info)
>   {
> -	strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
> -	strlcpy(info->version, "42", sizeof(info->version));
> +	strcpy(info->driver, DRIVER_NAME);
> +	strcpy(info->version, "42");
>   }
>   
>   static const struct ethtool_ops uml_net_ethtool_ops = {
>   	.get_drvinfo	= uml_net_get_drvinfo,
>   	.get_link	= ethtool_op_get_link,
> -	.get_ts_info	= ethtool_op_get_ts_info,
>   };
>   
>   static void uml_net_user_timer_expire(unsigned long _conn)
> @@ -447,6 +463,7 @@ static void eth_configure(int n, void *init, char *mac,
>   	 * These just fill in a data structure, so there's no failure
>   	 * to be worried about.
>   	 */
> +	dev->ethtool_ops = &uml_net_ethtool_ops;
>   	(*transport->kern->init)(dev, init);
>   
>   	*lp = ((struct uml_net_private)
> @@ -459,7 +476,9 @@ static void eth_configure(int n, void *init, char *mac,
>   		  .open 		= transport->user->open,
>   		  .close 		= transport->user->close,
>   		  .remove 		= transport->user->remove,
> +		  .options 		= transport->kern->options,
>   		  .read 		= transport->kern->read,
> +		  .skb_read 		= transport->kern->skb_read,
>   		  .write 		= transport->kern->write,
>   		  .add_address 		= transport->user->add_address,
>   		  .delete_address  	= transport->user->delete_address });
> @@ -475,9 +494,9 @@ static void eth_configure(int n, void *init, char *mac,
>   
>   	dev->mtu = transport->user->mtu;
>   	dev->netdev_ops = &uml_netdev_ops;
> -	dev->ethtool_ops = &uml_net_ethtool_ops;
>   	dev->watchdog_timeo = (HZ >> 1);
> -	dev->irq = UM_ETH_IRQ;
> +	dev->irq = UM_ETH_BASE_IRQ + (rr_counter % UM_ETH_IRQ_RR);
> +	rr_counter++;
>   
>   	err = update_drop_skb(lp->max_packet);
>   	if (err)
> @@ -829,7 +848,7 @@ static void close_devices(void)
>   	spin_lock(&opened_lock);
>   	list_for_each(ele, &opened) {
>   		lp = list_entry(ele, struct uml_net_private, list);
> -		um_free_irq(lp->dev->irq, lp->dev);
> +		free_irq(lp->dev->irq, lp->dev);
>   		if ((lp->close != NULL) && (lp->fd >= 0))
>   			(*lp->close)(lp->fd, &lp->user);
>   		if (lp->remove != NULL)
> diff --git a/arch/um/include/asm/irq.h b/arch/um/include/asm/irq.h
> index 4a2037f..be9128b 100644
> --- a/arch/um/include/asm/irq.h
> +++ b/arch/um/include/asm/irq.h
> @@ -1,21 +1,27 @@
> +
>   #ifndef __UM_IRQ_H
>   #define __UM_IRQ_H
>   
> +#define UM_ETH_IRQ_RR	        32
> +
>   #define TIMER_IRQ		0
>   #define UMN_IRQ			1
>   #define CONSOLE_IRQ		2
>   #define CONSOLE_WRITE_IRQ	3
>   #define UBD_IRQ			4
> -#define UM_ETH_IRQ		5
> -#define SSL_IRQ			6
> -#define SSL_WRITE_IRQ		7
> -#define ACCEPT_IRQ		8
> -#define MCONSOLE_IRQ		9
> -#define WINCH_IRQ		10
> -#define SIGIO_WRITE_IRQ 	11
> -#define TELNETD_IRQ 		12
> -#define XTERM_IRQ 		13
> -#define RANDOM_IRQ 		14
> +#define UM_ETH_BASE_IRQ		5
> +
> +#define UM_END_ETH_IRQ	        UM_ETH_BASE_IRQ + UM_ETH_IRQ_RR
> +
> +#define SSL_IRQ			UM_END_ETH_IRQ + 1
> +#define SSL_WRITE_IRQ		UM_END_ETH_IRQ + 2
> +#define ACCEPT_IRQ		UM_END_ETH_IRQ + 3
> +#define MCONSOLE_IRQ		UM_END_ETH_IRQ + 4
> +#define WINCH_IRQ		UM_END_ETH_IRQ + 5
> +#define SIGIO_WRITE_IRQ 	UM_END_ETH_IRQ + 6
> +#define TELNETD_IRQ 		UM_END_ETH_IRQ + 7
> +#define XTERM_IRQ 		UM_END_ETH_IRQ + 8
> +#define RANDOM_IRQ 		UM_END_ETH_IRQ + 9
>   
>   #define LAST_IRQ RANDOM_IRQ
>   #define NR_IRQS (LAST_IRQ + 1)
> diff --git a/arch/um/include/shared/net_kern.h b/arch/um/include/shared/net_kern.h
> index 012ac87..2229126 100644
> --- a/arch/um/include/shared/net_kern.h
> +++ b/arch/um/include/shared/net_kern.h
> @@ -1,4 +1,5 @@
>   /*
> + * Copyright (C) 2012 - 2014 Cisco Systems
>    * Copyright (C) 2002 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
>    * Licensed under the GPL
>    */
> @@ -13,6 +14,8 @@
>   #include <linux/list.h>
>   #include <linux/workqueue.h>
>   
> +#define UML_NET_USE_SKB_READ 1
> +
>   struct uml_net {
>   	struct list_head list;
>   	struct net_device *dev;
> @@ -28,6 +31,7 @@ struct uml_net_private {
>   
>   	struct work_struct work;
>   	int fd;
> +	unsigned int options;
>   	unsigned char mac[ETH_ALEN];
>   	int max_packet;
>   	unsigned short (*protocol)(struct sk_buff *);
> @@ -36,6 +40,7 @@ struct uml_net_private {
>   	void (*remove)(void *);
>   	int (*read)(int, struct sk_buff *skb, struct uml_net_private *);
>   	int (*write)(int, struct sk_buff *skb, struct uml_net_private *);
> +	struct sk_buff * (*skb_read)(struct uml_net_private *);
>   
>   	void (*add_address)(unsigned char *, unsigned char *, void *);
>   	void (*delete_address)(unsigned char *, unsigned char *, void *);
> @@ -47,6 +52,8 @@ struct net_kern_info {
>   	unsigned short (*protocol)(struct sk_buff *);
>   	int (*read)(int, struct sk_buff *skb, struct uml_net_private *);
>   	int (*write)(int, struct sk_buff *skb, struct uml_net_private *);
> +	struct sk_buff * (*skb_read)(struct uml_net_private *);
> +	unsigned int options;
>   };
>   
>   struct transport {
> @@ -59,11 +66,28 @@ struct transport {
>   	const int setup_size;
>   };
>   
> +struct mmsg_queue_info {
> +	int fd;
> +	struct mmsghdr * mmsg_send_vector;
> +	void ** skb_send_vector;
> +	int queue_depth, head, tail, max_depth;
> +	spinlock_t head_lock;
> +	spinlock_t tail_lock;
> +	unsigned int queue_fsm;
> +};
> +
>   extern struct net_device *ether_init(int);
>   extern unsigned short ether_protocol(struct sk_buff *);
>   extern int tap_setup_common(char *str, char *type, char **dev_name,
>   			    char **mac_out, char **gate_addr);
>   extern void register_transport(struct transport *new);
>   extern unsigned short eth_protocol(struct sk_buff *skb);
> +extern struct sk_buff *my_build_skb(void * head, void *data, unsigned int frag_size);
> +
> +extern void flush_pending_netio(void);
> +
> +extern int uml_net_advance_tail( struct mmsg_queue_info * queue_info, int advance);
> +extern int uml_net_advance_head( struct mmsg_queue_info * queue_info, int advance);
> +extern int uml_net_flush_mmsg_queue(struct mmsg_queue_info * queue_info, int queue_depth);
>   
>   #endif
> diff --git a/arch/um/include/shared/net_user.h b/arch/um/include/shared/net_user.h
> index 3dabbe1..4b46f37 100644
> --- a/arch/um/include/shared/net_user.h
> +++ b/arch/um/include/shared/net_user.h
> @@ -1,4 +1,5 @@
>   /*
> + * Copyright (C) 2012 - 2014 Cisco Systems
>    * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
>    * Licensed under the GPL
>    */
> @@ -38,10 +39,15 @@ extern void tap_check_ips(char *gate_addr, unsigned char *eth_addr);
>   extern void read_output(int fd, char *output_out, int len);
>   
>   extern int net_read(int fd, void *buf, int len);
> +extern int net_readv(int fd, void *iov, int iovcnt);
>   extern int net_recvfrom(int fd, void *buf, int len);
> +extern int net_recvfrom2(int fd, void *buf, int len, void *src_addr, int *addrlen);
>   extern int net_write(int fd, void *buf, int len);
> +extern int net_writev(int fd, void *iov, int iovcnt);
>   extern int net_send(int fd, void *buf, int len);
>   extern int net_sendto(int fd, void *buf, int len, void *to, int sock_len);
> +extern int net_sendmessage(int fd, void *msg, int flags);
> +extern int net_recvmessage(int fd, void *msg, int flags);
>   
>   extern void open_addr(unsigned char *addr, unsigned char *netmask, void *arg);
>   extern void close_addr(unsigned char *addr, unsigned char *netmask, void *arg);
> @@ -50,4 +56,22 @@ extern char *split_if_spec(char *str, ...);
>   
>   extern int dev_netmask(void *d, void *m);
>   
> +
> +extern void uml_net_destroy_skb(void * skb);
> +extern void * uml_net_build_skb (void * dev);
> +extern void * uml_net_skb_data (void * skb);
> +
> +extern void add_skbuffs(void * msgvec, void ** skbvec, int size, int skb_size, int offset);
> +extern void add_header_buffers(void * msgvec, int size, int header_size);
> +extern void * build_mmsg_vector(int size, int iovsize);
> +extern void rebuild_skbuf_vector(void ** skbvec, int size, void * dev);
> +extern void * build_skbuf_vector(int size, void * dev);
> +extern int net_recvmmsg(int fd, void *msgvec, unsigned int vlen,
> +		unsigned int flags, struct timespec *timeout);
> +extern int net_sendmmsg(int fd, void *msgvec, unsigned int vlen,
> +		unsigned int flags);
> +extern void repair_mmsg (void *msgvec, int iovsize, int header_size);
> +extern void destroy_skb_vector(void ** vector, int size);
> +extern void destroy_mmsg_vector(void * mmsgvector, int size, int free_iov_base);
> +
>   #endif
> diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
> index 5d7ee49e..f4c6fb1 100644
> --- a/arch/um/kernel/irq.c
> +++ b/arch/um/kernel/irq.c
> @@ -17,6 +17,7 @@
>   #include <as-layout.h>
>   #include <kern_util.h>
>   #include <os.h>
> +#include <net_kern.h>
>   
>   /*
>   *	We are on the "kernel side" so we cannot pick up the sys/epoll.h
> @@ -136,6 +137,8 @@ void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
>   		spin_unlock_irqrestore(&uml_sigio_lock, flags);
>   	}
>   
> +	flush_pending_netio();
> +
>   	/* This needs a better way - it slows down the event loop */
>   
>   	free_irqs();

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel


  reply	other threads:[~2014-08-30  7:35 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-29  7:05 [uml-devel] [PATCH 01/10] Epoll based interrupt controller anton.ivanov
2014-08-29  7:05 ` [uml-devel] [PATCH 02/10] Remove unnecessary 'reactivate' statements anton.ivanov
2014-08-29  7:05 ` [uml-devel] [PATCH 03/10] High performance networking subsystem anton.ivanov
2014-08-30  7:35   ` Anton Ivanov (antivano) [this message]
2014-08-29  7:05 ` [uml-devel] [PATCH 04/10] L2TPv3 Transport Driver for UML anton.ivanov
2014-08-29  7:05 ` [uml-devel] [PATCH 05/10] GRE transport " anton.ivanov
2014-08-29  7:05 ` [uml-devel] [PATCH 06/10] RAW Ethernet " anton.ivanov
2014-08-29  7:05 ` [uml-devel] [PATCH 07/10] Performance and NUMA improvements for ubd anton.ivanov
2014-08-29  7:05 ` [uml-devel] [PATCH 08/10] Minor performance optimization " anton.ivanov
2014-08-29  7:05 ` [uml-devel] [PATCH 09/10] Better IPC for UBD anton.ivanov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54017ED4.1000408@cisco.com \
    --to=antivano@cisco.com \
    --cc=anton.ivanov@kot-begemot.co.uk \
    --cc=user-mode-linux-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox