* Re: [PATCH net-next] tcp: add ability to set a timestamp offset
From: Rick Jones @ 2013-01-22 21:16 UTC (permalink / raw)
To: Andrey Vagin
Cc: netdev, criu, linux-kernel, David S. Miller, Alexey Kuznetsov,
James Morris, Hideaki YOSHIFUJI, Patrick McHardy, Eric Dumazet,
Yuchung Cheng, Neal Cardwell, Pavel Emelyanov, Dave Jones,
Michael Kerrisk
In-Reply-To: <1358887953-28665-1-git-send-email-avagin@openvz.org>
On 01/22/2013 12:52 PM, Andrey Vagin wrote:
> If a TCP socket will get live-migrated from one box to another the
> timestamps (which are typically ON) will get screwed up -- the new
> kernel will generate TS values that has nothing to do with what they
> were on dump. The solution is to yet again fix the kernel and put a
> "timestamp offset" on a socket.
Is there a chance a connection can be moved more than once within the
"lifetime" of a given timestamp value?
rick jones
^ permalink raw reply
* Re: [PATCH] ethtool: Fix space-after-if checkpatch errors
From: Ben Hutchings @ 2013-01-22 21:15 UTC (permalink / raw)
To: Mark Einon; +Cc: netdev
In-Reply-To: <1358888690-3140-1-git-send-email-mark.einon@gmail.com>
On Tue, 2013-01-22 at 21:04 +0000, Mark Einon wrote:
> Some version check statements are lacking a space after the if ()
> statement. Add them in.
>
> Signed-off-by: Mark Einon <mark.einon@gmail.com>
[...]
OK, I've applied this on top of your earlier patch.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH ethtool] rxclass: Show full 64 bits of user-data in rxclass_print_nfc_spec_ext()
From: Alexander Duyck @ 2013-01-22 21:07 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev
In-Reply-To: <1358886835.2892.14.camel@bwh-desktop.uk.solarflarecom.com>
On 01/22/2013 12:33 PM, Ben Hutchings wrote:
> Previously only the lower 32 bits would be shown.
>
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
> ---
> I just noticed this bug when applying Yan Burman's patch. Untested
> since sfc doesn't support this field.
>
> Ben.
>
> rxclass.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/rxclass.c b/rxclass.c
> index 1564b62..cd686a3 100644
> --- a/rxclass.c
> +++ b/rxclass.c
> @@ -49,7 +49,7 @@ static void rxclass_print_nfc_spec_ext(struct ethtool_rx_flow_spec *fsp)
> tci = ntohs(fsp->h_ext.vlan_tci);
> tcim = ntohs(~fsp->m_ext.vlan_tci);
> data = (u64)ntohl(fsp->h_ext.data[0]) << 32;
> - data = (u64)ntohl(fsp->h_ext.data[1]);
> + data |= (u64)ntohl(fsp->h_ext.data[1]);
> datam = (u64)ntohl(~fsp->m_ext.data[0]) << 32;
> datam |= (u64)ntohl(~fsp->m_ext.data[1]);
>
>
This looks fine to me. We didn't use data[0] in ixgbe so we never
noticed this either.
Acked-by: Alexander Duyck <alexander.h.duyck@intel.com>
^ permalink raw reply
* [PATCH] ethtool: Fix space-after-if checkpatch errors
From: Mark Einon @ 2013-01-22 21:04 UTC (permalink / raw)
To: bhutchings; +Cc: netdev, Mark Einon
Some version check statements are lacking a space after the if ()
statement. Add them in.
Signed-off-by: Mark Einon <mark.einon@gmail.com>
---
e100.c | 2 +-
e1000.c | 2 +-
et131x.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/e100.c b/e100.c
index 65627ab..b982e79 100644
--- a/e100.c
+++ b/e100.c
@@ -46,7 +46,7 @@ e100_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
u32 reg;
u16 scb_status, scb_cmd;
- if(version != 1)
+ if (version != 1)
return -1;
reg = regs_buff[0];
diff --git a/e1000.c b/e1000.c
index d1d3c73..dd47774 100644
--- a/e1000.c
+++ b/e1000.c
@@ -374,7 +374,7 @@ e1000_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
enum e1000_mac_type mac_type;
u32 reg;
- if(version != 1)
+ if (version != 1)
return -1;
mac_type = e1000_get_mac_type(hw_device_id, hw_revision_id);
diff --git a/et131x.c b/et131x.c
index 8cdbec0..36abaa2 100644
--- a/et131x.c
+++ b/et131x.c
@@ -7,7 +7,7 @@ int et131x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
u8 version = (u8)(regs->version >> 24);
u32 *reg = (u32 *)regs->data;
- if(version != 1)
+ if (version != 1)
return -1;
fprintf(stdout, "PHY Registers\n");
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] ethtool: Add version check for et131x regs
From: Mark Einon @ 2013-01-22 21:03 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev
In-Reply-To: <1358887479.2892.22.camel@bwh-desktop.uk.solarflarecom.com>
On 22 January 2013 20:44, Ben Hutchings <bhutchings@solarflare.com> wrote:
> On Sat, 2013-01-05 at 09:57 +0000, Mark Einon wrote:
>> Added a version check for the et131x reg dump, in case the dump format
>> needs to be changed later.
>>
>> Signed-off-by: Mark Einon <mark.einon@gmail.com>
>> ---
>> et131x.c | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/et131x.c b/et131x.c
>> index b36c184..8cdbec0 100644
>> --- a/et131x.c
>> +++ b/et131x.c
>> @@ -4,8 +4,12 @@
>>
>> int et131x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
>> {
>> + u8 version = (u8)(regs->version >> 24);
>> u32 *reg = (u32 *)regs->data;
>>
>> + if(version != 1)
>
> Needs a space before the open-parentheis.
>
> Ben.
You're right - I cut and pasted the code from another file without
checking. I'll send a separate patch for fixing them, if you want this
patch re-submitted as well, then just let me know.
cheers,
Mark
>
>> + return -1;
>> +
>> fprintf(stdout, "PHY Registers\n");
>> fprintf(stdout, "0x0, Basic Control Reg = 0x%04X\n", *reg++);
>> fprintf(stdout, "0x1, Basic Status Reg = 0x%04X\n", *reg++);
>
> --
> Ben Hutchings, Staff Engineer, Solarflare
> Not speaking for my employer; that's the marketing department's job.
> They asked us to note that Solarflare product names are trademarked.
>
^ permalink raw reply
* Re: [PATCH net-next 09/15] drivers/net: delete old 8 bit ISA Racal ni5010 support.
From: Ondrej Zary @ 2013-01-22 20:55 UTC (permalink / raw)
To: Jan-Pascal van Best; +Cc: Paul Gortmaker, David Miller, netdev, Andreas Mohr
In-Reply-To: <50FEEF92.3000809@vanbest.org>
On Tuesday 22 January 2013 20:59:14 Jan-Pascal van Best wrote:
> Hi Paul,
>
> Although for me personally it'll be a shock not be able to run the latest
> kernel on my legacy system I keep up especially for this ISA card, Andreas
> and I cannot seriously oppose removing this driver from the mainline
> kernel. It's probably more than a decade and a half ago since anyone used
> an NI5010 in production, which makes it time to move on...
>
> By the way, Andreas promises to keep his stable of NI5010 cards forever,
> and still has a BNC network in active (if loathed!) service.
I have BNC network too and use it every day. It's mostly used for internet
access, with 3c509 and ne2000 cards (one of the machines has currently uptime
of 439 days, it runs kernel 3.1). I remember using HP pclan cards too and
they worked fine. Too bad they're going away :(
Also got a nice 3c503 card a year ago or so. The driver worked fine after a
simple fix.
I really hate when a working driver is removed from Linux. New drivers are
either missing (alx) or problematic (various rtl8168/8169 variants, some of
which work and some don't). So you can't get any new machine and install
Linux. You also can't get any old machine and install Linux. If you're lucky
and the machine is somehow middle-aged, everything might work...
--
Ondrej Zary
^ permalink raw reply
* Re: Bug#697357: bridging broken over bond interfaces
From: Ferenc Wagner @ 2013-01-22 20:20 UTC (permalink / raw)
To: Ben Hutchings
Cc: netdev, Bastian Blank, 697357, Peter Palfrader, Stephen Hemminger,
Jay Vosburgh, Andy Gospodarek, wferi
In-Reply-To: <1357534704.26822.6.camel@deadeye.wl.decadent.org.uk>
Ben Hutchings <ben@decadent.org.uk> writes:
> Forwarding this to netdev since the bug is still present in Linux 3.7.1.
> For those joining us, this thread is archive at
> <http://bugs.debian.org/697357>.
Please forgive me for eliding the previous discussion; I think I hit the
same or a very similar problem in the same setup, but without the KVM or
guest parts (but I could reproduce this in a pretty bare KVM guest with
a virtio network device). My interface configuration (hopefully
comprehensible without familiarity with Debian):
# this is a bare bond interface named after the native VLAN (no .1q!)
auto vlan894
iface vlan894 inet manual
bond_mode active-backup
bond_slaves eth0
bond_miimon 100
bond_updelay 4000
# this bridge has a static IPv4 address and contains the above bond
auto br894
iface br894 inet static
bridge_ports vlan894
bridge_stp off
bridge_fd 0
address x.y.z.w
netmask 255.255.255.0
gateway x.y.z.g
Actually, I want ARP monitoring for the bond, but if I leave out either
the miimon *or* the updelay configuration, the machine stops responding
to solicited-node multicast packages (neighbor solicitations) thus
becoming unreachable via its autoconfigured global IPv6 address. That
is, until I put eth0 into promiscuous mode! And really, with the above
(working) config dmesg says:
bonding: Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)
bonding: vlan894 is being created...
bonding: vlan894: Setting MII monitoring interval to 100.
bonding: vlan894: Setting up delay to 4000.
bonding: vlan894: setting mode to active-backup (1).
bonding: vlan894: Adding slave eth0.
bonding: vlan894: enslaving eth0 as a backup interface with an up link.
Bridge firewalling registered
device vlan894 entered promiscuous mode
IPv6: ADDRCONF(NETDEV_UP): vlan894: link is not ready
bonding: vlan894: link status definitely up for interface eth0, 4294967295 Mbps full duplex.
bonding: vlan894: making interface eth0 the new active one.
device eth0 entered promiscuous mode
bonding: vlan894: first active interface up!
IPv6: ADDRCONF(NETDEV_CHANGE): vlan894: link becomes ready
br894: port 1(vlan894) entered forwarding state
br894: port 1(vlan894) entered forwarding state
(although ip link does not list any promiscuous interfaces). On the
other hand, if I don't configure eg. bond_updelay:
bonding: Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)
bonding: vlan894 is being created...
bonding: vlan894: Setting MII monitoring interval to 100.
bonding: vlan894: setting mode to active-backup (1).
bonding: vlan894: Adding slave eth0.
bonding: vlan894: making interface eth0 the new active one.
bonding: vlan894: first active interface up!
bonding: vlan894: enslaving eth0 as an active interface with an up link.
Bridge firewalling registered
device vlan894 entered promiscuous mode
br894: port 1(vlan894) entered forwarding state
br894: port 1(vlan894) entered forwarding state
ie. promiscuous mode isn't propageted to eth0 and the global IPv6
address of the machine does not respond to ping6 until tcpdump -i eth0
or ip link set eth0 promisc on. Meanwhile in all cases:
# ip maddr show dev br894
5: br894
link 33:33:00:00:00:01
link 01:00:5e:00:00:01
link 33:33:ff:02:00:07
inet 224.0.0.1
inet6 ff02::1:ff02:7 users 2
inet6 ff02::1
This happens with the current 3.7.3-1~experimental.1 amd64 kernel under
Debian wheezy (besides the current 3.2 wheezy kernel).
--
Thanks for your time,
Feri.
^ permalink raw reply
* Re: [PATCH v5 01/45] percpu_rwlock: Introduce the global reader-writer lock backend
From: Steven Rostedt @ 2013-01-22 20:54 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: linux-doc, peterz, fweisbec, linux-kernel, mingo, linux-arch,
linux, xiaoguangrong, wangyun, paulmck, nikunj, linux-pm, rusty,
rjw, namhyung, tglx, linux-arm-kernel, netdev, oleg, sbw, tj,
akpm, linuxppc-dev
In-Reply-To: <50FEEF5D.6080302@linux.vnet.ibm.com>
On Wed, 2013-01-23 at 01:28 +0530, Srivatsa S. Bhat wrote:
> > I thought global locks are now fair. That is, a reader will block if a
> > writer is waiting. Hence, the above should deadlock on the current
> > rwlock_t types.
> >
>
> Oh is it? Last I checked, lockdep didn't complain about this ABBA scenario!
It doesn't and Peter Zijlstra said we need to fix that ;-) It only
recently became an issue with the new "fair" locking of rwlocks.
-- Steve
^ permalink raw reply
* [PATCH net-next] tcp: add ability to set a timestamp offset
From: Andrey Vagin @ 2013-01-22 20:52 UTC (permalink / raw)
To: netdev
Cc: criu, linux-kernel, Andrey Vagin, David S. Miller,
Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
Patrick McHardy, Eric Dumazet, Yuchung Cheng, Neal Cardwell,
Pavel Emelyanov, Dave Jones, Michael Kerrisk
If a TCP socket will get live-migrated from one box to another the
timestamps (which are typically ON) will get screwed up -- the new
kernel will generate TS values that has nothing to do with what they
were on dump. The solution is to yet again fix the kernel and put a
"timestamp offset" on a socket.
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Dave Jones <davej@redhat.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
include/linux/tcp.h | 2 ++
include/uapi/linux/tcp.h | 1 +
net/ipv4/tcp.c | 6 ++++++
net/ipv4/tcp_output.c | 7 ++++---
4 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 4e1d228..746dad5 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -162,6 +162,8 @@ struct tcp_sock {
u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
u32 lsndtime; /* timestamp of last sent data packet (for restart window) */
+ u32 snd_tsval_offset; /* offset for snd_tsval */
+
struct list_head tsq_node; /* anchor in tsq_tasklet.head list */
unsigned long tsq_flags;
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index e962faa..6b1ead0 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -111,6 +111,7 @@ enum {
#define TCP_QUEUE_SEQ 21
#define TCP_REPAIR_OPTIONS 22
#define TCP_FASTOPEN 23 /* Enable FastOpen on listeners */
+#define TCP_TIMESTAMP 24
struct tcp_repair_opt {
__u32 opt_code;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 1ca2536..72dee28 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2704,6 +2704,9 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
else
err = -EINVAL;
break;
+ case TCP_TIMESTAMP:
+ tp->snd_tsval_offset = val - tcp_time_stamp;
+ break;
default:
err = -ENOPROTOOPT;
break;
@@ -2952,6 +2955,9 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
case TCP_USER_TIMEOUT:
val = jiffies_to_msecs(icsk->icsk_user_timeout);
break;
+ case TCP_TIMESTAMP:
+ val = tcp_time_stamp + tp->snd_tsval_offset;
+ break;
default:
return -ENOPROTOOPT;
}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 5d45159..9b6d485 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -622,7 +622,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
if (likely(sysctl_tcp_timestamps && *md5 == NULL)) {
opts->options |= OPTION_TS;
- opts->tsval = TCP_SKB_CB(skb)->when;
+ opts->tsval = TCP_SKB_CB(skb)->when + tp->snd_tsval_offset;
opts->tsecr = tp->rx_opt.ts_recent;
remaining -= TCPOLEN_TSTAMP_ALIGNED;
}
@@ -705,6 +705,7 @@ static unsigned int tcp_synack_options(struct sock *sk,
struct tcp_extend_values *xvp,
struct tcp_fastopen_cookie *foc)
{
+ struct tcp_sock *tp = tcp_sk(sk);
struct inet_request_sock *ireq = inet_rsk(req);
unsigned int remaining = MAX_TCP_OPTION_SPACE;
u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ?
@@ -739,7 +740,7 @@ static unsigned int tcp_synack_options(struct sock *sk,
}
if (likely(ireq->tstamp_ok)) {
opts->options |= OPTION_TS;
- opts->tsval = TCP_SKB_CB(skb)->when;
+ opts->tsval = TCP_SKB_CB(skb)->when + tp->snd_tsval_offset;
opts->tsecr = req->ts_recent;
remaining -= TCPOLEN_TSTAMP_ALIGNED;
}
@@ -806,7 +807,7 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
if (likely(tp->rx_opt.tstamp_ok)) {
opts->options |= OPTION_TS;
- opts->tsval = tcb ? tcb->when : 0;
+ opts->tsval = tcb ? tcb->when + tp->snd_tsval_offset : 0;
opts->tsecr = tp->rx_opt.ts_recent;
size += TCPOLEN_TSTAMP_ALIGNED;
}
--
1.7.11.7
^ permalink raw reply related
* Re: [PATCH] ethtool: Add version check for et131x regs
From: Ben Hutchings @ 2013-01-22 20:44 UTC (permalink / raw)
To: Mark Einon; +Cc: netdev
In-Reply-To: <1357379851-5298-1-git-send-email-mark.einon@gmail.com>
On Sat, 2013-01-05 at 09:57 +0000, Mark Einon wrote:
> Added a version check for the et131x reg dump, in case the dump format
> needs to be changed later.
>
> Signed-off-by: Mark Einon <mark.einon@gmail.com>
> ---
> et131x.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/et131x.c b/et131x.c
> index b36c184..8cdbec0 100644
> --- a/et131x.c
> +++ b/et131x.c
> @@ -4,8 +4,12 @@
>
> int et131x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
> {
> + u8 version = (u8)(regs->version >> 24);
> u32 *reg = (u32 *)regs->data;
>
> + if(version != 1)
Needs a space before the open-parentheis.
Ben.
> + return -1;
> +
> fprintf(stdout, "PHY Registers\n");
> fprintf(stdout, "0x0, Basic Control Reg = 0x%04X\n", *reg++);
> fprintf(stdout, "0x1, Basic Status Reg = 0x%04X\n", *reg++);
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH] ethtool: add register dump support for SMSC LAN9420
From: Ben Hutchings @ 2013-01-22 20:43 UTC (permalink / raw)
To: Steve Glendinning; +Cc: netdev
In-Reply-To: <1355823279-5533-1-git-send-email-steve.glendinning@shawell.net>
Sorry for the slow response.
On Tue, 2012-12-18 at 09:34 +0000, Steve Glendinning wrote:
> This patch adds support for SMSC's LAN9420 PCI ethernet controller
> to ethtool's dump registers (-d) command.
>
> This patch is for use with the smsc9420 driver.
>
> Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
> ---
> Makefile.am | 2 +-
> ethtool.c | 2 ++
> internal.h | 3 ++
> smsc9420.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 101 insertions(+), 1 deletion(-)
> create mode 100644 smsc9420.c
>
> diff --git a/Makefile.am b/Makefile.am
> index ba1faa6..728be0a 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -10,7 +10,7 @@ ethtool_SOURCES = ethtool.c ethtool-copy.h internal.h net_tstamp-copy.h \
> fec_8xx.c ibm_emac.c ixgb.c ixgbe.c natsemi.c \
> pcnet32.c realtek.c tg3.c marvell.c vioc.c \
> smsc911x.c at76c50x-usb.c sfc.c stmmac.c \
> - rxclass.c sfpid.c sfpdiag.c
> + rxclass.c sfpid.c sfpdiag.c smsc9420.c
>
> TESTS = test-cmdline test-features
> check_PROGRAMS = test-cmdline test-features
> diff --git a/ethtool.c b/ethtool.c
> index 345c21c..97c3d76 100644
> --- a/ethtool.c
> +++ b/ethtool.c
> @@ -15,6 +15,7 @@
> * amd8111e support by Reeja John <reeja.john@amd.com>
> * long arguments by Andi Kleen.
> * SMSC LAN911x support by Steve Glendinning <steve.glendinning@smsc.com>
> + * SMSC LAN9420 support by Steve Glendinning <steve.glendinning@shawell.net>
I don't think it makes sense to add credits for features in ethtool.c
when they're entirely implemented in other source files. I know there
are a lot of these already but I'd guess these date from before those
separate files existed. Put your name and copyright in smsc9420.c, and
in AUTHORS if you like.
> * Rx Network Flow Control configuration support <santwona.behera@sun.com>
> * Various features by Ben Hutchings <bhutchings@solarflare.com>;
> * Copyright 2009, 2010 Solarflare Communications
> @@ -884,6 +885,7 @@ static const struct {
> { "sky2", sky2_dump_regs },
> { "vioc", vioc_dump_regs },
> { "smsc911x", smsc911x_dump_regs },
> + { "smsc9420", smsc9420_dump_regs },
> { "at76c50x-usb", at76c50x_usb_dump_regs },
> { "sfc", sfc_dump_regs },
> { "st_mac100", st_mac100_dump_regs },
> diff --git a/internal.h b/internal.h
> index e977a81..8873cd1 100644
> --- a/internal.h
> +++ b/internal.h
> @@ -228,6 +228,9 @@ int vioc_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
> /* SMSC LAN911x/LAN921x embedded ethernet controller */
> int smsc911x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
>
> +/* SMSC LAN9420 PCI ethernet controller */
> +int smsc9420_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
> +
> int at76c50x_usb_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
>
> /* Solarflare Solarstorm controllers */
> diff --git a/smsc9420.c b/smsc9420.c
> new file mode 100644
> index 0000000..b6a24a0
> --- /dev/null
> +++ b/smsc9420.c
> @@ -0,0 +1,95 @@
> +#include <stdio.h>
> +#include <string.h>
> +#include "internal.h"
> +
> +int smsc9420_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
> +{
> + unsigned int *smsc_reg = (unsigned int *)regs->data;
No version check?
> + fprintf(stdout, "LAN9420 DMAC Control & Status Registers\n");
> + fprintf(stdout, "offset 0x00, BUS_MODE = 0x%08X\n",*smsc_reg++);
There should be a space after each comma.
> + fprintf(stdout, "offset 0x04, TX_POLL_DEMAND = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x08, TX_POLL_DEMAND = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x0C, RX_BASE_ADDR = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x10, TX_BASE_ADDR = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x14, DMAC_STATUS = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x18, DMAC_CONTROL = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x1C, DMAC_INTR_ENA = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x20, MISS_FRAME_CNT = 0x%08X\n",*smsc_reg++);
> + smsc_reg += 11; /* 0x24 - 0x4C RESERVED */
> + fprintf(stdout, "offset 0x50, CUR_TX_BUF_ADDR = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x54, CUR_RX_BUF_ADDR = 0x%08X\n",*smsc_reg++);
> + smsc_reg += 10; /* 0x58 - 0x7C RESERVED */
> + fprintf(stdout, "\n");
> +
> + fprintf(stdout, "LAN9420 MAC Control & Status Registers\n");
> + fprintf(stdout, "offset 0x80, MAC_CR = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x84, ADDRH = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x88, ADDRL = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x8C, HASHH = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x90, HASHL = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x94, MIIADDR = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x98, MIIDATA = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0x9C, FLOW = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xA0, VLAN1 = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xA4, VLAN2 = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xA8, WUFF = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xAC, WUCSR = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xB0, COE_CR = 0x%08X\n",*smsc_reg++);
> + smsc_reg += 3; /* 0xB4 - 0xBC RESERVED */
> + fprintf(stdout, "\n");
> +
> + fprintf(stdout, "LAN9420 System Control & Status Registers\n");
> + fprintf(stdout, "offset 0xC0, ID_REV = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xC4, INT_CTL = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xC8, INT_STS = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xCC, INT_CFG = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xD0, GPIO_CFG = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xD4, GPT_CFG = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xD8, GPT_CNT = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xDC, BUS_CFG = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xE0, PMT_CTRL = 0x%08X\n",*smsc_reg++);
> + smsc_reg += 4; /* 0xE4 - 0xF0 RESERVED */
> + fprintf(stdout, "offset 0xF4, FREE_RUN = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xF8, E2P_CMD = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "offset 0xFC, E2P_DATA = 0x%08X\n",*smsc_reg++);
> + fprintf(stdout, "\n");
> +
> + fprintf(stdout, "PHY Registers\n");
> + fprintf(stdout, "index 0, Basic Control Reg = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 1, Basic Status Reg = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 2, PHY identifier 1 = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 3, PHY identifier 2 = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 4, Auto Negotiation Advertisement Reg = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 5, Auto Negotiation Link Partner Ability Reg = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 6, Auto Negotiation Expansion Register = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 7, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 8, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 9, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 10, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 11, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 12, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 13, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 14, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 15, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 16, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 17, Mode Control/Status Reg = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 18, Special Modes = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 19, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 20, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 21, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 22, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 23, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 24, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 25, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 26, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 27, Control/Status Indication = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 28, Reserved = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 29, Interrupt Source Register = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 30, Interrupt Mask Register = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "index 31, PHY Special Control/Status Register = 0x%04X\n",*smsc_reg++);
> + fprintf(stdout, "\n");
Why aren't the PHY register values horizontally aligned while the MAC
and DMA registers are?
> + return 0;
> +}
> +
My git complains about the blank line on the end, so please remove that.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 0/20] net: remove CONFIG_EXPERIMENTAL
From: Greg Kroah-Hartman @ 2013-01-22 20:34 UTC (permalink / raw)
To: Kees Cook; +Cc: linux-kernel, netdev
In-Reply-To: <1358879444-25834-1-git-send-email-keescook@chromium.org>
On Tue, Jan 22, 2013 at 10:30:24AM -0800, Kees Cook wrote:
> Here's what's left of the "remove experimental"[1] tree, all for netdev.
>
> What would be the preference for taking these patches for linux-next?
> Should they go via the netdev tree, or should I ask Greg KH to take them
> via driver-core?
All now applied, thanks.
greg k-h
^ permalink raw reply
* [PATCH ethtool] rxclass: Show full 64 bits of user-data in rxclass_print_nfc_spec_ext()
From: Ben Hutchings @ 2013-01-22 20:33 UTC (permalink / raw)
To: netdev; +Cc: Alexander Duyck
Previously only the lower 32 bits would be shown.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
I just noticed this bug when applying Yan Burman's patch. Untested
since sfc doesn't support this field.
Ben.
rxclass.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/rxclass.c b/rxclass.c
index 1564b62..cd686a3 100644
--- a/rxclass.c
+++ b/rxclass.c
@@ -49,7 +49,7 @@ static void rxclass_print_nfc_spec_ext(struct ethtool_rx_flow_spec *fsp)
tci = ntohs(fsp->h_ext.vlan_tci);
tcim = ntohs(~fsp->m_ext.vlan_tci);
data = (u64)ntohl(fsp->h_ext.data[0]) << 32;
- data = (u64)ntohl(fsp->h_ext.data[1]);
+ data |= (u64)ntohl(fsp->h_ext.data[1]);
datam = (u64)ntohl(~fsp->m_ext.data[0]) << 32;
datam |= (u64)ntohl(~fsp->m_ext.data[1]);
--
1.7.7.6
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* Re: [PATCH v2] xen-netback: allow changing the MAC address of the interface
From: David Miller @ 2013-01-22 20:29 UTC (permalink / raw)
To: msw; +Cc: linux-kernel, ian.campbell, netdev, xen-devel, konrad.wilk
In-Reply-To: <1358878105-7890-1-git-send-email-msw@amazon.com>
From: Matt Wilson <msw@amazon.com>
Date: Tue, 22 Jan 2013 18:08:25 +0000
> Sometimes it is useful to be able to change the MAC address of the
> interface for netback devices. For example, when using ebtables it may
> be useful to be able to distinguish traffic from different interfaces
> without depending on the interface name.
>
> Reported-by: Nikita Borzykh <sample.n@gmail.com>
> Reported-by: Paul Harvey <stockingpaul@hotmail.com>
> Cc: netdev@vger.kernel.org
> Cc: xen-devel@lists.xen.org
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> Signed-off-by: Matt Wilson <msw@amazon.com>
Applied to net-next, thanks.
^ permalink raw reply
* Re: [PATCH 0/5]: soreuseport: Bind multiple sockets to the same port
From: David Miller @ 2013-01-22 20:28 UTC (permalink / raw)
To: therbert; +Cc: netdev, netdev, eric.dumazet
In-Reply-To: <alpine.DEB.2.00.1301221142300.26333@pokey.mtv.corp.google.com>
From: Tom Herbert <therbert@google.com>
Date: Tue, 22 Jan 2013 11:49:46 -0800 (PST)
> This series implements so_reuseport (SO_REUSEPORT socket option) for
> TCP and UDP.
Series applied, thanks Tom.
^ permalink raw reply
* Re: [PATCH ETHTOOL] Added dst-mac parameter for L3/L4 flow spec rules. This is usefull in vSwitch configurations.
From: Ben Hutchings @ 2013-01-22 20:27 UTC (permalink / raw)
To: Amir Vadai; +Cc: David S. Miller, netdev, Or Gerlitz, Yan Burman
In-Reply-To: <1355227436-18383-4-git-send-email-amirv@mellanox.com>
On Tue, 2012-12-11 at 14:03 +0200, Amir Vadai wrote:
> From: Yan Burman <yanb@mellanox.com>
>
> Signed-off-by: Yan Burman <yanb@mellanox.com>
> Signed-off-by: Amir Vadai <amirv@mellanox.com>
[...]
Applied, thanks. Sorry for the delay.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH v2] xen-netback: allow changing the MAC address of the interface
From: Konrad Rzeszutek Wilk @ 2013-01-22 20:21 UTC (permalink / raw)
To: Matt Wilson; +Cc: linux-kernel, Ian Campbell, netdev, xen-devel
In-Reply-To: <1358878105-7890-1-git-send-email-msw@amazon.com>
On Tue, Jan 22, 2013 at 06:08:25PM +0000, Matt Wilson wrote:
> Sometimes it is useful to be able to change the MAC address of the
> interface for netback devices. For example, when using ebtables it may
> be useful to be able to distinguish traffic from different interfaces
> without depending on the interface name.
>
> Reported-by: Nikita Borzykh <sample.n@gmail.com>
> Reported-by: Paul Harvey <stockingpaul@hotmail.com>
> Cc: netdev@vger.kernel.org
> Cc: xen-devel@lists.xen.org
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> Signed-off-by: Matt Wilson <msw@amazon.com>
>
> ---
> Changes since v1:
> * No code changes, only updated commit message
> ---
> drivers/net/xen-netback/interface.c | 2 ++
> 1 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
> index b7d41f8..f733cae 100644
> --- a/drivers/net/xen-netback/interface.c
> +++ b/drivers/net/xen-netback/interface.c
> @@ -238,6 +238,8 @@ static const struct net_device_ops xenvif_netdev_ops = {
> .ndo_stop = xenvif_close,
> .ndo_change_mtu = xenvif_change_mtu,
> .ndo_fix_features = xenvif_fix_features,
> + .ndo_set_mac_address = eth_mac_addr,
> + .ndo_validate_addr = eth_validate_addr,
> };
>
> struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
> --
> 1.7.4.5
>
^ permalink raw reply
* Re: [PATCH net-next 09/15] drivers/net: delete old 8 bit ISA Racal ni5010 support.
From: Jan-Pascal van Best @ 2013-01-22 19:59 UTC (permalink / raw)
To: Paul Gortmaker; +Cc: David Miller, netdev, Andreas Mohr
In-Reply-To: <1358819182-28032-10-git-send-email-paul.gortmaker@windriver.com>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Hi Paul,
Although for me personally it'll be a shock not be able to run the latest
kernel on my legacy system I keep up especially for this ISA card, Andreas
and I cannot seriously oppose removing this driver from the mainline
kernel. It's probably more than a decade and a half ago since anyone used
an NI5010 in production, which makes it time to move on...
By the way, Andreas promises to keep his stable of NI5010 cards forever,
and still has a BNC network in active (if loathed!) service.
Thanks for your work on keeping the kernel net drivers in good order!
Jan-Pascal
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBCAAGBQJQ/u+SAAoJEAD3KLeQ59brsAYH/0neYIXG2BLkghlc9rOakSYc
1oLJposC5WhMlON57xHD0zFh9tYGRV910k0YLuwlUBAb78gsPasnWHqZJ/9bd666
F/B7vi1uaLpT6lkem3xWx8FAkoiUb2i8RBccOseRiUPdrqqm0AKflygZ1RGhoZad
fzr6evOcbd0M6E1/bUNO79oayCN69NLhkqf7thBx/bT5jgKXD0H4RC3MoFghhqS1
dU0be/1Vc9VMc9UnLAO0BQOPzXJRLjAY1IFD4YZUgJYs/u6DnsRF0agxvsADf+Gx
ubHij5R/d+PuMpNEejtE3sfm9AEDpvN+rq3UAnr9y1xeIPr/D/0cKUL94LSpnTU=
=DBl6
-----END PGP SIGNATURE-----
^ permalink raw reply
* Re: BUG in netxen_release_tx_buffers when TSO enabled on kernels >= 3.3 and <= 3.6
From: Eric Dumazet @ 2013-01-22 19:59 UTC (permalink / raw)
To: Ben Hutchings
Cc: christoph.paasch, Ian Campbell, Sony Chacko, Rajesh Borundia,
David Miller, netdev
In-Reply-To: <1358883411.2892.11.camel@bwh-desktop.uk.solarflarecom.com>
On Tue, 2013-01-22 at 19:36 +0000, Ben Hutchings wrote:
> There's another bug right here, which is that 0 is a valid DMA address
> in some systems. The driver should be calling pci_dma_mapping_error()
> to find out whether an address is valid or not. But it also wants to be
> able to assign an invalid address to netxen_skb_frag::dma, and
> unfortunately there is no way to do that in the current DMA API.
>
I guess we should only test ->frag_count then, and set it to 0 in TX
completion path.
^ permalink raw reply
* Re: [PATCH 16/20] drivers/net/wireless/p54: remove depends on CONFIG_EXPERIMENTAL
From: Greg KH @ 2013-01-22 19:59 UTC (permalink / raw)
To: David Miller; +Cc: keescook, chunkeey, linux-kernel, netdev, linville, kvalo
In-Reply-To: <20130122.141252.781223481145097577.davem@davemloft.net>
On Tue, Jan 22, 2013 at 02:12:52PM -0500, David Miller wrote:
> From: Kees Cook <keescook@chromium.org>
> Date: Tue, 22 Jan 2013 10:40:12 -0800
>
> > On Tue, Jan 22, 2013 at 10:37 AM, Christian Lamparter
> > <chunkeey@googlemail.com> wrote:
> >> Aren't these patches going through wireless-next
> >> or linux-next?
> >
> > They can go however it makes things easiest. Greg has offered to carry
> > them in driver-core if Dave doesn't want to carry them in netdev.
>
> Greg can take these:
>
> Acked-by: David S. Miller <davem@davemloft.net>
Thanks, I'll go do that now.
greg k-h
^ permalink raw reply
* Re: [PATCH v5 01/45] percpu_rwlock: Introduce the global reader-writer lock backend
From: Srivatsa S. Bhat @ 2013-01-22 19:58 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-doc, peterz, fweisbec, linux-kernel, mingo, linux-arch,
linux, xiaoguangrong, wangyun, paulmck, nikunj, linux-pm, rusty,
rjw, namhyung, tglx, linux-arm-kernel, netdev, oleg, sbw, tj,
akpm, linuxppc-dev
In-Reply-To: <1358883152.21576.55.camel@gandalf.local.home>
On 01/23/2013 01:02 AM, Steven Rostedt wrote:
> On Tue, 2013-01-22 at 13:03 +0530, Srivatsa S. Bhat wrote:
>> A straight-forward (and obvious) algorithm to implement Per-CPU Reader-Writer
>> locks can also lead to too many deadlock possibilities which can make it very
>> hard/impossible to use. This is explained in the example below, which helps
>> justify the need for a different algorithm to implement flexible Per-CPU
>> Reader-Writer locks.
>>
>> We can use global rwlocks as shown below safely, without fear of deadlocks:
>>
>> Readers:
>>
>> CPU 0 CPU 1
>> ------ ------
>>
>> 1. spin_lock(&random_lock); read_lock(&my_rwlock);
>>
>>
>> 2. read_lock(&my_rwlock); spin_lock(&random_lock);
>>
>>
>> Writer:
>>
>> CPU 2:
>> ------
>>
>> write_lock(&my_rwlock);
>>
>
> I thought global locks are now fair. That is, a reader will block if a
> writer is waiting. Hence, the above should deadlock on the current
> rwlock_t types.
>
Oh is it? Last I checked, lockdep didn't complain about this ABBA scenario!
> We need to fix those locations (or better yet, remove all rwlocks ;-)
>
:-)
The challenge with stop_machine() removal is that the replacement on the
reader side must have the (locking) flexibility comparable to preempt_disable().
Otherwise, that solution most likely won't be viable because we'll hit way
too many locking problems and go crazy by the time we convert them over..(if
we can, that is!)
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* [PATCH 3/5] soreuseport: UDP/IPv4 implementation
From: Tom Herbert @ 2013-01-22 19:50 UTC (permalink / raw)
To: netdev, davem; +Cc: netdev, eric.dumazet
[-- Attachment #1: Type: TEXT/PLAIN, Size: 6197 bytes --]
Allow multiple UDP sockets to bind to the same port.
Motivation soreuseport would be something like a DNS server. An
alternative would be to recv on the same socket from multiple threads.
As in the case of TCP, the load across these threads tends to be
disproportionate and we also see a lot of contection on the socketlock.
Note that SO_REUSEADDR already allows multiple UDP sockets to bind to
the same port, however there is no provision to prevent hijacking and
nothing to distribute packets across all the sockets sharing the same
bound port. This patch does not change the semantics of SO_REUSEADDR,
but provides usable functionality of it for unicast.
Signed-off-by: Tom Herbert <therbert@google.com>
---
net/ipv4/udp.c | 61 +++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 43 insertions(+), 18 deletions(-)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 79c8dbe..b360b30 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -139,6 +139,7 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num,
{
struct sock *sk2;
struct hlist_nulls_node *node;
+ kuid_t uid = sock_i_uid(sk);
sk_nulls_for_each(sk2, node, &hslot->head)
if (net_eq(sock_net(sk2), net) &&
@@ -147,6 +148,8 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num,
(!sk2->sk_reuse || !sk->sk_reuse) &&
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+ (!sk2->sk_reuseport || !sk->sk_reuseport ||
+ !uid_eq(uid, sock_i_uid(sk2))) &&
(*saddr_comp)(sk, sk2)) {
if (bitmap)
__set_bit(udp_sk(sk2)->udp_port_hash >> log,
@@ -169,6 +172,7 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num,
{
struct sock *sk2;
struct hlist_nulls_node *node;
+ kuid_t uid = sock_i_uid(sk);
int res = 0;
spin_lock(&hslot2->lock);
@@ -179,6 +183,8 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num,
(!sk2->sk_reuse || !sk->sk_reuse) &&
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+ (!sk2->sk_reuseport || !sk->sk_reuseport ||
+ !uid_eq(uid, sock_i_uid(sk2))) &&
(*saddr_comp)(sk, sk2)) {
res = 1;
break;
@@ -337,26 +343,26 @@ static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr,
!ipv6_only_sock(sk)) {
struct inet_sock *inet = inet_sk(sk);
- score = (sk->sk_family == PF_INET ? 1 : 0);
+ score = (sk->sk_family == PF_INET ? 2 : 1);
if (inet->inet_rcv_saddr) {
if (inet->inet_rcv_saddr != daddr)
return -1;
- score += 2;
+ score += 4;
}
if (inet->inet_daddr) {
if (inet->inet_daddr != saddr)
return -1;
- score += 2;
+ score += 4;
}
if (inet->inet_dport) {
if (inet->inet_dport != sport)
return -1;
- score += 2;
+ score += 4;
}
if (sk->sk_bound_dev_if) {
if (sk->sk_bound_dev_if != dif)
return -1;
- score += 2;
+ score += 4;
}
}
return score;
@@ -365,7 +371,6 @@ static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr,
/*
* In this second variant, we check (daddr, dport) matches (inet_rcv_sadd, inet_num)
*/
-#define SCORE2_MAX (1 + 2 + 2 + 2)
static inline int compute_score2(struct sock *sk, struct net *net,
__be32 saddr, __be16 sport,
__be32 daddr, unsigned int hnum, int dif)
@@ -380,21 +385,21 @@ static inline int compute_score2(struct sock *sk, struct net *net,
if (inet->inet_num != hnum)
return -1;
- score = (sk->sk_family == PF_INET ? 1 : 0);
+ score = (sk->sk_family == PF_INET ? 2 : 1);
if (inet->inet_daddr) {
if (inet->inet_daddr != saddr)
return -1;
- score += 2;
+ score += 4;
}
if (inet->inet_dport) {
if (inet->inet_dport != sport)
return -1;
- score += 2;
+ score += 4;
}
if (sk->sk_bound_dev_if) {
if (sk->sk_bound_dev_if != dif)
return -1;
- score += 2;
+ score += 4;
}
}
return score;
@@ -409,19 +414,29 @@ static struct sock *udp4_lib_lookup2(struct net *net,
{
struct sock *sk, *result;
struct hlist_nulls_node *node;
- int score, badness;
+ int score, badness, matches = 0, reuseport = 0;
+ u32 hash = 0;
begin:
result = NULL;
- badness = -1;
+ badness = 0;
udp_portaddr_for_each_entry_rcu(sk, node, &hslot2->head) {
score = compute_score2(sk, net, saddr, sport,
daddr, hnum, dif);
if (score > badness) {
result = sk;
badness = score;
- if (score == SCORE2_MAX)
- goto exact_match;
+ reuseport = sk->sk_reuseport;
+ if (reuseport) {
+ hash = inet_ehashfn(net, daddr, hnum,
+ saddr, htons(sport));
+ matches = 1;
+ }
+ } else if (score == badness && reuseport) {
+ matches++;
+ if (((u64)hash * matches) >> 32 == 0)
+ result = sk;
+ hash = next_pseudo_random32(hash);
}
}
/*
@@ -431,9 +446,7 @@ begin:
*/
if (get_nulls_value(node) != slot2)
goto begin;
-
if (result) {
-exact_match:
if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2)))
result = NULL;
else if (unlikely(compute_score2(result, net, saddr, sport,
@@ -457,7 +470,8 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
unsigned short hnum = ntohs(dport);
unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask);
struct udp_hslot *hslot2, *hslot = &udptable->hash[slot];
- int score, badness;
+ int score, badness, matches = 0, reuseport = 0;
+ u32 hash = 0;
rcu_read_lock();
if (hslot->count > 10) {
@@ -486,13 +500,24 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
}
begin:
result = NULL;
- badness = -1;
+ badness = 0;
sk_nulls_for_each_rcu(sk, node, &hslot->head) {
score = compute_score(sk, net, saddr, hnum, sport,
daddr, dport, dif);
if (score > badness) {
result = sk;
badness = score;
+ reuseport = sk->sk_reuseport;
+ if (reuseport) {
+ hash = inet_ehashfn(net, daddr, hnum,
+ saddr, htons(sport));
+ matches = 1;
+ }
+ } else if (score == badness && reuseport) {
+ matches++;
+ if (((u64)hash * matches) >> 32 == 0)
+ result = sk;
+ hash = next_pseudo_random32(hash);
}
}
/*
--
1.7.7.3
^ permalink raw reply related
* [PATCH 5/5] soreuseport: UDP/IPv6 implementation
From: Tom Herbert @ 2013-01-22 19:50 UTC (permalink / raw)
To: netdev, davem; +Cc: netdev, eric.dumazet
[-- Attachment #1: Type: TEXT/PLAIN, Size: 2642 bytes --]
Motivation for soreuseport would be something like a DNS server. An
alternative would be to recv on the same socket from multiple threads.
As in the case of TCP, the load across these threads tends to be
disproportionate and we also see a lot of contection on the socket lock.
Note that SO_REUSEADDR already allows multiple UDP sockets to bind to
the same port, however there is no provision to prevent hijacking and
nothing to distribute packets across all the sockets sharing the same
bound port. This patch does not change the semantics of SO_REUSEADDR,
but provides usable functionality of it for unicast.
Signed-off-by: Tom Herbert <therbert@google.com>
---
net/ipv6/udp.c | 30 +++++++++++++++++++++++++++---
1 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 1afb635..cb5bf49 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -45,6 +45,7 @@
#include <net/tcp_states.h>
#include <net/ip6_checksum.h>
#include <net/xfrm.h>
+#include <net/inet6_hashtables.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
@@ -203,7 +204,8 @@ static struct sock *udp6_lib_lookup2(struct net *net,
{
struct sock *sk, *result;
struct hlist_nulls_node *node;
- int score, badness;
+ int score, badness, matches = 0, reuseport = 0;
+ u32 hash = 0;
begin:
result = NULL;
@@ -214,8 +216,18 @@ begin:
if (score > badness) {
result = sk;
badness = score;
- if (score == SCORE2_MAX)
+ reuseport = sk->sk_reuseport;
+ if (reuseport) {
+ hash = inet6_ehashfn(net, daddr, hnum,
+ saddr, sport);
+ matches = 1;
+ } else if (score == SCORE2_MAX)
goto exact_match;
+ } else if (score == badness && reuseport) {
+ matches++;
+ if (((u64)hash * matches) >> 32 == 0)
+ result = sk;
+ hash = next_pseudo_random32(hash);
}
}
/*
@@ -249,7 +261,8 @@ struct sock *__udp6_lib_lookup(struct net *net,
unsigned short hnum = ntohs(dport);
unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask);
struct udp_hslot *hslot2, *hslot = &udptable->hash[slot];
- int score, badness;
+ int score, badness, matches = 0, reuseport = 0;
+ u32 hash = 0;
rcu_read_lock();
if (hslot->count > 10) {
@@ -284,6 +297,17 @@ begin:
if (score > badness) {
result = sk;
badness = score;
+ reuseport = sk->sk_reuseport;
+ if (reuseport) {
+ hash = inet6_ehashfn(net, daddr, hnum,
+ saddr, sport);
+ matches = 1;
+ }
+ } else if (score == badness && reuseport) {
+ matches++;
+ if (((u64)hash * matches) >> 32 == 0)
+ result = sk;
+ hash = next_pseudo_random32(hash);
}
}
/*
--
1.7.7.3
^ permalink raw reply related
* [PATCH 4/5] soreuseport: TCP/IPv6 implementation
From: Tom Herbert @ 2013-01-22 19:50 UTC (permalink / raw)
To: netdev, davem; +Cc: netdev, eric.dumazet
Motivation for soreuseport would be something like a web server
binding to port 80 running with multiple threads, where each thread
might have it's own listener socket. This could be done as an
alternative to other models: 1) have one listener thread which
dispatches completed connections to workers. 2) accept on a single
listener socket from multiple threads. In case #1 the listener thread
can easily become the bottleneck with high connection turn-over rate.
In case #2, the proportion of connections accepted per thread tends
to be uneven under high connection load (assuming simple event loop:
while (1) { accept(); process() }, wakeup does not promote fairness
among the sockets. We have seen the disproportion to be as high
as 3:1 ratio between thread accepting most connections and the one
accepting the fewest. With so_reusport the distribution is
uniform.
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/net/inet6_hashtables.h | 5 ++++-
include/net/netfilter/nf_tproxy_core.h | 1 +
net/ipv6/inet6_connection_sock.c | 19 ++++++++++++++-----
net/ipv6/inet6_hashtables.c | 19 ++++++++++++++++---
net/ipv6/tcp_ipv6.c | 4 +++-
5 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 9e34c87..7ca75cb 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -71,6 +71,8 @@ extern struct sock *__inet6_lookup_established(struct net *net,
extern struct sock *inet6_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr,
+ const __be16 sport,
const struct in6_addr *daddr,
const unsigned short hnum,
const int dif);
@@ -88,7 +90,8 @@ static inline struct sock *__inet6_lookup(struct net *net,
if (sk)
return sk;
- return inet6_lookup_listener(net, hashinfo, daddr, hnum, dif);
+ return inet6_lookup_listener(net, hashinfo, saddr, sport,
+ daddr, hnum, dif);
}
static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index 1937964..36d9379 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -152,6 +152,7 @@ nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
break;
case NFT_LOOKUP_LISTENER:
sk = inet6_lookup_listener(net, &tcp_hashinfo,
+ saddr, sport,
daddr, ntohs(dport),
in->ifindex);
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 3064785..e4297a3 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -32,6 +32,9 @@ int inet6_csk_bind_conflict(const struct sock *sk,
{
const struct sock *sk2;
const struct hlist_node *node;
+ int reuse = sk->sk_reuse;
+ int reuseport = sk->sk_reuseport;
+ int uid = sock_i_uid((struct sock *)sk);
/* We must walk the whole port owner list in this case. -DaveM */
/*
@@ -42,11 +45,17 @@ int inet6_csk_bind_conflict(const struct sock *sk,
if (sk != sk2 &&
(!sk->sk_bound_dev_if ||
!sk2->sk_bound_dev_if ||
- sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
- (!sk->sk_reuse || !sk2->sk_reuse ||
- sk2->sk_state == TCP_LISTEN) &&
- ipv6_rcv_saddr_equal(sk, sk2))
- break;
+ sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
+ if ((!reuse || !sk2->sk_reuse ||
+ sk2->sk_state == TCP_LISTEN) &&
+ (!reuseport || !sk2->sk_reuseport ||
+ (sk2->sk_state != TCP_TIME_WAIT &&
+ !uid_eq(uid,
+ sock_i_uid((struct sock *)sk2))))) {
+ if (ipv6_rcv_saddr_equal(sk, sk2))
+ break;
+ }
+ }
}
return node != NULL;
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index dea17fd..32b4a16 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -158,25 +158,38 @@ static inline int compute_score(struct sock *sk, struct net *net,
}
struct sock *inet6_lookup_listener(struct net *net,
- struct inet_hashinfo *hashinfo, const struct in6_addr *daddr,
+ struct inet_hashinfo *hashinfo, const struct in6_addr *saddr,
+ const __be16 sport, const struct in6_addr *daddr,
const unsigned short hnum, const int dif)
{
struct sock *sk;
const struct hlist_nulls_node *node;
struct sock *result;
- int score, hiscore;
+ int score, hiscore, matches = 0, reuseport = 0;
+ u32 phash = 0;
unsigned int hash = inet_lhashfn(net, hnum);
struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
rcu_read_lock();
begin:
result = NULL;
- hiscore = -1;
+ hiscore = 0;
sk_nulls_for_each(sk, node, &ilb->head) {
score = compute_score(sk, net, hnum, daddr, dif);
if (score > hiscore) {
hiscore = score;
result = sk;
+ reuseport = sk->sk_reuseport;
+ if (reuseport) {
+ phash = inet6_ehashfn(net, daddr, hnum,
+ saddr, sport);
+ matches = 1;
+ }
+ } else if (score == hiscore && reuseport) {
+ matches++;
+ if (((u64)phash * matches) >> 32 == 0)
+ result = sk;
+ phash = next_pseudo_random32(phash);
}
}
/*
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3701c3c..06087e5 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -834,7 +834,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
* no RST generated if md5 hash doesn't match.
*/
sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
- &tcp_hashinfo, &ipv6h->daddr,
+ &tcp_hashinfo, &ipv6h->saddr,
+ th->source, &ipv6h->daddr,
ntohs(th->source), inet6_iif(skb));
if (!sk1)
return;
@@ -1598,6 +1599,7 @@ do_time_wait:
struct sock *sk2;
sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
+ &ipv6_hdr(skb)->saddr, th->source,
&ipv6_hdr(skb)->daddr,
ntohs(th->dest), inet6_iif(skb));
if (sk2 != NULL) {
--
1.7.7.3
^ permalink raw reply related
* [PATCH 2/5] soreuseport: TCP/IPv4 implementation
From: Tom Herbert @ 2013-01-22 19:50 UTC (permalink / raw)
To: netdev, davem; +Cc: netdev, eric.dumazet
Allow multiple listener sockets to bind to the same port.
Motivation for soresuseport would be something like a web server
binding to port 80 running with multiple threads, where each thread
might have it's own listener socket. This could be done as an
alternative to other models: 1) have one listener thread which
dispatches completed connections to workers. 2) accept on a single
listener socket from multiple threads. In case #1 the listener thread
can easily become the bottleneck with high connection turn-over rate.
In case #2, the proportion of connections accepted per thread tends
to be uneven under high connection load (assuming simple event loop:
while (1) { accept(); process() }, wakeup does not promote fairness
among the sockets. We have seen the disproportion to be as high
as 3:1 ratio between thread accepting most connections and the one
accepting the fewest. With so_reusport the distribution is
uniform.
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/net/inet_hashtables.h | 13 ++++++--
include/net/netfilter/nf_tproxy_core.h | 1 +
net/ipv4/inet_connection_sock.c | 48 ++++++++++++++++++++++++-------
net/ipv4/inet_hashtables.c | 28 ++++++++++++++----
net/ipv4/tcp_ipv4.c | 4 ++-
5 files changed, 73 insertions(+), 21 deletions(-)
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 67a8fa0..7b2ae9d 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -81,7 +81,9 @@ struct inet_bind_bucket {
struct net *ib_net;
#endif
unsigned short port;
- signed short fastreuse;
+ signed char fastreuse;
+ signed char fastreuseport;
+ kuid_t fastuid;
int num_owners;
struct hlist_node node;
struct hlist_head owners;
@@ -257,15 +259,19 @@ extern void inet_unhash(struct sock *sk);
extern struct sock *__inet_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
+ const __be32 saddr,
+ const __be16 sport,
const __be32 daddr,
const unsigned short hnum,
const int dif);
static inline struct sock *inet_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
+ __be32 saddr, __be16 sport,
__be32 daddr, __be16 dport, int dif)
{
- return __inet_lookup_listener(net, hashinfo, daddr, ntohs(dport), dif);
+ return __inet_lookup_listener(net, hashinfo, saddr, sport,
+ daddr, ntohs(dport), dif);
}
/* Socket demux engine toys. */
@@ -358,7 +364,8 @@ static inline struct sock *__inet_lookup(struct net *net,
struct sock *sk = __inet_lookup_established(net, hashinfo,
saddr, sport, daddr, hnum, dif);
- return sk ? : __inet_lookup_listener(net, hashinfo, daddr, hnum, dif);
+ return sk ? : __inet_lookup_listener(net, hashinfo, saddr, sport,
+ daddr, hnum, dif);
}
static inline struct sock *inet_lookup(struct net *net,
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index 75ca929..1937964 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -82,6 +82,7 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
break;
case NFT_LOOKUP_LISTENER:
sk = inet_lookup_listener(net, &tcp_hashinfo,
+ saddr, sport,
daddr, dport,
in->ifindex);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index d0670f0..8bb623d 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -59,6 +59,8 @@ int inet_csk_bind_conflict(const struct sock *sk,
struct sock *sk2;
struct hlist_node *node;
int reuse = sk->sk_reuse;
+ int reuseport = sk->sk_reuseport;
+ kuid_t uid = sock_i_uid((struct sock *)sk);
/*
* Unlike other sk lookup places we do not check
@@ -73,8 +75,11 @@ int inet_csk_bind_conflict(const struct sock *sk,
(!sk->sk_bound_dev_if ||
!sk2->sk_bound_dev_if ||
sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
- if (!reuse || !sk2->sk_reuse ||
- sk2->sk_state == TCP_LISTEN) {
+ if ((!reuse || !sk2->sk_reuse ||
+ sk2->sk_state == TCP_LISTEN) &&
+ (!reuseport || !sk2->sk_reuseport ||
+ (sk2->sk_state != TCP_TIME_WAIT &&
+ !uid_eq(uid, sock_i_uid(sk2))))) {
const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2);
if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) ||
sk2_rcv_saddr == sk_rcv_saddr(sk))
@@ -106,6 +111,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
int ret, attempts = 5;
struct net *net = sock_net(sk);
int smallest_size = -1, smallest_rover;
+ kuid_t uid = sock_i_uid(sk);
local_bh_disable();
if (!snum) {
@@ -125,9 +131,12 @@ again:
spin_lock(&head->lock);
inet_bind_bucket_for_each(tb, node, &head->chain)
if (net_eq(ib_net(tb), net) && tb->port == rover) {
- if (tb->fastreuse > 0 &&
- sk->sk_reuse &&
- sk->sk_state != TCP_LISTEN &&
+ if (((tb->fastreuse > 0 &&
+ sk->sk_reuse &&
+ sk->sk_state != TCP_LISTEN) ||
+ (tb->fastreuseport > 0 &&
+ sk->sk_reuseport &&
+ uid_eq(tb->fastuid, uid))) &&
(tb->num_owners < smallest_size || smallest_size == -1)) {
smallest_size = tb->num_owners;
smallest_rover = rover;
@@ -185,14 +194,17 @@ tb_found:
if (sk->sk_reuse == SK_FORCE_REUSE)
goto success;
- if (tb->fastreuse > 0 &&
- sk->sk_reuse && sk->sk_state != TCP_LISTEN &&
+ if (((tb->fastreuse > 0 &&
+ sk->sk_reuse && sk->sk_state != TCP_LISTEN) ||
+ (tb->fastreuseport > 0 &&
+ sk->sk_reuseport && uid_eq(tb->fastuid, uid))) &&
smallest_size == -1) {
goto success;
} else {
ret = 1;
if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true)) {
- if (sk->sk_reuse && sk->sk_state != TCP_LISTEN &&
+ if (((sk->sk_reuse && sk->sk_state != TCP_LISTEN) ||
+ (sk->sk_reuseport && uid_eq(tb->fastuid, uid))) &&
smallest_size != -1 && --attempts >= 0) {
spin_unlock(&head->lock);
goto again;
@@ -212,9 +224,23 @@ tb_not_found:
tb->fastreuse = 1;
else
tb->fastreuse = 0;
- } else if (tb->fastreuse &&
- (!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
- tb->fastreuse = 0;
+ if (sk->sk_reuseport) {
+ tb->fastreuseport = 1;
+ tb->fastuid = uid;
+ } else {
+ tb->fastreuseport = 0;
+ tb->fastuid = 0;
+ }
+ } else {
+ if (tb->fastreuse &&
+ (!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
+ tb->fastreuse = 0;
+ if (tb->fastreuseport &&
+ (!sk->sk_reuseport || !uid_eq(tb->fastuid, uid))) {
+ tb->fastreuseport = 0;
+ tb->fastuid = 0;
+ }
+ }
success:
if (!inet_csk(sk)->icsk_bind_hash)
inet_bind_hash(sk, tb, snum);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index fa3ae81..0ce0595 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -39,6 +39,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
write_pnet(&tb->ib_net, hold_net(net));
tb->port = snum;
tb->fastreuse = 0;
+ tb->fastreuseport = 0;
tb->num_owners = 0;
INIT_HLIST_HEAD(&tb->owners);
hlist_add_head(&tb->node, &head->chain);
@@ -151,16 +152,16 @@ static inline int compute_score(struct sock *sk, struct net *net,
if (net_eq(sock_net(sk), net) && inet->inet_num == hnum &&
!ipv6_only_sock(sk)) {
__be32 rcv_saddr = inet->inet_rcv_saddr;
- score = sk->sk_family == PF_INET ? 1 : 0;
+ score = sk->sk_family == PF_INET ? 2 : 1;
if (rcv_saddr) {
if (rcv_saddr != daddr)
return -1;
- score += 2;
+ score += 4;
}
if (sk->sk_bound_dev_if) {
if (sk->sk_bound_dev_if != dif)
return -1;
- score += 2;
+ score += 4;
}
}
return score;
@@ -176,6 +177,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
struct sock *__inet_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
+ const __be32 saddr, __be16 sport,
const __be32 daddr, const unsigned short hnum,
const int dif)
{
@@ -183,17 +185,29 @@ struct sock *__inet_lookup_listener(struct net *net,
struct hlist_nulls_node *node;
unsigned int hash = inet_lhashfn(net, hnum);
struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
- int score, hiscore;
+ int score, hiscore, matches = 0, reuseport = 0;
+ u32 phash = 0;
rcu_read_lock();
begin:
result = NULL;
- hiscore = -1;
+ hiscore = 0;
sk_nulls_for_each_rcu(sk, node, &ilb->head) {
score = compute_score(sk, net, hnum, daddr, dif);
if (score > hiscore) {
result = sk;
hiscore = score;
+ reuseport = sk->sk_reuseport;
+ if (reuseport) {
+ phash = inet_ehashfn(net, daddr, hnum,
+ saddr, sport);
+ matches = 1;
+ }
+ } else if (score == hiscore && reuseport) {
+ matches++;
+ if (((u64)phash * matches) >> 32 == 0)
+ result = sk;
+ phash = next_pseudo_random32(phash);
}
}
/*
@@ -501,7 +515,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
inet_bind_bucket_for_each(tb, node, &head->chain) {
if (net_eq(ib_net(tb), net) &&
tb->port == port) {
- if (tb->fastreuse >= 0)
+ if (tb->fastreuse >= 0 ||
+ tb->fastreuseport >= 0)
goto next_port;
WARN_ON(hlist_empty(&tb->owners));
if (!check_established(death_row, sk,
@@ -518,6 +533,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
break;
}
tb->fastreuse = -1;
+ tb->fastreuseport = -1;
goto ok;
next_port:
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c6ce9ca..bbbdcc5 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -657,7 +657,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
* no RST generated if md5 hash doesn't match.
*/
sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev),
- &tcp_hashinfo, ip_hdr(skb)->daddr,
+ &tcp_hashinfo, ip_hdr(skb)->saddr,
+ th->source, ip_hdr(skb)->daddr,
ntohs(th->source), inet_iif(skb));
/* don't send rst if it can't find key */
if (!sk1)
@@ -2074,6 +2075,7 @@ do_time_wait:
case TCP_TW_SYN: {
struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
&tcp_hashinfo,
+ iph->saddr, th->source,
iph->daddr, th->dest,
inet_iif(skb));
if (sk2) {
--
1.7.7.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox