* Re: TCP reaching to maximum throughput after a long time
From: Eric Dumazet @ 2016-04-13 3:32 UTC (permalink / raw)
To: Yuchung Cheng
Cc: Ben Greear, Machani, Yaniv, netdev, David S. Miller, Eric Dumazet,
Neal Cardwell, Nandita Dukkipati, open list, Kama, Meirav
In-Reply-To: <CAK6E8=f+4BagGi5BzLER=Hn2dDJ5FHWkEqLq=04tnWResk58GQ@mail.gmail.com>
On Tue, 2016-04-12 at 20:08 -0700, Yuchung Cheng wrote:
> based on the prev thread I propose we disable hystart ack-train. It is
> brittle under various circumstances. We've disabled that at Google for
> years.
Right, but because we also use sch_fq packet scheduler and pacing ;)
^ permalink raw reply
* Re: TCP reaching to maximum throughput after a long time
From: Yuchung Cheng @ 2016-04-13 3:08 UTC (permalink / raw)
To: Ben Greear
Cc: Eric Dumazet, Machani, Yaniv, netdev, David S. Miller,
Eric Dumazet, Neal Cardwell, Nandita Dukkipati, open list,
Kama, Meirav
In-Reply-To: <570D6B39.3050605@candelatech.com>
On Tue, Apr 12, 2016 at 2:40 PM, Ben Greear <greearb@candelatech.com> wrote:
> On 04/12/2016 01:29 PM, Eric Dumazet wrote:
>>
>> On Tue, 2016-04-12 at 13:23 -0700, Ben Greear wrote:
>>
>>> It worked well enough for years that I didn't even know other algorithms
>>> were
>>> available. It was broken around 4.0 time, and I reported it to the list,
>>> and no one seemed to really care enough to do anything about it. I
>>> changed
>>> to reno and ignored the problem as well.
>>>
>>> It is trivially easy to see the regression when using ath10k NIC, and
>>> from this email
>>> thread, I guess other NICs have similar issues.
>>
>>
>> Since it is so trivial, why don't you start a bisection ?
>
>
> I vaguely remember doing a bisect, but I can't find any email about
> that, so maybe I didn't. At any rate, it is somewhere between 3.17 and 4.0.
> From memory, it was between 3.19 and 4.0, but I am not certain of that.
>
> Neil's suggestion, from the thread below, is that it was likely: "605ad7f
> tcp: refine TSO autosizing"
>
> Here is previous email thread:
>
> https://www.mail-archive.com/netdev@vger.kernel.org/msg80803.html
>
> This one has a link to a pcap I made at the time:
>
> https://www.mail-archive.com/netdev@vger.kernel.org/msg80890.html
based on the prev thread I propose we disable hystart ack-train. It is
brittle under various circumstances. We've disabled that at Google for
years.
>
>>
>> I asked a capture, I did not say ' switch to Reno or whatever ', right ?
>>
>> Guessing is nice, but investigating and fixing is better.
>>
>> Do not assume that nothing can be done, please ?
>
>
> Thanks,
> Ben
>
> --
> Ben Greear <greearb@candelatech.com>
> Candela Technologies Inc http://www.candelatech.com
>
^ permalink raw reply
* Re: [PATCH V3 0/8] net: mediatek: make the driver pass stress tests
From: David Miller @ 2016-04-13 2:42 UTC (permalink / raw)
To: blogic; +Cc: nbd, matthias.bgg, sean.wang, netdev, linux-mediatek,
linux-kernel
In-Reply-To: <1460069651-1234-1-git-send-email-blogic@openwrt.org>
From: John Crispin <blogic@openwrt.org>
Date: Fri, 8 Apr 2016 00:54:03 +0200
> While testing the driver we managed to get the TX path to stall and fail
> to recover. When dual MAC support was added to the driver, the whole queue
> stop/wake code was not properly adapted. There was also a regression in the
> locking of the xmit function. The fact that watchdog_timeo was not set and
> that the tx_timeout code failed to properly reset the dma, irq and queue
> just made the mess complete.
>
> This series make the driver pass stress testing. With this series applied
> the testbed has been running for several days and still has not locked up.
> We have a second setup that has a small hack patch applied to randomly stop
> irqs and/or one of the queues and successfully manages to recover from these
> simulated tx stalls.
Series applied, thanks.
^ permalink raw reply
* Re: [PATCH RFC] net: decrease the length of backlog queue immediately after it's detached from sk
From: Eric Dumazet @ 2016-04-13 2:42 UTC (permalink / raw)
To: Yang Yingliang; +Cc: netdev, davem, Ding Tianhong
In-Reply-To: <570CEA9C.1070803@huawei.com>
On Tue, 2016-04-12 at 20:31 +0800, Yang Yingliang wrote:
> I traced the cost cycles of handling backlog packets in
> __release_sock().
> 16.97 ms to handling about 12MB backlog packets, of which 13.66ms to do
> sk_data_ready.
> The speed of handling packets in TCP is 5.65Gb/s which is smaller than
> the NIC's bandwidth. So the packets will be dropped.
>
> If the cost of sk_data_read cannot be reduced, do we have other choice
> exclude dropping packets ?
Normally, TCP stack sends ACK packets with appropriate RWIN.
Sender should not send more packets than allowed in RWIN, even if there
are 128 threads using one TCP socket, it does not matter.
Imagine you do not have a backlog problem (nothing does the sendmsg()
while you receive data), and nothing reads the socket. Then the receiver
should eventually send WIN 0 back to the sender and sender should stop,
before any drop can possibly happen.
I have no problem receiving one TCP flow at 34Gbit, so it must be
something related to the huge windows you seem to use.
One possibility could be to tweak in ACK packets a reduced rwin so that
the sender is not allowed to continue the flood while we are painfully
processing a huge backlog.
^ permalink raw reply
* Re: [PATCH 0/8] Netfilter updates for net-next
From: David Miller @ 2016-04-13 2:35 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Wed, 13 Apr 2016 01:02:38 +0200
> The following patchset contains the first batch of Netfilter updates for
> your net-next tree.
...
Pulled, thanks Pablo.
^ permalink raw reply
* Re: Configuring ethernet link fails with No such device
From: Stefan Agner @ 2016-04-13 1:29 UTC (permalink / raw)
To: David Miller, teg, f.fainelli
Cc: fabio.estevam, systemd-devel, netdev, u.kleine-koenig, l.stach
In-Reply-To: <20160412.114435.458888996741613334.davem@davemloft.net>
[added Tom Gundersen as he seemed to have worked on udev's net link
built-in]
On 2016-04-12 08:44, David Miller wrote:
> From: Bob Ham <bob.ham@collabora.com>
> Date: Tue, 12 Apr 2016 09:58:12 +0100
>
>> On Mon, 2016-04-11 at 15:46 -0700, Stefan Agner wrote:
>>
>>> Or in other words: Is this a Kernel or systemd issue?
>>
>> From what I recall, both; an issue with the FEC driver, and issues in
>> systemd/udevd's handling of link-level settings.
>
> This is my impression of the situation as well.
The execution order looks as follows for the FEC driver (taken from a
recent kernel with some additional printks, serial console):
...
[ 1.157086] fec_probe
...
[ 1.190350] fec_enet_mii_init
[ 1.205446] libphy: fec_enet_mii_bus: probed
[ 1.217849] fec 400d1000.ethernet eth0: registered PHC device 0
...
[ 10.751060] dev_ethtool, rc -19 => (ETHTOOL_GSET) Too early...
[ 11.262333] fec_enet_open
[ 11.479928] fec_enet_mii_probe => Or/and too late...
Looking at the journal:
...
Apr 13 01:02:49 colibri-vf systemd[1]: Started udev Coldplug all
Devices.
...
Apr 13 01:02:50 colibri-vf kernel: mdev_ethtool, rc -19
...
Apr 13 01:02:50 colibri-vf systemd-udevd[197]: Could not set speed or
duplex of eth0 to 0 Mbps (half): No such device
...
Apr 13 01:02:51 colibri-vf kernel: fec_enet_open
...
Apr 13 01:02:51 colibri-vf kernel: fec_enet_mii_probe
The service "udev Coldplug all Devices" essentially executes:
udevadm trigger --type=subsystems --action=add ; udevadm trigger
--type=devices --action=add
I guess the "add" udev event is generated due to the fact that the
device has successfully been probed. If the kernel is allowed to
initialize the PHY as late as at open time, systemd should configure the
link at a point after link up... Do you agree on that?
Afact there is no udev event on link up, hence this would not be a mere
udev rule change...?
So I think the issue is either a systemd/udev issue or a FEC driver
issue. And the solution is one of this two options:
- Move (all the) PHY probes at driver probe time, then the PHY will be
probed when udev processes the add event
- Or move systemd/networkd/udev link processing, set the link settings
only after the device has been opened (link up).
Florian brought up a good point in another answer:
> Part of the reason for doing that, is that probing for the PHY during
> the driver's probe function could leave you with unused HW that is
> powered on for no good reason. Until we get into ndo_open, we have no
> clue if the interface is going to be used or not, so it is better to
> move part of the HW initialization as late as possible in the process.
Therefor I think only option 2 is actually viable.
--
Stefan
_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel
^ permalink raw reply
* Re: [PATCH net-next] ibmvnic: Defer tx completion processing using a wait queue
From: David Miller @ 2016-04-13 1:12 UTC (permalink / raw)
To: jallen; +Cc: eric.dumazet, tlfalcon, netdev, linuxppc-dev
In-Reply-To: <570D61E7.2090203@linux.vnet.ibm.com>
From: John Allen <jallen@linux.vnet.ibm.com>
Date: Tue, 12 Apr 2016 16:00:23 -0500
> On 04/12/2016 03:12 PM, Eric Dumazet wrote:
>> On Tue, 2016-04-12 at 14:38 -0500, John Allen wrote:
>>> Moves tx completion processing out of interrupt context, deferring work
>>> using a wait queue. With this work now deferred, we must account for the
>>> possibility that skbs can be sent faster than we can process completion
>>> requests in which case the tx buffer will overflow. If the tx buffer is
>>> full, ibmvnic_xmit will return NETDEV_TX_BUSY and stop the current tx
>>> queue. Subsequently, the queue will be restarted in ibmvnic_complete_tx
>>> when all pending tx completion requests have been cleared.
>>
>> 1) Why is this needed ?
>
> In the current ibmvnic implementation, tx completion processing is done in
> interrupt context. Depending on the load, this can block further
> interrupts for a long time. This patch just creates a bottom half so that
> when a tx completion interrupt comes in, we can defer the majority of the
> work and exit interrupt context quickly.
You should use NAPI polling for this, not your own invented
mechanism.
^ permalink raw reply
* [PATCH v2 net-next 0/7] DSA refactoring: set 1
From: Andrew Lunn @ 2016-04-13 0:40 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
There has been a long running effort to refractor DSA probing to make
the switches true linux devices. Here are a small collection of
patches moving in this direction. Most have been seen before.
We take a little step forward by passing the dsa device point to the
driver, thus allowing it to perform resource allocations using the
normal mechanisms. This device structure will later be replaced by the
devices own device structure.
Future patches will add a true driver probe function, so we rename the
current probe function, cleaning up the namespace.
phys_port_mask continually confuses me, thinking it is about PHYs. But
it is actually about ports enabled to the outside world. So rename it to
enabled_port_mask.
Lots more patches yet to follow, this is just doing some ground work.
v2:
enabled_port_mask instread of user_port_masks
Added Tested-by's and Reviewed-by.
Andrew Lunn (7):
net: dsa: Pass the dsa device to the switch drivers
net: dsa: Have the switch driver allocate there own private memory
net: dsa: Remove allocation of driver private memory
net: dsa: Keep the mii bus and address in the private structure
net: dsa: Rename DSA probe function.
dsa: Rename phys_port_mask to user_port_mask
dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name()
drivers/net/dsa/bcm_sf2.c | 24 +++++++++++++-------
drivers/net/dsa/mv88e6060.c | 47 +++++++++++++++++++++++---------------
drivers/net/dsa/mv88e6060.h | 11 +++++++++
drivers/net/dsa/mv88e6123.c | 14 +++++++-----
drivers/net/dsa/mv88e6131.c | 14 +++++++-----
drivers/net/dsa/mv88e6171.c | 14 +++++++-----
drivers/net/dsa/mv88e6352.c | 14 +++++++-----
drivers/net/dsa/mv88e6xxx.c | 55 +++++++++++++++++++++++++++++++--------------
drivers/net/dsa/mv88e6xxx.h | 17 +++++++++++---
include/net/dsa.h | 16 ++++++++-----
net/dsa/dsa.c | 19 +++++++++-------
11 files changed, 166 insertions(+), 79 deletions(-)
--
2.7.0
^ permalink raw reply
* [PATCH v2 net-next 6/7] dsa: Rename phys_port_mask to enabled_port_mask
From: Andrew Lunn @ 2016-04-13 0:40 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460508045-20254-1-git-send-email-andrew@lunn.ch>
The phys in phys_port_mask suggests this mask is about PHYs. In fact,
it means physical ports. Rename to enabled_port_mask, indicating
external enabled ports of the switch, which is hopefully less
confusing.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
v2:
s/user_port_mask/enabled_port_mask/g
---
drivers/net/dsa/bcm_sf2.c | 19 ++++++++++---------
drivers/net/dsa/mv88e6060.c | 2 +-
include/net/dsa.h | 4 ++--
net/dsa/dsa.c | 8 ++++----
4 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 50caa525cda3..7a5f0ef46bd6 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -160,7 +160,7 @@ static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
* the same VLAN.
*/
for (i = 0; i < priv->hw_params.num_ports; i++) {
- if (!((1 << i) & ds->phys_port_mask))
+ if (!((1 << i) & ds->enabled_port_mask))
continue;
reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i));
@@ -1009,7 +1009,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
/* Enable all valid ports and disable those unused */
for (port = 0; port < priv->hw_params.num_ports; port++) {
/* IMP port receives special treatment */
- if ((1 << port) & ds->phys_port_mask)
+ if ((1 << port) & ds->enabled_port_mask)
bcm_sf2_port_setup(ds, port, NULL);
else if (dsa_is_cpu_port(ds, port))
bcm_sf2_imp_setup(ds, port);
@@ -1022,11 +1022,12 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
* 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such
* that we can use the regular SWITCH_MDIO master controller instead.
*
- * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask
- * to have a 1:1 mapping between Port address and PHY address in order
- * to utilize the slave_mii_bus instance to read from Port PHYs. This is
- * not what we want here, so we initialize phys_mii_mask 0 to always
- * utilize the "master" MDIO bus backed by the "mdio-unimac" driver.
+ * By default, DSA initializes ds->phys_mii_mask to
+ * ds->enabled_port_mask to have a 1:1 mapping between Port address
+ * and PHY address in order to utilize the slave_mii_bus instance to
+ * read from Port PHYs. This is not what we want here, so we
+ * initialize phys_mii_mask 0 to always utilize the "master" MDIO
+ * bus backed by the "mdio-unimac" driver.
*/
if (of_machine_is_compatible("brcm,bcm7445d0"))
ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0));
@@ -1284,7 +1285,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
* bcm_sf2_sw_setup
*/
for (port = 0; port < DSA_MAX_PORTS; port++) {
- if ((1 << port) & ds->phys_port_mask ||
+ if ((1 << port) & ds->enabled_port_mask ||
dsa_is_cpu_port(ds, port))
bcm_sf2_port_disable(ds, port, NULL);
}
@@ -1308,7 +1309,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
bcm_sf2_gphy_enable_set(ds, true);
for (port = 0; port < DSA_MAX_PORTS; port++) {
- if ((1 << port) & ds->phys_port_mask)
+ if ((1 << port) & ds->enabled_port_mask)
bcm_sf2_port_setup(ds, port, NULL);
else if (dsa_is_cpu_port(ds, port))
bcm_sf2_imp_setup(ds, port);
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index adb608ccd9aa..92cebab9383e 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -170,7 +170,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
REG_WRITE(addr, PORT_VLAN_MAP,
((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
(dsa_is_cpu_port(ds, p) ?
- ds->phys_port_mask :
+ ds->enabled_port_mask :
BIT(ds->dst->cpu_port)));
/* Port Association Vector: when learning source addresses
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 165c2e10615c..689ebd3542ba 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -167,7 +167,7 @@ struct dsa_switch {
* Slave mii_bus and devices for the individual ports.
*/
u32 dsa_port_mask;
- u32 phys_port_mask;
+ u32 enabled_port_mask;
u32 phys_mii_mask;
struct mii_bus *slave_mii_bus;
struct net_device *ports[DSA_MAX_PORTS];
@@ -185,7 +185,7 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
{
- return ds->phys_port_mask & (1 << p) && ds->ports[p];
+ return ds->enabled_port_mask & (1 << p) && ds->ports[p];
}
static inline u8 dsa_upstream_port(struct dsa_switch *ds)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 14bf12f637d2..60ea98481806 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -246,7 +246,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
} else if (!strcmp(name, "dsa")) {
ds->dsa_port_mask |= 1 << i;
} else {
- ds->phys_port_mask |= 1 << i;
+ ds->enabled_port_mask |= 1 << i;
}
valid_name_found = true;
}
@@ -259,7 +259,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
/* Make the built-in MII bus mask match the number of ports,
* switch drivers can override this later
*/
- ds->phys_mii_mask = ds->phys_port_mask;
+ ds->phys_mii_mask = ds->enabled_port_mask;
/*
* If the CPU connects to this switch, set the switch tree
@@ -325,7 +325,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
* Create network devices for physical switch ports.
*/
for (i = 0; i < DSA_MAX_PORTS; i++) {
- if (!(ds->phys_port_mask & (1 << i)))
+ if (!(ds->enabled_port_mask & (1 << i)))
continue;
ret = dsa_slave_create(ds, parent, i, pd->port_names[i]);
@@ -435,7 +435,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
/* Destroy network devices for physical switch ports. */
for (port = 0; port < DSA_MAX_PORTS; port++) {
- if (!(ds->phys_port_mask & (1 << port)))
+ if (!(ds->enabled_port_mask & (1 << port)))
continue;
if (!ds->ports[port])
--
2.7.0
^ permalink raw reply related
* [PATCH v2 net-next 1/7] net: dsa: Pass the dsa device to the switch drivers
From: Andrew Lunn @ 2016-04-13 0:40 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460508045-20254-1-git-send-email-andrew@lunn.ch>
By passing a device structure to the switch devices, it allows them
to use devm_* methods for resource management.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/bcm_sf2.c | 3 ++-
drivers/net/dsa/mv88e6060.c | 3 ++-
drivers/net/dsa/mv88e6123.c | 3 ++-
drivers/net/dsa/mv88e6131.c | 3 ++-
drivers/net/dsa/mv88e6171.c | 3 ++-
drivers/net/dsa/mv88e6352.c | 3 ++-
include/net/dsa.h | 3 ++-
net/dsa/dsa.c | 7 ++++---
8 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 780f22876538..18a79579141f 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -135,7 +135,8 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds)
return BCM_SF2_STATS_SIZE;
}
-static char *bcm_sf2_sw_probe(struct device *host_dev, int sw_addr)
+static char *bcm_sf2_sw_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr)
{
return "Broadcom Starfighter 2";
}
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 0527f485c3dc..34d0f9fe19db 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -57,7 +57,8 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
return __ret; \
})
-static char *mv88e6060_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr)
{
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int ret;
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 69a6f79dcb10..ede4c6f0b31a 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -29,7 +29,8 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
{ PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
};
-static char *mv88e6123_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6123_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr)
{
return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table,
ARRAY_SIZE(mv88e6123_table));
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 24070287c2bc..bfadfd2cbb8d 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -25,7 +25,8 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
{ PORT_SWITCH_ID_6185, "Marvell 88E6185" },
};
-static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6131_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr)
{
return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table,
ARRAY_SIZE(mv88e6131_table));
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 0e62f3b5bc81..fb35d3ac1644 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -24,7 +24,8 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
{ PORT_SWITCH_ID_6351, "Marvell 88E6351" },
};
-static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6171_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr)
{
return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table,
ARRAY_SIZE(mv88e6171_table));
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 7f452e4a04a5..577ab2cfa944 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -37,7 +37,8 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
{ PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" },
};
-static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6352_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr)
{
return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table,
ARRAY_SIZE(mv88e6352_table));
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 18d1be3ad62d..0f9f6f38f255 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -212,7 +212,8 @@ struct dsa_switch_driver {
/*
* Probing and setup.
*/
- char *(*probe)(struct device *host_dev, int sw_addr);
+ char *(*probe)(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr);
int (*setup)(struct dsa_switch *ds);
int (*set_addr)(struct dsa_switch *ds, u8 *addr);
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index c28c47463b7e..c06275311cb2 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -51,7 +51,8 @@ void unregister_switch_driver(struct dsa_switch_driver *drv)
EXPORT_SYMBOL_GPL(unregister_switch_driver);
static struct dsa_switch_driver *
-dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name)
+dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr,
+ char **_name)
{
struct dsa_switch_driver *ret;
struct list_head *list;
@@ -66,7 +67,7 @@ dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name)
drv = list_entry(list, struct dsa_switch_driver, list);
- name = drv->probe(host_dev, sw_addr);
+ name = drv->probe(parent, host_dev, sw_addr);
if (name != NULL) {
ret = drv;
break;
@@ -387,7 +388,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
/*
* Probe for switch model.
*/
- drv = dsa_switch_probe(host_dev, pd->sw_addr, &name);
+ drv = dsa_switch_probe(parent, host_dev, pd->sw_addr, &name);
if (drv == NULL) {
netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n",
index);
--
2.7.0
^ permalink raw reply related
* [PATCH v2 net-next 4/7] net: dsa: Keep the mii bus and address in the private structure
From: Andrew Lunn @ 2016-04-13 0:40 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460508045-20254-1-git-send-email-andrew@lunn.ch>
Rather than looking up the mii bus and address every time, do it once
at probe, and keep it in the private structure. Centralise this probe
code in mv88e6xxx.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6060.c | 44 ++++++++++++++++++++++++++------------------
drivers/net/dsa/mv88e6060.h | 11 +++++++++++
drivers/net/dsa/mv88e6123.c | 15 +++------------
drivers/net/dsa/mv88e6131.c | 15 +++------------
drivers/net/dsa/mv88e6171.c | 15 +++------------
drivers/net/dsa/mv88e6352.c | 15 +++------------
drivers/net/dsa/mv88e6xxx.c | 43 +++++++++++++++++++++++++++++--------------
drivers/net/dsa/mv88e6xxx.h | 14 +++++++++++---
8 files changed, 89 insertions(+), 83 deletions(-)
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 41195f1417f1..46fe5dc65a99 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -19,12 +19,9 @@
static int reg_read(struct dsa_switch *ds, int addr, int reg)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ struct mv88e6060_priv *priv = ds_to_priv(ds);
- if (bus == NULL)
- return -EINVAL;
-
- return mdiobus_read_nested(bus, ds->pd->sw_addr + addr, reg);
+ return mdiobus_read_nested(priv->bus, priv->sw_addr + addr, reg);
}
#define REG_READ(addr, reg) \
@@ -40,12 +37,9 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg)
static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
-
- if (bus == NULL)
- return -EINVAL;
+ struct mv88e6060_priv *priv = ds_to_priv(ds);
- return mdiobus_write_nested(bus, ds->pd->sw_addr + addr, reg, val);
+ return mdiobus_write_nested(priv->bus, priv->sw_addr + addr, reg, val);
}
#define REG_WRITE(addr, reg, val) \
@@ -57,16 +51,10 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
return __ret; \
})
-static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr, void **priv)
+static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int ret;
- *priv = NULL;
- if (bus == NULL)
- return NULL;
-
ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID);
if (ret >= 0) {
if (ret == PORT_SWITCH_ID_6060)
@@ -81,6 +69,26 @@ static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev,
return NULL;
}
+static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr, void **_priv)
+{
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+ struct mv88e6060_priv *priv;
+ char *name;
+
+ name = mv88e6060_get_name(bus, sw_addr);
+ if (name) {
+ priv = devm_kzalloc(dsa_dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return NULL;
+ *_priv = priv;
+ priv->bus = bus;
+ priv->sw_addr = sw_addr;
+ }
+
+ return name;
+}
+
static int mv88e6060_switch_reset(struct dsa_switch *ds)
{
int i;
@@ -176,8 +184,8 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
static int mv88e6060_setup(struct dsa_switch *ds)
{
- int i;
int ret;
+ int i;
ret = mv88e6060_switch_reset(ds);
if (ret < 0)
diff --git a/drivers/net/dsa/mv88e6060.h b/drivers/net/dsa/mv88e6060.h
index cc9b2ed4aff4..10249bd16292 100644
--- a/drivers/net/dsa/mv88e6060.h
+++ b/drivers/net/dsa/mv88e6060.h
@@ -108,4 +108,15 @@
#define GLOBAL_ATU_MAC_23 0x0e
#define GLOBAL_ATU_MAC_45 0x0f
+struct mv88e6060_priv {
+ /* MDIO bus and address on bus to use. When in single chip
+ * mode, address is 0, and the switch uses multiple addresses
+ * on the bus. When in multi-chip mode, the switch uses a
+ * single address which contains two registers used for
+ * indirect access to more registers.
+ */
+ struct mii_bus *bus;
+ int sw_addr;
+};
+
#endif
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index bcab3ef22448..8aaac0894752 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -32,18 +32,9 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
static char *mv88e6123_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv)
{
- struct mv88e6xxx_priv_state *ps;
- char *name;
-
- name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table,
- ARRAY_SIZE(mv88e6123_table));
- if (name) {
- ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
- if (!ps)
- return NULL;
- *priv = ps;
- }
- return name;
+ return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
+ mv88e6123_table,
+ ARRAY_SIZE(mv88e6123_table));
}
static int mv88e6123_setup_global(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index b9f9b009f65a..9e6edf94a855 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -28,18 +28,9 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
static char *mv88e6131_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv)
{
- struct mv88e6xxx_priv_state *ps;
- char *name;
-
- name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table,
- ARRAY_SIZE(mv88e6131_table));
- if (name) {
- ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
- if (!ps)
- return NULL;
- *priv = ps;
- }
- return name;
+ return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
+ mv88e6131_table,
+ ARRAY_SIZE(mv88e6131_table));
}
static int mv88e6131_setup_global(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 15200928cecc..6ab86071391f 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -27,18 +27,9 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
static char *mv88e6171_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv)
{
- struct mv88e6xxx_priv_state *ps;
- char *name;
-
- name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table,
- ARRAY_SIZE(mv88e6171_table));
- if (name) {
- ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
- if (!ps)
- return NULL;
- *priv = ps;
- }
- return name;
+ return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
+ mv88e6171_table,
+ ARRAY_SIZE(mv88e6171_table));
}
static int mv88e6171_setup_global(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 7081a78a67e1..764b10ffb631 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -40,18 +40,9 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
static char *mv88e6352_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv)
{
- struct mv88e6xxx_priv_state *ps;
- char *name;
-
- name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table,
- ARRAY_SIZE(mv88e6352_table));
- if (name) {
- ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
- if (!ps)
- return NULL;
- *priv = ps;
- }
- return name;
+ return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
+ mv88e6352_table,
+ ARRAY_SIZE(mv88e6352_table));
}
static int mv88e6352_setup_global(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 085fc4a49eb2..c242ffd8eb09 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -94,15 +94,12 @@ static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr,
static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
assert_smi_lock(ds);
- if (bus == NULL)
- return -EINVAL;
-
- ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg);
+ ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
if (ret < 0)
return ret;
@@ -159,17 +156,14 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
u16 val)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
assert_smi_lock(ds);
- if (bus == NULL)
- return -EINVAL;
-
dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
addr, reg, val);
- return __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val);
+ return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val);
}
int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
@@ -2671,7 +2665,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
ps->ds = ds;
-
mutex_init(&ps->smi_mutex);
ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
@@ -3075,9 +3068,9 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
}
#endif /* CONFIG_NET_DSA_HWMON */
-char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
- const struct mv88e6xxx_switch_id *table,
- unsigned int num)
+static char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int num)
{
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int i, ret;
@@ -3107,6 +3100,28 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
return NULL;
}
+char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr, void **priv,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int num)
+{
+ struct mv88e6xxx_priv_state *ps;
+ char *name;
+
+ name = mv88e6xxx_lookup_name(host_dev, sw_addr, table, num);
+ if (name) {
+ ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return NULL;
+ *priv = ps;
+ ps->bus = dsa_host_dev_to_mii_bus(host_dev);
+ if (!ps->bus)
+ return NULL;
+ ps->sw_addr = sw_addr;
+ }
+ return name;
+}
+
static int __init mv88e6xxx_init(void)
{
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 0322e3e0e7d9..5d27decc85cb 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -406,6 +406,12 @@ struct mv88e6xxx_priv_state {
*/
struct mutex smi_mutex;
+ /* The MII bus and the address on the bus that is used to
+ * communication with the switch
+ */
+ struct mii_bus *bus;
+ int sw_addr;
+
#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
/* Handles automatic disabling and re-enabling of the PHY
* polling unit.
@@ -456,9 +462,11 @@ struct mv88e6xxx_hw_stat {
};
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
-char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
- const struct mv88e6xxx_switch_id *table,
- unsigned int num);
+char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
+ int sw_addr, void **priv,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int num);
+
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
int mv88e6xxx_setup_common(struct dsa_switch *ds);
int mv88e6xxx_setup_global(struct dsa_switch *ds);
--
2.7.0
^ permalink raw reply related
* [PATCH v2 net-next 2/7] net: dsa: Have the switch driver allocate there own private memory
From: Andrew Lunn @ 2016-04-13 0:40 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460508045-20254-1-git-send-email-andrew@lunn.ch>
Now the switch devices have a dev pointer, make use of it for allocating
the drivers private data structures using a devm_kzalloc().
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/bcm_sf2.c | 10 ++++++++--
drivers/net/dsa/mv88e6060.c | 3 ++-
drivers/net/dsa/mv88e6123.c | 17 ++++++++++++++---
drivers/net/dsa/mv88e6131.c | 17 ++++++++++++++---
drivers/net/dsa/mv88e6171.c | 17 ++++++++++++++---
drivers/net/dsa/mv88e6352.c | 17 ++++++++++++++---
drivers/net/dsa/mv88e6xxx.c | 6 ++++--
drivers/net/dsa/mv88e6xxx.h | 3 +++
include/net/dsa.h | 10 ++++++++--
net/dsa/dsa.c | 8 +++++---
10 files changed, 86 insertions(+), 22 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 18a79579141f..7d62802a66d5 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -136,8 +136,15 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds)
}
static char *bcm_sf2_sw_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr)
+ int sw_addr, void **_priv)
{
+ struct bcm_sf2_priv *priv;
+
+ priv = devm_kzalloc(dsa_dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return NULL;
+ *_priv = priv;
+
return "Broadcom Starfighter 2";
}
@@ -1363,7 +1370,6 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
static struct dsa_switch_driver bcm_sf2_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_BRCM,
- .priv_size = sizeof(struct bcm_sf2_priv),
.probe = bcm_sf2_sw_probe,
.setup = bcm_sf2_sw_setup,
.set_addr = bcm_sf2_sw_set_addr,
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 34d0f9fe19db..41195f1417f1 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -58,11 +58,12 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
})
static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr)
+ int sw_addr, void **priv)
{
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int ret;
+ *priv = NULL;
if (bus == NULL)
return NULL;
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index ede4c6f0b31a..bcab3ef22448 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -30,10 +30,20 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
};
static char *mv88e6123_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr)
+ int sw_addr, void **priv)
{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table,
+ struct mv88e6xxx_priv_state *ps;
+ char *name;
+
+ name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table,
ARRAY_SIZE(mv88e6123_table));
+ if (name) {
+ ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return NULL;
+ *priv = ps;
+ }
+ return name;
}
static int mv88e6123_setup_global(struct dsa_switch *ds)
@@ -74,6 +84,8 @@ static int mv88e6123_setup(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
+ ps->ds = ds;
+
ret = mv88e6xxx_setup_common(ds);
if (ret < 0)
return ret;
@@ -103,7 +115,6 @@ static int mv88e6123_setup(struct dsa_switch *ds)
struct dsa_switch_driver mv88e6123_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
.probe = mv88e6123_probe,
.setup = mv88e6123_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index bfadfd2cbb8d..b9f9b009f65a 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -26,10 +26,20 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
};
static char *mv88e6131_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr)
+ int sw_addr, void **priv)
{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table,
+ struct mv88e6xxx_priv_state *ps;
+ char *name;
+
+ name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table,
ARRAY_SIZE(mv88e6131_table));
+ if (name) {
+ ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return NULL;
+ *priv = ps;
+ }
+ return name;
}
static int mv88e6131_setup_global(struct dsa_switch *ds)
@@ -92,6 +102,8 @@ static int mv88e6131_setup(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
+ ps->ds = ds;
+
ret = mv88e6xxx_setup_common(ds);
if (ret < 0)
return ret;
@@ -160,7 +172,6 @@ mv88e6131_phy_write(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6131_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_DSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
.probe = mv88e6131_probe,
.setup = mv88e6131_setup,
.set_addr = mv88e6xxx_set_addr_direct,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index fb35d3ac1644..15200928cecc 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -25,10 +25,20 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
};
static char *mv88e6171_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr)
+ int sw_addr, void **priv)
{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table,
+ struct mv88e6xxx_priv_state *ps;
+ char *name;
+
+ name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table,
ARRAY_SIZE(mv88e6171_table));
+ if (name) {
+ ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return NULL;
+ *priv = ps;
+ }
+ return name;
}
static int mv88e6171_setup_global(struct dsa_switch *ds)
@@ -70,6 +80,8 @@ static int mv88e6171_setup(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
+ ps->ds = ds;
+
ret = mv88e6xxx_setup_common(ds);
if (ret < 0)
return ret;
@@ -89,7 +101,6 @@ static int mv88e6171_setup(struct dsa_switch *ds)
struct dsa_switch_driver mv88e6171_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
.probe = mv88e6171_probe,
.setup = mv88e6171_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 577ab2cfa944..7081a78a67e1 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -38,10 +38,20 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
};
static char *mv88e6352_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr)
+ int sw_addr, void **priv)
{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table,
+ struct mv88e6xxx_priv_state *ps;
+ char *name;
+
+ name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table,
ARRAY_SIZE(mv88e6352_table));
+ if (name) {
+ ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return NULL;
+ *priv = ps;
+ }
+ return name;
}
static int mv88e6352_setup_global(struct dsa_switch *ds)
@@ -82,6 +92,8 @@ static int mv88e6352_setup(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
+ ps->ds = ds;
+
ret = mv88e6xxx_setup_common(ds);
if (ret < 0)
return ret;
@@ -303,7 +315,6 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6352_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
.probe = mv88e6352_probe,
.setup = mv88e6352_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 62320fca6712..085fc4a49eb2 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -281,7 +281,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
if (mutex_trylock(&ps->ppu_mutex)) {
- struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1;
+ struct dsa_switch *ds = ps->ds;
if (mv88e6xxx_ppu_enable(ds) == 0)
ps->ppu_disabled = 0;
@@ -2322,7 +2322,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
int port;
ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work);
- ds = ((struct dsa_switch *)ps) - 1;
+ ds = ps->ds;
mutex_lock(&ps->smi_mutex);
@@ -2670,6 +2670,8 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ ps->ds = ds;
+
mutex_init(&ps->smi_mutex);
ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 236bcaa606e7..0322e3e0e7d9 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -397,6 +397,9 @@ struct mv88e6xxx_priv_port {
};
struct mv88e6xxx_priv_state {
+ /* The dsa_switch this private structure is related to */
+ struct dsa_switch *ds;
+
/* When using multi-chip addressing, this mutex protects
* access to the indirect access registers. (In single-chip
* mode, this mutex is effectively useless.)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 0f9f6f38f255..7bc7bd9b5ded 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -130,6 +130,12 @@ struct dsa_switch {
int index;
/*
+ * Give the switch driver somewhere to hang its private data
+ * structure.
+ */
+ void *priv;
+
+ /*
* Tagging protocol understood by this switch
*/
enum dsa_tag_protocol tag_protocol;
@@ -213,7 +219,7 @@ struct dsa_switch_driver {
* Probing and setup.
*/
char *(*probe)(struct device *dsa_dev, struct device *host_dev,
- int sw_addr);
+ int sw_addr, void **priv);
int (*setup)(struct dsa_switch *ds);
int (*set_addr)(struct dsa_switch *ds, u8 *addr);
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
@@ -342,7 +348,7 @@ struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev);
static inline void *ds_to_priv(struct dsa_switch *ds)
{
- return (void *)(ds + 1);
+ return ds->priv;
}
static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index c06275311cb2..7ef8a92a9e39 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -52,7 +52,7 @@ EXPORT_SYMBOL_GPL(unregister_switch_driver);
static struct dsa_switch_driver *
dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr,
- char **_name)
+ char **_name, void **priv)
{
struct dsa_switch_driver *ret;
struct list_head *list;
@@ -67,7 +67,7 @@ dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr,
drv = list_entry(list, struct dsa_switch_driver, list);
- name = drv->probe(parent, host_dev, sw_addr);
+ name = drv->probe(parent, host_dev, sw_addr, priv);
if (name != NULL) {
ret = drv;
break;
@@ -384,11 +384,12 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
struct dsa_switch *ds;
int ret;
char *name;
+ void *priv;
/*
* Probe for switch model.
*/
- drv = dsa_switch_probe(parent, host_dev, pd->sw_addr, &name);
+ drv = dsa_switch_probe(parent, host_dev, pd->sw_addr, &name, &priv);
if (drv == NULL) {
netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n",
index);
@@ -409,6 +410,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
ds->index = index;
ds->pd = pd;
ds->drv = drv;
+ ds->priv = priv;
ds->tag_protocol = drv->tag_protocol;
ds->master_dev = host_dev;
--
2.7.0
^ permalink raw reply related
* [PATCH v2 net-next 3/7] net: dsa: Remove allocation of driver private memory
From: Andrew Lunn @ 2016-04-13 0:40 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460508045-20254-1-git-send-email-andrew@lunn.ch>
The drivers now allocate their own memory for private usage. Remove
the allocation from the core code.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
include/net/dsa.h | 1 -
net/dsa/dsa.c | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 7bc7bd9b5ded..165c2e10615c 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -213,7 +213,6 @@ struct dsa_switch_driver {
struct list_head list;
enum dsa_tag_protocol tag_protocol;
- int priv_size;
/*
* Probing and setup.
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 7ef8a92a9e39..14bf12f637d2 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -402,7 +402,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
/*
* Allocate and initialise switch state.
*/
- ds = devm_kzalloc(parent, sizeof(*ds) + drv->priv_size, GFP_KERNEL);
+ ds = devm_kzalloc(parent, sizeof(*ds), GFP_KERNEL);
if (ds == NULL)
return ERR_PTR(-ENOMEM);
--
2.7.0
^ permalink raw reply related
* [PATCH v2 net-next 7/7] dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name()
From: Andrew Lunn @ 2016-04-13 0:40 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460508045-20254-1-git-send-email-andrew@lunn.ch>
mv88e6xxx_lookup_name() returns the model name of a switch at a given
address on an MII bus. Using mii_bus to identify the bus rather than
the host device is more logical, so change the parameter.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6xxx.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index c242ffd8eb09..9985a0cf31f1 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3068,11 +3068,10 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
}
#endif /* CONFIG_NET_DSA_HWMON */
-static char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
+static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
const struct mv88e6xxx_switch_id *table,
unsigned int num)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int i, ret;
if (!bus)
@@ -3090,7 +3089,8 @@ static char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
/* Look up only the product number */
for (i = 0; i < num; ++i) {
if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) {
- dev_warn(host_dev, "unknown revision %d, using base switch 0x%x\n",
+ dev_warn(&bus->dev,
+ "unknown revision %d, using base switch 0x%x\n",
ret & PORT_SWITCH_ID_REV_MASK,
ret & PORT_SWITCH_ID_PROD_NUM_MASK);
return table[i].name;
@@ -3106,9 +3106,13 @@ char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
unsigned int num)
{
struct mv88e6xxx_priv_state *ps;
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
char *name;
- name = mv88e6xxx_lookup_name(host_dev, sw_addr, table, num);
+ if (!bus)
+ return NULL;
+
+ name = mv88e6xxx_lookup_name(bus, sw_addr, table, num);
if (name) {
ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
if (!ps)
--
2.7.0
^ permalink raw reply related
* [PATCH v2 net-next 5/7] net: dsa: Rename DSA probe function.
From: Andrew Lunn @ 2016-04-13 0:40 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460508045-20254-1-git-send-email-andrew@lunn.ch>
Rename the function called from the DSA to perform a probe for the
switch. This makes the normal _probe() name available for a standard
Linux device driver probe function.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/bcm_sf2.c | 7 ++++---
drivers/net/dsa/mv88e6060.c | 7 ++++---
drivers/net/dsa/mv88e6123.c | 7 ++++---
drivers/net/dsa/mv88e6131.c | 7 ++++---
drivers/net/dsa/mv88e6171.c | 7 ++++---
drivers/net/dsa/mv88e6352.c | 7 ++++---
6 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 7d62802a66d5..50caa525cda3 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -135,8 +135,9 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds)
return BCM_SF2_STATS_SIZE;
}
-static char *bcm_sf2_sw_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr, void **_priv)
+static char *bcm_sf2_sw_drv_probe(struct device *dsa_dev,
+ struct device *host_dev,
+ int sw_addr, void **_priv)
{
struct bcm_sf2_priv *priv;
@@ -1370,7 +1371,7 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
static struct dsa_switch_driver bcm_sf2_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_BRCM,
- .probe = bcm_sf2_sw_probe,
+ .probe = bcm_sf2_sw_drv_probe,
.setup = bcm_sf2_sw_setup,
.set_addr = bcm_sf2_sw_set_addr,
.get_phy_flags = bcm_sf2_sw_get_phy_flags,
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 46fe5dc65a99..adb608ccd9aa 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -69,8 +69,9 @@ static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr)
return NULL;
}
-static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr, void **_priv)
+static char *mv88e6060_drv_probe(struct device *dsa_dev,
+ struct device *host_dev,
+ int sw_addr, void **_priv)
{
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
struct mv88e6060_priv *priv;
@@ -248,7 +249,7 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
static struct dsa_switch_driver mv88e6060_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_TRAILER,
- .probe = mv88e6060_probe,
+ .probe = mv88e6060_drv_probe,
.setup = mv88e6060_setup,
.set_addr = mv88e6060_set_addr,
.phy_read = mv88e6060_phy_read,
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 8aaac0894752..c34283d929c4 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -29,8 +29,9 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
{ PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
};
-static char *mv88e6123_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr, void **priv)
+static char *mv88e6123_drv_probe(struct device *dsa_dev,
+ struct device *host_dev,
+ int sw_addr, void **priv)
{
return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
mv88e6123_table,
@@ -106,7 +107,7 @@ static int mv88e6123_setup(struct dsa_switch *ds)
struct dsa_switch_driver mv88e6123_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .probe = mv88e6123_probe,
+ .probe = mv88e6123_drv_probe,
.setup = mv88e6123_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 9e6edf94a855..f5d75fce1e96 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -25,8 +25,9 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
{ PORT_SWITCH_ID_6185, "Marvell 88E6185" },
};
-static char *mv88e6131_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr, void **priv)
+static char *mv88e6131_drv_probe(struct device *dsa_dev,
+ struct device *host_dev,
+ int sw_addr, void **priv)
{
return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
mv88e6131_table,
@@ -163,7 +164,7 @@ mv88e6131_phy_write(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6131_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_DSA,
- .probe = mv88e6131_probe,
+ .probe = mv88e6131_drv_probe,
.setup = mv88e6131_setup,
.set_addr = mv88e6xxx_set_addr_direct,
.phy_read = mv88e6131_phy_read,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 6ab86071391f..f5622506cdfa 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -24,8 +24,9 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
{ PORT_SWITCH_ID_6351, "Marvell 88E6351" },
};
-static char *mv88e6171_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr, void **priv)
+static char *mv88e6171_drv_probe(struct device *dsa_dev,
+ struct device *host_dev,
+ int sw_addr, void **priv)
{
return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
mv88e6171_table,
@@ -92,7 +93,7 @@ static int mv88e6171_setup(struct dsa_switch *ds)
struct dsa_switch_driver mv88e6171_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .probe = mv88e6171_probe,
+ .probe = mv88e6171_drv_probe,
.setup = mv88e6171_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 764b10ffb631..e54ee27db129 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -37,8 +37,9 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
{ PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" },
};
-static char *mv88e6352_probe(struct device *dsa_dev, struct device *host_dev,
- int sw_addr, void **priv)
+static char *mv88e6352_drv_probe(struct device *dsa_dev,
+ struct device *host_dev,
+ int sw_addr, void **priv)
{
return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
mv88e6352_table,
@@ -306,7 +307,7 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6352_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .probe = mv88e6352_probe,
+ .probe = mv88e6352_drv_probe,
.setup = mv88e6352_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect,
--
2.7.0
^ permalink raw reply related
* [PATCH 8/8] netfilter: conntrack: move expectation event helper to ecache.c
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Florian Westphal <fw@strlen.de>
Not performance critical, it is only invoked when an expectation is
added/destroyed.
While at it, kill unused nf_ct_expect_event() wrapper.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_conntrack_ecache.h | 42 +++--------------------------
net/netfilter/nf_conntrack_ecache.c | 30 +++++++++++++++++++++
2 files changed, 33 insertions(+), 39 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 019a5b8..fa36447 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -130,43 +130,9 @@ int nf_ct_expect_register_notifier(struct net *net,
void nf_ct_expect_unregister_notifier(struct net *net,
struct nf_exp_event_notifier *nb);
-static inline void
-nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
- struct nf_conntrack_expect *exp,
- u32 portid,
- int report)
-{
- struct net *net = nf_ct_exp_net(exp);
- struct nf_exp_event_notifier *notify;
- struct nf_conntrack_ecache *e;
-
- rcu_read_lock();
- notify = rcu_dereference(net->ct.nf_expect_event_cb);
- if (notify == NULL)
- goto out_unlock;
-
- e = nf_ct_ecache_find(exp->master);
- if (e == NULL)
- goto out_unlock;
-
- if (e->expmask & (1 << event)) {
- struct nf_exp_event item = {
- .exp = exp,
- .portid = portid,
- .report = report
- };
- notify->fcn(1 << event, &item);
- }
-out_unlock:
- rcu_read_unlock();
-}
-
-static inline void
-nf_ct_expect_event(enum ip_conntrack_expect_events event,
- struct nf_conntrack_expect *exp)
-{
- nf_ct_expect_event_report(event, exp, 0, 0);
-}
+void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp,
+ u32 portid, int report);
int nf_conntrack_ecache_pernet_init(struct net *net);
void nf_conntrack_ecache_pernet_fini(struct net *net);
@@ -203,8 +169,6 @@ static inline int nf_conntrack_event_report(enum ip_conntrack_events event,
u32 portid,
int report) { return 0; }
static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
-static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
- struct nf_conntrack_expect *exp) {}
static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
struct nf_conntrack_expect *exp,
u32 portid,
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index a0ebab9..d28011b 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -221,6 +221,36 @@ out_unlock:
}
EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
+void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp,
+ u32 portid, int report)
+
+{
+ struct net *net = nf_ct_exp_net(exp);
+ struct nf_exp_event_notifier *notify;
+ struct nf_conntrack_ecache *e;
+
+ rcu_read_lock();
+ notify = rcu_dereference(net->ct.nf_expect_event_cb);
+ if (!notify)
+ goto out_unlock;
+
+ e = nf_ct_ecache_find(exp->master);
+ if (!e)
+ goto out_unlock;
+
+ if (e->expmask & (1 << event)) {
+ struct nf_exp_event item = {
+ .exp = exp,
+ .portid = portid,
+ .report = report
+ };
+ notify->fcn(1 << event, &item);
+ }
+out_unlock:
+ rcu_read_unlock();
+}
+
int nf_conntrack_register_notifier(struct net *net,
struct nf_ct_event_notifier *new)
{
--
2.1.4
^ permalink raw reply related
* [PATCH 7/8] netfilter: conntrack: de-inline nf_conntrack_eventmask_report
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Florian Westphal <fw@strlen.de>
Way too large; move it to nf_conntrack_ecache.c.
Reduces total object size by 1216 byte on my machine.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_conntrack_ecache.h | 66 ++++++-----------------------
net/netfilter/nf_conntrack_ecache.c | 54 +++++++++++++++++++++++
2 files changed, 66 insertions(+), 54 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 57c8803..019a5b8 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -73,6 +73,8 @@ void nf_conntrack_unregister_notifier(struct net *net,
struct nf_ct_event_notifier *nb);
void nf_ct_deliver_cached_events(struct nf_conn *ct);
+int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
+ u32 portid, int report);
static inline void
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
@@ -91,69 +93,25 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
}
static inline int
-nf_conntrack_eventmask_report(unsigned int eventmask,
- struct nf_conn *ct,
- u32 portid,
- int report)
-{
- int ret = 0;
- struct net *net = nf_ct_net(ct);
- struct nf_ct_event_notifier *notify;
- struct nf_conntrack_ecache *e;
-
- rcu_read_lock();
- notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
- if (notify == NULL)
- goto out_unlock;
-
- e = nf_ct_ecache_find(ct);
- if (e == NULL)
- goto out_unlock;
-
- if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
- struct nf_ct_event item = {
- .ct = ct,
- .portid = e->portid ? e->portid : portid,
- .report = report
- };
- /* This is a resent of a destroy event? If so, skip missed */
- unsigned long missed = e->portid ? 0 : e->missed;
-
- if (!((eventmask | missed) & e->ctmask))
- goto out_unlock;
-
- ret = notify->fcn(eventmask | missed, &item);
- if (unlikely(ret < 0 || missed)) {
- spin_lock_bh(&ct->lock);
- if (ret < 0) {
- /* This is a destroy event that has been
- * triggered by a process, we store the PORTID
- * to include it in the retransmission. */
- if (eventmask & (1 << IPCT_DESTROY) &&
- e->portid == 0 && portid != 0)
- e->portid = portid;
- else
- e->missed |= eventmask;
- } else
- e->missed &= ~missed;
- spin_unlock_bh(&ct->lock);
- }
- }
-out_unlock:
- rcu_read_unlock();
- return ret;
-}
-
-static inline int
nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
u32 portid, int report)
{
+ const struct net *net = nf_ct_net(ct);
+
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
+ return 0;
+
return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
}
static inline int
nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
{
+ const struct net *net = nf_ct_net(ct);
+
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
+ return 0;
+
return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
}
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 4e78c57..a0ebab9 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -113,6 +113,60 @@ static void ecache_work(struct work_struct *work)
schedule_delayed_work(&ctnet->ecache_dwork, delay);
}
+int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
+ u32 portid, int report)
+{
+ int ret = 0;
+ struct net *net = nf_ct_net(ct);
+ struct nf_ct_event_notifier *notify;
+ struct nf_conntrack_ecache *e;
+
+ rcu_read_lock();
+ notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
+ if (!notify)
+ goto out_unlock;
+
+ e = nf_ct_ecache_find(ct);
+ if (!e)
+ goto out_unlock;
+
+ if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
+ struct nf_ct_event item = {
+ .ct = ct,
+ .portid = e->portid ? e->portid : portid,
+ .report = report
+ };
+ /* This is a resent of a destroy event? If so, skip missed */
+ unsigned long missed = e->portid ? 0 : e->missed;
+
+ if (!((eventmask | missed) & e->ctmask))
+ goto out_unlock;
+
+ ret = notify->fcn(eventmask | missed, &item);
+ if (unlikely(ret < 0 || missed)) {
+ spin_lock_bh(&ct->lock);
+ if (ret < 0) {
+ /* This is a destroy event that has been
+ * triggered by a process, we store the PORTID
+ * to include it in the retransmission.
+ */
+ if (eventmask & (1 << IPCT_DESTROY) &&
+ e->portid == 0 && portid != 0)
+ e->portid = portid;
+ else
+ e->missed |= eventmask;
+ } else {
+ e->missed &= ~missed;
+ }
+ spin_unlock_bh(&ct->lock);
+ }
+ }
+out_unlock:
+ rcu_read_unlock();
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_eventmask_report);
+
/* deliver cached events and clear cache entry - must be called with locally
* disabled softirqs */
void nf_ct_deliver_cached_events(struct nf_conn *ct)
--
2.1.4
^ permalink raw reply related
* [PATCH 5/8] netfilter: ip6t_SYNPROXY: remove magic number for hop_limit
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Liping Zhang <liping.zhang@spreadtrum.com>
Replace '64' with the per-net ipv6_devconf_all's hop_limit when
building the ipv6 header.
Signed-off-by: Liping Zhang <liping.zhang@spreadtrum.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv6/netfilter/ip6t_SYNPROXY.c | 56 ++++++++++++++++++++------------------
1 file changed, 30 insertions(+), 26 deletions(-)
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 3deed58..5d778dd 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -20,15 +20,16 @@
#include <net/netfilter/nf_conntrack_synproxy.h>
static struct ipv6hdr *
-synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr,
- const struct in6_addr *daddr)
+synproxy_build_ip(struct net *net, struct sk_buff *skb,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr)
{
struct ipv6hdr *iph;
skb_reset_network_header(skb);
iph = (struct ipv6hdr *)skb_put(skb, sizeof(*iph));
ip6_flow_hdr(iph, 0, 0);
- iph->hop_limit = 64; //XXX
+ iph->hop_limit = net->ipv6.devconf_all->hop_limit;
iph->nexthdr = IPPROTO_TCP;
iph->saddr = *saddr;
iph->daddr = *daddr;
@@ -37,13 +38,12 @@ synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr,
}
static void
-synproxy_send_tcp(const struct synproxy_net *snet,
+synproxy_send_tcp(struct net *net,
const struct sk_buff *skb, struct sk_buff *nskb,
struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo,
struct ipv6hdr *niph, struct tcphdr *nth,
unsigned int tcp_hdr_size)
{
- struct net *net = nf_ct_net(snet->tmpl);
struct dst_entry *dst;
struct flowi6 fl6;
@@ -84,7 +84,7 @@ free_nskb:
}
static void
-synproxy_send_client_synack(const struct synproxy_net *snet,
+synproxy_send_client_synack(struct net *net,
const struct sk_buff *skb, const struct tcphdr *th,
const struct synproxy_options *opts)
{
@@ -103,7 +103,7 @@ synproxy_send_client_synack(const struct synproxy_net *snet,
return;
skb_reserve(nskb, MAX_TCP_HEADER);
- niph = synproxy_build_ip(nskb, &iph->daddr, &iph->saddr);
+ niph = synproxy_build_ip(net, nskb, &iph->daddr, &iph->saddr);
skb_reset_transport_header(nskb);
nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
@@ -121,15 +121,16 @@ synproxy_send_client_synack(const struct synproxy_net *snet,
synproxy_build_options(nth, opts);
- synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
+ synproxy_send_tcp(net, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
niph, nth, tcp_hdr_size);
}
static void
-synproxy_send_server_syn(const struct synproxy_net *snet,
+synproxy_send_server_syn(struct net *net,
const struct sk_buff *skb, const struct tcphdr *th,
const struct synproxy_options *opts, u32 recv_seq)
{
+ struct synproxy_net *snet = synproxy_pernet(net);
struct sk_buff *nskb;
struct ipv6hdr *iph, *niph;
struct tcphdr *nth;
@@ -144,7 +145,7 @@ synproxy_send_server_syn(const struct synproxy_net *snet,
return;
skb_reserve(nskb, MAX_TCP_HEADER);
- niph = synproxy_build_ip(nskb, &iph->saddr, &iph->daddr);
+ niph = synproxy_build_ip(net, nskb, &iph->saddr, &iph->daddr);
skb_reset_transport_header(nskb);
nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
@@ -165,12 +166,12 @@ synproxy_send_server_syn(const struct synproxy_net *snet,
synproxy_build_options(nth, opts);
- synproxy_send_tcp(snet, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
+ synproxy_send_tcp(net, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
niph, nth, tcp_hdr_size);
}
static void
-synproxy_send_server_ack(const struct synproxy_net *snet,
+synproxy_send_server_ack(struct net *net,
const struct ip_ct_tcp *state,
const struct sk_buff *skb, const struct tcphdr *th,
const struct synproxy_options *opts)
@@ -189,7 +190,7 @@ synproxy_send_server_ack(const struct synproxy_net *snet,
return;
skb_reserve(nskb, MAX_TCP_HEADER);
- niph = synproxy_build_ip(nskb, &iph->daddr, &iph->saddr);
+ niph = synproxy_build_ip(net, nskb, &iph->daddr, &iph->saddr);
skb_reset_transport_header(nskb);
nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
@@ -205,11 +206,11 @@ synproxy_send_server_ack(const struct synproxy_net *snet,
synproxy_build_options(nth, opts);
- synproxy_send_tcp(snet, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
+ synproxy_send_tcp(net, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
}
static void
-synproxy_send_client_ack(const struct synproxy_net *snet,
+synproxy_send_client_ack(struct net *net,
const struct sk_buff *skb, const struct tcphdr *th,
const struct synproxy_options *opts)
{
@@ -227,7 +228,7 @@ synproxy_send_client_ack(const struct synproxy_net *snet,
return;
skb_reserve(nskb, MAX_TCP_HEADER);
- niph = synproxy_build_ip(nskb, &iph->saddr, &iph->daddr);
+ niph = synproxy_build_ip(net, nskb, &iph->saddr, &iph->daddr);
skb_reset_transport_header(nskb);
nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
@@ -243,15 +244,16 @@ synproxy_send_client_ack(const struct synproxy_net *snet,
synproxy_build_options(nth, opts);
- synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
+ synproxy_send_tcp(net, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
niph, nth, tcp_hdr_size);
}
static bool
-synproxy_recv_client_ack(const struct synproxy_net *snet,
+synproxy_recv_client_ack(struct net *net,
const struct sk_buff *skb, const struct tcphdr *th,
struct synproxy_options *opts, u32 recv_seq)
{
+ struct synproxy_net *snet = synproxy_pernet(net);
int mss;
mss = __cookie_v6_check(ipv6_hdr(skb), th, ntohl(th->ack_seq) - 1);
@@ -267,7 +269,7 @@ synproxy_recv_client_ack(const struct synproxy_net *snet,
if (opts->options & XT_SYNPROXY_OPT_TIMESTAMP)
synproxy_check_timestamp_cookie(opts);
- synproxy_send_server_syn(snet, skb, th, opts, recv_seq);
+ synproxy_send_server_syn(net, skb, th, opts, recv_seq);
return true;
}
@@ -275,7 +277,8 @@ static unsigned int
synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_synproxy_info *info = par->targinfo;
- struct synproxy_net *snet = synproxy_pernet(par->net);
+ struct net *net = par->net;
+ struct synproxy_net *snet = synproxy_pernet(net);
struct synproxy_options opts = {};
struct tcphdr *th, _th;
@@ -304,12 +307,12 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
XT_SYNPROXY_OPT_SACK_PERM |
XT_SYNPROXY_OPT_ECN);
- synproxy_send_client_synack(snet, skb, th, &opts);
+ synproxy_send_client_synack(net, skb, th, &opts);
return NF_DROP;
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
/* ACK from client */
- synproxy_recv_client_ack(snet, skb, th, &opts, ntohl(th->seq));
+ synproxy_recv_client_ack(net, skb, th, &opts, ntohl(th->seq));
return NF_DROP;
}
@@ -320,7 +323,8 @@ static unsigned int ipv6_synproxy_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *nhs)
{
- struct synproxy_net *snet = synproxy_pernet(nhs->net);
+ struct net *net = nhs->net;
+ struct synproxy_net *snet = synproxy_pernet(net);
enum ip_conntrack_info ctinfo;
struct nf_conn *ct;
struct nf_conn_synproxy *synproxy;
@@ -384,7 +388,7 @@ static unsigned int ipv6_synproxy_hook(void *priv,
* therefore we need to add 1 to make the SYN sequence
* number match the one of first SYN.
*/
- if (synproxy_recv_client_ack(snet, skb, th, &opts,
+ if (synproxy_recv_client_ack(net, skb, th, &opts,
ntohl(th->seq) + 1))
this_cpu_inc(snet->stats->cookie_retrans);
@@ -410,12 +414,12 @@ static unsigned int ipv6_synproxy_hook(void *priv,
XT_SYNPROXY_OPT_SACK_PERM);
swap(opts.tsval, opts.tsecr);
- synproxy_send_server_ack(snet, state, skb, th, &opts);
+ synproxy_send_server_ack(net, state, skb, th, &opts);
nf_ct_seqadj_init(ct, ctinfo, synproxy->isn - ntohl(th->seq));
swap(opts.tsval, opts.tsecr);
- synproxy_send_client_ack(snet, skb, th, &opts);
+ synproxy_send_client_ack(net, skb, th, &opts);
consume_skb(skb);
return NF_STOLEN;
--
2.1.4
^ permalink raw reply related
* [PATCH 3/8] netfilter: bridge: pass L2 header and VLAN as netlink attributes in queues to userspace
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Stephane Bryant <stephane.ml.bryant@gmail.com>
- This creates 2 netlink attribute NFQA_VLAN and NFQA_L2HDR.
- These are filled up for the PF_BRIDGE family on the way to userspace.
- NFQA_VLAN is a nested attribute, with the NFQA_VLAN_PROTO and the
NFQA_VLAN_TCI carrying the corresponding vlan_proto and vlan_tci
fields from the skb using big endian ordering (and using the CFI
bit as the VLAN_TAG_PRESENT flag in vlan_tci as in the skb)
Signed-off-by: Stephane Bryant <stephane.ml.bryant@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/uapi/linux/netfilter/nfnetlink_queue.h | 10 +++++
net/netfilter/nfnetlink_queue.c | 58 ++++++++++++++++++++++++++
2 files changed, 68 insertions(+)
diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h
index b67a853..ae30841 100644
--- a/include/uapi/linux/netfilter/nfnetlink_queue.h
+++ b/include/uapi/linux/netfilter/nfnetlink_queue.h
@@ -30,6 +30,14 @@ struct nfqnl_msg_packet_timestamp {
__aligned_be64 usec;
};
+enum nfqnl_vlan_attr {
+ NFQA_VLAN_UNSPEC,
+ NFQA_VLAN_PROTO, /* __be16 skb vlan_proto */
+ NFQA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */
+ __NFQA_VLAN_MAX,
+};
+#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX + 1)
+
enum nfqnl_attr_type {
NFQA_UNSPEC,
NFQA_PACKET_HDR,
@@ -50,6 +58,8 @@ enum nfqnl_attr_type {
NFQA_UID, /* __u32 sk uid */
NFQA_GID, /* __u32 sk gid */
NFQA_SECCTX, /* security context string */
+ NFQA_VLAN, /* nested attribute: packet vlan info */
+ NFQA_L2HDR, /* full L2 header */
__NFQA_MAX
};
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7542999..6889c7c 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -295,6 +295,59 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
return seclen;
}
+static u32 nfqnl_get_bridge_size(struct nf_queue_entry *entry)
+{
+ struct sk_buff *entskb = entry->skb;
+ u32 nlalen = 0;
+
+ if (entry->state.pf != PF_BRIDGE || !skb_mac_header_was_set(entskb))
+ return 0;
+
+ if (skb_vlan_tag_present(entskb))
+ nlalen += nla_total_size(nla_total_size(sizeof(__be16)) +
+ nla_total_size(sizeof(__be16)));
+
+ if (entskb->network_header > entskb->mac_header)
+ nlalen += nla_total_size((entskb->network_header -
+ entskb->mac_header));
+
+ return nlalen;
+}
+
+static int nfqnl_put_bridge(struct nf_queue_entry *entry, struct sk_buff *skb)
+{
+ struct sk_buff *entskb = entry->skb;
+
+ if (entry->state.pf != PF_BRIDGE || !skb_mac_header_was_set(entskb))
+ return 0;
+
+ if (skb_vlan_tag_present(entskb)) {
+ struct nlattr *nest;
+
+ nest = nla_nest_start(skb, NFQA_VLAN | NLA_F_NESTED);
+ if (!nest)
+ goto nla_put_failure;
+
+ if (nla_put_be16(skb, NFQA_VLAN_TCI, htons(entskb->vlan_tci)) ||
+ nla_put_be16(skb, NFQA_VLAN_PROTO, entskb->vlan_proto))
+ goto nla_put_failure;
+
+ nla_nest_end(skb, nest);
+ }
+
+ if (entskb->mac_header < entskb->network_header) {
+ int len = (int)(entskb->network_header - entskb->mac_header);
+
+ if (nla_put(skb, NFQA_L2HDR, len, skb_mac_header(entskb)))
+ goto nla_put_failure;
+ }
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
static struct sk_buff *
nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
struct nf_queue_entry *entry,
@@ -334,6 +387,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
if (entskb->tstamp.tv64)
size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
+ size += nfqnl_get_bridge_size(entry);
+
if (entry->state.hook <= NF_INET_FORWARD ||
(entry->state.hook == NF_INET_POST_ROUTING && entskb->sk == NULL))
csum_verify = !skb_csum_unnecessary(entskb);
@@ -497,6 +552,9 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
}
+ if (nfqnl_put_bridge(entry, skb) < 0)
+ goto nla_put_failure;
+
if (entskb->tstamp.tv64) {
struct nfqnl_msg_packet_timestamp ts;
struct timespec64 kts = ktime_to_timespec64(skb->tstamp);
--
2.1.4
^ permalink raw reply related
* [PATCH 2/8] netfilter: bridge: add nf_afinfo to enable queuing to userspace
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Stephane Bryant <stephane.ml.bryant@gmail.com>
This just adds and registers a nf_afinfo for the ethernet
bridge, which enables queuing to userspace for the AF_BRIDGE
family. No checksum computation is done.
Signed-off-by: Stephane Bryant <stephane.ml.bryant@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/bridge/netfilter/nf_tables_bridge.c | 47 +++++++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index 7fcdd72..a78c4e2 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -162,15 +162,57 @@ static const struct nf_chain_type filter_bridge = {
(1 << NF_BR_POST_ROUTING),
};
+static void nf_br_saveroute(const struct sk_buff *skb,
+ struct nf_queue_entry *entry)
+{
+}
+
+static int nf_br_reroute(struct net *net, struct sk_buff *skb,
+ const struct nf_queue_entry *entry)
+{
+ return 0;
+}
+
+static __sum16 nf_br_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol)
+{
+ return 0;
+}
+
+static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, unsigned int len,
+ u_int8_t protocol)
+{
+ return 0;
+}
+
+static int nf_br_route(struct net *net, struct dst_entry **dst,
+ struct flowi *fl, bool strict __always_unused)
+{
+ return 0;
+}
+
+static const struct nf_afinfo nf_br_afinfo = {
+ .family = AF_BRIDGE,
+ .checksum = nf_br_checksum,
+ .checksum_partial = nf_br_checksum_partial,
+ .route = nf_br_route,
+ .saveroute = nf_br_saveroute,
+ .reroute = nf_br_reroute,
+ .route_key_size = 0,
+};
+
static int __init nf_tables_bridge_init(void)
{
int ret;
+ nf_register_afinfo(&nf_br_afinfo);
nft_register_chain_type(&filter_bridge);
ret = register_pernet_subsys(&nf_tables_bridge_net_ops);
- if (ret < 0)
+ if (ret < 0) {
nft_unregister_chain_type(&filter_bridge);
-
+ nf_unregister_afinfo(&nf_br_afinfo);
+ }
return ret;
}
@@ -178,6 +220,7 @@ static void __exit nf_tables_bridge_exit(void)
{
unregister_pernet_subsys(&nf_tables_bridge_net_ops);
nft_unregister_chain_type(&filter_bridge);
+ nf_unregister_afinfo(&nf_br_afinfo);
}
module_init(nf_tables_bridge_init);
--
2.1.4
^ permalink raw reply related
* [PATCH 1/8] netfilter: nf_conntrack: Uses pr_fmt() for logging.
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Weongyo Jeong <weongyo.linux@gmail.com>
Uses pr_fmt() macro for debugging messages of nf_conntrack module.
Signed-off-by: Weongyo Jeong <weongyo.linux@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_conntrack_core.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index afde5f5..2fd6074 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -12,6 +12,8 @@
* published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/types.h>
#include <linux/netfilter.h>
#include <linux/module.h>
@@ -966,7 +968,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
if (!l4proto->new(ct, skb, dataoff, timeouts)) {
nf_conntrack_free(ct);
- pr_debug("init conntrack: can't track with proto module\n");
+ pr_debug("can't track with proto module\n");
return NULL;
}
@@ -988,7 +990,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
spin_lock(&nf_conntrack_expect_lock);
exp = nf_ct_find_expectation(net, zone, tuple);
if (exp) {
- pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
+ pr_debug("expectation arrives ct=%p exp=%p\n",
ct, exp);
/* Welcome, Mr. Bond. We've been expecting you... */
__set_bit(IPS_EXPECTED_BIT, &ct->status);
@@ -1053,7 +1055,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
dataoff, l3num, protonum, net, &tuple, l3proto,
l4proto)) {
- pr_debug("resolve_normal_ct: Can't get tuple\n");
+ pr_debug("Can't get tuple\n");
return NULL;
}
@@ -1079,14 +1081,13 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
} else {
/* Once we've had two way comms, always ESTABLISHED. */
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
- pr_debug("nf_conntrack_in: normal packet for %p\n", ct);
+ pr_debug("normal packet for %p\n", ct);
*ctinfo = IP_CT_ESTABLISHED;
} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
- pr_debug("nf_conntrack_in: related packet for %p\n",
- ct);
+ pr_debug("related packet for %p\n", ct);
*ctinfo = IP_CT_RELATED;
} else {
- pr_debug("nf_conntrack_in: new packet for %p\n", ct);
+ pr_debug("new packet for %p\n", ct);
*ctinfo = IP_CT_NEW;
}
*set_reply = 0;
--
2.1.4
^ permalink raw reply related
* [PATCH 6/8] netfilter: ipv6: unnecessary to check whether ip6_route_output() returns NULL
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
ip6_route_output() never returns NULL, so it is not appropriate to
check if the return value is NULL.
Signed-off-by: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv6/netfilter/nf_reject_ipv6.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
index 4709f65..a540022 100644
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -158,7 +158,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
fl6.fl6_dport = otcph->source;
security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
dst = ip6_route_output(net, NULL, &fl6);
- if (dst == NULL || dst->error) {
+ if (dst->error) {
dst_release(dst);
return;
}
--
2.1.4
^ permalink raw reply related
* [PATCH 4/8] netfilter: bridge: nf queue verdict to use NFQA_VLAN and NFQA_L2HDR
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460502166-20340-1-git-send-email-pablo@netfilter.org>
From: Stephane Bryant <stephane.ml.bryant@gmail.com>
This makes nf queues use NFQA_VLAN and NFQA_L2HDR in verdict to modify the
original skb
Signed-off-by: Stephane Bryant <stephane.ml.bryant@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nfnetlink_queue.c | 47 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 6889c7c..5bebe78 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -964,12 +964,18 @@ static struct notifier_block nfqnl_rtnl_notifier = {
.notifier_call = nfqnl_rcv_nl_event,
};
+static const struct nla_policy nfqa_vlan_policy[NFQA_VLAN_MAX + 1] = {
+ [NFQA_VLAN_TCI] = { .type = NLA_U16},
+ [NFQA_VLAN_PROTO] = { .type = NLA_U16},
+};
+
static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
[NFQA_VERDICT_HDR] = { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
[NFQA_MARK] = { .type = NLA_U32 },
[NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
[NFQA_CT] = { .type = NLA_UNSPEC },
[NFQA_EXP] = { .type = NLA_UNSPEC },
+ [NFQA_VLAN] = { .type = NLA_NESTED },
};
static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
@@ -1083,6 +1089,40 @@ static struct nf_conn *nfqnl_ct_parse(struct nfnl_ct_hook *nfnl_ct,
return ct;
}
+static int nfqa_parse_bridge(struct nf_queue_entry *entry,
+ const struct nlattr * const nfqa[])
+{
+ if (nfqa[NFQA_VLAN]) {
+ struct nlattr *tb[NFQA_VLAN_MAX + 1];
+ int err;
+
+ err = nla_parse_nested(tb, NFQA_VLAN_MAX, nfqa[NFQA_VLAN],
+ nfqa_vlan_policy);
+ if (err < 0)
+ return err;
+
+ if (!tb[NFQA_VLAN_TCI] || !tb[NFQA_VLAN_PROTO])
+ return -EINVAL;
+
+ entry->skb->vlan_tci = ntohs(nla_get_be16(tb[NFQA_VLAN_TCI]));
+ entry->skb->vlan_proto = nla_get_be16(tb[NFQA_VLAN_PROTO]);
+ }
+
+ if (nfqa[NFQA_L2HDR]) {
+ int mac_header_len = entry->skb->network_header -
+ entry->skb->mac_header;
+
+ if (mac_header_len != nla_len(nfqa[NFQA_L2HDR]))
+ return -EINVAL;
+ else if (mac_header_len > 0)
+ memcpy(skb_mac_header(entry->skb),
+ nla_data(nfqa[NFQA_L2HDR]),
+ mac_header_len);
+ }
+
+ return 0;
+}
+
static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl,
struct sk_buff *skb,
const struct nlmsghdr *nlh,
@@ -1098,6 +1138,7 @@ static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl,
struct nfnl_ct_hook *nfnl_ct;
struct nf_conn *ct = NULL;
struct nfnl_queue_net *q = nfnl_queue_pernet(net);
+ int err;
queue = instance_lookup(q, queue_num);
if (!queue)
@@ -1124,6 +1165,12 @@ static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl,
ct = nfqnl_ct_parse(nfnl_ct, nlh, nfqa, entry, &ctinfo);
}
+ if (entry->state.pf == PF_BRIDGE) {
+ err = nfqa_parse_bridge(entry, nfqa);
+ if (err < 0)
+ return err;
+ }
+
if (nfqa[NFQA_PAYLOAD]) {
u16 payload_len = nla_len(nfqa[NFQA_PAYLOAD]);
int diff = payload_len - entry->skb->len;
--
2.1.4
^ permalink raw reply related
* [PATCH 0/8] Netfilter updates for net-next
From: Pablo Neira Ayuso @ 2016-04-12 23:02 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Hi David,
The following patchset contains the first batch of Netfilter updates for
your net-next tree.
1) Define pr_fmt() in nf_conntrack, from Weongyo Jeong.
2) Define and register netfilter's afinfo for the bridge family,
this comes in preparation for native nfqueue's bridge for nft,
from Stephane Bryant.
3) Add new attributes to store layer 2 and VLAN headers to nfqueue,
also from Stephane Bryant.
4) Parse new NFQA_VLAN and NFQA_L2HDR nfqueue netlink attributes
coming from userspace, from Stephane Bryant.
5) Use net->ipv6.devconf_all->hop_limit instead of hardcoded hop_limit
in IPv6 SYNPROXY, from Liping Zhang.
6) Remove unnecessary check for dst == NULL in nf_reject_ipv6,
from Haishuang Yan.
7) Deinline ctnetlink event report functions, from Florian Westphal.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Thanks!
----------------------------------------------------------------
The following changes since commit e46b4e2b46e173889b19999b8bd033d5e8b3acf0:
Merge tag 'trace-v4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace (2016-03-24 10:52:25 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git HEAD
for you to fetch changes up to ecdfb48cddfd1096343148113d5b1bd789033aa8:
netfilter: conntrack: move expectation event helper to ecache.c (2016-04-12 23:01:57 +0200)
----------------------------------------------------------------
Florian Westphal (2):
netfilter: conntrack: de-inline nf_conntrack_eventmask_report
netfilter: conntrack: move expectation event helper to ecache.c
Haishuang Yan (1):
netfilter: ipv6: unnecessary to check whether ip6_route_output() returns NULL
Liping Zhang (1):
netfilter: ip6t_SYNPROXY: remove magic number for hop_limit
Stephane Bryant (3):
netfilter: bridge: add nf_afinfo to enable queuing to userspace
netfilter: bridge: pass L2 header and VLAN as netlink attributes in queues to userspace
netfilter: bridge: nf queue verdict to use NFQA_VLAN and NFQA_L2HDR
Weongyo Jeong (1):
netfilter: nf_conntrack: Uses pr_fmt() for logging.
include/net/netfilter/nf_conntrack_ecache.h | 108 ++++---------------------
include/uapi/linux/netfilter/nfnetlink_queue.h | 10 +++
net/bridge/netfilter/nf_tables_bridge.c | 47 ++++++++++-
net/ipv6/netfilter/ip6t_SYNPROXY.c | 56 +++++++------
net/ipv6/netfilter/nf_reject_ipv6.c | 2 +-
net/netfilter/nf_conntrack_core.c | 15 ++--
net/netfilter/nf_conntrack_ecache.c | 84 +++++++++++++++++++
net/netfilter/nfnetlink_queue.c | 105 ++++++++++++++++++++++++
8 files changed, 298 insertions(+), 129 deletions(-)
^ permalink raw reply
* Re: Issue with ping source address display
From: 吉藤英明 @ 2016-04-12 22:59 UTC (permalink / raw)
To: Daniele Orlandi; +Cc: network dev
In-Reply-To: <570D35CF.9070006@orlandi.com>
Hi,
2016-04-13 2:52 GMT+09:00 Daniele Orlandi <daniele@orlandi.com>:
>
> Hello,
>
> More than one year ago I posted the following message but it hasn't
> received a reply, now I've been stung by a similar issue, you may want
> to investigate:
>
>
> I noticed that when ping receives ICMP messages from different sources
> the first IP address is always used and displayed:
>
>
> vihai@seviolab:~$ ping -V
> ping utility, iputils-s20121221
>
> This is a (simulated) flapping route:
>
> vihai@seviolab:~$ ping 10.254.10.140
> PING 10.254.10.140 (10.254.10.140) 56(84) bytes of data.
> From 192.168.1.1 icmp_seq=1 Destination Host Unreachable
> From 192.168.1.1 icmp_seq=2 Destination Host Unreachable
> From 192.168.1.1 icmp_seq=3 Destination Host Unreachable
> 64 bytes from 192.168.1.1: icmp_seq=4 ttl=61 time=24.7 ms
> 64 bytes from 192.168.1.1: icmp_seq=5 ttl=61 time=25.6 ms
> 64 bytes from 192.168.1.1: icmp_seq=6 ttl=61 time=69.6 ms
> From 192.168.1.1 icmp_seq=7 Destination Host Unreachable
> From 192.168.1.1 icmp_seq=8 Destination Host Unreachable
> From 192.168.1.1 icmp_seq=9 Destination Host Unreachable
> ^C
> --- 10.254.10.140 ping statistics ---
> 9 packets transmitted, 3 received, +6 errors, 66% packet loss, time 8001ms
> rtt min/avg/max/mdev = 24.797/40.061/69.692/20.955 ms
>
>
> The sources, however are different:
>
> vihai@seviolab:~$ sudo tcpdump -n icmp
> tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
> listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
> ^[OA^[OA^[OA17:09:55.932981 IP 192.168.1.21 > 10.254.10.140: ICMP echo
> request, id 9278, seq 1, length 64
> 17:09:55.933234 IP 192.168.1.1 > 192.168.1.21: ICMP host 10.254.10.140
> unreachable, length 92
> 17:09:56.933169 IP 192.168.1.21 > 10.254.10.140: ICMP echo request, id
> 9278, seq 2, length 64
> 17:09:56.933416 IP 192.168.1.1 > 192.168.1.21: ICMP host 10.254.10.140
> unreachable, length 92
> 17:09:57.933160 IP 192.168.1.21 > 10.254.10.140: ICMP echo request, id
> 9278, seq 3, length 64
> 17:09:57.933404 IP 192.168.1.1 > 192.168.1.21: ICMP host 10.254.10.140
> unreachable, length 92
> 17:09:58.933163 IP 192.168.1.21 > 10.254.10.140: ICMP echo request, id
> 9278, seq 4, length 64
> 17:09:58.957939 IP 10.254.10.140 > 192.168.1.21: ICMP echo reply, id
> 9278, seq 4, length 64
> 17:09:59.935050 IP 192.168.1.21 > 10.254.10.140: ICMP echo request, id
> 9278, seq 5, length 64
> 17:09:59.960724 IP 10.254.10.140 > 192.168.1.21: ICMP echo reply, id
> 9278, seq 5, length 64
> 17:10:00.936177 IP 192.168.1.21 > 10.254.10.140: ICMP echo request, id
> 9278, seq 6, length 64
> 17:10:01.005849 IP 10.254.10.140 > 192.168.1.21: ICMP echo reply, id
> 9278, seq 6, length 64
> 17:10:01.936313 IP 192.168.1.21 > 10.254.10.140: ICMP echo request, id
> 9278, seq 7, length 64
> 17:10:01.936626 IP 192.168.1.1 > 192.168.1.21: ICMP host 10.254.10.140
> unreachable, length 92
> 17:10:02.935321 IP 192.168.1.21 > 10.254.10.140: ICMP echo request, id
> 9278, seq 8, length 64
> 17:10:02.935591 IP 192.168.1.1 > 192.168.1.21: ICMP host 10.254.10.140
> unreachable, length 92
> 17:10:03.934322 IP 192.168.1.21 > 10.254.10.140: ICMP echo request, id
> 9278, seq 9, length 64
> 17:10:03.934613 IP 192.168.1.1 > 192.168.1.21: ICMP host 10.254.10.140
> unreachable, length 92
>
Thank you for your report. I'll try fixing it.
--yoshfuji
>
>
>
> Tried with a different ping implementation (RouterOS) and the behaviour
> seems correct:
>
> [vihai@SevioLab SW1] > ping 10.254.10.140
> HOST SIZE TTL TIME STATUS
> 192.168.1.1 84 64 0ms host unreachable
> 192.168.1.1 84 64 0ms host unreachable
> 192.168.1.1 84 64 0ms host unreachable
> 10.254.10.140 56 61 20ms
> 10.254.10.140 56 61 46ms
> 10.254.10.140 56 61 37ms
> 192.168.1.1 84 64 0ms host unreachable
> 192.168.1.1 84 64 0ms host unreachable
> 192.168.1.1 84 64 0ms host unreachable
> sent=9 received=3 packet-loss=66% min-rtt=20ms avg-rtt=34ms max-rtt=46ms
>
>
> Recently I was pinging with IPv6, a router in between filtered the
> packet, however the shown source address was not the right one:
>
> root@monitor:~# ping6 -i 0.2 www.google.com
> PING www.google.com(mil01s25-in-x04.1e100.net) 56 data bytes
> From mil01s25-in-x04.1e100.net icmp_seq=1 Destination unreachable: No route
> From mil01s25-in-x04.1e100.net icmp_seq=2 Destination unreachable: No route
> From mil01s25-in-x04.1e100.net icmp_seq=3 Destination unreachable: No route
>
> 19:33:19.589285 IP6 2a01:2d8:aca0:fce:944e:c8ff:fe4d:96de >
> mil01s25-in-x04.1e100.net: ICMP6, echo request, seq 1, length 64
> 19:33:19.611666 IP6 mix-br2.intercom.it >
> 2a01:2d8:aca0:fce:944e:c8ff:fe4d:96de: ICMP6, destination unreachable,
> unreachable route mil01s25-in-x04.1e100.net, length 112
>
>
> Bye,
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox