Netdev List
 help / color / mirror / Atom feed
* [PATCH] rtnetlink: Handle IFLA_MASTER parameter when processing rtnl_newlink
From: Theuns Verwoerd @ 2017-01-30 23:23 UTC (permalink / raw)
  To: netdev; +Cc: dsa, Theuns Verwoerd

Allow a master interface to be specified as one of the parameters when
creating a new interface via rtnl_newlink.  Previously this would
require invoking interface creation, waiting for it to complete, and
then separately binding that new interface to a master.

In particular, this is used when creating a macvlan child interface for
VRRP in a VRF configuration, allowing the interface creator to specify
directly what master interface should be inherited by the child,
without having to deal with asynchronous complications and potential
race conditions.

Signed-off-by: Theuns Verwoerd <theuns.verwoerd@alliedtelesis.co.nz>
---
 net/core/rtnetlink.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 75e3ea7bda08..a24719c98238 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2571,7 +2571,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 			return -ENODEV;
 		}
 
-		if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
+		if (tb[IFLA_MAP] || tb[IFLA_PROTINFO])
 			return -EOPNOTSUPP;
 
 		if (!ops) {
@@ -2653,6 +2653,11 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 			if (err < 0)
 				goto out_unregister;
 		}
+		if (tb[IFLA_MASTER]) {
+			err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]));
+			if (err)
+				goto out_unregister;
+		}
 out:
 		if (link_net)
 			put_net(link_net);
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH] ipv6: fix flow labels when the traffic class is non-0
From: Dimitris Michailidis @ 2017-01-30 23:38 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, Tom Herbert, netdev
In-Reply-To: <CANn89iLUfp7Y+LkvZ80UsFEw8VZ23=F6_SDyPzpbyAvxxoNeLw@mail.gmail.com>

On Mon, Jan 30, 2017 at 2:23 PM, Eric Dumazet <edumazet@google.com> wrote:
> On Mon, Jan 30, 2017 at 2:09 PM, Dimitris Michailidis
> <dmichail@google.com> wrote:
>> ip6_make_flowlabel() determines the flow label for IPv6 packets. It's
>> supposed to be passed a flow label, which it returns as is if non-0 and
>> in some other cases, otherwise it calculates a new value.
>>
>> The problem is callers often pass a flowi6.flowlabel, which may also
>> contain traffic class bits.
>
> Do you have an idea which commit added this bug Dimitris ?

[Resending reply as text]

