Netdev List
 help / color / mirror / Atom feed
* Re: [PATCHv2 bluetooth-next 08/10] ipv6: export ndisc functions
From: Alexander Aring @ 2016-05-08 10:46 UTC (permalink / raw)
  To: Hannes Frederic Sowa, linux-wpan
  Cc: kernel, marcel, jukka.rissanen, stefan, mcr, werner,
	linux-bluetooth, netdev, David S . Miller, Alexey Kuznetsov,
	James Morris, Hideaki YOSHIFUJI, Patrick McHardy
In-Reply-To: <f5d5970d-afed-8a2f-9292-9ccb77f0e0db@stressinduktion.org>


Hi,

On 05/02/2016 09:39 PM, Hannes Frederic Sowa wrote:
> On 20.04.2016 10:19, Alexander Aring wrote:
>> This patch exports some neighbour discovery functions which can be used
>> by 6lowpan neighbour discovery ops functionality then.
>>
>> Cc: David S. Miller <davem@davemloft.net>
>> Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
>> Cc: James Morris <jmorris@namei.org>
>> Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
>> Cc: Patrick McHardy <kaber@trash.net>
>> Signed-off-by: Alexander Aring <aar@pengutronix.de>
>> ---
>>  include/net/ndisc.h | 16 ++++++++++++++++
>>  net/ipv6/addrconf.c |  1 +
>>  net/ipv6/ndisc.c    | 28 ++++++++++------------------
>>  3 files changed, 27 insertions(+), 18 deletions(-)
>>
>> diff --git a/include/net/ndisc.h b/include/net/ndisc.h
>> index 14ed016..35a4396 100644
>> --- a/include/net/ndisc.h
>> +++ b/include/net/ndisc.h
>> @@ -53,6 +53,15 @@ enum {
>>  
>>  #include <net/neighbour.h>
>>  
>> +/* Set to 3 to get tracing... */
>> +#define ND_DEBUG 1
>> +
>> +#define ND_PRINTK(val, level, fmt, ...)				\
>> +do {								\
>> +	if (val <= ND_DEBUG)					\
>> +		net_##level##_ratelimited(fmt, ##__VA_ARGS__);	\
>> +} while (0)
>> +
> 
> If the debug messages are well thought out, I think we could install
> them always on debug level.
> 
> There are valid users now, so
> 

Not sure if I understand you correctly here. Is this patch is fine or I
should remove ND_DEBUG, because it's handled by "net_##level##_ratelimited"
and the debug level will be handled then by other debug level settings
then?

Thanks.

- Alex

^ permalink raw reply

* Re: [PATCHv2 bluetooth-next 04/10] ndisc: add addr_len parameter to ndisc_opt_addr_space
From: Alexander Aring @ 2016-05-08 10:39 UTC (permalink / raw)
  To: Hannes Frederic Sowa, linux-wpan
  Cc: kernel, marcel, jukka.rissanen, stefan, mcr, werner,
	linux-bluetooth, netdev, David S . Miller, Alexey Kuznetsov,
	James Morris, Hideaki YOSHIFUJI, Patrick McHardy
In-Reply-To: <240084aa-2751-6f24-c07b-662b19a74475@stressinduktion.org>

Hi,

On 05/07/2016 12:23 AM, Hannes Frederic Sowa wrote:
> On 04.05.2016 14:30, Alexander Aring wrote:
>> Hi,
>>
>> On 05/02/2016 09:37 PM, Hannes Frederic Sowa wrote:
>>> On 20.04.2016 10:19, Alexander Aring wrote:
>>>> This patch makes the address length as argument for the
>>>> ndisc_opt_addr_space function. This is necessary to handle addresses
>>>> which don't use dev->addr_len as address length.
>>>
>>> Would it make sense for patch 4, 5 and 6 to add the operation to ndisc_ops?
>>>
>>
>> not sure if I understand this question right,
>>
>> We have now the ndisc_ops where we can could change the send/recv of
>> NS/NA, also is_useropt (for add 6CO RA is userspace option field).
>>
>> In case of 802.15.4 we have two MAC addresses with different length:
>>
>>  - extended address - 8 bytes => EUI64
>>  - short address - 2 bytes
>>
>> Now [0] describes how to make the source/target address option for
>> NS/NA/RS/RA/... to deal with both addresses.
>>
>> The short address is a special case in 802.15.4 and not always
>> available. If available we add both addresses as option field in
>> NS/NA (RS/RA will follow in future, but currently NS/NA only).
>>
>> At this point the understanding of [0] differs in 6LoWPAN
>> implementations.
>>
>> Some people handles it like:
>>
>> Handle the short address/extended address in XOR case of 6LoWPAN
>> interface. The interface has as MAC address the extended XOR short (if
>> available), depends on setting.
>>
>> Then dev->addr_len is 8 XOR 2.
>>
>> Other people (inclusive me) handle it like:
>>
>> Handle the short/extended address in case of OR, but never short address
>> alone. The interface can be accessed by extended address or short
>> address and each neighbour stores both information.
>>
>> The case "short address never alone" means that the extended address is
>> always available and MUST be there.
>>
>> Furthermore, depends on L3 addressing it could be useful to have the
>> possibility to decide if using or short OR extended address as L2 address
>> for do better compressing stuff.
>>
>> ---
>>
>> I implement it as OR case, so we add both addresses when short address
>> is available. Also we drop NS/NA when the short address is given only,
>> in theory we could also react on this and store a "dummy" 0x00..00
>> address for extended address then.
>>
>> Not sure how it need to be handled correctly, for now I implemented how
>> I understand it.
>>
>> In case of the OR case, we need to add two option fields for the
>> address, extended and short. This is why I do the calculation stuff more
>> accessible with different address lengths, so we can use 8 or 2 and not
>> dev->addr_len which stores always the 802.15.4 EUI64 address length.
>>
>> And the answer would be, no it makes no sense because we need to call
>> these functions with 8 (dev->addr_len) and 2 (if short addr is
>> available).
> 
> I had to understand the usage in patch 9. It seems you are right, the
> decision cannot be done based on the protocol alone but based on the
> context, so we need to pass in different lengths based on the context.
> Thanks for your explanation.
> 
> I would still suggest to not use net_device as an argument but just the
> type and length to keep the API cleaner, but this is not a strong opinion.
> 

yes, I agree. I will try to change it without any dev argument.

The general question would also here, if we just not "simple" support
for general IPv6 implementation a mapping where:

L2+ (in meaning of one or more) addresses <-> one L3 address

Which means e.g. two ethernet addresses can be mapped to one L3 address.
I don't know if this makes sense somehow, but I have such use-case for
802.15.4 but it's even complicated because different address lengths.

Additional to this feature, we add also supporting of multiple L2
addresses for a net_device with different address lengths.

---

I wrote "simple" but it isn't simple, but I suppose the truly mainline
solution.

What I did in the patch series to store short address in neighbour
private data, which makes everything 802.15.4 6lowpan specific. We
currently store the short address as part of 802.15.4 interface type
in netdev_priv also.

This requires lot of changes which are not easy, also dev_hard_header
callback does not contain any length information in context when calling
this function. Btw: 0xffff (short address) in 802.15.4 is the broadcast
address, which currently works because a workaround by mapping 0xff..ff
dev->broadcast (8 bytes) to 0xffff short.

Big question is also if it's valid to make such mapping in all link-layers
e.g. ethernet, because Linux filters multiple target/source link address
option fields in NS/NA/RS/etc. Anyway could be also some flag if valid
or not.

I think this more something for future, because it's really big work. :-)

- Alex

^ permalink raw reply

* RE: [PATCH v9 net-next 1/2] hv_sock: introduce Hyper-V Sockets
From: Dexuan Cui @ 2016-05-08  6:11 UTC (permalink / raw)
  To: David Miller
  Cc: olaf@aepfle.de, gregkh@linuxfoundation.org, jasowang@redhat.com,
	linux-kernel@vger.kernel.org, joe@perches.com,
	netdev@vger.kernel.org, apw@canonical.com,
	devel@linuxdriverproject.org, Haiyang Zhang
In-Reply-To: <20160507.134048.139772599380708393.davem@davemloft.net>

> From: David Miller [mailto:davem@davemloft.net]
> Sent: Sunday, May 8, 2016 1:41
> To: Dexuan Cui <decui@microsoft.com>
> Cc: gregkh@linuxfoundation.org; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; devel@linuxdriverproject.org; olaf@aepfle.de;
> apw@canonical.com; jasowang@redhat.com; cavery@redhat.com; KY
> Srinivasan <kys@microsoft.com>; Haiyang Zhang <haiyangz@microsoft.com>;
> joe@perches.com; vkuznets@redhat.com
> Subject: Re: [PATCH v9 net-next 1/2] hv_sock: introduce Hyper-V Sockets
>
> From: Dexuan Cui <decui@microsoft.com>
> Date: Sat, 7 May 2016 10:49:25 +0000
>
> > I should be able to make 'send', 'recv' here to pointers and use vmalloc()
> > to allocate the memory for them.  I will do this.
>
> That's still unswappable kernel memory.
Hi David,
My understanding is: kernel pages are not swappable in Linux, so it looks I
can't avoid unswappable kernel memory here?

> People can open N sockets, where N is something on the order of the FD
> limit the process has, per process.  This allows someone to quickly
> eat up a lot of memory and hold onto it nearly indefinitely.

Thanks for pointing this out!
I understand, so I think I should add a module parameter, e.g.,
"hv_sock.max_socket_number" with a default value, say, 1024?

1 established hv_sock connection takes less than 20 pages, including 10
pages for VMBus ringbuffer, 6 pages for send/recv buffers(I'll use
vmalloc() for this), etc.
Here the recv buf needs a size of 5 pages because potentially the host
can send the guest a VMBus packet with an up-to-5-page payload, i..e,
the VMBus inbound ringbuffer size.

1024 hv_sock connections take less than 20*4KB * 1K = 80MB memory.

A user who needs more connections can change the module parameter
without reboot.

hv_sock connection is designed  to work only between the host and the
guest. I think 1024 connections seem pretty enough.

BTW, a user can't create hv_sock connections without enough privilege.
Please see

+static int hvsock_create(struct net *net, struct socket *sock,
+                        int protocol, int kern)
+{
+       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN))
+               return -EPERM;

David, does this make sense to you?

Thanks,
-- Dexuan

^ permalink raw reply

* Re: [PATCH net-next v2 1/2] net: l3mdev: Add hook in ip and ipv6
From: Shmulik Ladkani @ 2016-05-08  5:44 UTC (permalink / raw)
  To: David Ahern; +Cc: netdev
In-Reply-To: <572EA3A4.9010200@cumulusnetworks.com>

Hi,

On Sat, 7 May 2016 20:25:40 -0600 David Ahern <dsa@cumulusnetworks.com> wrote:
> >   - On which circumstances we end up entering
> >     l3mdev_ip_rcv/l3mdev_ip6_rcv where skb->dev is the master?
> >     If I got it right, we enter 'ip_rcv_finish' on a slave device,
> >     the callback is invoked and eventually sets skb->dev and skb->skb_iif
> >     to the VRF device; then ip_rcv_finish continues processing the
> >     altered skb (with the changed skb->dev).
> >     So on which cicumstances do we enter 'ip_rcv_finish' where the
> >     skb->dev is ALREADY a master device?  
> 
> If you look at the full patchset I posted on 5/4 the patch after PKTINFO 
> allows local traffic. That change needs the netif_is_l3_master().

I see. Thanks David.

^ permalink raw reply

* Re: [PATCH v2 net-next] ifb: support more features
From: Eric Dumazet @ 2016-05-08  5:41 UTC (permalink / raw)
  To: David Miller, Alexander Duyck; +Cc: netdev
In-Reply-To: <1462583999.13075.67.camel@edumazet-glaptop3.roam.corp.google.com>

On Fri, 2016-05-06 at 18:19 -0700, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> When using ifb+netem on ingress on SIT/IPIP/GRE traffic,
> GRO packets are not properly processed.
> 
> Segmentation should not be forced, since ifb is already adding
> quite a performance hit.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
>  drivers/net/ifb.c |    3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
> index cc56fac3c3f8..66c0eeafcb5d 100644
> --- a/drivers/net/ifb.c
> +++ b/drivers/net/ifb.c
> @@ -196,6 +196,7 @@ static const struct net_device_ops ifb_netdev_ops = {
>  
>  #define IFB_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG  | NETIF_F_FRAGLIST	| \
>  		      NETIF_F_TSO_ECN | NETIF_F_TSO | NETIF_F_TSO6	| \
> +		      NETIF_F_GSO_ENCAP_ALL 				| \
>  		      NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_TX		| \
>  		      NETIF_F_HW_VLAN_STAG_TX)
>  
> @@ -224,6 +225,8 @@ static void ifb_setup(struct net_device *dev)
>  	dev->tx_queue_len = TX_Q_LIMIT;
>  
>  	dev->features |= IFB_FEATURES;
> +	dev->hw_features |= dev->features;
> +	dev->hw_enc_features |= dev->features;
>  	dev->vlan_features |= IFB_FEATURES & ~(NETIF_F_HW_VLAN_CTAG_TX |
>  					       NETIF_F_HW_VLAN_STAG_TX);
>  
> 


BTW, encapsulated GRO traffic going through mirred+ifb is dropped
because segments get an incorrect skb->mac_len 

(If TSO/GSO is disabled on ifb, as before the above patch)

SIT traffic for example : segments get mac_len set to 34 instead of 14

What do you think of :

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e561f9f07d6d..bec5c32b2fe9 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3176,7 +3176,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 		__copy_skb_header(nskb, head_skb);
 
 		skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom);
-		skb_reset_mac_len(nskb);
+		nskb->mac_len = head_skb->mac_len;
 
 		skb_copy_from_linear_data_offset(head_skb, -tnl_hlen,
 						 nskb->data - tnl_hlen,

^ permalink raw reply related

* Re: [PATCH] Add support for configuring Infiniband GUIDs
From: Leon Romanovsky @ 2016-05-08  4:59 UTC (permalink / raw)
  To: Eli Cohen; +Cc: shemminger, netdev
In-Reply-To: <1462549405-16003-1-git-send-email-eli@mellanox.com>

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

On Fri, May 06, 2016 at 10:43:25AM -0500, Eli Cohen wrote:
> Add two NLA's that allow configuration of Infiniband node or port GUIDs
> by referencing the IPoIB net device set over then physical function. The
> format to be used is as follows:
> 
> ip link set dev ib0 vf 0 node_guid 00:02:c9:03:00:21:6e:70
> ip link set dev ib0 vf 0 port_guid 00:02:c9:03:00:21:6e:78
> 
> Issue: 702759
> Change-Id: I5ffb54d6de7bfa8650bf5818f484279914991d6e

These two lines are not needed to be part of commit message.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* [PATCH net-next 2/2] net: original ingress device index in PKTINFO
From: David Ahern @ 2016-05-08  4:16 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern
In-Reply-To: <1462681005-25959-1-git-send-email-dsa@cumulusnetworks.com>

Applications such as OSPF and BFD need the original ingress device not
the VRF device; the latter can be derived from the former. To that end
add the skb_iif to inet_skb_parm and set it in ipv4 code after clearing
the skb control buffer similar to IPv6. From there the pktinfo can just
pull it from cb with the PKTINFO_SKB_CB cast.

The previous patch moving the skb->dev change to L3 means nothing else
is needed for IPv6; it just works.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 include/net/ip.h       | 1 +
 net/ipv4/ip_input.c    | 1 +
 net/ipv4/ip_sockglue.c | 7 ++++++-
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index 247ac82e9cf2..37165fba3741 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -36,6 +36,7 @@
 struct sock;
 
 struct inet_skb_parm {
+	int			iif;
 	struct ip_options	opt;		/* Compiled IP options		*/
 	unsigned char		flags;
 
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 37375eedeef9..4b351af3e67b 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -478,6 +478,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 
 	/* Remove any debris in the socket control block */
 	memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+	IPCB(skb)->iif = skb->skb_iif;
 
 	/* Must drop socket now because of tproxy. */
 	skb_orphan(skb);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index bdb222c0c6a2..5805762d7fc7 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -1193,7 +1193,12 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
 		       ipv6_sk_rxinfo(sk);
 
 	if (prepare && skb_rtable(skb)) {
-		pktinfo->ipi_ifindex = inet_iif(skb);
+		/* skb->cb is overloaded: prior to this point it is IP{6}CB
+		 * which has interface index (iif) as the first member of the
+		 * underlying inet{6}_skb_parm struct. This code then overlays
+		 * PKTINFO_SKB_CB and in_pktinfo also has iif as the first
+		 * element so the iif is picked up from the prior IPCB
+		 */
 		pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
 	} else {
 		pktinfo->ipi_ifindex = 0;
-- 
2.1.4

^ permalink raw reply related

* [PATCH net-next v3 1/2] net: l3mdev: Add hook in ip and ipv6
From: David Ahern @ 2016-05-08  4:16 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern
In-Reply-To: <1462681005-25959-1-git-send-email-dsa@cumulusnetworks.com>

Currently the VRF driver uses the rx_handler to switch the skb device
to the VRF device. Switching the dev prior to the ip / ipv6 layer
means the VRF driver has to duplicate IP/IPv6 processing which adds
overhead and makes features such as retaining the ingress device index
more complicated than necessary.

This patch moves the hook to the L3 layer just after the first NF_HOOK
for PRE_ROUTING. This location makes exposing the original ingress device
trivial (next patch) and allows adding other NF_HOOKs to the VRF driver
in the future.

dev_queue_xmit_nit is exported so that the VRF driver can cycle the skb
with the switched device through the packet taps to maintain current
behavior (tcpdump can be used on either the vrf device or the enslaved
devices).

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
v3
- reverted direct skb->data accesses caused by inadvertent drop of
  65c38aa653c1 with forward port of this patch

v2
- add skb_l3mdev_slave helper for inet6_iif and tcp_v6_iif rather
  than open coding the if case. Added benefit that the change compiles
  out if CONFIG_NET_L3_MASTER_DEV is not enabled.

 drivers/net/vrf.c         | 189 ++++++++++++++++++++++------------------------
 include/linux/ipv6.h      |  17 ++++-
 include/linux/netdevice.h |   2 +
 include/net/l3mdev.h      |  43 +++++++++++
 include/net/tcp.h         |   4 +-
 net/core/dev.c            |   3 +-
 net/ipv4/ip_input.c       |   7 ++
 net/ipv6/ip6_input.c      |   7 ++
 8 files changed, 171 insertions(+), 101 deletions(-)

diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 4b2461ae5d3b..309efbf8da0e 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -42,9 +42,6 @@
 #define DRV_NAME	"vrf"
 #define DRV_VERSION	"1.0"
 
-#define vrf_master_get_rcu(dev) \
-	((struct net_device *)rcu_dereference(dev->rx_handler_data))
-
 struct net_vrf {
 	struct rtable           *rth;
 	struct rt6_info		*rt6;
@@ -60,90 +57,12 @@ struct pcpu_dstats {
 	struct u64_stats_sync	syncp;
 };
 
-/* neighbor handling is done with actual device; do not want
- * to flip skb->dev for those ndisc packets. This really fails
- * for multiple next protocols (e.g., NEXTHDR_HOP). But it is
- * a start.
- */
-#if IS_ENABLED(CONFIG_IPV6)
-static bool check_ipv6_frame(const struct sk_buff *skb)
-{
-	const struct ipv6hdr *ipv6h;
-	struct ipv6hdr _ipv6h;
-	bool rc = true;
-
-	ipv6h = skb_header_pointer(skb, 0, sizeof(_ipv6h), &_ipv6h);
-	if (!ipv6h)
-		goto out;
-
-	if (ipv6h->nexthdr == NEXTHDR_ICMP) {
-		const struct icmp6hdr *icmph;
-		struct icmp6hdr _icmph;
-
-		icmph = skb_header_pointer(skb, sizeof(_ipv6h),
-					   sizeof(_icmph), &_icmph);
-		if (!icmph)
-			goto out;
-
-		switch (icmph->icmp6_type) {
-		case NDISC_ROUTER_SOLICITATION:
-		case NDISC_ROUTER_ADVERTISEMENT:
-		case NDISC_NEIGHBOUR_SOLICITATION:
-		case NDISC_NEIGHBOUR_ADVERTISEMENT:
-		case NDISC_REDIRECT:
-			rc = false;
-			break;
-		}
-	}
-
-out:
-	return rc;
-}
-#else
-static bool check_ipv6_frame(const struct sk_buff *skb)
-{
-	return false;
-}
-#endif
-
-static bool is_ip_rx_frame(struct sk_buff *skb)
-{
-	switch (skb->protocol) {
-	case htons(ETH_P_IP):
-		return true;
-	case htons(ETH_P_IPV6):
-		return check_ipv6_frame(skb);
-	}
-	return false;
-}
-
 static void vrf_tx_error(struct net_device *vrf_dev, struct sk_buff *skb)
 {
 	vrf_dev->stats.tx_errors++;
 	kfree_skb(skb);
 }
 
-/* note: already called with rcu_read_lock */
-static rx_handler_result_t vrf_handle_frame(struct sk_buff **pskb)
-{
-	struct sk_buff *skb = *pskb;
-
-	if (is_ip_rx_frame(skb)) {
-		struct net_device *dev = vrf_master_get_rcu(skb->dev);
-		struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
-
-		u64_stats_update_begin(&dstats->syncp);
-		dstats->rx_pkts++;
-		dstats->rx_bytes += skb->len;
-		u64_stats_update_end(&dstats->syncp);
-
-		skb->dev = dev;
-
-		return RX_HANDLER_ANOTHER;
-	}
-	return RX_HANDLER_PASS;
-}
-
 static struct rtnl_link_stats64 *vrf_get_stats64(struct net_device *dev,
 						 struct rtnl_link_stats64 *stats)
 {
@@ -506,28 +425,14 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
 {
 	int ret;
 
-	/* register the packet handler for slave ports */
-	ret = netdev_rx_handler_register(port_dev, vrf_handle_frame, dev);
-	if (ret) {
-		netdev_err(port_dev,
-			   "Device %s failed to register rx_handler\n",
-			   port_dev->name);
-		goto out_fail;
-	}
-
 	ret = netdev_master_upper_dev_link(port_dev, dev, NULL, NULL);
 	if (ret < 0)
-		goto out_unregister;
+		return ret;
 
 	port_dev->priv_flags |= IFF_L3MDEV_SLAVE;
 	cycle_netdev(port_dev);
 
 	return 0;
-
-out_unregister:
-	netdev_rx_handler_unregister(port_dev);
-out_fail:
-	return ret;
 }
 
 static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
@@ -544,8 +449,6 @@ static int do_vrf_del_slave(struct net_device *dev, struct net_device *port_dev)
 	netdev_upper_dev_unlink(port_dev, dev);
 	port_dev->priv_flags &= ~IFF_L3MDEV_SLAVE;
 
-	netdev_rx_handler_unregister(port_dev);
-
 	cycle_netdev(port_dev);
 
 	return 0;
@@ -668,6 +571,95 @@ static int vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
+/* neighbor handling is done with actual device; do not want
+ * to flip skb->dev for those ndisc packets. This really fails
+ * for multiple next protocols (e.g., NEXTHDR_HOP). But it is
+ * a start.
+ */
+static bool ipv6_ndisc_frame(const struct sk_buff *skb)
+{
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	bool rc = false;
+
+	if (iph->nexthdr == NEXTHDR_ICMP) {
+		const struct icmp6hdr *icmph;
+		struct icmp6hdr _icmph;
+
+		icmph = skb_header_pointer(skb, sizeof(*iph),
+					   sizeof(_icmph), &_icmph);
+		if (!icmph)
+			goto out;
+
+		switch (icmph->icmp6_type) {
+		case NDISC_ROUTER_SOLICITATION:
+		case NDISC_ROUTER_ADVERTISEMENT:
+		case NDISC_NEIGHBOUR_SOLICITATION:
+		case NDISC_NEIGHBOUR_ADVERTISEMENT:
+		case NDISC_REDIRECT:
+			rc = true;
+			break;
+		}
+	}
+
+out:
+	return rc;
+}
+
+static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
+				   struct sk_buff *skb)
+{
+	/* if packet is NDISC keep the ingress interface */
+	if (!ipv6_ndisc_frame(skb)) {
+		skb->dev = vrf_dev;
+		skb->skb_iif = vrf_dev->ifindex;
+
+		skb_push(skb, skb->mac_len);
+		dev_queue_xmit_nit(skb, vrf_dev);
+		skb_pull(skb, skb->mac_len);
+
+		IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
+	}
+
+	return skb;
+}
+
+#else
+static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
+				   struct sk_buff *skb)
+{
+	return skb;
+}
+#endif
+
+static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
+				  struct sk_buff *skb)
+{
+	skb->dev = vrf_dev;
+	skb->skb_iif = vrf_dev->ifindex;
+
+	skb_push(skb, skb->mac_len);
+	dev_queue_xmit_nit(skb, vrf_dev);
+	skb_pull(skb, skb->mac_len);
+
+	return skb;
+}
+
+/* called with rcu lock held */
+static struct sk_buff *vrf_l3_rcv(struct net_device *vrf_dev,
+				  struct sk_buff *skb,
+				  u16 proto)
+{
+	switch (proto) {
+	case AF_INET:
+		return vrf_ip_rcv(vrf_dev, skb);
+	case AF_INET6:
+		return vrf_ip6_rcv(vrf_dev, skb);
+	}
+
+	return skb;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
 static struct dst_entry *vrf_get_rt6_dst(const struct net_device *dev,
 					 const struct flowi6 *fl6)
 {
@@ -688,6 +680,7 @@ static const struct l3mdev_ops vrf_l3mdev_ops = {
 	.l3mdev_fib_table	= vrf_fib_table,
 	.l3mdev_get_rtable	= vrf_get_rtable,
 	.l3mdev_get_saddr	= vrf_get_saddr,
+	.l3mdev_l3_rcv		= vrf_l3_rcv,
 #if IS_ENABLED(CONFIG_IPV6)
 	.l3mdev_get_rt6_dst	= vrf_get_rt6_dst,
 #endif
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 58d6e158755f..5c91b0b055d4 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -118,14 +118,29 @@ struct inet6_skb_parm {
 #define IP6SKB_ROUTERALERT	8
 #define IP6SKB_FRAGMENTED      16
 #define IP6SKB_HOPBYHOP        32
+#define IP6SKB_L3SLAVE         64
 };
 
+#if defined(CONFIG_NET_L3_MASTER_DEV)
+static inline bool skb_l3mdev_slave(__u16 flags)
+{
+	return flags & IP6SKB_L3SLAVE;
+}
+#else
+static inline bool skb_l3mdev_slave(__u16 flags)
+{
+	return false;
+}
+#endif
+
 #define IP6CB(skb)	((struct inet6_skb_parm*)((skb)->cb))
 #define IP6CBMTU(skb)	((struct ip6_mtuinfo *)((skb)->cb))
 
 static inline int inet6_iif(const struct sk_buff *skb)
 {
-	return IP6CB(skb)->iif;
+	bool l3_slave = skb_l3mdev_slave(IP6CB(skb)->flags);
+
+	return l3_slave ? skb->skb_iif : IP6CB(skb)->iif;
 }
 
 struct tcp6_request_sock {
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 63580e6d0df4..c2f5112f08f7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3258,6 +3258,8 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 bool is_skb_forwardable(const struct net_device *dev,
 			const struct sk_buff *skb);
 
+void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
+
 extern int		netdev_budget;
 
 /* Called by rtnetlink.c:rtnl_unlock() */
diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h
index c43a9c73de5e..19d8171d7cbb 100644
--- a/include/net/l3mdev.h
+++ b/include/net/l3mdev.h
@@ -25,6 +25,8 @@
 
 struct l3mdev_ops {
 	u32		(*l3mdev_fib_table)(const struct net_device *dev);
+	struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev,
+					  struct sk_buff *skb, u16 proto);
 
 	/* IPv4 ops */
 	struct rtable *	(*l3mdev_get_rtable)(const struct net_device *dev,
@@ -177,6 +179,35 @@ struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
 	return dst;
 }
 
+static inline
+struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
+{
+	struct net_device *master = NULL;
+
+	if (netif_is_l3_slave(skb->dev))
+		master = netdev_master_upper_dev_get_rcu(skb->dev);
+
+	else if (netif_is_l3_master(skb->dev))
+		master = skb->dev;
+
+	if (master && master->l3mdev_ops->l3mdev_l3_rcv)
+		skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto);
+
+	return skb;
+}
+
+static inline
+struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
+{
+	return l3mdev_l3_rcv(skb, AF_INET);
+}
+
+static inline
+struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
+{
+	return l3mdev_l3_rcv(skb, AF_INET6);
+}
+
 #else
 
 static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev)
@@ -244,6 +275,18 @@ struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
 {
 	return NULL;
 }
+
+static inline
+struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
+{
+	return skb;
+}
+
+static inline
+struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
+{
+	return skb;
+}
 #endif
 
 #endif /* _NET_L3MDEV_H_ */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 24ec80483805..264e8bb3d1ea 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -781,7 +781,9 @@ struct tcp_skb_cb {
  */
 static inline int tcp_v6_iif(const struct sk_buff *skb)
 {
-	return TCP_SKB_CB(skb)->header.h6.iif;
+	bool l3_slave = skb_l3mdev_slave(TCP_SKB_CB(skb)->header.h6.flags);
+
+	return l3_slave ? skb->skb_iif : TCP_SKB_CB(skb)->header.h6.iif;
 }
 #endif
 
diff --git a/net/core/dev.c b/net/core/dev.c
index e98ba63fe280..51a8bf28a3e0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1850,7 +1850,7 @@ static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)
  *	taps currently in use.
  */
 
-static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
+void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct packet_type *ptype;
 	struct sk_buff *skb2 = NULL;
@@ -1907,6 +1907,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 		pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);
 	rcu_read_unlock();
 }
+EXPORT_SYMBOL_GPL(dev_queue_xmit_nit);
 
 /**
  * netif_setup_tc - Handle tc mappings on real_num_tx_queues change
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 751c0658e194..37375eedeef9 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -313,6 +313,13 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 	const struct iphdr *iph = ip_hdr(skb);
 	struct rtable *rt;
 
+	/* if ingress device is enslaved to an L3 master device pass the
+	 * skb to its handler for processing
+	 */
+	skb = l3mdev_ip_rcv(skb);
+	if (!skb)
+		return NET_RX_SUCCESS;
+
 	if (net->ipv4.sysctl_ip_early_demux &&
 	    !skb_dst(skb) &&
 	    !skb->sk &&
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 6ed56012005d..f185cbcda114 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -49,6 +49,13 @@
 
 int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+	/* if ingress device is enslaved to an L3 master device pass the
+	 * skb to its handler for processing
+	 */
+	skb = l3mdev_ip6_rcv(skb);
+	if (!skb)
+		return NET_RX_SUCCESS;
+
 	if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
 		const struct inet6_protocol *ipprot;
 
-- 
2.1.4

^ permalink raw reply related

* [PATCH net-next v3 0/2] net: vrf: Fixup PKTINFO to return enslaved device index
From: David Ahern @ 2016-05-08  4:16 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern

Applications such as OSPF and BFD need the original ingress device not
the VRF device; the latter can be derived from the former. To that end
move the packet intercept from an rx handler that is invoked by
__netif_receive_skb_core to the ipv4 and ipv6 receive processing.

IPv6 already saves the skb_iif to the control buffer in ipv6_rcv. Since
the skb->dev has not been switched the cb has the enslaved device. Make
the same happen for IPv4 by adding the skb_iif to inet_skb_parm and set
it in ipv4 code after clearing the skb control buffer similar to IPv6.
>From there the pktinfo can just pull it from cb with the PKTINFO_SKB_CB
cast.

David Ahern (2):
  net: l3mdev: Add hook in ip and ipv6
  net: original ingress device index in PKTINFO

 drivers/net/vrf.c         | 189 ++++++++++++++++++++++------------------------
 include/linux/ipv6.h      |  17 ++++-
 include/linux/netdevice.h |   2 +
 include/net/ip.h          |   1 +
 include/net/l3mdev.h      |  43 +++++++++++
 include/net/tcp.h         |   4 +-
 net/core/dev.c            |   3 +-
 net/ipv4/ip_input.c       |   8 ++
 net/ipv4/ip_sockglue.c    |   7 +-
 net/ipv6/ip6_input.c      |   7 ++
 10 files changed, 179 insertions(+), 102 deletions(-)

-- 
2.1.4

^ permalink raw reply

* Re: [PATCH net-next v2 1/2] net: l3mdev: Add hook in ip and ipv6
From: David Ahern @ 2016-05-08  2:25 UTC (permalink / raw)
  To: Shmulik Ladkani; +Cc: netdev
In-Reply-To: <20160507213205.02529bde@halley>

On 5/7/16 12:32 PM, Shmulik Ladkani wrote:
> Hi David,
>
> On Sat, 7 May 2016 08:50:49 -0600 David Ahern <dsa@cumulusnetworks.com> wrote:
>>>> +static inline
>>>> +struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
>>>> +{
>>>> +	struct net_device *master = NULL;
>>>> +
>>>> +	if (netif_is_l3_slave(skb->dev))
>>>> +		master = netdev_master_upper_dev_get_rcu(skb->dev);
>>>> +
>>>> +	else if (netif_is_l3_master(skb->dev))
>>>> +		master = skb->dev;
>>>> +
>>>> +	if (master && master->l3mdev_ops->l3mdev_l3_rcv)
>>>> +		skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto);
>>>
>>> In the case where netif_is_l3_master(skb->dev) is true, can you explain
>>> why we need to pass it through the l3mdev_l3_rcv callback again?
>>
>> what do you mean again? This is only time the l3mdev_l3_rcv method is
>> called on a packet.
>
> You have the following:
>
> 	if (netif_is_l3_slave(skb->dev))
> 		master = netdev_master_upper_dev_get_rcu(skb->dev);
> 	else if (netif_is_l3_master(skb->dev))
> 		master = skb->dev;
> 	if (master && master->l3mdev_ops->l3mdev_l3_rcv)
> 		skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto);
>
> So in both conditions (skb->dev being the slave or the master) the skb
> is passed to master's l3mdev_l3_rcv callback.
>
> Appreciate if you can elaborate:
>   - Why callback needs to be invoked when skb->dev is the L3 master?

Every l3mdev_ops has converged on that ordering -- if l3 slave else if 
l3 master.

>   - On which circumstances we end up entering
>     l3mdev_ip_rcv/l3mdev_ip6_rcv where skb->dev is the master?
>     If I got it right, we enter 'ip_rcv_finish' on a slave device,
>     the callback is invoked and eventually sets skb->dev and skb->skb_iif
>     to the VRF device; then ip_rcv_finish continues processing the
>     altered skb (with the changed skb->dev).
>     So on which cicumstances do we enter 'ip_rcv_finish' where the
>     skb->dev is ALREADY a master device?

If you look at the full patchset I posted on 5/4 the patch after PKTINFO 
allows local traffic. That change needs the netif_is_l3_master().

^ permalink raw reply

* Re: [PATCH 1/2] net: phy: add ethtool_phy_{get|set}_link_ksettings
From: Ben Hutchings @ 2016-05-08  0:13 UTC (permalink / raw)
  To: Philippe Reynes; +Cc: f.fainelli, fugang.duan, davem, netdev, linux-kernel
In-Reply-To: <572E72A2.9010004@gmail.com>

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

On Sun, 2016-05-08 at 00:56 +0200, Philippe Reynes wrote:
> On 07/05/16 13:59, Ben Hutchings wrote:
> > 
> > On Sat, 2016-05-07 at 01:18 +0200, Philippe Reynes wrote:
> > > 
> > > The callback {get|set}_link_ksettings are often defined
> > > in a very close way. There are mainly two differences in
> > > those callback:
> > > - the name of the netdev private structure
> > > - the name of the struct phydev in the private structure
> > > 
> > > We add two defines ethtool_phy_{get|set}_link_ksettings
> > > to avoid writing severals times almost the same function.
> > [...]
> > 
> > I don't think there's no need to access a private structure, as there's
> > a phydev pointer in struct net_device.  If some drivers don't maintain
> > that pointer, they should be changed to do so.  Then they can
> > use generic implementations of {get,set}_link_ksettings provided by
> > phylib.
> If we could use the phydev in the struct net_device, we could write a
> generic function for {get|set}_link_ksettings. It's a good idea.
> 
> But I've quickly looked and a lot of ethernet driver use the private
> structure to store the phydev. If the ethernet driver may use the
> struct net_device for phydev, do you know why so many drivers use
> the private structure ?

Maybe just because no-one bothered to update them after it was added to
net_device.

Ben.

> If everybody agree, I can send a new version with a generic {get|set}_link_ksettings
> and a update of fec to use the phydev store in the structure net_device.

-- 
Ben Hutchings
I haven't lost my mind; it's backed up on tape somewhere.

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

^ permalink raw reply

* [PATCH net-next 2/2] net: l3mdev: Allow send on enslaved interface
From: David Ahern @ 2016-05-07 23:49 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern
In-Reply-To: <1462664940-26678-1-git-send-email-dsa@cumulusnetworks.com>

Allow udp and raw sockets to send by oif that is an enslaved interface
versus the l3mdev/VRF device. For example, this allows BFD to use ifindex
from IP_PKTINFO on a receive to send a response without the need to
convert to the VRF index. It also allows ping and ping6 to work when
specifying an enslaved interface (e.g., ping -I swp1 <ip>) which is
a natural use case.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 drivers/net/vrf.c   |  2 ++
 net/ipv4/route.c    |  4 ++++
 net/l3mdev/l3mdev.c | 17 +++++++++++++----
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 4b2461ae5d3b..c8db55aa8280 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -648,6 +648,8 @@ static int vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
 
 	fl4->flowi4_flags |= FLOWI_FLAG_SKIP_NH_OIF;
 	fl4->flowi4_iif = LOOPBACK_IFINDEX;
+	/* make sure oif is set to VRF device for lookup */
+	fl4->flowi4_oif = dev->ifindex;
 	fl4->flowi4_tos = tos & IPTOS_RT_MASK;
 	fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
 			     RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 8c8c655bb2c4..a1f2830d8110 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2146,6 +2146,7 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
 	unsigned int flags = 0;
 	struct fib_result res;
 	struct rtable *rth;
+	int master_idx;
 	int orig_oif;
 	int err = -ENETUNREACH;
 
@@ -2155,6 +2156,9 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
 
 	orig_oif = fl4->flowi4_oif;
 
+	master_idx = l3mdev_master_ifindex_by_index(net, fl4->flowi4_oif);
+	if (master_idx)
+		fl4->flowi4_oif = master_idx;
 	fl4->flowi4_iif = LOOPBACK_IFINDEX;
 	fl4->flowi4_tos = tos & IPTOS_RT_MASK;
 	fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
diff --git a/net/l3mdev/l3mdev.c b/net/l3mdev/l3mdev.c
index 898d01e0f87b..6651a78e100c 100644
--- a/net/l3mdev/l3mdev.c
+++ b/net/l3mdev/l3mdev.c
@@ -112,12 +112,18 @@ struct dst_entry *l3mdev_get_rt6_dst(struct net *net,
 	struct dst_entry *dst = NULL;
 	struct net_device *dev;
 
-	dev = dev_get_by_index(net, fl6->flowi6_oif);
-	if (dev) {
-		if (netif_is_l3_master(dev) &&
+	if (fl6->flowi6_oif) {
+		rcu_read_lock();
+
+		dev = dev_get_by_index_rcu(net, fl6->flowi6_oif);
+		if (dev && netif_is_l3_slave(dev))
+			dev = netdev_master_upper_dev_get_rcu(dev);
+
+		if (dev && netif_is_l3_master(dev) &&
 		    dev->l3mdev_ops->l3mdev_get_rt6_dst)
 			dst = dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6);
-		dev_put(dev);
+
+		rcu_read_unlock();
 	}
 
 	return dst;
@@ -141,6 +147,9 @@ int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4)
 		rcu_read_lock();
 
 		dev = dev_get_by_index_rcu(net, ifindex);
+		if (dev && netif_is_l3_slave(dev))
+			dev = netdev_master_upper_dev_get_rcu(dev);
+
 		if (dev && netif_is_l3_master(dev) &&
 		    dev->l3mdev_ops->l3mdev_get_saddr)
 			rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
-- 
2.1.4

^ permalink raw reply related

* [PATCH net-next 1/2] net: l3mdev: Move get_saddr and rt6_dst
From: David Ahern @ 2016-05-07 23:48 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern
In-Reply-To: <1462664940-26678-1-git-send-email-dsa@cumulusnetworks.com>

Move l3mdev_rt6_dst_by_oif and l3mdev_get_saddr to l3mdev.c. Collapse
l3mdev_get_rt6_dst into l3mdev_rt6_dst_by_oif since it is the only
user and keep the l3mdev_get_rt6_dst name for consistency with other
hooks.

A follow-on patch adds more code to these functions making them long
for inlined functions.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 include/net/l3mdev.h | 56 +++-------------------------------------------------
 net/ipv6/route.c     |  2 +-
 net/l3mdev/l3mdev.c  | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 54 deletions(-)

diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h
index c43a9c73de5e..78872bd1dc2c 100644
--- a/include/net/l3mdev.h
+++ b/include/net/l3mdev.h
@@ -130,52 +130,9 @@ static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
 	return rc;
 }
 
-static inline int l3mdev_get_saddr(struct net *net, int ifindex,
-				   struct flowi4 *fl4)
-{
-	struct net_device *dev;
-	int rc = 0;
-
-	if (ifindex) {
-
-		rcu_read_lock();
-
-		dev = dev_get_by_index_rcu(net, ifindex);
-		if (dev && netif_is_l3_master(dev) &&
-		    dev->l3mdev_ops->l3mdev_get_saddr) {
-			rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
-		}
-
-		rcu_read_unlock();
-	}
-
-	return rc;
-}
+int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4);
 
-static inline struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
-						   const struct flowi6 *fl6)
-{
-	if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rt6_dst)
-		return dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6);
-
-	return NULL;
-}
-
-static inline
-struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
-					const struct flowi6 *fl6)
-{
-	struct dst_entry *dst = NULL;
-	struct net_device *dev;
-
-	dev = dev_get_by_index(net, fl6->flowi6_oif);
-	if (dev) {
-		dst = l3mdev_get_rt6_dst(dev, fl6);
-		dev_put(dev);
-	}
-
-	return dst;
-}
+struct dst_entry *l3mdev_get_rt6_dst(struct net *net, const struct flowi6 *fl6);
 
 #else
 
@@ -233,14 +190,7 @@ static inline int l3mdev_get_saddr(struct net *net, int ifindex,
 }
 
 static inline
-struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
-				     const struct flowi6 *fl6)
-{
-	return NULL;
-}
-static inline
-struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
-					const struct flowi6 *fl6)
+struct dst_entry *l3mdev_get_rt6_dst(struct net *net, const struct flowi6 *fl6)
 {
 	return NULL;
 }
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index af46e19205f5..c42fa1deb152 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1190,7 +1190,7 @@ struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
 	struct dst_entry *dst;
 	bool any_src;
 
-	dst = l3mdev_rt6_dst_by_oif(net, fl6);
+	dst = l3mdev_get_rt6_dst(net, fl6);
 	if (dst)
 		return dst;
 
diff --git a/net/l3mdev/l3mdev.c b/net/l3mdev/l3mdev.c
index e925037fa0df..898d01e0f87b 100644
--- a/net/l3mdev/l3mdev.c
+++ b/net/l3mdev/l3mdev.c
@@ -97,3 +97,57 @@ u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
 	return tb_id;
 }
 EXPORT_SYMBOL_GPL(l3mdev_fib_table_by_index);
+
+/**
+ *	l3mdev_get_rt6_dst - IPv6 route lookup based on flow. Returns
+ *			     cached route for L3 master device if relevant
+ *			     to flow
+ *	@net: network namespace for device index lookup
+ *	@fl6: IPv6 flow struct for lookup
+ */
+
+struct dst_entry *l3mdev_get_rt6_dst(struct net *net,
+				     const struct flowi6 *fl6)
+{
+	struct dst_entry *dst = NULL;
+	struct net_device *dev;
+
+	dev = dev_get_by_index(net, fl6->flowi6_oif);
+	if (dev) {
+		if (netif_is_l3_master(dev) &&
+		    dev->l3mdev_ops->l3mdev_get_rt6_dst)
+			dst = dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6);
+		dev_put(dev);
+	}
+
+	return dst;
+}
+EXPORT_SYMBOL_GPL(l3mdev_get_rt6_dst);
+
+/**
+ *	l3mdev_get_saddr - get source address for a flow based on an interface
+ *			   enslaved to an L3 master device
+ *	@net: network namespace for device index lookup
+ *	@ifindex: Interface index
+ *	@fl4: IPv4 flow struct
+ */
+
+int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4)
+{
+	struct net_device *dev;
+	int rc = 0;
+
+	if (ifindex) {
+		rcu_read_lock();
+
+		dev = dev_get_by_index_rcu(net, ifindex);
+		if (dev && netif_is_l3_master(dev) &&
+		    dev->l3mdev_ops->l3mdev_get_saddr)
+			rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
+
+		rcu_read_unlock();
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(l3mdev_get_saddr);
-- 
2.1.4

^ permalink raw reply related

* [PATCH net-next v2 0/2] net: l3mdev: Allow send on enslaved interface
From: David Ahern @ 2016-05-07 23:48 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern

First patch preps for the second. The second is required for several use
cases such as ping on an interface and BFD that need to send packets on
a specific interface, including ones enslaved to a VRF device.

v2
- fixed brackets on both patches per comment from DaveM

David Ahern (2):
  net: l3mdev: Move get_saddr and rt6_dst
  net: l3mdev: Allow send on enslaved interface

 drivers/net/vrf.c    |  2 ++
 include/net/l3mdev.h | 56 +++-------------------------------------------
 net/ipv4/route.c     |  4 ++++
 net/ipv6/route.c     |  2 +-
 net/l3mdev/l3mdev.c  | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 73 insertions(+), 54 deletions(-)

-- 
2.1.4

^ permalink raw reply

* ?
From: Robert @ 2016-05-07 21:24 UTC (permalink / raw)


Did you get my previous mail? When can i call you?

^ permalink raw reply

* Re: [PATCH 1/2] net: phy: add ethtool_phy_{get|set}_link_ksettings
From: Philippe Reynes @ 2016-05-07 22:56 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: f.fainelli, fugang.duan, davem, netdev, linux-kernel
In-Reply-To: <1462622397.19332.28.camel@decadent.org.uk>

On 07/05/16 13:59, Ben Hutchings wrote:
> On Sat, 2016-05-07 at 01:18 +0200, Philippe Reynes wrote:
>> The callback {get|set}_link_ksettings are often defined
>> in a very close way. There are mainly two differences in
>> those callback:
>> - the name of the netdev private structure
>> - the name of the struct phydev in the private structure
>>
>> We add two defines ethtool_phy_{get|set}_link_ksettings
>> to avoid writing severals times almost the same function.
> [...]
>
> I don't think there's no need to access a private structure, as there's
> a phydev pointer in struct net_device.  If some drivers don't maintain
> that pointer, they should be changed to do so.  Then they can
> use generic implementations of {get,set}_link_ksettings provided by
> phylib.

If we could use the phydev in the struct net_device, we could write a
generic function for {get|set}_link_ksettings. It's a good idea.

But I've quickly looked and a lot of ethernet driver use the private
structure to store the phydev. If the ethernet driver may use the
struct net_device for phydev, do you know why so many drivers use
the private structure ?

If everybody agree, I can send a new version with a generic {get|set}_link_ksettings
and a update of fec to use the phydev store in the structure net_device.

Philippe

^ permalink raw reply

* Loan
From: Loan Financial Institute @ 2016-05-07 21:12 UTC (permalink / raw)
  To: Recipients

Do you need a personal or business loan without stress and
quick approval?
contact us via email: loa121@foxmail.com

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

^ permalink raw reply

* [PATCH 2/2] sh_eth: reuse sh_eth_chip_reset()
From: Sergei Shtylyov @ 2016-05-07 21:09 UTC (permalink / raw)
  To: netdev; +Cc: linux-renesas-soc
In-Reply-To: <1808900.MGlUzc8O9C@wasted.cogentembedded.com>

All the chip_reset() methods repeat the code writing to the ARSTR register
and delaying for 1 ms, so that we can reuse sh_eth_chip_reset() twice.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

---
 drivers/net/ethernet/renesas/sh_eth.c |   11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

Index: net-next/drivers/net/ethernet/renesas/sh_eth.c
===================================================================
--- net-next.orig/drivers/net/ethernet/renesas/sh_eth.c
+++ net-next/drivers/net/ethernet/renesas/sh_eth.c
@@ -537,11 +537,7 @@ static struct sh_eth_cpu_data r7s72100_d
 
 static void sh_eth_chip_reset_r8a7740(struct net_device *ndev)
 {
-	struct sh_eth_private *mdp = netdev_priv(ndev);
-
-	/* reset device */
-	sh_eth_tsu_write(mdp, ARSTR_ARST, ARSTR);
-	mdelay(1);
+	sh_eth_chip_reset(ndev);
 
 	sh_eth_select_mii(ndev);
 }
@@ -725,7 +721,6 @@ static struct sh_eth_cpu_data sh7757_dat
 #define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
 static void sh_eth_chip_reset_giga(struct net_device *ndev)
 {
-	struct sh_eth_private *mdp = netdev_priv(ndev);
 	u32 mahr[2], malr[2];
 	int i;
 
@@ -735,9 +730,7 @@ static void sh_eth_chip_reset_giga(struc
 		mahr[i] = ioread32((void *)GIGA_MAHR(i));
 	}
 
-	/* reset device */
-	sh_eth_tsu_write(mdp, ARSTR_ARST, ARSTR);
-	mdelay(1);
+	sh_eth_chip_reset(ndev);
 
 	/* restore MAHR and MALR */
 	for (i = 0; i < 2; i++) {

^ permalink raw reply

* [PATCH 1/2] sh_eth: call sh_eth_tsu_write() from sh_eth_chip_reset_giga()
From: Sergei Shtylyov @ 2016-05-07 21:08 UTC (permalink / raw)
  To: netdev; +Cc: linux-renesas-soc
In-Reply-To: <1808900.MGlUzc8O9C@wasted.cogentembedded.com>

sh_eth_chip_reset_giga() doesn't really need to use direct iowrite32() when
writing  to the ARSTR register,  it can use sh_eth_tsu_write() as all other
chip_reset() methods.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

---
 drivers/net/ethernet/renesas/sh_eth.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Index: net-next/drivers/net/ethernet/renesas/sh_eth.c
===================================================================
--- net-next.orig/drivers/net/ethernet/renesas/sh_eth.c
+++ net-next/drivers/net/ethernet/renesas/sh_eth.c
@@ -725,8 +725,9 @@ static struct sh_eth_cpu_data sh7757_dat
 #define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
 static void sh_eth_chip_reset_giga(struct net_device *ndev)
 {
-	int i;
+	struct sh_eth_private *mdp = netdev_priv(ndev);
 	u32 mahr[2], malr[2];
+	int i;
 
 	/* save MAHR and MALR */
 	for (i = 0; i < 2; i++) {
@@ -735,7 +736,7 @@ static void sh_eth_chip_reset_giga(struc
 	}
 
 	/* reset device */
-	iowrite32(ARSTR_ARST, (void *)(SH_GIGA_ETH_BASE + 0x1800));
+	sh_eth_tsu_write(mdp, ARSTR_ARST, ARSTR);
 	mdelay(1);
 
 	/* restore MAHR and MALR */

^ permalink raw reply

* [PATCH 0/2] sh_eth: couple of software reset bit cleanups
From: Sergei Shtylyov @ 2016-05-07 21:06 UTC (permalink / raw)
  To: netdev; +Cc: linux-renesas-soc

Hello.

   Here's a set of 2 patches against DaveM's 'net-next.git' repo. We can save
on the repetitive chip reset code...

[1/2] sh_eth: call sh_eth_tsu_write() from sh_eth_chip_reset_giga()
[2/2] sh_eth: reuse sh_eth_chip_reset()

MBR, Sergei

^ permalink raw reply

* Re: [PATCH net-next 15/21] net: dsa: mv88e6xxx: factorize VLAN Ethertype
From: Vivien Didelot @ 2016-05-07 20:51 UTC (permalink / raw)
  To: Andrew Lunn, f
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <20160506223344.GE2073@lunn.ch>

Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> On Fri, May 06, 2016 at 05:57:17PM -0400, Vivien Didelot wrote:
>> The 6131 switch models have a Core Tag Type register. Add a
>> MV88E6XXX_FLAG_CORE_TAG_TYPE flag and set the VLAN Ethertype to 0x8100
>> in the shared setup code if it is present.
>
> Do you have any idea what the core tag is?

Core Tag Type is the global register 0x19 present only on 6185 and
similar. It is used when egressing double tagged frames. This value is
also checked when ingressing frames on ports in UseCoreTag mode.

Note that we might remove this flag and setup condition, because 0x8100
is the reset value anyway.

        Vivien

^ permalink raw reply

* Re: [PATCH net-next 06/21] net: dsa: mv88e6xxx: factorize MAC address setting
From: Vivien Didelot @ 2016-05-07 20:37 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <20160506222320.GB2073@lunn.ch>

Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

>> @@ -378,6 +385,7 @@ enum mv88e6xxx_cap {
>>  #define MV88E6XXX_FLAG_EEPROM		BIT(MV88E6XXX_CAP_EEPROM)
>>  #define MV88E6XXX_FLAG_PPU		BIT(MV88E6XXX_CAP_PPU)
>>  #define MV88E6XXX_FLAG_SMI_PHY		BIT(MV88E6XXX_CAP_SMI_PHY)
>> +#define MV88E6XXX_FLAG_SWITCH_MAC	BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)
>>  #define MV88E6XXX_FLAG_TEMP		BIT(MV88E6XXX_CAP_TEMP)
>>  #define MV88E6XXX_FLAG_TEMP_LIMIT	BIT(MV88E6XXX_CAP_TEMP_LIMIT)
>
> There is a general pattern here that the flag has a name derived from
> the capability. Except you dropped the WOL_WOF here. It would probably
> be better to not have WOL_WOF at all.

Indeed, I did that because the global 2 register 0x0D "Switch
MAC/WoL/WoF" is used to indirectly configure the switch MAC address, the
Wake on Lan and Wake on Frame. So I explicitly named the capability
MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF and the flag for the switch MAC
MV88E6XXX_FLAG_SWITCH_MAC.

So if we add support for WoL, we can then define:

    #define MV88E6XXX_FLAG_WOL BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)

But I can get rid of it if it feels confusing.

Thanks,

        Vivien

^ permalink raw reply

* [PATCH] pxa168_eth: mdiobus_scan() doesn't return NULL anymore
From: Sergei Shtylyov @ 2016-05-07 19:53 UTC (permalink / raw)
  To: netdev
In-Reply-To: <19240252.825Vlx6L0H@wasted.cogentembedded.com>

Now that mdiobus_scan() doesn't return NULL on failure anymore, this driver
no  longer needs to check for it...

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

---
The patch is against DaveM's 'net-next.git' repo.

 drivers/net/ethernet/marvell/pxa168_eth.c |    2 --
 1 file changed, 2 deletions(-)

Index: net-next/drivers/net/ethernet/marvell/pxa168_eth.c
===================================================================
--- net-next.orig/drivers/net/ethernet/marvell/pxa168_eth.c
+++ net-next/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -981,8 +981,6 @@ static int pxa168_init_phy(struct net_de
 	pep->phy = mdiobus_scan(pep->smi_bus, pep->phy_addr);
 	if (IS_ERR(pep->phy))
 		return PTR_ERR(pep->phy);
-	if (!pep->phy)
-		return -ENODEV;
 
 	err = phy_connect_direct(dev, pep->phy, pxa168_eth_adjust_link,
 				 pep->phy_intf);

^ permalink raw reply

* Re: [PATCH v2 1/2 -net] ravb: Add missing free_irq() call to ravb_close()
From: Geert Uytterhoeven @ 2016-05-07 19:42 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Geert Uytterhoeven, David S. Miller, Yoshihiro Kaneko,
	Simon Horman, netdev@vger.kernel.org, linux-renesas-soc
In-Reply-To: <572E3673.5020304@cogentembedded.com>

On Sat, May 7, 2016 at 8:39 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> On 05/07/2016 02:17 PM, Geert Uytterhoeven wrote:
>
>> When reopening the network device on ra7795/salvator-x, e.g. after a
>> DHCP timeout:
>>
>>      IP-Config: Reopening network devices...
>>      genirq: Flags mismatch irq 139. 00000000 (eth0:ch24:emac) vs.
>> 00000000 (eth0:ch24:emac)
>>      ravb e6800000.ethernet eth0: cannot request IRQ eth0:ch24:emac
>
>    Er, this can't be a message from the kernel built from net.git. That
> driver used 'ndev->name'
> to request both IRQs...

Oops, I copied the error message from the second patch.
I don't think it matters that much, though...

>>      IP-Config: Failed to open eth0
>>      IP-Config: No network devices available
>>
>> The "mismatch" is due to requesting an IRQ that is already in use,
>> while IRQF_PROBE_SHARED wasn't set.
>>
>> However, the real cause is that ravb_close() doesn't release the R-Car
>> Gen3-specific secondary IRQ.
>>
>> Add the missing free_irq() call to fix this.
>>
>> Fixes: 22d4df8ff3a3cc72 ("ravb: Add support for r8a7795 SoC")
>> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
>
>
> Acked-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

Thanks!

Gr{oetje,eeting}s,

                        Geert

^ permalink raw reply

* Re: [patch] netxen: netxen_rom_fast_read() doesn't return -1
From: David Miller @ 2016-05-07 19:16 UTC (permalink / raw)
  To: dan.carpenter
  Cc: manish.chopra, sony.chacko, rajesh.borundia, netdev, linux-kernel,
	kernel-janitors
In-Reply-To: <20160505132019.GD3038@mwanda>

From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Thu, 5 May 2016 16:20:20 +0300

> The error handling is broken here.  netxen_rom_fast_read() returns zero
> on success and -EIO on error.  It never returns -1.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied.

^ permalink raw reply


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