Netdev List
 help / color / mirror / Atom feed
* Re: [RFC v2] mac80211: disallow bridging managed/adhoc interfaces
From: Stefan Monnier @ 2009-11-18  1:59 UTC (permalink / raw)
  To: linux-wireless-u79uwXL29TY76Z2rM5mHXA; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1258490898.21197.42.camel@johannes.local>

> A number of people have tried to add a wireless interface
> (in managed mode) to a bridge and then complained that it
> doesn't work. It cannot work, however, because in 802.11
[...]
> To avoid such mistakes in the future, disallow adding a
> wireless interface to a bridge.

As someone who's been bitten by this, I fully support this change.
Still, it makes me wonder: my broadcom-based home-router using the wl.o
driver can be set in "client bridge" mode.  How does it work?


        Stefan

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* NETLINK sockets dont honor SO_RCVLOWAT?
From: Jeff Haran @ 2009-11-18  1:54 UTC (permalink / raw)
  To: netdev

Hi,

Am I correct in my observation that the SO_RCVLOWAT socket option is not honored when one calls readv() on a PF_NETLINK socket?

The test application I wrote returns data as soon as it's available regardless of the option value I've specified and my perusal of the kernel sources leads me to believe that the NETLINK code does not honor it (support for the option appears to be protocol specific and I don't see it in the netlink code), but I could be missing something.

Please respond directly to my email address, jharan (at) brocade.com, as I do not subscribe to this list.

Thanks,

Jeff Haran
Brocade Communications

^ permalink raw reply

* Re: [PATCH] Documentation, clarify tuntap IPX example.
From: andrew hendry @ 2009-11-18  2:14 UTC (permalink / raw)
  To: Max Krasnyansky; +Cc: netdev@vger.kernel.org, linux-kernel
In-Reply-To: <4B035081.8040900@qualcomm.com>

Hi Max,

I started looking through the documentation because im looking to use
tun for X.25 over TCP. The IPX example sounded similar but i couldn't
get it to work as I was expecting. Looking for a hint in the right
direction.
There is an old non-mainline patch called x25tap (clone of obsolete
ethertap). I'm hoping to replace x25tap with tun.

The old x25tap creates a device like:
x25tap0   Link encap:generic X.25  HWaddr
          UP BROADCAST RUNNING NOARP MULTICAST  MTU:1024  Metric:1
          RX packets:3040785 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2895530 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10
          RX bytes:138787339 (132.3 Mb)  TX bytes:91395983 (87.1 Mb)
When the x25tap is loaded it has dev->type = ARPHRD_X25, after which
x.25 routing and AF_X25 sockets can be created.  Along with an XoT
userspace program which handles some basic headers and TCP port 1998
it works well.

If using tun, how does something get registered to handle protocol AF_X25?

Regards,
Andrew.

On Wed, Nov 18, 2009 at 12:40 PM, Max Krasnyansky <maxk@qualcomm.com> wrote:
> On 11/17/2009 05:30 PM, andrew hendry wrote:
>>
>> Can the TUNSETIFF ioctl change a tap's protocol to IPX as the
>> documentation suggests?
>> I think tun.c would need IFF_IPX_TAP added for it to work as described?
>> Otherwise tap can only be ptp or ethernet, and there is no way to
>> route or use AF_IPX.
>
> TAP is an Ethernet device. No special handling is required for IPX or for
> that matter any other protocol. Example seems fine too.
>
> Max
>
>> Signed-off-by: Andrew Hendry<andrew.hendry@gmail.com>
>>
>> --- a/Documentation/networking/tuntap.txt       2009-11-11
>> 14:03:22.676167648 +1100
>> +++ b/Documentation/networking/tuntap.txt       2009-11-18
>> 11:34:18.106647029 +1100
>> @@ -127,12 +127,14 @@ Ethernet device, which instead of receiv
>>  media, receives them from user space program and instead of sending
>>  packets via physical media sends them to the user space program.
>>
>> -Let's say that you configured IPX on the tap0, then whenever
>> -the kernel sends an IPX packet to tap0, it is passed to the application
>> -(VTun for example). The application encrypts, compresses and sends it to
>> -the other side over TCP or UDP. The application on the other side
>> decompresses
>> -and decrypts the data received and writes the packet to the TAP device,
>> -the kernel handles the packet like it came from real physical device.
>> +Let's say for the purpose of example, IPX support was added to tuntap.
>> +Then whenever the kernel routes an IPX packet to tap0, it is passed to
>> the
>> +application reading the file descriptor from /dev/net/tun (VTun for
>> example).
>> +The application encrypts, compresses and sends it to the other side over
>> TCP
>> +or UDP. The application on the other side decompresses and decrypts the
>> data
>> +received and writes the packet to the TAP device, the remote kernel
>> handles
>> +the packet like it came from real physical device. The IPX applications
>> are
>> +able to communicate as if there was a real IPX network.
>>
>>  4. What is the difference between TUN driver and TAP driver?
>>  TUN works with IP frames. TAP works with Ethernet frames.
>
>

^ permalink raw reply

* [PATCH 2.6.32] cxgb3: fix premature page unmap
From: Divy Le Ray @ 2009-11-18  2:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, linux-kernel, swise

From: Divy Le Ray <divy@chelsio.com>

unmap Rx page only when guaranteed that this page won't be
used anymore to allocate rx page chunks.

Signed-off-by: Divy Le Ray <divy@chelsio.com>
---

 drivers/net/cxgb3/sge.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)


diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index f866128..6366061 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -879,7 +879,7 @@ recycle:
 	pci_dma_sync_single_for_cpu(adap->pdev, dma_addr, len,
 				    PCI_DMA_FROMDEVICE);
 	(*sd->pg_chunk.p_cnt)--;
-	if (!*sd->pg_chunk.p_cnt)
+	if (!*sd->pg_chunk.p_cnt && sd->pg_chunk.page != fl->pg_chunk.page)
 		pci_unmap_page(adap->pdev,
 			       sd->pg_chunk.mapping,
 			       fl->alloc_size,
@@ -2088,7 +2088,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
 				    PCI_DMA_FROMDEVICE);
 
 	(*sd->pg_chunk.p_cnt)--;
-	if (!*sd->pg_chunk.p_cnt)
+	if (!*sd->pg_chunk.p_cnt && sd->pg_chunk.page != fl->pg_chunk.page)
 		pci_unmap_page(adap->pdev,
 			       sd->pg_chunk.mapping,
 			       fl->alloc_size,

^ permalink raw reply related

* Re: [RFC v2] mac80211: disallow bridging managed/adhoc interfaces
From: John W. Linville @ 2009-11-18  2:59 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <jwvy6m4bnqp.fsf-monnier+gmane.linux.kernel.wireless.general-mXXj517/zsQ@public.gmane.org>

On Tue, Nov 17, 2009 at 08:59:03PM -0500, Stefan Monnier wrote:
> > A number of people have tried to add a wireless interface
> > (in managed mode) to a bridge and then complained that it
> > doesn't work. It cannot work, however, because in 802.11
> [...]
> > To avoid such mistakes in the future, disallow adding a
> > wireless interface to a bridge.
> 
> As someone who's been bitten by this, I fully support this change.
> Still, it makes me wonder: my broadcom-based home-router using the wl.o
> driver can be set in "client bridge" mode.  How does it work?

If I'm not mistaken, that has a bunch of code embedded in it that
among other things can do a layer-2 version of NAT to rewrite the
MAC adresses for frames on the air.

YMMV...

John
-- 
John W. Linville                Someday the world will need a hero, and you
linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org                  might be all we have.  Be ready.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFC-PATCH] libiscsi dhcp handler
From: Rakesh Ranjan @ 2009-11-18  3:26 UTC (permalink / raw)
  To: Mike Christie
  Cc: open-iscsi-/JYPxA39Uh5TLH3MbocFFw, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, James.Bottomley-l3A5Bk7waGM,
	David Miller, Karen Xie, Rakesh Ranjan
In-Reply-To: <4B01577E.2020003-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>

Rakesh Ranjan wrote:
> David Miller wrote:
>> From: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
>> Date: Mon, 16 Nov 2009 18:41:49 +0530
>>
>>> Herein attached patches to support dhcp based provisioning for iSCSI
>>> offload capable cards. I have made dhcp code as generic as possible,
>>> please go through the code. Based on the feedback I will submit final
>>> version of these patches.
>> You can't really add objects to the build before the patch that
>> adds the source for that object.
>>
> 
> Hi david,
> 
> Fixed patch attached.

ping ...


--

You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=.

^ permalink raw reply

* Re: [PATCH 17/11]Optimize the upload speed for PPP connection.
From: William Allen Simpson @ 2009-11-18  4:00 UTC (permalink / raw)
  To: Valdis.Kletnieks; +Cc: huananhu, David Miller, netdev, linux-kernel
In-Reply-To: <13129.1258483787@turing-police.cc.vt.edu>

Valdis.Kletnieks@vt.edu wrote:
> The '-- ' *convention* isn't even at the next layer up, MIME.  If anything,
> it's out at the liveware level (though some MUAs provide code to make it
> a bit easier to deal with...)
> 
Hey Valdis, nice to hear from you....


> (Feel free to cite RFC chapter-and-verse if you disagree, and note that
> 'Informational' RFCs are never standards. ;)
> 
Yeah, a quick check shows it's mentioned in MIME RFC-1341 (June 1992), but
certainly going back to "Proposed standard for message encapsulation"
RFC-934 (January 1985) at the very least.  I seem to remember that Marshall
or Stef or somebody used it for digest sections too, but don't remember the
RFC number or a good search term.

Still, (relevance here) a convention observed for patches.

^ permalink raw reply

* Re: [PATCH 2/4] [RFC] Add c/r support for connected INET sockets (v5)
From: Serge E. Hallyn @ 2009-11-18  4:34 UTC (permalink / raw)
  To: Dan Smith; +Cc: containers, netdev
In-Reply-To: <1258471590-29768-3-git-send-email-danms@us.ibm.com>

Quoting Dan Smith (danms@us.ibm.com):
> This patch adds basic support for C/R of open INET sockets.  I think that
> all the important bits of the TCP and ICSK socket structures is saved,
> but I think there is still some additional IPv6 stuff that needs to be
> handled.
> 
> With this patch applied, the following script can be used to demonstrate
> the functionality:
> 
>   https://lists.linux-foundation.org/pipermail/containers/2009-October/021239.html
> 
> It shows that this enables migration of a sendmail process with open
> connections from one machine to another without dropping.
> 
> We probably need comments from the netdev people about the quality of
> sanity checking we do on the values in the ckpt_hdr_socket_inet
> structure on restart.
> 
> Note that this still doesn't address lingering sockets yet.
> 
> Changes in v5:
>  - Change ckpt_write_err() to ckpt_err()
> 
> Changes in v4:
>  - Use the new socket buffer restore functions introduced in the
>    previous patch
>  - Move listen_sockets list under the restart items in ckpt_ctx
>  - Rename RESTART_SOCK_LISTENONLY to RESTART_CONN_RESET
> 
> Changes in v3:
>  - Prevent restart from allowing a bind on a <1024 port unless the
>    user is granted that capability
>  - Add some sanity checking in the inet_precheck() function to make sure
>    the values read from the checkpoint image are within acceptable ranges
>  - Check the result of sock_restore_header_info() and fail if needed
> 
> Changes in v2:
>  - Restore saddr, rcv_saddr, daddr, sport, and dport from the sockaddr
>    structure instead of saving them separately
>  - Fix 'sock' naming in sock_cptrst()
>  - Don't take the queue lock before skb_queue_tail() since it is
>    done for us
>  - Allow "listen only" restore behavior if RESTART_SOCK_LISTENONLY
>    flag is specified on sys_restart()
>  - Pull the implementation of the list of listening sockets back into
>    this patch
>  - Fix dangling printk
>  - Add some comments around the parent/child restore logic
> 
> Cc: netdev@vger.kernel.org
> Acked-by: Oren Laadan <orenl@librato.com>
> Signed-off-by: Dan Smith <danms@us.ibm.com>

Acked-by: Serge Hallyn <serue@us.ibm.com>

> ---
>  checkpoint/sys.c                 |    4 +
>  include/linux/checkpoint.h       |    5 +-
>  include/linux/checkpoint_hdr.h   |   95 +++++++++
>  include/linux/checkpoint_types.h |    1 +
>  net/checkpoint.c                 |   27 ++--
>  net/ipv4/checkpoint.c            |  391 ++++++++++++++++++++++++++++++++++----
>  6 files changed, 473 insertions(+), 50 deletions(-)
> 
> diff --git a/checkpoint/sys.c b/checkpoint/sys.c
> index 9f9e825..baed891 100644
> --- a/checkpoint/sys.c
> +++ b/checkpoint/sys.c
> @@ -244,6 +244,8 @@ static void ckpt_ctx_free(struct ckpt_ctx *ctx)
> 
>  	kfree(ctx->pids_arr);
> 
> +	sock_listening_list_free(&ctx->listen_sockets);
> +
>  	kfree(ctx);
>  }
> 
> @@ -274,6 +276,8 @@ static struct ckpt_ctx *ckpt_ctx_alloc(int fd, unsigned long uflags,
> 
>  	mutex_init(&ctx->msg_mutex);
> 
> +	INIT_LIST_HEAD(&ctx->listen_sockets);
> +
>  	err = -EBADF;
>  	ctx->file = fget(fd);
>  	if (!ctx->file)
> diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
> index 0eff43e..ddc9aa0 100644
> --- a/include/linux/checkpoint.h
> +++ b/include/linux/checkpoint.h
> @@ -20,6 +20,7 @@
>  #define RESTART_FROZEN		0x2
>  #define RESTART_GHOST		0x4
>  #define RESTART_KEEP_LSM	0x8
> +#define RESTART_CONN_RESET      0x10
> 
>  /* misc user visible */
>  #define CHECKPOINT_FD_NONE	-1
> @@ -53,7 +54,8 @@
>  	(RESTART_TASKSELF | \
>  	 RESTART_FROZEN | \
>  	 RESTART_KEEP_LSM | \
> -	 RESTART_GHOST)
> +	 RESTART_GHOST | \
> +	 RESTART_CONN_RESET)
>  #define CKPT_LSM_INFO_LEN 200
>  #define CKPT_LSM_STRING_MAX 1024
> 
> @@ -105,6 +107,7 @@ extern int ckpt_sock_getnames(struct ckpt_ctx *ctx,
>  			      struct sockaddr *loc, unsigned *loc_len,
>  			      struct sockaddr *rem, unsigned *rem_len);
>  struct sk_buff *sock_restore_skb(struct ckpt_ctx *ctx);
> +void sock_listening_list_free(struct list_head *head);
> 
>  /* ckpt kflags */
>  #define ckpt_set_ctx_kflag(__ctx, __kflag)  \
> diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
> index 787cf89..d1a93e3 100644
> --- a/include/linux/checkpoint_hdr.h
> +++ b/include/linux/checkpoint_hdr.h
> @@ -15,6 +15,7 @@
>  #include <linux/socket.h>
>  #include <linux/un.h>
>  #include <linux/in.h>
> +#include <linux/in6.h>
>  #else
>  #include <sys/types.h>
>  #include <linux/types.h>
> @@ -625,6 +626,100 @@ struct ckpt_hdr_socket_unix {
> 
>  struct ckpt_hdr_socket_inet {
>  	struct ckpt_hdr h;
> +	__u32 daddr;
> +	__u32 rcv_saddr;
> +	__u32 saddr;
> +	__u16 dport;
> +	__u16 num;
> +	__u16 sport;
> +	__s16 uc_ttl;
> +	__u16 cmsg_flags;
> +
> +	struct {
> +		__u64 timeout;
> +		__u32 ato;
> +		__u32 lrcvtime;
> +		__u16 last_seg_size;
> +		__u16 rcv_mss;
> +		__u8 pending;
> +		__u8 quick;
> +		__u8 pingpong;
> +		__u8 blocked;
> +	} icsk_ack __attribute__ ((aligned(8)));
> +
> +	/* FIXME: Skipped opt, tos, multicast, cork settings */
> +
> +	struct {
> +		__u32 rcv_nxt;
> +		__u32 copied_seq;
> +		__u32 rcv_wup;
> +		__u32 snd_nxt;
> +		__u32 snd_una;
> +		__u32 snd_sml;
> +		__u32 rcv_tstamp;
> +		__u32 lsndtime;
> +
> +		__u32 snd_wl1;
> +		__u32 snd_wnd;
> +		__u32 max_window;
> +		__u32 mss_cache;
> +		__u32 window_clamp;
> +		__u32 rcv_ssthresh;
> +		__u32 frto_highmark;
> +
> +		__u32 srtt;
> +		__u32 mdev;
> +		__u32 mdev_max;
> +		__u32 rttvar;
> +		__u32 rtt_seq;
> +
> +		__u32 packets_out;
> +		__u32 retrans_out;
> +
> +		__u32 snd_up;
> +		__u32 rcv_wnd;
> +		__u32 write_seq;
> +		__u32 pushed_seq;
> +		__u32 lost_out;
> +		__u32 sacked_out;
> +		__u32 fackets_out;
> +		__u32 tso_deferred;
> +		__u32 bytes_acked;
> +
> +		__s32 lost_cnt_hint;
> +		__u32 retransmit_high;
> +
> +		__u32 lost_retrans_low;
> +
> +		__u32 prior_ssthresh;
> +		__u32 high_seq;
> +
> +		__u32 retrans_stamp;
> +		__u32 undo_marker;
> +		__s32 undo_retrans;
> +		__u32 total_retrans;
> +
> +		__u32 urg_seq;
> +		__u32 keepalive_time;
> +		__u32 keepalive_intvl;
> +
> +		__u16 urg_data;
> +		__u16 advmss;
> +		__u8 frto_counter;
> +		__u8 nonagle;
> +
> +		__u8 ecn_flags;
> +		__u8 reordering;
> +
> +		__u8 keepalive_probes;
> +	} tcp __attribute__ ((aligned(8)));
> +
> +	struct {
> +		struct in6_addr saddr;
> +		struct in6_addr rcv_saddr;
> +		struct in6_addr daddr;
> +	} inet6 __attribute__ ((aligned(8)));
> +
>  	__u32 laddr_len;
>  	__u32 raddr_len;
>  	struct sockaddr_in laddr;
> diff --git a/include/linux/checkpoint_types.h b/include/linux/checkpoint_types.h
> index 77f8592..79c9c09 100644
> --- a/include/linux/checkpoint_types.h
> +++ b/include/linux/checkpoint_types.h
> @@ -82,6 +82,7 @@ struct ckpt_ctx {
>  	wait_queue_head_t waitq;	/* waitqueue for restarting tasks */
>  	wait_queue_head_t ghostq;	/* waitqueue for ghost tasks */
>  	struct cred *realcred, *ecred;	/* tmp storage for cred at restart */
> +	struct list_head listen_sockets;/* listening parent sockets */
> 
>  	struct ckpt_stats stats;	/* statistics */
> 
> diff --git a/net/checkpoint.c b/net/checkpoint.c
> index 49d9a2f..aba1497 100644
> --- a/net/checkpoint.c
> +++ b/net/checkpoint.c
> @@ -324,6 +324,7 @@ static int __sock_write_skb(struct ckpt_ctx *ctx,
> 
>  static int __sock_write_buffers(struct ckpt_ctx *ctx,
>  				struct sk_buff_head *queue,
> +				uint16_t family,
>  				int dst_objref)
>  {
>  	struct sk_buff *skb;
> @@ -336,11 +337,11 @@ static int __sock_write_buffers(struct ckpt_ctx *ctx,
>  			return -EBUSY;
>  		}
> 
> -		/* The other ancillary messages are always present
> -		 * unlike descriptors.  Even though we can't detect
> -		 * them and fail the checkpoint, we're not at risk
> -		 * because we don't save out (or restore) the control
> -		 * information contained in the skb.
> +		/* The other ancillary messages UNIX are always
> +		 * present unlike descriptors.  Even though we can't
> +		 * detect them and fail the checkpoint, we're not at
> +		 * risk because we don't restore the control
> +		 * information in the UNIX code.
>  		 */
> 
>  		ret = __sock_write_skb(ctx, skb, dst_objref);
> @@ -353,6 +354,7 @@ static int __sock_write_buffers(struct ckpt_ctx *ctx,
> 
>  static int sock_write_buffers(struct ckpt_ctx *ctx,
>  			      struct sk_buff_head *queue,
> +			      uint16_t family,
>  			      int dst_objref)
>  {
>  	struct ckpt_hdr_socket_queue *h;
> @@ -372,7 +374,7 @@ static int sock_write_buffers(struct ckpt_ctx *ctx,
>  	h->skb_count = ret;
>  	ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h);
>  	if (!ret)
> -		ret = __sock_write_buffers(ctx, &tmpq, dst_objref);
> +		ret = __sock_write_buffers(ctx, &tmpq, family, dst_objref);
> 
>   out:
>  	ckpt_hdr_put(ctx, h);
> @@ -394,12 +396,14 @@ int sock_deferred_write_buffers(void *data)
>  		return dst_objref;
>  	}
> 
> -	ret = sock_write_buffers(ctx, &dq->sk->sk_receive_queue, dst_objref);
> +	ret = sock_write_buffers(ctx, &dq->sk->sk_receive_queue,
> +				 dq->sk->sk_family, dst_objref);
>  	ckpt_debug("write recv buffers: %i\n", ret);
>  	if (ret < 0)
>  		return ret;
> 
> -	ret = sock_write_buffers(ctx, &dq->sk->sk_write_queue, dst_objref);
> +	ret = sock_write_buffers(ctx, &dq->sk->sk_write_queue,
> +				 dq->sk->sk_family, dst_objref);
>  	ckpt_debug("write send buffers: %i\n", ret);
> 
>  	return ret;
> @@ -924,10 +928,9 @@ struct sock *do_sock_restore(struct ckpt_ctx *ctx)
>  		goto err;
> 
>  	if ((h->sock_common.family == AF_INET) &&
> -	    (h->sock.state != TCP_LISTEN)) {
> -		/* Temporary hack to enable restore of TCP_LISTEN sockets
> -		 * while forcing anything else to a closed state
> -		 */
> +	    (h->sock.state != TCP_LISTEN) &&
> +	    (ctx->uflags & RESTART_CONN_RESET)) {
> +		ckpt_debug("Forcing open socket closed\n");
>  		sock->sk->sk_state = TCP_CLOSE;
>  		sock->state = SS_UNCONNECTED;
>  	}
> diff --git a/net/ipv4/checkpoint.c b/net/ipv4/checkpoint.c
> index 9cbbf5e..3e20cc9 100644
> --- a/net/ipv4/checkpoint.c
> +++ b/net/ipv4/checkpoint.c
> @@ -17,6 +17,7 @@
>  #include <linux/deferqueue.h>
>  #include <net/tcp_states.h>
>  #include <net/tcp.h>
> +#include <net/ipv6.h>
> 
>  struct dq_sock {
>  	struct ckpt_ctx *ctx;
> @@ -28,6 +29,236 @@ struct dq_buffers {
>  	struct sock *sk;
>  };
> 
> +struct listen_item {
> +	struct sock *sk;
> +	struct list_head list;
> +};
> +
> +void sock_listening_list_free(struct list_head *head)
> +{
> +	struct listen_item *item, *tmp;
> +
> +	list_for_each_entry_safe(item, tmp, head, list) {
> +		list_del(&item->list);
> +		kfree(item);
> +	}
> +}
> +
> +static int sock_listening_list_add(struct ckpt_ctx *ctx, struct sock *sk)
> +{
> +	struct listen_item *item;
> +
> +	item = kmalloc(sizeof(*item), GFP_KERNEL);
> +	if (!item)
> +		return -ENOMEM;
> +
> +	item->sk = sk;
> +	list_add(&item->list, &ctx->listen_sockets);
> +
> +	return 0;
> +}
> +
> +static struct sock *sock_get_parent(struct ckpt_ctx *ctx, struct sock *sk)
> +{
> +	struct listen_item *item;
> +
> +	list_for_each_entry(item, &ctx->listen_sockets, list) {
> +		if (inet_sk(sk)->sport == inet_sk(item->sk)->sport)
> +			return item->sk;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int sock_hash_parent(void *data)
> +{
> +	struct dq_sock *dq = (struct dq_sock *)data;
> +	struct sock *parent;
> +
> +	ckpt_debug("INET post-restart hash\n");
> +
> +	dq->sk->sk_prot->hash(dq->sk);
> +
> +	/* If there is a listening socket with the same source port,
> +	 * then become a child of that socket [we are the result of an
> +	 * accept()].  Otherwise hash ourselves directly in [we are
> +	 * the result of a connect()]
> +	 */
> +
> +	parent = sock_get_parent(dq->ctx, dq->sk);
> +	if (parent) {
> +		inet_sk(dq->sk)->num = ntohs(inet_sk(dq->sk)->sport);
> +		local_bh_disable();
> +		__inet_inherit_port(parent, dq->sk);
> +		local_bh_enable();
> +	} else {
> +		inet_sk(dq->sk)->num = 0;
> +		inet_hash_connect(&tcp_death_row, dq->sk);
> +		inet_sk(dq->sk)->num = ntohs(inet_sk(dq->sk)->sport);
> +	}
> +
> +	return 0;
> +}
> +
> +static int sock_defer_hash(struct ckpt_ctx *ctx, struct sock *sock)
> +{
> +	struct dq_sock dq;
> +
> +	dq.sk = sock;
> +	dq.ctx = ctx;
> +
> +	return deferqueue_add(ctx->deferqueue, &dq, sizeof(dq),
> +			      sock_hash_parent, NULL);
> +}
> +
> +static int sock_inet_tcp_cptrst(struct ckpt_ctx *ctx,
> +				struct tcp_sock *sk,
> +				struct ckpt_hdr_socket_inet *hh,
> +				int op)
> +{
> +	CKPT_COPY(op, hh->tcp.rcv_nxt, sk->rcv_nxt);
> +	CKPT_COPY(op, hh->tcp.copied_seq, sk->copied_seq);
> +	CKPT_COPY(op, hh->tcp.rcv_wup, sk->rcv_wup);
> +	CKPT_COPY(op, hh->tcp.snd_nxt, sk->snd_nxt);
> +	CKPT_COPY(op, hh->tcp.snd_una, sk->snd_una);
> +	CKPT_COPY(op, hh->tcp.snd_sml, sk->snd_sml);
> +	CKPT_COPY(op, hh->tcp.rcv_tstamp, sk->rcv_tstamp);
> +	CKPT_COPY(op, hh->tcp.lsndtime, sk->lsndtime);
> +
> +	CKPT_COPY(op, hh->tcp.snd_wl1, sk->snd_wl1);
> +	CKPT_COPY(op, hh->tcp.snd_wnd, sk->snd_wnd);
> +	CKPT_COPY(op, hh->tcp.max_window, sk->max_window);
> +	CKPT_COPY(op, hh->tcp.mss_cache, sk->mss_cache);
> +	CKPT_COPY(op, hh->tcp.window_clamp, sk->window_clamp);
> +	CKPT_COPY(op, hh->tcp.rcv_ssthresh, sk->rcv_ssthresh);
> +	CKPT_COPY(op, hh->tcp.frto_highmark, sk->frto_highmark);
> +	CKPT_COPY(op, hh->tcp.advmss, sk->advmss);
> +	CKPT_COPY(op, hh->tcp.frto_counter, sk->frto_counter);
> +	CKPT_COPY(op, hh->tcp.nonagle, sk->nonagle);
> +
> +	CKPT_COPY(op, hh->tcp.srtt, sk->srtt);
> +	CKPT_COPY(op, hh->tcp.mdev, sk->mdev);
> +	CKPT_COPY(op, hh->tcp.mdev_max, sk->mdev_max);
> +	CKPT_COPY(op, hh->tcp.rttvar, sk->rttvar);
> +	CKPT_COPY(op, hh->tcp.rtt_seq, sk->rtt_seq);
> +
> +	CKPT_COPY(op, hh->tcp.packets_out, sk->packets_out);
> +	CKPT_COPY(op, hh->tcp.retrans_out, sk->retrans_out);
> +
> +	CKPT_COPY(op, hh->tcp.urg_data, sk->urg_data);
> +	CKPT_COPY(op, hh->tcp.ecn_flags, sk->ecn_flags);
> +	CKPT_COPY(op, hh->tcp.reordering, sk->reordering);
> +	CKPT_COPY(op, hh->tcp.snd_up, sk->snd_up);
> +
> +	CKPT_COPY(op, hh->tcp.keepalive_probes, sk->keepalive_probes);
> +
> +	CKPT_COPY(op, hh->tcp.rcv_wnd, sk->rcv_wnd);
> +	CKPT_COPY(op, hh->tcp.write_seq, sk->write_seq);
> +	CKPT_COPY(op, hh->tcp.pushed_seq, sk->pushed_seq);
> +	CKPT_COPY(op, hh->tcp.lost_out, sk->lost_out);
> +	CKPT_COPY(op, hh->tcp.sacked_out, sk->sacked_out);
> +	CKPT_COPY(op, hh->tcp.fackets_out, sk->fackets_out);
> +	CKPT_COPY(op, hh->tcp.tso_deferred, sk->tso_deferred);
> +	CKPT_COPY(op, hh->tcp.bytes_acked, sk->bytes_acked);
> +
> +	CKPT_COPY(op, hh->tcp.lost_cnt_hint, sk->lost_cnt_hint);
> +	CKPT_COPY(op, hh->tcp.retransmit_high, sk->retransmit_high);
> +
> +	CKPT_COPY(op, hh->tcp.lost_retrans_low, sk->lost_retrans_low);
> +
> +	CKPT_COPY(op, hh->tcp.prior_ssthresh, sk->prior_ssthresh);
> +	CKPT_COPY(op, hh->tcp.high_seq, sk->high_seq);
> +
> +	CKPT_COPY(op, hh->tcp.retrans_stamp, sk->retrans_stamp);
> +	CKPT_COPY(op, hh->tcp.undo_marker, sk->undo_marker);
> +	CKPT_COPY(op, hh->tcp.undo_retrans, sk->undo_retrans);
> +	CKPT_COPY(op, hh->tcp.total_retrans, sk->total_retrans);
> +
> +	CKPT_COPY(op, hh->tcp.urg_seq, sk->urg_seq);
> +	CKPT_COPY(op, hh->tcp.keepalive_time, sk->keepalive_time);
> +	CKPT_COPY(op, hh->tcp.keepalive_intvl, sk->keepalive_intvl);
> +
> +	if (!skb_queue_empty(&sk->ucopy.prequeue))
> +		printk("PREQUEUE!\n");
> +
> +	return 0;
> +}
> +
> +static int sock_inet_restore_addrs(struct inet_sock *inet,
> +				   struct ckpt_hdr_socket_inet *hh)
> +{
> +	inet->daddr = hh->raddr.sin_addr.s_addr;
> +	inet->saddr = hh->laddr.sin_addr.s_addr;
> +	inet->rcv_saddr = inet->saddr;
> +
> +	inet->dport = hh->raddr.sin_port;
> +	inet->sport = hh->laddr.sin_port;
> +
> +	return 0;
> +}
> +
> +static int sock_inet_cptrst(struct ckpt_ctx *ctx,
> +			    struct sock *sk,
> +			    struct ckpt_hdr_socket_inet *hh,
> +			    int op)
> +{
> +	struct inet_sock *inet = inet_sk(sk);
> +	struct inet_connection_sock *icsk = inet_csk(sk);
> +	int ret;
> +
> +	if (op == CKPT_CPT) {
> +		CKPT_COPY(op, hh->daddr, inet->daddr);
> +		CKPT_COPY(op, hh->rcv_saddr, inet->rcv_saddr);
> +		CKPT_COPY(op, hh->dport, inet->dport);
> +		CKPT_COPY(op, hh->saddr, inet->saddr);
> +		CKPT_COPY(op, hh->sport, inet->sport);
> +	} else {
> +		ret = sock_inet_restore_addrs(inet, hh);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	CKPT_COPY(op, hh->num, inet->num);
> +	CKPT_COPY(op, hh->uc_ttl, inet->uc_ttl);
> +	CKPT_COPY(op, hh->cmsg_flags, inet->cmsg_flags);
> +
> +	CKPT_COPY(op, hh->icsk_ack.pending, icsk->icsk_ack.pending);
> +	CKPT_COPY(op, hh->icsk_ack.quick, icsk->icsk_ack.quick);
> +	CKPT_COPY(op, hh->icsk_ack.pingpong, icsk->icsk_ack.pingpong);
> +	CKPT_COPY(op, hh->icsk_ack.blocked, icsk->icsk_ack.blocked);
> +	CKPT_COPY(op, hh->icsk_ack.ato, icsk->icsk_ack.ato);
> +	CKPT_COPY(op, hh->icsk_ack.timeout, icsk->icsk_ack.timeout);
> +	CKPT_COPY(op, hh->icsk_ack.lrcvtime, icsk->icsk_ack.lrcvtime);
> +	CKPT_COPY(op,
> +		  hh->icsk_ack.last_seg_size, icsk->icsk_ack.last_seg_size);
> +	CKPT_COPY(op, hh->icsk_ack.rcv_mss, icsk->icsk_ack.rcv_mss);
> +
> +	if (sk->sk_protocol == IPPROTO_TCP)
> +		ret = sock_inet_tcp_cptrst(ctx, tcp_sk(sk), hh, op);
> +	else if (sk->sk_protocol == IPPROTO_UDP)
> +		ret = 0;
> +	else {
> +		ret = -EINVAL;
> +		ckpt_err(ctx, ret, "unknown socket protocol %d",
> +			 sk->sk_protocol);
> +	}
> +
> +	if (sk->sk_family == AF_INET6) {
> +		struct ipv6_pinfo *inet6 = inet6_sk(sk);
> +		if (op == CKPT_CPT) {
> +			ipv6_addr_copy(&hh->inet6.saddr, &inet6->saddr);
> +			ipv6_addr_copy(&hh->inet6.rcv_saddr, &inet6->rcv_saddr);
> +			ipv6_addr_copy(&hh->inet6.daddr, &inet6->daddr);
> +		} else {
> +			ipv6_addr_copy(&inet6->saddr, &hh->inet6.saddr);
> +			ipv6_addr_copy(&inet6->rcv_saddr, &hh->inet6.rcv_saddr);
> +			ipv6_addr_copy(&inet6->daddr, &hh->inet6.daddr);
> +		}
> +	}
> +
> +	return ret;
> +}
> +
>  int inet_checkpoint(struct ckpt_ctx *ctx, struct socket *sock)
>  {
>  	struct ckpt_hdr_socket_inet *in;
> @@ -43,6 +274,10 @@ int inet_checkpoint(struct ckpt_ctx *ctx, struct socket *sock)
>  	if (ret)
>  		goto out;
> 
> +	ret = sock_inet_cptrst(ctx, sock->sk, in, CKPT_CPT);
> +	if (ret < 0)
> +		goto out;
> +
>  	ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) in);
>   out:
>  	ckpt_hdr_put(ctx, in);
> @@ -55,51 +290,22 @@ int inet_collect(struct ckpt_ctx *ctx, struct socket *sock)
>  	return ckpt_obj_collect(ctx, sock->sk, CKPT_OBJ_SOCK);
>  }
> 
> -static int inet_read_buffer(struct ckpt_ctx *ctx, struct sk_buff_head *queue)
> +static int inet_read_buffer(struct ckpt_ctx *ctx,
> +			    struct sk_buff_head *queue)
>  {
> -	struct ckpt_hdr_socket_buffer *h;
> -	int len;
> -	int ret;
>  	struct sk_buff *skb = NULL;
> 
> -	h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_SOCKET_BUFFER);
> -	if (IS_ERR(h))
> -		return PTR_ERR(h);
> -
> -	len = _ckpt_read_obj_type(ctx, NULL, 0, CKPT_HDR_BUFFER);
> -	if (len < 0) {
> -		ret = len;
> -		goto out;
> -	} else if (len > SKB_MAX_ALLOC) {
> -		ckpt_debug("Socket buffer too big (%i > %lu)",
> -			   len, SKB_MAX_ALLOC);
> -		ret = -ENOSPC;
> -		goto out;
> -	}
> -
> -	skb = alloc_skb(len, GFP_KERNEL);
> -	if (!skb) {
> -		ret = -ENOMEM;
> -		goto out;
> -	}
> -
> -	ret = ckpt_kread(ctx, skb_put(skb, len), len);
> -	if (ret < 0)
> -		goto out;
> +	skb = sock_restore_skb(ctx);
> +	if (IS_ERR(skb))
> +		return PTR_ERR(skb);
> 
> -	spin_lock(&queue->lock);
>  	skb_queue_tail(queue, skb);
> -	spin_unlock(&queue->lock);
> - out:
> -	ckpt_hdr_put(ctx, h);
> -
> -	if ((ret < 0) && skb)
> -		kfree_skb(skb);
> 
> -	return ret;
> +	return skb->len;
>  }
> 
> -static int inet_read_buffers(struct ckpt_ctx *ctx, struct sk_buff_head *queue)
> +static int inet_read_buffers(struct ckpt_ctx *ctx,
> +			     struct sk_buff_head *queue)
>  {
>  	struct ckpt_hdr_socket_queue *h;
>  	int ret = 0;
> @@ -162,6 +368,19 @@ static int inet_defer_restore_buffers(struct ckpt_ctx *ctx, struct sock *sk)
> 
>  static int inet_precheck(struct socket *sock, struct ckpt_hdr_socket_inet *in)
>  {
> +	__u8 icsk_ack_mask = ICSK_ACK_SCHED | ICSK_ACK_TIMER |
> +		ICSK_ACK_PUSHED | ICSK_ACK_PUSHED2;
> +	__u16 urg_mask = TCP_URG_VALID | TCP_URG_NOTYET | TCP_URG_READ;
> +	__u8 nonagle_mask = TCP_NAGLE_OFF | TCP_NAGLE_CORK | TCP_NAGLE_PUSH;
> +	__u8 ecn_mask = TCP_ECN_OK | TCP_ECN_QUEUE_CWR | TCP_ECN_DEMAND_CWR;
> +
> +	if ((htons(in->laddr.sin_port) < PROT_SOCK) &&
> +	    !capable(CAP_NET_BIND_SERVICE)) {
> +		ckpt_debug("unable to bind to port %hu\n",
> +			   htons(in->laddr.sin_port));
> +		return -EINVAL;
> +	}
> +
>  	if (in->laddr_len > sizeof(struct sockaddr_in)) {
>  		ckpt_debug("laddr_len is too big\n");
>  		return -EINVAL;
> @@ -172,6 +391,77 @@ static int inet_precheck(struct socket *sock, struct ckpt_hdr_socket_inet *in)
>  		return -EINVAL;
>  	}
> 
> +	/* Set ato to the default */
> +	in->icsk_ack.ato = TCP_ATO_MIN;
> +
> +	/* No quick acks are scheduled after a restart */
> +	in->icsk_ack.quick = 0;
> +
> +	if (in->icsk_ack.pending & ~icsk_ack_mask) {
> +		ckpt_debug("invalid pending flags 0x%x\n",
> +			   in->icsk_ack.pending & ~icsk_ack_mask);
> +		return -EINVAL;
> +	}
> +
> +	if (in->icsk_ack.pingpong > 1) {
> +		ckpt_debug("invalid icsk_ack.pingpong value\n");
> +		return -EINVAL;
> +	}
> +
> +	if (in->icsk_ack.blocked > 1) {
> +		ckpt_debug("invalid icsk_ack.blocked value\n");
> +		return -EINVAL;
> +	}
> +
> +	/* do_tcp_setsockopt() quietly makes this coercion */
> +	if (in->tcp.window_clamp < (SOCK_MIN_RCVBUF / 2))
> +		in->tcp.window_clamp = SOCK_MIN_RCVBUF / 2;
> +	else if (in->tcp.window_clamp > 65535U) {
> +		ckpt_debug("invalid window_clamp value\n");
> +		return -EINVAL;
> +	}
> +
> +	if (in->tcp.rcv_ssthresh > (4U * in->tcp.advmss))
> +		in->tcp.rcv_ssthresh = 4U * in->tcp.advmss;
> +
> +	/* These will all be recalculated on the next call to
> +	 * tcp_rtt_estimator()
> +	 */
> +	in->tcp.srtt = in->tcp.mdev = in->tcp.mdev_max = 0;
> +	in->tcp.rttvar = in->tcp.rtt_seq = 0;
> +
> +	/* Might want to set packets_out to zero ? */
> +
> +	if (in->tcp.rcv_wnd > MAX_TCP_WINDOW)
> +		in->tcp.rcv_wnd = MAX_TCP_WINDOW;
> +
> +	if (in->tcp.keepalive_intvl > MAX_TCP_KEEPINTVL) {
> +		ckpt_debug("keepalive_intvl %i out of range\n",
> +			   in->tcp.keepalive_intvl);
> +		return -EINVAL;
> +	}
> +
> +	if (in->tcp.keepalive_probes > MAX_TCP_KEEPCNT) {
> +		ckpt_debug("Invalid keepalive_probes value %i\n",
> +			   in->tcp.keepalive_probes);
> +		return -EINVAL;
> +	}
> +
> +	if (in->tcp.urg_data & ~urg_mask) {
> +		ckpt_debug("Invalid urg_data value\n");
> +		return -EINVAL;
> +	}
> +
> +	if (in->tcp.nonagle & ~nonagle_mask) {
> +		ckpt_debug("Invalid nonagle value\n");
> +		return -EINVAL;
> +	}
> +
> +	if (in->tcp.ecn_flags & ~ecn_mask) {
> +		ckpt_debug("Invalid ecn_flags value\n");
> +		return -EINVAL;
> +	}
> +
>  	return 0;
>  }
> 
> @@ -209,8 +499,35 @@ int inet_restore(struct ckpt_ctx *ctx,
>  			ckpt_debug("inet listen: %i\n", ret);
>  			if (ret < 0)
>  				goto out;
> +
> +			/* We are a listening socket, so add ourselves
> +			 * to the list of parent sockets.  This will
> +			 * allow our children to find us later and
> +			 * link up
> +			 */
> +
> +			ret = sock_listening_list_add(ctx, sock->sk);
> +			if (ret < 0)
> +				goto out;
>  		}
>  	} else {
> +		ret = sock_inet_cptrst(ctx, sock->sk, in, CKPT_RST);
> +		if (ret)
> +			goto out;
> +
> +		if ((h->sock.state == TCP_ESTABLISHED) &&
> +		    (h->sock.protocol == IPPROTO_TCP)) {
> +			/* A connected socket that was spawned from an
> +			 * accept() needs to be hashed with its parent
> +			 * listening socket in order to receive
> +			 * traffic on the original port.  Since we may
> +			 * not have restarted the parent yet, we defer
> +			 * this until later when we know we have all
> +			 * the listening sockets accounted for.
> +			 */
> +			ret = sock_defer_hash(ctx, sock->sk);
> +		}
> +
>  		if (!sock_flag(sock->sk, SOCK_DEAD))
>  			ret = inet_defer_restore_buffers(ctx, sock->sk);
>  	}
> -- 
> 1.6.2.5
> 
> _______________________________________________
> Containers mailing list
> Containers@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/containers

^ permalink raw reply

* Re: [PATCH 17/11]Optimize the upload speed for PPP connection.
From: William Allen Simpson @ 2009-11-18  5:04 UTC (permalink / raw)
  To: David Miller; +Cc: huananhu, netdev, linux-kernel
In-Reply-To: <20091117.034959.159359822.davem@davemloft.net>

David Miller wrote:
> From: William Allen Simpson <william.allen.simpson@gmail.com>
> Date: Tue, 17 Nov 2009 05:20:09 -0500
> 
>> What David may have meant, had he followed
>> Documentation/ManagementStyle or had any project management skills
>> what-so-ever, is that you need to follow
>> Documentation/SubmittingPatches more carefully.
> 
> Are personal attacks on me really necessary?
> 
Actually, ironic sarcasm (juxtaposition) is a form of humor, fairly
popular on such venues as "The Daily Show". :-)


> Do you want me to look closely at your patches with a high priority
> when you submit them for inclusion?
> 
Great, you're planning to start a new practice?  So far, I've only been
blessed with:

* 1st contact (Oct 2):

      "Otherwise asking for a is absolutely pointless as we have no
      context in which to judge the code you're showing us."

   The context (and entire previous patch) was pointed at by a link
   in the message, and an internet-draft, but that would have required
   effort (clicking and browsing).

   Not exactly what I'd call "look closely at your patches"....

* 2nd contact (Oct 5), replying to my post of Oct 3:

      "struct tcp_sock is already WAY TOO BIG on 64-bit systems, adding
      20 more bytes to it for some odd-ball feature is not something I'm
      willing to do, sorry."

   Always delighted to know our work is an "odd-ball feature"....

* 3rd contact, sending private email to you as maintainer, suggested by
   Andi Kleen's "On submitting kernel patches" for resolving conflicts,
   and getting flamed for sending private email to you!

* Recently, flamed for re-sending a query (after waiting 30 days):

      "Complaining that your work isn't getting looked at in a timely
      manner will always have the exact opposite effect that you want,
      it makes people have a smaller desire to look at your stuff."

   Yeah, 30 days just isn't long enough....  Fortunately, Eric Dumazet
   and Paul E. McKenney were really helpful (and others privately), and
   I thank them again!

* 2 days ago, flamed again for re-sending a patch (after waiting 5 days),
   although you'd never Ack'd or otherwise responded.


> You may be right, but that doesn't matter if you're interested in
> working together with me in the future.  There are diplomatic ways to
> do everything, and this wasn't one of those ways.
> 
Working *together* would be handy!  But that implies cooperation and
respect -- *not* biting the newbies nor dropping the F-bomb.

^ permalink raw reply

* RE: [PATCHv9 3/3] vhost_net: a kernel-level virtio server
From: Xin, Xiaohui @ 2009-11-18  5:42 UTC (permalink / raw)
  To: Michael S. Tsirkin, netdev@vger.kernel.org,
	virtualization@lists.linux-foundation.org, "kvm@
In-Reply-To: <20091109172230.GD4724@redhat.com>

Michael,
>From the http://www.linux-kvm.org/page/VhostNet, we can see netperf with TCP_STREAM can get more than 4GMb/s for the receive side, and more than 5GMb/s for the send side.
Is it the result from the raw socket or through tap?
I want to duplicate such performance with vhost on my side. I can only get more than 1GMb/s with following conditions:
1) disabled the GRO feature in the host 10G NIC driver
2) vi->big_packet in guest is false
3) MTU is 1500.
4) raw socket, not the tap
5) using your vhost git tree

Is that the reasonable result with such conditions or maybe I have made some silly mistakes somewhere I don't know yet?
May you kindly describe your test environment/conditions in detail to have much better performance in your website (I really need the performance)?

And I have tested the tun support with vhost now, and may you share your /home/mst/ifup script here?

Thanks
Xiaohui


-----Original Message-----
From: kvm-owner@vger.kernel.org [mailto:kvm-owner@vger.kernel.org] On Behalf Of Michael S. Tsirkin
Sent: Tuesday, November 10, 2009 1:23 AM
To: netdev@vger.kernel.org; virtualization@lists.linux-foundation.org; kvm@vger.kernel.org; linux-kernel@vger.kernel.org; mingo@elte.hu; linux-mm@kvack.org; akpm@linux-foundation.org; hpa@zytor.com; gregory.haskins@gmail.com; Rusty Russell; s.hetze@linux-ag.com; Daniel Walker; Eric Dumazet
Subject: [PATCHv9 3/3] vhost_net: a kernel-level virtio server

What it is: vhost net is a character device that can be used to reduce
the number of system calls involved in virtio networking.
Existing virtio net code is used in the guest without modification.

There's similarity with vringfd, with some differences and reduced scope
- uses eventfd for signalling
- structures can be moved around in memory at any time (good for
  migration, bug work-arounds in userspace)
- write logging is supported (good for migration)
- support memory table and not just an offset (needed for kvm)

common virtio related code has been put in a separate file vhost.c and
can be made into a separate module if/when more backends appear.  I used
Rusty's lguest.c as the source for developing this part : this supplied
me with witty comments I wouldn't be able to write myself.

What it is not: vhost net is not a bus, and not a generic new system
call. No assumptions are made on how guest performs hypercalls.
Userspace hypervisors are supported as well as kvm.

How it works: Basically, we connect virtio frontend (configured by
userspace) to a backend. The backend could be a network device, or a tap
device.  Backend is also configured by userspace, including vlan/mac
etc.

Status: This works for me, and I haven't see any crashes.
Compared to userspace, people reported improved latency (as I save up to
4 system calls per packet), as well as better bandwidth and CPU
utilization.

Features that I plan to look at in the future:
- mergeable buffers
- zero copy
- scalability tuning: figure out the best threading model to use

Note on RCU usage (this is also documented in vhost.h, near
private_pointer which is the value protected by this variant of RCU):
what is happening is that the rcu_dereference() is being used in a
workqueue item.  The role of rcu_read_lock() is taken on by the start of
execution of the workqueue item, of rcu_read_unlock() by the end of
execution of the workqueue item, and of synchronize_rcu() by
flush_workqueue()/flush_work(). In the future we might need to apply
some gcc attribute or sparse annotation to the function passed to
INIT_WORK(). Paul's ack below is for this RCU usage.

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 MAINTAINERS                |    9 +
 arch/x86/kvm/Kconfig       |    1 +
 drivers/Makefile           |    1 +
 drivers/vhost/Kconfig      |   11 +
 drivers/vhost/Makefile     |    2 +
 drivers/vhost/net.c        |  648 +++++++++++++++++++++++++++++
 drivers/vhost/vhost.c      |  965 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/vhost/vhost.h      |  159 ++++++++
 include/linux/Kbuild       |    1 +
 include/linux/miscdevice.h |    1 +
 include/linux/vhost.h      |  130 ++++++
 11 files changed, 1928 insertions(+), 0 deletions(-)
 create mode 100644 drivers/vhost/Kconfig
 create mode 100644 drivers/vhost/Makefile
 create mode 100644 drivers/vhost/net.c
 create mode 100644 drivers/vhost/vhost.c
 create mode 100644 drivers/vhost/vhost.h
 create mode 100644 include/linux/vhost.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a1a2ace..7d4bfa2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5636,6 +5636,15 @@ S:       Maintained
 F:     Documentation/filesystems/vfat.txt
 F:     fs/fat/

+VIRTIO HOST (VHOST)
+M:     "Michael S. Tsirkin" <mst@redhat.com>
+L:     kvm@vger.kernel.org
+L:     virtualization@lists.osdl.org
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/vhost/
+F:     include/linux/vhost.h
+
 VIA RHINE NETWORK DRIVER
 M:     Roger Luethi <rl@hellgate.ch>
 S:     Maintained
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index b84e571..94f44d9 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -64,6 +64,7 @@ config KVM_AMD

 # OK, it's a little counter-intuitive to do this, but it puts it neatly under
 # the virtualization menu.
+source drivers/vhost/Kconfig
 source drivers/lguest/Kconfig
 source drivers/virtio/Kconfig

diff --git a/drivers/Makefile b/drivers/Makefile
index 6ee53c7..81e3659 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_HID)           += hid/
 obj-$(CONFIG_PPC_PS3)          += ps3/
 obj-$(CONFIG_OF)               += of/
 obj-$(CONFIG_SSB)              += ssb/
+obj-$(CONFIG_VHOST_NET)                += vhost/
 obj-$(CONFIG_VIRTIO)           += virtio/
 obj-$(CONFIG_VLYNQ)            += vlynq/
 obj-$(CONFIG_STAGING)          += staging/
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
new file mode 100644
index 0000000..9f409f4
--- /dev/null
+++ b/drivers/vhost/Kconfig
@@ -0,0 +1,11 @@
+config VHOST_NET
+       tristate "Host kernel accelerator for virtio net (EXPERIMENTAL)"
+       depends on NET && EVENTFD && EXPERIMENTAL
+       ---help---
+         This kernel module can be loaded in host kernel to accelerate
+         guest networking with virtio_net. Not to be confused with virtio_net
+         module itself which needs to be loaded in guest kernel.
+
+         To compile this driver as a module, choose M here: the module will
+         be called vhost_net.
+
diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile
new file mode 100644
index 0000000..72dd020
--- /dev/null
+++ b/drivers/vhost/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_VHOST_NET) += vhost_net.o
+vhost_net-y := vhost.o net.o
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
new file mode 100644
index 0000000..22d5fef
--- /dev/null
+++ b/drivers/vhost/net.c
@@ -0,0 +1,648 @@
+/* Copyright (C) 2009 Red Hat, Inc.
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * virtio-net server in host kernel.
+ */
+
+#include <linux/compat.h>
+#include <linux/eventfd.h>
+#include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <linux/mmu_context.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/rcupdate.h>
+#include <linux/file.h>
+
+#include <linux/net.h>
+#include <linux/if_packet.h>
+#include <linux/if_arp.h>
+#include <linux/if_tun.h>
+
+#include <net/sock.h>
+
+#include "vhost.h"
+
+/* Max number of bytes transferred before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others. */
+#define VHOST_NET_WEIGHT 0x80000
+
+enum {
+       VHOST_NET_VQ_RX = 0,
+       VHOST_NET_VQ_TX = 1,
+       VHOST_NET_VQ_MAX = 2,
+};
+
+enum vhost_net_poll_state {
+       VHOST_NET_POLL_DISABLED = 0,
+       VHOST_NET_POLL_STARTED = 1,
+       VHOST_NET_POLL_STOPPED = 2,
+};
+
+struct vhost_net {
+       struct vhost_dev dev;
+       struct vhost_virtqueue vqs[VHOST_NET_VQ_MAX];
+       struct vhost_poll poll[VHOST_NET_VQ_MAX];
+       /* Tells us whether we are polling a socket for TX.
+        * We only do this when socket buffer fills up.
+        * Protected by tx vq lock. */
+       enum vhost_net_poll_state tx_poll_state;
+};
+
+/* Pop first len bytes from iovec. Return number of segments used. */
+static int move_iovec_hdr(struct iovec *from, struct iovec *to,
+                         size_t len, int iov_count)
+{
+       int seg = 0;
+       size_t size;
+       while (len && seg < iov_count) {
+               size = min(from->iov_len, len);
+               to->iov_base = from->iov_base;
+               to->iov_len = size;
+               from->iov_len -= size;
+               from->iov_base += size;
+               len -= size;
+               ++from;
+               ++to;
+               ++seg;
+       }
+       return seg;
+}
+
+/* Caller must have TX VQ lock */
+static void tx_poll_stop(struct vhost_net *net)
+{
+       if (likely(net->tx_poll_state != VHOST_NET_POLL_STARTED))
+               return;
+       vhost_poll_stop(net->poll + VHOST_NET_VQ_TX);
+       net->tx_poll_state = VHOST_NET_POLL_STOPPED;
+}
+
+/* Caller must have TX VQ lock */
+static void tx_poll_start(struct vhost_net *net, struct socket *sock)
+{
+       if (unlikely(net->tx_poll_state != VHOST_NET_POLL_STOPPED))
+               return;
+       vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file);
+       net->tx_poll_state = VHOST_NET_POLL_STARTED;
+}
+
+/* Expects to be always run from workqueue - which acts as
+ * read-size critical section for our kind of RCU. */
+static void handle_tx(struct vhost_net *net)
+{
+       struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
+       unsigned head, out, in, s;
+       struct msghdr msg = {
+               .msg_name = NULL,
+               .msg_namelen = 0,
+               .msg_control = NULL,
+               .msg_controllen = 0,
+               .msg_iov = vq->iov,
+               .msg_flags = MSG_DONTWAIT,
+       };
+       size_t len, total_len = 0;
+       int err, wmem;
+       size_t hdr_size;
+       struct socket *sock = rcu_dereference(vq->private_data);
+       if (!sock)
+               return;
+
+       wmem = atomic_read(&sock->sk->sk_wmem_alloc);
+       if (wmem >= sock->sk->sk_sndbuf)
+               return;
+
+       use_mm(net->dev.mm);
+       mutex_lock(&vq->mutex);
+       vhost_disable_notify(vq);
+
+       if (wmem < sock->sk->sk_sndbuf * 2)
+               tx_poll_stop(net);
+       hdr_size = vq->hdr_size;
+
+       for (;;) {
+               head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
+                                        ARRAY_SIZE(vq->iov),
+                                        &out, &in,
+                                        NULL, NULL);
+               /* Nothing new?  Wait for eventfd to tell us they refilled. */
+               if (head == vq->num) {
+                       wmem = atomic_read(&sock->sk->sk_wmem_alloc);
+                       if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
+                               tx_poll_start(net, sock);
+                               set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+                               break;
+                       }
+                       if (unlikely(vhost_enable_notify(vq))) {
+                               vhost_disable_notify(vq);
+                               continue;
+                       }
+                       break;
+               }
+               if (in) {
+                       vq_err(vq, "Unexpected descriptor format for TX: "
+                              "out %d, int %d\n", out, in);
+                       break;
+               }
+               /* Skip header. TODO: support TSO. */
+               s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, out);
+               msg.msg_iovlen = out;
+               len = iov_length(vq->iov, out);
+               /* Sanity check */
+               if (!len) {
+                       vq_err(vq, "Unexpected header len for TX: "
+                              "%zd expected %zd\n",
+                              iov_length(vq->hdr, s), hdr_size);
+                       break;
+               }
+               /* TODO: Check specific error and bomb out unless ENOBUFS? */
+               err = sock->ops->sendmsg(NULL, sock, &msg, len);
+               if (unlikely(err < 0)) {
+                       vhost_discard_vq_desc(vq);
+                       tx_poll_start(net, sock);
+                       break;
+               }
+               if (err != len)
+                       pr_err("Truncated TX packet: "
+                              " len %d != %zd\n", err, len);
+               vhost_add_used_and_signal(&net->dev, vq, head, 0);
+               total_len += len;
+               if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
+                       vhost_poll_queue(&vq->poll);
+                       break;
+               }
+       }
+
+       mutex_unlock(&vq->mutex);
+       unuse_mm(net->dev.mm);
+}
+
+/* Expects to be always run from workqueue - which acts as
+ * read-size critical section for our kind of RCU. */
+static void handle_rx(struct vhost_net *net)
+{
+       struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
+       unsigned head, out, in, log, s;
+       struct vhost_log *vq_log;
+       struct msghdr msg = {
+               .msg_name = NULL,
+               .msg_namelen = 0,
+               .msg_control = NULL, /* FIXME: get and handle RX aux data. */
+               .msg_controllen = 0,
+               .msg_iov = vq->iov,
+               .msg_flags = MSG_DONTWAIT,
+       };
+
+       struct virtio_net_hdr hdr = {
+               .flags = 0,
+               .gso_type = VIRTIO_NET_HDR_GSO_NONE
+       };
+
+       size_t len, total_len = 0;
+       int err;
+       size_t hdr_size;
+       struct socket *sock = rcu_dereference(vq->private_data);
+       if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
+               return;
+
+       use_mm(net->dev.mm);
+       mutex_lock(&vq->mutex);
+       vhost_disable_notify(vq);
+       hdr_size = vq->hdr_size;
+
+       vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
+               vq->log : NULL;
+
+       for (;;) {
+               head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
+                                        ARRAY_SIZE(vq->iov),
+                                        &out, &in,
+                                        vq_log, &log);
+               /* OK, now we need to know about added descriptors. */
+               if (head == vq->num) {
+                       if (unlikely(vhost_enable_notify(vq))) {
+                               /* They have slipped one in as we were
+                                * doing that: check again. */
+                               vhost_disable_notify(vq);
+                               continue;
+                       }
+                       /* Nothing new?  Wait for eventfd to tell us
+                        * they refilled. */
+                       break;
+               }
+               /* We don't need to be notified again. */
+               if (out) {
+                       vq_err(vq, "Unexpected descriptor format for RX: "
+                              "out %d, int %d\n",
+                              out, in);
+                       break;
+               }
+               /* Skip header. TODO: support TSO/mergeable rx buffers. */
+               s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
+               msg.msg_iovlen = in;
+               len = iov_length(vq->iov, in);
+               /* Sanity check */
+               if (!len) {
+                       vq_err(vq, "Unexpected header len for RX: "
+                              "%zd expected %zd\n",
+                              iov_length(vq->hdr, s), hdr_size);
+                       break;
+               }
+               err = sock->ops->recvmsg(NULL, sock, &msg,
+                                        len, MSG_DONTWAIT | MSG_TRUNC);
+               /* TODO: Check specific error and bomb out unless EAGAIN? */
+               if (err < 0) {
+                       vhost_discard_vq_desc(vq);
+                       break;
+               }
+               /* TODO: Should check and handle checksum. */
+               if (err > len) {
+                       pr_err("Discarded truncated rx packet: "
+                              " len %d > %zd\n", err, len);
+                       vhost_discard_vq_desc(vq);
+                       continue;
+               }
+               len = err;
+               err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr, hdr_size);
+               if (err) {
+                       vq_err(vq, "Unable to write vnet_hdr at addr %p: %d\n",
+                              vq->iov->iov_base, err);
+                       break;
+               }
+               len += hdr_size;
+               vhost_add_used_and_signal(&net->dev, vq, head, len);
+               if (unlikely(vq_log))
+                       vhost_log_write(vq, vq_log, log, len);
+               total_len += len;
+               if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
+                       vhost_poll_queue(&vq->poll);
+                       break;
+               }
+       }
+
+       mutex_unlock(&vq->mutex);
+       unuse_mm(net->dev.mm);
+}
+
+static void handle_tx_kick(struct work_struct *work)
+{
+       struct vhost_virtqueue *vq;
+       struct vhost_net *net;
+       vq = container_of(work, struct vhost_virtqueue, poll.work);
+       net = container_of(vq->dev, struct vhost_net, dev);
+       handle_tx(net);
+}
+
+static void handle_rx_kick(struct work_struct *work)
+{
+       struct vhost_virtqueue *vq;
+       struct vhost_net *net;
+       vq = container_of(work, struct vhost_virtqueue, poll.work);
+       net = container_of(vq->dev, struct vhost_net, dev);
+       handle_rx(net);
+}
+
+static void handle_tx_net(struct work_struct *work)
+{
+       struct vhost_net *net;
+       net = container_of(work, struct vhost_net, poll[VHOST_NET_VQ_TX].work);
+       handle_tx(net);
+}
+
+static void handle_rx_net(struct work_struct *work)
+{
+       struct vhost_net *net;
+       net = container_of(work, struct vhost_net, poll[VHOST_NET_VQ_RX].work);
+       handle_rx(net);
+}
+
+static int vhost_net_open(struct inode *inode, struct file *f)
+{
+       struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL);
+       int r;
+       if (!n)
+               return -ENOMEM;
+       f->private_data = n;
+       n->vqs[VHOST_NET_VQ_TX].handle_kick = handle_tx_kick;
+       n->vqs[VHOST_NET_VQ_RX].handle_kick = handle_rx_kick;
+       r = vhost_dev_init(&n->dev, n->vqs, VHOST_NET_VQ_MAX);
+       if (r < 0) {
+               kfree(n);
+               return r;
+       }
+
+       vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, POLLOUT);
+       vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, POLLIN);
+       n->tx_poll_state = VHOST_NET_POLL_DISABLED;
+       return 0;
+}
+
+static void vhost_net_disable_vq(struct vhost_net *n,
+                                struct vhost_virtqueue *vq)
+{
+       if (!vq->private_data)
+               return;
+       if (vq == n->vqs + VHOST_NET_VQ_TX) {
+               tx_poll_stop(n);
+               n->tx_poll_state = VHOST_NET_POLL_DISABLED;
+       } else
+               vhost_poll_stop(n->poll + VHOST_NET_VQ_RX);
+}
+
+static void vhost_net_enable_vq(struct vhost_net *n,
+                               struct vhost_virtqueue *vq)
+{
+       struct socket *sock = vq->private_data;
+       if (!sock)
+               return;
+       if (vq == n->vqs + VHOST_NET_VQ_TX) {
+               n->tx_poll_state = VHOST_NET_POLL_STOPPED;
+               tx_poll_start(n, sock);
+       } else
+               vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file);
+}
+
+static struct socket *vhost_net_stop_vq(struct vhost_net *n,
+                                       struct vhost_virtqueue *vq)
+{
+       struct socket *sock;
+
+       mutex_lock(&vq->mutex);
+       sock = vq->private_data;
+       vhost_net_disable_vq(n, vq);
+       rcu_assign_pointer(vq->private_data, NULL);
+       mutex_unlock(&vq->mutex);
+       return sock;
+}
+
+static void vhost_net_stop(struct vhost_net *n, struct socket **tx_sock,
+                          struct socket **rx_sock)
+{
+       *tx_sock = vhost_net_stop_vq(n, n->vqs + VHOST_NET_VQ_TX);
+       *rx_sock = vhost_net_stop_vq(n, n->vqs + VHOST_NET_VQ_RX);
+}
+
+static void vhost_net_flush_vq(struct vhost_net *n, int index)
+{
+       vhost_poll_flush(n->poll + index);
+       vhost_poll_flush(&n->dev.vqs[index].poll);
+}
+
+static void vhost_net_flush(struct vhost_net *n)
+{
+       vhost_net_flush_vq(n, VHOST_NET_VQ_TX);
+       vhost_net_flush_vq(n, VHOST_NET_VQ_RX);
+}
+
+static int vhost_net_release(struct inode *inode, struct file *f)
+{
+       struct vhost_net *n = f->private_data;
+       struct socket *tx_sock;
+       struct socket *rx_sock;
+
+       vhost_net_stop(n, &tx_sock, &rx_sock);
+       vhost_net_flush(n);
+       vhost_dev_cleanup(&n->dev);
+       if (tx_sock)
+               fput(tx_sock->file);
+       if (rx_sock)
+               fput(rx_sock->file);
+       /* We do an extra flush before freeing memory,
+        * since jobs can re-queue themselves. */
+       vhost_net_flush(n);
+       kfree(n);
+       return 0;
+}
+
+static struct socket *get_raw_socket(int fd)
+{
+       struct {
+               struct sockaddr_ll sa;
+               char  buf[MAX_ADDR_LEN];
+       } uaddr;
+       int uaddr_len = sizeof uaddr, r;
+       struct socket *sock = sockfd_lookup(fd, &r);
+       if (!sock)
+               return ERR_PTR(-ENOTSOCK);
+
+       /* Parameter checking */
+       if (sock->sk->sk_type != SOCK_RAW) {
+               r = -ESOCKTNOSUPPORT;
+               goto err;
+       }
+
+       r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa,
+                              &uaddr_len, 0);
+       if (r)
+               goto err;
+
+       if (uaddr.sa.sll_family != AF_PACKET) {
+               r = -EPFNOSUPPORT;
+               goto err;
+       }
+       return sock;
+err:
+       fput(sock->file);
+       return ERR_PTR(r);
+}
+
+static struct socket *get_tun_socket(int fd)
+{
+       struct file *file = fget(fd);
+       struct socket *sock;
+       if (!file)
+               return ERR_PTR(-EBADF);
+       sock = tun_get_socket(file);
+       if (IS_ERR(sock))
+               fput(file);
+       return sock;
+}
+
+static struct socket *get_socket(int fd)
+{
+       struct socket *sock;
+       if (fd == -1)
+               return NULL;
+       sock = get_raw_socket(fd);
+       if (!IS_ERR(sock))
+               return sock;
+       sock = get_tun_socket(fd);
+       if (!IS_ERR(sock))
+               return sock;
+       return ERR_PTR(-ENOTSOCK);
+}
+
+static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
+{
+       struct socket *sock, *oldsock;
+       struct vhost_virtqueue *vq;
+       int r;
+
+       mutex_lock(&n->dev.mutex);
+       r = vhost_dev_check_owner(&n->dev);
+       if (r)
+               goto err;
+
+       if (index >= VHOST_NET_VQ_MAX) {
+               r = -ENOBUFS;
+               goto err;
+       }
+       vq = n->vqs + index;
+       mutex_lock(&vq->mutex);
+       sock = get_socket(fd);
+       if (IS_ERR(sock)) {
+               r = PTR_ERR(sock);
+               goto err;
+       }
+
+       /* start polling new socket */
+       oldsock = vq->private_data;
+       if (sock == oldsock)
+               goto done;
+
+       vhost_net_disable_vq(n, vq);
+       rcu_assign_pointer(vq->private_data, sock);
+       vhost_net_enable_vq(n, vq);
+       mutex_unlock(&vq->mutex);
+done:
+       mutex_unlock(&n->dev.mutex);
+       if (oldsock) {
+               vhost_net_flush_vq(n, index);
+               fput(oldsock->file);
+       }
+       return r;
+err:
+       mutex_unlock(&n->dev.mutex);
+       return r;
+}
+
+static long vhost_net_reset_owner(struct vhost_net *n)
+{
+       struct socket *tx_sock = NULL;
+       struct socket *rx_sock = NULL;
+       long err;
+       mutex_lock(&n->dev.mutex);
+       err = vhost_dev_check_owner(&n->dev);
+       if (err)
+               goto done;
+       vhost_net_stop(n, &tx_sock, &rx_sock);
+       vhost_net_flush(n);
+       err = vhost_dev_reset_owner(&n->dev);
+done:
+       mutex_unlock(&n->dev.mutex);
+       if (tx_sock)
+               fput(tx_sock->file);
+       if (rx_sock)
+               fput(rx_sock->file);
+       return err;
+}
+
+static void vhost_net_set_features(struct vhost_net *n, u64 features)
+{
+       size_t hdr_size = features & (1 << VHOST_NET_F_VIRTIO_NET_HDR) ?
+               sizeof(struct virtio_net_hdr) : 0;
+       int i;
+       mutex_lock(&n->dev.mutex);
+       n->dev.acked_features = features;
+       smp_wmb();
+       for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
+               mutex_lock(&n->vqs[i].mutex);
+               n->vqs[i].hdr_size = hdr_size;
+               mutex_unlock(&n->vqs[i].mutex);
+       }
+       mutex_unlock(&n->dev.mutex);
+       vhost_net_flush(n);
+}
+
+static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
+                           unsigned long arg)
+{
+       struct vhost_net *n = f->private_data;
+       void __user *argp = (void __user *)arg;
+       u32 __user *featurep = argp;
+       struct vhost_vring_file backend;
+       u64 features;
+       int r;
+       switch (ioctl) {
+       case VHOST_NET_SET_BACKEND:
+               r = copy_from_user(&backend, argp, sizeof backend);
+               if (r < 0)
+                       return r;
+               return vhost_net_set_backend(n, backend.index, backend.fd);
+       case VHOST_GET_FEATURES:
+               features = VHOST_FEATURES;
+               return put_user(features, featurep);
+       case VHOST_SET_FEATURES:
+               r = get_user(features, featurep);
+               /* No features for now */
+               if (r < 0)
+                       return r;
+               if (features & ~VHOST_FEATURES)
+                       return -EOPNOTSUPP;
+               vhost_net_set_features(n, features);
+               return 0;
+       case VHOST_RESET_OWNER:
+               return vhost_net_reset_owner(n);
+       default:
+               r = vhost_dev_ioctl(&n->dev, ioctl, arg);
+               vhost_net_flush(n);
+               return r;
+       }
+}
+
+#ifdef CONFIG_COMPAT
+static long vhost_net_compat_ioctl(struct file *f, unsigned int ioctl,
+                                  unsigned long arg)
+{
+       return vhost_net_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+const static struct file_operations vhost_net_fops = {
+       .owner          = THIS_MODULE,
+       .release        = vhost_net_release,
+       .unlocked_ioctl = vhost_net_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = vhost_net_compat_ioctl,
+#endif
+       .open           = vhost_net_open,
+};
+
+static struct miscdevice vhost_net_misc = {
+       VHOST_NET_MINOR,
+       "vhost-net",
+       &vhost_net_fops,
+};
+
+int vhost_net_init(void)
+{
+       int r = vhost_init();
+       if (r)
+               goto err_init;
+       r = misc_register(&vhost_net_misc);
+       if (r)
+               goto err_reg;
+       return 0;
+err_reg:
+       vhost_cleanup();
+err_init:
+       return r;
+
+}
+module_init(vhost_net_init);
+
+void vhost_net_exit(void)
+{
+       misc_deregister(&vhost_net_misc);
+       vhost_cleanup();
+}
+module_exit(vhost_net_exit);
+
+MODULE_VERSION("0.0.1");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Michael S. Tsirkin");
+MODULE_DESCRIPTION("Host kernel accelerator for virtio net");
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
new file mode 100644
index 0000000..97233d5
--- /dev/null
+++ b/drivers/vhost/vhost.c
@@ -0,0 +1,965 @@
+/* Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2006 Rusty Russell IBM Corporation
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * Inspiration, some code, and most witty comments come from
+ * Documentation/lguest/lguest.c, by Rusty Russell
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * Generic code for virtio server in host kernel.
+ */
+
+#include <linux/eventfd.h>
+#include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/rcupdate.h>
+#include <linux/poll.h>
+#include <linux/file.h>
+#include <linux/highmem.h>
+
+#include <linux/net.h>
+#include <linux/if_packet.h>
+#include <linux/if_arp.h>
+
+#include <net/sock.h>
+
+#include "vhost.h"
+
+enum {
+       VHOST_MEMORY_MAX_NREGIONS = 64,
+       VHOST_MEMORY_F_LOG = 0x1,
+};
+
+static struct workqueue_struct *vhost_workqueue;
+
+static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
+                           poll_table *pt)
+{
+       struct vhost_poll *poll;
+       poll = container_of(pt, struct vhost_poll, table);
+
+       poll->wqh = wqh;
+       add_wait_queue(wqh, &poll->wait);
+}
+
+static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync,
+                            void *key)
+{
+       struct vhost_poll *poll;
+       poll = container_of(wait, struct vhost_poll, wait);
+       if (!((unsigned long)key & poll->mask))
+               return 0;
+
+       queue_work(vhost_workqueue, &poll->work);
+       return 0;
+}
+
+/* Init poll structure */
+void vhost_poll_init(struct vhost_poll *poll, work_func_t func,
+                    unsigned long mask)
+{
+       INIT_WORK(&poll->work, func);
+       init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
+       init_poll_funcptr(&poll->table, vhost_poll_func);
+       poll->mask = mask;
+}
+
+/* Start polling a file. We add ourselves to file's wait queue. The caller must
+ * keep a reference to a file until after vhost_poll_stop is called. */
+void vhost_poll_start(struct vhost_poll *poll, struct file *file)
+{
+       unsigned long mask;
+       mask = file->f_op->poll(file, &poll->table);
+       if (mask)
+               vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask);
+}
+
+/* Stop polling a file. After this function returns, it becomes safe to drop the
+ * file reference. You must also flush afterwards. */
+void vhost_poll_stop(struct vhost_poll *poll)
+{
+       remove_wait_queue(poll->wqh, &poll->wait);
+}
+
+/* Flush any work that has been scheduled. When calling this, don't hold any
+ * locks that are also used by the callback. */
+void vhost_poll_flush(struct vhost_poll *poll)
+{
+       flush_work(&poll->work);
+}
+
+void vhost_poll_queue(struct vhost_poll *poll)
+{
+       queue_work(vhost_workqueue, &poll->work);
+}
+
+static void vhost_vq_reset(struct vhost_dev *dev,
+                          struct vhost_virtqueue *vq)
+{
+       vq->num = 1;
+       vq->desc = NULL;
+       vq->avail = NULL;
+       vq->used = NULL;
+       vq->last_avail_idx = 0;
+       vq->avail_idx = 0;
+       vq->last_used_idx = 0;
+       vq->used_flags = 0;
+       vq->used_flags = 0;
+       vq->log_used = false;
+       vq->log_addr = -1ull;
+       vq->hdr_size = 0;
+       vq->private_data = NULL;
+       vq->log_base = NULL;
+       vq->error_ctx = NULL;
+       vq->error = NULL;
+       vq->kick = NULL;
+       vq->call_ctx = NULL;
+       vq->call = NULL;
+}
+
+long vhost_dev_init(struct vhost_dev *dev,
+                   struct vhost_virtqueue *vqs, int nvqs)
+{
+       int i;
+       dev->vqs = vqs;
+       dev->nvqs = nvqs;
+       mutex_init(&dev->mutex);
+       dev->log_ctx = NULL;
+       dev->log_file = NULL;
+       dev->memory = NULL;
+       dev->mm = NULL;
+
+       for (i = 0; i < dev->nvqs; ++i) {
+               dev->vqs[i].dev = dev;
+               mutex_init(&dev->vqs[i].mutex);
+               vhost_vq_reset(dev, dev->vqs + i);
+               if (dev->vqs[i].handle_kick)
+                       vhost_poll_init(&dev->vqs[i].poll,
+                                       dev->vqs[i].handle_kick,
+                                       POLLIN);
+       }
+       return 0;
+}
+
+/* Caller should have device mutex */
+long vhost_dev_check_owner(struct vhost_dev *dev)
+{
+       /* Are you the owner? If not, I don't think you mean to do that */
+       return dev->mm == current->mm ? 0 : -EPERM;
+}
+
+/* Caller should have device mutex */
+static long vhost_dev_set_owner(struct vhost_dev *dev)
+{
+       /* Is there an owner already? */
+       if (dev->mm)
+               return -EBUSY;
+       /* No owner, become one */
+       dev->mm = get_task_mm(current);
+       return 0;
+}
+
+/* Caller should have device mutex */
+long vhost_dev_reset_owner(struct vhost_dev *dev)
+{
+       struct vhost_memory *memory;
+
+       /* Restore memory to default 1:1 mapping. */
+       memory = kmalloc(offsetof(struct vhost_memory, regions) +
+                        2 * sizeof *memory->regions, GFP_KERNEL);
+       if (!memory)
+               return -ENOMEM;
+
+       vhost_dev_cleanup(dev);
+
+       memory->nregions = 2;
+       memory->regions[0].guest_phys_addr = 1;
+       memory->regions[0].userspace_addr = 1;
+       memory->regions[0].memory_size = ~0ULL;
+       memory->regions[1].guest_phys_addr = 0;
+       memory->regions[1].userspace_addr = 0;
+       memory->regions[1].memory_size = 1;
+       dev->memory = memory;
+       return 0;
+}
+
+/* Caller should have device mutex */
+void vhost_dev_cleanup(struct vhost_dev *dev)
+{
+       int i;
+       for (i = 0; i < dev->nvqs; ++i) {
+               if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
+                       vhost_poll_stop(&dev->vqs[i].poll);
+                       vhost_poll_flush(&dev->vqs[i].poll);
+               }
+               if (dev->vqs[i].error_ctx)
+                       eventfd_ctx_put(dev->vqs[i].error_ctx);
+               if (dev->vqs[i].error)
+                       fput(dev->vqs[i].error);
+               if (dev->vqs[i].kick)
+                       fput(dev->vqs[i].kick);
+               if (dev->vqs[i].call_ctx)
+                       eventfd_ctx_put(dev->vqs[i].call_ctx);
+               if (dev->vqs[i].call)
+                       fput(dev->vqs[i].call);
+               vhost_vq_reset(dev, dev->vqs + i);
+       }
+       if (dev->log_ctx)
+               eventfd_ctx_put(dev->log_ctx);
+       dev->log_ctx = NULL;
+       if (dev->log_file)
+               fput(dev->log_file);
+       dev->log_file = NULL;
+       /* No one will access memory at this point */
+       kfree(dev->memory);
+       dev->memory = NULL;
+       if (dev->mm)
+               mmput(dev->mm);
+       dev->mm = NULL;
+}
+
+static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
+{
+       struct vhost_memory mem, *newmem, *oldmem;
+       unsigned long size = offsetof(struct vhost_memory, regions);
+       long r;
+       r = copy_from_user(&mem, m, size);
+       if (r)
+               return r;
+       if (mem.padding)
+               return -EOPNOTSUPP;
+       if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS)
+               return -E2BIG;
+       newmem = kmalloc(size + mem.nregions * sizeof *m->regions, GFP_KERNEL);
+       if (!newmem)
+               return -ENOMEM;
+
+       memcpy(newmem, &mem, size);
+       r = copy_from_user(newmem->regions, m->regions,
+                          mem.nregions * sizeof *m->regions);
+       if (r) {
+               kfree(newmem);
+               return r;
+       }
+       oldmem = d->memory;
+       rcu_assign_pointer(d->memory, newmem);
+       synchronize_rcu();
+       kfree(oldmem);
+       return 0;
+}
+
+static int init_used(struct vhost_virtqueue *vq,
+                    struct vring_used __user *used)
+{
+       int r = put_user(vq->used_flags, &used->flags);
+       if (r)
+               return r;
+       return get_user(vq->last_used_idx, &used->idx);
+}
+
+static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
+{
+       struct file *eventfp, *filep = NULL,
+                   *pollstart = NULL, *pollstop = NULL;
+       struct eventfd_ctx *ctx = NULL;
+       u32 __user *idxp = argp;
+       struct vhost_virtqueue *vq;
+       struct vhost_vring_state s;
+       struct vhost_vring_file f;
+       struct vhost_vring_addr a;
+       u32 idx;
+       long r;
+
+       r = get_user(idx, idxp);
+       if (r < 0)
+               return r;
+       if (idx > d->nvqs)
+               return -ENOBUFS;
+
+       vq = d->vqs + idx;
+
+       mutex_lock(&vq->mutex);
+
+       switch (ioctl) {
+       case VHOST_SET_VRING_NUM:
+               r = copy_from_user(&s, argp, sizeof s);
+               if (r < 0)
+                       break;
+               if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) {
+                       r = -EINVAL;
+                       break;
+               }
+               vq->num = s.num;
+               break;
+       case VHOST_SET_VRING_BASE:
+               r = copy_from_user(&s, argp, sizeof s);
+               if (r < 0)
+                       break;
+               if (s.num > 0xffff) {
+                       r = -EINVAL;
+                       break;
+               }
+               vq->last_avail_idx = s.num;
+               /* Forget the cached index value. */
+               vq->avail_idx = vq->last_avail_idx;
+               break;
+       case VHOST_GET_VRING_BASE:
+               s.index = idx;
+               s.num = vq->last_avail_idx;
+               r = copy_to_user(argp, &s, sizeof s);
+               break;
+       case VHOST_SET_VRING_ADDR:
+               r = copy_from_user(&a, argp, sizeof a);
+               if (r < 0)
+                       break;
+               if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) {
+                       r = -EOPNOTSUPP;
+                       break;
+               }
+               if ((u64)(unsigned long)a.desc_user_addr != a.desc_user_addr ||
+                   (u64)(unsigned long)a.used_user_addr != a.used_user_addr ||
+                   (u64)(unsigned long)a.avail_user_addr != a.avail_user_addr) {
+                       r = -EFAULT;
+                       break;
+               }
+               if ((a.avail_user_addr & (sizeof *vq->avail->ring - 1)) ||
+                   (a.used_user_addr & (sizeof *vq->used->ring - 1)) ||
+                   (a.log_guest_addr & (sizeof *vq->used->ring - 1))) {
+                       r = -EINVAL;
+                       break;
+               }
+               r = init_used(vq, (struct vring_used __user *)a.used_user_addr);
+               if (r)
+                       break;
+               vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG));
+               vq->desc = (void __user *)(unsigned long)a.desc_user_addr;
+               vq->avail = (void __user *)(unsigned long)a.avail_user_addr;
+               vq->log_addr = a.log_guest_addr;
+               vq->used = (void __user *)(unsigned long)a.used_user_addr;
+               break;
+       case VHOST_SET_VRING_KICK:
+               r = copy_from_user(&f, argp, sizeof f);
+               if (r < 0)
+                       break;
+               eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
+               if (IS_ERR(eventfp))
+                       return PTR_ERR(eventfp);
+               if (eventfp != vq->kick) {
+                       pollstop = filep = vq->kick;
+                       pollstart = vq->kick = eventfp;
+               } else
+                       filep = eventfp;
+               break;
+       case VHOST_SET_VRING_CALL:
+               r = copy_from_user(&f, argp, sizeof f);
+               if (r < 0)
+                       break;
+               eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
+               if (IS_ERR(eventfp))
+                       return PTR_ERR(eventfp);
+               if (eventfp != vq->call) {
+                       filep = vq->call;
+                       ctx = vq->call_ctx;
+                       vq->call = eventfp;
+                       vq->call_ctx = eventfp ?
+                               eventfd_ctx_fileget(eventfp) : NULL;
+               } else
+                       filep = eventfp;
+               break;
+       case VHOST_SET_VRING_ERR:
+               r = copy_from_user(&f, argp, sizeof f);
+               if (r < 0)
+                       break;
+               eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
+               if (IS_ERR(eventfp))
+                       return PTR_ERR(eventfp);
+               if (eventfp != vq->error) {
+                       filep = vq->error;
+                       vq->error = eventfp;
+                       ctx = vq->error_ctx;
+                       vq->error_ctx = eventfp ?
+                               eventfd_ctx_fileget(eventfp) : NULL;
+               } else
+                       filep = eventfp;
+               break;
+       default:
+               r = -ENOIOCTLCMD;
+       }
+
+       if (pollstop && vq->handle_kick)
+               vhost_poll_stop(&vq->poll);
+
+       if (ctx)
+               eventfd_ctx_put(ctx);
+       if (filep)
+               fput(filep);
+
+       if (pollstart && vq->handle_kick)
+               vhost_poll_start(&vq->poll, vq->kick);
+
+       mutex_unlock(&vq->mutex);
+
+       if (pollstop && vq->handle_kick)
+               vhost_poll_flush(&vq->poll);
+       return r;
+}
+
+long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       struct file *eventfp, *filep = NULL;
+       struct eventfd_ctx *ctx = NULL;
+       u64 p;
+       long r;
+       int i, fd;
+
+       mutex_lock(&d->mutex);
+       /* If you are not the owner, you can become one */
+       if (ioctl == VHOST_SET_OWNER) {
+               r = vhost_dev_set_owner(d);
+               goto done;
+       }
+
+       /* You must be the owner to do anything else */
+       r = vhost_dev_check_owner(d);
+       if (r)
+               goto done;
+
+       switch (ioctl) {
+       case VHOST_SET_MEM_TABLE:
+               r = vhost_set_memory(d, argp);
+               break;
+       case VHOST_SET_LOG_BASE:
+               r = copy_from_user(&p, argp, sizeof p);
+               if (r < 0)
+                       break;
+               if ((u64)(unsigned long)p != p) {
+                       r = -EFAULT;
+                       break;
+               }
+               for (i = 0; i < d->nvqs; ++i) {
+                       mutex_lock(&d->vqs[i].mutex);
+                       d->vqs[i].log_base = (void __user *)(unsigned long)p;
+                       mutex_unlock(&d->vqs[i].mutex);
+               }
+               break;
+       case VHOST_SET_LOG_FD:
+               r = get_user(fd, (int __user *)argp);
+               if (r < 0)
+                       break;
+               eventfp = fd == -1 ? NULL : eventfd_fget(fd);
+               if (IS_ERR(eventfp)) {
+                       r = PTR_ERR(eventfp);
+                       break;
+               }
+               if (eventfp != d->log_file) {
+                       filep = d->log_file;
+                       ctx = d->log_ctx;
+                       d->log_ctx = eventfp ?
+                               eventfd_ctx_fileget(eventfp) : NULL;
+               } else
+                       filep = eventfp;
+               for (i = 0; i < d->nvqs; ++i) {
+                       mutex_lock(&d->vqs[i].mutex);
+                       d->vqs[i].log_ctx = d->log_ctx;
+                       mutex_unlock(&d->vqs[i].mutex);
+               }
+               if (ctx)
+                       eventfd_ctx_put(ctx);
+               if (filep)
+                       fput(filep);
+               break;
+       default:
+               r = vhost_set_vring(d, ioctl, argp);
+               break;
+       }
+done:
+       mutex_unlock(&d->mutex);
+       return r;
+}
+
+static const struct vhost_memory_region *find_region(struct vhost_memory *mem,
+                                                    __u64 addr, __u32 len)
+{
+       struct vhost_memory_region *reg;
+       int i;
+       /* linear search is not brilliant, but we really have on the order of 6
+        * regions in practice */
+       for (i = 0; i < mem->nregions; ++i) {
+               reg = mem->regions + i;
+               if (reg->guest_phys_addr <= addr &&
+                   reg->guest_phys_addr + reg->memory_size - 1 >= addr)
+                       return reg;
+       }
+       return NULL;
+}
+
+/* TODO: This is really inefficient.  We need something like get_user()
+ * (instruction directly accesses the data, with an exception table entry
+ * returning -EFAULT). See Documentation/x86/exception-tables.txt.
+ */
+static int set_bit_to_user(int nr, void __user *addr)
+{
+       unsigned long log = (unsigned long)addr;
+       struct page *page;
+       void *base;
+       int bit = nr + (log % PAGE_SIZE) * 8;
+       int r;
+       r = get_user_pages_fast(log, 1, 1, &page);
+       if (r)
+               return r;
+       base = kmap_atomic(page, KM_USER0);
+       set_bit(bit, base);
+       kunmap_atomic(base, KM_USER0);
+       set_page_dirty_lock(page);
+       put_page(page);
+       return 0;
+}
+
+static int log_write(void __user *log_base,
+                    u64 write_address, u64 write_length)
+{
+       int r;
+       if (!write_length)
+               return 0;
+       write_address /= VHOST_PAGE_SIZE;
+       for (;;) {
+               u64 base = (u64)(unsigned long)log_base;
+               u64 log = base + write_address / 8;
+               int bit = write_address % 8;
+               if ((u64)(unsigned long)log != log)
+                       return -EFAULT;
+               r = set_bit_to_user(bit, (void __user *)(unsigned long)log);
+               if (r < 0)
+                       return r;
+               if (write_length <= VHOST_PAGE_SIZE)
+                       break;
+               write_length -= VHOST_PAGE_SIZE;
+               write_address += VHOST_PAGE_SIZE;
+       }
+       return r;
+}
+
+int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
+                   unsigned int log_num, u64 len)
+{
+       int i, r;
+
+       /* Make sure data written is seen before log. */
+       wmb();
+       for (i = 0; i < log_num; ++i) {
+               u64 l = min(log[i].len, len);
+               r = log_write(vq->log_base, log[i].addr, l);
+               if (r < 0)
+                       return r;
+               len -= l;
+               if (!len)
+                       return 0;
+       }
+       if (vq->log_ctx)
+               eventfd_signal(vq->log_ctx, 1);
+       /* Length written exceeds what we have stored. This is a bug. */
+       BUG();
+       return 0;
+}
+
+int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
+                  struct iovec iov[], int iov_size)
+{
+       const struct vhost_memory_region *reg;
+       struct vhost_memory *mem;
+       struct iovec *_iov;
+       u64 s = 0;
+       int ret = 0;
+
+       rcu_read_lock();
+
+       mem = rcu_dereference(dev->memory);
+       while ((u64)len > s) {
+               u64 size;
+               if (ret >= iov_size) {
+                       ret = -ENOBUFS;
+                       break;
+               }
+               reg = find_region(mem, addr, len);
+               if (!reg) {
+                       ret = -EFAULT;
+                       break;
+               }
+               _iov = iov + ret;
+               size = reg->memory_size - addr + reg->guest_phys_addr;
+               _iov->iov_len = min((u64)len, size);
+               _iov->iov_base = (void *)(unsigned long)
+                       (reg->userspace_addr + addr - reg->guest_phys_addr);
+               s += size;
+               addr += size;
+               ++ret;
+       }
+
+       rcu_read_unlock();
+       return ret;
+}
+
+/* Each buffer in the virtqueues is actually a chain of descriptors.  This
+ * function returns the next descriptor in the chain,
+ * or -1U if we're at the end. */
+static unsigned next_desc(struct vring_desc *desc)
+{
+       unsigned int next;
+
+       /* If this descriptor says it doesn't chain, we're done. */
+       if (!(desc->flags & VRING_DESC_F_NEXT))
+               return -1U;
+
+       /* Check they're not leading us off end of descriptors. */
+       next = desc->next;
+       /* Make sure compiler knows to grab that: we don't want it changing! */
+       /* We will use the result as an index in an array, so most
+        * architectures only need a compiler barrier here. */
+       read_barrier_depends();
+
+       return next;
+}
+
+static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
+                            struct iovec iov[], unsigned int iov_size,
+                            unsigned int *out_num, unsigned int *in_num,
+                            struct vhost_log *log, unsigned int *log_num,
+                            struct vring_desc *indirect)
+{
+       struct vring_desc desc;
+       unsigned int i = 0, count, found = 0;
+       int ret;
+
+       /* Sanity check */
+       if (indirect->len % sizeof desc) {
+               vq_err(vq, "Invalid length in indirect descriptor: "
+                      "len 0x%llx not multiple of 0x%zx\n",
+                      (unsigned long long)indirect->len,
+                      sizeof desc);
+               return -EINVAL;
+       }
+
+       ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,
+                            ARRAY_SIZE(vq->indirect));
+       if (ret < 0) {
+               vq_err(vq, "Translation failure %d in indirect.\n", ret);
+               return ret;
+       }
+
+       /* We will use the result as an address to read from, so most
+        * architectures only need a compiler barrier here. */
+       read_barrier_depends();
+
+       count = indirect->len / sizeof desc;
+       /* Buffers are chained via a 16 bit next field, so
+        * we can have at most 2^16 of these. */
+       if (count > USHORT_MAX + 1) {
+               vq_err(vq, "Indirect buffer length too big: %d\n",
+                      indirect->len);
+               return -E2BIG;
+       }
+
+       do {
+               unsigned iov_count = *in_num + *out_num;
+               if (++found > count) {
+                       vq_err(vq, "Loop detected: last one at %u "
+                              "indirect size %u\n",
+                              i, count);
+                       return -EINVAL;
+               }
+               if (memcpy_fromiovec((unsigned char *)&desc, vq->indirect,
+                                    sizeof desc)) {
+                       vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n",
+                              i, (size_t)indirect->addr + i * sizeof desc);
+                       return -EINVAL;
+               }
+               if (desc.flags & VRING_DESC_F_INDIRECT) {
+                       vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n",
+                              i, (size_t)indirect->addr + i * sizeof desc);
+                       return -EINVAL;
+               }
+
+               ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
+                                    iov_size - iov_count);
+               if (ret < 0) {
+                       vq_err(vq, "Translation failure %d indirect idx %d\n",
+                              ret, i);
+                       return ret;
+               }
+               /* If this is an input descriptor, increment that count. */
+               if (desc.flags & VRING_DESC_F_WRITE) {
+                       *in_num += ret;
+                       if (unlikely(log)) {
+                               log[*log_num].addr = desc.addr;
+                               log[*log_num].len = desc.len;
+                               ++*log_num;
+                       }
+               } else {
+                       /* If it's an output descriptor, they're all supposed
+                        * to come before any input descriptors. */
+                       if (*in_num) {
+                               vq_err(vq, "Indirect descriptor "
+                                      "has out after in: idx %d\n", i);
+                               return -EINVAL;
+                       }
+                       *out_num += ret;
+               }
+       } while ((i = next_desc(&desc)) != -1);
+       return 0;
+}
+
+/* This looks in the virtqueue and for the first available buffer, and converts
+ * it to an iovec for convenient access.  Since descriptors consist of some
+ * number of output then some number of input descriptors, it's actually two
+ * iovecs, but we pack them into one and note how many of each there were.
+ *
+ * This function returns the descriptor number found, or vq->num (which
+ * is never a valid descriptor number) if none was found. */
+unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
+                          struct iovec iov[], unsigned int iov_size,
+                          unsigned int *out_num, unsigned int *in_num,
+                          struct vhost_log *log, unsigned int *log_num)
+{
+       struct vring_desc desc;
+       unsigned int i, head, found = 0;
+       u16 last_avail_idx;
+       int ret;
+
+       /* Check it isn't doing very strange things with descriptor numbers. */
+       last_avail_idx = vq->last_avail_idx;
+       if (get_user(vq->avail_idx, &vq->avail->idx)) {
+               vq_err(vq, "Failed to access avail idx at %p\n",
+                      &vq->avail->idx);
+               return vq->num;
+       }
+
+       if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) {
+               vq_err(vq, "Guest moved used index from %u to %u",
+                      last_avail_idx, vq->avail_idx);
+               return vq->num;
+       }
+
+       /* If there's nothing new since last we looked, return invalid. */
+       if (vq->avail_idx == last_avail_idx)
+               return vq->num;
+
+       /* Only get avail ring entries after they have been exposed by guest. */
+       rmb();
+
+       /* Grab the next descriptor number they're advertising, and increment
+        * the index we've seen. */
+       if (get_user(head, &vq->avail->ring[last_avail_idx % vq->num])) {
+               vq_err(vq, "Failed to read head: idx %d address %p\n",
+                      last_avail_idx,
+                      &vq->avail->ring[last_avail_idx % vq->num]);
+               return vq->num;
+       }
+
+       /* If their number is silly, that's an error. */
+       if (head >= vq->num) {
+               vq_err(vq, "Guest says index %u > %u is available",
+                      head, vq->num);
+               return vq->num;
+       }
+
+       /* When we start there are none of either input nor output. */
+       *out_num = *in_num = 0;
+       if (unlikely(log))
+               *log_num = 0;
+
+       i = head;
+       do {
+               unsigned iov_count = *in_num + *out_num;
+               if (i >= vq->num) {
+                       vq_err(vq, "Desc index is %u > %u, head = %u",
+                              i, vq->num, head);
+                       return vq->num;
+               }
+               if (++found > vq->num) {
+                       vq_err(vq, "Loop detected: last one at %u "
+                              "vq size %u head %u\n",
+                              i, vq->num, head);
+                       return vq->num;
+               }
+               ret = copy_from_user(&desc, vq->desc + i, sizeof desc);
+               if (ret) {
+                       vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
+                              i, vq->desc + i);
+                       return vq->num;
+               }
+               if (desc.flags & VRING_DESC_F_INDIRECT) {
+                       ret = get_indirect(dev, vq, iov, iov_size,
+                                          out_num, in_num,
+                                          log, log_num, &desc);
+                       if (ret < 0) {
+                               vq_err(vq, "Failure detected "
+                                      "in indirect descriptor at idx %d\n", i);
+                               return vq->num;
+                       }
+                       continue;
+               }
+
+               ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
+                                    iov_size - iov_count);
+               if (ret < 0) {
+                       vq_err(vq, "Translation failure %d descriptor idx %d\n",
+                              ret, i);
+                       return vq->num;
+               }
+               if (desc.flags & VRING_DESC_F_WRITE) {
+                       /* If this is an input descriptor,
+                        * increment that count. */
+                       *in_num += ret;
+                       if (unlikely(log)) {
+                               log[*log_num].addr = desc.addr;
+                               log[*log_num].len = desc.len;
+                               ++*log_num;
+                       }
+               } else {
+                       /* If it's an output descriptor, they're all supposed
+                        * to come before any input descriptors. */
+                       if (*in_num) {
+                               vq_err(vq, "Descriptor has out after in: "
+                                      "idx %d\n", i);
+                               return vq->num;
+                       }
+                       *out_num += ret;
+               }
+       } while ((i = next_desc(&desc)) != -1);
+
+       /* On success, increment avail index. */
+       vq->last_avail_idx++;
+       return head;
+}
+
+/* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */
+void vhost_discard_vq_desc(struct vhost_virtqueue *vq)
+{
+       vq->last_avail_idx--;
+}
+
+/* After we've used one of their buffers, we tell them about it.  We'll then
+ * want to notify the guest, using eventfd. */
+int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len)
+{
+       struct vring_used_elem *used;
+
+       /* The virtqueue contains a ring of used buffers.  Get a pointer to the
+        * next entry in that used ring. */
+       used = &vq->used->ring[vq->last_used_idx % vq->num];
+       if (put_user(head, &used->id)) {
+               vq_err(vq, "Failed to write used id");
+               return -EFAULT;
+       }
+       if (put_user(len, &used->len)) {
+               vq_err(vq, "Failed to write used len");
+               return -EFAULT;
+       }
+       /* Make sure buffer is written before we update index. */
+       wmb();
+       if (put_user(vq->last_used_idx + 1, &vq->used->idx)) {
+               vq_err(vq, "Failed to increment used idx");
+               return -EFAULT;
+       }
+       if (unlikely(vq->log_used)) {
+               /* Make sure data is seen before log. */
+               wmb();
+               log_write(vq->log_base, vq->log_addr + sizeof *vq->used->ring *
+                         (vq->last_used_idx % vq->num),
+                         sizeof *vq->used->ring);
+               log_write(vq->log_base, vq->log_addr, sizeof *vq->used->ring);
+               if (vq->log_ctx)
+                       eventfd_signal(vq->log_ctx, 1);
+       }
+       vq->last_used_idx++;
+       return 0;
+}
+
+/* This actually signals the guest, using eventfd. */
+void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
+{
+       __u16 flags = 0;
+       if (get_user(flags, &vq->avail->flags)) {
+               vq_err(vq, "Failed to get flags");
+               return;
+       }
+
+       /* If they don't want an interrupt, don't signal, unless empty. */
+       if ((flags & VRING_AVAIL_F_NO_INTERRUPT) &&
+           (vq->avail_idx != vq->last_avail_idx ||
+            !vhost_has_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY)))
+               return;
+
+       /* Signal the Guest tell them we used something up. */
+       if (vq->call_ctx)
+               eventfd_signal(vq->call_ctx, 1);
+}
+
+/* And here's the combo meal deal.  Supersize me! */
+void vhost_add_used_and_signal(struct vhost_dev *dev,
+                              struct vhost_virtqueue *vq,
+                              unsigned int head, int len)
+{
+       vhost_add_used(vq, head, len);
+       vhost_signal(dev, vq);
+}
+
+/* OK, now we need to know about added descriptors. */
+bool vhost_enable_notify(struct vhost_virtqueue *vq)
+{
+       u16 avail_idx;
+       int r;
+       if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY))
+               return false;
+       vq->used_flags &= ~VRING_USED_F_NO_NOTIFY;
+       r = put_user(vq->used_flags, &vq->used->flags);
+       if (r) {
+               vq_err(vq, "Failed to enable notification at %p: %d\n",
+                      &vq->used->flags, r);
+               return false;
+       }
+       /* They could have slipped one in as we were doing that: make
+        * sure it's written, then check again. */
+       mb();
+       r = get_user(avail_idx, &vq->avail->idx);
+       if (r) {
+               vq_err(vq, "Failed to check avail idx at %p: %d\n",
+                      &vq->avail->idx, r);
+               return false;
+       }
+
+       return avail_idx != vq->last_avail_idx;
+}
+
+/* We don't need to be notified again. */
+void vhost_disable_notify(struct vhost_virtqueue *vq)
+{
+       int r;
+       if (vq->used_flags & VRING_USED_F_NO_NOTIFY)
+               return;
+       vq->used_flags |= VRING_USED_F_NO_NOTIFY;
+       r = put_user(vq->used_flags, &vq->used->flags);
+       if (r)
+               vq_err(vq, "Failed to enable notification at %p: %d\n",
+                      &vq->used->flags, r);
+}
+
+int vhost_init(void)
+{
+       vhost_workqueue = create_singlethread_workqueue("vhost");
+       if (!vhost_workqueue)
+               return -ENOMEM;
+       return 0;
+}
+
+void vhost_cleanup(void)
+{
+       destroy_workqueue(vhost_workqueue);
+}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
new file mode 100644
index 0000000..d1f0453
--- /dev/null
+++ b/drivers/vhost/vhost.h
@@ -0,0 +1,159 @@
+#ifndef _VHOST_H
+#define _VHOST_H
+
+#include <linux/eventfd.h>
+#include <linux/vhost.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+#include <linux/file.h>
+#include <linux/skbuff.h>
+#include <linux/uio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+
+struct vhost_device;
+
+enum {
+       /* Enough place for all fragments, head, and virtio net header. */
+       VHOST_NET_MAX_SG = MAX_SKB_FRAGS + 2,
+};
+
+/* Poll a file (eventfd or socket) */
+/* Note: there's nothing vhost specific about this structure. */
+struct vhost_poll {
+       poll_table                table;
+       wait_queue_head_t        *wqh;
+       wait_queue_t              wait;
+       /* struct which will handle all actual work. */
+       struct work_struct        work;
+       unsigned long             mask;
+};
+
+void vhost_poll_init(struct vhost_poll *poll, work_func_t func,
+                    unsigned long mask);
+void vhost_poll_start(struct vhost_poll *poll, struct file *file);
+void vhost_poll_stop(struct vhost_poll *poll);
+void vhost_poll_flush(struct vhost_poll *poll);
+void vhost_poll_queue(struct vhost_poll *poll);
+
+struct vhost_log {
+       u64 addr;
+       u64 len;
+};
+
+/* The virtqueue structure describes a queue attached to a device. */
+struct vhost_virtqueue {
+       struct vhost_dev *dev;
+
+       /* The actual ring of buffers. */
+       struct mutex mutex;
+       unsigned int num;
+       struct vring_desc __user *desc;
+       struct vring_avail __user *avail;
+       struct vring_used __user *used;
+       struct file *kick;
+       struct file *call;
+       struct file *error;
+       struct eventfd_ctx *call_ctx;
+       struct eventfd_ctx *error_ctx;
+       struct eventfd_ctx *log_ctx;
+
+       struct vhost_poll poll;
+
+       /* The routine to call when the Guest pings us, or timeout. */
+       work_func_t handle_kick;
+
+       /* Last available index we saw. */
+       u16 last_avail_idx;
+
+       /* Caches available index value from user. */
+       u16 avail_idx;
+
+       /* Last index we used. */
+       u16 last_used_idx;
+
+       /* Used flags */
+       u16 used_flags;
+
+       /* Log writes to used structure. */
+       bool log_used;
+       u64 log_addr;
+
+       struct iovec indirect[VHOST_NET_MAX_SG];
+       struct iovec iov[VHOST_NET_MAX_SG];
+       struct iovec hdr[VHOST_NET_MAX_SG];
+       size_t hdr_size;
+       /* We use a kind of RCU to access private pointer.
+        * All readers access it from workqueue, which makes it possible to
+        * flush the workqueue instead of synchronize_rcu. Therefore readers do
+        * not need to call rcu_read_lock/rcu_read_unlock: the beginning of
+        * work item execution acts instead of rcu_read_lock() and the end of
+        * work item execution acts instead of rcu_read_lock().
+        * Writers use virtqueue mutex. */
+       void *private_data;
+       /* Log write descriptors */
+       void __user *log_base;
+       struct vhost_log log[VHOST_NET_MAX_SG];
+};
+
+struct vhost_dev {
+       /* Readers use RCU to access memory table pointer
+        * log base pointer and features.
+        * Writers use mutex below.*/
+       struct vhost_memory *memory;
+       struct mm_struct *mm;
+       struct mutex mutex;
+       unsigned acked_features;
+       struct vhost_virtqueue *vqs;
+       int nvqs;
+       struct file *log_file;
+       struct eventfd_ctx *log_ctx;
+};
+
+long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue *vqs, int nvqs);
+long vhost_dev_check_owner(struct vhost_dev *);
+long vhost_dev_reset_owner(struct vhost_dev *);
+void vhost_dev_cleanup(struct vhost_dev *);
+long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
+
+unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
+                          struct iovec iov[], unsigned int iov_count,
+                          unsigned int *out_num, unsigned int *in_num,
+                          struct vhost_log *log, unsigned int *log_num);
+void vhost_discard_vq_desc(struct vhost_virtqueue *);
+
+int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
+void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
+void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *,
+                              unsigned int head, int len);
+void vhost_disable_notify(struct vhost_virtqueue *);
+bool vhost_enable_notify(struct vhost_virtqueue *);
+
+int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
+                   unsigned int log_num, u64 len);
+
+int vhost_init(void);
+void vhost_cleanup(void);
+
+#define vq_err(vq, fmt, ...) do {                                  \
+               pr_debug(pr_fmt(fmt), ##__VA_ARGS__);       \
+               if ((vq)->error_ctx)                               \
+                               eventfd_signal((vq)->error_ctx, 1);\
+       } while (0)
+
+enum {
+       VHOST_FEATURES = (1 << VIRTIO_F_NOTIFY_ON_EMPTY) |
+                        (1 << VIRTIO_RING_F_INDIRECT_DESC) |
+                        (1 << VHOST_F_LOG_ALL) |
+                        (1 << VHOST_NET_F_VIRTIO_NET_HDR),
+};
+
+static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
+{
+       unsigned acked_features = rcu_dereference(dev->acked_features);
+       return acked_features & (1 << bit);
+}
+
+#endif
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 1feed71..e210194 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -361,6 +361,7 @@ unifdef-y += uio.h
 unifdef-y += unistd.h
 unifdef-y += usbdevice_fs.h
 unifdef-y += utsname.h
+unifdef-y += vhost.h
 unifdef-y += videodev2.h
 unifdef-y += videodev.h
 unifdef-y += virtio_config.h
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index adaf3c1..8b5f7cc 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -30,6 +30,7 @@
 #define HPET_MINOR             228
 #define FUSE_MINOR             229
 #define KVM_MINOR              232
+#define VHOST_NET_MINOR                233
 #define MISC_DYNAMIC_MINOR     255

 struct device;
diff --git a/include/linux/vhost.h b/include/linux/vhost.h
new file mode 100644
index 0000000..e847f1e
--- /dev/null
+++ b/include/linux/vhost.h
@@ -0,0 +1,130 @@
+#ifndef _LINUX_VHOST_H
+#define _LINUX_VHOST_H
+/* Userspace interface for in-kernel virtio accelerators. */
+
+/* vhost is used to reduce the number of system calls involved in virtio.
+ *
+ * Existing virtio net code is used in the guest without modification.
+ *
+ * This header includes interface used by userspace hypervisor for
+ * device configuration.
+ */
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/ioctl.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+
+struct vhost_vring_state {
+       unsigned int index;
+       unsigned int num;
+};
+
+struct vhost_vring_file {
+       unsigned int index;
+       int fd; /* Pass -1 to unbind from file. */
+
+};
+
+struct vhost_vring_addr {
+       unsigned int index;
+       /* Option flags. */
+       unsigned int flags;
+       /* Flag values: */
+       /* Whether log address is valid. If set enables logging. */
+#define VHOST_VRING_F_LOG 0
+
+       /* Start of array of descriptors (virtually contiguous) */
+       __u64 desc_user_addr;
+       /* Used structure address. Must be 32 bit aligned */
+       __u64 used_user_addr;
+       /* Available structure address. Must be 16 bit aligned */
+       __u64 avail_user_addr;
+       /* Logging support. */
+       /* Log writes to used structure, at offset calculated from specified
+        * address. Address must be 32 bit aligned. */
+       __u64 log_guest_addr;
+};
+
+struct vhost_memory_region {
+       __u64 guest_phys_addr;
+       __u64 memory_size; /* bytes */
+       __u64 userspace_addr;
+       __u64 flags_padding; /* No flags are currently specified. */
+};
+
+/* All region addresses and sizes must be 4K aligned. */
+#define VHOST_PAGE_SIZE 0x1000
+
+struct vhost_memory {
+       __u32 nregions;
+       __u32 padding;
+       struct vhost_memory_region regions[0];
+};
+
+/* ioctls */
+
+#define VHOST_VIRTIO 0xAF
+
+/* Features bitmask for forward compatibility.  Transport bits are used for
+ * vhost specific features. */
+#define VHOST_GET_FEATURES     _IOR(VHOST_VIRTIO, 0x00, __u64)
+#define VHOST_SET_FEATURES     _IOW(VHOST_VIRTIO, 0x00, __u64)
+
+/* Set current process as the (exclusive) owner of this file descriptor.  This
+ * must be called before any other vhost command.  Further calls to
+ * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
+#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
+/* Give up ownership, and reset the device to default values.
+ * Allows subsequent call to VHOST_OWNER_SET to succeed. */
+#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
+
+/* Set up/modify memory layout */
+#define VHOST_SET_MEM_TABLE    _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
+
+/* Write logging setup. */
+/* Memory writes can optionally be logged by setting bit at an offset
+ * (calculated from the physical address) from specified log base.
+ * The bit is set using an atomic 32 bit operation. */
+/* Set base address for logging. */
+#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
+/* Specify an eventfd file descriptor to signal on log write. */
+#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
+
+/* Ring setup. */
+/* Set number of descriptors in ring. This parameter can not
+ * be modified while ring is running (bound to a device). */
+#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
+/* Set addresses for the ring. */
+#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
+/* Base value where queue looks for available descriptors */
+#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
+/* Get accessor: reads index, writes value in num */
+#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
+
+/* The following ioctls use eventfd file descriptors to signal and poll
+ * for events. */
+
+/* Set eventfd to poll for added buffers */
+#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
+/* Set eventfd to signal when buffers have beed used */
+#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
+/* Set eventfd to signal an error */
+#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
+
+/* VHOST_NET specific defines */
+
+/* Attach virtio net ring to a raw socket, or tap device.
+ * The socket must be already bound to an ethernet device, this device will be
+ * used for transmit.  Pass fd -1 to unbind from the socket and the transmit
+ * device.  This can be used to stop the ring (e.g. for migration). */
+#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
+
+/* Feature bits */
+/* Log all write descriptors. Can be changed while device is active. */
+#define VHOST_F_LOG_ALL 26
+/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
+#define VHOST_NET_F_VIRTIO_NET_HDR 27
+
+#endif
--
1.6.5.2.143.g8cc62
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* Re: [PATCH] Documentation, clarify tuntap IPX example.
From: Max Krasnyansky @ 2009-11-18  5:52 UTC (permalink / raw)
  To: andrew hendry; +Cc: netdev@vger.kernel.org, linux-kernel
In-Reply-To: <d45a3acc0911171814i310bbd16t8ff3fba2410e9375@mail.gmail.com>

andrew hendry wrote:
> Hi Max,
> 
> I started looking through the documentation because im looking to use
> tun for X.25 over TCP. The IPX example sounded similar but i couldn't
> get it to work as I was expecting. Looking for a hint in the right
> direction.
Ah, X25 is different.

> There is an old non-mainline patch called x25tap (clone of obsolete
> ethertap). I'm hoping to replace x25tap with tun.
> 
> The old x25tap creates a device like:
> x25tap0   Link encap:generic X.25  HWaddr
>           UP BROADCAST RUNNING NOARP MULTICAST  MTU:1024  Metric:1
>           RX packets:3040785 errors:0 dropped:0 overruns:0 frame:0
>           TX packets:2895530 errors:0 dropped:0 overruns:0 carrier:0
>           collisions:0 txqueuelen:10
>           RX bytes:138787339 (132.3 Mb)  TX bytes:91395983 (87.1 Mb)
> When the x25tap is loaded it has dev->type = ARPHRD_X25, after which
> x.25 routing and AF_X25 sockets can be created.  Along with an XoT
> userspace program which handles some basic headers and TCP port 1998
> it works well.
> 
> If using tun, how does something get registered to handle protocol AF_X25?
> 

I've never tried this personally so ... :). But I just glanced over net/ax25
and drivers/wan/ax25 and it looks TUNSETLINK might work for you.
In other words you want to allocate TUN device (not TAP) and then call
TUNSETLINK with ARPHRD_X25. Seems like you'll get exactly what you need.

Max


> Regards,
> Andrew.
> 
> On Wed, Nov 18, 2009 at 12:40 PM, Max Krasnyansky <maxk@qualcomm.com> wrote:
>> On 11/17/2009 05:30 PM, andrew hendry wrote:
>>> Can the TUNSETIFF ioctl change a tap's protocol to IPX as the
>>> documentation suggests?
>>> I think tun.c would need IFF_IPX_TAP added for it to work as described?
>>> Otherwise tap can only be ptp or ethernet, and there is no way to
>>> route or use AF_IPX.
>> TAP is an Ethernet device. No special handling is required for IPX or for
>> that matter any other protocol. Example seems fine too.
>>
>> Max
>>
>>> Signed-off-by: Andrew Hendry<andrew.hendry@gmail.com>
>>>
>>> --- a/Documentation/networking/tuntap.txt       2009-11-11
>>> 14:03:22.676167648 +1100
>>> +++ b/Documentation/networking/tuntap.txt       2009-11-18
>>> 11:34:18.106647029 +1100
>>> @@ -127,12 +127,14 @@ Ethernet device, which instead of receiv
>>>  media, receives them from user space program and instead of sending
>>>  packets via physical media sends them to the user space program.
>>>
>>> -Let's say that you configured IPX on the tap0, then whenever
>>> -the kernel sends an IPX packet to tap0, it is passed to the application
>>> -(VTun for example). The application encrypts, compresses and sends it to
>>> -the other side over TCP or UDP. The application on the other side
>>> decompresses
>>> -and decrypts the data received and writes the packet to the TAP device,
>>> -the kernel handles the packet like it came from real physical device.
>>> +Let's say for the purpose of example, IPX support was added to tuntap.
>>> +Then whenever the kernel routes an IPX packet to tap0, it is passed to
>>> the
>>> +application reading the file descriptor from /dev/net/tun (VTun for
>>> example).
>>> +The application encrypts, compresses and sends it to the other side over
>>> TCP
>>> +or UDP. The application on the other side decompresses and decrypts the
>>> data
>>> +received and writes the packet to the TAP device, the remote kernel
>>> handles
>>> +the packet like it came from real physical device. The IPX applications
>>> are
>>> +able to communicate as if there was a real IPX network.
>>>
>>>  4. What is the difference between TUN driver and TAP driver?
>>>  TUN works with IP frames. TAP works with Ethernet frames.
>>


^ permalink raw reply

* Re: [PATCH 1/3] macvlan: Reflect macvlan packets meant for other macvlan devices
From: Eric Dumazet @ 2009-11-18  6:30 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, netdev, David Miller, Stephen Hemminger, Herbert Xu,
	Patrick McHardy, Patrick Mullaney, Eric W. Biederman,
	Edge Virtual Bridging, Anna Fischer, bridge, virtualization,
	Jens Osterkamp, Gerhard Stenzel
In-Reply-To: <1258497551-25959-2-git-send-email-arnd@arndb.de>

Arnd Bergmann a écrit :
> From: Eric Biederman <ebiederm@xmission.com>
> 
> Switch ports do not send packets back out the same port they came
> in on.	This causes problems when using a macvlan device inside
> of a network namespace as it becomes impossible to talk to
> other macvlan devices.

This patch is very welcome. I review it and found one oddity.

> 
> Signed-off-by: Eric Biederman <ebiederm@xmission.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> +static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	const struct macvlan_dev *vlan = netdev_priv(dev);
> +	const struct macvlan_port *port = vlan->port;
> +	const struct macvlan_dev *dest;
> +	const struct ethhdr *eth;
>  
> -	skb->dev = dev;
> -	skb->pkt_type = PACKET_HOST;
> +	skb->protocol = eth_type_trans(skb, dev);
> +	eth = eth_hdr(skb);
>  
> -	netif_rx(skb);
> -	return NULL;
> +	skb_dst_drop(skb);

Why do you drop dst here ?

It seems strange, since this driver specifically masks out IFF_XMIT_DST_RELEASE
in its macvlan_setup() :

dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;

If we really want to drop dst, it could be done by caller, if IFF_XMIT_DST_RELEASE
was not masked in macvlan_setup().


> +	skb->mark = 0;
> +	secpath_reset(skb);
> +	nf_reset(skb);
> +
> +	if (is_multicast_ether_addr(eth->h_dest)) {
> +		macvlan_broadcast(skb, port, dev);
> +		return macvlan_xmit_world(skb, dev);
> +	}
> +
> +	dest = macvlan_hash_lookup(port, eth->h_dest);
> +	if (dest)
> +		return macvlan_unicast(skb, dest);
> +
> +	return macvlan_xmit_world(skb, dev);
>  }


# find net drivers/net|xargs grep -n IFF_XMIT_DST_RELEASE
net/8021q/vlan_dev.c:837:       dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
net/atm/clip.c:561:     dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
net/core/dev.c:1778:            if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
net/core/dev.c:5287:    dev->priv_flags = IFF_XMIT_DST_RELEASE;
net/ipv4/ip_gre.c:1236: dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
net/ipv4/ipip.c:717:    dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
net/ipv6/sit.c:1104:    dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE;
drivers/net/appletalk/ipddp.c:76:       dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
drivers/net/bonding/bond_main.c:4534:   bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
drivers/net/eql.c:197:  dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE;
drivers/net/ifb.c:162:  dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
drivers/net/loopback.c:174:     dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE;
drivers/net/macvlan.c:421:      dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE;
drivers/net/ppp_generic.c:1057: dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
drivers/net/wan/hdlc_fr.c:1057: dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;

^ permalink raw reply

* Re: [PATCH 2/3] macvlan: implement VEPA and private mode
From: Eric Dumazet @ 2009-11-18  6:42 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, netdev, David Miller, Stephen Hemminger, Herbert Xu,
	Patrick McHardy, Patrick Mullaney, Eric W. Biederman,
	Edge Virtual Bridging, Anna Fischer, bridge, virtualization,
	Jens Osterkamp, Gerhard Stenzel
In-Reply-To: <1258497551-25959-3-git-send-email-arnd@arndb.de>

Arnd Bergmann a écrit :
> This allows each macvlan slave device to be in one
> of three modes, depending on the use case:
> 
> MACVLAN_MODE_PRIVATE:
>   The device never communicates with any other device
>   on the same upper_dev. This even includes frames
>   coming back from a reflective relay, where supported
>   by the adjacent bridge.
> 
> MACVLAN_MODE_VEPA:
>   The new Virtual Ethernet Port Aggregator (VEPA) mode,
>   we assume that the adjacent bridge returns all frames
>   where both source and destination are local to the
>   macvlan port, i.e. the bridge is set up as a reflective
>   relay.
>   Broadcast frames coming in from the upper_dev get
>   flooded to all macvlan interfaces in VEPA mode.
>   We never deliver any frames locally.
> 
> MACVLAN_MODE_BRIDGE:
>   We provide the behavior of a simple bridge between
>   different macvlan interfaces on the same port. Frames
>   from one interface to another one get delivered directly
>   and are not sent out externally. Broadcast frames get
>   flooded to all other bridge ports and to the external
>   interface, but when they come back from a reflective
>   relay, we don't deliver them again.
>   Since we know all the MAC addresses, the macvlan bridge
>   mode does not require learning or STP like the bridge
>   module does.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---


>  	if (is_multicast_ether_addr(eth->h_dest)) {
> -		macvlan_broadcast(skb, port, NULL);
> +		src = macvlan_hash_lookup(port, eth->h_source);
> +		if (!src)
> +			/* frame comes from an external address */


> +			macvlan_broadcast(skb, port, NULL, MACVLAN_MODE_VEPA
> +				| MACVLAN_MODE_VEPA | MACVLAN_MODE_BRIDGE);

typo here, you probably meant MACVLAN_PRIVATE | MACVLAN_VEPA | MACVLAN_BRIDGE 

> +		else if (src->mode == MACVLAN_MODE_VEPA)
> +			/* flood to everyone except source */
> +			macvlan_broadcast(skb, port, src->dev,
> +				MACVLAN_MODE_VEPA | MACVLAN_MODE_BRIDGE);
> +		else if (src->mode == MACVLAN_MODE_BRIDGE)
> +			/* flood only to VEPA ports, bridge ports
> +			   already saw the frame */
> +			macvlan_broadcast(skb, port, src->dev,
> +				MACVLAN_MODE_VEPA);
>  		return skb;
>  	}
>  


^ permalink raw reply

* Re: [PATCH 3/3] macvlan: export macvlan mode through netlink
From: Eric Dumazet @ 2009-11-18  6:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, netdev, David Miller, Stephen Hemminger, Herbert Xu,
	Patrick McHardy, Patrick Mullaney, Eric W. Biederman,
	Edge Virtual Bridging, Anna Fischer, bridge, virtualization,
	Jens Osterkamp, Gerhard Stenzel
In-Reply-To: <1258497551-25959-4-git-send-email-arnd@arndb.de>

Arnd Bergmann a écrit :
> In order to support all three modes of macvlan at
> runtime, extend the existing netlink protocol
> to allow choosing the mode per macvlan slave
> interface.
> 
> This depends on a matching patch to iproute2
> in order to become accessible in user land.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/net/macvlan.c   |   67 +++++++++++++++++++++++++++++++++++++++++-----
>  include/linux/if_link.h |   15 ++++++++++
>  2 files changed, 74 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
> index fa8b568..731017e 100644
> --- a/drivers/net/macvlan.c
> +++ b/drivers/net/macvlan.c
> @@ -33,12 +33,6 @@
>  
>  #define MACVLAN_HASH_SIZE	(1 << BITS_PER_BYTE)
>  
> -enum macvlan_type {
> -	MACVLAN_PRIVATE		= 1,
> -	MACVLAN_VEPA		= 2,
> -	MACVLAN_BRIDGE		= 4,
> -};

I realize you defined MACVLAN_PRIVATE in patch 2, but used MACVLAN_MODE_PRIVATE,
so patch 2 is not compilable and breaks bisection ?


> +
> +enum ifla_macvlan_mode {
> +	MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */
> +	MACVLAN_MODE_VEPA    = 2, /* talk to other ports through ext bridge */
> +	MACVLAN_MODE_BRIDGE  = 4, /* talk to bridge ports directly */
> +};

^ permalink raw reply

* Re: NETLINK sockets dont honor SO_RCVLOWAT?
From: David Miller @ 2009-11-18  7:17 UTC (permalink / raw)
  To: jharan; +Cc: netdev
In-Reply-To: <D67825C5985D0647BE40A5F5B0B70D1106E9C56894@HQ-EXCH-7.corp.brocade.com>

From: Jeff Haran <jharan@Brocade.COM>
Date: Tue, 17 Nov 2009 17:54:59 -0800

> Am I correct in my observation that the SO_RCVLOWAT socket option is
> not honored when one calls readv() on a PF_NETLINK socket?

That's correct.

SO_RCVLOWAT is only available on stream based sockets such as TCP and
UNIX.

^ permalink raw reply

* Re: [PATCH 1/2] rps: core implementation
From: David Miller @ 2009-11-18  7:21 UTC (permalink / raw)
  To: therbert; +Cc: netdev
In-Reply-To: <65634d660911160843j3df398f2w876044083181cfcd@mail.gmail.com>

From: Tom Herbert <therbert@google.com>
Date: Mon, 16 Nov 2009 08:43:05 -0800

> On Mon, Nov 16, 2009 at 3:19 AM, David Miller <davem@davemloft.net> wrote:
>> {,__}send_remote_softirq() doesn't work? :-)
>>
> NET_RPS_SOFTIRQ is intended to provide coalescing of IPIs.
> 
> send_remote_softirq could be used, but we would also need to get the
> napi structure on the remote cpu poll list so that would probably need
> to be protected by locks (something like __napi_schedule_oncpu could
> be defined).  Would this be better to do?

We talked about this several times in the past too.  Let me think some
more about this, I want to consider all of the issues a bit before
making any suggestions.

Thanks.

^ permalink raw reply

* Re: [RFC-PATCH] libiscsi dhcp handler
From: David Miller @ 2009-11-18  7:25 UTC (permalink / raw)
  To: rakesh; +Cc: michaelc, open-iscsi, netdev, linux-kernel, James.Bottomley, kxie
In-Reply-To: <4B03697F.9090200@chelsio.com>

From: Rakesh Ranjan <rakesh@chelsio.com>
Date: Wed, 18 Nov 2009 08:56:55 +0530

> ping ...

I'm too busy, if you're waiting for me.  It could take weeks for me to
get to this, sorry.

^ permalink raw reply

* nf_conntrack sets wrong value for ctorigsrc parameter
From: Ben Hutchings @ 2009-11-18  7:39 UTC (permalink / raw)
  To: netdev; +Cc: Michel Messerschmidt, 556587

[-- Attachment #1: Type: text/plain, Size: 28101 bytes --]

From the Debian bug tracking system:

-------- Forwarded Message --------
From: Michel Messerschmidt <lists@michel-messerschmidt.de>
Reply-to: Michel Messerschmidt <lists@michel-messerschmidt.de>, 556587@bugs.debian.org
To: Debian Bug Tracking System <submit@bugs.debian.org>
Subject: Bug#556587: linux-image-2.6.31-1-686-bigmem: nf_conntrack sets wrong value for ctorigsrc parameter
Date: Mon, 16 Nov 2009 23:09:10 +0100

Package: linux-2.6
Version: 2.6.31-2
Severity: normal

My iptables script using the conntrack module does not work with this kernel 
version anymore. The value of the ctorigsrc parameter is not set correctly:
rei:~$ cat /etc/mm_iptables/mm_iptables_dmz | grep -E 'ctorig|LOCALIP='
LOCALIP="192.168.40.3"
        $IPT -A in_dmz -p udp --dport 1024:65535 -m conntrack --ctproto udp --ctorigsrc $LOCALIP --ctorigdstport 53 --ctreplsrcport 53 -j ACCEPT
        $IPT -A in_dmz -p udp --dport 1024:65535 -m conntrack --ctstate RELATED,ESTABLISHED --ctproto udp --ctorigsrc $LOCALIP -j ACCEPT
rei:~$ iptables -nvL | grep ctorig
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp dpts:1024:65535 ctproto 17 ctorigsrc 192.60.154.245 ctorigdstport 53 ctreplsrcport 53 
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp dpts:1024:65535 ctstate RELATED,ESTABLISHED ctproto 17 ctorigsrc 128.49.154.245 

I see the same behavior with the 686 flavour (without bigmem).

With older kernels up to 2.6.30-8, the ctorigsrc value was set as expected:
rei:~$ iptables -nvL | grep ctorig
   21  2452 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp dpts:1024:65535 ctproto 17 ctorigsrc 192.168.40.3 ctorigdstport 53 ctreplsrcport 53 
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp dpts:1024:65535 ctstate RELATED,ESTABLISHED ctproto 17 ctorigsrc 192.168.40.3 



-- Package-specific info:
** Version:
Linux version 2.6.31-1-686-bigmem (Debian 2.6.31-2) (ben@decadent.org.uk) (gcc version 4.3.4 (Debian 4.3.4-6) ) #1 SMP Sun Nov 15 21:22:56 UTC 2009

** Command line:
BOOT_IMAGE=/vmlinuz-2.6.31-1-686-bigmem root=/dev/mapper/sda2_crypt ro vdso=1

** Not tainted

** Kernel log:
[  252.421890] FW-DROP-DEFAULT IN=eth1 OUT= MAC=00:08:54:50:08:d8:00:16:38:aa:fd:00:08:00 SRC=217.237.150.205 DST=192.168.40.3 LEN=126 TOS=0x00 PREC=0x00 TTL=60 ID=0 DF PROTO=UDP SPT=53 DPT=25586 LEN=106 
[  252.425260] FW-DROP-DEFAULT IN=eth1 OUT= MAC=00:08:54:50:08:d8:00:16:38:aa:fd:00:08:00 SRC=217.237.149.142 DST=192.168.40.3 LEN=126 TOS=0x00 PREC=0x00 TTL=59 ID=0 DF PROTO=UDP SPT=53 DPT=25586 LEN=106 
[  252.425929] FW-DROP-DEFAULT IN=eth1 OUT= MAC=00:08:54:50:08:d8:00:16:38:aa:fd:00:08:00 SRC=217.237.150.205 DST=192.168.40.3 LEN=144 TOS=0x00 PREC=0x00 TTL=60 ID=0 DF PROTO=UDP SPT=53 DPT=42698 LEN=124 
[  252.429781] FW-DROP-DEFAULT IN=eth1 OUT= MAC=00:08:54:50:08:d8:00:16:38:aa:fd:00:08:00 SRC=217.237.149.142 DST=192.168.40.3 LEN=144 TOS=0x00 PREC=0x00 TTL=59 ID=0 DF PROTO=UDP SPT=53 DPT=42698 LEN=124 
[...cut many repeated log messages...]

** Model information
not available

** Loaded modules:
Module                  Size  Used by
tun                    13120  2 
video                  19856  0 
output                  2872  1 video
ac                      3124  0 
battery                 6348  0 
acpi_cpufreq            8104  0 
cpufreq_userspace       2944  0 
cpufreq_conservative     6780  0 
cpufreq_powersave       1408  0 
cpufreq_stats           3868  0 
nfsd                  223620  9 
exportfs                4016  1 nfsd
nfs                   252000  0 
lockd                  64696  2 nfsd,nfs
fscache                36696  1 nfs
nfs_acl                 2860  2 nfsd,nfs
auth_rpcgss            34388  2 nfsd,nfs
sunrpc                181096  10 nfsd,nfs,lockd,nfs_acl,auth_rpcgss
ipt_MASQUERADE          2400  1 
iptable_nat             5596  1 
xt_TCPMSS               3604  1 
xt_conntrack            4028  36 
xt_tcpudp               2716  195 
ip6t_LOG                4864  1 
ipt_LOG                 4784  39 
ip6table_filter         3312  1 
ip6_tables             12000  2 ip6t_LOG,ip6table_filter
iptable_filter          3240  1 
nf_nat                 17316  2 ipt_MASQUERADE,iptable_nat
nf_conntrack_ftp        6592  0 
nf_conntrack_ipv4      13120  39 iptable_nat,nf_nat
nf_conntrack           64156  6 ipt_MASQUERADE,iptable_nat,xt_conntrack,nf_nat,nf_conntrack_ftp,nf_conntrack_ipv4
nf_defrag_ipv4          1808  1 nf_conntrack_ipv4
ip_tables              10764  2 iptable_nat,iptable_filter
x_tables               16084  9 ipt_MASQUERADE,iptable_nat,xt_TCPMSS,xt_conntrack,xt_tcpudp,ip6t_LOG,ipt_LOG,ip6_tables,ip_tables
fuse                   58196  1 
ext2                   58996  1 
hwmon_vid               2576  0 
eeprom                  5184  0 
firewire_sbp2          14016  0 
loop                   14268  0 
snd_ca0106             32032  0 
snd_rawmidi            20452  1 snd_ca0106
snd_seq_device          6780  1 snd_rawmidi
snd_ac97_codec         99668  1 snd_ca0106
snd_pcsp                9540  0 
ac97_bus                1628  1 snd_ac97_codec
i2c_i801                8952  0 
snd_pcm                70136  3 snd_ca0106,snd_ac97_codec,snd_pcsp
snd_timer              19000  1 snd_pcm
i2c_core               21744  2 eeprom,i2c_i801
rng_core                3996  0 
snd                    54440  7 snd_ca0106,snd_rawmidi,snd_seq_device,snd_ac97_codec,snd_pcsp,snd_pcm,snd_timer
soundcore               6844  1 snd
snd_page_alloc          8716  2 snd_ca0106,snd_pcm
evdev                   8832  3 
button                  5488  0 
processor              36772  1 acpi_cpufreq
ext4                  284896  8 
mbcache                 7488  2 ext2,ext4
jbd2                   73892  1 ext4
crc16                   1840  1 ext4
cbc                     3352  9 
dm_crypt               12340  9 
dm_mod                 65432  40 dm_crypt
sd_mod                 31840  7 
crc_t10dif              1716  1 sd_mod
ide_pci_generic         3784  0 
ide_core               97736  1 ide_pci_generic
ata_generic             4500  0 
ahci                   33412  0 
ata_piix               21532  5 
uhci_hcd               20568  0 
libata                163228  3 ata_generic,ahci,ata_piix
firewire_ohci          20740  0 
firewire_core          45276  2 firewire_sbp2,firewire_ohci
crc_itu_t               1892  1 firewire_core
r8169                  30624  0 
mii                     5048  1 r8169
ehci_hcd               32868  0 
scsi_mod              143036  3 firewire_sbp2,sd_mod,libata
tg3                    97292  0 
libphy                 23160  1 tg3
usbcore               141496  4 uhci_hcd,ehci_hcd
nls_base                7188  1 usbcore
intel_agp              25752  1 
agpgart                33112  1 intel_agp
thermal                13720  0 
fan                     4460  0 
thermal_sys            14396  4 video,processor,thermal,fan
aes_i586                8312  18 
aes_generic            27640  1 aes_i586
sha256_generic         11492  0 

** Network interface configuration:
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback
	post-up /etc/mm_iptables/mm_iptables_init start

# The primary network interface
# really use hotplug ???
#allow-hotplug eth0
auto eth0
iface eth0 inet static
	address 192.168.42.3
	netmask 255.255.255.0
	broadcast 192.168.42.255
	# gateway must not be set here to allow dialup connections
	#gateway 192.168.42.3
	# hardware address (MAC)
#	hwaddress ether 
	# set MTU for ethernet only network
	mtu 1500
	# dns-* options are implemented by the resolvconf package, if installed
	dns-nameservers 192.168.42.3
	dns-search matrix
	# handle firewall rules for this interface
	post-up /etc/mm_iptables/mm_iptables_localnet start
	pre-down /etc/mm_iptables/mm_iptables_localnet stop || true

auto eth1
iface eth1 inet static
	address 192.168.40.3
	netmask 255.255.255.0
	broadcast 192.168.40.255
	# gateway must not be set here to allow dialup connections
	gateway 192.168.40.1
	# hardware address (MAC)
#	hwaddress ether 
	# set MTU for dialup / dsl / internet
	mtu 1492
	# dns-* options are implemented by the resolvconf package, if installed
	dns-nameservers 192.168.42.3
	dns-search home
	# handle firewall rules for this interface
	post-up /etc/mm_iptables/mm_iptables_dmz start
	pre-down /etc/mm_iptables/mm_iptables_dmz stop || true


** Network status:
*** IP interfaces and addresses:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1492 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether 00:08:54:50:08:d8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.40.3/24 brd 192.168.40.255 scope global eth1
    inet6 fe80::208:54ff:fe50:8d8/64 scope link 
       valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:30:1b:ba:73:70 brd ff:ff:ff:ff:ff:ff
    inet 192.168.42.3/24 brd 192.168.42.255 scope global eth0
    inet6 fe80::230:1bff:feba:7370/64 scope link 
       valid_lft forever preferred_lft forever
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100
    link/[65534] 
    inet 10.1.41.3 peer 10.1.41.10/32 scope global tun0

*** Device statistics:
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo:   18976     258    0    0    0     0          0         0    18976     258    0    0    0     0       0          0
  eth1:   48518     332    0    0    0     0          0         0    30390     378    0    0    0     0       0          0
  eth0:   84454     855    0    0    0     0          0         0   115085     537    0    0    0     0       0          0
  tun0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

*** Protocol statistics:
Ip:
    1475 total packets received
    70 forwarded
    0 incoming packets discarded
    1105 incoming packets delivered
    1146 requests sent out
Icmp:
    1 ICMP messages received
    0 input ICMP message failed.
    ICMP input histogram:
        destination unreachable: 1
    1 ICMP messages sent
    0 ICMP messages failed
    ICMP output histogram:
        destination unreachable: 1
IcmpMsg:
        InType3: 1
        OutType3: 1
Tcp:
    4 active connections openings
    2 passive connection openings
    4 failed connection attempts
    0 connection resets received
    2 connections established
    727 segments received
    452 segments send out
    0 segments retransmited
    0 bad segments received.
    9 resets sent
Udp:
    377 packets received
    1 packets to unknown port received.
    0 packet receive errors
    627 packets sent
UdpLite:
TcpExt:
    4 delayed acks sent
    4 packets directly queued to recvmsg prequeue.
    230 packet headers predicted
    45 acknowledgments not containing data payload received
    376 predicted acknowledgments
IpExt:
    InBcastPkts: 48
    OutBcastPkts: 48
    InOctets: 136879
    OutOctets: 148461
    InBcastOctets: 5833
    OutBcastOctets: 5833

*** Device features:
eth0: 0x109a3
eth1: 0x180
lo: 0x13865
tun0: 0x0

** PCI devices:
00:00.0 Host bridge [0600]: Intel Corporation Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller [8086:2590] (rev 04)
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ >SERR- <PERR- INTx-
	Latency: 0
	Capabilities: <access denied>
	Kernel driver in use: agpgart-intel

00:02.0 VGA compatible controller [0300]: Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller [8086:2592] (rev 04) (prog-if 00 [VGA controller])
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Interrupt: pin A routed to IRQ 5
	Region 0: Memory at dff00000 (32-bit, non-prefetchable) [size=512K]
	Region 1: I/O ports at ff00 [size=8]
	Region 2: Memory at c0000000 (32-bit, prefetchable) [size=256M]
	Region 3: Memory at dff80000 (32-bit, non-prefetchable) [size=256K]
	Expansion ROM at <unassigned> [disabled]
	Capabilities: <access denied>

00:02.1 Display controller [0380]: Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller [8086:2792] (rev 04)
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Region 0: Memory at dfe80000 (32-bit, non-prefetchable) [disabled] [size=512K]
	Capabilities: <access denied>

00:1c.0 PCI bridge [0604]: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 [8086:2660] (rev 04) (prog-if 00 [Normal decode])
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0, Cache Line Size: 32 bytes
	Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
	I/O behind bridge: 0000c000-0000cfff
	Memory behind bridge: dfd00000-dfdfffff
	Prefetchable memory behind bridge: 00000000dfa00000-00000000dfafffff
	Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
	BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
		PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
	Capabilities: <access denied>
	Kernel driver in use: pcieport-driver

00:1c.2 PCI bridge [0604]: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 [8086:2664] (rev 04) (prog-if 00 [Normal decode])
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0, Cache Line Size: 32 bytes
	Bus: primary=00, secondary=02, subordinate=02, sec-latency=0
	I/O behind bridge: 0000b000-0000bfff
	Memory behind bridge: df900000-df9fffff
	Prefetchable memory behind bridge: 00000000df800000-00000000df8fffff
	Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
	BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
		PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
	Capabilities: <access denied>
	Kernel driver in use: pcieport-driver

00:1d.0 USB Controller [0c03]: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 [8086:2658] (rev 04) (prog-if 00 [UHCI])
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Interrupt: pin A routed to IRQ 23
	Region 4: I/O ports at fe00 [size=32]
	Kernel driver in use: uhci_hcd

00:1d.1 USB Controller [0c03]: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 [8086:2659] (rev 04) (prog-if 00 [UHCI])
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Interrupt: pin B routed to IRQ 19
	Region 4: I/O ports at fd00 [size=32]
	Kernel driver in use: uhci_hcd

00:1d.2 USB Controller [0c03]: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 [8086:265a] (rev 04) (prog-if 00 [UHCI])
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Interrupt: pin C routed to IRQ 18
	Region 4: I/O ports at fc00 [size=32]
	Kernel driver in use: uhci_hcd

00:1d.3 USB Controller [0c03]: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 [8086:265b] (rev 04) (prog-if 00 [UHCI])
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Interrupt: pin D routed to IRQ 16
	Region 4: I/O ports at fb00 [size=32]
	Kernel driver in use: uhci_hcd

00:1d.7 USB Controller [0c03]: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller [8086:265c] (rev 04) (prog-if 20 [EHCI])
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Interrupt: pin A routed to IRQ 23
	Region 0: Memory at dffff000 (32-bit, non-prefetchable) [size=1K]
	Capabilities: <access denied>
	Kernel driver in use: ehci_hcd

00:1e.0 PCI bridge [0604]: Intel Corporation 82801 Mobile PCI Bridge [8086:2448] (rev d4) (prog-if 01 [Subtractive decode])
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Bus: primary=00, secondary=03, subordinate=03, sec-latency=32
	I/O behind bridge: 0000d000-0000dfff
	Memory behind bridge: dfc00000-dfcfffff
	Prefetchable memory behind bridge: 00000000dfb00000-00000000dfbfffff
	Secondary status: 66MHz- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
	BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
		PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
	Capabilities: <access denied>

00:1f.0 ISA bridge [0601]: Intel Corporation 82801FBM (ICH6M) LPC Interface Bridge [8086:2641] (rev 04)
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
	Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0

00:1f.2 IDE interface [0101]: Intel Corporation 82801FBM (ICH6M) SATA Controller [8086:2653] (rev 04) (prog-if 80 [Master])
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx+
	Latency: 0
	Interrupt: pin B routed to IRQ 19
	Region 0: I/O ports at 01f0 [size=8]
	Region 1: I/O ports at 03f4 [size=1]
	Region 2: I/O ports at 0170 [size=8]
	Region 3: I/O ports at 0374 [size=1]
	Region 4: I/O ports at f800 [size=16]
	Capabilities: <access denied>
	Kernel driver in use: ata_piix

00:1f.3 SMBus [0c05]: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller [8086:266a] (rev 04)
	Control: I/O+ Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Interrupt: pin B routed to IRQ 19
	Region 4: I/O ports at 0500 [size=32]
	Kernel driver in use: i801_smbus

01:00.0 Ethernet controller [0200]: Broadcom Corporation NetLink BCM5789 Gigabit Ethernet PCI Express [14e4:169d] (rev 11)
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:fd11]
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0, Cache Line Size: 32 bytes
	Interrupt: pin A routed to IRQ 16
	Region 0: Memory at dfdf0000 (64-bit, non-prefetchable) [size=64K]
	Expansion ROM at <ignored> [disabled]
	Capabilities: <access denied>
	Kernel driver in use: tg3

02:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller [10ec:8168] (rev 01)
	Subsystem: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller [10ec:8168]
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0, Cache Line Size: 32 bytes
	Interrupt: pin A routed to IRQ 26
	Region 0: I/O ports at be00 [size=256]
	Region 2: Memory at df9ff000 (64-bit, non-prefetchable) [size=4K]
	[virtual] Expansion ROM at df800000 [disabled] [size=128K]
	Capabilities: <access denied>
	Kernel driver in use: r8169

03:09.0 Multimedia audio controller [0401]: Creative Labs CA0106 Soundblaster [1102:0007]
	Subsystem: Holco Enterprise Co, Ltd/Shuttle Computer Device [1297:3041]
	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 32 (500ns min, 5000ns max)
	Interrupt: pin A routed to IRQ 17
	Region 0: I/O ports at df00 [size=32]
	Capabilities: <access denied>
	Kernel driver in use: CA0106

03:0a.0 FireWire (IEEE 1394) [0c00]: VIA Technologies, Inc. VT6306 Fire II IEEE 1394 OHCI Link Layer Controller [1106:3044] (rev 80) (prog-if 10 [OHCI])
	Subsystem: VIA Technologies, Inc. VT6306 Fire II IEEE 1394 OHCI Link Layer Controller [1106:3044]
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping+ SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 32 (8000ns max), Cache Line Size: 32 bytes
	Interrupt: pin A routed to IRQ 18
	Region 0: Memory at dfcff000 (32-bit, non-prefetchable) [size=2K]
	Region 1: I/O ports at de00 [size=128]
	Capabilities: <access denied>
	Kernel driver in use: firewire_ohci


** USB devices:
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 002: ID 04e6:5115 SCM Microsystems, Inc. SCR335 SmartCard Reader
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub


-- System Information:
Debian Release: squeeze/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (500, 'stable'), (1, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.31-1-686-bigmem (SMP w/1 CPU core)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages linux-image-2.6.31-1-686-bigmem depends on:
ii  debconf [debconf-2.0]         1.5.28     Debian configuration management sy
ii  initramfs-tools [linux-initra 0.93.4     tools for generating an initramfs
ii  module-init-tools             3.11-1     tools for managing Linux kernel mo

Versions of packages linux-image-2.6.31-1-686-bigmem recommends:
ii  firmware-linux-free           2.6.31-2   Binary firmware for various driver
ii  libc6-i686                    2.10.1-7   GNU C Library: Shared libraries [i

Versions of packages linux-image-2.6.31-1-686-bigmem suggests:
ii  grub                          0.97-59    GRand Unified Bootloader (dummy pa
pn  linux-doc-2.6.31              <none>     (no description available)

Versions of packages linux-image-2.6.31-1-686-bigmem is related to:
pn  firmware-bnx2                 <none>     (no description available)
pn  firmware-bnx2x                <none>     (no description available)
pn  firmware-ipw2x00              <none>     (no description available)
pn  firmware-ivtv                 <none>     (no description available)
pn  firmware-iwlwifi              <none>     (no description available)
ii  firmware-linux                0.18       Binary firmware for various driver
pn  firmware-linux-nonfree        <none>     (no description available)
pn  firmware-qlogic               <none>     (no description available)
pn  firmware-ralink               <none>     (no description available)

-- debconf information:
  shared/kernel-image/really-run-bootloader: true
  linux-image-2.6.31-1-686-bigmem/postinst/bootloader-error-2.6.31-1-686-bigmem:
  linux-image-2.6.31-1-686-bigmem/postinst/depmod-error-initrd-2.6.31-1-686-bigmem: false
  linux-image-2.6.31-1-686-bigmem/prerm/removing-running-kernel-2.6.31-1-686-bigmem: true
  linux-image-2.6.31-1-686-bigmem/postinst/bootloader-test-error-2.6.31-1-686-bigmem:
  linux-image-2.6.31-1-686-bigmem/postinst/missing-firmware-2.6.31-1-686-bigmem:
  linux-image-2.6.31-1-686-bigmem/prerm/would-invalidate-boot-loader-2.6.31-1-686-bigmem: true


-- System Information:
Debian Release: squeeze/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (500, 'stable'), (1, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.30-2-686 (SMP w/1 CPU core)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages linux-image-2.6.31-1-686-bigmem depends on:
ii  debconf [debconf-2.0]         1.5.28     Debian configuration management sy
ii  initramfs-tools [linux-initra 0.93.4     tools for generating an initramfs
ii  module-init-tools             3.11-1     tools for managing Linux kernel mo

Versions of packages linux-image-2.6.31-1-686-bigmem recommends:
ii  firmware-linux-free           2.6.31-2   Binary firmware for various driver
ii  libc6-i686                    2.10.1-7   GNU C Library: Shared libraries [i

Versions of packages linux-image-2.6.31-1-686-bigmem suggests:
ii  grub                          0.97-59    GRand Unified Bootloader (dummy pa
pn  linux-doc-2.6.31              <none>     (no description available)

Versions of packages linux-image-2.6.31-1-686-bigmem is related to:
pn  firmware-bnx2                 <none>     (no description available)
pn  firmware-bnx2x                <none>     (no description available)
pn  firmware-ipw2x00              <none>     (no description available)
pn  firmware-ivtv                 <none>     (no description available)
pn  firmware-iwlwifi              <none>     (no description available)
ii  firmware-linux                0.18       Binary firmware for various driver
pn  firmware-linux-nonfree        <none>     (no description available)
pn  firmware-qlogic               <none>     (no description available)
pn  firmware-ralink               <none>     (no description available)



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* Re: [PATCH 17/11]Optimize the upload speed for PPP connection.
From: Jarek Poplawski @ 2009-11-18  7:51 UTC (permalink / raw)
  To: William Allen Simpson; +Cc: David Miller, huananhu, netdev, linux-kernel
In-Reply-To: <4B03806F.7010803@gmail.com>

On 18-11-2009 06:04, William Allen Simpson wrote:
> David Miller wrote:
>> From: William Allen Simpson <william.allen.simpson@gmail.com>
>> Date: Tue, 17 Nov 2009 05:20:09 -0500
>>
>>> What David may have meant, had he followed
>>> Documentation/ManagementStyle or had any project management skills
>>> what-so-ever, is that you need to follow
>>> Documentation/SubmittingPatches more carefully.
>> Are personal attacks on me really necessary?
>>
> Actually, ironic sarcasm (juxtaposition) is a form of humor, fairly
> popular on such venues as "The Daily Show". :-)

Actually, it didn't work. But AFAIK adding "...NOT!" can make the
difference ;-)

Jarek P.

^ permalink raw reply

* Re: [PATCH 1/2 net-next-2.6] net: add dev_txq_stats_fold() helper
From: David Miller @ 2009-11-18  7:52 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <4B015573.9090502@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 16 Nov 2009 14:36:51 +0100

> Some drivers ndo_get_stats() method need to perform txqueue stats folding.
> 
> Move folding from dev_get_stats() to a new dev_txq_stats_fold() function
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH 2/2 net-next-2.6] vlan: Precise RX stats accounting
From: David Miller @ 2009-11-18  7:53 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <4B02B8D5.8040402@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 17 Nov 2009 15:53:09 +0100

> Given that vlan_setup(struct net_device *) is void and cannot
> return error status, unless using a global variable (ugly),
> or changing all setup() prototypes (oh well...)
> 
> One possibility is to perform the allocation in vlan_dev_init()
> (called from register_netdevice()), and freeing it in vlan_dev_uninit().

That looks fine.

> [PATCH net-next-2.6 take2] vlan: Precise RX stats accounting
 ...
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next-2.6] macvlan: Precise RX stats accounting
From: David Miller @ 2009-11-18  7:53 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, kaber
In-Reply-To: <4B02F13D.1060903@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 17 Nov 2009 19:53:49 +0100

> [PATCH net-next-2.6] macvlan: Precise RX stats accounting
 ...
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Also applied, thanks Eric.

^ permalink raw reply

* Patches for hso driver
From: Martin Schiller @ 2009-11-18  7:35 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 1603 bytes --]

Hi,

I've found some problems in the hso driver for Option HSxPA devices.

The first and most important are 2 memory leaks in the buffer cleanup routines.
Have a look at the "hso-memleak.patch" file to see what I mean.

ATTENTION:
-------------------------------------------------------------------------------------
kmemleak still finds 1 remaining leak, but i can't find it:

unreferenced object 0xce461130 (size 32):
 comm "khubd", pid 1105, jiffies 17464
 backtrace:
   [<c10745b6>] create_object+0xe6/0x210
   [<c10747d7>] kmemleak_alloc+0x27/0x60
   [<c1071b0d>] kmem_cache_alloc+0xcd/0x120
   [<d0ba29a7>] hso_create_net_device+0x207/0x420 [hso]
   [<d0ba30c7>] hso_probe+0x417/0x690 [hso]
   [<d0998103>] usb_probe_interface+0x83/0x170 [usbcore]
   [<c113f9e2>] driver_probe_device+0x62/0x140
   [<c113fb81>] __device_attach+0x41/0x50
   [<c113f098>] bus_for_each_drv+0x48/0x70
   [<c113fc2d>] device_attach+0x6d/0x80
   [<c113eeed>] bus_probe_device+0x1d/0x40
   [<c113da66>] device_add+0x436/0x4f0
   [<d0997654>] usb_set_configuration+0x424/0x5c0 [usbcore]
   [<d099e68e>] generic_probe+0x2e/0xa0 [usbcore]
   [<d09979cf>] usb_probe_device+0x1f/0x30 [usbcore]
   [<c113f9e2>] driver_probe_device+0x62/0x140

Maybe anyone else have an idea for that.
-------------------------------------------------------------------------------------

The second patch "hso-disable_net.patch" stops the useless creation of an serial
ttyHS<x> for the Network Port, when disable_net=1 is set. By that, the order
of the ttyHS<x> is always the same, regardless if disable_net is set or not.

Best Regards,
Martin

[-- Attachment #2: hso-memleak.patch --]
[-- Type: application/octet-stream, Size: 1255 bytes --]

Subject: memory leak in hso driver

This patches fixes 2 memory leaks in the hso driver.
The first problem is, that the tx_buffer of a serial device will never be freed.
The second one is, that hso_net is also freed by free_netdev(). So, the rx urbs
and buffers must be freed before free_netdev().

Signed-off-by: Martin Schiller <mschiller@tdt.de>

diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index b862e66..6865f3f 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2312,6 +2312,7 @@ static void hso_serial_common_free(struct hso_serial *serial)
 	/* unlink and free TX URB */
 	usb_free_urb(serial->tx_urb);
 	kfree(serial->tx_data);
+	kfree(serial->tx_buffer);
 }
 
 static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
@@ -2438,7 +2439,6 @@ static void hso_free_net_device(struct hso_device *hso_dev)
 
 	if (hso_net->net) {
 		unregister_netdev(hso_net->net);
-		free_netdev(hso_net->net);
 	}
 
 	/* start freeing */
@@ -2451,6 +2451,10 @@ static void hso_free_net_device(struct hso_device *hso_dev)
 	kfree(hso_net->mux_bulk_tx_buf);
 	hso_net->mux_bulk_tx_buf = NULL;
 
+	if (hso_net->net) {
+		free_netdev(hso_net->net);
+	}
+
 	kfree(hso_dev);
 }
 

[-- Attachment #3: hso-disable_net.patch --]
[-- Type: application/octet-stream, Size: 942 bytes --]

Subject: Fix interface order when disabled_net=1 in hso driver

This patch stops the useless creation of an serial ttyHS<x> for the
Network Port, when disable_net=1 is set. By that, the order of the
ttyHS<x> is always the same, regardless if disable_net is set or not.

Signed-off-by: Martin Schiller <mschiller@tdt.de>

diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index a11dfd0..e9210b7 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2993,9 +2993,10 @@ static int hso_probe(struct usb_interface *interface,
 
 	case HSO_INTF_BULK:
 		/* It's a regular bulk interface */
-		if (((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK)
-		    && !disable_net)
+		if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) {
+		    if (!disable_net)
 			hso_dev = hso_create_net_device(interface, port_spec);
+		}
 		else
 			hso_dev =
 			    hso_create_bulk_serial_device(interface, port_spec);

^ permalink raw reply related

* Re: [PATCH 0/3] macvlan: add vepa and bridge mode
From: Mark Smith @ 2009-11-18  9:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, netdev, David Miller, Stephen Hemminger, Herbert Xu,
	Patrick McHardy, Patrick Mullaney, Eric W. Biederman,
	Edge Virtual Bridging, Anna Fischer, bridge, virtualization,
	Jens Osterkamp, Gerhard Stenzel, Arnd Bergmann
In-Reply-To: <1258497551-25959-1-git-send-email-arnd@arndb.de>

On Tue, 17 Nov 2009 22:39:07 +0000
Arnd Bergmann <arnd@arndb.de> wrote:

> This is based on an earlier patch from Eric Biederman adding
> forwarding between macvlans. I extended his approach to
> allow the administrator to choose the mode for each macvlan,
> and to implement a functional VEPA between macvlan.
> 
> Still missing from this is support for communication between
> the lower device that the macvlans are based on. This would
> be extremely useful but as others have found out before me
> requires significant changes not only to macvlan but also
> to the common transmit path.

If this means that the "children" macvlans can't communicate with their
"parent" interface as though they were all attached to the same virtual
ethernet segment, I think that is a reasonable limitation. On other
networking equipment I've used, the moment "sub-interfaces"
are created, their parent interface can't be used for any
communications, only for setting link related parameters e.g. for
ethernet interfaces, speed and duplex etc.

> 
> I've seen one panic during testing this that I still need
> to track down, but it generally does what is advertised.
> I've tested VEPA operation with the hairpin support
> added to the bridge driver by Anna Fischer.
> 
> My current plan is to submit this for inclusion in 2.6.33
> when people are happy with it and I tracked down any
> remaining bugs, and possibly to do the communication with
> the lower device one release later.
> 
> 	Arnd <><
> 
> ---
> 
> Arnd Bergmann (3):
>   macvlan: implement VEPA and private mode
>   macvlan: export macvlan mode through netlink
>   iplink: add macvlan options for bridge mode
> 
> Eric Biederman (1):
>   macvlan: Reflect macvlan packets meant for other macvlan devices
> 
>  linux/drivers/net/macvlan.c   |  170 +++++++++++++++++++++++++++++++++-----
>  linux/include/linux/if_link.h |   15 +++
>  2 files changed, 161 insertions(+), 24 deletions(-)
> 
>  iproute2/include/linux/if_link.h |   15 +++
>  iproute2/ip/Makefile             |    3 +-
>  iproute2/ip/iplink_macvlan.c     |   93 ++++++++++++++++++
>  3 files changed, 110 insertions(+), 1 deletions(-)
>  create mode 100644 ip/iplink_macvlan.c
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] Documentation, clarify tuntap IPX example.
From: andrew hendry @ 2009-11-18  9:03 UTC (permalink / raw)
  To: Max Krasnyansky; +Cc: netdev@vger.kernel.org, linux-kernel
In-Reply-To: <4B038BB7.2050902@qualcomm.com>

Hi Max,

Thanks. TUNSETLINK looks like exactly what I need.
I'll have to have a closer look at kernel x.25 next, i don't think it
likes the tunx25 going away with routes still too it.

deb32:~# cat /proc/net/x25/route
Address          Digits  Device
000000000000000  0       @�\x18��
                              \x18�@�\x1d

[  662.425648] BUG: unable to handle kernel NULL pointer dereference at 00000017
[  662.426291] IP: [<c10b5908>] dup_fd+0x21f/0x2fa
[  662.427849] *pde = 00000000
[  662.428028] Oops: 0002 [#1] SMP
[  662.428028] last sysfs file: /sys/class/net/lo/operstate
[  662.428028] Modules linked in: x25 tun ipv6 loop ac button
parport_pc parport snd_pcm snd_timer serio_raw psmouse snd soundcore
snd_page_alloc pcspkr i2c_piix4 i2c_core evdev ext3 jbd mbcache
ide_cd_mod cdrom ide_gd_mod ata_generic ata_piix libata scsi_mod
ide_pci_generic piix floppy pcnet32 mii ide_core thermal fan
thermal_sys [last unloaded: tun]
[  662.428028]
[  662.428028] Pid: 12252, comm: net.agent Not tainted (2.6.31.6 #1) VirtualBox
[  662.428028] EIP: 0060:[<c10b5908>] EFLAGS: 00010286 CPU: 0
[  662.428028] EIP is at dup_fd+0x21f/0x2fa
[  662.428028] EAX: 00000017 EBX: ce5262a0 ECX: 00000220 EDX: ffffffff
[  662.428028] ESI: 00000088 EDI: ce41e400 EBP: 00000100 ESP: c2849eec
[  662.428028]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0069
[  662.428028] Process net.agent (pid: 12252, ti=c2848000
task=ce9d51c0 task.ti=c2848000)
[  662.428028] Stack:
[  662.428028]  00000202 00000020 00000008 cf466cc0 cf466cc4 cf4667c0
ce41e400 00000078
[  662.428028] <0> ce5262c0 cf466d00 cf4667c8 ce02bc00 ce18db60
00000000 00000000 ce9d51c0
[  662.428028] <0> c102d03b 080a8120 cf649668 c2849fb4 bfe05a6c
01200011 ce18dca4 fffffff4
[  662.428028] Call Trace:
[  662.428028]  [<c102d03b>] ? copy_process+0x469/0xf96
[  662.428028]  [<c102dc7d>] ? do_fork+0x115/0x282
[  662.428028]  [<c10a4965>] ? vfs_llseek+0x30/0x34
[  662.428028]  [<c1001d8e>] ? sys_clone+0x21/0x27
[  662.428028]  [<c10030c9>] ? syscall_call+0x7/0xb
[  662.428028] Code: 4c 24 08 8b 70 08 f3 a5 8b 4c 24 04 83 e1 03 74
02 f3 a4 31 c9 31 f6 89 6c 24 1c eb 29 8b 7c 24 18 8b 14 0f 85 d2 74
09 8d 42 18 <3e> ff 42 18 eb 06 8b 43 0c 0f b3 30 8b 44 24 2c 46 89 14
08 83
[  662.428028] EIP: [<c10b5908>] dup_fd+0x21f/0x2fa SS:ESP 0069:c2849eec
[  662.428028] CR2: 0000000000000017
[  662.452941] ---[ end trace aab1610cb3ca8b89 ]---

Message from syslogd@deb32 at Nov 19 06:58:56 ...
 kernel:[  904.324109] unregister_netdevice: waiting for xotdtun to
become free. Usage count = -3


Andrew

On Wed, Nov 18, 2009 at 4:52 PM, Max Krasnyansky <maxk@qualcomm.com> wrote:
> andrew hendry wrote:
>> Hi Max,
>>
>> I started looking through the documentation because im looking to use
>> tun for X.25 over TCP. The IPX example sounded similar but i couldn't
>> get it to work as I was expecting. Looking for a hint in the right
>> direction.
> Ah, X25 is different.
>
>> There is an old non-mainline patch called x25tap (clone of obsolete
>> ethertap). I'm hoping to replace x25tap with tun.
>>
>> The old x25tap creates a device like:
>> x25tap0   Link encap:generic X.25  HWaddr
>>           UP BROADCAST RUNNING NOARP MULTICAST  MTU:1024  Metric:1
>>           RX packets:3040785 errors:0 dropped:0 overruns:0 frame:0
>>           TX packets:2895530 errors:0 dropped:0 overruns:0 carrier:0
>>           collisions:0 txqueuelen:10
>>           RX bytes:138787339 (132.3 Mb)  TX bytes:91395983 (87.1 Mb)
>> When the x25tap is loaded it has dev->type = ARPHRD_X25, after which
>> x.25 routing and AF_X25 sockets can be created.  Along with an XoT
>> userspace program which handles some basic headers and TCP port 1998
>> it works well.
>>
>> If using tun, how does something get registered to handle protocol AF_X25?
>>
>
> I've never tried this personally so ... :). But I just glanced over net/ax25
> and drivers/wan/ax25 and it looks TUNSETLINK might work for you.
> In other words you want to allocate TUN device (not TAP) and then call
> TUNSETLINK with ARPHRD_X25. Seems like you'll get exactly what you need.
>
> Max
>
>
>> Regards,
>> Andrew.
>>
>> On Wed, Nov 18, 2009 at 12:40 PM, Max Krasnyansky <maxk@qualcomm.com> wrote:
>>> On 11/17/2009 05:30 PM, andrew hendry wrote:
>>>> Can the TUNSETIFF ioctl change a tap's protocol to IPX as the
>>>> documentation suggests?
>>>> I think tun.c would need IFF_IPX_TAP added for it to work as described?
>>>> Otherwise tap can only be ptp or ethernet, and there is no way to
>>>> route or use AF_IPX.
>>> TAP is an Ethernet device. No special handling is required for IPX or for
>>> that matter any other protocol. Example seems fine too.
>>>
>>> Max
>>>
>>>> Signed-off-by: Andrew Hendry<andrew.hendry@gmail.com>
>>>>
>>>> --- a/Documentation/networking/tuntap.txt       2009-11-11
>>>> 14:03:22.676167648 +1100
>>>> +++ b/Documentation/networking/tuntap.txt       2009-11-18
>>>> 11:34:18.106647029 +1100
>>>> @@ -127,12 +127,14 @@ Ethernet device, which instead of receiv
>>>>  media, receives them from user space program and instead of sending
>>>>  packets via physical media sends them to the user space program.
>>>>
>>>> -Let's say that you configured IPX on the tap0, then whenever
>>>> -the kernel sends an IPX packet to tap0, it is passed to the application
>>>> -(VTun for example). The application encrypts, compresses and sends it to
>>>> -the other side over TCP or UDP. The application on the other side
>>>> decompresses
>>>> -and decrypts the data received and writes the packet to the TAP device,
>>>> -the kernel handles the packet like it came from real physical device.
>>>> +Let's say for the purpose of example, IPX support was added to tuntap.
>>>> +Then whenever the kernel routes an IPX packet to tap0, it is passed to
>>>> the
>>>> +application reading the file descriptor from /dev/net/tun (VTun for
>>>> example).
>>>> +The application encrypts, compresses and sends it to the other side over
>>>> TCP
>>>> +or UDP. The application on the other side decompresses and decrypts the
>>>> data
>>>> +received and writes the packet to the TAP device, the remote kernel
>>>> handles
>>>> +the packet like it came from real physical device. The IPX applications
>>>> are
>>>> +able to communicate as if there was a real IPX network.
>>>>
>>>>  4. What is the difference between TUN driver and TAP driver?
>>>>  TUN works with IP frames. TAP works with Ethernet frames.
>>>
>
>

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox