* Re: [PATCH v3] net/fsl_pq_mdio: Document supported compatibles
From: David Miller @ 2015-02-04 0:11 UTC (permalink / raw)
To: Emilian.Medve-eDlz3WWmN0ll57MIdRCFDg
Cc: scottwood-eDlz3WWmN0ll57MIdRCFDg,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
Kanetkar.Shruti-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1422827911-32629-1-git-send-email-Emilian.Medve-eDlz3WWmN0ll57MIdRCFDg@public.gmane.org>
From: Emil Medve <Emilian.Medve-eDlz3WWmN0ll57MIdRCFDg@public.gmane.org>
Date: Sun, 1 Feb 2015 15:58:31 -0600
> From: Shruti Kanetkar <Kanetkar.Shruti-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> The device tree binding(s) document has fallen out of sync with the
> driver code. Update the list of supported devices to reflect current
> driver capabilities
>
> Change-Id: I440d8de2ee2d9c3b7b23e69b3da851cab18a4c9a
> Signed-off-by: Shruti Kanetkar <Kanetkar.Shruti-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Emil Medve <Emilian.Medve-eDlz3WWmN0ll57MIdRCFDg@public.gmane.org>
Applied to net-next, thanks.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" 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: [PATCH] net: sched: One function call less in em_meta_change() after error detection
From: David Miller @ 2015-02-04 0:10 UTC (permalink / raw)
To: elfring; +Cc: jhs, netdev, linux-kernel, kernel-janitors, julia.lawall
In-Reply-To: <54CD042E.6030606@users.sourceforge.net>
From: SF Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 31 Jan 2015 17:34:54 +0100
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Sat, 31 Jan 2015 17:18:48 +0100
>
> The meta_delete() function could be called in four cases by the
> em_meta_change() function during error handling even if the passed
> variable "meta" contained still a null pointer.
>
> * This implementation detail could be improved by adjustments for jump labels.
>
> * Let us return immediately after the first failed function call according to
> the current Linux coding style convention.
>
> * Let us delete also unnecessary checks for the variables "err" and
> "meta" there.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
I kind of like the way the code is now, branching to the end of the function
even when cleanups are not necessary.
Inter-function return statements make code harder to audit, for locking
errors, resource leaks, etc.
^ permalink raw reply
* Re: [RFC 0/3] Slab allocator array operations
From: Jesper Dangaard Brouer @ 2015-02-03 23:19 UTC (permalink / raw)
To: Christoph Lameter
Cc: Andrew Morton, linux-kernel, linux-mm, penberg, brouer,
netdev@vger.kernel.org, Joonsoo Kim
In-Reply-To: <alpine.DEB.2.11.1501231827330.10083@gentwo.org>
On Fri, 23 Jan 2015 18:28:00 -0600 (CST)
Christoph Lameter <cl@linux.com> wrote:
> On Fri, 23 Jan 2015, Andrew Morton wrote:
>
> > On Fri, 23 Jan 2015 15:37:27 -0600 Christoph Lameter <cl@linux.com> wrote:
> >
> > > Attached a series of 3 patches to implement functionality to allocate
> > > arrays of pointers to slab objects. This can be used by the slab
> > > allocators to offer more optimized allocation and free paths.
> >
> > What's the driver for this? The networking people, I think? If so,
> > some discussion about that would be useful: who is involved, why they
> > have this need, who are the people we need to bug to get it tested,
> > whether this implementation is found adequate, etc.
Yes, networking people like me ;-)
I promised Christoph that I will performance benchmark this. I'll start
by writing/performing some micro benchmarks, but it first starts to get
really interesting once we plug it into e.g. the networking stack, as
effects as instruction-cache misses due to code size starts to play a
role.
>
> Jesper and I gave a talk at LCA about this. LWN has an article on it.
LWN: Improving Linux networking performance
- http://lwn.net/Articles/629155/
- YouTube: https://www.youtube.com/watch?v=3XG9-X777Jo
LWN: Toward a more efficient slab allocator
- http://lwn.net/Articles/629152/
- YouTube: https://www.youtube.com/watch?v=s0lZzP1jOzI
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Sr. Network Kernel Developer at Red Hat
Author of http://www.iptv-analyzer.org
LinkedIn: http://www.linkedin.com/in/brouer
--
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
* Re: Per-connection tcp_retries2 and RFC 1122 compliance
From: Willy Tarreau @ 2015-02-03 23:15 UTC (permalink / raw)
To: David Miller; +Cc: John Eckersberg, Neal Cardwell, Yuchung Cheng, Netdev
In-Reply-To: <874mr227bx.fsf@redhat.com>
Hi David,
do you think we could have the fix below queued for -stable ? It
appears to fix some quite annoying issues that are not easy to
debug.
Thanks,
Willy
On Tue, Feb 03, 2015 at 01:11:46PM -0500, John Eckersberg wrote:
> Neal Cardwell <ncardwell@google.com> writes:
> > I believe the functionality you are looking for is the
> > TCP_USER_TIMEOUT socket option:
>
> I had tried that previously, and it did not help my case. The reason
> why is that I was using a downstream kernel (Fedora 21, 3.17.8 in this
> case) and it was missing this commit that went into 3.18:
>
> commit b248230c34970a6c1c17c591d63b464e8d2cfc33
> Author: Yuchung Cheng <ycheng@google.com>
> Date: Mon Sep 29 13:20:38 2014 -0700
>
> tcp: abort orphan sockets stalling on zero window probes
>
> Currently we have two different policies for orphan sockets
> that repeatedly stall on zero window ACKs. If a socket gets
> a zero window ACK when it is transmitting data, the RTO is
> used to probe the window. The socket is aborted after roughly
> tcp_orphan_retries() retries (as in tcp_write_timeout()).
>
> But if the socket was idle when it received the zero window ACK,
> and later wants to send more data, we use the probe timer to
> probe the window. If the receiver always returns zero window ACKs,
> icsk_probes keeps getting reset in tcp_ack() and the orphan socket
> can stall forever until the system reaches the orphan limit (as
> commented in tcp_probe_timer()). This opens up a simple attack
> to create lots of hanging orphan sockets to burn the memory
> and the CPU, as demonstrated in the recent netdev post "TCP
> connection will hang in FIN_WAIT1 after closing if zero window is
> advertised." http://www.spinics.net/lists/netdev/msg296539.html
>
> This patch follows the design in RTO-based probe: we abort an orphan
> socket stalling on zero window when the probe timer reaches both
> the maximum backoff and the maximum RTO. For example, an 100ms RTT
> connection will timeout after roughly 153 seconds (0.3 + 0.6 +
> .... + 76.8) if the receiver keeps the window shut. If the orphan
> socket passes this check, but the system already has too many orphans
> (as in tcp_out_of_resources()), we still abort it but we'll also
> send an RST packet as the connection may still be active.
>
> In addition, we change TCP_USER_TIMEOUT to cover (life or dead)
> sockets stalled on zero-window probes. This changes the semantics
> of TCP_USER_TIMEOUT slightly because it previously only applies
> when the socket has pending transmission.
>
> The key part being that last paragraph about stalled zero-window
> probes. Here's the specific use case where I'm hitting this:
>
> (1) Establish a TCP connection bound to a given IP address
> (2) Remove IP address from host
> (3) Write to socket
>
> This gets kicked back by the IP layer as non-routable, which triggers
> the same behavior as the zero-window probes.
>
> The good news is, I confirmed this is working as expected when I tested
> on 3.19.0-rc7.
>
> Thanks for the pointer, I'll go take my harassment to the relevant
> downstream folks.
> --
> 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 v2 17/18] vhost: don't bother copying iovecs in handle_rx(), kill memcpy_toiovecend()
From: Al Viro @ 2015-02-03 22:13 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: David Miller, netdev, kvm
In-Reply-To: <20150203152154.GA9072@redhat.com>
On Tue, Feb 03, 2015 at 04:21:54PM +0100, Michael S. Tsirkin wrote:
> > Hmm having second thoughts here.
> > Will this modify the iov in vq->iov?
> > If yes, how will recvmsg fill it?
>
> OK that was just me misunderstanding what the
> function does. As it doesn't modify the iovec itself,
> I think there's no issue, my ack stands.
That, BTW, was the point of switching ->sendmsg() and ->recvmsg() to
iov_iter primitives - not only do memcpy_toiovec() et.al. change the
iovec, the way it's done was protocol-dependent, up to and including
the things like "have sent 60 caller-supplied bytes, iovec modified
with only 6 bytes consumed". What's worse, on TCP sendmsg we usually
left iovec unchanged, but sometimes it got drained. Granted, that
happened only after setsockopt() playing caller with TCP_REPAIR (i.e.
checkpoint/restart stuff), but...
^ permalink raw reply
* Re: [PATCH net-next v2 1/2] pkt_sched: fq: avoid artificial bursts for clocked flows
From: Eric Dumazet @ 2015-02-03 22:06 UTC (permalink / raw)
To: Kenneth Klette Jonassen; +Cc: netdev
In-Reply-To: <1422992932-9893-1-git-send-email-kennetkl@ifi.uio.no>
On Tue, 2015-02-03 at 20:48 +0100, Kenneth Klette Jonassen wrote:
>
> - if (tb[TCA_FQ_INITIAL_QUANTUM])
> - q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
> + if (tb[TCA_FQ_INITIAL_QUANTUM]) {
> + u32 initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
> +
> + if (initial_quantum > q->quantum)
> + q->initial_quantum = initial_quantum - q->quantum;
> + else
> + q->initial_quantum = 0;
> + }
Please do not mix patches. This part already have been Acked by me.
Quite frankly I do not like this patch.
There is no rush, and you touch some critical infrastructure for us.
Always CC me on any fq change, do not assume I catch all netdev
messages.
^ permalink raw reply
* Re: [PATCH net-next 1/2] pkt_sched: fq: avoid artificial bursts for clocked flows
From: Eric Dumazet @ 2015-02-03 22:05 UTC (permalink / raw)
To: Kenneth Klette Jonassen; +Cc: netdev@vger.kernel.org
In-Reply-To: <F3E6220B-F2F4-4985-AECE-9EB9AA7D1C20@ifi.uio.no>
On Tue, 2015-02-03 at 19:51 +0000, Kenneth Klette Jonassen wrote:
> >
> > ACK packets are not paced, ever.
> >
> > This patch also allows skb->ooo_okay being set even if the DATA packet
> > immediately follows a train of ACK packets (as in typical RPC patterns)
> >
> Could you please expand on this?
>
If you followed netdev recently, you might have noticed I am currently
upstreaming patches that we tested more than 6 months at Google.
I am doing this in a non bursty way to ease David Miller work ;)
A hint is given in commit b2532eb9abd88384a
("tcp: fix ooo_okay setting vs Small Queues")
* TODO: Ideally, in-flight pure ACK packets should not matter here.
* One way to get this would be to set skb->truesize = 2 on them.
Thanks
^ permalink raw reply
* [PATCH v3 net 3/3] Revert "drivers/net: Disable UFO through virtio"
From: Vladislav Yasevich @ 2015-02-03 21:36 UTC (permalink / raw)
To: netdev; +Cc: virtualization, Vladislav Yasevich
In-Reply-To: <1422999377-18777-1-git-send-email-vyasevic@redhat.com>
This reverts commit 3d0ad09412ffe00c9afa201d01effdb6023d09b4.
Now that GSO functionality can correctly track if the fragment
id has been selected and select a fragment id if necessary,
we can re-enable UFO on tap/macvap and virtio devices.
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
---
drivers/net/macvtap.c | 13 ++++++++-----
drivers/net/tun.c | 19 ++++++++-----------
drivers/net/virtio_net.c | 24 ++++++++++--------------
3 files changed, 26 insertions(+), 30 deletions(-)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 0b86e46..919f4fc 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -80,7 +80,7 @@ static struct cdev macvtap_cdev;
static const struct proto_ops macvtap_socket_ops;
#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
- NETIF_F_TSO6)
+ NETIF_F_TSO6 | NETIF_F_UFO)
#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
@@ -585,8 +585,6 @@ static int macvtap_skb_from_vnet_hdr(struct macvtap_queue *q,
gso_type = SKB_GSO_TCPV6;
break;
case VIRTIO_NET_HDR_GSO_UDP:
- pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n",
- current->comm);
gso_type = SKB_GSO_UDP;
break;
default:
@@ -633,6 +631,8 @@ static void macvtap_skb_to_vnet_hdr(struct macvtap_queue *q,
vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
else if (sinfo->gso_type & SKB_GSO_TCPV6)
vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ else if (sinfo->gso_type & SKB_GSO_UDP)
+ vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
else
BUG();
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
@@ -962,6 +962,9 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
if (arg & TUN_F_TSO6)
feature_mask |= NETIF_F_TSO6;
}
+
+ if (arg & TUN_F_UFO)
+ feature_mask |= NETIF_F_UFO;
}
/* tun/tap driver inverts the usage for TSO offloads, where
@@ -972,7 +975,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
* When user space turns off TSO, we turn off GSO/LRO so that
* user-space will not receive TSO frames.
*/
- if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6))
+ if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO))
features |= RX_OFFLOADS;
else
features &= ~RX_OFFLOADS;
@@ -1087,7 +1090,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
case TUNSETOFFLOAD:
/* let the user check for future flags */
if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
- TUN_F_TSO_ECN))
+ TUN_F_TSO_ECN | TUN_F_UFO))
return -EINVAL;
rtnl_lock();
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 5ca42b7..10f9e40 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -186,7 +186,7 @@ struct tun_struct {
struct net_device *dev;
netdev_features_t set_features;
#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
- NETIF_F_TSO6)
+ NETIF_F_TSO6|NETIF_F_UFO)
int vnet_hdr_sz;
int sndbuf;
@@ -1176,18 +1176,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
case VIRTIO_NET_HDR_GSO_UDP:
- {
- static bool warned;
-
- if (!warned) {
- warned = true;
- netdev_warn(tun->dev,
- "%s: using disabled UFO feature; please fix this program\n",
- current->comm);
- }
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
break;
- }
default:
tun->dev->stats.rx_frame_errors++;
kfree_skb(skb);
@@ -1294,6 +1284,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
else if (sinfo->gso_type & SKB_GSO_TCPV6)
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ else if (sinfo->gso_type & SKB_GSO_UDP)
+ gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
else {
pr_err("unexpected GSO type: "
"0x%x, gso_size %d, hdr_len %d\n",
@@ -1742,6 +1734,11 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
features |= NETIF_F_TSO6;
arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
}
+
+ if (arg & TUN_F_UFO) {
+ features |= NETIF_F_UFO;
+ arg &= ~TUN_F_UFO;
+ }
}
/* This gives the user a way to test for new features in future by
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 5ca9771..059fdf1 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -490,17 +490,8 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
break;
case VIRTIO_NET_HDR_GSO_UDP:
- {
- static bool warned;
-
- if (!warned) {
- warned = true;
- netdev_warn(dev,
- "host using disabled UFO feature; please fix it\n");
- }
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
break;
- }
case VIRTIO_NET_HDR_GSO_TCPV6:
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
@@ -888,6 +879,8 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
+ hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
else
BUG();
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
@@ -1748,7 +1741,7 @@ static int virtnet_probe(struct virtio_device *vdev)
dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
- dev->hw_features |= NETIF_F_TSO
+ dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO
| NETIF_F_TSO_ECN | NETIF_F_TSO6;
}
/* Individual feature bits: what can host handle? */
@@ -1758,9 +1751,11 @@ static int virtnet_probe(struct virtio_device *vdev)
dev->hw_features |= NETIF_F_TSO6;
if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
dev->hw_features |= NETIF_F_TSO_ECN;
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
+ dev->hw_features |= NETIF_F_UFO;
if (gso)
- dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
+ dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO);
/* (!csum && gso) case will be fixed by register_netdev() */
}
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
@@ -1798,7 +1793,8 @@ static int virtnet_probe(struct virtio_device *vdev)
/* If we can receive ANY GSO packets, we must allocate large ones. */
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
- virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
+ virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) ||
+ virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO))
vi->big_packets = true;
if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
@@ -1994,9 +1990,9 @@ static struct virtio_device_id id_table[] = {
static unsigned int features[] = {
VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM,
VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
- VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6,
+ VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
- VIRTIO_NET_F_GUEST_ECN,
+ VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
--
1.9.3
^ permalink raw reply related
* [PATCH v3 net 2/3] Revert "drivers/net, ipv6: Select IPv6 fragment idents for virtio UFO packets"
From: Vladislav Yasevich @ 2015-02-03 21:36 UTC (permalink / raw)
To: netdev; +Cc: virtualization, Vladislav Yasevich
In-Reply-To: <1422999377-18777-1-git-send-email-vyasevic@redhat.com>
This reverts commit 5188cd44c55db3e92cd9e77a40b5baa7ed4340f7.
Now that GSO layer can track if fragment id has been selected
and can allocate one if necessary, we don't need to do this in
tap and macvtap. This reverts most of the code and only keeps
the new ipv6 fragment id generation function that is still needed.
Fixes: 3d0ad09412ff (drivers/net: Disable UFO through virtio)
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
---
drivers/net/macvtap.c | 3 ---
drivers/net/tun.c | 6 +-----
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 7df2217..0b86e46 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -17,7 +17,6 @@
#include <linux/fs.h>
#include <linux/uio.h>
-#include <net/ipv6.h>
#include <net/net_namespace.h>
#include <net/rtnetlink.h>
#include <net/sock.h>
@@ -589,8 +588,6 @@ static int macvtap_skb_from_vnet_hdr(struct macvtap_queue *q,
pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n",
current->comm);
gso_type = SKB_GSO_UDP;
- if (skb->protocol == htons(ETH_P_IPV6))
- ipv6_proxy_select_ident(skb);
break;
default:
return -EINVAL;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 8c8dc16..5ca42b7 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -65,7 +65,6 @@
#include <linux/nsproxy.h>
#include <linux/virtio_net.h>
#include <linux/rcupdate.h>
-#include <net/ipv6.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
@@ -1167,8 +1166,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
break;
}
- skb_reset_network_header(skb);
-
if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
pr_debug("GSO!\n");
switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
@@ -1189,8 +1186,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
current->comm);
}
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
- if (skb->protocol == htons(ETH_P_IPV6))
- ipv6_proxy_select_ident(skb);
break;
}
default:
@@ -1221,6 +1216,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
}
+ skb_reset_network_header(skb);
skb_probe_transport_header(skb, 0);
rxhash = skb_get_hash(skb);
--
1.9.3
^ permalink raw reply related
* [PATCH v3 net 1/3] ipv6: Select fragment id during UFO segmentation if not set.
From: Vladislav Yasevich @ 2015-02-03 21:36 UTC (permalink / raw)
To: netdev; +Cc: virtualization, Vladislav Yasevich
In-Reply-To: <1422999377-18777-1-git-send-email-vyasevic@redhat.com>
If the IPv6 fragment id has not been set and we perform
fragmentation due to UFO, select a new fragment id.
We now consider a fragment id of 0 as unset and if id selection
process returns 0 (after all the pertrubations), we set it to
0x80000000, thus giving us ample space not to create collisions
with the next packet we may have to fragment.
When doing UFO integrity checking, we also select the
fragment id if it has not be set yet. This is stored into
the skb_shinfo() thus allowing UFO to function correclty.
This patch also removes duplicate fragment id generation code
and moves ipv6_select_ident() into the header as it may be
used during GSO.
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
---
include/net/ipv6.h | 3 +++
net/ipv6/ip6_output.c | 14 --------------
net/ipv6/output_core.c | 41 +++++++++++++++++++++++++++++++++++------
net/ipv6/udp_offload.c | 10 +++++++++-
4 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 4292929..9bf85d3 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -671,6 +671,9 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
}
+u32 __ipv6_select_ident(u32 hashrnd, struct in6_addr *dst,
+ struct in6_addr *src);
+void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
void ipv6_proxy_select_ident(struct sk_buff *skb);
int ip6_dst_hoplimit(struct dst_entry *dst);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index ce69a12..d28f2a2 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -537,20 +537,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
skb_copy_secmark(to, from);
}
-static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
-{
- static u32 ip6_idents_hashrnd __read_mostly;
- u32 hash, id;
-
- net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
-
- hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd);
- hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash);
-
- id = ip_idents_reserve(hash, 1);
- fhdr->identification = htonl(id);
-}
-
int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
{
struct sk_buff *frag;
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index 97f41a3..54520a0 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -9,6 +9,24 @@
#include <net/addrconf.h>
#include <net/secure_seq.h>
+u32 __ipv6_select_ident(u32 hashrnd, struct in6_addr *dst, struct in6_addr *src)
+{
+ u32 hash, id;
+
+ hash = __ipv6_addr_jhash(dst, hashrnd);
+ hash = __ipv6_addr_jhash(src, hash);
+
+ /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve,
+ * set the hight order instead thus minimizing possible future
+ * collisions.
+ */
+ id = ip_idents_reserve(hash, 1);
+ if (unlikely(!id))
+ id = 1 << 31;
+
+ return id;
+}
+
/* This function exists only for tap drivers that must support broken
* clients requesting UFO without specifying an IPv6 fragment ID.
*
@@ -22,7 +40,7 @@ void ipv6_proxy_select_ident(struct sk_buff *skb)
static u32 ip6_proxy_idents_hashrnd __read_mostly;
struct in6_addr buf[2];
struct in6_addr *addrs;
- u32 hash, id;
+ u32 id;
addrs = skb_header_pointer(skb,
skb_network_offset(skb) +
@@ -34,14 +52,25 @@ void ipv6_proxy_select_ident(struct sk_buff *skb)
net_get_random_once(&ip6_proxy_idents_hashrnd,
sizeof(ip6_proxy_idents_hashrnd));
- hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd);
- hash = __ipv6_addr_jhash(&addrs[0], hash);
-
- id = ip_idents_reserve(hash, 1);
- skb_shinfo(skb)->ip6_frag_id = htonl(id);
+ id = __ipv6_select_ident(ip6_proxy_idents_hashrnd,
+ &addrs[1], &addrs[0]);
+ skb_shinfo(skb)->ip6_frag_id = id;
}
EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
+void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
+{
+ static u32 ip6_idents_hashrnd __read_mostly;
+ u32 id;
+
+ net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
+
+ id = __ipv6_select_ident(ip6_idents_hashrnd, &rt->rt6i_dst.addr,
+ &rt->rt6i_src.addr);
+ fhdr->identification = htonl(id);
+}
+EXPORT_SYMBOL(ipv6_select_ident);
+
int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
{
u16 offset = sizeof(struct ipv6hdr);
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index b6aa8ed..a562769 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -52,6 +52,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
+ /* Set the IPv6 fragment id if not set yet */
+ if (!skb_shinfo(skb)->ip6_frag_id)
+ ipv6_proxy_select_ident(skb);
+
segs = NULL;
goto out;
}
@@ -108,7 +112,11 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
fptr->nexthdr = nexthdr;
fptr->reserved = 0;
- fptr->identification = skb_shinfo(skb)->ip6_frag_id;
+ if (skb_shinfo(skb)->ip6_frag_id)
+ fptr->identification = skb_shinfo(skb)->ip6_frag_id;
+ else
+ ipv6_select_ident(fptr,
+ (struct rt6_info *)skb_dst(skb));
/* Fragment the skb. ipv6 header and the remaining fields of the
* fragment header are updated in ipv6_gso_segment()
--
1.9.3
^ permalink raw reply related
* [PATCH v4 net 0/3] Restore UFO support to virtio_net devices
From: Vladislav Yasevich @ 2015-02-03 21:36 UTC (permalink / raw)
To: netdev; +Cc: virtualization
commit 3d0ad09412ffe00c9afa201d01effdb6023d09b4
Author: Ben Hutchings <ben@decadent.org.uk>
Date: Thu Oct 30 18:27:12 2014 +0000
drivers/net: Disable UFO through virtio
Turned off UFO support to virtio-net based devices due to issues
with IPv6 fragment id generation for UFO packets. The issue
was that IPv6 UFO/GSO implementation expects the fragment id
to be supplied in skb_shinfo(). However, for packets generated
by the VMs, the fragment id is not supplied which causes all
IPv6 fragments to have the id of 0.
The problem is that turning off UFO support on tap/macvtap
as well as virtio devices caused issues with migrations.
Migrations would fail when moving a vm from a kernel supporting
expecting UFO to work to the newer kernels that disabled UFO.
This series provides a partial solution to address the migration
issue. The series allows us to track whether skb_shinfo()->ip6_frag_id
has been set by treating value of 0 as unset.
This lets GSO code to generate fragment ids if they are necessary
(ex: packet was generated by VM or packet socket).
Since v3:
- Resolved build issue when IPv6 is a module.
- Removed trailing white space.
Since v2:
- Rebase and rebuild to make sure everything works. No changes
to the patches were done.
Since v1:
- Removed the skb bit and use value of 0 as tracker.
- Used Eric's suggestion to set fragment id as 0x80000000 if id
generation procedure yeilded a 0 result.
- Consolidated ipv6 id genration code.
Vladislav Yasevich (3):
ipv6: Select fragment id during UFO segmentation if not set.
Revert "drivers/net, ipv6: Select IPv6 fragment idents for virtio UFO
packets"
Revert "drivers/net: Disable UFO through virtio"
drivers/net/macvtap.c | 16 ++++++++--------
drivers/net/tun.c | 25 +++++++++----------------
drivers/net/virtio_net.c | 24 ++++++++++--------------
include/net/ipv6.h | 3 +++
net/ipv6/ip6_output.c | 14 --------------
net/ipv6/output_core.c | 41 +++++++++++++++++++++++++++++++++++------
net/ipv6/udp_offload.c | 10 +++++++++-
7 files changed, 74 insertions(+), 59 deletions(-)
--
1.9.3
^ permalink raw reply
* RE: [PATCH] hyper-v: allow access to vmbus from userspace driver
From: KY Srinivasan @ 2015-02-03 21:21 UTC (permalink / raw)
To: KY Srinivasan, Stephen Hemminger, Haiyang Zhang
Cc: devel@linuxdriverproject.org, netdev@vger.kernel.org
In-Reply-To: <BY2PR0301MB0711862B8AD44FC335D57A8BA03D0@BY2PR0301MB0711.namprd03.prod.outlook.com>
> -----Original Message-----
> From: devel [mailto:driverdev-devel-bounces@linuxdriverproject.org] On
> Behalf Of KY Srinivasan
> Sent: Tuesday, February 3, 2015 11:24 AM
> To: Stephen Hemminger; Haiyang Zhang
> Cc: devel@linuxdriverproject.org; netdev@vger.kernel.org
> Subject: RE: [PATCH] hyper-v: allow access to vmbus from userspace driver
>
>
>
> > -----Original Message-----
> > From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> > Sent: Tuesday, February 3, 2015 11:04 AM
> > To: KY Srinivasan; Haiyang Zhang
> > Cc: devel@linuxdriverproject.org; netdev@vger.kernel.org
> > Subject: [PATCH] hyper-v: allow access to vmbus from userspace driver
> >
> > Brocade is submitting a hyper-v driver for DPDK <dev@dpdk.org> but
> > this driver needs a hook in the hyper-v bus layer to allow the
> > additional hv_uio driver to access the shared vmbus pages. The hv_uio
> > driver lives in DPDK (like
> > igb_uio) and provides userspace access to raw network packets.
> >
> > Signed-off-by: Stas Egorov <segorov@mirantis.com>
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> >
> > ---
> > drivers/hv/connection.c | 20 +++++++++++++++++---
> > include/linux/hyperv.h | 3 +++
> > 2 files changed, 20 insertions(+), 3 deletions(-)
> >
> > --- a/drivers/hv/connection.c 2015-02-03 10:58:51.751752450 -0800
> > +++ b/drivers/hv/connection.c 2015-02-03 10:58:51.751752450 -0800
> > @@ -64,6 +64,21 @@ static __u32 vmbus_get_next_version(__u3
> > }
> > }
> >
> > +static const uuid_le HV_NET_GUID = {
> > + .b = {
> > + 0x63, 0x51, 0x61, 0xf8, 0x3e, 0xdf, 0xc5, 0x46,
> > + 0x91, 0x3f, 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e
> > + }
> > +};
> > +
>
> We already have this guid defined in linux/hyperv.h; look at HV_NIC_GUID.
>
> > +void vmbus_get_pages(unsigned long *int_page, unsigned long
> > +monitor_pages[2]) {
> > + *int_page = (unsigned long)vmbus_connection.int_page;
> > + monitor_pages[0] = (unsigned
> > long)vmbus_connection.monitor_pages[0];
> > + monitor_pages[1] = (unsigned
> > long)vmbus_connection.monitor_pages[1];
> > +}
> > +EXPORT_SYMBOL_GPL(vmbus_get_pages);
vmbus_get_pages() is too generic. Perhaps vmbus_get_monitor_pages() may be a better
name for this function.
Regards,
K. Y
^ permalink raw reply
* [PATCH 4/4] netfilter: Use rhashtable walk iterator
From: Herbert Xu @ 2015-02-03 20:33 UTC (permalink / raw)
To: David Miller, tgraf, netdev
In-Reply-To: <20150203203213.GA23177@gondor.apana.org.au>
This patch gets rid of the manual rhashtable walk in nft_hash
which touches rhashtable internals that should not be exposed.
It does so by using the rhashtable iterator primitives.
Note that I'm leaving nft_hash_destroy alone since it's only
invoked on shutdown and it shouldn't be affected by changes
to rhashtable internals (or at least not what I'm planning to
change).
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/netfilter/nft_hash.c | 53 +++++++++++++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 17 deletions(-)
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index 75887d7..61e6c40 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -130,31 +130,50 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
struct nft_set_iter *iter)
{
struct rhashtable *priv = nft_set_priv(set);
- const struct bucket_table *tbl;
const struct nft_hash_elem *he;
+ struct rhashtable_iter hti;
struct nft_set_elem elem;
- unsigned int i;
+ int err;
- tbl = rht_dereference_rcu(priv->tbl, priv);
- for (i = 0; i < tbl->size; i++) {
- struct rhash_head *pos;
+ err = rhashtable_walk_init(priv, &hti);
+ iter->err = err;
+ if (err)
+ return;
+
+ err = rhashtable_walk_start(&hti);
+ if (err && err != -EAGAIN) {
+ iter->err = err;
+ goto out;
+ }
- rht_for_each_entry_rcu(he, pos, tbl, i, node) {
- if (iter->count < iter->skip)
- goto cont;
+ while ((he = rhashtable_walk_next(&hti))) {
+ if (IS_ERR(he)) {
+ err = PTR_ERR(he);
+ if (err != -EAGAIN) {
+ iter->err = err;
+ goto out;
+ }
+ }
+
+ if (iter->count < iter->skip)
+ goto cont;
+
+ memcpy(&elem.key, &he->key, sizeof(elem.key));
+ if (set->flags & NFT_SET_MAP)
+ memcpy(&elem.data, he->data, sizeof(elem.data));
+ elem.flags = 0;
- memcpy(&elem.key, &he->key, sizeof(elem.key));
- if (set->flags & NFT_SET_MAP)
- memcpy(&elem.data, he->data, sizeof(elem.data));
- elem.flags = 0;
+ iter->err = iter->fn(ctx, set, iter, &elem);
+ if (iter->err < 0)
+ goto out;
- iter->err = iter->fn(ctx, set, iter, &elem);
- if (iter->err < 0)
- return;
cont:
- iter->count++;
- }
+ iter->count++;
}
+
+out:
+ rhashtable_walk_stop(&hti);
+ rhashtable_walk_exit(&hti);
}
static unsigned int nft_hash_privsize(const struct nlattr * const nla[])
^ permalink raw reply related
* [PATCH 3/4] netlink: Use rhashtable walk iterator
From: Herbert Xu @ 2015-02-03 20:33 UTC (permalink / raw)
To: David Miller, tgraf, netdev
In-Reply-To: <20150203203213.GA23177@gondor.apana.org.au>
This patch gets rid of the manual rhashtable walk in netlink
which touches rhashtable internals that should not be exposed.
It does so by using the rhashtable iterator primitives.
In fact the existing code was very buggy. Some sockets weren't
shown at all while others were shown more than once.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/netlink/af_netlink.c | 130 +++++++++++++++++++++++------------------------
1 file changed, 64 insertions(+), 66 deletions(-)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index a36777b..1558548 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2886,99 +2886,97 @@ EXPORT_SYMBOL(nlmsg_notify);
#ifdef CONFIG_PROC_FS
struct nl_seq_iter {
struct seq_net_private p;
+ struct rhashtable_iter hti;
int link;
- int hash_idx;
};
-static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos)
+static int netlink_walk_start(struct nl_seq_iter *iter)
{
- struct nl_seq_iter *iter = seq->private;
- int i, j;
- struct netlink_sock *nlk;
- struct sock *s;
- loff_t off = 0;
-
- for (i = 0; i < MAX_LINKS; i++) {
- struct rhashtable *ht = &nl_table[i].hash;
- const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
-
- for (j = 0; j < tbl->size; j++) {
- struct rhash_head *node;
-
- rht_for_each_entry_rcu(nlk, node, tbl, j, node) {
- s = (struct sock *)nlk;
+ int err;
- if (sock_net(s) != seq_file_net(seq))
- continue;
- if (off == pos) {
- iter->link = i;
- iter->hash_idx = j;
- return s;
- }
- ++off;
- }
- }
+ err = rhashtable_walk_init(&nl_table[iter->link].hash, &iter->hti);
+ if (err) {
+ iter->link = MAX_LINKS;
+ return err;
}
- return NULL;
+
+ err = rhashtable_walk_start(&iter->hti);
+ return err == -EAGAIN ? 0 : err;
}
-static void *netlink_seq_start(struct seq_file *seq, loff_t *pos)
- __acquires(RCU)
+static void netlink_walk_stop(struct nl_seq_iter *iter)
{
- rcu_read_lock();
- return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+ rhashtable_walk_stop(&iter->hti);
+ rhashtable_walk_exit(&iter->hti);
}
-static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *__netlink_seq_next(struct seq_file *seq)
{
- struct rhashtable *ht;
- const struct bucket_table *tbl;
- struct rhash_head *node;
+ struct nl_seq_iter *iter = seq->private;
struct netlink_sock *nlk;
- struct nl_seq_iter *iter;
- struct net *net;
- int i, j;
- ++*pos;
+ do {
+ for (;;) {
+ int err;
- if (v == SEQ_START_TOKEN)
- return netlink_seq_socket_idx(seq, 0);
+ nlk = rhashtable_walk_next(&iter->hti);
- net = seq_file_net(seq);
- iter = seq->private;
- nlk = v;
+ if (IS_ERR(nlk)) {
+ if (PTR_ERR(nlk) == -EAGAIN)
+ continue;
- i = iter->link;
- ht = &nl_table[i].hash;
- tbl = rht_dereference_rcu(ht->tbl, ht);
- rht_for_each_entry_rcu_continue(nlk, node, nlk->node.next, tbl, iter->hash_idx, node)
- if (net_eq(sock_net((struct sock *)nlk), net))
- return nlk;
+ return nlk;
+ }
- j = iter->hash_idx + 1;
+ if (nlk)
+ break;
- do {
+ netlink_walk_stop(iter);
+ if (++iter->link >= MAX_LINKS)
+ return NULL;
- for (; j < tbl->size; j++) {
- rht_for_each_entry_rcu(nlk, node, tbl, j, node) {
- if (net_eq(sock_net((struct sock *)nlk), net)) {
- iter->link = i;
- iter->hash_idx = j;
- return nlk;
- }
- }
+ err = netlink_walk_start(iter);
+ if (err)
+ return ERR_PTR(err);
}
+ } while (sock_net(&nlk->sk) != seq_file_net(seq));
- j = 0;
- } while (++i < MAX_LINKS);
+ return nlk;
+}
- return NULL;
+static void *netlink_seq_start(struct seq_file *seq, loff_t *posp)
+{
+ struct nl_seq_iter *iter = seq->private;
+ void *obj = SEQ_START_TOKEN;
+ loff_t pos;
+ int err;
+
+ iter->link = 0;
+
+ err = netlink_walk_start(iter);
+ if (err)
+ return ERR_PTR(err);
+
+ for (pos = *posp; pos && obj && !IS_ERR(obj); pos--)
+ obj = __netlink_seq_next(seq);
+
+ return obj;
+}
+
+static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ return __netlink_seq_next(seq);
}
static void netlink_seq_stop(struct seq_file *seq, void *v)
- __releases(RCU)
{
- rcu_read_unlock();
+ struct nl_seq_iter *iter = seq->private;
+
+ if (iter->link >= MAX_LINKS)
+ return;
+
+ netlink_walk_stop(iter);
}
^ permalink raw reply related
* [PATCH 2/4] rhashtable: Introduce rhashtable_walk_*
From: Herbert Xu @ 2015-02-03 20:33 UTC (permalink / raw)
To: David Miller, tgraf, netdev
In-Reply-To: <20150203203213.GA23177@gondor.apana.org.au>
Some existing rhashtable users get too intimate with it by walking
the buckets directly. This prevents us from easily changing the
internals of rhashtable.
This patch adds the helpers rhashtable_walk_init/exit/start/next/stop
which will replace these custom walkers.
They are meant to be usable for both procfs seq_file walks as well
as walking by a netlink dump. The iterator structure should fit
inside a netlink dump cb structure, with at least one element to
spare.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/rhashtable.h | 35 +++++++++
lib/rhashtable.c | 163 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 198 insertions(+)
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index e033784..5885127 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -18,6 +18,7 @@
#ifndef _LINUX_RHASHTABLE_H
#define _LINUX_RHASHTABLE_H
+#include <linux/compiler.h>
#include <linux/list_nulls.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
@@ -111,6 +112,7 @@ struct rhashtable_params {
* @p: Configuration parameters
* @run_work: Deferred worker to expand/shrink asynchronously
* @mutex: Mutex to protect current/future table swapping
+ * @walkers: List of active walkers
* @being_destroyed: True if table is set up for destruction
*/
struct rhashtable {
@@ -121,9 +123,36 @@ struct rhashtable {
struct rhashtable_params p;
struct work_struct run_work;
struct mutex mutex;
+ struct list_head walkers;
bool being_destroyed;
};
+/**
+ * struct rhashtable_walker - Hash table walker
+ * @list: List entry on list of walkers
+ * @resize: Resize event occured
+ */
+struct rhashtable_walker {
+ struct list_head list;
+ bool resize;
+};
+
+/**
+ * struct rhashtable_iter - Hash table iterator, fits into netlink cb
+ * @ht: Table to iterate through
+ * @p: Current pointer
+ * @walker: Associated rhashtable walker
+ * @slot: Current slot
+ * @skip: Number of entries to skip in slot
+ */
+struct rhashtable_iter {
+ struct rhashtable *ht;
+ struct rhash_head *p;
+ struct rhashtable_walker *walker;
+ unsigned int slot;
+ unsigned int skip;
+};
+
static inline unsigned long rht_marker(const struct rhashtable *ht, u32 hash)
{
return NULLS_MARKER(ht->p.nulls_base + hash);
@@ -179,6 +208,12 @@ bool rhashtable_lookup_compare_insert(struct rhashtable *ht,
bool (*compare)(void *, void *),
void *arg);
+int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter);
+void rhashtable_walk_exit(struct rhashtable_iter *iter);
+int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU);
+void *rhashtable_walk_next(struct rhashtable_iter *iter);
+void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU);
+
void rhashtable_destroy(struct rhashtable *ht);
#define rht_dereference(p, ht) \
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 904b419..0579191 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -484,6 +484,7 @@ static void rht_deferred_worker(struct work_struct *work)
{
struct rhashtable *ht;
struct bucket_table *tbl;
+ struct rhashtable_walker *walker;
ht = container_of(work, struct rhashtable, run_work);
mutex_lock(&ht->mutex);
@@ -492,6 +493,9 @@ static void rht_deferred_worker(struct work_struct *work)
tbl = rht_dereference(ht->tbl, ht);
+ list_for_each_entry(walker, &ht->walkers, list)
+ walker->resize = true;
+
if (ht->p.grow_decision && ht->p.grow_decision(ht, tbl->size))
rhashtable_expand(ht);
else if (ht->p.shrink_decision && ht->p.shrink_decision(ht, tbl->size))
@@ -822,6 +826,164 @@ exit:
}
EXPORT_SYMBOL_GPL(rhashtable_lookup_compare_insert);
+/**
+ * rhashtable_walk_init - Initialise an iterator
+ * @ht: Table to walk over
+ * @iter: Hash table Iterator
+ *
+ * This function prepares a hash table walk.
+ *
+ * Note that if you restart a walk after rhashtable_walk_stop you
+ * may see the same object twice. Also, you may miss objects if
+ * there are removals in between rhashtable_walk_stop and the next
+ * call to rhashtable_walk_start.
+ *
+ * For a completely stable walk you should construct your own data
+ * structure outside the hash table.
+ *
+ * This function may sleep so you must not call it from interrupt
+ * context or with spin locks held.
+ *
+ * You must call rhashtable_walk_exit if this function returns
+ * successfully.
+ */
+int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter)
+{
+ iter->ht = ht;
+ iter->p = NULL;
+ iter->slot = 0;
+ iter->skip = 0;
+
+ iter->walker = kmalloc(sizeof(*iter->walker), GFP_KERNEL);
+ if (!iter->walker)
+ return -ENOMEM;
+
+ mutex_lock(&ht->mutex);
+ list_add(&iter->walker->list, &ht->walkers);
+ mutex_unlock(&ht->mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rhashtable_walk_init);
+
+/**
+ * rhashtable_walk_exit - Free an iterator
+ * @iter: Hash table Iterator
+ *
+ * This function frees resources allocated by rhashtable_walk_init.
+ */
+void rhashtable_walk_exit(struct rhashtable_iter *iter)
+{
+ mutex_lock(&iter->ht->mutex);
+ list_del(&iter->walker->list);
+ mutex_unlock(&iter->ht->mutex);
+ kfree(iter->walker);
+}
+EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
+
+/**
+ * rhashtable_walk_start - Start a hash table walk
+ * @iter: Hash table iterator
+ *
+ * Start a hash table walk. Note that we take the RCU lock in all
+ * cases including when we return an error. So you must always call
+ * rhashtable_walk_stop to clean up.
+ *
+ * Returns zero if successful.
+ *
+ * Returns -EAGAIN if resize event occured. Note that the iterator
+ * will rewind back to the beginning and you may use it immediately
+ * by calling rhashtable_walk_next.
+ */
+int rhashtable_walk_start(struct rhashtable_iter *iter)
+{
+ rcu_read_lock();
+
+ if (iter->walker->resize) {
+ iter->slot = 0;
+ iter->skip = 0;
+ iter->walker->resize = false;
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rhashtable_walk_start);
+
+/**
+ * rhashtable_walk_next - Return the next object and advance the iterator
+ * @iter: Hash table iterator
+ *
+ * Note that you must call rhashtable_walk_stop when you are finished
+ * with the walk.
+ *
+ * Returns the next object or NULL when the end of the table is reached.
+ *
+ * Returns -EAGAIN if resize event occured. Note that the iterator
+ * will rewind back to the beginning and you may continue to use it.
+ */
+void *rhashtable_walk_next(struct rhashtable_iter *iter)
+{
+ const struct bucket_table *tbl;
+ struct rhashtable *ht = iter->ht;
+ struct rhash_head *p = iter->p;
+ void *obj = NULL;
+
+ tbl = rht_dereference_rcu(ht->tbl, ht);
+
+ if (p) {
+ p = rht_dereference_bucket_rcu(p->next, tbl, iter->slot);
+ goto next;
+ }
+
+ for (; iter->slot < tbl->size; iter->slot++) {
+ int skip = iter->skip;
+
+ rht_for_each_rcu(p, tbl, iter->slot) {
+ if (!skip)
+ break;
+ skip--;
+ }
+
+next:
+ if (!rht_is_a_nulls(p)) {
+ iter->skip++;
+ iter->p = p;
+ obj = rht_obj(ht, p);
+ goto out;
+ }
+
+ iter->skip = 0;
+ }
+
+ iter->p = NULL;
+
+out:
+ if (iter->walker->resize) {
+ iter->p = NULL;
+ iter->slot = 0;
+ iter->skip = 0;
+ iter->walker->resize = false;
+ return ERR_PTR(-EAGAIN);
+ }
+
+ return obj;
+}
+EXPORT_SYMBOL_GPL(rhashtable_walk_next);
+
+/**
+ * rhashtable_walk_stop - Finish a hash table walk
+ * @iter: Hash table iterator
+ *
+ * Finish a hash table walk.
+ */
+void rhashtable_walk_stop(struct rhashtable_iter *iter)
+{
+ rcu_read_unlock();
+ iter->p = NULL;
+}
+EXPORT_SYMBOL_GPL(rhashtable_walk_stop);
+
static size_t rounded_hashtable_size(struct rhashtable_params *params)
{
return max(roundup_pow_of_two(params->nelem_hint * 4 / 3),
@@ -894,6 +1056,7 @@ int rhashtable_init(struct rhashtable *ht, struct rhashtable_params *params)
memset(ht, 0, sizeof(*ht));
mutex_init(&ht->mutex);
memcpy(&ht->p, params, sizeof(*params));
+ INIT_LIST_HEAD(&ht->walkers);
if (params->locks_mul)
ht->p.locks_mul = roundup_pow_of_two(params->locks_mul);
^ permalink raw reply related
* [PATCH 1/4] rhashtable: Fix potential crash on destroy in rhashtable_shrink
From: Herbert Xu @ 2015-02-03 20:33 UTC (permalink / raw)
To: David Miller, tgraf, netdev
In-Reply-To: <20150203203213.GA23177@gondor.apana.org.au>
The current being_destroyed check in rhashtable_expand is not
enough since if we start a shrinking process after freeing all
elements in the table that's also going to crash.
This patch adds a being_destroyed check to the deferred worker
thread so that we bail out as soon as we take the lock.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
lib/rhashtable.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index c41e210..904b419 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -487,6 +487,9 @@ static void rht_deferred_worker(struct work_struct *work)
ht = container_of(work, struct rhashtable, run_work);
mutex_lock(&ht->mutex);
+ if (ht->being_destroyed)
+ goto unlock;
+
tbl = rht_dereference(ht->tbl, ht);
if (ht->p.grow_decision && ht->p.grow_decision(ht, tbl->size))
@@ -494,6 +497,7 @@ static void rht_deferred_worker(struct work_struct *work)
else if (ht->p.shrink_decision && ht->p.shrink_decision(ht, tbl->size))
rhashtable_shrink(ht);
+unlock:
mutex_unlock(&ht->mutex);
}
^ permalink raw reply related
* [PATCH 0/4] rhashtable: Add iterators and use them
From: Herbert Xu @ 2015-02-03 20:32 UTC (permalink / raw)
To: David Miller; +Cc: tgraf, netdev
In-Reply-To: <20150203201750.GA22474@gondor.apana.org.au>
On Wed, Feb 04, 2015 at 07:17:50AM +1100, Herbert Xu wrote:
>
> > ERROR: "rhashtable_walk_start" [net/netfilter/nft_hash.ko] undefined!
>
> Oops, I missed an export on that symbol. I'll fix it up and
> repost.
OK here is the repost without the hash_rnd patch.
The first patch fixes a potential crash with nft_hash destroying
the table during a shrinking process. While the next patch adds
rhashtable iterators to replace current manual walks used by
netlink and netfilter. The final two patches make use of these
iterators in netlink and netfilter.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: rhashtable: Move hash_rnd into bucket_table
From: Herbert Xu @ 2015-02-03 20:17 UTC (permalink / raw)
To: David Miller; +Cc: tgraf, netdev
In-Reply-To: <20150202.192634.1792206005008667377.davem@davemloft.net>
On Mon, Feb 02, 2015 at 07:26:34PM -0800, David Miller wrote:
>
> Firstly, the hash_rnd change results in this:
>
> lib/rhashtable.c: In function ‘obj_raw_hashfn’:
> lib/rhashtable.c:84:9: warning: passing argument 1 of ‘lockdep_rht_mutex_is_held’ discards ‘const’ qualifier from pointer target type [enabled by default]
> lib/rhashtable.c:57:5: note: expected ‘struct rhashtable *’ but argument is of type ‘const struct rhashtable *’
Pleas drop the hash_rnd patch since that's only needed by my
rehash work which is not yet complete. Although I thought it
built correctly on its own since I've always had it in my test
tree but obviously I missed something.
> Next, the netfilter change results in:
>
> ERROR: "rhashtable_walk_start" [net/netfilter/nft_hash.ko] undefined!
Oops, I missed an export on that symbol. I'll fix it up and
repost.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH net] amd-xgbe: Set RSS enablement based on hardware features
From: Tom Lendacky @ 2015-02-03 20:14 UTC (permalink / raw)
To: netdev; +Cc: David Miller
The RSS support requires enablement based on the features reported by
the hardware. The setting of this flag is missing. Add support to
set the RSS enablement flag based on the reported hardware features.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 1246140..e5ffb2c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -523,6 +523,7 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
hw_feat->sph = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, SPHEN);
hw_feat->tso = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, TSOEN);
hw_feat->dma_debug = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, DBGMEMA);
+ hw_feat->rss = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, RSSEN);
hw_feat->tc_cnt = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, NUMTC);
hw_feat->hash_table_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R,
HASHTBLSZ);
^ permalink raw reply related
* Re: [PATCH net-next 1/2] pkt_sched: fq: avoid artificial bursts for clocked flows
From: Kenneth Klette Jonassen @ 2015-02-03 19:51 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev@vger.kernel.org
In-Reply-To: <1422905092.21689.122.camel@edumazet-glaptop2.roam.corp.google.com>
> On 02 Feb 2015, at 20:24, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
> On Mon, 2015-02-02 at 19:59 +0100, Kenneth Klette Jonassen wrote:
>> Current pacing behavior always throttle flows for a time equal to one full
>> quantum, starting at the instance in time when a flow depletes its credit.
>> …
>
>
> We do not want to perfectly space packets, but have an efficient packet
> scheduler, allowing TCP pacing.
>
> I chose to not use ktime_get() in enqueue() when I wrote sch_fq.
Posted V2 to address this.
>
> A Token Bucket Filter has the notion of quantum, meaning you configure
> the granularity given this quantum.
>
> At Google, we have a special handling for TCP ACK packets, so that they
> do not interfere with FQ/pacing.
Interesting. How does this work when ACKs are piggybacked to data?
>
> ACK packets are not paced, ever.
>
> This patch also allows skb->ooo_okay being set even if the DATA packet
> immediately follows a train of ACK packets (as in typical RPC patterns)
>
Could you please expand on this?
Thanks for the feedback so far.
Sincerely,
Kenneth
^ permalink raw reply
* [PATCH net-next v2 1/2] pkt_sched: fq: avoid artificial bursts for clocked flows
From: Kenneth Klette Jonassen @ 2015-02-03 19:48 UTC (permalink / raw)
To: netdev; +Cc: Kenneth Klette Jonassen
Current pacing behavior always throttle flows for a time equal to one full
quantum, starting when a flow exhausts its credit. This is only optimal for
bursty traffic that consumes the entire credit in one sitting.
For flows with small packets, this throttling behavior can cause packets
to artificially queue and transmit in bursts, even when their sending rate
is well below their pacing rate. There is a refill mechanism in fq_enqueue()
that counteracts this in some cases, but it only works when flows space
their packets further apart than the flow refill delay.
Keep track of the time a flows credit was last filled, and use this to
approximate a full credit refill when one quantum of time passes. This is
a more fine-grained approach than the refill heuristic in fq_enqueue(),
which is removed by the next patch in this series.
Since calls to ktime are expensive, time_credit_filled is only set correctly
on dequeue. For new flows, set time_credit_filled to zero and anticipate
dequeue to refill one quantum without throttling. This approach requires
that initial_quantum >= quantum.
Increases memory footprint from 104 to 112 bytes per flow.
V2: avoids ktime_get_ns() on enqueue, as suggested by Eric Dumazet.
Signed-off-by: Kenneth Klette Jonassen <kennetkl@ifi.uio.no>
---
net/sched/sch_fq.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 313794b..43d5b74 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -71,6 +71,7 @@ struct fq_flow {
struct rb_node rate_node; /* anchor in q->delayed tree */
u64 time_next_packet;
+ u64 time_credit_filled;
};
struct fq_flow_head {
@@ -250,6 +251,7 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
if (unlikely(skb->sk &&
f->socket_hash != sk->sk_hash)) {
f->credit = q->initial_quantum;
+ f->time_credit_filled = 0ULL;
f->socket_hash = sk->sk_hash;
f->time_next_packet = 0ULL;
}
@@ -271,6 +273,7 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
if (skb->sk)
f->socket_hash = sk->sk_hash;
f->credit = q->initial_quantum;
+ f->time_credit_filled = 0ULL;
rb_link_node(&f->fq_node, parent, p);
rb_insert_color(&f->fq_node, root);
@@ -374,8 +377,10 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
qdisc_qstats_backlog_inc(sch, skb);
if (fq_flow_is_detached(f)) {
fq_flow_add_tail(&q->new_flows, f);
- if (time_after(jiffies, f->age + q->flow_refill_delay))
- f->credit = max_t(u32, f->credit, q->quantum);
+ if (time_after(jiffies, f->age + q->flow_refill_delay)) {
+ f->credit = max_t(int, f->credit - q->quantum, 0);
+ f->time_credit_filled = 0ULL;
+ }
q->inactive_flows--;
}
@@ -440,6 +445,7 @@ begin:
if (f->credit <= 0) {
f->credit += q->quantum;
+ f->time_credit_filled = max(now, f->time_next_packet);
head->first = f->next;
fq_flow_add_tail(&q->old_flows, f);
goto begin;
@@ -489,7 +495,7 @@ begin:
q->stat_pkts_too_long++;
}
- f->time_next_packet = now + len;
+ f->time_next_packet = max(now, f->time_credit_filled + len);
}
out:
qdisc_bstats_update(sch, skb);
@@ -679,8 +685,14 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
err = -EINVAL;
}
- if (tb[TCA_FQ_INITIAL_QUANTUM])
- q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
+ if (tb[TCA_FQ_INITIAL_QUANTUM]) {
+ u32 initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
+
+ if (initial_quantum > q->quantum)
+ q->initial_quantum = initial_quantum - q->quantum;
+ else
+ q->initial_quantum = 0;
+ }
if (tb[TCA_FQ_FLOW_DEFAULT_RATE])
pr_warn_ratelimited("sch_fq: defrate %u ignored.\n",
@@ -740,7 +752,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt)
sch->limit = 10000;
q->flow_plimit = 100;
q->quantum = 2 * psched_mtu(qdisc_dev(sch));
- q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch));
+ q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch)) - q->quantum;
q->flow_refill_delay = msecs_to_jiffies(40);
q->flow_max_rate = ~0U;
q->rate_enable = 1;
@@ -773,7 +785,8 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb)
if (nla_put_u32(skb, TCA_FQ_PLIMIT, sch->limit) ||
nla_put_u32(skb, TCA_FQ_FLOW_PLIMIT, q->flow_plimit) ||
nla_put_u32(skb, TCA_FQ_QUANTUM, q->quantum) ||
- nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) ||
+ nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM,
+ q->initial_quantum + q->quantum) ||
nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) ||
nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) ||
nla_put_u32(skb, TCA_FQ_FLOW_REFILL_DELAY,
--
1.9.1
^ permalink raw reply related
* Re: PROBLEM: Bnx2x Checksum/Length Error Over GRE Tunnel
From: Rick Jones @ 2015-02-03 19:29 UTC (permalink / raw)
To: Eric Dumazet, Eren Türkay; +Cc: Network Development
In-Reply-To: <1422989196.907.34.camel@edumazet-glaptop2.roam.corp.google.com>
On 02/03/2015 10:46 AM, Eric Dumazet wrote:
> On Tue, 2015-02-03 at 20:05 +0200, Eren Türkay wrote:
>> Hello,
>>
>> I am having incorrect checksum and length calculation error when using
>> GRE tunnel and this leads to unstable/unreliable connections where even
>> simple nc connection cannot be made correctly due to a lot of TCP
>> retransmissions. The reported iperf output becomes 23Kbit/s.
>>
>> When I disable tx checksumming with "ethtool -K eth0 tx off", the
>> problem seems to be solved but then I lose tcp segmentation offloading
>> support, without which adds an additional overhead on 10Gbit network
>> interface. With tx off, I get 4 to 7Gbit/s with parallel 40 connections
>> using iperf.
>>
>> In tcpdump output (tcpdump -i em1 proto gre) when tx checksumming is
>> enabled, I see "checksum error" in every packet + "IP truncated-ip -
>> 63631 bytes missing!" messages, and a lot of TCP
>> retransmissions. When tx is off, checksums are correct but I get 4-7Gbit
>> output. With GSO generalization code in [0] it is reported that
>> 9.3Gbit/s is possible over GRE tunnel but I'm nowhere near these results.
>
> Strange, I am using bnx2x with no such problem.
A pedantic question, but do the driver and firmware versions match
between your setup and his?
rick
^ permalink raw reply
* RE: [PATCH] hyper-v: allow access to vmbus from userspace driver
From: KY Srinivasan @ 2015-02-03 19:23 UTC (permalink / raw)
To: Stephen Hemminger, Haiyang Zhang
Cc: devel@linuxdriverproject.org, netdev@vger.kernel.org
In-Reply-To: <20150203110345.15c38345@urahara>
> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Tuesday, February 3, 2015 11:04 AM
> To: KY Srinivasan; Haiyang Zhang
> Cc: devel@linuxdriverproject.org; netdev@vger.kernel.org
> Subject: [PATCH] hyper-v: allow access to vmbus from userspace driver
>
> Brocade is submitting a hyper-v driver for DPDK <dev@dpdk.org> but this
> driver needs a hook in the hyper-v bus layer to allow the additional hv_uio
> driver to access the shared vmbus pages. The hv_uio driver lives in DPDK (like
> igb_uio) and provides userspace access to raw network packets.
>
> Signed-off-by: Stas Egorov <segorov@mirantis.com>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>
> ---
> drivers/hv/connection.c | 20 +++++++++++++++++---
> include/linux/hyperv.h | 3 +++
> 2 files changed, 20 insertions(+), 3 deletions(-)
>
> --- a/drivers/hv/connection.c 2015-02-03 10:58:51.751752450 -0800
> +++ b/drivers/hv/connection.c 2015-02-03 10:58:51.751752450 -0800
> @@ -64,6 +64,21 @@ static __u32 vmbus_get_next_version(__u3
> }
> }
>
> +static const uuid_le HV_NET_GUID = {
> + .b = {
> + 0x63, 0x51, 0x61, 0xf8, 0x3e, 0xdf, 0xc5, 0x46,
> + 0x91, 0x3f, 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e
> + }
> +};
> +
We already have this guid defined in linux/hyperv.h; look at HV_NIC_GUID.
> +void vmbus_get_pages(unsigned long *int_page, unsigned long
> +monitor_pages[2]) {
> + *int_page = (unsigned long)vmbus_connection.int_page;
> + monitor_pages[0] = (unsigned
> long)vmbus_connection.monitor_pages[0];
> + monitor_pages[1] = (unsigned
> long)vmbus_connection.monitor_pages[1];
> +}
> +EXPORT_SYMBOL_GPL(vmbus_get_pages);
> +
> static int vmbus_negotiate_version(struct vmbus_channel_msginfo
> *msginfo,
> __u32 version)
> {
> @@ -347,7 +362,8 @@ static void process_chn_event(u32 relid)
> else
> bytes_to_read = 0;
> } while (read_state && (bytes_to_read != 0));
> - } else {
> + } else if (!memcmp(&channel->device_obj->dev_type,
> &HV_NET_GUID,
> + sizeof(uuid_le))) {
> pr_err("no channel callback for relid - %u\n", relid);
> }
I am not sure this message is all that useful. We may just get rid of the message.
If we get rid of this message, we can significantly simplify.
>
> --- a/include/linux/hyperv.h 2015-02-03 10:58:51.751752450 -0800
> +++ b/include/linux/hyperv.h 2015-02-03 10:58:51.751752450 -0800
> @@ -868,6 +868,9 @@ extern int vmbus_recvpacket_raw(struct v
>
> extern void vmbus_ontimer(unsigned long data);
>
> +extern void vmbus_get_pages(unsigned long *int_page,
> + unsigned long monitor_pages[2]);
> +
> /* Base driver object */
> struct hv_driver {
> const char *name;
Thanks,
K. Y
^ permalink raw reply
* [PATCH] NetCP: Deletion of unnecessary checks before two function calls
From: SF Markus Elfring @ 2015-02-03 19:22 UTC (permalink / raw)
To: Murali Karicheri, Wingman Kwok, netdev
Cc: LKML, kernel-janitors, Julia Lawall
In-Reply-To: <5317A59D.4@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Tue, 3 Feb 2015 20:12:25 +0100
The functions cpsw_ale_destroy() and of_dev_put() test whether their argument
is NULL and then return immediately. Thus the test around the call
is not needed.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/net/ethernet/ti/netcp_ethss.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
index fa1041a..cbd6dde 100644
--- a/drivers/net/ethernet/ti/netcp_ethss.c
+++ b/drivers/net/ethernet/ti/netcp_ethss.c
@@ -2010,12 +2010,10 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
quit:
if (gbe_dev->hw_stats)
devm_kfree(dev, gbe_dev->hw_stats);
- if (gbe_dev->ale)
- cpsw_ale_destroy(gbe_dev->ale);
+ cpsw_ale_destroy(gbe_dev->ale);
if (gbe_dev->ss_regs)
devm_iounmap(dev, gbe_dev->ss_regs);
- if (interfaces)
- of_node_put(interfaces);
+ of_node_put(interfaces);
devm_kfree(dev, gbe_dev);
return ret;
}
--
2.2.2
^ permalink raw reply related
* [PATCH net] amd-xgbe: Adjust for zero-based traffic class count
From: Tom Lendacky @ 2015-02-03 18:49 UTC (permalink / raw)
To: netdev; +Cc: David Miller
The number of traffic classes reported by the hardware is zero-based
so increment the value returned to get an actual count.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 7bb5f07..1246140 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -552,13 +552,14 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
break;
}
- /* The Queue and Channel counts are zero based so increment them
+ /* The Queue, Channel and TC counts are zero based so increment them
* to get the actual number
*/
hw_feat->rx_q_cnt++;
hw_feat->tx_q_cnt++;
hw_feat->rx_ch_cnt++;
hw_feat->tx_ch_cnt++;
+ hw_feat->tc_cnt++;
DBGPR("<--xgbe_get_all_hw_features\n");
}
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox