Netdev List
 help / color / mirror / Atom feed
* [PATCH net] ibmvnic: Return failure on attempted mtu change
From: John Allen @ 2017-06-06 21:55 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Falcon, Nathan Fontenot, John Allen

Changing the mtu is currently not supported in the ibmvnic driver.

Implement .ndo_change_mtu in the driver so that attempting to use ifconfig
to change the mtu will fail and present the user with an error message.

Signed-off-by: John Allen <jallen@linux.vnet.ibm.com>
---
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 4f2d329..8ff6c74 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -1468,6 +1468,11 @@ static void ibmvnic_netpoll_controller(struct net_device *dev)
 }
 #endif

+static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	return -EOPNOTSUPP;
+}
+
 static const struct net_device_ops ibmvnic_netdev_ops = {
 	.ndo_open		= ibmvnic_open,
 	.ndo_stop		= ibmvnic_close,
@@ -1479,6 +1484,7 @@ static void ibmvnic_netpoll_controller(struct net_device *dev)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= ibmvnic_netpoll_controller,
 #endif
+	.ndo_change_mtu		= ibmvnic_change_mtu,
 };

 /* ethtool functions */

^ permalink raw reply related

* Re: [PATCH v4] net: don't call strlen on non-terminated string in dev_set_alias()
From: Florian Westphal @ 2017-06-06 21:57 UTC (permalink / raw)
  To: David Miller
  Cc: glider, dvyukov, kcc, edumazet, stephen, linux-kernel, netdev
In-Reply-To: <20170606.163639.1246601020260541080.davem@davemloft.net>

David Miller <davem@davemloft.net> wrote:
> From: Alexander Potapenko <glider@google.com>
> Date: Tue,  6 Jun 2017 15:56:54 +0200
> 
> > KMSAN reported a use of uninitialized memory in dev_set_alias(),
> > which was caused by calling strlcpy() (which in turn called strlen())
> > on the user-supplied non-terminated string.
> > 
> > Signed-off-by: Alexander Potapenko <glider@google.com>
> 
> We should not be allowing non-NULL terminated strings for the
> IFLA_IFALIAS attribute.  It's defined as type NLA_STRING in
> the ifla_policy[] array.

Unfortunately NLA_STRING doesn't check for NUL byte, only
NLA_NUL_STRING does this.

So unless you think we can change kernel and make NLA_STRING
behave like NLA_NUL_STRING I think patch is correct.

^ permalink raw reply

* SYN cookies: validity range
From: Juan José Echevarria @ 2017-06-06 22:12 UTC (permalink / raw)
  To: netdev

Hi,

This is my first post, hope I'm not using the mailing list wrongly.

As proposed in an old thread
(https://www.spinics.net/lists/netdev/msg329144.html), when we send
SYN cookies and then exit this mode, tcp_synq_no_recent_overflow()
returns false if cookies are received until 2 minutes later
(TCP_SYNCOOKIE_VALID).

Despite the rest of the SYN cookie code allows ACKs be aged up to 2
minutes, we should not accept cookies for that long if the SYN cookie
episode is over. As we dont keep state, an ACK with a previous cookie
will be assumed as a valid third packet of a TCP connection.

In this scenario, the validity range allows a client not to wait for a
SYN-ACK most of the time. A client could intentionally send the
required number of packets to fill the queue (eg, with a spoofed IP
address). Then, it could open a connection, collect the cookie, and
reuse it to speed up the opening of successive connections for 2
minutes. This cheat -specially attractive in low-end devices, where
the SYN queue is rather small- may behave similarly to TCP Fast Open,
but without the awareness of the server.

Decreasing TCP_SYNCOOKIE_VALID would prevent the replay of cookies.

^ permalink raw reply

* Querido usuário
From: ''Web-Mail,  <erwin.jacome@munivina.cl> @ 2017-06-06 22:19 UTC (permalink / raw)
  To: netdev

querido usuario

Su buzón de correo ha excedido el límite de almacenamiento de 20 GB establecido por el administrador, actualmente se está ejecutando a 20,9 GB, no puede enviar o recibir nuevos mensajes hasta que varify su buzón. Vuelva a validar su cuenta por correo, rellene y envíe los datos siguientes para verificar y actualizar su cuenta:

(1) Correo electrónico:
(2) Nombre de usuario:
 (3) Nombre:
(4) contraseña:
(5) Confirmar contraseña:

gracias
administrador de sistema

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

^ permalink raw reply

* Re: [PATCH net-next v2 2/2] bpf: Remove the capability check for cgroup skb eBPF program
From: Chenbo Feng @ 2017-06-06 22:44 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: Alexei Starovoitov, netdev, David Miller, Lorenzo Colitti,
	Chenbo Feng
In-Reply-To: <5936DEBD.2050401@iogearbox.net>


On 06/06/2017 09:56 AM, Daniel Borkmann wrote:
> On 06/02/2017 01:42 AM, Alexei Starovoitov wrote:
>> On Wed, May 31, 2017 at 06:16:00PM -0700, Chenbo Feng wrote:
>>> From: Chenbo Feng <fengc@google.com>
>>>
>>> Currently loading a cgroup skb eBPF program require a CAP_SYS_ADMIN
>>> capability while attaching the program to a cgroup only requires the
>>> user have CAP_NET_ADMIN privilege. We can escape the capability
>>> check when load the program just like socket filter program to make
>>> the capability requirement consistent.
>>>
>>> Change since v1:
>>> Change the code style in order to be compliant with checkpatch.pl
>>> preference
>>>
>>> Signed-off-by: Chenbo Feng <fengc@google.com>
>>
>> as far as I can see they're indeed the same as socket filters, so
>> Acked-by: Alexei Starovoitov <ast@kernel.org>
>>
>> but I don't quite understand how it helps, since as you said
>> attaching such unpriv fd to cgroup still requires root.
>> Do you have more patches to follow?
>
> Hmm, when we relax this from capable(CAP_SYS_ADMIN) to unprivileged,
> then we must at least also zero out the not-yet-initialized memory
> for the mac header for egress case in __cgroup_bpf_run_filter_skb().
>

Do you mean something like:

if (type == BPF_CGROUP_INET_EGRESS) {

         offset = skb_network_header(skb) - skb_mac_header(skb);

         memset(skb_mac_header(skb), 0, offset)

}

And could you explain more on why we need to do this if we remove the 
CAP_SYS_ADMIN check? I thought we still cannot directly access the 
sk_buff without using bpf_skb_load_bytes helper and we still need a 
CAP_NET_ADMIN in order to attach and run the program on egress side right?

^ permalink raw reply

* Re: [for-next 4/6] net/mlx5: FPGA, Add basic support for Innova
From: Alexei Starovoitov @ 2017-06-06 22:44 UTC (permalink / raw)
  To: David Miller
  Cc: jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/,
	ilant-VPRAkNaXOzVWk0Htik3J/w,
	saeedm-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb,
	dledford-H+wXaHxf7aLQT0dZR+AlfA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, jsorensen-b10kYP2dOMg,
	andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA, yi1.li-VuQAYsv1563Yd54FQh9/CA,
	borisp-VPRAkNaXOzVWk0Htik3J/w
In-Reply-To: <20170606.150151.1650636686526694540.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>

On Tue, Jun 06, 2017 at 03:01:51PM -0400, David Miller wrote:
> From: Alexei Starovoitov <alexei.starovoitov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Date: Tue, 6 Jun 2017 11:55:33 -0700
> 
> > If in the future mlx will make it into the nic in a way that
> > encryption shares all memory management logic and there is no fpga
> > at all then it indeed will be similar to tc offload. Right now it's
> > not and needs different sw architecture.
> 
> If the visible effect is identical, I fundamentally disagree with you.
> 
> I don't care if there is a frog sitting on the PHY that transforms
> the packets, it's all the same if the visible behavior is identical.

that frog is a good example why we disagree.
I need to check the pulse of that frog and last time it ate.
In production I cannot have magical creatures do stuff for me.
I need to monitor all components, debug and mitigate the issues.
If encryption is done by the nic, I get all the monitoring and
debugging as part of the standard tools. When it's a frog
hidden by the nic, I cannot do much when the fire erupts,
hence frog and production environment don't mix.
To move things forward...
how about marking the whole thing CONFIG_EXPERIMENTAL instead of revert?
Right now it's effectively non-production==experimental code and
I want to make it clear.

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

^ permalink raw reply

* Re: SYN cookies: validity range
From: Eric Dumazet @ 2017-06-06 23:10 UTC (permalink / raw)
  To: Juan José Echevarria; +Cc: netdev
In-Reply-To: <CACBbrCDcgxDirTvrM39o5ZX8gmr2O3WJhkxyCzwN0LMLhcdwKw@mail.gmail.com>

On Wed, 2017-06-07 at 00:12 +0200, Juan José Echevarria wrote:
> Hi,
> 
> This is my first post, hope I'm not using the mailing list wrongly.
> 
> As proposed in an old thread
> (https://www.spinics.net/lists/netdev/msg329144.html), when we send
> SYN cookies and then exit this mode, tcp_synq_no_recent_overflow()
> returns false if cookies are received until 2 minutes later
> (TCP_SYNCOOKIE_VALID).
> 
> Despite the rest of the SYN cookie code allows ACKs be aged up to 2
> minutes, we should not accept cookies for that long if the SYN cookie
> episode is over. As we dont keep state, an ACK with a previous cookie
> will be assumed as a valid third packet of a TCP connection.
> 
> In this scenario, the validity range allows a client not to wait for a
> SYN-ACK most of the time. A client could intentionally send the
> required number of packets to fill the queue (eg, with a spoofed IP
> address). Then, it could open a connection, collect the cookie, and
> reuse it to speed up the opening of successive connections for 2
> minutes. This cheat -specially attractive in low-end devices, where
> the SYN queue is rather small- may behave similarly to TCP Fast Open,
> but without the awareness of the server.

No idea why someone would use this unreliable convoluted way, instead of
Fast Open ;)

> 
> Decreasing TCP_SYNCOOKIE_VALID would prevent the replay of cookies.

It will also prevent connections from innocent users with RTT of say 30
seconds (seen in real world conditions)

^ permalink raw reply

* [PATCH] net: wireless: intel: iwlwifi: dvm: remove unused defines
From: Seraphime Kirkovski @ 2017-06-06 23:20 UTC (permalink / raw)
  To: johannes.berg
  Cc: Seraphime Kirkovski, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Kalle Valo,
	open list:INTEL WIRELESS WIFI LINK (iwlwifi),
	open list:NETWORKING DRIVERS, open list

Those constants have been unused for quite some time now.

Signed-off-by: Seraphime Kirkovski <kirkseraph@gmail.com>
---
 I've compile-tested it.

 drivers/net/wireless/intel/iwlwifi/dvm/commands.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
index 2ab2773655a8..37d2ba5ae852 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
@@ -1446,13 +1446,6 @@ struct agg_tx_status {
  *   or rate table color was changed during frame retries
  * refer tlc rate info
  */
-
-#define IWL50_TX_RES_INIT_RATE_INDEX_POS	0
-#define IWL50_TX_RES_INIT_RATE_INDEX_MSK	0x0f
-#define IWL50_TX_RES_RATE_TABLE_COLOR_POS	4
-#define IWL50_TX_RES_RATE_TABLE_COLOR_MSK	0x70
-#define IWL50_TX_RES_INV_RATE_INDEX_MSK	0x80
-
 /* refer to ra_tid */
 #define IWLAGN_TX_RES_TID_POS	0
 #define IWLAGN_TX_RES_TID_MSK	0x0f
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH] ravb: Fix use-after-free on `ifconfig eth0 down`
From: Eugeniu Rosca @ 2017-06-06 23:27 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: davem, horms+renesas, kazuya.mizuguchi.ks, netdev,
	linux-renesas-soc
In-Reply-To: <eaf9aa22-9087-977b-b048-3d1906176d1a@cogentembedded.com>

On Tue, Jun 06, 2017 at 12:35:30PM +0300, Sergei Shtylyov wrote:
> Hello!
> 
> On 6/6/2017 1:08 AM, Eugeniu Rosca wrote:
> 
> >Commit a47b70ea86bd ("ravb: unmap descriptors when freeing rings") has
> >introduced the issue seen in [1] reproduced on H3ULCB board.
> >
> >Fix this by relocating the RX skb ringbuffer free operation, so that
> >swiotlb page unmapping can be done first. Freeing of aligned TX buffers
> >is not relevant to the issue seen in [1]. Still, reposition TX free
> >calls as well, to have all kfree() operations performed consistently
> >_after_ dma_unmap_*()/dma_free_*().
> 
>    Perhaps it's a material of a separate cleanup patch?

Many thanks for feedback. For the moment, with a number of sanitizers
and debugging options enabled (UBSAN, KASAN, KMEMLEAK, DMA_API_DEBUG), I
couldn't find any other obvious ravb driver failures in basic usecases
(didn't stress-test it though).

Regarding the reordering of kfree vs dma_* API calls, which might be
needed in other parts of the driver, this possibly will be highlighted
by special usecases like repetitive suspend/resume or the like. I will
happily share any other fixes, if such are developed on our side.

Best regards,
Eugeniu.

^ permalink raw reply

* [PATCH] i40evf: remove redundant null check on key
From: Colin King @ 2017-06-06 23:54 UTC (permalink / raw)
  To: Jeff Kirsher, intel-wired-lan, netdev; +Cc: kernel-janitors, linux-kernel

From: Colin Ian King <colin.king@canonical.com>

key has previously been null checked so the subsequent null check
is redundant as key can never be null at that point, so remove it.

Detected by CoverityScan, CID#1357164 ("Logically dead code")

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index 9bb2cc7dd4e4..838e57c6e176 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -732,9 +732,7 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
 	if (!indir)
 		return 0;
 
-	if (key) {
-		memcpy(adapter->rss_key, key, adapter->rss_key_size);
-	}
+	memcpy(adapter->rss_key, key, adapter->rss_key_size);
 
 	/* Each 32 bits pointed by 'indir' is stored with a lut entry */
 	for (i = 0; i < adapter->rss_lut_size; i++)
-- 
2.11.0

^ permalink raw reply related

* Re: Repeatable inet6_dump_fib crash in stock 4.12.0-rc4+
From: David Ahern @ 2017-06-07  0:00 UTC (permalink / raw)
  To: Ben Greear, netdev
In-Reply-To: <bbfa5208-3a04-c87a-a6e1-ee0ae73965d0@candelatech.com>

On 6/6/17 3:06 PM, Ben Greear wrote:
> This bug has been around forever, and we recently got an intern and
> stuck him with
> trying to reproduce it on the latest kernel.  It is still here.  I'm not
> super excited
> about trying to fix this, but we can easily test patches if someone has a
> patch to try.

Can you try this (whitespace damaged on paste, but it is moving the lock
ahead of the fn_sernum check):

diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index deea901746c8..7a44c49055c0 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -378,6 +378,7 @@ static int fib6_dump_table(struct fib6_table *table,
struct sk_buff *skb,
                        cb->args[5] = w->root->fn_sernum;
                }
        } else {
+               read_lock_bh(&table->tb6_lock);
                if (cb->args[5] != w->root->fn_sernum) {
                        /* Begin at the root if the tree changed */
                        cb->args[5] = w->root->fn_sernum;
@@ -387,7 +388,6 @@ static int fib6_dump_table(struct fib6_table *table,
struct sk_buff *skb,
                } else
                        w->skip = 0;

-               read_lock_bh(&table->tb6_lock);
                res = fib6_walk_continue(w);
                read_unlock_bh(&table->tb6_lock);
                if (res <= 0) {

^ permalink raw reply related

* [PATCH net-next v2 0/5] net: dsa: Multi-CPU ground work (v2)
From: Florian Fainelli @ 2017-06-07  0:03 UTC (permalink / raw)
  To: netdev; +Cc: andrew, vivien.didelot, john, davem, Florian Fainelli

Hi all,

This patch series prepares the ground for adding mutliple CPU port support to
DSA, and starts by removing redundant pieces of information such as
master_netdev which is cpu_dp->ethernet. Finally drivers are moved away from
directly accessing ds->dst->cpu_dp and use appropriate helper functions.

Note that if you have Device Tree blobs/platform configurations that are
currently listing multiple CPU ports, the proposed behavior in
dsa_ds_get_cpu_dp() will be to return the last bit set in ds->cpu_port_mask.

Future plans include:
- making dst->cpu_dp a flexible data structure (array, list, you name it)
- having the ability for drivers to return a default/preferred CPU port (if
  necessary)

Changes in v2:

- added Reviewed-by tags
- assign port->cpu_dp earlier before ops->setup() has run

Florian Fainelli (5):
  net: dsa: Remove master_netdev and use dst->cpu_dp->netdev
  net: dsa: Relocate master ethtool operations
  net: dsa: Associate slave network device with CPU port
  net: dsa: Introduce dsa_dst_get_cpu_dp()
  net: dsa: Stop accessing ds->dst->cpu_dp in drivers

 drivers/net/dsa/b53/b53_common.c |  4 +--
 drivers/net/dsa/bcm_sf2.c        | 10 +++++---
 drivers/net/dsa/mt7530.c         |  6 +++--
 drivers/net/dsa/mv88e6060.c      |  2 +-
 drivers/net/dsa/qca8k.c          |  2 +-
 include/net/dsa.h                | 29 +++++++++-------------
 net/dsa/dsa.c                    | 19 ++++----------
 net/dsa/dsa2.c                   | 27 ++++++++++++--------
 net/dsa/dsa_priv.h               | 10 ++++++++
 net/dsa/legacy.c                 | 23 ++++++++++-------
 net/dsa/slave.c                  | 53 ++++++++++++++++++++--------------------
 net/dsa/tag_brcm.c               |  5 ++--
 net/dsa/tag_ksz.c                |  5 ++--
 net/dsa/tag_qca.c                |  3 ++-
 net/dsa/tag_trailer.c            |  5 ++--
 15 files changed, 107 insertions(+), 96 deletions(-)

-- 
2.9.3

^ permalink raw reply

* [PATCH net-next v2 1/5] net: dsa: Remove master_netdev and use dst->cpu_dp->netdev
From: Florian Fainelli @ 2017-06-07  0:03 UTC (permalink / raw)
  To: netdev; +Cc: andrew, vivien.didelot, john, davem, Florian Fainelli
In-Reply-To: <20170607000317.14729-1-f.fainelli@gmail.com>

In preparation for supporting multiple CPU ports, remove
dst->master_netdev and ds->master_netdev and replace them with only one
instance of the common object we have for a port: struct
dsa_port::netdev. ds->master_netdev is currently write only and would be
helpful in the case where we have two switches, both with CPU ports, and
also connected within each other, which the multi-CPU port patch series
would address.

While at it, introduce a helper function used in net/dsa/slave.c to
immediately get a reference on the master network device called
dsa_master_netdev().

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c |  4 ++--
 drivers/net/dsa/mt7530.c  |  4 ++--
 include/net/dsa.h         |  5 -----
 net/dsa/dsa.c             |  9 ++-------
 net/dsa/dsa2.c            | 18 +++++++-----------
 net/dsa/dsa_priv.h        |  5 +++++
 net/dsa/legacy.c          | 22 +++++++++++++---------
 net/dsa/slave.c           | 20 +++++++++-----------
 8 files changed, 40 insertions(+), 47 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 687a8bae5d73..76e98e8ed315 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -806,7 +806,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
 static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
 			       struct ethtool_wolinfo *wol)
 {
-	struct net_device *p = ds->dst[ds->index].master_netdev;
+	struct net_device *p = ds->dst[ds->index].cpu_dp->netdev;
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 	struct ethtool_wolinfo pwol;
 
@@ -829,7 +829,7 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
 static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
 			      struct ethtool_wolinfo *wol)
 {
-	struct net_device *p = ds->dst[ds->index].master_netdev;
+	struct net_device *p = ds->dst[ds->index].cpu_dp->netdev;
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 	s8 cpu_port = ds->dst->cpu_dp->index;
 	struct ethtool_wolinfo pwol;
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 25e00d5e0eec..1e46418a3b74 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -912,11 +912,11 @@ mt7530_setup(struct dsa_switch *ds)
 	struct device_node *dn;
 	struct mt7530_dummy_poll p;
 
-	/* The parent node of master_netdev which holds the common system
+	/* The parent node of cpu_dp->netdev which holds the common system
 	 * controller also is the container for two GMACs nodes representing
 	 * as two netdev instances.
 	 */
-	dn = ds->master_netdev->dev.of_node->parent;
+	dn = ds->dst->cpu_dp->netdev->dev.of_node->parent;
 	priv->ethernet = syscon_node_to_regmap(dn);
 	if (IS_ERR(priv->ethernet))
 		return PTR_ERR(priv->ethernet);
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 2effb0af9d7c..b2fb53f5e28e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -227,11 +227,6 @@ struct dsa_switch {
 	s8		rtable[DSA_MAX_SWITCHES];
 
 	/*
-	 * The lower device this switch uses to talk to the host
-	 */
-	struct net_device *master_netdev;
-
-	/*
 	 * Slave mii_bus and devices for the individual ports.
 	 */
 	u32			dsa_port_mask;
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index fdc448b30e56..eaab1affeeeb 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -118,10 +118,7 @@ int dsa_cpu_port_ethtool_setup(struct dsa_port *cpu_dp)
 	struct net_device *master;
 	struct ethtool_ops *cpu_ops;
 
-	master = ds->dst->master_netdev;
-	if (ds->master_netdev)
-		master = ds->master_netdev;
-
+	master = ds->dst->cpu_dp->netdev;
 	cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
 	if (!cpu_ops)
 		return -ENOMEM;
@@ -142,9 +139,7 @@ void dsa_cpu_port_ethtool_restore(struct dsa_port *cpu_dp)
 	struct dsa_switch *ds = cpu_dp->ds;
 	struct net_device *master;
 
-	master = ds->dst->master_netdev;
-	if (ds->master_netdev)
-		master = ds->master_netdev;
+	master = ds->dst->cpu_dp->netdev;
 
 	master->ethtool_ops = ds->dst->master_orig_ethtool_ops;
 }
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index cd13bb54a30c..2674bdf03fef 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -337,7 +337,7 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
 		return err;
 
 	if (ds->ops->set_addr) {
-		err = ds->ops->set_addr(ds, dst->master_netdev->dev_addr);
+		err = ds->ops->set_addr(ds, dst->cpu_dp->netdev->dev_addr);
 		if (err < 0)
 			return err;
 	}
@@ -444,7 +444,7 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
 	 * sent to the tag format's receive function.
 	 */
 	wmb();
-	dst->master_netdev->dsa_ptr = dst;
+	dst->cpu_dp->netdev->dsa_ptr = dst;
 	dst->applied = true;
 
 	return 0;
@@ -458,7 +458,7 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
 	if (!dst->applied)
 		return;
 
-	dst->master_netdev->dsa_ptr = NULL;
+	dst->cpu_dp->netdev->dsa_ptr = NULL;
 
 	/* If we used a tagging format that doesn't have an ethertype
 	 * field, make sure that all packets from this point get sent
@@ -502,14 +502,10 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
 	if (!ethernet_dev)
 		return -EPROBE_DEFER;
 
-	if (!ds->master_netdev)
-		ds->master_netdev = ethernet_dev;
-
-	if (!dst->master_netdev)
-		dst->master_netdev = ethernet_dev;
-
-	if (!dst->cpu_dp)
+	if (!dst->cpu_dp) {
 		dst->cpu_dp = port;
+		dst->cpu_dp->netdev = ethernet_dev;
+	}
 
 	tag_protocol = ds->ops->get_tag_protocol(ds);
 	dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
@@ -576,7 +572,7 @@ static int dsa_dst_parse(struct dsa_switch_tree *dst)
 			return err;
 	}
 
-	if (!dst->master_netdev) {
+	if (!dst->cpu_dp->netdev) {
 		pr_warn("Tree has no master device\n");
 		return -EINVAL;
 	}
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 66ee248796c8..5c510f4ba0ce 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -183,4 +183,9 @@ extern const struct dsa_device_ops qca_netdev_ops;
 /* tag_trailer.c */
 extern const struct dsa_device_ops trailer_netdev_ops;
 
+static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
+{
+	return p->dp->ds->dst->cpu_dp->netdev;
+}
+
 #endif
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index d534d8f4b9cf..443ebf3b5e5b 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -101,9 +101,12 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 	struct dsa_switch_tree *dst = ds->dst;
 	struct dsa_chip_data *cd = ds->cd;
 	bool valid_name_found = false;
+	struct net_device *master;
 	int index = ds->index;
 	int i, ret;
 
+	master = dst->cpu_dp->netdev;
+
 	/*
 	 * Validate supplied switch configuration.
 	 */
@@ -116,7 +119,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 
 		if (!strcmp(name, "cpu")) {
 			if (dst->cpu_dp) {
-				netdev_err(dst->master_netdev,
+				netdev_err(master,
 					   "multiple cpu ports?!\n");
 				return -EINVAL;
 			}
@@ -168,7 +171,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 		return ret;
 
 	if (ops->set_addr) {
-		ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
+		ret = ops->set_addr(ds, master->dev_addr);
 		if (ret < 0)
 			return ret;
 	}
@@ -195,14 +198,14 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 
 		ret = dsa_slave_create(ds, parent, i, cd->port_names[i]);
 		if (ret < 0)
-			netdev_err(dst->master_netdev, "[%d]: can't create dsa slave device for port %d(%s): %d\n",
+			netdev_err(master, "[%d]: can't create dsa slave device for port %d(%s): %d\n",
 				   index, i, cd->port_names[i], ret);
 	}
 
 	/* Perform configuration of the CPU and DSA ports */
 	ret = dsa_cpu_dsa_setups(ds, parent);
 	if (ret < 0)
-		netdev_err(dst->master_netdev, "[%d] : can't configure CPU and DSA ports\n",
+		netdev_err(master, "[%d] : can't configure CPU and DSA ports\n",
 			   index);
 
 	ret = dsa_cpu_port_ethtool_setup(ds->dst->cpu_dp);
@@ -217,6 +220,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
 		 struct device *parent, struct device *host_dev)
 {
 	struct dsa_chip_data *cd = dst->pd->chip + index;
+	struct net_device *master = dst->cpu_dp->netdev;
 	const struct dsa_switch_ops *ops;
 	struct dsa_switch *ds;
 	int ret;
@@ -228,11 +232,11 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
 	 */
 	ops = dsa_switch_probe(parent, host_dev, cd->sw_addr, &name, &priv);
 	if (!ops) {
-		netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n",
+		netdev_err(master, "[%d]: could not detect attached switch\n",
 			   index);
 		return ERR_PTR(-EINVAL);
 	}
-	netdev_info(dst->master_netdev, "[%d]: detected a %s switch\n",
+	netdev_info(master, "[%d]: detected a %s switch\n",
 		    index, name);
 
 
@@ -622,7 +626,7 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
 	unsigned configured = 0;
 
 	dst->pd = pd;
-	dst->master_netdev = dev;
+	dst->cpu_dp->netdev = dev;
 
 	for (i = 0; i < pd->nr_chips; i++) {
 		struct dsa_switch *ds;
@@ -718,7 +722,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
 {
 	int i;
 
-	dst->master_netdev->dsa_ptr = NULL;
+	dst->cpu_dp->netdev->dsa_ptr = NULL;
 
 	/* If we used a tagging format that doesn't have an ethertype
 	 * field, make sure that all packets from this point get sent
@@ -735,7 +739,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
 
 	dsa_cpu_port_ethtool_restore(dst->cpu_dp);
 
-	dev_put(dst->master_netdev);
+	dev_put(dst->cpu_dp->netdev);
 }
 
 static int dsa_remove(struct platform_device *pdev)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 1cfdb31a2f44..d52c9ceb0566 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -66,7 +66,7 @@ static int dsa_slave_get_iflink(const struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
 
-	return p->dp->ds->dst->master_netdev->ifindex;
+	return dsa_master_netdev(p)->ifindex;
 }
 
 static int dsa_slave_open(struct net_device *dev)
@@ -74,7 +74,7 @@ static int dsa_slave_open(struct net_device *dev)
 	struct dsa_slave_priv *p = netdev_priv(dev);
 	struct dsa_port *dp = p->dp;
 	struct dsa_switch *ds = dp->ds;
-	struct net_device *master = ds->dst->master_netdev;
+	struct net_device *master = dsa_master_netdev(p);
 	u8 stp_state = dp->bridge_dev ? BR_STATE_BLOCKING : BR_STATE_FORWARDING;
 	int err;
 
@@ -127,7 +127,7 @@ static int dsa_slave_open(struct net_device *dev)
 static int dsa_slave_close(struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = p->dp->ds->dst->master_netdev;
+	struct net_device *master = dsa_master_netdev(p);
 	struct dsa_switch *ds = p->dp->ds;
 
 	if (p->phy)
@@ -154,7 +154,7 @@ static int dsa_slave_close(struct net_device *dev)
 static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = p->dp->ds->dst->master_netdev;
+	struct net_device *master = dsa_master_netdev(p);
 
 	if (change & IFF_ALLMULTI)
 		dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
@@ -165,7 +165,7 @@ static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 static void dsa_slave_set_rx_mode(struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = p->dp->ds->dst->master_netdev;
+	struct net_device *master = dsa_master_netdev(p);
 
 	dev_mc_sync(master, dev);
 	dev_uc_sync(master, dev);
@@ -174,7 +174,7 @@ static void dsa_slave_set_rx_mode(struct net_device *dev)
 static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct net_device *master = p->dp->ds->dst->master_netdev;
+	struct net_device *master = dsa_master_netdev(p);
 	struct sockaddr *addr = a;
 	int err;
 
@@ -375,7 +375,7 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Queue the SKB for transmission on the parent interface, but
 	 * do not modify its EtherType
 	 */
-	nskb->dev = p->dp->ds->dst->master_netdev;
+	nskb->dev = dsa_master_netdev(p);
 	dev_queue_xmit(nskb);
 
 	return NETDEV_TX_OK;
@@ -684,7 +684,7 @@ static int dsa_slave_netpoll_setup(struct net_device *dev,
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
 	struct dsa_switch *ds = p->dp->ds;
-	struct net_device *master = ds->dst->master_netdev;
+	struct net_device *master = dsa_master_netdev(p);
 	struct netpoll *netpoll;
 	int err = 0;
 
@@ -1141,9 +1141,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 	struct dsa_slave_priv *p;
 	int ret;
 
-	master = ds->dst->master_netdev;
-	if (ds->master_netdev)
-		master = ds->master_netdev;
+	master = ds->dst->cpu_dp->netdev;
 
 	slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name,
 				 NET_NAME_UNKNOWN, ether_setup);
-- 
2.9.3

^ permalink raw reply related

* [PATCH net-next v2 3/5] net: dsa: Associate slave network device with CPU port
From: Florian Fainelli @ 2017-06-07  0:03 UTC (permalink / raw)
  To: netdev; +Cc: andrew, vivien.didelot, john, davem, Florian Fainelli
In-Reply-To: <20170607000317.14729-1-f.fainelli@gmail.com>

In preparation for supporting multiple CPU ports with DSA, have the
dsa_port structure know which CPU it is associated with. This will be
important in order to make sure the correct CPU is used for transmission
of the frames. If not for functional reasons, for performance (e.g: load
balancing) and forwarding decisions.

Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 include/net/dsa.h  | 1 +
 net/dsa/dsa_priv.h | 2 +-
 net/dsa/slave.c    | 5 ++++-
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 7e93869819f9..58969b9a090c 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -171,6 +171,7 @@ struct dsa_port {
 	struct dsa_switch	*ds;
 	unsigned int		index;
 	const char		*name;
+	struct dsa_port		*cpu_dp;
 	struct net_device	*netdev;
 	struct device_node	*dn;
 	unsigned int		ageing_time;
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 5c510f4ba0ce..7c2326f3b538 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -185,7 +185,7 @@ extern const struct dsa_device_ops trailer_netdev_ops;
 
 static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
 {
-	return p->dp->ds->dst->cpu_dp->netdev;
+	return p->dp->cpu_dp->netdev;
 }
 
 #endif
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index ea4ed0285922..de1ab41cfd38 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1139,9 +1139,11 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 	struct net_device *master;
 	struct net_device *slave_dev;
 	struct dsa_slave_priv *p;
+	struct dsa_port *cpu_dp;
 	int ret;
 
-	master = ds->dst->cpu_dp->netdev;
+	cpu_dp = ds->dst->cpu_dp;
+	master = cpu_dp->netdev;
 
 	slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name,
 				 NET_NAME_UNKNOWN, ether_setup);
@@ -1176,6 +1178,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 	p->old_duplex = -1;
 
 	ds->ports[port].netdev = slave_dev;
+	p->dp->cpu_dp = cpu_dp;
 	ret = register_netdev(slave_dev);
 	if (ret) {
 		netdev_err(master, "error %d registering interface %s\n",
-- 
2.9.3

^ permalink raw reply related

* [PATCH net-next v2 4/5] net: dsa: Introduce dsa_dst_get_cpu_dp()
From: Florian Fainelli @ 2017-06-07  0:03 UTC (permalink / raw)
  To: netdev; +Cc: andrew, vivien.didelot, john, davem, Florian Fainelli
In-Reply-To: <20170607000317.14729-1-f.fainelli@gmail.com>

Introduce a helper function which will return a reference to the CPU
port used in a dsa_switch_tree. Right now this is a singleton, but this
will change once we introduce multi-CPU port support, so ease the
transition by converting the affected code paths.

Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 net/dsa/dsa_priv.h    |  5 +++++
 net/dsa/slave.c       | 31 ++++++++++++++++---------------
 net/dsa/tag_brcm.c    |  5 ++---
 net/dsa/tag_ksz.c     |  5 ++---
 net/dsa/tag_qca.c     |  3 ++-
 net/dsa/tag_trailer.c |  5 ++---
 6 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 7c2326f3b538..49b4b047aed0 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -188,4 +188,9 @@ static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
 	return p->dp->cpu_dp->netdev;
 }
 
+static inline struct dsa_port *dsa_dst_get_cpu_dp(struct dsa_switch_tree *dst)
+{
+	return dst->cpu_dp;
+}
+
 #endif
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index de1ab41cfd38..a73c1de398b5 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -519,14 +519,14 @@ static void dsa_cpu_port_get_ethtool_stats(struct net_device *dev,
 					   uint64_t *data)
 {
 	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_switch *ds = dst->cpu_dp->ds;
-	s8 cpu_port = dst->cpu_dp->index;
+	struct dsa_port *cpu_dp = dsa_dst_get_cpu_dp(dst);
+	struct dsa_switch *ds = cpu_dp->ds;
+	s8 cpu_port = cpu_dp->index;
 	int count = 0;
 
-	if (dst->cpu_dp->ethtool_ops.get_sset_count) {
-		count = dst->cpu_dp->ethtool_ops.get_sset_count(dev,
-							       ETH_SS_STATS);
-		dst->cpu_dp->ethtool_ops.get_ethtool_stats(dev, stats, data);
+	if (cpu_dp->ethtool_ops.get_sset_count) {
+		count = cpu_dp->ethtool_ops.get_sset_count(dev, ETH_SS_STATS);
+		cpu_dp->ethtool_ops.get_ethtool_stats(dev, stats, data);
 	}
 
 	if (ds->ops->get_ethtool_stats)
@@ -536,11 +536,12 @@ static void dsa_cpu_port_get_ethtool_stats(struct net_device *dev,
 static int dsa_cpu_port_get_sset_count(struct net_device *dev, int sset)
 {
 	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_switch *ds = dst->cpu_dp->ds;
+	struct dsa_port *cpu_dp = dsa_dst_get_cpu_dp(dst);
+	struct dsa_switch *ds = cpu_dp->ds;
 	int count = 0;
 
-	if (dst->cpu_dp->ethtool_ops.get_sset_count)
-		count += dst->cpu_dp->ethtool_ops.get_sset_count(dev, sset);
+	if (cpu_dp->ethtool_ops.get_sset_count)
+		count += cpu_dp->ethtool_ops.get_sset_count(dev, sset);
 
 	if (sset == ETH_SS_STATS && ds->ops->get_sset_count)
 		count += ds->ops->get_sset_count(ds);
@@ -552,8 +553,9 @@ static void dsa_cpu_port_get_strings(struct net_device *dev,
 				     uint32_t stringset, uint8_t *data)
 {
 	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_switch *ds = dst->cpu_dp->ds;
-	s8 cpu_port = dst->cpu_dp->index;
+	struct dsa_port *cpu_dp = dsa_dst_get_cpu_dp(dst);
+	struct dsa_switch *ds = cpu_dp->ds;
+	s8 cpu_port = cpu_dp->index;
 	int len = ETH_GSTRING_LEN;
 	int mcount = 0, count;
 	unsigned int i;
@@ -564,10 +566,9 @@ static void dsa_cpu_port_get_strings(struct net_device *dev,
 	/* We do not want to be NULL-terminated, since this is a prefix */
 	pfx[sizeof(pfx) - 1] = '_';
 
-	if (dst->cpu_dp->ethtool_ops.get_sset_count) {
-		mcount = dst->cpu_dp->ethtool_ops.get_sset_count(dev,
-								ETH_SS_STATS);
-		dst->cpu_dp->ethtool_ops.get_strings(dev, stringset, data);
+	if (cpu_dp->ethtool_ops.get_sset_count) {
+		mcount = cpu_dp->ethtool_ops.get_sset_count(dev, ETH_SS_STATS);
+		cpu_dp->ethtool_ops.get_strings(dev, stringset, data);
 	}
 
 	if (stringset == ETH_SS_STATS && ds->ops->get_strings) {
diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
index c03860907f28..d7ef2b35e61e 100644
--- a/net/dsa/tag_brcm.c
+++ b/net/dsa/tag_brcm.c
@@ -93,12 +93,11 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 				    struct net_device *orig_dev)
 {
 	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_switch *ds;
+	struct dsa_port *cpu_dp = dsa_dst_get_cpu_dp(dst);
+	struct dsa_switch *ds = cpu_dp->ds;
 	int source_port;
 	u8 *brcm_tag;
 
-	ds = dst->cpu_dp->ds;
-
 	if (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN)))
 		return NULL;
 
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index b94a334a1d02..c41a24e83e83 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -75,12 +75,11 @@ static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
 			       struct net_device *orig_dev)
 {
 	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_switch *ds;
+	struct dsa_port *cpu_dp = dsa_dst_get_cpu_dp(dst);
+	struct dsa_switch *ds = cpu_dp->ds;
 	u8 *tag;
 	int source_port;
 
-	ds = dst->cpu_dp->ds;
-
 	tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
 
 	source_port = tag[0] & 7;
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
index 4f43cf0b4eff..73244ae388df 100644
--- a/net/dsa/tag_qca.c
+++ b/net/dsa/tag_qca.c
@@ -67,6 +67,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 				   struct net_device *orig_dev)
 {
 	struct dsa_switch_tree *dst = dev->dsa_ptr;
+	struct dsa_port *cpu_dp = dsa_dst_get_cpu_dp(dst);
 	struct dsa_switch *ds;
 	u8 ver;
 	int port;
@@ -95,7 +96,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 	/* This protocol doesn't support cascading multiple switches so it's
 	 * safe to assume the switch is first in the tree
 	 */
-	ds = dst->cpu_dp->ds;
+	ds = cpu_dp->ds;
 	if (!ds)
 		return NULL;
 
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index b4f6db094409..68f664cb7517 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -61,12 +61,11 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
 				   struct net_device *orig_dev)
 {
 	struct dsa_switch_tree *dst = dev->dsa_ptr;
-	struct dsa_switch *ds;
+	struct dsa_port *cpu_dp = dsa_dst_get_cpu_dp(dst);
+	struct dsa_switch *ds = cpu_dp->ds;
 	u8 *trailer;
 	int source_port;
 
-	ds = dst->cpu_dp->ds;
-
 	if (skb_linearize(skb))
 		return NULL;
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH net-next v2 2/5] net: dsa: Relocate master ethtool operations
From: Florian Fainelli @ 2017-06-07  0:03 UTC (permalink / raw)
  To: netdev; +Cc: andrew, vivien.didelot, john, davem, Florian Fainelli
In-Reply-To: <20170607000317.14729-1-f.fainelli@gmail.com>

Relocate master_ethtool_ops and master_orig_ethtool_ops into struct
dsa_port in order to be both consistent, and make things self contained
within the dsa_port structure.

This is a preliminary change to supporting multiple CPU port interfaces.

Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 include/net/dsa.h | 17 +++++------------
 net/dsa/dsa.c     | 16 ++++++----------
 net/dsa/slave.c   | 16 ++++++++--------
 3 files changed, 19 insertions(+), 30 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index b2fb53f5e28e..7e93869819f9 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -122,12 +122,6 @@ struct dsa_switch_tree {
 	 */
 	struct dsa_platform_data	*pd;
 
-	/*
-	 * Reference to network device to use, and which tagging
-	 * protocol to use.
-	 */
-	struct net_device	*master_netdev;
-
 	/* Copy of tag_ops->rcv for faster access in hot path */
 	struct sk_buff *	(*rcv)(struct sk_buff *skb,
 				       struct net_device *dev,
@@ -135,12 +129,6 @@ struct dsa_switch_tree {
 				       struct net_device *orig_dev);
 
 	/*
-	 * Original copy of the master netdev ethtool_ops
-	 */
-	struct ethtool_ops	master_ethtool_ops;
-	const struct ethtool_ops *master_orig_ethtool_ops;
-
-	/*
 	 * The switch port to which the CPU is attached.
 	 */
 	struct dsa_port		*cpu_dp;
@@ -189,6 +177,11 @@ struct dsa_port {
 	u8			stp_state;
 	struct net_device	*bridge_dev;
 	struct devlink_port	devlink_port;
+	/*
+	 * Original copy of the master netdev ethtool_ops
+	 */
+	struct ethtool_ops	ethtool_ops;
+	const struct ethtool_ops *orig_ethtool_ops;
 };
 
 struct dsa_switch {
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index eaab1affeeeb..2665a66e833d 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -118,15 +118,16 @@ int dsa_cpu_port_ethtool_setup(struct dsa_port *cpu_dp)
 	struct net_device *master;
 	struct ethtool_ops *cpu_ops;
 
-	master = ds->dst->cpu_dp->netdev;
+	master = cpu_dp->netdev;
+
 	cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
 	if (!cpu_ops)
 		return -ENOMEM;
 
-	memcpy(&ds->dst->master_ethtool_ops, master->ethtool_ops,
+	memcpy(&cpu_dp->ethtool_ops, master->ethtool_ops,
 	       sizeof(struct ethtool_ops));
-	ds->dst->master_orig_ethtool_ops = master->ethtool_ops;
-	memcpy(cpu_ops, &ds->dst->master_ethtool_ops,
+	cpu_dp->orig_ethtool_ops = master->ethtool_ops;
+	memcpy(cpu_ops, &cpu_dp->ethtool_ops,
 	       sizeof(struct ethtool_ops));
 	dsa_cpu_port_ethtool_init(cpu_ops);
 	master->ethtool_ops = cpu_ops;
@@ -136,12 +137,7 @@ int dsa_cpu_port_ethtool_setup(struct dsa_port *cpu_dp)
 
 void dsa_cpu_port_ethtool_restore(struct dsa_port *cpu_dp)
 {
-	struct dsa_switch *ds = cpu_dp->ds;
-	struct net_device *master;
-
-	master = ds->dst->cpu_dp->netdev;
-
-	master->ethtool_ops = ds->dst->master_orig_ethtool_ops;
+	cpu_dp->netdev->ethtool_ops = cpu_dp->orig_ethtool_ops;
 }
 
 void dsa_cpu_dsa_destroy(struct dsa_port *port)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index d52c9ceb0566..ea4ed0285922 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -523,10 +523,10 @@ static void dsa_cpu_port_get_ethtool_stats(struct net_device *dev,
 	s8 cpu_port = dst->cpu_dp->index;
 	int count = 0;
 
-	if (dst->master_ethtool_ops.get_sset_count) {
-		count = dst->master_ethtool_ops.get_sset_count(dev,
+	if (dst->cpu_dp->ethtool_ops.get_sset_count) {
+		count = dst->cpu_dp->ethtool_ops.get_sset_count(dev,
 							       ETH_SS_STATS);
-		dst->master_ethtool_ops.get_ethtool_stats(dev, stats, data);
+		dst->cpu_dp->ethtool_ops.get_ethtool_stats(dev, stats, data);
 	}
 
 	if (ds->ops->get_ethtool_stats)
@@ -539,8 +539,8 @@ static int dsa_cpu_port_get_sset_count(struct net_device *dev, int sset)
 	struct dsa_switch *ds = dst->cpu_dp->ds;
 	int count = 0;
 
-	if (dst->master_ethtool_ops.get_sset_count)
-		count += dst->master_ethtool_ops.get_sset_count(dev, sset);
+	if (dst->cpu_dp->ethtool_ops.get_sset_count)
+		count += dst->cpu_dp->ethtool_ops.get_sset_count(dev, sset);
 
 	if (sset == ETH_SS_STATS && ds->ops->get_sset_count)
 		count += ds->ops->get_sset_count(ds);
@@ -564,10 +564,10 @@ static void dsa_cpu_port_get_strings(struct net_device *dev,
 	/* We do not want to be NULL-terminated, since this is a prefix */
 	pfx[sizeof(pfx) - 1] = '_';
 
-	if (dst->master_ethtool_ops.get_sset_count) {
-		mcount = dst->master_ethtool_ops.get_sset_count(dev,
+	if (dst->cpu_dp->ethtool_ops.get_sset_count) {
+		mcount = dst->cpu_dp->ethtool_ops.get_sset_count(dev,
 								ETH_SS_STATS);
-		dst->master_ethtool_ops.get_strings(dev, stringset, data);
+		dst->cpu_dp->ethtool_ops.get_strings(dev, stringset, data);
 	}
 
 	if (stringset == ETH_SS_STATS && ds->ops->get_strings) {
-- 
2.9.3

^ permalink raw reply related

* [PATCH net-next v2 5/5] net: dsa: Stop accessing ds->dst->cpu_dp in drivers
From: Florian Fainelli @ 2017-06-07  0:03 UTC (permalink / raw)
  To: netdev; +Cc: andrew, vivien.didelot, john, davem, Florian Fainelli
In-Reply-To: <20170607000317.14729-1-f.fainelli@gmail.com>

Out of the few drivers that do access ds->dst->cpu_dp, there is only a
handful for which we cannot substitute that for either an existing and
equivalent piece of information (b53, bcm_sf2, qca8k), and there is only
one for which we need to introduce a helper: mt7530. We do introduce
dsa_ds_get_cpu_dp() which reads the CPU port from ds->cpu_port_mask.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/b53/b53_common.c |  4 ++--
 drivers/net/dsa/bcm_sf2.c        | 10 ++++++----
 drivers/net/dsa/mt7530.c         |  4 +++-
 drivers/net/dsa/mv88e6060.c      |  2 +-
 drivers/net/dsa/qca8k.c          |  2 +-
 include/net/dsa.h                |  6 ++++++
 net/dsa/dsa2.c                   | 11 +++++++++++
 net/dsa/legacy.c                 |  1 +
 net/dsa/slave.c                  |  1 -
 9 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index e68d368e20ac..faec6fcacd31 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1341,7 +1341,7 @@ EXPORT_SYMBOL(b53_fdb_dump);
 int b53_br_join(struct dsa_switch *ds, int port, struct net_device *br)
 {
 	struct b53_device *dev = ds->priv;
-	s8 cpu_port = ds->dst->cpu_dp->index;
+	s8 cpu_port = dev->cpu_port;
 	u16 pvlan, reg;
 	unsigned int i;
 
@@ -1387,7 +1387,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br)
 {
 	struct b53_device *dev = ds->priv;
 	struct b53_vlan *vl = &dev->vlans[0];
-	s8 cpu_port = ds->dst->cpu_dp->index;
+	s8 cpu_port = dev->cpu_port;
 	unsigned int i;
 	u16 pvlan, reg, pvid;
 
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 76e98e8ed315..9744100d0276 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -227,7 +227,7 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
 			      struct phy_device *phy)
 {
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
-	s8 cpu_port = ds->dst->cpu_dp->index;
+	s8 cpu_port = priv->dev->cpu_port;
 	unsigned int i;
 	u32 reg;
 
@@ -806,8 +806,9 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
 static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
 			       struct ethtool_wolinfo *wol)
 {
-	struct net_device *p = ds->dst[ds->index].cpu_dp->netdev;
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+	struct dsa_port *cpu_dp = ds->ports[port].cpu_dp;
+	struct net_device *p = cpu_dp->netdev;
 	struct ethtool_wolinfo pwol;
 
 	/* Get the parent device WoL settings */
@@ -829,9 +830,10 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
 static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
 			      struct ethtool_wolinfo *wol)
 {
-	struct net_device *p = ds->dst[ds->index].cpu_dp->netdev;
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
-	s8 cpu_port = ds->dst->cpu_dp->index;
+	struct dsa_port *cpu_dp = ds->ports[port].cpu_dp;
+	struct net_device *p = cpu_dp->netdev;
+	s8 cpu_port = cpu_dp->index;
 	struct ethtool_wolinfo pwol;
 
 	p->ethtool_ops->get_wol(p, &pwol);
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 1e46418a3b74..9b1b76c7b927 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -907,6 +907,7 @@ static int
 mt7530_setup(struct dsa_switch *ds)
 {
 	struct mt7530_priv *priv = ds->priv;
+	struct dsa_port *cpu_dp;
 	int ret, i;
 	u32 id, val;
 	struct device_node *dn;
@@ -916,7 +917,8 @@ mt7530_setup(struct dsa_switch *ds)
 	 * controller also is the container for two GMACs nodes representing
 	 * as two netdev instances.
 	 */
-	dn = ds->dst->cpu_dp->netdev->dev.of_node->parent;
+	cpu_dp = dsa_ds_get_cpu_dp(ds);
+	dn = cpu_dp->netdev->dev.of_node->parent;
 	priv->ethernet = syscon_node_to_regmap(dn);
 	if (IS_ERR(priv->ethernet))
 		return PTR_ERR(priv->ethernet);
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index dce7fa57eb55..621cdc46ad81 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -176,7 +176,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
 		  ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
 		   (dsa_is_cpu_port(ds, p) ?
 			ds->enabled_port_mask :
-			BIT(ds->dst->cpu_dp->index)));
+			BIT(ds->ports[p].cpu_dp->index)));
 
 	/* Port Association Vector: when learning source addresses
 	 * of packets, add the address to the address database using
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index b3bee7eab45f..68b45298f6d1 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -506,7 +506,7 @@ qca8k_setup(struct dsa_switch *ds)
 		pr_warn("regmap initialization failed");
 
 	/* Initialize CPU port pad mode (xMII type, delays...) */
-	phy_mode = of_get_phy_mode(ds->dst->cpu_dp->dn);
+	phy_mode = of_get_phy_mode(ds->ports[QCA8K_CPU_PORT].dn);
 	if (phy_mode < 0) {
 		pr_err("Can't find phy-mode for master device\n");
 		return phy_mode;
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 58969b9a090c..264cb3f93764 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -11,6 +11,7 @@
 #ifndef __LINUX_NET_DSA_H
 #define __LINUX_NET_DSA_H
 
+#include <linux/bitops.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/list.h>
@@ -261,6 +262,11 @@ static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
 	return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;
 }
 
+static inline struct dsa_port *dsa_ds_get_cpu_dp(struct dsa_switch *ds)
+{
+	return &ds->ports[fls(ds->cpu_port_mask) - 1];
+}
+
 static inline u8 dsa_upstream_port(struct dsa_switch *ds)
 {
 	struct dsa_switch_tree *dst = ds->dst;
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 2674bdf03fef..3878dcd081bb 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -488,6 +488,8 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
 	enum dsa_tag_protocol tag_protocol;
 	struct net_device *ethernet_dev;
 	struct device_node *ethernet;
+	struct dsa_port *p;
+	unsigned int i;
 
 	if (port->dn) {
 		ethernet = of_parse_phandle(port->dn, "ethernet", 0);
@@ -505,6 +507,15 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
 	if (!dst->cpu_dp) {
 		dst->cpu_dp = port;
 		dst->cpu_dp->netdev = ethernet_dev;
+
+		for (i = 0; i < ds->num_ports; i++) {
+			p = &ds->ports[i];
+			if (!dsa_port_is_valid(p) ||
+			    i == index)
+				continue;
+
+			p->cpu_dp = port;
+		}
 	}
 
 	tag_protocol = ds->ops->get_tag_protocol(ds);
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index 443ebf3b5e5b..217034cb25cd 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -129,6 +129,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 			ds->dsa_port_mask |= 1 << i;
 		} else {
 			ds->enabled_port_mask |= 1 << i;
+			ds->ports[i].cpu_dp = dst->cpu_dp;
 		}
 		valid_name_found = true;
 	}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index a73c1de398b5..46fd4a985e0a 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1179,7 +1179,6 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 	p->old_duplex = -1;
 
 	ds->ports[port].netdev = slave_dev;
-	p->dp->cpu_dp = cpu_dp;
 	ret = register_netdev(slave_dev);
 	if (ret) {
 		netdev_err(master, "error %d registering interface %s\n",
-- 
2.9.3

^ permalink raw reply related

* Re: [PATCH net-next v2 0/5] net: dsa: Multi-CPU ground work (v2)
From: Florian Fainelli @ 2017-06-07  0:05 UTC (permalink / raw)
  To: netdev; +Cc: andrew, vivien.didelot, john, davem
In-Reply-To: <20170607000317.14729-1-f.fainelli@gmail.com>

On 06/06/2017 05:03 PM, Florian Fainelli wrote:
> Hi all,
> 
> This patch series prepares the ground for adding mutliple CPU port support to
> DSA, and starts by removing redundant pieces of information such as
> master_netdev which is cpu_dp->ethernet. Finally drivers are moved away from
> directly accessing ds->dst->cpu_dp and use appropriate helper functions.
> 
> Note that if you have Device Tree blobs/platform configurations that are
> currently listing multiple CPU ports, the proposed behavior in
> dsa_ds_get_cpu_dp() will be to return the last bit set in ds->cpu_port_mask.
> 
> Future plans include:
> - making dst->cpu_dp a flexible data structure (array, list, you name it)
> - having the ability for drivers to return a default/preferred CPU port (if
>   necessary)
> 
> Changes in v2:
> 
> - added Reviewed-by tags
> - assign port->cpu_dp earlier before ops->setup() has run

There are some hunks in patch 5 that actually belong in patch 3, I will
post a v3 after getting some more feedback.

> 
> Florian Fainelli (5):
>   net: dsa: Remove master_netdev and use dst->cpu_dp->netdev
>   net: dsa: Relocate master ethtool operations
>   net: dsa: Associate slave network device with CPU port
>   net: dsa: Introduce dsa_dst_get_cpu_dp()
>   net: dsa: Stop accessing ds->dst->cpu_dp in drivers
> 
>  drivers/net/dsa/b53/b53_common.c |  4 +--
>  drivers/net/dsa/bcm_sf2.c        | 10 +++++---
>  drivers/net/dsa/mt7530.c         |  6 +++--
>  drivers/net/dsa/mv88e6060.c      |  2 +-
>  drivers/net/dsa/qca8k.c          |  2 +-
>  include/net/dsa.h                | 29 +++++++++-------------
>  net/dsa/dsa.c                    | 19 ++++----------
>  net/dsa/dsa2.c                   | 27 ++++++++++++--------
>  net/dsa/dsa_priv.h               | 10 ++++++++
>  net/dsa/legacy.c                 | 23 ++++++++++-------
>  net/dsa/slave.c                  | 53 ++++++++++++++++++++--------------------
>  net/dsa/tag_brcm.c               |  5 ++--
>  net/dsa/tag_ksz.c                |  5 ++--
>  net/dsa/tag_qca.c                |  3 ++-
>  net/dsa/tag_trailer.c            |  5 ++--
>  15 files changed, 107 insertions(+), 96 deletions(-)
> 


-- 
Florian

^ permalink raw reply

* Re: ath9k_htc - Division by zero in kernel (as well as firmware panic)
From: Tobias Diedrich @ 2017-06-07  0:12 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Nathan Royce, QCA ath9k Development, Kalle Valo,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ath9k_htc_fw
In-Reply-To: <71818afe-9075-5582-bb6c-650dfa8a5363-YEK0n+YFykbzxQdaRaTXBw@public.gmane.org>

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

Oleksij Rempel wrote:
> Yes, this is "normal" problem. The firmware has no error handler for PCI
> bus related exceptions. So if we filed to read PCI bus first time, we
> have choice to Ooops and stall or Ooops and reboot ASAP. So we reboot
> and provide an kernel "firmware panic!" message.
> Every one who can or will to fix this, is welcome.
> 
> > *****
> > Jun 02 14:55:30 computer kernel: usb 1-1.1: ath: firmware panic!
> > exccause: 0x0000000d; pc: 0x0090ae81; badvaddr: 0x10ff4038.
[...]

>memdmp 50ae78 50ae88

50ae78: 6c10 0412 6aa2 0c02 0088 20c0 2008 1940  l...j..........@

[...copy to bin...]
$ bin/objdump -b binary -m xtensa  -D /tmp/memdump.bin 
[..]
   0:   6c1004          entry   a1, 32
   3:   126aa2          l32r    a2, 0xfffdaa8c
   6:   0c0200          memw
   9:   8820            l32i.n  a8, a2, 0      <----------Exception cause PC still points at load
   b:   c020            movi.n  a2, 0
   d:   081940          extui   a9, a8, 1, 1

Judging from that it should be fairly simple to at least implement
some sort of retry, possible after triggering a PCIe link retrain?
There are some related PCIe root complex registers that may point to
what exactly failed if they were dumped.

The root complex registers live at 0x00040000 and I think match the
registers described for the root complex in the AR9344 datasheet.

PCIE_INT_MASK would map to 0x40050 and has a bit for SYS_ERR:
"A system error. The RC Core asserts CFG_SYS_ERR_RC if any device in
the hierarchy reports any of the following errors and the associated
enable bit is set in the Root Control register: ERR_COR, ERR_FATAL,
ERR_NONFATAL."

AFAICS link retrain can be done by setting bit3 (INIT_RST,
"Application request to initiate a training reset") in
PCIE_APP (0x40000).

See sboot/magpie_1_1/sboot/cmnos/eeprom/src/cmnos_eeprom.c (which
flips some bits in the RC to enable the PCIe bus for reading the
EEPROM).

The root complex pci configuration space is at 0x20000 which could
have further error details:
>memdmp 20000 20200

020000: a02a 168c 0010 0006 0000 0001 0001 0000  .*..............
020010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020030: 0000 0000 0000 0040 0000 0000 0000 01ff  .......@........
020040: 5bc3 5001 0000 0000 0000 0000 0000 0000  [.P.............
020050: 0080 7005 0000 0000 0000 0000 0000 0000  ..p.............
020060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020070: 0042 0010 0000 8701 0000 2010 0013 4411  .B............D.
020080: 3011 0000 0000 0000 00c0 03c0 0000 0000  0...............
020090: 0000 0000 0000 0010 0000 0000 0000 0000  ................
0200a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0200b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0200c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0200d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0200e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0200f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020100: 1401 0001 0000 0000 0000 0000 0006 2030  ...............0
020110: 0000 0000 0000 2000 0000 00a0 0000 0000  ................
020120: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020140: 0001 0002 0000 0000 0000 0000 0000 0000  ................
020150: 0000 0000 8000 00ff 0000 0000 0000 0000  ................
020160: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020170: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020180: 0000 0000 0000 0000 0000 0000 0000 0000  ................
020190: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0201a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0201b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0201c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0201d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0201e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0201f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

Transformed into something suitable for feeding into lspci -F:

00:00.0 Description filled in by lspci
00: 8c 16 2a a0 06 00 10 00 01 00 00 00 00 00 01 00
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30: 00 00 00 00 40 00 00 00 00 00 00 00 ff 01 00 00
40: 01 50 c3 5b 00 00 00 00 00 00 00 00 00 00 00 00
50: 05 70 80 00 00 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 10 00 42 00 01 87 00 00 10 20 00 00 11 44 13 00
80: 00 00 11 30 00 00 00 00 c0 03 c0 00 00 00 00 00
90: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

$ lspci -F /tmp/hexdump -vvv
00:00.0 Non-VGA unclassified device: Qualcomm Atheros Device a02a (rev 01)
        !!! Invalid class 0000 for header type 01
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 255
        Bus: primary=00, secondary=00, subordinate=00, sec-latency=0
        I/O behind bridge: 00000000-00000fff
        Memory behind bridge: 00000000-000fffff
        Prefetchable memory behind bridge: 00000000-000fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold-)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
                Address: 0000000000000000  Data: 0000
        Capabilities: [70] Express (v2) Root Port (Slot-), MSI 00
                DevCap: MaxPayload 256 bytes, PhantFunc 0
                        ExtTag- RBE+
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s, Exit Latency L0s <1us, L1 <64us
                        ClockPM- Surprise- LLActRep+ BwNot- ASPMOptComp-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive+ BWMgmt- ABWMgmt-
                RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
                RootCap: CRSVisible-
                RootSta: PME ReqID 0000, PMEStatus- PMEPending-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis+, LTR-, OBFF Not Supported ARIFwd-
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd-
                LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-


> > Jun 02 14:55:30 computer kernel: usb 1-1.1: ath9k_htc: Transferred FW:
> > ath9k_htc/htc_7010-1.4.0.fw, size: 72812

$ ls -l /lib/firmware/ath9k_htc/htc_7010-1.4.0.fw
-rw-r--r-- 1 root root 72812 Dec 14 04:59 /lib/firmware/ath9k_htc/htc_7010-1.4.0.fw
$ sha1sum /lib/firmware/ath9k_htc/htc_7010-1.4.0.fw
959cb6550930de2882e12b9a549c3cf0c9bf51ac /lib/firmware/ath9k_htc/htc_7010-1.4.0.fw



-- 
Tobias						PGP: http://8ef7ddba.uguu.de

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

^ permalink raw reply

* Re: Repeatable inet6_dump_fib crash in stock 4.12.0-rc4+
From: Eric Dumazet @ 2017-06-07  0:27 UTC (permalink / raw)
  To: David Ahern; +Cc: Ben Greear, netdev
In-Reply-To: <a5733c67-e3a3-9cc0-0862-40ef6fc03de3@gmail.com>

On Tue, 2017-06-06 at 18:00 -0600, David Ahern wrote:
> On 6/6/17 3:06 PM, Ben Greear wrote:
> > This bug has been around forever, and we recently got an intern and
> > stuck him with
> > trying to reproduce it on the latest kernel.  It is still here.  I'm not
> > super excited
> > about trying to fix this, but we can easily test patches if someone has a
> > patch to try.
> 
> Can you try this (whitespace damaged on paste, but it is moving the lock
> ahead of the fn_sernum check):
> 
> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> index deea901746c8..7a44c49055c0 100644
> --- a/net/ipv6/ip6_fib.c
> +++ b/net/ipv6/ip6_fib.c
> @@ -378,6 +378,7 @@ static int fib6_dump_table(struct fib6_table *table,
> struct sk_buff *skb,
>                         cb->args[5] = w->root->fn_sernum;
>                 }
>         } else {
> +               read_lock_bh(&table->tb6_lock);
>                 if (cb->args[5] != w->root->fn_sernum) {
>                         /* Begin at the root if the tree changed */
>                         cb->args[5] = w->root->fn_sernum;
> @@ -387,7 +388,6 @@ static int fib6_dump_table(struct fib6_table *table,
> struct sk_buff *skb,
>                 } else
>                         w->skip = 0;
> 
> -               read_lock_bh(&table->tb6_lock);
>                 res = fib6_walk_continue(w);
>                 read_unlock_bh(&table->tb6_lock);
>                 if (res <= 0) {


Good catch, but it looks like similar fix is needed a few lines before.

diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index deea901746c8570c5e801e40592c91e3b62812e0..b214443dc8346cef3690df7f27cc48a864028865 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -372,12 +372,13 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
 
 		read_lock_bh(&table->tb6_lock);
 		res = fib6_walk(net, w);
-		read_unlock_bh(&table->tb6_lock);
 		if (res > 0) {
 			cb->args[4] = 1;
 			cb->args[5] = w->root->fn_sernum;
 		}
+		read_unlock_bh(&table->tb6_lock);
 	} else {
+		read_lock_bh(&table->tb6_lock);
 		if (cb->args[5] != w->root->fn_sernum) {
 			/* Begin at the root if the tree changed */
 			cb->args[5] = w->root->fn_sernum;
@@ -387,7 +388,6 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
 		} else
 			w->skip = 0;
 
-		read_lock_bh(&table->tb6_lock);
 		res = fib6_walk_continue(w);
 		read_unlock_bh(&table->tb6_lock);
 		if (res <= 0) {

^ permalink raw reply related

* Re: Repeatable inet6_dump_fib crash in stock 4.12.0-rc4+
From: David Ahern @ 2017-06-07  0:34 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Ben Greear, netdev
In-Reply-To: <1496795269.736.21.camel@edumazet-glaptop3.roam.corp.google.com>

On 6/6/17 6:27 PM, Eric Dumazet wrote:
> Good catch, but it looks like similar fix is needed a few lines before.
> 
> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> index deea901746c8570c5e801e40592c91e3b62812e0..b214443dc8346cef3690df7f27cc48a864028865 100644
> --- a/net/ipv6/ip6_fib.c
> +++ b/net/ipv6/ip6_fib.c
> @@ -372,12 +372,13 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
>  
>  		read_lock_bh(&table->tb6_lock);
>  		res = fib6_walk(net, w);
> -		read_unlock_bh(&table->tb6_lock);
>  		if (res > 0) {
>  			cb->args[4] = 1;
>  			cb->args[5] = w->root->fn_sernum;
>  		}
> +		read_unlock_bh(&table->tb6_lock);

indeed. tunnel vision on Ben's problem

^ permalink raw reply

* Re: Repeatable inet6_dump_fib crash in stock 4.12.0-rc4+
From: Ben Greear @ 2017-06-07  0:48 UTC (permalink / raw)
  To: Eric Dumazet, David Ahern; +Cc: netdev
In-Reply-To: <1496795269.736.21.camel@edumazet-glaptop3.roam.corp.google.com>

On 06/06/2017 05:27 PM, Eric Dumazet wrote:
> On Tue, 2017-06-06 at 18:00 -0600, David Ahern wrote:
>> On 6/6/17 3:06 PM, Ben Greear wrote:
>>> This bug has been around forever, and we recently got an intern and
>>> stuck him with
>>> trying to reproduce it on the latest kernel.  It is still here.  I'm not
>>> super excited
>>> about trying to fix this, but we can easily test patches if someone has a
>>> patch to try.
>>
>> Can you try this (whitespace damaged on paste, but it is moving the lock
>> ahead of the fn_sernum check):
>>
>> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
>> index deea901746c8..7a44c49055c0 100644
>> --- a/net/ipv6/ip6_fib.c
>> +++ b/net/ipv6/ip6_fib.c
>> @@ -378,6 +378,7 @@ static int fib6_dump_table(struct fib6_table *table,
>> struct sk_buff *skb,
>>                         cb->args[5] = w->root->fn_sernum;
>>                 }
>>         } else {
>> +               read_lock_bh(&table->tb6_lock);
>>                 if (cb->args[5] != w->root->fn_sernum) {
>>                         /* Begin at the root if the tree changed */
>>                         cb->args[5] = w->root->fn_sernum;
>> @@ -387,7 +388,6 @@ static int fib6_dump_table(struct fib6_table *table,
>> struct sk_buff *skb,
>>                 } else
>>                         w->skip = 0;
>>
>> -               read_lock_bh(&table->tb6_lock);
>>                 res = fib6_walk_continue(w);
>>                 read_unlock_bh(&table->tb6_lock);
>>                 if (res <= 0) {
>
>
> Good catch, but it looks like similar fix is needed a few lines before.

We will test this tomorrow.

Thanks,
Ben


>
> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> index deea901746c8570c5e801e40592c91e3b62812e0..b214443dc8346cef3690df7f27cc48a864028865 100644
> --- a/net/ipv6/ip6_fib.c
> +++ b/net/ipv6/ip6_fib.c
> @@ -372,12 +372,13 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
>
>  		read_lock_bh(&table->tb6_lock);
>  		res = fib6_walk(net, w);
> -		read_unlock_bh(&table->tb6_lock);
>  		if (res > 0) {
>  			cb->args[4] = 1;
>  			cb->args[5] = w->root->fn_sernum;
>  		}
> +		read_unlock_bh(&table->tb6_lock);
>  	} else {
> +		read_lock_bh(&table->tb6_lock);
>  		if (cb->args[5] != w->root->fn_sernum) {
>  			/* Begin at the root if the tree changed */
>  			cb->args[5] = w->root->fn_sernum;
> @@ -387,7 +388,6 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
>  		} else
>  			w->skip = 0;
>
> -		read_lock_bh(&table->tb6_lock);
>  		res = fib6_walk_continue(w);
>  		read_unlock_bh(&table->tb6_lock);
>  		if (res <= 0) {
>
>


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com

^ permalink raw reply

* Re: [for-next 4/6] net/mlx5: FPGA, Add basic support for Innova
From: Andrew Lunn @ 2017-06-07  0:48 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: David Miller, jgunthorpe, ilant, saeedm, dledford, netdev,
	linux-rdma, jsorensen, andy.shevchenko, linux-fpga, yi1.li,
	borisp
In-Reply-To: <20170606224451.76732gjmf6vaetxx@ast-mbp>

On Tue, Jun 06, 2017 at 03:44:53PM -0700, Alexei Starovoitov wrote:
> On Tue, Jun 06, 2017 at 03:01:51PM -0400, David Miller wrote:
> > From: Alexei Starovoitov <alexei.starovoitov@gmail.com>
> > Date: Tue, 6 Jun 2017 11:55:33 -0700
> > 
> > > If in the future mlx will make it into the nic in a way that
> > > encryption shares all memory management logic and there is no fpga
> > > at all then it indeed will be similar to tc offload. Right now it's
> > > not and needs different sw architecture.
> > 
> > If the visible effect is identical, I fundamentally disagree with you.
> > 
> > I don't care if there is a frog sitting on the PHY that transforms
> > the packets, it's all the same if the visible behavior is identical.
> 
> that frog is a good example why we disagree.
> I need to check the pulse of that frog and last time it ate.

It is probably over-engineered for a single frog, but maybe you could
use a modified RFC 2795?

    Andrew

^ permalink raw reply

* [PATCH 1/2] tcp: md5: add an address prefix for key lookup
From: Ivan Delalande @ 2017-06-07  0:54 UTC (permalink / raw)
  To: David Miller; +Cc: Eric Dumazet, netdev, linux-kernel, Ivan Delalande

This allows the keys used for TCP MD5 signature to be used for whole
range of addresses, specified with a prefix length, instead of only one
address as it currently is.

Signed-off-by: Bob Gilligan <gilligan@arista.com>
Signed-off-by: Eric Mowat <mowat@arista.com>
Signed-off-by: Ivan Delalande <colona@arista.com>
---
 include/net/tcp.h   |  6 +++--
 net/ipv4/tcp_ipv4.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-------
 net/ipv6/tcp_ipv6.c | 12 ++++++----
 3 files changed, 70 insertions(+), 16 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 38a7427ae902..2b68023ab095 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1395,6 +1395,7 @@ struct tcp_md5sig_key {
 	u8			keylen;
 	u8			family; /* AF_INET or AF_INET6 */
 	union tcp_md5_addr	addr;
+	u8			prefixlen;
 	u8			key[TCP_MD5SIG_MAXKEYLEN];
 	struct rcu_head		rcu;
 };
@@ -1438,9 +1439,10 @@ struct tcp_md5sig_pool {
 int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
 			const struct sock *sk, const struct sk_buff *skb);
 int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
-		   int family, const u8 *newkey, u8 newkeylen, gfp_t gfp);
+		   int family, u8 prefixlen, const u8 *newkey, u8 newkeylen,
+		   gfp_t gfp);
 int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr,
-		   int family);
+		   int family, u8 prefixlen);
 struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk,
 					 const struct sock *addr_sk);
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 5ab2aac5ca19..51ca3bd5a8a3 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -80,6 +80,7 @@
 #include <linux/stddef.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/inetdevice.h>
 
 #include <crypto/hash.h>
 #include <linux/scatterlist.h>
@@ -906,6 +907,9 @@ struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk,
 	struct tcp_md5sig_key *key;
 	unsigned int size = sizeof(struct in_addr);
 	const struct tcp_md5sig_info *md5sig;
+	__be32 mask;
+	struct tcp_md5sig_key *best_match = NULL;
+	bool match;
 
 	/* caller either holds rcu_read_lock() or socket lock */
 	md5sig = rcu_dereference_check(tp->md5sig_info,
@@ -919,12 +923,55 @@ struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk,
 	hlist_for_each_entry_rcu(key, &md5sig->head, node) {
 		if (key->family != family)
 			continue;
-		if (!memcmp(&key->addr, addr, size))
+
+		if (family == AF_INET) {
+			mask = inet_make_mask(key->prefixlen);
+			match = (key->addr.a4.s_addr & mask) ==
+				(addr->a4.s_addr & mask);
+#if IS_ENABLED(CONFIG_IPV6)
+		} else if (family == AF_INET6) {
+			match = ipv6_prefix_equal(&key->addr.a6, &addr->a6,
+						  key->prefixlen);
+#endif
+		} else {
+			match = false;
+		}
+
+		if (match && (!best_match ||
+			      key->prefixlen > best_match->prefixlen))
+			best_match = key;
+	}
+	return best_match;
+}
+EXPORT_SYMBOL(tcp_md5_do_lookup);
+
+struct tcp_md5sig_key *tcp_md5_do_lookup_exact(const struct sock *sk,
+					       const union tcp_md5_addr *addr,
+					       int family, u8 prefixlen)
+{
+	const struct tcp_sock *tp = tcp_sk(sk);
+	struct tcp_md5sig_key *key;
+	unsigned int size = sizeof(struct in_addr);
+	const struct tcp_md5sig_info *md5sig;
+
+	/* caller either holds rcu_read_lock() or socket lock */
+	md5sig = rcu_dereference_check(tp->md5sig_info,
+				       lockdep_sock_is_held(sk));
+	if (!md5sig)
+		return NULL;
+#if IS_ENABLED(CONFIG_IPV6)
+	if (family == AF_INET6)
+		size = sizeof(struct in6_addr);
+#endif
+	hlist_for_each_entry_rcu(key, &md5sig->head, node) {
+		if (key->family != family)
+			continue;
+		if (!memcmp(&key->addr, addr, size) &&
+		    key->prefixlen == prefixlen)
 			return key;
 	}
 	return NULL;
 }
-EXPORT_SYMBOL(tcp_md5_do_lookup);
 
 struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk,
 					 const struct sock *addr_sk)
@@ -938,14 +985,15 @@ EXPORT_SYMBOL(tcp_v4_md5_lookup);
 
 /* This can be called on a newly created socket, from other files */
 int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
-		   int family, const u8 *newkey, u8 newkeylen, gfp_t gfp)
+		   int family, u8 prefixlen, const u8 *newkey, u8 newkeylen,
+		   gfp_t gfp)
 {
 	/* Add Key to the list */
 	struct tcp_md5sig_key *key;
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct tcp_md5sig_info *md5sig;
 
-	key = tcp_md5_do_lookup(sk, addr, family);
+	key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen);
 	if (key) {
 		/* Pre-existing entry - just update that one. */
 		memcpy(key->key, newkey, newkeylen);
@@ -976,6 +1024,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
 	memcpy(key->key, newkey, newkeylen);
 	key->keylen = newkeylen;
 	key->family = family;
+	key->prefixlen = prefixlen;
 	memcpy(&key->addr, addr,
 	       (family == AF_INET6) ? sizeof(struct in6_addr) :
 				      sizeof(struct in_addr));
@@ -984,11 +1033,12 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
 }
 EXPORT_SYMBOL(tcp_md5_do_add);
 
-int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
+int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family,
+		   u8 prefixlen)
 {
 	struct tcp_md5sig_key *key;
 
-	key = tcp_md5_do_lookup(sk, addr, family);
+	key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen);
 	if (!key)
 		return -ENOENT;
 	hlist_del_rcu(&key->node);
@@ -1031,13 +1081,13 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
 
 	if (!cmd.tcpm_keylen)
 		return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
-				      AF_INET);
+				      AF_INET, 32);
 
 	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
 		return -EINVAL;
 
 	return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
-			      AF_INET, cmd.tcpm_key, cmd.tcpm_keylen,
+			      AF_INET, 32, cmd.tcpm_key, cmd.tcpm_keylen,
 			      GFP_KERNEL);
 }
 
@@ -1340,7 +1390,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 		 * across. Shucks.
 		 */
 		tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newinet->inet_daddr,
-			       AF_INET, key->key, key->keylen, GFP_ATOMIC);
+			       AF_INET, 32, key->key, key->keylen, GFP_ATOMIC);
 		sk_nocaps_add(newsk, NETIF_F_GSO_MASK);
 	}
 #endif
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 7a8237acd210..5cf19dab60aa 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -532,9 +532,9 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
 	if (!cmd.tcpm_keylen) {
 		if (ipv6_addr_v4mapped(&sin6->sin6_addr))
 			return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
-					      AF_INET);
+					      AF_INET, 32);
 		return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
-				      AF_INET6);
+				      AF_INET6, 128);
 	}
 
 	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
@@ -542,10 +542,12 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
 
 	if (ipv6_addr_v4mapped(&sin6->sin6_addr))
 		return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
-				      AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
+				      AF_INET, 32, cmd.tcpm_key,
+				      cmd.tcpm_keylen, GFP_KERNEL);
 
 	return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
-			      AF_INET6, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
+			      AF_INET6, 128, cmd.tcpm_key, cmd.tcpm_keylen,
+			      GFP_KERNEL);
 }
 
 static int tcp_v6_md5_hash_headers(struct tcp_md5sig_pool *hp,
@@ -1183,7 +1185,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
 		 * across. Shucks.
 		 */
 		tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr,
-			       AF_INET6, key->key, key->keylen,
+			       AF_INET6, 128, key->key, key->keylen,
 			       sk_gfp_mask(sk, GFP_ATOMIC));
 	}
 #endif
-- 
2.13.0

^ permalink raw reply related

* [PATCH 2/2] tcp: md5: add fields to the tcp_md5sig struct to set a key address prefix
From: Ivan Delalande @ 2017-06-07  0:54 UTC (permalink / raw)
  To: David Miller; +Cc: Eric Dumazet, netdev, linux-kernel, Ivan Delalande
In-Reply-To: <20170607005414.25361-1-colona@arista.com>

Replace padding in the socket option structure tcp_md5sig with a new
flag field and address prefix length so it can be specified when
configuring a new key with the TCP_MD5SIG socket option.

Signed-off-by: Bob Gilligan <gilligan@arista.com>
Signed-off-by: Eric Mowat <mowat@arista.com>
Signed-off-by: Ivan Delalande <colona@arista.com>
---
 include/uapi/linux/tcp.h |  6 +++++-
 net/ipv4/tcp_ipv4.c      | 13 +++++++++++--
 net/ipv6/tcp_ipv6.c      | 20 +++++++++++++++-----
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 38a2b07afdff..52ac30aa0652 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -234,9 +234,13 @@ enum {
 /* for TCP_MD5SIG socket option */
 #define TCP_MD5SIG_MAXKEYLEN	80
 
+/* tcp_md5sig flags */
+#define TCP_MD5SIG_FLAG_PREFIX		1	/* address prefix length */
+
 struct tcp_md5sig {
 	struct __kernel_sockaddr_storage tcpm_addr;	/* address associated */
-	__u16	__tcpm_pad1;				/* zero */
+	__u8	tcpm_flags;				/* flags */
+	__u8	tcpm_prefixlen;				/* address prefix */
 	__u16	tcpm_keylen;				/* key length */
 	__u32	__tcpm_pad2;				/* zero */
 	__u8	tcpm_key[TCP_MD5SIG_MAXKEYLEN];		/* key (binary) */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 51ca3bd5a8a3..2b1bb67b3388 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1069,6 +1069,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
 {
 	struct tcp_md5sig cmd;
 	struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
+	u8 prefixlen;
 
 	if (optlen < sizeof(cmd))
 		return -EINVAL;
@@ -1079,15 +1080,23 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
 	if (sin->sin_family != AF_INET)
 		return -EINVAL;
 
+	if (cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) {
+		prefixlen = cmd.tcpm_prefixlen;
+		if (prefixlen > 32)
+			return -EINVAL;
+	} else {
+		prefixlen = 32;
+	}
+
 	if (!cmd.tcpm_keylen)
 		return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
-				      AF_INET, 32);
+				      AF_INET, prefixlen);
 
 	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
 		return -EINVAL;
 
 	return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
-			      AF_INET, 32, cmd.tcpm_key, cmd.tcpm_keylen,
+			      AF_INET, prefixlen, cmd.tcpm_key, cmd.tcpm_keylen,
 			      GFP_KERNEL);
 }
 
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5cf19dab60aa..f293fc69e88b 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -519,6 +519,7 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
 {
 	struct tcp_md5sig cmd;
 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
+	u8 prefixlen;
 
 	if (optlen < sizeof(cmd))
 		return -EINVAL;
@@ -529,12 +530,21 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
 	if (sin6->sin6_family != AF_INET6)
 		return -EINVAL;
 
+	if (cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) {
+		prefixlen = cmd.tcpm_prefixlen;
+		if (prefixlen > 128 || (ipv6_addr_v4mapped(&sin6->sin6_addr) &&
+					prefixlen > 32))
+			return -EINVAL;
+	} else {
+		prefixlen = ipv6_addr_v4mapped(&sin6->sin6_addr) ? 32 : 128;
+	}
+
 	if (!cmd.tcpm_keylen) {
 		if (ipv6_addr_v4mapped(&sin6->sin6_addr))
 			return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
-					      AF_INET, 32);
+					      AF_INET, prefixlen);
 		return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
-				      AF_INET6, 128);
+				      AF_INET6, prefixlen);
 	}
 
 	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
@@ -542,12 +552,12 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
 
 	if (ipv6_addr_v4mapped(&sin6->sin6_addr))
 		return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
-				      AF_INET, 32, cmd.tcpm_key,
+				      AF_INET, prefixlen, cmd.tcpm_key,
 				      cmd.tcpm_keylen, GFP_KERNEL);
 
 	return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
-			      AF_INET6, 128, cmd.tcpm_key, cmd.tcpm_keylen,
-			      GFP_KERNEL);
+			      AF_INET6, prefixlen, cmd.tcpm_key,
+			      cmd.tcpm_keylen, GFP_KERNEL);
 }
 
 static int tcp_v6_md5_hash_headers(struct tcp_md5sig_pool *hp,
-- 
2.13.0

^ 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