* Re: [RFC] Discuss about an new idea "Vsock over Virtio-net"
From: Michael S. Tsirkin @ 2018-11-15 8:10 UTC (permalink / raw)
To: jiangyiwen; +Cc: kvm, virtualization, stefanha, netdev
In-Reply-To: <5BED2267.8030306@huawei.com>
On Thu, Nov 15, 2018 at 03:38:15PM +0800, jiangyiwen wrote:
> On 2018/11/15 15:04, Michael S. Tsirkin wrote:
> > On Thu, Nov 15, 2018 at 11:56:03AM +0800, jiangyiwen wrote:
> >> Hi Stefan, Michael, Jason and everyone,
> >>
> >> Several days ago, I discussed with jason about "Vsock over Virtio-net".
> >> This idea has two advantages:
> >> First, it can use many great features of virtio-net, like batching,
> >> mergeable rx buffer and multiqueue, etc.
> >> Second, it can reduce many duplicate codes and make it easy to be
> >> maintained.
> >
> > I'm not sure I get the motivation. Which features of
> > virtio net are relevant to vsock? The ones that you mention
> > all seem to be mostly of use to the networking stack.
> >
> >
> >> Before the implement, I want to discuss with everyone again, and
> >> want to know everyone's suggestions.
> >>
> >> After the discussion, based on this point I will try to implement
> >> this idea, but I am not familiar with the virtio-net, that is a
> >> pity. :(
> >>
> >> -------------------------Simple idea------------------------------
> >>
> >> 1. The packet layout will become as follows:
> >>
> >> +---------------------------------+
> >> | Virtio-net header |
> >> |(struct virtio_net_hdr_mrg_rxbuf)|
> >
> > Which fields in virtio_net_hdr_mrg_rxbuf are of interest to vsock?
> >
>
> Hi Michael,
>
> Yes, currently vsock has poor performance, first, it only support transport
> small packet, in order to make the balance between performance and guest memory.
>
> In order to solve this problem, there are two features vsock can used,
> mergeable rx buffer and multiqueue. Based on this, there are some shared
> codes vsock can use.
>
> Thanks,
> Yiwen.
Supporting more queues with vsock is probably significantly
less work than a completely new interface.
For mergeable, as buffers are split arbitrarily, why can't you combine
them within guest driver before sending them up the stack?
Probably better than relying on host to do it.
> >> +---------------------------------+
> >> | Vsock header |
> >> | (struct virtio_vsock_hdr) |
> >> +---------------------------------+
> >> | payload |
> >> | (until end of packet) |
> >> +---------------------------------+
> >
> > Thanks,
> >
>
^ permalink raw reply
* Re: [RFC] Discuss about an new idea "Vsock over Virtio-net"
From: jiangyiwen @ 2018-11-15 7:38 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: kvm, virtualization, stefanha, netdev
In-Reply-To: <20181115015547-mutt-send-email-mst@kernel.org>
On 2018/11/15 15:04, Michael S. Tsirkin wrote:
> On Thu, Nov 15, 2018 at 11:56:03AM +0800, jiangyiwen wrote:
>> Hi Stefan, Michael, Jason and everyone,
>>
>> Several days ago, I discussed with jason about "Vsock over Virtio-net".
>> This idea has two advantages:
>> First, it can use many great features of virtio-net, like batching,
>> mergeable rx buffer and multiqueue, etc.
>> Second, it can reduce many duplicate codes and make it easy to be
>> maintained.
>
> I'm not sure I get the motivation. Which features of
> virtio net are relevant to vsock? The ones that you mention
> all seem to be mostly of use to the networking stack.
>
>
>> Before the implement, I want to discuss with everyone again, and
>> want to know everyone's suggestions.
>>
>> After the discussion, based on this point I will try to implement
>> this idea, but I am not familiar with the virtio-net, that is a
>> pity. :(
>>
>> -------------------------Simple idea------------------------------
>>
>> 1. The packet layout will become as follows:
>>
>> +---------------------------------+
>> | Virtio-net header |
>> |(struct virtio_net_hdr_mrg_rxbuf)|
>
> Which fields in virtio_net_hdr_mrg_rxbuf are of interest to vsock?
>
Hi Michael,
Yes, currently vsock has poor performance, first, it only support transport
small packet, in order to make the balance between performance and guest memory.
In order to solve this problem, there are two features vsock can used,
mergeable rx buffer and multiqueue. Based on this, there are some shared
codes vsock can use.
Thanks,
Yiwen.
>> +---------------------------------+
>> | Vsock header |
>> | (struct virtio_vsock_hdr) |
>> +---------------------------------+
>> | payload |
>> | (until end of packet) |
>> +---------------------------------+
>
> Thanks,
>
^ permalink raw reply
* Re: [PATCH v2 net-next 19/21] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
From: Andrew Lunn @ 2018-11-14 21:30 UTC (permalink / raw)
To: Igor Russkikh
Cc: David S . Miller, linux-usb@vger.kernel.org,
netdev@vger.kernel.org, Dmitry Bezrukov
In-Reply-To: <3c322e27-06c7-69a1-cbe8-271741da0bb3@aquantia.com>
> We've considered that, but then thought about the following case:
>
> After such a sleep state where partner's capabilities were considered,
> user may move with the unit and replug it into different link partner with
> other, incompatible speed mask. That will anyway lead to wol link failure.
WOL for a nomadic device? Is that even a real use case?
Anyway, looking at the link partner capabilities is just really a
corner case, that the LP only supports 1G. Do such devices exist?
So skipping this is fine. But if you use phylib, you pretty much get
it for free if you want it.
Andrew
^ permalink raw reply
* Re: [PATCH v2 net-next 06/21] net: usb: aqc111: Introduce link management
From: Andrew Lunn @ 2018-11-14 21:16 UTC (permalink / raw)
To: Igor Russkikh
Cc: David S . Miller, linux-usb@vger.kernel.org,
netdev@vger.kernel.org, Dmitry Bezrukov
In-Reply-To: <6a92f825-576e-3826-66c7-791304661174@aquantia.com>
> > Thats again because of this product has tightly integrated MAC+Phy.
> > MAC FW controls system interface and reports/alters link state
> > as a joint state on copper and SIF (even in dpa direct phy mode).
> >
> > We can't extract phy api into a standalone fully functional phylib therefore.
> > Also as far as I know this particular phy is not available in the wild.
>
> So the point is that MAC firmware is managing SERDES and system interface link.
Linux can manage that SERDES link between the MAC and the PHY. There
are two ways this can go:
1) You use phylib. When the PHY reports link, the adjust_link callback
in the MAC is called. The phydev structure contains information about
how you should configure the SERDES, SGMII, 2500Base-X, 5000Base-X. It
works, but it is not so nice.
2) phylink gives you a much nicer API to do the same. Again, the PHY
reports the link is up. phylink will then tell the MAC how to
configure its end of the SERDES. The problem with phylink is that it
expects a DT building. You don't have that, since this is a USB
device. But you also don't need a lot of the features of phylink like
SFPs, the i2c bus for the SFPs, GPIOs etc. So it should not be to hard
to make this work without device tree.
By using core linux code, we avoid bugs in firmware which nobody can
fix. The Linux core code should be well tested and supported, but
phylink is rather new, so might still have some corner cases.
I also cannot imaging parts of the PHY driver will not be re-usable
for other Aquantia PHYs. I have a board with an AQCS109 under my desk
waiting for me to do something with it. I really would like a better
PHY driver for it than the kernel currently has. Hopefully there is
some code reuse possibilities here.
Andrew
^ permalink raw reply
* Re: [RFC] Discuss about an new idea "Vsock over Virtio-net"
From: jiangyiwen @ 2018-11-15 6:49 UTC (permalink / raw)
To: Jason Wang, stefanha, stefanha, mst; +Cc: netdev, kvm, virtualization
In-Reply-To: <5BED162C.5070902@huawei.com>
On 2018/11/15 14:46, jiangyiwen wrote:
> On 2018/11/15 12:19, Jason Wang wrote:
>>
>> On 2018/11/15 上午11:56, jiangyiwen wrote:
>>> Hi Stefan, Michael, Jason and everyone,
>>>
>>> Several days ago, I discussed with jason about "Vsock over Virtio-net".
>>> This idea has two advantages:
>>> First, it can use many great features of virtio-net, like batching,
>>> mergeable rx buffer and multiqueue, etc.
>>> Second, it can reduce many duplicate codes and make it easy to be
>>> maintained.
>>>
>>> Before the implement, I want to discuss with everyone again, and
>>> want to know everyone's suggestions.
>>>
>>> After the discussion, based on this point I will try to implement
>>> this idea, but I am not familiar with the virtio-net, that is a
>>> pity. :(
>>
>>
>> I think we should have a new feature flag for this. E.g VIRTIO_NET_F_VSOCK. And host should fail the negotiation if guest doesn't support this to avoid confusion. When this feature is negotiated, we will use it only for VOSCK transport. This can simplify things somehow.
>>
>>
>>> -------------------------Simple idea------------------------------
>>>
>>> 1. The packet layout will become as follows:
>>>
>>> +---------------------------------+
>>> | Virtio-net header |
>>> |(struct virtio_net_hdr_mrg_rxbuf)|
>>> +---------------------------------+
>>> | Vsock header |
>>> | (struct virtio_vsock_hdr) |
>>> +---------------------------------+
>>> | payload |
>>> | (until end of packet) |
>>> +---------------------------------+
>>>
>>> 2. The Guest->Host basic code flow as follow:
>>> +------------+
>>> | Client |
>>> +------------+
>>> |
>>> |
>>> +------------------------------------------------------------------+
>>> |VSOCK Core Module |
>>> |ops->sendmsg; (vsock_stream_sendmsg) |
>>> | -> alloc_skb; /* it will packet a skb buffer, and include vsock |
>>> | * hdr and payload */ |
>>> | -> dev_queue_xmit(); /* it will call start_xmit(virtio-net.c) */|
>>> |vsock hdr and payload, and then call |
>>> +------------------------------------------------------------------+
>>
>>
>> Note, if we've negotiated the feature, virtio-net driver must not use register_netdev to register it to network core. This can avoid lots of confusion.
>
> Hi Jason,
>
> You mean we should not register netdev if use vsock, and in order to
> avoid confusion, then I think whether we should keep vsock and export
> some virtio-net's functions that can be shared. In this way, first, vsock
> may keep existing architecture and will not affect virtio-net. In addition,
> vsock doesn't need to use virtio_net header too, then it don't need to pack
> skb structure.
>
> Thanks,
> Yiwen.
>
>>
>>
>>> |
>>> |
>>> +------------------------------------------------------------------+
>>> |Virtio-net Module |
>>> |start_xmit |
>>> | -> add virtio_net_hdr and pack sg in ring desc, notify Host |
>>> +------------------------------------------------------------------+
>>> |
>>> |
>>> +------------------------------------------------------------------+
>>> |Vhost-net Module |
>>> |handle_tx |
>>> | -> get tx buffer, skip virtio_net_hdr and call Vsock function. |
>>> | /* This point has some differences, vhost-net use ->sendmsg to |
>>> | * forward information, however vsock only need to notify server |
>>> | * that data ready. */ |
>>> +------------------------------------------------------------------+
>>
>>
>> When VIRTIO_NET_F_VOSCK is negotiated, we know that it's a vsock transport, we can then forward it to vsock core.
>>
>>
>>> |
>>> |
>>> +------------------------------------------------------------------+
>>> |VSOCK Core Module |
>>> |alloc_pkt, copy skb data to pkt. |
>>> |add pkt to rx_queue and notify server to get data. |
>>> +------------------------------------------------------------------+
>>>
>>> 3. To Host->Guest
>>> I have a problem and difficult, mainly I know about virtio-net a little),
>>> because I have been doing work related with storage and file system.
>>>
>>> The problem as follows:
>>> we should monitor all of socket of vsock in handle_rx, when there are
>>> data coming, and copy data to vq desc. Vhost-net use ->recvmsg to
>>> get data, it is different with socket. To vsock, I think host will
>>> not call ->recvmsg when it need to send message to guest. To net,
>>> vhost-net only as forwarding layer.
>>
>> Know not much here, but is it possible to have a vsock(tap) to be passed to vhost_net and let vhost call its recvmgs()? Bascially it was a socket on host as well I believe?
>
> For vsock, Host->Guest, it's code flow as follows:
> Server call send()
> -> sendmsg(); (vsock_stream_sendmsg)
> -> virtio_trasnport_send_pkt_info
> -> alloc pkt, add pkt to send_pkt_list, wake up vhost_worker
>
> Vhost_worker
> -> vhost_transport_send_pkt_work
> -> get pkt from send_pkt_list
> -> get vq input desc and then fill data to desc addr
> -> update used ring and then signal guest
>
> In the whole process, host don't call recvmsg() because it is a net device, and
> it also receives any messages.
Sorry, it is *not* a net device, it *does not* receive any messages.
Thanks.
>
> For vhost-net, I understand it is a tap device, so it can receive messages
> from other net device.
>
> This is my understanding, it may have some errors.
>
> Thanks.
>
>>
>> If this doesn't work, we can have vsock specific receiving routine in vhost_net if VIRTIO_NET_F_VOSCK is negotiated.
>>
>> Generally, I think we should try out best to keep the exist sendmsg()/recvmsg() interfaces and only consider the alternatives if we meet some real blocker.
>>
>> Thanks
>>
>>
>>>
>>
>> .
>>
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [RFC] Discuss about an new idea "Vsock over Virtio-net"
From: jiangyiwen @ 2018-11-15 6:46 UTC (permalink / raw)
To: Jason Wang, stefanha, stefanha, mst; +Cc: netdev, kvm, virtualization
In-Reply-To: <88eaf53b-b148-7b27-491a-30706398ae06@redhat.com>
On 2018/11/15 12:19, Jason Wang wrote:
>
> On 2018/11/15 上午11:56, jiangyiwen wrote:
>> Hi Stefan, Michael, Jason and everyone,
>>
>> Several days ago, I discussed with jason about "Vsock over Virtio-net".
>> This idea has two advantages:
>> First, it can use many great features of virtio-net, like batching,
>> mergeable rx buffer and multiqueue, etc.
>> Second, it can reduce many duplicate codes and make it easy to be
>> maintained.
>>
>> Before the implement, I want to discuss with everyone again, and
>> want to know everyone's suggestions.
>>
>> After the discussion, based on this point I will try to implement
>> this idea, but I am not familiar with the virtio-net, that is a
>> pity. :(
>
>
> I think we should have a new feature flag for this. E.g VIRTIO_NET_F_VSOCK. And host should fail the negotiation if guest doesn't support this to avoid confusion. When this feature is negotiated, we will use it only for VOSCK transport. This can simplify things somehow.
>
>
>> -------------------------Simple idea------------------------------
>>
>> 1. The packet layout will become as follows:
>>
>> +---------------------------------+
>> | Virtio-net header |
>> |(struct virtio_net_hdr_mrg_rxbuf)|
>> +---------------------------------+
>> | Vsock header |
>> | (struct virtio_vsock_hdr) |
>> +---------------------------------+
>> | payload |
>> | (until end of packet) |
>> +---------------------------------+
>>
>> 2. The Guest->Host basic code flow as follow:
>> +------------+
>> | Client |
>> +------------+
>> |
>> |
>> +------------------------------------------------------------------+
>> |VSOCK Core Module |
>> |ops->sendmsg; (vsock_stream_sendmsg) |
>> | -> alloc_skb; /* it will packet a skb buffer, and include vsock |
>> | * hdr and payload */ |
>> | -> dev_queue_xmit(); /* it will call start_xmit(virtio-net.c) */|
>> |vsock hdr and payload, and then call |
>> +------------------------------------------------------------------+
>
>
> Note, if we've negotiated the feature, virtio-net driver must not use register_netdev to register it to network core. This can avoid lots of confusion.
Hi Jason,
You mean we should not register netdev if use vsock, and in order to
avoid confusion, then I think whether we should keep vsock and export
some virtio-net's functions that can be shared. In this way, first, vsock
may keep existing architecture and will not affect virtio-net. In addition,
vsock doesn't need to use virtio_net header too, then it don't need to pack
skb structure.
Thanks,
Yiwen.
>
>
>> |
>> |
>> +------------------------------------------------------------------+
>> |Virtio-net Module |
>> |start_xmit |
>> | -> add virtio_net_hdr and pack sg in ring desc, notify Host |
>> +------------------------------------------------------------------+
>> |
>> |
>> +------------------------------------------------------------------+
>> |Vhost-net Module |
>> |handle_tx |
>> | -> get tx buffer, skip virtio_net_hdr and call Vsock function. |
>> | /* This point has some differences, vhost-net use ->sendmsg to |
>> | * forward information, however vsock only need to notify server |
>> | * that data ready. */ |
>> +------------------------------------------------------------------+
>
>
> When VIRTIO_NET_F_VOSCK is negotiated, we know that it's a vsock transport, we can then forward it to vsock core.
>
>
>> |
>> |
>> +------------------------------------------------------------------+
>> |VSOCK Core Module |
>> |alloc_pkt, copy skb data to pkt. |
>> |add pkt to rx_queue and notify server to get data. |
>> +------------------------------------------------------------------+
>>
>> 3. To Host->Guest
>> I have a problem and difficult, mainly I know about virtio-net a little),
>> because I have been doing work related with storage and file system.
>>
>> The problem as follows:
>> we should monitor all of socket of vsock in handle_rx, when there are
>> data coming, and copy data to vq desc. Vhost-net use ->recvmsg to
>> get data, it is different with socket. To vsock, I think host will
>> not call ->recvmsg when it need to send message to guest. To net,
>> vhost-net only as forwarding layer.
>
> Know not much here, but is it possible to have a vsock(tap) to be passed to vhost_net and let vhost call its recvmgs()? Bascially it was a socket on host as well I believe?
For vsock, Host->Guest, it's code flow as follows:
Server call send()
-> sendmsg(); (vsock_stream_sendmsg)
-> virtio_trasnport_send_pkt_info
-> alloc pkt, add pkt to send_pkt_list, wake up vhost_worker
Vhost_worker
-> vhost_transport_send_pkt_work
-> get pkt from send_pkt_list
-> get vq input desc and then fill data to desc addr
-> update used ring and then signal guest
In the whole process, host don't call recvmsg() because it is a net device, and
it also receives any messages.
For vhost-net, I understand it is a tap device, so it can receive messages
from other net device.
This is my understanding, it may have some errors.
Thanks.
>
> If this doesn't work, we can have vsock specific receiving routine in vhost_net if VIRTIO_NET_F_VOSCK is negotiated.
>
> Generally, I think we should try out best to keep the exist sendmsg()/recvmsg() interfaces and only consider the alternatives if we meet some real blocker.
>
> Thanks
>
>
>>
>
> .
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH net] net/sched: act_pedit: fix memory leak when IDR allocation fails
From: Cong Wang @ 2018-11-14 20:36 UTC (permalink / raw)
To: Davide Caratti
Cc: Jiri Pirko, David Miller, Vlad Buslov,
Linux Kernel Network Developers, Jamal Hadi Salim
In-Reply-To: <8ae2ff111546be071b461a0678939078353dff27.1542193853.git.dcaratti@redhat.com>
(Cc'ing Jamal)
On Wed, Nov 14, 2018 at 3:26 AM Davide Caratti <dcaratti@redhat.com> wrote:
>
> tcf_idr_check_alloc() can return a negative value, on allocation failures
> (-ENOMEM) or IDR exhaustion (-ENOSPC): don't leak keys_ex in these cases.
I think the comments above tcf_idr_check_alloc() need to improve too,
they imply tcf_idr_check_alloc() returns either 0 or 1.
Of course, this can be done with a separated patch.
>
> Fixes: 0190c1d452a9 ("net: sched: atomically check-allocate action")
> Signed-off-by: Davide Caratti <dcaratti@redhat.com>
I think your patch is correct.
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
^ permalink raw reply
* Re: [RFC v1 3/3] vxlan: handle underlay VRF changes
From: David Ahern @ 2018-11-14 20:04 UTC (permalink / raw)
To: Alexis Bauvin, roopa, nicolas.dichtel; +Cc: netdev, akherbouche
In-Reply-To: <20181114093104.93286-4-abauvin@scaleway.com>
On 11/14/18 1:31 AM, Alexis Bauvin wrote:
> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> index 7477b5510a04..188c0cdb8838 100644
> --- a/drivers/net/vxlan.c
> +++ b/drivers/net/vxlan.c
> @@ -208,6 +208,18 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
> return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
> }
>
> +static int vxlan_is_in_l3mdev_chain(struct net_device *chain,
> + struct net_device *dev)
> +{
> + if (!chain)
> + return 0;
> +
> + if (chain->ifindex == dev->ifindex)
> + return 1;
> + return vxlan_is_in_l3mdev_chain(netdev_master_upper_dev_get(chain),
> + dev);
l3mdev_master_dev_rcu
^ permalink raw reply
* Re: [RFC v1 2/3] vxlan: add support for underlay in non-default VRF
From: David Ahern @ 2018-11-14 19:58 UTC (permalink / raw)
To: Alexis Bauvin, roopa, nicolas.dichtel; +Cc: netdev, akherbouche
In-Reply-To: <20181114093104.93286-3-abauvin@scaleway.com>
you are making this more specific than it needs to be ....
On 11/14/18 1:31 AM, Alexis Bauvin wrote:
> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> index 27bd586b94b0..7477b5510a04 100644
> --- a/drivers/net/vxlan.c
> +++ b/drivers/net/vxlan.c
> @@ -208,11 +208,23 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
> return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
> }
>
> +static int vxlan_get_l3mdev(struct net *net, int ifindex)
> +{
> + struct net_device *dev;
> +
> + dev = __dev_get_by_index(net, ifindex);
> + while (dev && !netif_is_l3_master(dev))
> + dev = netdev_master_upper_dev_get(dev);
> +
> + return dev ? dev->ifindex : 0;
> +}
l3mdev_master_ifindex_by_index should work instead of defining this for
vxlan.
But I do not believe you need this function.
> +
> /* Find VXLAN socket based on network namespace, address family and UDP port
> * and enabled unshareable flags.
> */
> static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
> - __be16 port, u32 flags)
> + __be16 port, u32 flags,
> + int l3mdev_ifindex)
> {
> struct vxlan_sock *vs;
>
> @@ -221,7 +233,8 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
> hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
> if (inet_sk(vs->sock->sk)->inet_sport == port &&
> vxlan_get_sk_family(vs) == family &&
> - vs->flags == flags)
> + vs->flags == flags &&
> + vs->sock->sk->sk_bound_dev_if == l3mdev_ifindex)
Why not allow the vxlan socket to bind to any ifindex? In that case this
socket lookup follows what we do for tcp, udp and raw sockets, and you
don't need to call out vrf / l3mdev directly (ie.,
s/l3mdev_ifindex/ifindex/g) - it comes for free.
^ permalink raw reply
* linux-next: build failure after merge of the net tree
From: Stephen Rothwell @ 2018-11-15 6:02 UTC (permalink / raw)
To: David Miller, Networking
Cc: Linux-Next Mailing List, Linux Kernel Mailing List,
Michal Kalderon
[-- Attachment #1: Type: text/plain, Size: 326 bytes --]
Hi all,
After merging the net tree, today's linux-next build (arm allmodconfig
(from KernelCI)) failed like this:
drivers/net/ethernet/qlogic/qed/qed_rdma.h:186:79: error: expected ';' before '}' token
Caused by commit
291d57f67d24 ("qed: Fix rdma_info structure allocation")
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [iproute PATCH] ip-address: Fix filtering by negated address flags
From: Stephen Hemminger @ 2018-11-14 19:29 UTC (permalink / raw)
To: Phil Sutter; +Cc: netdev
In-Reply-To: <20181114105251.GR6440@orbyte.nwl.cc>
On Wed, 14 Nov 2018 11:52:51 +0100
Phil Sutter <phil@nwl.cc> wrote:
> Hi Stephen,
>
> On Tue, Nov 13, 2018 at 02:47:59PM -0800, Stephen Hemminger wrote:
> > On Tue, 13 Nov 2018 16:12:01 +0100
> > Phil Sutter <phil@nwl.cc> wrote:
> >
> > > + if (arg[0] == '-') {
> > > + inv = true;
> > > + arg++;
> > > + }
> > The inverse logic needs to be moved into the loop handling filter names.
> >
> > Otherwise, you get weirdness like "-dynamic" being accepted and not
> > doing what was expected.
>
> I intentionally moved it there to allow for '-dynamic' and '-primary'
> as well. IMO this is consistent: 'dynamic' is the inverse of 'permanent'
> and 'primary' the inverse of 'secondary' but currently only '-permanent'
> and '-secondary' are allowed. With my patch applied, one may specify not
> only '-permanent' to get the same effect as 'dynamic' but also
> '-dynamic' to get the same effect as 'permanent'. Likewise for the other
> two. Did I miss something?
>
> > Also, please make sure the man page matches the code.
>
> Oh, right. Given the above is fine with you, I will add the man page
> change in v2.
>
> Thanks, Phil
I was thinking something like this which simplifies the logic.
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index cd8cc76a3473..3f1510383071 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -1212,37 +1212,34 @@ static void print_ifa_flags(FILE *fp, const struct ifaddrmsg *ifa,
static int get_filter(const char *arg)
{
unsigned int i;
+ bool inv = false;
/* Special cases */
if (strcmp(arg, "dynamic") == 0) {
- filter.flags &= ~IFA_F_PERMANENT;
- filter.flagmask |= IFA_F_PERMANENT;
+ arg = "-permanent";
} else if (strcmp(arg, "primary") == 0) {
- filter.flags &= ~IFA_F_SECONDARY;
- filter.flagmask |= IFA_F_SECONDARY;
- } else if (*arg == '-') {
- for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
- if (strcmp(arg + 1, ifa_flag_names[i].name))
- continue;
+ arg = "-secondary";
+ }
- filter.flags &= ifa_flag_names[i].value;
- filter.flagmask |= ifa_flag_names[i].value;
- return 0;
- }
+ if (*arg == '-') {
+ inv = true;
+ ++arg;
+ }
- return -1;
- } else {
- for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
- if (strcmp(arg, ifa_flag_names[i].name))
- continue;
+ for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
+ if (strcmp(arg, ifa_flag_names[i].name))
+ continue;
+
+ if (inv) {
+ filter.flags &= ~ifa_flag_names[i].value;
+ filter.flagmask |= ifa_flag_names[i].value;
+ } else {
filter.flags |= ifa_flag_names[i].value;
filter.flagmask |= ifa_flag_names[i].value;
- return 0;
}
- return -1;
+ return 0;
}
-
- return 0;
+ return -1;
}
static int ifa_label_match_rta(int ifindex, const struct rtattr *rta)
^ permalink raw reply related
* Re: [iproute PATCH] ip-route: Fix nexthop encap parsing
From: Stephen Hemminger @ 2018-11-14 19:20 UTC (permalink / raw)
To: Phil Sutter; +Cc: netdev
In-Reply-To: <20181113123904.27880-1-phil@nwl.cc>
On Tue, 13 Nov 2018 13:39:04 +0100
Phil Sutter <phil@nwl.cc> wrote:
> When parsing nexthop parameters, a buffer of 4k bytes is provided. Yet,
> in lwt_parse_encap() and some functions called by it, buffer size was
> assumed to be 1k despite the actual size was provided. This led to
> spurious buffer size errors if the buffer was filled by previous nexthop
> parameters to exceed that 1k boundary.
>
> Fixes: 1e5293056a02c ("lwtunnel: Add encapsulation support to ip route")
> Fixes: 5866bddd9aa9e ("ila: Add support for ILA lwtunnels")
> Fixes: ed67f83806538 ("ila: Support for checksum neutral translation")
> Fixes: 86905c8f057c0 ("ila: support for configuring identifier and hook types")
> Fixes: b15f440e78373 ("lwt: BPF support for LWT")
> Signed-off-by: Phil Sutter <phil@nwl.cc>
Applied
^ permalink raw reply
* Re: [iproute PATCH] man: ip-route.8: Document nexthop limit
From: Stephen Hemminger @ 2018-11-14 19:20 UTC (permalink / raw)
To: Phil Sutter; +Cc: netdev
In-Reply-To: <20181112222101.9674-1-phil@nwl.cc>
On Mon, 12 Nov 2018 23:21:01 +0100
Phil Sutter <phil@nwl.cc> wrote:
> Add a note to 'nexthop' description stating the maximum number of
> nexthops per command and pointing at 'append' command as a workaround.
>
> Signed-off-by: Phil Sutter <phil@nwl.cc>
Applied
^ permalink raw reply
* [PATCH v5] net: phy: mdio-gpio: Fix working over slow can_sleep GPIOs
From: Martin Schiller @ 2018-11-15 5:24 UTC (permalink / raw)
To: andrew, sergei.shtylyov, f.fainelli
Cc: davem, netdev, linux-kernel, Martin Schiller
In-Reply-To: <20181114061703.11026-1-ms@dev.tdt.de>
Up until commit 7e5fbd1e0700 ("net: mdio-gpio: Convert to use gpiod
functions where possible"), the _cansleep variants of the gpio_ API was
used. After that commit and the change to gpiod_ API, the _cansleep()
was dropped. This then results in WARN_ON() when used with GPIO
devices which do sleep. Add back the _cansleep() to avoid this.
Fixes: 7e5fbd1e0700 ("net: mdio-gpio: Convert to use gpiod functions where possible")
Signed-off-by: Martin Schiller <ms@dev.tdt.de>
---
v5:
- reworked commit message
- added "Fixes:" tag
- based on DaveM net tree instead of mainline
v4:
- remove linewrap of kernel message
v3:
- modified commit summary
- fixed commit cites in commit message
- fixed line continuation
v2:
- fixed copy/paste bug in warning about slow GPIO pins
---
drivers/net/phy/mdio-gpio.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 33265747bf39..3a5a24daf384 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -63,7 +63,7 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
* assume the pin serves as pull-up. If direction is
* output, the default value is high.
*/
- gpiod_set_value(bitbang->mdo, 1);
+ gpiod_set_value_cansleep(bitbang->mdo, 1);
return;
}
@@ -78,7 +78,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- return gpiod_get_value(bitbang->mdio);
+ return gpiod_get_value_cansleep(bitbang->mdio);
}
static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
@@ -87,9 +87,9 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
container_of(ctrl, struct mdio_gpio_info, ctrl);
if (bitbang->mdo)
- gpiod_set_value(bitbang->mdo, what);
+ gpiod_set_value_cansleep(bitbang->mdo, what);
else
- gpiod_set_value(bitbang->mdio, what);
+ gpiod_set_value_cansleep(bitbang->mdio, what);
}
static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
@@ -97,7 +97,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- gpiod_set_value(bitbang->mdc, what);
+ gpiod_set_value_cansleep(bitbang->mdc, what);
}
static const struct mdiobb_ops mdio_gpio_ops = {
@@ -162,6 +162,10 @@ static int mdio_gpio_probe(struct platform_device *pdev)
if (ret)
return ret;
+ if (gpiod_cansleep(bitbang->mdc) || gpiod_cansleep(bitbang->mdio) ||
+ gpiod_cansleep(bitbang->mdo))
+ dev_warn(&pdev->dev, "Slow GPIO pins might wreak havoc into MDIO bus timing");
+
if (pdev->dev.of_node) {
bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio");
if (bus_id < 0) {
--
2.11.0
^ permalink raw reply related
* [PATCH 1/1] net-next/hinic:fix three problems in HiNIC Driver
From: Xue Chaojing @ 2018-11-15 5:23 UTC (permalink / raw)
To: davem
Cc: linux-kernel, xuechaojing, netdev, wulike1, chiqijun, fy.wang,
tony.qu, luoshaokai
This patch fixes these problems:
1. In order to improve performance, this patch add rx checksum offload
for the HiNIC driver. Performance test(Iperf) shows more than 95%
improvement in TCP streams.
2. In add_mac_addr(), if the MAC address is a muliticast address, it
will not be set, which causes the network card fail to receive the
multicast packet. This patch fixes this bug.
3. In rx_alloc_pkts(), there is a loop call of tasklet, which causes
100% cpu utilization, even no packets are being received. This patch
fixes this bug.
Signed-off-by: Xue Chaojing <xuechaojing@huawei.com>
---
.../net/ethernet/huawei/hinic/hinic_hw_dev.h | 2 +
.../net/ethernet/huawei/hinic/hinic_hw_wq.c | 43 +++++++++++++------
.../net/ethernet/huawei/hinic/hinic_hw_wq.h | 3 +-
.../net/ethernet/huawei/hinic/hinic_hw_wqe.h | 4 ++
.../net/ethernet/huawei/hinic/hinic_main.c | 14 ++++--
.../net/ethernet/huawei/hinic/hinic_port.c | 28 ++++++++++++
.../net/ethernet/huawei/hinic/hinic_port.h | 10 +++++
drivers/net/ethernet/huawei/hinic/hinic_rx.c | 26 ++++++++++-
drivers/net/ethernet/huawei/hinic/hinic_rx.h | 5 +++
9 files changed, 116 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
index 097b5502603f..d1a7d2522d82 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
@@ -50,6 +50,8 @@ enum hinic_port_cmd {
HINIC_PORT_CMD_GET_LINK_STATE = 24,
+ HINIC_PORT_CMD_SET_RX_CSUM = 26,
+
HINIC_PORT_CMD_SET_PORT_STATE = 41,
HINIC_PORT_CMD_FWCTXT_INIT = 69,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
index f92f1bf3901a..34859502c932 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
@@ -74,12 +74,6 @@
((void *)((cmdq_pages)->shadow_page_vaddr) \
+ (wq)->block_idx * CMDQ_BLOCK_SIZE)
-#define WQE_PAGE_OFF(wq, idx) (((idx) & ((wq)->num_wqebbs_per_page - 1)) * \
- (wq)->wqebb_size)
-
-#define WQE_PAGE_NUM(wq, idx) (((idx) / ((wq)->num_wqebbs_per_page)) \
- & ((wq)->num_q_pages - 1))
-
#define WQ_PAGE_ADDR(wq, idx) \
((wq)->shadow_block_vaddr[WQE_PAGE_NUM(wq, idx)])
@@ -93,6 +87,17 @@
(((unsigned long)(wqe) - (unsigned long)(wq)->shadow_wqe) \
/ (wq)->max_wqe_size)
+static inline int WQE_PAGE_OFF(struct hinic_wq *wq, u16 idx)
+{
+ return (((idx) & ((wq)->num_wqebbs_per_page - 1))
+ << (wq)->wqebb_size_shift);
+}
+
+static inline int WQE_PAGE_NUM(struct hinic_wq *wq, u16 idx)
+{
+ return (((idx) >> ((wq)->wqebbs_per_page_shift))
+ & ((wq)->num_q_pages - 1));
+}
/**
* queue_alloc_page - allocate page for Queue
* @hwif: HW interface for allocating DMA
@@ -513,6 +518,7 @@ int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq,
struct hinic_hwif *hwif = wqs->hwif;
struct pci_dev *pdev = hwif->pdev;
u16 num_wqebbs_per_page;
+ u16 wqebb_size_shift;
int err;
if (wqebb_size == 0) {
@@ -530,7 +536,9 @@ int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq,
return -EINVAL;
}
- num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size) / wqebb_size;
+ wqebb_size_shift = ilog2(wqebb_size);
+ num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size)
+ >> wqebb_size_shift;
if (num_wqebbs_per_page & (num_wqebbs_per_page - 1)) {
dev_err(&pdev->dev, "num wqebbs per page must be power of 2\n");
@@ -550,7 +558,8 @@ int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq,
wq->q_depth = q_depth;
wq->max_wqe_size = max_wqe_size;
wq->num_wqebbs_per_page = num_wqebbs_per_page;
-
+ wq->wqebbs_per_page_shift = ilog2(num_wqebbs_per_page);
+ wq->wqebb_size_shift = wqebb_size_shift;
wq->block_vaddr = WQ_BASE_VADDR(wqs, wq);
wq->shadow_block_vaddr = WQ_BASE_ADDR(wqs, wq);
wq->block_paddr = WQ_BASE_PADDR(wqs, wq);
@@ -604,7 +613,9 @@ int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages,
u16 q_depth, u16 max_wqe_size)
{
struct pci_dev *pdev = hwif->pdev;
+ u16 num_wqebbs_per_page_shift;
u16 num_wqebbs_per_page;
+ u16 wqebb_size_shift;
int i, j, err = -ENOMEM;
if (wqebb_size == 0) {
@@ -622,7 +633,9 @@ int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages,
return -EINVAL;
}
- num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size) / wqebb_size;
+ wqebb_size_shift = ilog2(wqebb_size);
+ num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size)
+ >> wqebb_size_shift;
if (num_wqebbs_per_page & (num_wqebbs_per_page - 1)) {
dev_err(&pdev->dev, "num wqebbs per page must be power of 2\n");
@@ -636,6 +649,7 @@ int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages,
dev_err(&pdev->dev, "Failed to allocate CMDQ page\n");
return err;
}
+ num_wqebbs_per_page_shift = ilog2(num_wqebbs_per_page);
for (i = 0; i < cmdq_blocks; i++) {
wq[i].hwif = hwif;
@@ -647,7 +661,8 @@ int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages,
wq[i].q_depth = q_depth;
wq[i].max_wqe_size = max_wqe_size;
wq[i].num_wqebbs_per_page = num_wqebbs_per_page;
-
+ wq[i].wqebbs_per_page_shift = num_wqebbs_per_page_shift;
+ wq[i].wqebb_size_shift = wqebb_size_shift;
wq[i].block_vaddr = CMDQ_BASE_VADDR(cmdq_pages, &wq[i]);
wq[i].shadow_block_vaddr = CMDQ_BASE_ADDR(cmdq_pages, &wq[i]);
wq[i].block_paddr = CMDQ_BASE_PADDR(cmdq_pages, &wq[i]);
@@ -741,7 +756,7 @@ struct hinic_hw_wqe *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size,
*prod_idx = MASKED_WQE_IDX(wq, atomic_read(&wq->prod_idx));
- num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) / wq->wqebb_size;
+ num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) >> wq->wqebb_size_shift;
if (atomic_sub_return(num_wqebbs, &wq->delta) <= 0) {
atomic_add(num_wqebbs, &wq->delta);
@@ -795,7 +810,8 @@ void hinic_return_wqe(struct hinic_wq *wq, unsigned int wqe_size)
**/
void hinic_put_wqe(struct hinic_wq *wq, unsigned int wqe_size)
{
- int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) / wq->wqebb_size;
+ int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size)
+ >> wq->wqebb_size_shift;
atomic_add(num_wqebbs, &wq->cons_idx);
@@ -813,7 +829,8 @@ void hinic_put_wqe(struct hinic_wq *wq, unsigned int wqe_size)
struct hinic_hw_wqe *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size,
u16 *cons_idx)
{
- int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) / wq->wqebb_size;
+ int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size)
+ >> wq->wqebb_size_shift;
u16 curr_cons_idx, end_cons_idx;
int curr_pg, end_pg;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h
index 9b66545ba563..0a936cd6709b 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h
@@ -39,7 +39,8 @@ struct hinic_wq {
u16 q_depth;
u16 max_wqe_size;
u16 num_wqebbs_per_page;
-
+ u16 wqebbs_per_page_shift;
+ u16 wqebb_size_shift;
/* The addresses are 64 bit in the HW */
u64 block_paddr;
void **shadow_block_vaddr;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h
index 9754d6ed5f4a..138941527872 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h
@@ -170,6 +170,10 @@
#define HINIC_RQ_CQE_STATUS_RXDONE_MASK 0x1
+#define HINIC_RQ_CQE_STATUS_CSUM_ERR_SHIFT 0
+
+#define HINIC_RQ_CQE_STATUS_CSUM_ERR_MASK 0xFFFFU
+
#define HINIC_RQ_CQE_STATUS_GET(val, member) \
(((val) >> HINIC_RQ_CQE_STATUS_##member##_SHIFT) & \
HINIC_RQ_CQE_STATUS_##member##_MASK)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index fdf2bdb6b0d0..6d48dc62a44b 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -600,9 +600,6 @@ static int add_mac_addr(struct net_device *netdev, const u8 *addr)
u16 vid = 0;
int err;
- if (!is_valid_ether_addr(addr))
- return -EADDRNOTAVAIL;
-
netif_info(nic_dev, drv, netdev, "set mac addr = %02x %02x %02x %02x %02x %02x\n",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
@@ -726,6 +723,7 @@ static void set_rx_mode(struct work_struct *work)
{
struct hinic_rx_mode_work *rx_mode_work = work_to_rx_mode_work(work);
struct hinic_dev *nic_dev = rx_mode_work_to_nic_dev(rx_mode_work);
+ struct netdev_hw_addr *ha;
netif_info(nic_dev, drv, nic_dev->netdev, "set rx mode work\n");
@@ -733,6 +731,9 @@ static void set_rx_mode(struct work_struct *work)
__dev_uc_sync(nic_dev->netdev, add_mac_addr, remove_mac_addr);
__dev_mc_sync(nic_dev->netdev, add_mac_addr, remove_mac_addr);
+
+ netdev_for_each_mc_addr(ha, nic_dev->netdev)
+ add_mac_addr(nic_dev->netdev, ha->addr);
}
static void hinic_set_rx_mode(struct net_device *netdev)
@@ -806,7 +807,8 @@ static const struct net_device_ops hinic_netdev_ops = {
static void netdev_features_init(struct net_device *netdev)
{
netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM |
- NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
+ NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_RXCSUM;
netdev->vlan_features = netdev->hw_features;
@@ -869,12 +871,16 @@ static int set_features(struct hinic_dev *nic_dev,
netdev_features_t features, bool force_change)
{
netdev_features_t changed = force_change ? ~0 : pre_features ^ features;
+ u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
int err = 0;
if (changed & NETIF_F_TSO)
err = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);
+ if (changed & NETIF_F_RXCSUM)
+ err = hinic_set_rx_csum_offload(nic_dev, csum_en);
+
return err;
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c
index 7575a7d3bd9f..e9f76e904610 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c
@@ -409,3 +409,31 @@ int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)
return 0;
}
+
+int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)
+{
+ struct hinic_checksum_offload rx_csum_cfg = {0};
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
+ struct hinic_hwif *hwif = hwdev->hwif;
+ struct pci_dev *pdev = hwif->pdev;
+ u16 out_size;
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
+ rx_csum_cfg.rx_csum_offload = en;
+
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
+ &rx_csum_cfg, sizeof(rx_csum_cfg),
+ &rx_csum_cfg, &out_size);
+ if (err || !out_size || rx_csum_cfg.status) {
+ dev_err(&pdev->dev,
+ "Failed to set rx csum offload, ret = %d\n",
+ rx_csum_cfg.status);
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.h b/drivers/net/ethernet/huawei/hinic/hinic_port.h
index f6e3220fe28f..02d896eed455 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.h
@@ -183,6 +183,15 @@ struct hinic_tso_config {
u8 resv2[3];
};
+struct hinic_checksum_offload {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u16 rsvd1;
+ u32 rx_csum_offload;
+};
int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
u16 vlan_id);
@@ -213,4 +222,5 @@ int hinic_port_get_cap(struct hinic_dev *nic_dev,
int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state);
+int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
index 4c0f7eda1166..f86f2e693224 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
@@ -89,6 +89,28 @@ static void rxq_stats_init(struct hinic_rxq *rxq)
hinic_rxq_clean_stats(rxq);
}
+static void rx_csum(struct hinic_rxq *rxq, u16 cons_idx,
+ struct sk_buff *skb)
+{
+ struct net_device *netdev = rxq->netdev;
+ struct hinic_rq_cqe *cqe;
+ struct hinic_rq *rq;
+ u32 csum_err;
+ u32 status;
+
+ rq = rxq->rq;
+ cqe = rq->cqe[cons_idx];
+ status = be32_to_cpu(cqe->status);
+ csum_err = HINIC_RQ_CQE_STATUS_GET(status, CSUM_ERR);
+
+ if (!(netdev->features & NETIF_F_RXCSUM))
+ return;
+
+ if (!csum_err)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+}
/**
* rx_alloc_skb - allocate skb and map it to dma address
* @rxq: rx queue
@@ -207,9 +229,9 @@ static int rx_alloc_pkts(struct hinic_rxq *rxq)
wmb(); /* write all the wqes before update PI */
hinic_rq_update(rxq->rq, prod_idx);
+ tasklet_schedule(&rxq->rx_task);
}
- tasklet_schedule(&rxq->rx_task);
return i;
}
@@ -328,6 +350,8 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget)
rx_unmap_skb(rxq, hinic_sge_to_dma(&sge));
+ rx_csum(rxq, ci, skb);
+
prefetch(skb->data);
pkt_len = sge.len;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.h b/drivers/net/ethernet/huawei/hinic/hinic_rx.h
index 27c9af4b1c12..7ab57d6ff83f 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.h
@@ -23,6 +23,11 @@
#include "hinic_hw_qp.h"
+#define BIT(nr) (1UL << (nr))
+#define HINIC_RX_CSUM_OFFLOAD_EN 0xFFF
+#define HINIC_RX_CSUM_HW_CHECK_NONE BIT(7)
+#define HINIC_RX_CSUM_IPSU_OTHER_ERR BIT(8)
+
struct hinic_rxq_stats {
u64 pkts;
u64 bytes;
--
2.17.1
^ permalink raw reply related
* Re: [PATCH net] ipv6: fix a dst leak when removing its exception
From: David Ahern @ 2018-11-14 19:03 UTC (permalink / raw)
To: Xin Long, network dev; +Cc: davem
In-Reply-To: <b031b44110fcb06d780ed60ecadfa4e8bc39acfb.1542127708.git.lucien.xin@gmail.com>
On 11/13/18 8:48 AM, Xin Long wrote:
> These is no need to hold dst before calling rt6_remove_exception_rt().
> The call to dst_hold_safe() in ip6_link_failure() was for ip6_del_rt(),
> which has been removed in Commit 93531c674315 ("net/ipv6: separate
> handling of FIB entries from dst based routes"). Otherwise, it will
> cause a dst leak.
>
> This patch is to simply remove the dst_hold_safe() call before calling
> rt6_remove_exception_rt() and also do the same in ip6_del_cached_rt().
> It's safe, because the removal of the exception that holds its dst's
> refcnt is protected by rt6_exception_lock.
>
> Fixes: 93531c674315 ("net/ipv6: separate handling of FIB entries from dst based routes")
> Fixes: 23fb93a4d3f1 ("net/ipv6: Cleanup exception and cache route handling")
> Reported-by: Li Shuang <shuali@redhat.com>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
> net/ipv6/route.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
was this problem actually hit or is this patch based on a code analysis?
^ permalink raw reply
* [PATCH net-next] nxp: fix trivial comment typo
From: Andrea Claudi @ 2018-11-14 18:47 UTC (permalink / raw)
To: netdev, davem, vz
s/rxfliterctrl/rxfilterctrl
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
---
drivers/net/ethernet/nxp/lpc_eth.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index bd8695a4faaa..89d17399fb5a 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -280,7 +280,7 @@
#define LPC_FCCR_MIRRORCOUNTERCURRENT(n) ((n) & 0xFFFF)
/*
- * rxfliterctrl, rxfilterwolstatus, and rxfilterwolclear shared
+ * rxfilterctrl, rxfilterwolstatus, and rxfilterwolclear shared
* register definitions
*/
#define LPC_RXFLTRW_ACCEPTUNICAST (1 << 0)
@@ -291,7 +291,7 @@
#define LPC_RXFLTRW_ACCEPTPERFECT (1 << 5)
/*
- * rxfliterctrl register definitions
+ * rxfilterctrl register definitions
*/
#define LPC_RXFLTRWSTS_MAGICPACKETENWOL (1 << 12)
#define LPC_RXFLTRWSTS_RXFILTERENWOL (1 << 13)
--
2.17.2
^ permalink raw reply related
* [PATCH v3 net-next 4/4] net/core: handle GRO_NORMAL skbs as a list in napi_gro_receive_list
From: Edward Cree @ 2018-11-14 18:10 UTC (permalink / raw)
To: linux-net-drivers, davem; +Cc: netdev, eric.dumazet
In-Reply-To: <8e9ea3c4-82e0-a34c-08ea-32a387e4c9e1@solarflare.com>
Allows GRO-using drivers to get the benefits of batching for non-GROable
traffic.
Signed-off-by: Edward Cree <ecree@solarflare.com>
---
net/core/dev.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 35427167f6fb..65bfe28fbc81 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5664,6 +5664,7 @@ EXPORT_SYMBOL(napi_gro_receive);
int napi_gro_receive_list(struct napi_struct *napi, struct list_head *head)
{
struct sk_buff *skb, *next;
+ struct list_head sublist;
gro_result_t result;
int kept = 0;
@@ -5673,14 +5674,26 @@ int napi_gro_receive_list(struct napi_struct *napi, struct list_head *head)
skb_gro_reset_offset(skb);
}
+ INIT_LIST_HEAD(&sublist);
list_for_each_entry_safe(skb, next, head, list) {
list_del(&skb->list);
skb->next = NULL;
result = dev_gro_receive(napi, skb);
- result = napi_skb_finish(result, skb);
- if (result != GRO_DROP)
- kept++;
+ if (result == GRO_NORMAL) {
+ list_add_tail(&skb->list, &sublist);
+ continue;
+ } else {
+ if (!list_empty(&sublist)) {
+ /* Handle the GRO_NORMAL skbs to prevent OoO */
+ kept += netif_receive_skb_list_internal(&sublist);
+ INIT_LIST_HEAD(&sublist);
+ }
+ result = napi_skb_finish(result, skb);
+ if (result != GRO_DROP)
+ kept++;
+ }
}
+ kept += netif_receive_skb_list_internal(&sublist);
return kept;
}
EXPORT_SYMBOL(napi_gro_receive_list);
^ permalink raw reply related
* [PATCH v3 net-next 3/4] net: make listified RX functions return number of good packets
From: Edward Cree @ 2018-11-14 18:09 UTC (permalink / raw)
To: linux-net-drivers, davem; +Cc: netdev, eric.dumazet
In-Reply-To: <8e9ea3c4-82e0-a34c-08ea-32a387e4c9e1@solarflare.com>
'Good' packets are defined as skbs for which netif_receive_skb() would
have returned %NET_RX_SUCCESS. Thus, drivers can use this number for
adaptive interrupt moderation where they previously reacted to the
return code from netif_receive_skb().
Signed-off-by: Edward Cree <ecree@solarflare.com>
---
include/linux/netdevice.h | 4 +--
include/net/ip.h | 4 +--
include/net/ipv6.h | 4 +--
net/core/dev.c | 63 +++++++++++++++++++++++++++++------------------
net/ipv4/ip_input.c | 39 ++++++++++++++++++-----------
net/ipv6/ip6_input.c | 37 +++++++++++++++++-----------
6 files changed, 92 insertions(+), 59 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2cef1d0fb2b1..76b98386a5dd 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2357,7 +2357,7 @@ struct packet_type {
struct net_device *,
struct packet_type *,
struct net_device *);
- void (*list_func) (struct list_head *,
+ int (*list_func) (struct list_head *,
struct packet_type *,
struct net_device *);
bool (*id_match)(struct packet_type *ptype,
@@ -3587,7 +3587,7 @@ int netif_rx(struct sk_buff *skb);
int netif_rx_ni(struct sk_buff *skb);
int netif_receive_skb(struct sk_buff *skb);
int netif_receive_skb_core(struct sk_buff *skb);
-void netif_receive_skb_list(struct list_head *head);
+int netif_receive_skb_list(struct list_head *head);
gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb);
int napi_gro_receive_list(struct napi_struct *napi, struct list_head *head);
void napi_gro_flush(struct napi_struct *napi, bool flush_old);
diff --git a/include/net/ip.h b/include/net/ip.h
index 8866bfce6121..33ab464f7a09 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -152,8 +152,8 @@ int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
struct ip_options_rcu *opt);
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
struct net_device *orig_dev);
-void ip_list_rcv(struct list_head *head, struct packet_type *pt,
- struct net_device *orig_dev);
+int ip_list_rcv(struct list_head *head, struct packet_type *pt,
+ struct net_device *orig_dev);
int ip_local_deliver(struct sk_buff *skb);
void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto);
int ip_mr_input(struct sk_buff *skb);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index daf80863d3a5..e25920829a94 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -914,8 +914,8 @@ static inline __be32 flowi6_get_flowlabel(const struct flowi6 *fl6)
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev);
-void ipv6_list_rcv(struct list_head *head, struct packet_type *pt,
- struct net_device *orig_dev);
+int ipv6_list_rcv(struct list_head *head, struct packet_type *pt,
+ struct net_device *orig_dev);
int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
diff --git a/net/core/dev.c b/net/core/dev.c
index 8f0fb56170b3..35427167f6fb 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4969,24 +4969,27 @@ int netif_receive_skb_core(struct sk_buff *skb)
}
EXPORT_SYMBOL(netif_receive_skb_core);
-static inline void __netif_receive_skb_list_ptype(struct list_head *head,
- struct packet_type *pt_prev,
- struct net_device *orig_dev)
+static inline int __netif_receive_skb_list_ptype(struct list_head *head,
+ struct packet_type *pt_prev,
+ struct net_device *orig_dev)
{
struct sk_buff *skb, *next;
+ int kept = 0;
if (!pt_prev)
- return;
+ return 0;
if (list_empty(head))
- return;
+ return 0;
if (pt_prev->list_func != NULL)
- pt_prev->list_func(head, pt_prev, orig_dev);
+ kept = pt_prev->list_func(head, pt_prev, orig_dev);
else
list_for_each_entry_safe(skb, next, head, list)
- pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
+ if (pt_prev->func(skb, skb->dev, pt_prev, orig_dev) == NET_RX_SUCCESS)
+ kept++;
+ return kept;
}
-static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemalloc)
+static int __netif_receive_skb_list_core(struct list_head *head, bool pfmemalloc)
{
/* Fast-path assumptions:
* - There is no RX handler.
@@ -5003,6 +5006,7 @@ static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemallo
struct net_device *od_curr = NULL;
struct list_head sublist;
struct sk_buff *skb, *next;
+ int kept = 0, ret;
INIT_LIST_HEAD(&sublist);
list_for_each_entry_safe(skb, next, head, list) {
@@ -5010,12 +5014,15 @@ static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemallo
struct packet_type *pt_prev = NULL;
list_del(&skb->list);
- __netif_receive_skb_core(skb, pfmemalloc, &pt_prev);
- if (!pt_prev)
+ ret = __netif_receive_skb_core(skb, pfmemalloc, &pt_prev);
+ if (!pt_prev) {
+ if (ret == NET_RX_SUCCESS)
+ kept++;
continue;
+ }
if (pt_curr != pt_prev || od_curr != orig_dev) {
/* dispatch old sublist */
- __netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr);
+ kept += __netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr);
/* start new sublist */
INIT_LIST_HEAD(&sublist);
pt_curr = pt_prev;
@@ -5025,7 +5032,8 @@ static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemallo
}
/* dispatch final sublist */
- __netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr);
+ kept += __netif_receive_skb_list_ptype(&sublist, pt_curr, od_curr);
+ return kept;
}
static int __netif_receive_skb(struct sk_buff *skb)
@@ -5053,11 +5061,12 @@ static int __netif_receive_skb(struct sk_buff *skb)
return ret;
}
-static void __netif_receive_skb_list(struct list_head *head)
+static int __netif_receive_skb_list(struct list_head *head)
{
unsigned long noreclaim_flag = 0;
struct sk_buff *skb, *next;
bool pfmemalloc = false; /* Is current sublist PF_MEMALLOC? */
+ int kept = 0;
list_for_each_entry_safe(skb, next, head, list) {
if ((sk_memalloc_socks() && skb_pfmemalloc(skb)) != pfmemalloc) {
@@ -5066,7 +5075,7 @@ static void __netif_receive_skb_list(struct list_head *head)
/* Handle the previous sublist */
list_cut_before(&sublist, head, &skb->list);
if (!list_empty(&sublist))
- __netif_receive_skb_list_core(&sublist, pfmemalloc);
+ kept += __netif_receive_skb_list_core(&sublist, pfmemalloc);
pfmemalloc = !pfmemalloc;
/* See comments in __netif_receive_skb */
if (pfmemalloc)
@@ -5077,10 +5086,11 @@ static void __netif_receive_skb_list(struct list_head *head)
}
/* Handle the remaining sublist */
if (!list_empty(head))
- __netif_receive_skb_list_core(head, pfmemalloc);
+ kept += __netif_receive_skb_list_core(head, pfmemalloc);
/* Restore pflags */
if (pfmemalloc)
memalloc_noreclaim_restore(noreclaim_flag);
+ return kept;
}
static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp)
@@ -5156,17 +5166,20 @@ static int netif_receive_skb_internal(struct sk_buff *skb)
return ret;
}
-static void netif_receive_skb_list_internal(struct list_head *head)
+static int netif_receive_skb_list_internal(struct list_head *head)
{
struct bpf_prog *xdp_prog = NULL;
struct sk_buff *skb, *next;
struct list_head sublist;
+ int kept = 0;
INIT_LIST_HEAD(&sublist);
list_for_each_entry_safe(skb, next, head, list) {
net_timestamp_check(netdev_tstamp_prequeue, skb);
list_del(&skb->list);
- if (!skb_defer_rx_timestamp(skb))
+ if (skb_defer_rx_timestamp(skb))
+ kept++;
+ else
list_add_tail(&skb->list, &sublist);
}
list_splice_init(&sublist, head);
@@ -5196,13 +5209,15 @@ static void netif_receive_skb_list_internal(struct list_head *head)
if (cpu >= 0) {
/* Will be handled, remove from list */
list_del(&skb->list);
- enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
+ if (enqueue_to_backlog(skb, cpu, &rflow->last_qtail) == NET_RX_SUCCESS)
+ kept++;
}
}
}
#endif
- __netif_receive_skb_list(head);
+ kept += __netif_receive_skb_list(head);
rcu_read_unlock();
+ return kept;
}
/**
@@ -5232,21 +5247,21 @@ EXPORT_SYMBOL(netif_receive_skb);
* netif_receive_skb_list - process many receive buffers from network
* @head: list of skbs to process.
*
- * Since return value of netif_receive_skb() is normally ignored, and
- * wouldn't be meaningful for a list, this function returns void.
+ * Returns the number of skbs for which netif_receive_skb() would have
+ * returned %NET_RX_SUCCESS.
*
* This function may only be called from softirq context and interrupts
* should be enabled.
*/
-void netif_receive_skb_list(struct list_head *head)
+int netif_receive_skb_list(struct list_head *head)
{
struct sk_buff *skb;
if (list_empty(head))
- return;
+ return 0;
list_for_each_entry(skb, head, list)
trace_netif_receive_skb_list_entry(skb);
- netif_receive_skb_list_internal(head);
+ return netif_receive_skb_list_internal(head);
}
EXPORT_SYMBOL(netif_receive_skb_list);
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 72250b4e466d..fa4eb82f9e55 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -525,22 +525,26 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
ip_rcv_finish);
}
-static void ip_sublist_rcv_finish(struct list_head *head)
+static int ip_sublist_rcv_finish(struct list_head *head)
{
struct sk_buff *skb, *next;
+ int kept = 0;
list_for_each_entry_safe(skb, next, head, list) {
skb_list_del_init(skb);
- dst_input(skb);
+ if (dst_input(skb) == NET_RX_SUCCESS)
+ kept++;
}
+ return kept;
}
-static void ip_list_rcv_finish(struct net *net, struct sock *sk,
- struct list_head *head)
+static int ip_list_rcv_finish(struct net *net, struct sock *sk,
+ struct list_head *head)
{
struct dst_entry *curr_dst = NULL;
struct sk_buff *skb, *next;
struct list_head sublist;
+ int kept = 0;
INIT_LIST_HEAD(&sublist);
list_for_each_entry_safe(skb, next, head, list) {
@@ -551,8 +555,10 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk,
* skb to its handler for processing
*/
skb = l3mdev_ip_rcv(skb);
- if (!skb)
+ if (!skb) {
+ kept++;
continue;
+ }
if (ip_rcv_finish_core(net, sk, skb) == NET_RX_DROP)
continue;
@@ -560,7 +566,7 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk,
if (curr_dst != dst) {
/* dispatch old sublist */
if (!list_empty(&sublist))
- ip_sublist_rcv_finish(&sublist);
+ kept += ip_sublist_rcv_finish(&sublist);
/* start new sublist */
INIT_LIST_HEAD(&sublist);
curr_dst = dst;
@@ -568,25 +574,27 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk,
list_add_tail(&skb->list, &sublist);
}
/* dispatch final sublist */
- ip_sublist_rcv_finish(&sublist);
+ kept += ip_sublist_rcv_finish(&sublist);
+ return kept;
}
-static void ip_sublist_rcv(struct list_head *head, struct net_device *dev,
- struct net *net)
+static int ip_sublist_rcv(struct list_head *head, struct net_device *dev,
+ struct net *net)
{
NF_HOOK_LIST(NFPROTO_IPV4, NF_INET_PRE_ROUTING, net, NULL,
head, dev, NULL, ip_rcv_finish);
- ip_list_rcv_finish(net, NULL, head);
+ return ip_list_rcv_finish(net, NULL, head);
}
-/* Receive a list of IP packets */
-void ip_list_rcv(struct list_head *head, struct packet_type *pt,
- struct net_device *orig_dev)
+/* Receive a list of IP packets; return number of successful receives */
+int ip_list_rcv(struct list_head *head, struct packet_type *pt,
+ struct net_device *orig_dev)
{
struct net_device *curr_dev = NULL;
struct net *curr_net = NULL;
struct sk_buff *skb, *next;
struct list_head sublist;
+ int kept = 0;
INIT_LIST_HEAD(&sublist);
list_for_each_entry_safe(skb, next, head, list) {
@@ -601,7 +609,7 @@ void ip_list_rcv(struct list_head *head, struct packet_type *pt,
if (curr_dev != dev || curr_net != net) {
/* dispatch old sublist */
if (!list_empty(&sublist))
- ip_sublist_rcv(&sublist, curr_dev, curr_net);
+ kept += ip_sublist_rcv(&sublist, curr_dev, curr_net);
/* start new sublist */
INIT_LIST_HEAD(&sublist);
curr_dev = dev;
@@ -610,5 +618,6 @@ void ip_list_rcv(struct list_head *head, struct packet_type *pt,
list_add_tail(&skb->list, &sublist);
}
/* dispatch final sublist */
- ip_sublist_rcv(&sublist, curr_dev, curr_net);
+ kept += ip_sublist_rcv(&sublist, curr_dev, curr_net);
+ return kept;
}
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 3c06cc9e9b79..6e013672e1de 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -76,20 +76,24 @@ int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
return dst_input(skb);
}
-static void ip6_sublist_rcv_finish(struct list_head *head)
+static int ip6_sublist_rcv_finish(struct list_head *head)
{
struct sk_buff *skb, *next;
+ int kept = 0;
list_for_each_entry_safe(skb, next, head, list)
- dst_input(skb);
+ if (dst_input(skb) == NET_RX_SUCCESS)
+ kept++;
+ return kept;
}
-static void ip6_list_rcv_finish(struct net *net, struct sock *sk,
- struct list_head *head)
+static int ip6_list_rcv_finish(struct net *net, struct sock *sk,
+ struct list_head *head)
{
struct dst_entry *curr_dst = NULL;
struct sk_buff *skb, *next;
struct list_head sublist;
+ int kept = 0;
INIT_LIST_HEAD(&sublist);
list_for_each_entry_safe(skb, next, head, list) {
@@ -100,14 +104,16 @@ static void ip6_list_rcv_finish(struct net *net, struct sock *sk,
* skb to its handler for processing
*/
skb = l3mdev_ip6_rcv(skb);
- if (!skb)
+ if (!skb) {
+ kept++;
continue;
+ }
ip6_rcv_finish_core(net, sk, skb);
dst = skb_dst(skb);
if (curr_dst != dst) {
/* dispatch old sublist */
if (!list_empty(&sublist))
- ip6_sublist_rcv_finish(&sublist);
+ kept += ip6_sublist_rcv_finish(&sublist);
/* start new sublist */
INIT_LIST_HEAD(&sublist);
curr_dst = dst;
@@ -115,7 +121,8 @@ static void ip6_list_rcv_finish(struct net *net, struct sock *sk,
list_add_tail(&skb->list, &sublist);
}
/* dispatch final sublist */
- ip6_sublist_rcv_finish(&sublist);
+ kept += ip6_sublist_rcv_finish(&sublist);
+ return kept;
}
static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
@@ -274,22 +281,23 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
ip6_rcv_finish);
}
-static void ip6_sublist_rcv(struct list_head *head, struct net_device *dev,
- struct net *net)
+static int ip6_sublist_rcv(struct list_head *head, struct net_device *dev,
+ struct net *net)
{
NF_HOOK_LIST(NFPROTO_IPV6, NF_INET_PRE_ROUTING, net, NULL,
head, dev, NULL, ip6_rcv_finish);
- ip6_list_rcv_finish(net, NULL, head);
+ return ip6_list_rcv_finish(net, NULL, head);
}
/* Receive a list of IPv6 packets */
-void ipv6_list_rcv(struct list_head *head, struct packet_type *pt,
- struct net_device *orig_dev)
+int ipv6_list_rcv(struct list_head *head, struct packet_type *pt,
+ struct net_device *orig_dev)
{
struct net_device *curr_dev = NULL;
struct net *curr_net = NULL;
struct sk_buff *skb, *next;
struct list_head sublist;
+ int kept = 0;
INIT_LIST_HEAD(&sublist);
list_for_each_entry_safe(skb, next, head, list) {
@@ -304,7 +312,7 @@ void ipv6_list_rcv(struct list_head *head, struct packet_type *pt,
if (curr_dev != dev || curr_net != net) {
/* dispatch old sublist */
if (!list_empty(&sublist))
- ip6_sublist_rcv(&sublist, curr_dev, curr_net);
+ kept += ip6_sublist_rcv(&sublist, curr_dev, curr_net);
/* start new sublist */
INIT_LIST_HEAD(&sublist);
curr_dev = dev;
@@ -313,7 +321,8 @@ void ipv6_list_rcv(struct list_head *head, struct packet_type *pt,
list_add_tail(&skb->list, &sublist);
}
/* dispatch final sublist */
- ip6_sublist_rcv(&sublist, curr_dev, curr_net);
+ kept += ip6_sublist_rcv(&sublist, curr_dev, curr_net);
+ return kept;
}
/*
^ permalink raw reply related
* [PATCH v3 net-next 2/4] sfc: use batched receive for GRO
From: Edward Cree @ 2018-11-14 18:09 UTC (permalink / raw)
To: linux-net-drivers, davem; +Cc: netdev, eric.dumazet
In-Reply-To: <8e9ea3c4-82e0-a34c-08ea-32a387e4c9e1@solarflare.com>
Signed-off-by: Edward Cree <ecree@solarflare.com>
---
drivers/net/ethernet/sfc/efx.c | 11 +++++++++--
drivers/net/ethernet/sfc/net_driver.h | 1 +
drivers/net/ethernet/sfc/rx.c | 16 +++++++++++++---
3 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 98fe7e762e17..dbe4a70b36b0 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -263,9 +263,9 @@ static int efx_check_disabled(struct efx_nic *efx)
*/
static int efx_process_channel(struct efx_channel *channel, int budget)
{
+ struct list_head rx_list, gro_list;
struct efx_tx_queue *tx_queue;
- struct list_head rx_list;
- int spent;
+ int spent, gro_count;
if (unlikely(!channel->enabled))
return 0;
@@ -275,6 +275,10 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
INIT_LIST_HEAD(&rx_list);
channel->rx_list = &rx_list;
+ EFX_WARN_ON_PARANOID(channel->gro_list != NULL);
+ INIT_LIST_HEAD(&gro_list);
+ channel->gro_list = &gro_list;
+
efx_for_each_channel_tx_queue(tx_queue, channel) {
tx_queue->pkts_compl = 0;
tx_queue->bytes_compl = 0;
@@ -300,6 +304,9 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
/* Receive any packets we queued up */
netif_receive_skb_list(channel->rx_list);
channel->rx_list = NULL;
+ gro_count = napi_gro_receive_list(&channel->napi_str, channel->gro_list);
+ channel->irq_mod_score += gro_count * 2;
+ channel->gro_list = NULL;
return spent;
}
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 961b92979640..72addac7a84a 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -502,6 +502,7 @@ struct efx_channel {
unsigned int rx_pkt_index;
struct list_head *rx_list;
+ struct list_head *gro_list;
struct efx_rx_queue rx_queue;
struct efx_tx_queue tx_queue[EFX_TXQ_TYPES];
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 396ff01298cd..0534a54048c6 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -453,9 +453,19 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf,
skb_record_rx_queue(skb, channel->rx_queue.core_index);
- gro_result = napi_gro_frags(napi);
- if (gro_result != GRO_DROP)
- channel->irq_mod_score += 2;
+ /* Pass the packet up */
+ if (channel->gro_list != NULL) {
+ /* Clear napi->skb and prepare skb for GRO */
+ skb = napi_frags_skb(napi);
+ if (skb)
+ /* Add to list, will pass up later */
+ list_add_tail(&skb->list, channel->gro_list);
+ } else {
+ /* No list, so pass it up now */
+ gro_result = napi_gro_frags(napi);
+ if (gro_result != GRO_DROP)
+ channel->irq_mod_score += 2;
+ }
}
/* Allocate and construct an SKB around page fragments */
^ permalink raw reply related
* [PATCH v3 net-next 1/4] net: introduce list entry point for GRO
From: Edward Cree @ 2018-11-14 18:09 UTC (permalink / raw)
To: linux-net-drivers, davem; +Cc: netdev, eric.dumazet
In-Reply-To: <8e9ea3c4-82e0-a34c-08ea-32a387e4c9e1@solarflare.com>
Also export napi_frags_skb() so that drivers using the napi_gro_frags()
interface can prepare their SKBs properly for submitting on such a list.
Signed-off-by: Edward Cree <ecree@solarflare.com>
---
include/linux/netdevice.h | 2 ++
net/core/dev.c | 28 +++++++++++++++++++++++++++-
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 487fa5e0e165..2cef1d0fb2b1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3589,8 +3589,10 @@ int netif_receive_skb(struct sk_buff *skb);
int netif_receive_skb_core(struct sk_buff *skb);
void netif_receive_skb_list(struct list_head *head);
gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb);
+int napi_gro_receive_list(struct napi_struct *napi, struct list_head *head);
void napi_gro_flush(struct napi_struct *napi, bool flush_old);
struct sk_buff *napi_get_frags(struct napi_struct *napi);
+struct sk_buff *napi_frags_skb(struct napi_struct *napi);
gro_result_t napi_gro_frags(struct napi_struct *napi);
struct packet_offload *gro_find_receive_by_type(__be16 type);
struct packet_offload *gro_find_complete_by_type(__be16 type);
diff --git a/net/core/dev.c b/net/core/dev.c
index bf7e0a471186..8f0fb56170b3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5645,6 +5645,31 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
}
EXPORT_SYMBOL(napi_gro_receive);
+/* Returns the number of SKBs on the list successfully received */
+int napi_gro_receive_list(struct napi_struct *napi, struct list_head *head)
+{
+ struct sk_buff *skb, *next;
+ gro_result_t result;
+ int kept = 0;
+
+ list_for_each_entry(skb, head, list) {
+ skb_mark_napi_id(skb, napi);
+ trace_napi_gro_receive_entry(skb);
+ skb_gro_reset_offset(skb);
+ }
+
+ list_for_each_entry_safe(skb, next, head, list) {
+ list_del(&skb->list);
+ skb->next = NULL;
+ result = dev_gro_receive(napi, skb);
+ result = napi_skb_finish(result, skb);
+ if (result != GRO_DROP)
+ kept++;
+ }
+ return kept;
+}
+EXPORT_SYMBOL(napi_gro_receive_list);
+
static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
{
if (unlikely(skb->pfmemalloc)) {
@@ -5716,7 +5741,7 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi,
* Drivers could call both napi_gro_frags() and napi_gro_receive()
* We copy ethernet header into skb->data to have a common layout.
*/
-static struct sk_buff *napi_frags_skb(struct napi_struct *napi)
+struct sk_buff *napi_frags_skb(struct napi_struct *napi)
{
struct sk_buff *skb = napi->skb;
const struct ethhdr *eth;
@@ -5752,6 +5777,7 @@ static struct sk_buff *napi_frags_skb(struct napi_struct *napi)
return skb;
}
+EXPORT_SYMBOL(napi_frags_skb);
gro_result_t napi_gro_frags(struct napi_struct *napi)
{
^ permalink raw reply related
* [PATCH v3 net-next 0/4] net: batched receive in GRO path
From: Edward Cree @ 2018-11-14 18:07 UTC (permalink / raw)
To: linux-net-drivers, davem; +Cc: netdev, eric.dumazet
This series listifies part of GRO processing, in a manner which allows those
packets which are not GROed (i.e. for which dev_gro_receive returns
GRO_NORMAL) to be passed on to the listified regular receive path.
dev_gro_receive() itself is not listified, nor the per-protocol GRO
callback, since GRO's need to hold packets on lists under napi->gro_hash
makes keeping the packets on other lists awkward, and since the GRO control
block state of held skbs can refer only to one 'new' skb at a time.
Performance figures with this series, collected on a back-to-back pair of
Solarflare sfn8522-r2 NICs with 120-second NetPerf tests. In the stats,
sample size n for old and new code is 6 runs each; p is from a Welch t-test.
Tests were run both with GRO enabled and disabled, the latter simulating
uncoalesceable packets (e.g. due to IP or TCP options). Payload_size in all
tests was 8000 bytes. BW tests use 4 streams, RR tests use 100.
TCP Stream, GRO on:
net-next: 9.415 Gb/s (line rate); 190% total rxcpu
after #4: 9.415 Gb/s; 192% total rxcpu
p_bw = 0.155; p_cpu = 0.382
TCP Stream, GRO off:
net-next: 5.625 Gb/s
after #4: 6.551 Gb/s
16.5% faster; p < 0.001
TCP RR, GRO on:
net-next: 837.6 us
after #4: 840.0 us
0.3% slower; p = 0.229
TCP RR, GRO off:
net-next: 867.6 us
after #4: 860.1 us
0.9% faster; p = 0.064
UDP Stream (GRO off):
net-next: 7.808 Gb/s
after #4: 7.848 Gb/s
0.5% slower; p = 0.144
Conclusion:
* TCP b/w is 16.5% faster for traffic which cannot be coalesced by GRO.
* TCP latency might be slightly improved in the same case, but it's not
quite statistically significant
* Both see no statistically significant change in performance with GRO
active
* UDP throughput might be slightly slowed (probably by patch #3) but it's
not statistically significant. Note that drivers which (unlike sfc) pass
UDP traffic to GRO will probably see gains here as this gives them access
to bundling.
Change history:
v3: Rebased on latest net-next. Re-ran performance tests and added TCP_RR
tests at suggestion of Eric Dumazet. Expanded changelog of patch #3.
v2: Rebased on latest net-next. Removed RFC tags. Otherwise unchanged
owing to lack of comments on v1.
Edward Cree (4):
net: introduce list entry point for GRO
sfc: use batched receive for GRO
net: make listified RX functions return number of good packets
net/core: handle GRO_NORMAL skbs as a list in napi_gro_receive_list
drivers/net/ethernet/sfc/efx.c | 11 +++-
drivers/net/ethernet/sfc/net_driver.h | 1 +
drivers/net/ethernet/sfc/rx.c | 16 +++++-
include/linux/netdevice.h | 6 +-
include/net/ip.h | 4 +-
include/net/ipv6.h | 4 +-
net/core/dev.c | 104 ++++++++++++++++++++++++++--------
net/ipv4/ip_input.c | 39 ++++++++-----
net/ipv6/ip6_input.c | 37 +++++++-----
9 files changed, 157 insertions(+), 65 deletions(-)
^ permalink raw reply
* [RFC] Discuss about an new idea "Vsock over Virtio-net"
From: jiangyiwen @ 2018-11-15 3:56 UTC (permalink / raw)
To: stefanha, stefanha, Jason Wang, mst; +Cc: netdev, kvm, virtualization
Hi Stefan, Michael, Jason and everyone,
Several days ago, I discussed with jason about "Vsock over Virtio-net".
This idea has two advantages:
First, it can use many great features of virtio-net, like batching,
mergeable rx buffer and multiqueue, etc.
Second, it can reduce many duplicate codes and make it easy to be
maintained.
Before the implement, I want to discuss with everyone again, and
want to know everyone's suggestions.
After the discussion, based on this point I will try to implement
this idea, but I am not familiar with the virtio-net, that is a
pity. :(
-------------------------Simple idea------------------------------
1. The packet layout will become as follows:
+---------------------------------+
| Virtio-net header |
|(struct virtio_net_hdr_mrg_rxbuf)|
+---------------------------------+
| Vsock header |
| (struct virtio_vsock_hdr) |
+---------------------------------+
| payload |
| (until end of packet) |
+---------------------------------+
2. The Guest->Host basic code flow as follow:
+------------+
| Client |
+------------+
|
|
+------------------------------------------------------------------+
|VSOCK Core Module |
|ops->sendmsg; (vsock_stream_sendmsg) |
| -> alloc_skb; /* it will packet a skb buffer, and include vsock |
| * hdr and payload */ |
| -> dev_queue_xmit(); /* it will call start_xmit(virtio-net.c) */|
|vsock hdr and payload, and then call |
+------------------------------------------------------------------+
|
|
+------------------------------------------------------------------+
|Virtio-net Module |
|start_xmit |
| -> add virtio_net_hdr and pack sg in ring desc, notify Host |
+------------------------------------------------------------------+
|
|
+------------------------------------------------------------------+
|Vhost-net Module |
|handle_tx |
| -> get tx buffer, skip virtio_net_hdr and call Vsock function. |
| /* This point has some differences, vhost-net use ->sendmsg to |
| * forward information, however vsock only need to notify server |
| * that data ready. */ |
+------------------------------------------------------------------+
|
|
+------------------------------------------------------------------+
|VSOCK Core Module |
|alloc_pkt, copy skb data to pkt. |
|add pkt to rx_queue and notify server to get data. |
+------------------------------------------------------------------+
3. To Host->Guest
I have a problem and difficult, mainly I know about virtio-net a little),
because I have been doing work related with storage and file system.
The problem as follows:
we should monitor all of socket of vsock in handle_rx, when there are
data coming, and copy data to vq desc. Vhost-net use ->recvmsg to
get data, it is different with socket. To vsock, I think host will
not call ->recvmsg when it need to send message to guest. To net,
vhost-net only as forwarding layer.
^ permalink raw reply
* Re: [RFC v1 1/3] udp_tunnel: add config option to bind to a device
From: Alexis Bauvin @ 2018-11-14 17:22 UTC (permalink / raw)
To: nicolas.dichtel, dsa, roopa; +Cc: netdev, akherbouche
In-Reply-To: <f6e43d80-4657-685e-b88b-452331744683@6wind.com>
Le 14 nov. 2018 à 17:07, Nicolas Dichtel <nicolas.dichtel@6wind.com> a écrit :
> Le 14/11/2018 à 10:31, Alexis Bauvin a écrit :
>> UDP tunnel sockets are always opened unbound to a specific device. This
>> patch allow the socket to be bound on a custom device, which
>> incidentally makes UDP tunnels VRF-aware if binding to an l3mdev.
>>
>> Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
>> Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
>> Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
> What is the difference with the previous version?
> Maybe a cover letter would help to track the history.
Unless a mistake from my side, you should have received the cover letter in
the previous email. The previous version had a typo in the commit log of the
third patch of this patch set.
> Regards,
> Nicolas
Regards,
Alexis
^ permalink raw reply
* [PATCH net v2] net: bridge: fix vlan stats use-after-free on destruction
From: Nikolay Aleksandrov @ 2018-11-14 17:27 UTC (permalink / raw)
To: netdev; +Cc: roopa, davem, bridge, syzkaller-bugs, Nikolay Aleksandrov
In-Reply-To: <ae147dd3-1ad8-8b8b-93f1-09297171883a@cumulusnetworks.com>
Syzbot reported a use-after-free of the global vlan context on port vlan
destruction. When I added per-port vlan stats I missed the fact that the
global vlan context can be freed before the per-port vlan rcu callback.
There're a few different ways to deal with this, I've chosen to add a
new private flag that is set only when per-port stats are allocated so
we can directly check it on destruction without dereferencing the global
context at all. The flag is internally controlled by the kernel and
user-space isn't allowed to set it.
Fixes: 9163a0fc1f0c ("net: bridge: add support for per-port vlan stats")
Reported-by: syzbot+04681da557a0e49a52e5@syzkaller.appspotmail.com
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
v2: cosmetic change, move the check to br_process_vlan_info where the
other checks are done
include/uapi/linux/if_bridge.h | 3 +++
net/bridge/br_netlink.c | 4 ++++
net/bridge/br_vlan.c | 3 ++-
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index e41eda3c71f1..fa1f72276712 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -130,6 +130,9 @@ enum {
#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */
#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */
#define BRIDGE_VLAN_INFO_BRENTRY (1<<5) /* Global bridge VLAN entry */
+#define BRIDGE_VLAN_INFO_PORT_STATS (1<<6) /* Per-port VLAN stats */
+
+#define BRIDGE_VLAN_INFO_PRIVATE_FLAGS BRIDGE_VLAN_INFO_PORT_STATS
struct bridge_vlan_info {
__u16 flags;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 3345f1984542..a017ed566b67 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -573,6 +573,10 @@ static int br_process_vlan_info(struct net_bridge *br,
if (!vinfo_curr->vid || vinfo_curr->vid >= VLAN_VID_MASK)
return -EINVAL;
+ /* don't allow user-space control over private flags */
+ if (vinfo_curr->flags & BRIDGE_VLAN_INFO_PRIVATE_FLAGS)
+ return -EINVAL;
+
if (vinfo_curr->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
/* check if we are already processing a range */
if (*vinfo_last)
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 8c9297a01947..004e1f8c5040 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -197,7 +197,7 @@ static void nbp_vlan_rcu_free(struct rcu_head *rcu)
v = container_of(rcu, struct net_bridge_vlan, rcu);
WARN_ON(br_vlan_is_master(v));
/* if we had per-port stats configured then free them here */
- if (v->brvlan->stats != v->stats)
+ if (v->flags & BRIDGE_VLAN_INFO_PORT_STATS)
free_percpu(v->stats);
v->stats = NULL;
kfree(v);
@@ -264,6 +264,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
err = -ENOMEM;
goto out_filt;
}
+ v->flags |= BRIDGE_VLAN_INFO_PORT_STATS;
} else {
v->stats = masterv->stats;
}
--
2.17.2
^ 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