I believe it was wrong since cb1ce2ef387b01 ("ipv6: Implement
automatic flow label generation on transmit"), the commit that
introduced ip6_make_flowlabel(). The function was somewhat different
at the time but it was doing

       if (!flowlabel && (autolabel || net->ipv6.sysctl.auto_flowlabels)) {
       ...
       }
       return flowlabel;

 and all the callers were passing flowi6.flowlabel.

^ permalink raw reply

* Re: [PATCH] ipv6: fix flow labels when the traffic class is non-0
From: Tom Herbert @ 2017-01-30 23:40 UTC (permalink / raw)
  To: Dimitris Michailidis
  Cc: David S. Miller, Linux Kernel Network Developers, Eric Dumazet
In-Reply-To: <20170130220942.19105-1-dmichail@google.com>

On Mon, Jan 30, 2017 at 2:09 PM, Dimitris Michailidis
<dmichail@google.com> wrote:
> ip6_make_flowlabel() determines the flow label for IPv6 packets. It's
> supposed to be passed a flow label, which it returns as is if non-0 and
> in some other cases, otherwise it calculates a new value.
>
> The problem is callers often pass a flowi6.flowlabel, which may also
> contain traffic class bits. If the traffic class is non-0
> ip6_make_flowlabel() mistakes the non-0 it gets as a flow label and
> returns the whole thing. Thus it can return a 'flow label' longer than
> 20b and the low 20b of that is typically 0 resulting in packets with 0
> label. Moreover, different packets of a flow may be labeled differently.
> For a TCP flow with ECN non-payload and payload packets get different
> labels as exemplified by this pair of consecutive packets:
>
> (pure ACK)
> Internet Protocol Version 6, Src: 2002:af5:11a3::, Dst: 2002:af5:11a2::
>     0110 .... = Version: 6
>     .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
>         .... 0000 00.. .... .... .... .... .... = Differentiated Services Codepoint: Default (0)
>         .... .... ..00 .... .... .... .... .... = Explicit Congestion Notification: Not ECN-Capable Transport (0)
>     .... .... .... 0001 1100 1110 0100 1001 = Flow Label: 0x1ce49
>     Payload Length: 32
>     Next Header: TCP (6)
>
> (payload)
> Internet Protocol Version 6, Src: 2002:af5:11a3::, Dst: 2002:af5:11a2::
>     0110 .... = Version: 6
>     .... 0000 0010 .... .... .... .... .... = Traffic Class: 0x02 (DSCP: CS0, ECN: ECT(0))
>         .... 0000 00.. .... .... .... .... .... = Differentiated Services Codepoint: Default (0)
>         .... .... ..10 .... .... .... .... .... = Explicit Congestion Notification: ECN-Capable Transport codepoint '10' (2)
>     .... .... .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
>     Payload Length: 688
>     Next Header: TCP (6)
>
> This patch allows ip6_make_flowlabel() to be passed more than just a
> flow label and has it extract the part it really wants. This was simpler
> than modifying the callers. With this patch packets like the above become
>
> Internet Protocol Version 6, Src: 2002:af5:11a3::, Dst: 2002:af5:11a2::
>     0110 .... = Version: 6
>     .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
>         .... 0000 00.. .... .... .... .... .... = Differentiated Services Codepoint: Default (0)
>         .... .... ..00 .... .... .... .... .... = Explicit Congestion Notification: Not ECN-Capable Transport (0)
>     .... .... .... 1010 1111 1010 0101 1110 = Flow Label: 0xafa5e
>     Payload Length: 32
>     Next Header: TCP (6)
>
> Internet Protocol Version 6, Src: 2002:af5:11a3::, Dst: 2002:af5:11a2::
>     0110 .... = Version: 6
>     .... 0000 0010 .... .... .... .... .... = Traffic Class: 0x02 (DSCP: CS0, ECN: ECT(0))
>         .... 0000 00.. .... .... .... .... .... = Differentiated Services Codepoint: Default (0)
>         .... .... ..10 .... .... .... .... .... = Explicit Congestion Notification: ECN-Capable Transport codepoint '10' (2)
>     .... .... .... 1010 1111 1010 0101 1110 = Flow Label: 0xafa5e
>     Payload Length: 688
>     Next Header: TCP (6)
>
> Signed-off-by: Dimitris Michailidis <dmichail@google.com>
> ---
>  include/net/ipv6.h | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index 7afe991e900e..dbf0abba33b8 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -776,6 +776,11 @@ static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
>  {
>         u32 hash;
>
> +       /* @flowlabel may include more than a flow label, eg, the traffic class.
> +        * Here we want only the flow label value.
> +        */
> +       flowlabel &= IPV6_FLOWLABEL_MASK;
> +
Thanks for pointing out the issue, but I don't think this fix is quite
right. This would be discarding traffic class from being in the return
value. I can try to fix that.

Tom

>         if (flowlabel ||
>             net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF ||
>             (!autolabel &&
> --
> 2.11.0.483.g087da7b7c-goog
>

^ permalink raw reply

* Re: [PATCH] ipv6: fix flow labels when the traffic class is non-0
From: Eric Dumazet @ 2017-01-30 23:45 UTC (permalink / raw)
  To: Tom Herbert
  Cc: Dimitris Michailidis, David S. Miller,
	Linux Kernel Network Developers
In-Reply-To: <CALx6S375e127OSj9cHk4JuJLdee6tUmnBz7gSrsWTSLFP84JaA@mail.gmail.com>

On Mon, Jan 30, 2017 at 3:40 PM, Tom Herbert <tom@herbertland.com> wrote:

> Thanks for pointing out the issue, but I don't think this fix is quite
> right. This would be discarding traffic class from being in the return
> value. I can try to fix that.

Fix looks fine to me.

ip6_make_flowlabel() is usually used in an enclosing ip6_flow_hdr(),
which gives the tclass.

ip6_flow_hdr(hdr, tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel,

  np->autoflowlabel, fl6));

^ permalink raw reply

* Re: [PATCH net-next v3 0/4] net: ipv6: Improve user experience with multipath routes
From: David Ahern @ 2017-01-30 23:53 UTC (permalink / raw)
  To: Stephen Hemminger, Roopa Prabhu; +Cc: netdev, nicolas.dichtel
In-Reply-To: <20170130131600.00c21eb3@xeon-e3>

On 1/30/17 2:16 PM, Stephen Hemminger wrote:
> My fear is that routing daemons already adapt to the funny semantics of multi-path routing in IPv4 vs IPv6
> and therefore any change in semantics or flags risks breaking existing user space.

That is a possibility, but so far the 2 open source code bases I know of have problems with IPv6 mpath.

As I mentioned quagga does not work with IPv6 multipath as is today. 

I just looked at bird. IPv6 mpath support was added in Sept. 2016. It specifically hard codes not accepting RTA_MULTIPATH for IPv6 which I think is an odd choice and clearly coding to quirks as opposed to rtnetlink design. Having never looked at bird code I was able to get it working in < 1 hour. I will contact the patch author about that limitation. That said, the bird implementation needs work when you look at the add/delete/replace/append permutations, so the current code has its problems as well.

^ permalink raw reply

* Re: [PATCH net-next v3 0/4] net: ipv6: Improve user experience with multipath routes
From: Stephen Hemminger @ 2017-01-30 23:56 UTC (permalink / raw)
  To: David Ahern; +Cc: Roopa Prabhu, netdev, nicolas.dichtel
In-Reply-To: <7a363b93-bf14-9a13-d154-42a26ac06a06@cumulusnetworks.com>

On Mon, 30 Jan 2017 16:53:44 -0700
David Ahern <dsa@cumulusnetworks.com> wrote:

> On 1/30/17 2:16 PM, Stephen Hemminger wrote:
> > My fear is that routing daemons already adapt to the funny semantics of multi-path routing in IPv4 vs IPv6
> > and therefore any change in semantics or flags risks breaking existing user space.  
> 
> That is a possibility, but so far the 2 open source code bases I know of have problems with IPv6 mpath.

Breaking closed source is not acceptable either.

> 
> As I mentioned quagga does not work with IPv6 multipath as is today. 
> 
> I just looked at bird. IPv6 mpath support was added in Sept. 2016. It specifically hard codes not accepting RTA_MULTIPATH for IPv6 which I think is an odd choice and clearly coding to quirks as opposed to rtnetlink design. Having never looked at bird code I was able to get it working in < 1 hour. I will contact the patch author about that limitation. That said, the bird implementation needs work when you look at the add/delete/replace/append permutations, so the current code has its problems as well.

Also what if quagga was fixed but  had to work with existing enterprise distros?

^ permalink raw reply

* Re: [PATCH] rtnetlink: Handle IFLA_MASTER parameter when processing rtnl_newlink
From: Stephen Hemminger @ 2017-01-30 23:57 UTC (permalink / raw)
  To: Theuns Verwoerd; +Cc: netdev, dsa
In-Reply-To: <20170130232346.29761-1-theuns.verwoerd@alliedtelesis.co.nz>

On Tue, 31 Jan 2017 12:23:46 +1300
Theuns Verwoerd <theuns.verwoerd@alliedtelesis.co.nz> wrote:

> Allow a master interface to be specified as one of the parameters when
> creating a new interface via rtnl_newlink.  Previously this would
> require invoking interface creation, waiting for it to complete, and
> then separately binding that new interface to a master.
> 
> In particular, this is used when creating a macvlan child interface for
> VRRP in a VRF configuration, allowing the interface creator to specify
> directly what master interface should be inherited by the child,
> without having to deal with asynchronous complications and potential
> race conditions.
> 
> Signed-off-by: Theuns Verwoerd <theuns.verwoerd@alliedtelesis.co.nz>

Thanks it came through without modification by email client or server this time.

^ permalink raw reply

* Re: [PATCH] ipv6: fix flow labels when the traffic class is non-0
From: Dimitris Michailidis @ 2017-01-30 23:51 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Tom Herbert, David S. Miller, Linux Kernel Network Developers
In-Reply-To: <CANn89iLCyo8RgjHAg7YsQJCpS-P=76M5ZN1Ps3HhAzm-gZJpGw@mail.gmail.com>

On Mon, Jan 30, 2017 at 3:45 PM, Eric Dumazet <edumazet@google.com> wrote:
> On Mon, Jan 30, 2017 at 3:40 PM, Tom Herbert <tom@herbertland.com> wrote:
>
>> Thanks for pointing out the issue, but I don't think this fix is quite
>> right. This would be discarding traffic class from being in the return
>> value. I can try to fix that.
>
> Fix looks fine to me.
>
> ip6_make_flowlabel() is usually used in an enclosing ip6_flow_hdr(),
> which gives the tclass.
>
> ip6_flow_hdr(hdr, tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel,
>
>   np->autoflowlabel, fl6));

Yes, all the callers of ip6_make_flowlabel() I've seen feed the result
to ip6_flow_hdr().

^ permalink raw reply

* Re: [PATCH net-next v3 0/4] net: ipv6: Improve user experience with multipath routes
From: David Ahern @ 2017-01-31  0:02 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Roopa Prabhu, netdev, nicolas.dichtel
In-Reply-To: <20170130155630.787daf0a@xeon-e3>

On 1/30/17 4:56 PM, Stephen Hemminger wrote:
>>
>> As I mentioned quagga does not work with IPv6 multipath as is today. 
>>
>> I just looked at bird. IPv6 mpath support was added in Sept. 2016. It specifically hard codes not accepting RTA_MULTIPATH for IPv6 which I think is an odd choice and clearly coding to quirks as opposed to rtnetlink design. Having never looked at bird code I was able to get it working in < 1 hour. I will contact the patch author about that limitation. That said, the bird implementation needs work when you look at the add/delete/replace/append permutations, so the current code has its problems as well.
> 
> Also what if quagga was fixed but  had to work with existing enterprise distros?
> 

I am testing the patches; it will work on both.

^ permalink raw reply

* Re: [PATCH net-next] mpls: allow TTL propagation to/from IP packets to be configured
From: Eric W. Biederman @ 2017-01-31  0:17 UTC (permalink / raw)
  To: Robert Shearman; +Cc: davem, netdev, roopa
In-Reply-To: <1485808575-16852-1-git-send-email-rshearma@brocade.com>

Robert Shearman <rshearma@brocade.com> writes:

> It is sometimes desirable to present an MPLS transport network as a
> single hop to traffic transiting it because it prevents confusion when
> diagnosing failures. An example of where confusion can be generated is
> when addresses used in the provider network overlap with addresses in
> the overlay network and the addresses get exposed through ICMP errors
> generated as packets transit the provider network.
>
> Therefore, provide the ability to control whether the TTL value from
> an MPLS packet is propagated to an IPv4/IPv6 packet when the last
> label is popped through the addition of a new per-namespace sysctl:
> "net.mpls.ip_ttl_propagate" which defaults to enabled.
>
> Use the same sysctl to control whether the TTL is propagated from IP
> packets into the MPLS header. If the TTL isn't propagated then a
> default TTL value is used which can be configured via a new sysctl:
> "net.mpls.default_ttl".

Instead of having a global sysctl can we please have a different way
to configure the ingress/egress?

My general memory is that this makes sense for a slightly different
tunnel type.   Making it a per mpls tunnel property instead of global
property feels like it should be much more maintainable.

Similarly with the related behavior of what to do if the mpls ttl is
exhausted during the trip through the tunnel.  Drop or dig through the
packet and send an ICMP error message at the ip layer.

Eric

^ permalink raw reply

* Re: [PATCH net-next] mpls: allow TTL propagation to/from IP packets to be configured
From: David Ahern @ 2017-01-31  0:41 UTC (permalink / raw)
  To: Robert Shearman, davem; +Cc: netdev, roopa, ebiederm
In-Reply-To: <1485808575-16852-1-git-send-email-rshearma@brocade.com>

On 1/30/17 1:36 PM, Robert Shearman wrote:
> It is sometimes desirable to present an MPLS transport network as a
> single hop to traffic transiting it because it prevents confusion when
> diagnosing failures. An example of where confusion can be generated is
> when addresses used in the provider network overlap with addresses in
> the overlay network and the addresses get exposed through ICMP errors
> generated as packets transit the provider network.
> 
> Therefore, provide the ability to control whether the TTL value from
> an MPLS packet is propagated to an IPv4/IPv6 packet when the last
> label is popped through the addition of a new per-namespace sysctl:
> "net.mpls.ip_ttl_propagate" which defaults to enabled.
> 
> Use the same sysctl to control whether the TTL is propagated from IP
> packets into the MPLS header. If the TTL isn't propagated then a
> default TTL value is used which can be configured via a new sysctl:
> "net.mpls.default_ttl".
> 
> Signed-off-by: Robert Shearman <rshearma@brocade.com>
> ---
>  Documentation/networking/mpls-sysctl.txt | 19 +++++++++
>  include/net/netns/mpls.h                 |  3 ++
>  net/mpls/af_mpls.c                       | 70 ++++++++++++++++++++++++--------
>  net/mpls/mpls_iptunnel.c                 | 12 +++++-
>  4 files changed, 85 insertions(+), 19 deletions(-)
> 
> diff --git a/Documentation/networking/mpls-sysctl.txt b/Documentation/networking/mpls-sysctl.txt
> index 15d8d16934fd..b8f0725ff09e 100644
> --- a/Documentation/networking/mpls-sysctl.txt
> +++ b/Documentation/networking/mpls-sysctl.txt
> @@ -19,6 +19,25 @@ platform_labels - INTEGER
>  	Possible values: 0 - 1048575
>  	Default: 0
>  
> +ip_ttl_propagate - BOOL
> +	Control whether TTL is propagated from the IPv4/IPv6 header to
> +	the MPLS header on imposing labels and propagated from the
> +	MPLS header to the IPv4/IPv6 header on popping the last label.
> +
> +	If disabled, the MPLS transport network will appear as a
> +	single hop to transit traffic.
> +
> +	0 - disabled
> +	1 - enabled (default)
> +

It seems like you are going after RFC 3443 with this change. Can you add comment to that effect? i.e.,  ip_ttl_propagate enabled is the Uniform Model and ip_ttl_propagate disabled is the Short Pipe Model.

^ permalink raw reply

* Re: [PATCHv3 perf/core 1/6] tools lib bpf: Add BPF program pinning APIs.
From: Arnaldo Carvalho de Melo @ 2017-01-31  0:58 UTC (permalink / raw)
  To: Joe Stringer; +Cc: Wang Nan, ast, Daniel Borkmann, LKML, netdev
In-Reply-To: <CAPWQB7FDThp03e6DTHio8Myv5e8J6RcDXK-jG8W6B7Sh2Gvisw@mail.gmail.com>

Em Mon, Jan 30, 2017 at 01:16:18PM -0800, Joe Stringer escreveu:
> On 30 January 2017 at 12:28, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> > ---
> > Thus, a return value of size or more means that the output was
> > truncated.
> > ---
 
> Good spotting, I looked over the committed versions and tested them,
> they seem good to me. Thanks!

Thanks for checking, will push Ingo's way after a battery of extra
tests, tomorrow,

- Arnaldo

^ permalink raw reply

* [PATCH -next] net/phy: fix phy_bcm_nsp_usb3.c build and kconfig
From: Randy Dunlap @ 2017-01-31  1:02 UTC (permalink / raw)
  To: netdev@vger.kernel.org, David Miller; +Cc: Yendapally Reddy Dhananjaya Reddy

From: Randy Dunlap <rdunlap@infradead.org>

This driver uses mdio* (PHYLIB) interfaces, so it should select
PHYLIB. PHYLIB depends on NETDEVICES to this driver should also
depend on NETDEVICES.

Fixes these build errors:

drivers/built-in.o: In function `nsp_usb3_phy_init':
phy-bcm-nsp-usb3.c:(.text+0x42d8): undefined reference to `mdiobus_write'
phy-bcm-nsp-usb3.c:(.text+0x42f4): undefined reference to `mdiobus_write'
phy-bcm-nsp-usb3.c:(.text+0x4310): undefined reference to `mdiobus_write'
phy-bcm-nsp-usb3.c:(.text+0x432c): undefined reference to `mdiobus_write'
phy-bcm-nsp-usb3.c:(.text+0x4348): undefined reference to `mdiobus_write'
drivers/built-in.o:phy-bcm-nsp-usb3.c:(.text+0x437a): more undefined references to `mdiobus_write' follow
drivers/built-in.o: In function `mdio_module_init':
phy-bcm-nsp-usb3.c:(.init.text+0x1e1): undefined reference to `mdio_driver_register'
drivers/built-in.o: In function `mdio_module_exit':
phy-bcm-nsp-usb3.c:(.exit.text+0xae): undefined reference to `mdio_driver_unregister'

Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Cc: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
 drivers/phy/Kconfig |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- linux-next-20170130.orig/drivers/phy/Kconfig
+++ linux-next-20170130/drivers/phy/Kconfig
@@ -504,8 +504,9 @@ config PHY_MESON8B_USB2
 
 config PHY_NSP_USB3
 	tristate "Broadcom NorthStar plus USB3 PHY driver"
-	depends on OF && (ARCH_BCM_NSP || COMPILE_TEST)
+	depends on OF && (ARCH_BCM_NSP || COMPILE_TEST) && NETDEVICES
 	select GENERIC_PHY
+	select PHYLIB
 	default ARCH_BCM_NSP
 	help
 	  Enable this to support the Broadcom Northstar plus USB3 PHY.

^ permalink raw reply

* Re: [PATCH net-next] mpls: allow TTL propagation to/from IP packets to be configured
From: David Ahern @ 2017-01-31  1:09 UTC (permalink / raw)
  To: Robert Shearman, davem; +Cc: netdev, roopa, ebiederm
In-Reply-To: <1485808575-16852-1-git-send-email-rshearma@brocade.com>

On 1/30/17 1:36 PM, Robert Shearman wrote:
> @@ -243,24 +245,29 @@ static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb,
>  		payload_type = ip_hdr(skb)->version;
>  
>  	switch (payload_type) {
> -	case MPT_IPV4: {
> -		struct iphdr *hdr4 = ip_hdr(skb);
> -		skb->protocol = htons(ETH_P_IP);
> -		csum_replace2(&hdr4->check,
> -			      htons(hdr4->ttl << 8),
> -			      htons(dec.ttl << 8));
> -		hdr4->ttl = dec.ttl;
> +	case MPT_IPV4:
> +		if (net->mpls.ip_ttl_propagate) {
> +			struct iphdr *hdr4 = ip_hdr(skb);
> +
> +			skb->protocol = htons(ETH_P_IP);

The protocol setting here and ...

> +			csum_replace2(&hdr4->check,
> +				      htons(hdr4->ttl << 8),
> +				      htons(dec.ttl << 8));
> +			hdr4->ttl = dec.ttl;
> +		}
>  		success = true;
>  		break;
> -	}
> -	case MPT_IPV6: {
> -		struct ipv6hdr *hdr6 = ipv6_hdr(skb);
> -		skb->protocol = htons(ETH_P_IPV6);
> -		hdr6->hop_limit = dec.ttl;
> +	case MPT_IPV6:
> +		if (net->mpls.ip_ttl_propagate) {
> +			struct ipv6hdr *hdr6 = ipv6_hdr(skb);
> +
> +			skb->protocol = htons(ETH_P_IPV6);

here need to be done outside of net->mpls.ip_ttl_propagate otherwise ...

> +			hdr6->hop_limit = dec.ttl;
> +		}
>  		success = true;
>  		break;
> -	}
>  	case MPT_UNSPEC:
> +		/* Should have decided which protocol it is by now */
>  		break;
>  	}
>  

disabling ip_ttl_propagate causes a corrupted packet to show up at the end host (after the LSP):

IP4:
16:54:08.895372 46:a9:1c:9f:30:ba > fa:61:57:d6:1a:7d, ethertype MPLS unicast (0x8847), length 98: MPLS (label 282624, exp 0, ttl 84)
	(label 433380, exp 0, ttl 0)
	(label 262160, exp 7, [S], ttl 182)
	0x0000:  ac10 0101 0a0a 0a0a 0800 1677 05d3 0001  ...........w....
	0x0010:  30e0 8f58 0000 0000 4fa9 0d00 0000 0000  0..X....O.......
	0x0020:  1011 1213 1415 1617 1819 1a1b 1c1d 1e1f  ................
	0x0030:  2021 2223 2425 2627 2829 2a2b 2c2d 2e2f  .!"#$%&'()*+,-./
	0x0040:  3031 3233 3435 3637                      01234567


IPv6:
16:57:40.517520 46:a9:1c:9f:30:ba > fa:61:57:d6:1a:7d, ethertype MPLS unicast (0x8847), length 118: MPLS (label 393290, exp 5, ttl 240)
	(label 1027, exp 5, ttl 64)
	(label 131072, exp 0, ttl 1)
	(label 0 (IPv4 explicit NULL), exp 0, ttl 0)
	(label 0 (IPv4 explicit NULL), exp 0, ttl 0)
	(label 0 (IPv4 explicit NULL), exp 0, ttl 1)
	(label 196608, exp 0, ttl 1)
	(label 0 (IPv4 explicit NULL), exp 0, ttl 0)
	(label 0 (IPv4 explicit NULL), exp 0, ttl 0)
	(label 0 (IPv4 explicit NULL), exp 0, ttl 1)
	(label 524297, exp 1, [S], ttl 102)
	0x0000:  0628 0001 04e1 8f58 0000 0000 3be5 0700  .(.....X....;...
	0x0010:  0000 0000 1011 1213 1415 1617 1819 1a1b  ................
	0x0020:  1c1d 1e1f 2021 2223 2425 2627 2829 2a2b  .....!"#$%&'()*+
	0x0030:  2c2d 2e2f 3031 3233 3435 3637            ,-./01234567

^ permalink raw reply

* Re: [PATCH -next] net/phy: fix phy_bcm_nsp_usb3.c build and kconfig
From: Florian Fainelli @ 2017-01-31  1:13 UTC (permalink / raw)
  To: Randy Dunlap, netdev@vger.kernel.org, David Miller
  Cc: Yendapally Reddy Dhananjaya Reddy, Andrew Lunn
In-Reply-To: <8b028a54-08a1-8e53-04ab-3fa8c51d2369@infradead.org>

On 01/30/2017 05:02 PM, Randy Dunlap wrote:
> From: Randy Dunlap <rdunlap@infradead.org>
> 
> This driver uses mdio* (PHYLIB) interfaces, so it should select
> PHYLIB. PHYLIB depends on NETDEVICES to this driver should also
> depend on NETDEVICES.
> 
> Fixes these build errors:
> 
> drivers/built-in.o: In function `nsp_usb3_phy_init':
> phy-bcm-nsp-usb3.c:(.text+0x42d8): undefined reference to `mdiobus_write'
> phy-bcm-nsp-usb3.c:(.text+0x42f4): undefined reference to `mdiobus_write'
> phy-bcm-nsp-usb3.c:(.text+0x4310): undefined reference to `mdiobus_write'
> phy-bcm-nsp-usb3.c:(.text+0x432c): undefined reference to `mdiobus_write'
> phy-bcm-nsp-usb3.c:(.text+0x4348): undefined reference to `mdiobus_write'
> drivers/built-in.o:phy-bcm-nsp-usb3.c:(.text+0x437a): more undefined references to `mdiobus_write' follow
> drivers/built-in.o: In function `mdio_module_init':
> phy-bcm-nsp-usb3.c:(.init.text+0x1e1): undefined reference to `mdio_driver_register'
> drivers/built-in.o: In function `mdio_module_exit':
> phy-bcm-nsp-usb3.c:(.exit.text+0xae): undefined reference to `mdio_driver_unregister'
> 
> Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
> Cc: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>

Acked-by: Florian Fainelli <f.fainelli@gmail.com>

This is certainly a good fix for now, but I think we really need to
split the PHY library and its state machine from generic support for
MDIO buses and devices, let me see if I can come up with something for that.

Thanks!

> ---
>  drivers/phy/Kconfig |    3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> --- linux-next-20170130.orig/drivers/phy/Kconfig
> +++ linux-next-20170130/drivers/phy/Kconfig
> @@ -504,8 +504,9 @@ config PHY_MESON8B_USB2
>  
>  config PHY_NSP_USB3
>  	tristate "Broadcom NorthStar plus USB3 PHY driver"
> -	depends on OF && (ARCH_BCM_NSP || COMPILE_TEST)
> +	depends on OF && (ARCH_BCM_NSP || COMPILE_TEST) && NETDEVICES
>  	select GENERIC_PHY
> +	select PHYLIB
>  	default ARCH_BCM_NSP
>  	help
>  	  Enable this to support the Broadcom Northstar plus USB3 PHY.
> 


-- 
Florian

^ permalink raw reply

* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2017-01-31  1:18 UTC (permalink / raw)
  To: David Miller, Networking
  Cc: linux-next, linux-kernel, Rafal Ozieblo, Andrei Pistirica

Hi all,

Today's linux-next merge of the net-next tree got a conflict in:

  drivers/net/ethernet/cadence/macb.h

between commit:

  dc97a89e726c ("net: macb: Fix 64 bit addressing support for GEM")

from the net tree and commit:

  c2594d804d5c ("macb: Common code to enable ptp support for MACB/GEM")

from the net-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc drivers/net/ethernet/cadence/macb.h
index fc8550a5d47f,94ddedd2d83e..000000000000
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@@ -385,9 -426,18 +426,20 @@@
  /* Bitfields in DCFG6. */
  #define GEM_PBUF_LSO_OFFSET			27
  #define GEM_PBUF_LSO_SIZE			1
 +#define GEM_DAW64_OFFSET			23
 +#define GEM_DAW64_SIZE				1
  
+ /* Bitfields in TISUBN */
+ #define GEM_SUBNSINCR_OFFSET			0
+ #define GEM_SUBNSINCR_SIZE			16
+ 
+ /* Bitfields in TI */
+ #define GEM_NSINCR_OFFSET			0
+ #define GEM_NSINCR_SIZE				8
+ 
+ /* Bitfields in ADJ */
+ #define GEM_ADDSUB_OFFSET			31
+ #define GEM_ADDSUB_SIZE				1
  /* Constants for CLK */
  #define MACB_CLK_DIV8				0
  #define MACB_CLK_DIV16				1
@@@ -885,9 -942,7 +952,11 @@@ struct macb 
  
  	u32			wol;
  
 +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 +	enum macb_hw_dma_cap hw_dma_cap;
 +#endif
++
+ 	struct macb_ptp_info	*ptp_info;	/* macb-ptp interface */
  };
  
  static inline bool macb_is_gem(struct macb *bp)

^ permalink raw reply

* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2017-01-31  1:23 UTC (permalink / raw)
  To: David Miller, Networking
  Cc: linux-next, linux-kernel, Hadar Hen Zion, Saeed Mahameed,
	Or Gerlitz

Hi all,

Today's linux-next merge of the net-next tree got a conflict in:

  drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

between commit:

  3e621b19b0bb ("net/mlx5e: Support TC encapsulation offloads with upper devices")

from the net tree and commits:

  75c33da82736 ("net/mlx5e: TC ipv4 tunnel encap offload cosmetic changes")
  9a941117fb76 ("net/mlx5e: Maximize ip tunnel key usage on the TC offloading path")

from the net-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index c5282b6aba8b,640f10f2e994..000000000000
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@@ -660,13 -684,10 +684,11 @@@ static int mlx5e_route_lookup_ipv4(stru
  				   struct net_device **out_dev,
  				   struct flowi4 *fl4,
  				   struct neighbour **out_n,
- 				   __be32 *saddr,
  				   int *out_ttl)
  {
 +	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
  	struct rtable *rt;
  	struct neighbour *n = NULL;
- 	int ttl;
  
  #if IS_ENABLED(CONFIG_INET)
  	int ret;
@@@ -678,21 -699,21 +700,19 @@@
  #else
  	return -EOPNOTSUPP;
  #endif
 -
 -	if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev)) {
 -		pr_warn("%s: can't offload, devices not on same HW e-switch\n", __func__);
 -		ip_rt_put(rt);
 -		return -EOPNOTSUPP;
 -	}
 +	/* if the egress device isn't on the same HW e-switch, we use the uplink */
 +	if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev))
 +		*out_dev = mlx5_eswitch_get_uplink_netdev(esw);
 +	else
 +		*out_dev = rt->dst.dev;
  
- 	ttl = ip4_dst_hoplimit(&rt->dst);
+ 	*out_ttl = ip4_dst_hoplimit(&rt->dst);
  	n = dst_neigh_lookup(&rt->dst, &fl4->daddr);
  	ip_rt_put(rt);
  	if (!n)
  		return -ENOMEM;
  
  	*out_n = n;
- 	*saddr = fl4->saddr;
- 	*out_ttl = ttl;
 -	*out_dev = rt->dst.dev;
  
  	return 0;
  }

^ permalink raw reply

* Re: [RFC PATCH 1/2] af_packet: direct dma for packet ineterface
From: Willem de Bruijn @ 2017-01-31  1:31 UTC (permalink / raw)
  To: John Fastabend
  Cc: Jesper Dangaard Brouer, bjorn.topel, jasowang, ast,
	alexander.duyck, john.r.fastabend, Network Development
In-Reply-To: <588FB57B.1060507@gmail.com>

>>> V3 header formats added bulk polling via socket calls and timers
>>> used in the polling interface to return every n milliseconds. Currently,
>>> I don't see any way to support this in hardware because we can't
>>> know if the hardware is in the middle of a DMA operation or not
>>> on a slot. So when a timer fires I don't know how to advance the
>>> descriptor ring leaving empty descriptors similar to how the software
>>> ring works. The easiest (best?) route is to simply not support this.
>>
>> From a performance pov bulking is essential. Systems like netmap that
>> also depend on transferring control between kernel and userspace,
>> report[1] that they need at least bulking size 8, to amortize the overhead.

To introduce interrupt moderation, ixgbe_do_ddma only has to elide the
sk_data_ready, and schedule an hrtimer if one is not scheduled yet.

If I understand correctly, the difficulty lies in v3 requiring that the
timer "close" the block when the timer expires. That may not be worth
implementing, indeed.

Hardware interrupt moderation and napi may already give some
moderation, even with a sock_def_readable call for each packet. If
considering a v4 format, I'll again suggest virtio virtqueues. Those
have interrupt suppression built in with EVENT_IDX.

>> Likely, but I would like that we do a measurement based approach.  Lets
>> benchmark with this V2 header format, and see how far we are from
>> target, and see what lights-up in perf report and if it is something we
>> can address.
>
> Yep I'm hoping to get to this sometime this week.

Perhaps also without filling in the optional metadata data fields
in tpacket and sockaddr_ll.

>> E.g. how will you support XDP_TX?  AFAIK you cannot remove/detach a
>> packet with this solution (and place it on a TX queue and wait for DMA
>> TX completion).
>>
>
> This is something worth exploring. tpacket_v2 uses a fixed ring with
> slots so all the pages are allocated and assigned to the ring at init
> time. To xmit a packet in this case the user space application would
> be required to leave the packet descriptor on the rx side pinned
> until the tx side DMA has completed. Then it can unpin the rx side
> and return it to the driver. This works if the TX/RX processing is
> fast enough to keep up. For many things this is good enough.
>
> For some work loads though this may not be sufficient. In which
> case a tpacket_v4 would be useful that can push down a new set
> of "slots" every n packets. Where n is sufficiently large to keep
> the workload running.

Here, too, virtio rings may help.

The extra level of indirection allows out of order completions,
reducing the chance of running out of rx descriptors when redirecting
a subset of packets to a tx ring, as that does not block the entire ring.

And passing explicit descriptors from userspace enables pointing to
new memory regions. On the flipside, they now have to be checked for
safety against region bounds.

> This is similar in many ways to virtio/vhost interaction.

Ah, I only saw this after writing the above :)

^ permalink raw reply

* [PATCH net-next 00/10] bnxt_en: Add XDP support.
From: Michael Chan @ 2017-01-31  1:49 UTC (permalink / raw)
  To: davem; +Cc: netdev

The first 8 patches refactor the code (rx/tx code paths and ring logic)
and add the basic infrastructure to support XDP.  The 9th patch adds
basic ndo_xdp to support XDP_DROP and XDP_PASS only.  The 10th patch
completes the series with XDP_TX.

Michael Chan (10):
  bnxt_en: Refactor rx SKB function.
  bnxt_en: Add bp->rx_dir field for rx buffer DMA direction.
  bnxt_en: Add RX page mode support.
  bnxt_en: Use event bit map in RX path.
  bnxt_en: Centralize logic to reserve rings.
  bnxt_en: Add tx ring mapping logic.
  bnxt_en: Add a set of TX rings to support XDP.
  bnxt_en: Refactor tx completion path.
  bnxt_en: Add basic XDP support.
  bnxt_en: Add support for XDP_TX action.

 drivers/net/ethernet/broadcom/Kconfig             |   8 +
 drivers/net/ethernet/broadcom/bnxt/Makefile       |   2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c         | 347 ++++++++++++++++------
 drivers/net/ethernet/broadcom/bnxt/bnxt.h         |  56 +++-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c |  53 ++--
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c     | 231 ++++++++++++++
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h     |  30 ++
 7 files changed, 599 insertions(+), 128 deletions(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
 create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h

-- 
1.8.3.1

^ permalink raw reply

* [PATCH net-next 02/10] bnxt_en: Add bp->rx_dir field for rx buffer DMA direction.
From: Michael Chan @ 2017-01-31  1:49 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1485827375-20421-1-git-send-email-michael.chan@broadcom.com>

When driver is running in XDP mode, rx buffers are DMA mapped as
DMA_BIDIRECTIONAL.  Add a field so the code will map/unmap rx buffers
according to this field.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c | 22 ++++++++++------------
 drivers/net/ethernet/broadcom/bnxt/bnxt.h |  1 +
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index d419199..c343ade 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -584,7 +584,7 @@ static inline u8 *__bnxt_alloc_rx_data(struct bnxt *bp, dma_addr_t *mapping,
 		return NULL;
 
 	*mapping = dma_map_single(&pdev->dev, data + BNXT_RX_DMA_OFFSET,
-				  bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+				  bp->rx_buf_use_size, bp->rx_dir);
 
 	if (dma_mapping_error(&pdev->dev, *mapping)) {
 		kfree(data);
@@ -771,7 +771,7 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp,
 
 	skb = build_skb(data, 0);
 	dma_unmap_single(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
-			 PCI_DMA_FROMDEVICE);
+			 bp->rx_dir);
 	if (!skb) {
 		kfree(data);
 		return NULL;
@@ -877,15 +877,14 @@ static inline struct sk_buff *bnxt_copy_skb(struct bnxt_napi *bnapi, u8 *data,
 	if (!skb)
 		return NULL;
 
-	dma_sync_single_for_cpu(&pdev->dev, mapping,
-				bp->rx_copy_thresh, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_cpu(&pdev->dev, mapping, bp->rx_copy_thresh,
+				bp->rx_dir);
 
 	memcpy(skb->data - NET_IP_ALIGN, data - NET_IP_ALIGN,
 	       len + NET_IP_ALIGN);
 
-	dma_sync_single_for_device(&pdev->dev, mapping,
-				   bp->rx_copy_thresh,
-				   PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_device(&pdev->dev, mapping, bp->rx_copy_thresh,
+				   bp->rx_dir);
 
 	skb_put(skb, len);
 	return skb;
@@ -1260,7 +1259,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
 
 		skb = build_skb(data, 0);
 		dma_unmap_single(&bp->pdev->dev, mapping, bp->rx_buf_use_size,
-				 PCI_DMA_FROMDEVICE);
+				 bp->rx_dir);
 
 		if (!skb) {
 			kfree(data);
@@ -1879,8 +1878,7 @@ static void bnxt_free_rx_skbs(struct bnxt *bp)
 				dma_unmap_single(
 					&pdev->dev,
 					dma_unmap_addr(tpa_info, mapping),
-					bp->rx_buf_use_size,
-					PCI_DMA_FROMDEVICE);
+					bp->rx_buf_use_size, bp->rx_dir);
 
 				tpa_info->data = NULL;
 
@@ -1897,8 +1895,7 @@ static void bnxt_free_rx_skbs(struct bnxt *bp)
 
 			dma_unmap_single(&pdev->dev,
 					 dma_unmap_addr(rx_buf, mapping),
-					 bp->rx_buf_use_size,
-					 PCI_DMA_FROMDEVICE);
+					 bp->rx_buf_use_size, bp->rx_dir);
 
 			rx_buf->data = NULL;
 
@@ -2563,6 +2560,7 @@ void bnxt_set_ring_params(struct bnxt *bp)
 
 static int bnxt_set_rx_skb_mode(struct bnxt *bp)
 {
+	bp->rx_dir = DMA_FROM_DEVICE;
 	bp->rx_skb_func = bnxt_rx_skb;
 	return 0;
 }
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 33302b0..b0da02d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -997,6 +997,7 @@ struct bnxt {
 
 	u32			rx_buf_size;
 	u32			rx_buf_use_size;	/* useable size */
+	enum dma_data_direction	rx_dir;
 	u32			rx_ring_size;
 	u32			rx_agg_ring_size;
 	u32			rx_copy_thresh;
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 09/10] bnxt_en: Add basic XDP support.
From: Michael Chan @ 2017-01-31  1:49 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1485827375-20421-1-git-send-email-michael.chan@broadcom.com>

Add basic ndo_xdp support to setup and query program, configure the NIC
to run in rx page mode, and support XDP_PASS, XDP_DROP, XDP_ABORTED
actions only.  Use Kconfig option to enable XDP support.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Tested-by: Andy Gospodarek <gospo@broadcom.com>
---
 drivers/net/ethernet/broadcom/Kconfig         |   8 ++
 drivers/net/ethernet/broadcom/bnxt/Makefile   |   2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  29 +++++-
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |   6 ++
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 141 ++++++++++++++++++++++++++
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h |  28 +++++
 6 files changed, 210 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
 create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h

diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 940fb24..ca543a4 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -213,4 +213,12 @@ config BNXT_DCB
 
 	  If unsure, say N.
 
+config BNXT_XDP
+	bool "Xpress Data Path (XDP) driver support"
+	default n
+	depends on BNXT && BPF
+	---help---
+	  Say Y here if you want to enable XDP in the driver to support
+	  eBPF programs in the fast path.
+
 endif # NET_VENDOR_BROADCOM
diff --git a/drivers/net/ethernet/broadcom/bnxt/Makefile b/drivers/net/ethernet/broadcom/bnxt/Makefile
index 6082ed1..a7ca45b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/Makefile
+++ b/drivers/net/ethernet/broadcom/bnxt/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_BNXT) += bnxt_en.o
 
-bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o
+bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index d9098ee..ae1f400 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -33,6 +33,7 @@
 #include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/rtc.h>
+#include <linux/bpf.h>
 #include <net/ip.h>
 #include <net/tcp.h>
 #include <net/udp.h>
@@ -53,6 +54,7 @@
 #include "bnxt_sriov.h"
 #include "bnxt_ethtool.h"
 #include "bnxt_dcb.h"
+#include "bnxt_xdp.h"
 
 #define BNXT_TX_TIMEOUT		(5 * HZ)
 
@@ -643,8 +645,7 @@ static inline int bnxt_alloc_rx_data(struct bnxt *bp,
 	return 0;
 }
 
-static void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons,
-			       void *data)
+void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, void *data)
 {
 	u16 prod = rxr->rx_prod;
 	struct bnxt_sw_rx_bd *cons_rx_buf, *prod_rx_buf;
@@ -1476,6 +1477,11 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
 	len = le32_to_cpu(rxcmp->rx_cmp_len_flags_type) >> RX_CMP_LEN_SHIFT;
 	dma_addr = dma_unmap_addr(rx_buf, mapping);
 
+	if (bnxt_rx_xdp(rxr, cons, data, data_ptr, len, dma_addr, event)) {
+		rc = 1;
+		goto next_rx;
+	}
+
 	if (len <= bp->rx_copy_thresh) {
 		skb = bnxt_copy_skb(bnapi, data_ptr, len, dma_addr);
 		bnxt_reuse_rx_data(rxr, cons, data);
@@ -2081,6 +2087,9 @@ static void bnxt_free_rx_rings(struct bnxt *bp)
 		struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
 		struct bnxt_ring_struct *ring;
 
+		if (rxr->xdp_prog)
+			bpf_prog_put(rxr->xdp_prog);
+
 		kfree(rxr->rx_tpa);
 		rxr->rx_tpa = NULL;
 
@@ -2368,6 +2377,15 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
 	ring = &rxr->rx_ring_struct;
 	bnxt_init_rxbd_pages(ring, type);
 
+	if (BNXT_RX_PAGE_MODE(bp) && bp->xdp_prog) {
+		rxr->xdp_prog = bpf_prog_add(bp->xdp_prog, 1);
+		if (IS_ERR(rxr->xdp_prog)) {
+			int rc = PTR_ERR(rxr->xdp_prog);
+
+			rxr->xdp_prog = NULL;
+			return rc;
+		}
+	}
 	prod = rxr->rx_prod;
 	for (i = 0; i < bp->rx_ring_size; i++) {
 		if (bnxt_alloc_rx_data(bp, rxr, prod, GFP_KERNEL) != 0) {
@@ -2553,7 +2571,7 @@ static int bnxt_calc_nr_ring_pages(u32 ring_size, int desc_per_pg)
 	return pages;
 }
 
-static void bnxt_set_tpa_flags(struct bnxt *bp)
+void bnxt_set_tpa_flags(struct bnxt *bp)
 {
 	bp->flags &= ~BNXT_FLAG_TPA;
 	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
@@ -7097,6 +7115,9 @@ static void bnxt_udp_tunnel_del(struct net_device *dev,
 #endif
 	.ndo_udp_tunnel_add	= bnxt_udp_tunnel_add,
 	.ndo_udp_tunnel_del	= bnxt_udp_tunnel_del,
+#ifdef CONFIG_BNXT_XDP
+	.ndo_xdp		= bnxt_xdp,
+#endif
 };
 
 static void bnxt_remove_one(struct pci_dev *pdev)
@@ -7121,6 +7142,8 @@ static void bnxt_remove_one(struct pci_dev *pdev)
 	pci_iounmap(pdev, bp->bar0);
 	kfree(bp->edev);
 	bp->edev = NULL;
+	if (bp->xdp_prog)
+		bpf_prog_put(bp->xdp_prog);
 	free_netdev(dev);
 
 	pci_release_regions(pdev);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index f5d5971..007e779 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -620,6 +620,8 @@ struct bnxt_rx_ring_info {
 	void __iomem		*rx_doorbell;
 	void __iomem		*rx_agg_doorbell;
 
+	struct bpf_prog		*xdp_prog;
+
 	struct rx_bd		*rx_desc_ring[MAX_RX_PAGES];
 	struct bnxt_sw_rx_bd	*rx_buf_ring;
 
@@ -1167,6 +1169,8 @@ struct bnxt {
 
 	u8			num_leds;
 	struct bnxt_led_info	leds[BNXT_MAX_LED];
+
+	struct bpf_prog		*xdp_prog;
 };
 
 #define BNXT_RX_STATS_OFFSET(counter)			\
@@ -1186,6 +1190,8 @@ struct bnxt {
 #define SFF_MODULE_ID_QSFP28			0x11
 #define BNXT_MAX_PHY_I2C_RESP_SIZE		64
 
+void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, void *data);
+void bnxt_set_tpa_flags(struct bnxt *bp);
 void bnxt_set_ring_params(struct bnxt *);
 int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode);
 void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
new file mode 100644
index 0000000..133e515
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -0,0 +1,141 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016-2017 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/bpf.h>
+#include <linux/filter.h>
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_xdp.h"
+
+#ifdef CONFIG_BNXT_XDP
+/* returns the following:
+ * true    - packet consumed by XDP and new buffer is allocated.
+ * false   - packet should be passed to the stack.
+ */
+bool bnxt_rx_xdp(struct bnxt_rx_ring_info *rxr, u16 cons, void *data,
+		 u8 *data_ptr, unsigned int len, dma_addr_t dma_addr,
+		 u8 *event)
+{
+	struct bpf_prog *xdp_prog = READ_ONCE(rxr->xdp_prog);
+	struct xdp_buff xdp;
+	u32 act;
+
+	if (!xdp_prog)
+		return false;
+
+	xdp.data = data_ptr;
+	xdp.data_end = xdp.data + len;
+	rcu_read_lock();
+	act = bpf_prog_run_xdp(xdp_prog, &xdp);
+	rcu_read_unlock();
+
+	switch (act) {
+	case XDP_PASS:
+		return false;
+
+	default:
+		bpf_warn_invalid_xdp_action(act);
+		/* Fall thru */
+	case XDP_DROP:
+	case XDP_ABORTED:
+		bnxt_reuse_rx_data(rxr, cons, data);
+		break;
+	}
+	return true;
+}
+
+/* Under rtnl_lock */
+static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
+{
+	struct net_device *dev = bp->dev;
+	int tx_xdp = 0, rc, tc;
+	struct bpf_prog *old;
+
+	if (prog && prog->xdp_adjust_head) {
+		netdev_err(dev, "Does not support bpf_xdp_adjust_head().\n");
+		return -EOPNOTSUPP;
+	}
+	if (prog && bp->dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
+		netdev_err(dev, "MTU %d larger than largest XDP supported MTU %d.\n",
+			   bp->dev->mtu, BNXT_MAX_PAGE_MODE_MTU);
+		return -EOPNOTSUPP;
+	}
+	if (!(bp->flags & BNXT_FLAG_SHARED_RINGS)) {
+		netdev_err(dev, "ethtool rx/tx channels must be combined to support XDP.\n");
+		return -EOPNOTSUPP;
+	}
+	if (prog)
+		tx_xdp = bp->rx_nr_rings;
+
+	tc = netdev_get_num_tc(dev);
+	if (!tc)
+		tc = 1;
+	rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings,
+				tc, tx_xdp);
+	if (rc) {
+		netdev_err(dev, "Unable to reserve enough TX rings to support XDP.\n");
+		return rc;
+	}
+	if (netif_running(dev))
+		bnxt_close_nic(bp, true, false);
+
+	old = xchg(&bp->xdp_prog, prog);
+	if (old)
+		bpf_prog_put(old);
+
+	if (prog) {
+		bnxt_set_rx_skb_mode(bp, true);
+	} else {
+		bool sh = (bp->flags & BNXT_FLAG_SHARED_RINGS) ? true : false;
+		int rx, tx;
+
+		bnxt_set_rx_skb_mode(bp, false);
+		bnxt_get_max_rings(bp, &rx, &tx, sh);
+		if (rx > 1) {
+			bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS;
+			bp->dev->hw_features |= NETIF_F_LRO;
+		}
+	}
+	bp->tx_nr_rings_xdp = tx_xdp;
+	bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc + tx_xdp;
+	bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings);
+	bp->num_stat_ctxs = bp->cp_nr_rings;
+	bnxt_set_tpa_flags(bp);
+	bnxt_set_ring_params(bp);
+
+	if (netif_running(dev))
+		return bnxt_open_nic(bp, true, false);
+
+	return 0;
+}
+
+int bnxt_xdp(struct net_device *dev, struct netdev_xdp *xdp)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	int rc;
+
+	switch (xdp->command) {
+	case XDP_SETUP_PROG:
+		rc = bnxt_xdp_set(bp, xdp->prog);
+		break;
+	case XDP_QUERY_PROG:
+		xdp->prog_attached = !!bp->xdp_prog;
+		rc = 0;
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
new file mode 100644
index 0000000..066a411
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
@@ -0,0 +1,28 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016-2017 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef BNXT_XDP_H
+#define BNXT_XDP_H
+
+#ifdef CONFIG_BNXT_XDP
+bool bnxt_rx_xdp(struct bnxt_rx_ring_info *rxr, u16 cons, void *data,
+		 u8 *data_ptr, unsigned int len, dma_addr_t dma_addr,
+		 u8 *event);
+
+int bnxt_xdp(struct net_device *dev, struct netdev_xdp *xdp);
+
+#else
+static inline bool bnxt_rx_xdp(struct bnxt_rx_ring_info *rxr, u16 cons,
+			       void *data, u8 *data_ptr, unsigned int len,
+			       dma_addr_t dma_addr, u8 *event)
+{
+	return false;
+}
+#endif
+#endif
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 08/10] bnxt_en: Refactor tx completion path.
From: Michael Chan @ 2017-01-31  1:49 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1485827375-20421-1-git-send-email-michael.chan@broadcom.com>

XDP_TX requires a different function to handle completion.  Add a
function pointer to handle tx completion logic.  Regular TX rings
will be assigned the current bnxt_tx_int() for the ->tx_int()
function pointer.

Also, add a struct page pointer as a union with the current skb pointer
to the struct bnxt_sw_tx_bd.  XDP TX rings will use the struct page
pointer.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c |  5 ++++-
 drivers/net/ethernet/broadcom/bnxt/bnxt.h | 10 +++++++++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 295c91f..d9098ee 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1763,7 +1763,7 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
 	BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons);
 
 	if (tx_pkts)
-		bnxt_tx_int(bp, bnapi, tx_pkts);
+		bnapi->tx_int(bp, bnapi, tx_pkts);
 
 	if (event & BNXT_RX_EVENT) {
 		struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
@@ -3038,6 +3038,9 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool irq_re_init)
 			bp->tx_ring[i].bnapi = bp->bnapi[j];
 			bp->bnapi[j]->tx_ring = &bp->tx_ring[i];
 			bp->tx_ring_map[i] = bp->tx_nr_rings_xdp + i;
+			if (i < bp->tx_nr_rings_xdp)
+				bp->bnapi[j]->flags |= BNXT_NAPI_FLAG_XDP;
+			bp->bnapi[j]->tx_int = bnxt_tx_int;
 		}
 
 		rc = bnxt_alloc_stats(bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 9bd1a26..f5d5971 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -515,7 +515,10 @@ struct rx_tpa_end_cmp_ext {
 #define BNXT_AGG_EVENT	2
 
 struct bnxt_sw_tx_bd {
-	struct sk_buff		*skb;
+	union {
+		struct sk_buff		*skb;
+		struct page		*page;
+	};
 	DEFINE_DMA_UNMAP_ADDR(mapping);
 	u8			is_gso;
 	u8			is_push;
@@ -663,6 +666,11 @@ struct bnxt_napi {
 	struct bnxt_rx_ring_info	*rx_ring;
 	struct bnxt_tx_ring_info	*tx_ring;
 
+	void			(*tx_int)(struct bnxt *, struct bnxt_napi *,
+					  int);
+	u32			flags;
+#define BNXT_NAPI_FLAG_XDP	0x1
+
 	bool			in_reset;
 };
 
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 07/10] bnxt_en: Add a set of TX rings to support XDP.
From: Michael Chan @ 2017-01-31  1:49 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1485827375-20421-1-git-send-email-michael.chan@broadcom.com>

Add logic for an extra set of TX rings for XDP.  If enabled, this
set of TX rings equals the number of RX rings and shares the same
IRQ as the RX ring set.  A new field bp->tx_nr_rings_xdp is added
to keep track of these TX XDP rings.  Adjust all other relevant functions
to handle bp->tx_nr_rings_xdp.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c         | 17 ++++++++++-------
 drivers/net/ethernet/broadcom/bnxt/bnxt.h         |  3 ++-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 16 ++++++++++++----
 3 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index db78103..295c91f 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -2219,6 +2219,8 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
 			memset(txr->tx_push, 0, sizeof(struct tx_push_bd));
 		}
 		ring->queue_id = bp->q_info[j].queue_id;
+		if (i < bp->tx_nr_rings_xdp)
+			continue;
 		if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1))
 			j++;
 	}
@@ -3035,7 +3037,7 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool irq_re_init)
 		for (i = 0; i < bp->tx_nr_rings; i++, j++) {
 			bp->tx_ring[i].bnapi = bp->bnapi[j];
 			bp->bnapi[j]->tx_ring = &bp->tx_ring[i];
-			bp->tx_ring_map[i] = i;
+			bp->tx_ring_map[i] = bp->tx_nr_rings_xdp + i;
 		}
 
 		rc = bnxt_alloc_stats(bp);
@@ -4958,7 +4960,8 @@ static int bnxt_set_real_num_queues(struct bnxt *bp)
 	int rc;
 	struct net_device *dev = bp->dev;
 
-	rc = netif_set_real_num_tx_queues(dev, bp->tx_nr_rings);
+	rc = netif_set_real_num_tx_queues(dev, bp->tx_nr_rings -
+					  bp->tx_nr_rings_xdp);
 	if (rc)
 		return rc;
 
@@ -6574,7 +6577,7 @@ static void bnxt_sp_task(struct work_struct *work)
 }
 
 /* Under rtnl_lock */
-int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs)
+int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs, int tx_xdp)
 {
 	int max_rx, max_tx, tx_sets = 1;
 	int tx_rings_needed;
@@ -6594,12 +6597,12 @@ int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs)
 	if (max_rx < rx)
 		return -ENOMEM;
 
-	tx_rings_needed = tx * tx_sets;
+	tx_rings_needed = tx * tx_sets + tx_xdp;
 	if (max_tx < tx_rings_needed)
 		return -ENOMEM;
 
 	if (bnxt_hwrm_reserve_tx_rings(bp, &tx_rings_needed) ||
-	    tx_rings_needed < (tx * tx_sets))
+	    tx_rings_needed < (tx * tx_sets + tx_xdp))
 		return -ENOMEM;
 	return 0;
 }
@@ -6780,8 +6783,8 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
 	if (bp->flags & BNXT_FLAG_SHARED_RINGS)
 		sh = true;
 
-	rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc,
-				bp->rx_nr_rings, tc);
+	rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings,
+				tc, bp->tx_nr_rings_xdp);
 	if (rc)
 		return rc;
 
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 924c1fa..9bd1a26 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1023,6 +1023,7 @@ struct bnxt {
 	int			tx_nr_pages;
 	int			tx_nr_rings;
 	int			tx_nr_rings_per_tc;
+	int			tx_nr_rings_xdp;
 
 	int			tx_wake_thresh;
 	int			tx_push_thresh;
@@ -1200,7 +1201,7 @@ int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap,
 int bnxt_hwrm_fw_set_time(struct bnxt *);
 int bnxt_open_nic(struct bnxt *, bool, bool);
 int bnxt_close_nic(struct bnxt *, bool, bool);
-int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs);
+int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs, int tx_xdp);
 int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
 int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
 void bnxt_restore_pf_fw_resources(struct bnxt *bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 6f2568d..7aa248d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -389,6 +389,7 @@ static int bnxt_set_channels(struct net_device *dev,
 	struct bnxt *bp = netdev_priv(dev);
 	int req_tx_rings, req_rx_rings, tcs;
 	bool sh = false;
+	int tx_xdp = 0;
 	int rc = 0;
 
 	if (channel->other_count)
@@ -413,7 +414,14 @@ static int bnxt_set_channels(struct net_device *dev,
 
 	req_tx_rings = sh ? channel->combined_count : channel->tx_count;
 	req_rx_rings = sh ? channel->combined_count : channel->rx_count;
-	rc = bnxt_reserve_rings(bp, req_tx_rings, req_rx_rings, tcs);
+	if (bp->tx_nr_rings_xdp) {
+		if (!sh) {
+			netdev_err(dev, "Only combined mode supported when XDP is enabled.\n");
+			return -EINVAL;
+		}
+		tx_xdp = req_rx_rings;
+	}
+	rc = bnxt_reserve_rings(bp, req_tx_rings, req_rx_rings, tcs, tx_xdp);
 	if (rc) {
 		netdev_warn(dev, "Unable to allocate the requested rings\n");
 		return rc;
@@ -442,10 +450,10 @@ static int bnxt_set_channels(struct net_device *dev,
 		bp->rx_nr_rings = channel->rx_count;
 		bp->tx_nr_rings_per_tc = channel->tx_count;
 	}
-
-	bp->tx_nr_rings = bp->tx_nr_rings_per_tc;
+	bp->tx_nr_rings_xdp = tx_xdp;
+	bp->tx_nr_rings = bp->tx_nr_rings_per_tc + tx_xdp;
 	if (tcs > 1)
-		bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
+		bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs + tx_xdp;
 
 	bp->cp_nr_rings = sh ? max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) :
 			       bp->tx_nr_rings + bp->rx_nr_rings;
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 01/10] bnxt_en: Refactor rx SKB function.
From: Michael Chan @ 2017-01-31  1:49 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1485827375-20421-1-git-send-email-michael.chan@broadcom.com>

Minor refactoring of bnxt_rx_skb() so that it can easily be replaced by
a new function that handles packets in a single page.  Also, use a
function pointer bp->rx_skb_func() to switch to a new function when
we add the new mode in the next patch.

Add a new field data_ptr that points to the packet data in the
bnxt_sw_rx_bd structure.  The original data field is changed to void
pointer so that it can either hold the kmalloc'ed data or a page
pointer.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c | 42 ++++++++++++++++++++++---------
 drivers/net/ethernet/broadcom/bnxt/bnxt.h | 11 ++++++--
 2 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 3d83b90..d419199 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -607,6 +607,7 @@ static inline int bnxt_alloc_rx_data(struct bnxt *bp,
 		return -ENOMEM;
 
 	rx_buf->data = data;
+	rx_buf->data_ptr = data + BNXT_RX_OFFSET;
 	dma_unmap_addr_set(rx_buf, mapping, mapping);
 
 	rxbd->rx_bd_haddr = cpu_to_le64(mapping);
@@ -615,7 +616,7 @@ static inline int bnxt_alloc_rx_data(struct bnxt *bp,
 }
 
 static void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons,
-			       u8 *data)
+			       void *data)
 {
 	u16 prod = rxr->rx_prod;
 	struct bnxt_sw_rx_bd *cons_rx_buf, *prod_rx_buf;
@@ -625,6 +626,7 @@ static void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons,
 	cons_rx_buf = &rxr->rx_buf_ring[cons];
 
 	prod_rx_buf->data = data;
+	prod_rx_buf->data_ptr = cons_rx_buf->data_ptr;
 
 	dma_unmap_addr_set(prod_rx_buf, mapping,
 			   dma_unmap_addr(cons_rx_buf, mapping));
@@ -755,7 +757,7 @@ static void bnxt_reuse_rx_agg_bufs(struct bnxt_napi *bnapi, u16 cp_cons,
 
 static struct sk_buff *bnxt_rx_skb(struct bnxt *bp,
 				   struct bnxt_rx_ring_info *rxr, u16 cons,
-				   u16 prod, u8 *data, dma_addr_t dma_addr,
+				   u16 prod, void *data, dma_addr_t dma_addr,
 				   unsigned int len)
 {
 	int err;
@@ -776,7 +778,7 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp,
 	}
 
 	skb_reserve(skb, BNXT_RX_OFFSET);
-	skb_put(skb, len);
+	skb_put(skb, len & 0xffff);
 	return skb;
 }
 
@@ -878,7 +880,8 @@ static inline struct sk_buff *bnxt_copy_skb(struct bnxt_napi *bnapi, u8 *data,
 	dma_sync_single_for_cpu(&pdev->dev, mapping,
 				bp->rx_copy_thresh, PCI_DMA_FROMDEVICE);
 
-	memcpy(skb->data - BNXT_RX_OFFSET, data, len + BNXT_RX_OFFSET);
+	memcpy(skb->data - NET_IP_ALIGN, data - NET_IP_ALIGN,
+	       len + NET_IP_ALIGN);
 
 	dma_sync_single_for_device(&pdev->dev, mapping,
 				   bp->rx_copy_thresh,
@@ -951,6 +954,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
 	}
 
 	prod_rx_buf->data = tpa_info->data;
+	prod_rx_buf->data_ptr = tpa_info->data_ptr;
 
 	mapping = tpa_info->mapping;
 	dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
@@ -960,6 +964,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
 	prod_bd->rx_bd_haddr = cpu_to_le64(mapping);
 
 	tpa_info->data = cons_rx_buf->data;
+	tpa_info->data_ptr = cons_rx_buf->data_ptr;
 	cons_rx_buf->data = NULL;
 	tpa_info->mapping = dma_unmap_addr(cons_rx_buf, mapping);
 
@@ -1192,12 +1197,13 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
 	struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
 	struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
 	u8 agg_id = TPA_END_AGG_ID(tpa_end);
-	u8 *data, agg_bufs;
+	u8 *data_ptr, agg_bufs;
 	u16 cp_cons = RING_CMP(*raw_cons);
 	unsigned int len;
 	struct bnxt_tpa_info *tpa_info;
 	dma_addr_t mapping;
 	struct sk_buff *skb;
+	void *data;
 
 	if (unlikely(bnapi->in_reset)) {
 		int rc = bnxt_discard_rx(bp, bnapi, raw_cons, tpa_end);
@@ -1209,7 +1215,8 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
 
 	tpa_info = &rxr->rx_tpa[agg_id];
 	data = tpa_info->data;
-	prefetch(data);
+	data_ptr = tpa_info->data_ptr;
+	prefetch(data_ptr);
 	len = tpa_info->len;
 	mapping = tpa_info->mapping;
 
@@ -1232,7 +1239,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
 	}
 
 	if (len <= bp->rx_copy_thresh) {
-		skb = bnxt_copy_skb(bnapi, data, len, mapping);
+		skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping);
 		if (!skb) {
 			bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs);
 			return NULL;
@@ -1248,6 +1255,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
 		}
 
 		tpa_info->data = new_data;
+		tpa_info->data_ptr = new_data + BNXT_RX_OFFSET;
 		tpa_info->mapping = new_mapping;
 
 		skb = build_skb(data, 0);
@@ -1316,9 +1324,10 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
 	u16 cons, prod, cp_cons = RING_CMP(tmp_raw_cons);
 	struct bnxt_sw_rx_bd *rx_buf;
 	unsigned int len;
-	u8 *data, agg_bufs, cmp_type;
+	u8 *data_ptr, agg_bufs, cmp_type;
 	dma_addr_t dma_addr;
 	struct sk_buff *skb;
+	void *data;
 	int rc = 0;
 
 	rxcmp = (struct rx_cmp *)
@@ -1363,13 +1372,14 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
 	cons = rxcmp->rx_cmp_opaque;
 	rx_buf = &rxr->rx_buf_ring[cons];
 	data = rx_buf->data;
+	data_ptr = rx_buf->data_ptr;
 	if (unlikely(cons != rxr->rx_next_cons)) {
 		int rc1 = bnxt_discard_rx(bp, bnapi, raw_cons, rxcmp);
 
 		bnxt_sched_reset(bp, rxr);
 		return rc1;
 	}
-	prefetch(data);
+	prefetch(data_ptr);
 
 	agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >>
 				RX_CMP_AGG_BUFS_SHIFT;
@@ -1396,14 +1406,14 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
 	dma_addr = dma_unmap_addr(rx_buf, mapping);
 
 	if (len <= bp->rx_copy_thresh) {
-		skb = bnxt_copy_skb(bnapi, data, len, dma_addr);
+		skb = bnxt_copy_skb(bnapi, data_ptr, len, dma_addr);
 		bnxt_reuse_rx_data(rxr, cons, data);
 		if (!skb) {
 			rc = -ENOMEM;
 			goto next_rx;
 		}
 	} else {
-		skb = bnxt_rx_skb(bp, rxr, cons, prod, data, dma_addr, len);
+		skb = bp->rx_skb_func(bp, rxr, cons, prod, data, dma_addr, len);
 		if (!skb) {
 			rc = -ENOMEM;
 			goto next_rx;
@@ -1880,7 +1890,7 @@ static void bnxt_free_rx_skbs(struct bnxt *bp)
 
 		for (j = 0; j < max_idx; j++) {
 			struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[j];
-			u8 *data = rx_buf->data;
+			void *data = rx_buf->data;
 
 			if (!data)
 				continue;
@@ -2326,6 +2336,7 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr)
 					return -ENOMEM;
 
 				rxr->rx_tpa[i].data = data;
+				rxr->rx_tpa[i].data_ptr = data + BNXT_RX_OFFSET;
 				rxr->rx_tpa[i].mapping = mapping;
 			}
 		} else {
@@ -2550,6 +2561,12 @@ void bnxt_set_ring_params(struct bnxt *bp)
 	bp->cp_ring_mask = bp->cp_bit - 1;
 }
 
+static int bnxt_set_rx_skb_mode(struct bnxt *bp)
+{
+	bp->rx_skb_func = bnxt_rx_skb;
+	return 0;
+}
+
 static void bnxt_free_vnic_attributes(struct bnxt *bp)
 {
 	int i;
@@ -7299,6 +7316,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	bnxt_hwrm_func_qcfg(bp);
 	bnxt_hwrm_port_led_qcaps(bp);
 
+	bnxt_set_rx_skb_mode(bp);
 	bnxt_set_tpa_flags(bp);
 	bnxt_set_ring_params(bp);
 	bnxt_set_max_func_irqs(bp, max_irqs);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 52a1cc0..33302b0 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -516,7 +516,8 @@ struct bnxt_sw_tx_bd {
 };
 
 struct bnxt_sw_rx_bd {
-	u8			*data;
+	void			*data;
+	u8			*data_ptr;
 	DEFINE_DMA_UNMAP_ADDR(mapping);
 };
 
@@ -576,7 +577,8 @@ struct bnxt_tx_ring_info {
 };
 
 struct bnxt_tpa_info {
-	u8			*data;
+	void			*data;
+	u8			*data_ptr;
 	dma_addr_t		mapping;
 	u16			len;
 	unsigned short		gso_type;
@@ -988,6 +990,11 @@ struct bnxt {
 	struct sk_buff *	(*gro_func)(struct bnxt_tpa_info *, int, int,
 					    struct sk_buff *);
 
+	struct sk_buff *	(*rx_skb_func)(struct bnxt *,
+					       struct bnxt_rx_ring_info *,
+					       u16, u16, void *, dma_addr_t,
+					       unsigned int);
+
 	u32			rx_buf_size;
 	u32			rx_buf_use_size;	/* useable size */
 	u32			rx_ring_size;
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 05/10] bnxt_en: Centralize logic to reserve rings.
From: Michael Chan @ 2017-01-31  1:49 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1485827375-20421-1-git-send-email-michael.chan@broadcom.com>

Currently, bnxt_setup_tc() and bnxt_set_channels() have similar and
duplicated code to check and reserve rx and tx rings.  Add a new
function bnxt_reserve_rings() to centralize the logic.  This will
make it easier to add XDP_TX support which requires allocating a
new set of TX rings.

Also, the tx ring checking logic in bnxt_setup_msix() can be removed.
The rings have been reserved before hand.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c         | 68 ++++++++++++++---------
 drivers/net/ethernet/broadcom/bnxt/bnxt.h         |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 39 +++----------
 3 files changed, 52 insertions(+), 57 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 0f6ca67..cb30ba4 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -4204,7 +4204,7 @@ int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings)
 	return rc;
 }
 
-int bnxt_hwrm_reserve_tx_rings(struct bnxt *bp, int *tx_rings)
+static int bnxt_hwrm_reserve_tx_rings(struct bnxt *bp, int *tx_rings)
 {
 	struct hwrm_func_cfg_input req = {0};
 	int rc;
@@ -4997,19 +4997,12 @@ static void bnxt_setup_msix(struct bnxt *bp)
 
 	tcs = netdev_get_num_tc(dev);
 	if (tcs > 1) {
-		bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs;
-		if (bp->tx_nr_rings_per_tc == 0) {
-			netdev_reset_tc(dev);
-			bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
-		} else {
-			int i, off, count;
+		int i, off, count;
 
-			bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
-			for (i = 0; i < tcs; i++) {
-				count = bp->tx_nr_rings_per_tc;
-				off = i * count;
-				netdev_set_tc_queue(dev, i, count, off);
-			}
+		for (i = 0; i < tcs; i++) {
+			count = bp->tx_nr_rings_per_tc;
+			off = i * count;
+			netdev_set_tc_queue(dev, i, count, off);
 		}
 	}
 
@@ -6571,6 +6564,37 @@ static void bnxt_sp_task(struct work_struct *work)
 	clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 }
 
+/* Under rtnl_lock */
+int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs)
+{
+	int max_rx, max_tx, tx_sets = 1;
+	int tx_rings_needed;
+	bool sh = true;
+	int rc;
+
+	if (!(bp->flags & BNXT_FLAG_SHARED_RINGS))
+		sh = false;
+
+	if (tcs)
+		tx_sets = tcs;
+
+	rc = bnxt_get_max_rings(bp, &max_rx, &max_tx, sh);
+	if (rc)
+		return rc;
+
+	if (max_rx < rx)
+		return -ENOMEM;
+
+	tx_rings_needed = tx * tx_sets;
+	if (max_tx < tx_rings_needed)
+		return -ENOMEM;
+
+	if (bnxt_hwrm_reserve_tx_rings(bp, &tx_rings_needed) ||
+	    tx_rings_needed < (tx * tx_sets))
+		return -ENOMEM;
+	return 0;
+}
+
 static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
 {
 	int rc;
@@ -6733,6 +6757,7 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
 {
 	struct bnxt *bp = netdev_priv(dev);
 	bool sh = false;
+	int rc;
 
 	if (tc > bp->max_tc) {
 		netdev_err(dev, "too many traffic classes requested: %d Max supported is %d\n",
@@ -6746,19 +6771,10 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
 	if (bp->flags & BNXT_FLAG_SHARED_RINGS)
 		sh = true;
 
-	if (tc) {
-		int max_rx_rings, max_tx_rings, req_tx_rings, rsv_tx_rings, rc;
-
-		req_tx_rings = bp->tx_nr_rings_per_tc * tc;
-		rc = bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, sh);
-		if (rc || req_tx_rings > max_tx_rings)
-			return -ENOMEM;
-
-		rsv_tx_rings = req_tx_rings;
-		if (bnxt_hwrm_reserve_tx_rings(bp, &rsv_tx_rings) ||
-		    rsv_tx_rings < req_tx_rings)
-			return -ENOMEM;
-	}
+	rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc,
+				bp->rx_nr_rings, tc);
+	if (rc)
+		return rc;
 
 	/* Needs to close the device and do hw resource re-allocations */
 	if (netif_running(bp->dev))
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 2202113..44dcc26 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1186,7 +1186,6 @@ int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap,
 				     int bmap_size);
 int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id);
 int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings);
-int bnxt_hwrm_reserve_tx_rings(struct bnxt *bp, int *tx_rings);
 int bnxt_hwrm_set_coal(struct bnxt *);
 unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp);
 void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max);
@@ -1200,6 +1199,7 @@ int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap,
 int bnxt_hwrm_fw_set_time(struct bnxt *);
 int bnxt_open_nic(struct bnxt *, bool, bool);
 int bnxt_close_nic(struct bnxt *, bool, bool);
+int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs);
 int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
 int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
 void bnxt_restore_pf_fw_resources(struct bnxt *bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 24818e1..6f2568d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -387,10 +387,9 @@ static int bnxt_set_channels(struct net_device *dev,
 			     struct ethtool_channels *channel)
 {
 	struct bnxt *bp = netdev_priv(dev);
-	int max_rx_rings, max_tx_rings, tcs;
-	int req_tx_rings, rsv_tx_rings;
-	u32 rc = 0;
+	int req_tx_rings, req_rx_rings, tcs;
 	bool sh = false;
+	int rc = 0;
 
 	if (channel->other_count)
 		return -EINVAL;
@@ -410,32 +409,14 @@ static int bnxt_set_channels(struct net_device *dev,
 	if (channel->combined_count)
 		sh = true;
 
-	bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, sh);
-
 	tcs = netdev_get_num_tc(dev);
-	if (tcs > 1)
-		max_tx_rings /= tcs;
-
-	if (sh &&
-	    channel->combined_count > max_t(int, max_rx_rings, max_tx_rings))
-		return -ENOMEM;
-
-	if (!sh && (channel->rx_count > max_rx_rings ||
-		    channel->tx_count > max_tx_rings))
-		return -ENOMEM;
 
 	req_tx_rings = sh ? channel->combined_count : channel->tx_count;
-	req_tx_rings = min_t(int, req_tx_rings, max_tx_rings);
-	if (tcs > 1)
-		req_tx_rings *= tcs;
-
-	rsv_tx_rings = req_tx_rings;
-	if (bnxt_hwrm_reserve_tx_rings(bp, &rsv_tx_rings))
-		return -ENOMEM;
-
-	if (rsv_tx_rings < req_tx_rings) {
-		netdev_warn(dev, "Unable to allocate the requested tx rings\n");
-		return -ENOMEM;
+	req_rx_rings = sh ? channel->combined_count : channel->rx_count;
+	rc = bnxt_reserve_rings(bp, req_tx_rings, req_rx_rings, tcs);
+	if (rc) {
+		netdev_warn(dev, "Unable to allocate the requested rings\n");
+		return rc;
 	}
 
 	if (netif_running(dev)) {
@@ -454,10 +435,8 @@ static int bnxt_set_channels(struct net_device *dev,
 
 	if (sh) {
 		bp->flags |= BNXT_FLAG_SHARED_RINGS;
-		bp->rx_nr_rings = min_t(int, channel->combined_count,
-					max_rx_rings);
-		bp->tx_nr_rings_per_tc = min_t(int, channel->combined_count,
-					       max_tx_rings);
+		bp->rx_nr_rings = channel->combined_count;
+		bp->tx_nr_rings_per_tc = channel->combined_count;
 	} else {
 		bp->flags &= ~BNXT_FLAG_SHARED_RINGS;
 		bp->rx_nr_rings = channel->rx_count;
-- 
1.8.3.1

^ permalink raw reply related


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