* Re: [PATCH v2 2/2] stmmac: rename it to synopsys
From: Florian Fainelli @ 2017-01-11 21:14 UTC (permalink / raw)
To: Joao Pinto, davem
Cc: lars.persson, niklass, peppe.cavallaro, alexandre.torgue, netdev
In-Reply-To: <c74e6665ca14a4ca03b38cd3442ef0644d9e250d.1484059674.git.jpinto@synopsys.com>
On 01/10/2017 06:52 AM, Joao Pinto wrote:
> This patch renames stmicro/stmmac to synopsys/ since it is a standard
> ethernet software package regarding synopsys ethernet controllers, supporting
> the majority of Synopsys Ethernet IPs. The config IDs remain the same, for
> retro-compatibility, only the description was changed.
Do re really have to do this? ST Micro were the first to upstream
support for a Synopsys IP, and it was later on identified as being
"stmicro" instead of "synopsys" (during the big driver move under
drivers/net/ethernet) whichever came first in the driver essentially "wins".
As mentioned before, although git is able to track renames, git log does
not automatically have --follow, so it can be hard for people to track
down the (new) history of the driver.
Personally, I don't see much value in doing this rename, especially when
all the driver internal structures are still going to be named with
stmmac (and please don't even think about doing a s/stmmac/snps/ inside
the driver ;)).
My 2 cents.
--
Florian
^ permalink raw reply
* Re: [PATCH net-next v2] net: thunderx: Make hfunc variable const type in nicvf_set_rxfh()
From: David Miller @ 2017-01-11 21:13 UTC (permalink / raw)
To: rrichter; +Cc: sgoutham, rric, netdev
In-Reply-To: <20170111170432.31210-1-rrichter@cavium.com>
From: Robert Richter <rrichter@cavium.com>
Date: Wed, 11 Jan 2017 18:04:32 +0100
> From struct ethtool_ops:
>
> int (*set_rxfh)(struct net_device *, const u32 *indir,
> const u8 *key, const u8 hfunc);
>
> Change function arg of hfunc to const type.
>
> V2: Fixed indentation.
>
> Signed-off-by: Robert Richter <rrichter@cavium.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] sfc: efx_get_phys_port_id() can be static
From: David Miller @ 2017-01-11 21:12 UTC (permalink / raw)
To: weiyj.lk; +Cc: linux-net-drivers, ecree, bkenward, weiyongjun1, netdev
In-Reply-To: <20170111161612.14384-1-weiyj.lk@gmail.com>
From: Wei Yongjun <weiyj.lk@gmail.com>
Date: Wed, 11 Jan 2017 16:16:12 +0000
> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> Fixes the following sparse warning:
>
> drivers/net/ethernet/sfc/efx.c:2337:5: warning:
> symbol 'efx_get_phys_port_id' was not declared. Should it be static?
>
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] net: thunderx: Fix error return code in nicvf_open()
From: David Miller @ 2017-01-11 21:12 UTC (permalink / raw)
To: weiyj.lk; +Cc: weiyongjun1, sgoutham, rric, linux-arm-kernel, netdev
In-Reply-To: <20170111163251.19367-1-weiyj.lk@gmail.com>
From: Wei Yongjun <weiyj.lk@gmail.com>
Date: Wed, 11 Jan 2017 16:32:51 +0000
> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> Fix to return a negative error code from the error handling
> case instead of 0, as done elsewhere in this function.
>
> Fixes: 712c31853440 ("net: thunderx: Program LMAC credits based on MTU")
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Applied.
^ permalink raw reply
* Re: [PATCH v2] vxlan: Set ports in flow key when doing route lookups
From: David Miller @ 2017-01-11 21:10 UTC (permalink / raw)
To: martynas; +Cc: netdev
In-Reply-To: <20170111151853.4794-1-martynas@weave.works>
From: Martynas Pumputis <martynas@weave.works>
Date: Wed, 11 Jan 2017 15:18:53 +0000
> Otherwise, a xfrm policy with sport/dport being set cannot be matched.
>
> Signed-off-by: Martynas Pumputis <martynas@weave.works>
> ---
> Changes in v2:
> - Set the source port in the flow key.
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net] r8152: fix the sw rx checksum is unavailable
From: David Miller @ 2017-01-11 21:09 UTC (permalink / raw)
To: hayeswang; +Cc: netdev, nic_swsd, linux-kernel, linux-usb
In-Reply-To: <1394712342-15778-232-Taiwan-albertk@realtek.com>
From: Hayes Wang <hayeswang@realtek.com>
Date: Wed, 11 Jan 2017 16:25:34 +0800
> Fix the hw rx checksum is always enabled, and the user couldn't switch
> it to sw rx checksum.
>
> Note that the RTL_VER_01 only support sw rx checksum only. Besides,
> the hw rx checksum for RTL_VER_02 is disabled after
> commit b9a321b48af4 ("r8152: Fix broken RX checksums."). Re-enable it.
>
> Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* [PATCH net-next 3/3] net: mdio-gpio: Use gpio subsystem to handle low-active pins
From: Florian Fainelli @ 2017-01-11 20:59 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, vivien.didelot, cphealy, linux, Florian Fainelli
In-Reply-To: <20170111205951.32363-1-f.fainelli@gmail.com>
From: Guenter Roeck <linux@roeck-us.net>
gpiod functions support handling low-active pins, so we can move
thos code out of this driver into the gpio subsystem and simplify
the code a bit.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/mdio-gpio.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index e62fcea2d945..7faa79b254ef 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -33,7 +33,6 @@
struct mdio_gpio_info {
struct mdiobb_ctrl ctrl;
struct gpio_desc *mdc, *mdio, *mdo;
- int mdc_active_low, mdio_active_low, mdo_active_low;
};
static void *mdio_gpio_of_get_data(struct platform_device *pdev)
@@ -80,13 +79,12 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
* assume the pin serves as pull-up. If direction is
* output, the default value is high.
*/
- gpiod_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low);
+ gpiod_set_value(bitbang->mdo, 1);
return;
}
if (dir)
- gpiod_direction_output(bitbang->mdio,
- 1 ^ bitbang->mdio_active_low);
+ gpiod_direction_output(bitbang->mdio, 1);
else
gpiod_direction_input(bitbang->mdio);
}
@@ -96,7 +94,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- return gpiod_get_value(bitbang->mdio) ^ bitbang->mdio_active_low;
+ return gpiod_get_value(bitbang->mdio);
}
static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
@@ -105,9 +103,9 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
container_of(ctrl, struct mdio_gpio_info, ctrl);
if (bitbang->mdo)
- gpiod_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low);
+ gpiod_set_value(bitbang->mdo, what);
else
- gpiod_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low);
+ gpiod_set_value(bitbang->mdio, what);
}
static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
@@ -115,7 +113,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- gpiod_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low);
+ gpiod_set_value(bitbang->mdc, what);
}
static struct mdiobb_ops mdio_gpio_ops = {
@@ -146,14 +144,18 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
bitbang->ctrl.reset = pdata->reset;
mdc = pdata->mdc;
bitbang->mdc = gpio_to_desc(mdc);
- bitbang->mdc_active_low = pdata->mdc_active_low;
+ if (pdata->mdc_active_low)
+ mdc_flags = GPIOF_OUT_INIT_HIGH | GPIOF_ACTIVE_LOW;
mdio = pdata->mdio;
bitbang->mdio = gpio_to_desc(mdio);
- bitbang->mdio_active_low = pdata->mdio_active_low;
+ if (pdata->mdio_active_low)
+ mdio_flags |= GPIOF_ACTIVE_LOW;
mdo = pdata->mdo;
- if (mdo)
+ if (mdo) {
bitbang->mdo = gpio_to_desc(mdo);
- bitbang->mdo_active_low = pdata->mdo_active_low;
+ if (pdata->mdo_active_low)
+ mdo_flags = GPIOF_OUT_INIT_LOW | GPIOF_ACTIVE_LOW;
+ }
new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
if (!new_bus)
--
2.9.3
^ permalink raw reply related
* [PATCH net-next 2/3] net: mdio-gpio: Convert to use gpiod functions where possible
From: Florian Fainelli @ 2017-01-11 20:59 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, vivien.didelot, cphealy, linux, Florian Fainelli
In-Reply-To: <20170111205951.32363-1-f.fainelli@gmail.com>
From: Guenter Roeck <linux@roeck-us.net>
Using gpiod functions lets us use functionality which is not available
with gpio functions.
There is no gpiod function to match devm_gpio_request_one, so leave it
in place and use gpio_to_desc() to convert absolute pin numbers to gpio
descriptors.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/mdio-gpio.c | 43 +++++++++++++++++++++----------------------
1 file changed, 21 insertions(+), 22 deletions(-)
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index f6e773256c82..e62fcea2d945 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -32,7 +32,7 @@
struct mdio_gpio_info {
struct mdiobb_ctrl ctrl;
- int mdc, mdio, mdo;
+ struct gpio_desc *mdc, *mdio, *mdo;
int mdc_active_low, mdio_active_low, mdo_active_low;
};
@@ -80,16 +80,15 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
* assume the pin serves as pull-up. If direction is
* output, the default value is high.
*/
- gpio_set_value_cansleep(bitbang->mdo,
- 1 ^ bitbang->mdo_active_low);
+ gpiod_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low);
return;
}
if (dir)
- gpio_direction_output(bitbang->mdio,
- 1 ^ bitbang->mdio_active_low);
+ gpiod_direction_output(bitbang->mdio,
+ 1 ^ bitbang->mdio_active_low);
else
- gpio_direction_input(bitbang->mdio);
+ gpiod_direction_input(bitbang->mdio);
}
static int mdio_get(struct mdiobb_ctrl *ctrl)
@@ -97,8 +96,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- return gpio_get_value_cansleep(bitbang->mdio) ^
- bitbang->mdio_active_low;
+ return gpiod_get_value(bitbang->mdio) ^ bitbang->mdio_active_low;
}
static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
@@ -107,11 +105,9 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
container_of(ctrl, struct mdio_gpio_info, ctrl);
if (bitbang->mdo)
- gpio_set_value_cansleep(bitbang->mdo,
- what ^ bitbang->mdo_active_low);
+ gpiod_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low);
else
- gpio_set_value_cansleep(bitbang->mdio,
- what ^ bitbang->mdio_active_low);
+ gpiod_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low);
}
static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
@@ -119,7 +115,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- gpio_set_value_cansleep(bitbang->mdc, what ^ bitbang->mdc_active_low);
+ gpiod_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low);
}
static struct mdiobb_ops mdio_gpio_ops = {
@@ -137,6 +133,7 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
struct mii_bus *new_bus;
struct mdio_gpio_info *bitbang;
int i;
+ int mdc, mdio, mdo;
unsigned long mdc_flags = GPIOF_OUT_INIT_LOW;
unsigned long mdio_flags = GPIOF_DIR_IN;
unsigned long mdo_flags = GPIOF_OUT_INIT_HIGH;
@@ -147,11 +144,15 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
bitbang->ctrl.ops = &mdio_gpio_ops;
bitbang->ctrl.reset = pdata->reset;
- bitbang->mdc = pdata->mdc;
+ mdc = pdata->mdc;
+ bitbang->mdc = gpio_to_desc(mdc);
bitbang->mdc_active_low = pdata->mdc_active_low;
- bitbang->mdio = pdata->mdio;
+ mdio = pdata->mdio;
+ bitbang->mdio = gpio_to_desc(mdio);
bitbang->mdio_active_low = pdata->mdio_active_low;
- bitbang->mdo = pdata->mdo;
+ mdo = pdata->mdo;
+ if (mdo)
+ bitbang->mdo = gpio_to_desc(mdo);
bitbang->mdo_active_low = pdata->mdo_active_low;
new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
@@ -177,16 +178,14 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
else
strncpy(new_bus->id, "gpio", MII_BUS_ID_SIZE);
- if (devm_gpio_request_one(dev, bitbang->mdc, mdc_flags, "mdc"))
+ if (devm_gpio_request_one(dev, mdc, mdc_flags, "mdc"))
goto out_free_bus;
- if (devm_gpio_request_one(dev, bitbang->mdio, mdio_flags, "mdio"))
+ if (devm_gpio_request_one(dev, mdio, mdio_flags, "mdio"))
goto out_free_bus;
- if (bitbang->mdo) {
- if (devm_gpio_request_one(dev, bitbang->mdo, mdo_flags, "mdo"))
- goto out_free_bus;
- }
+ if (mdo && devm_gpio_request_one(dev, mdo, mdo_flags, "mdo"))
+ goto out_free_bus;
dev_set_drvdata(dev, new_bus);
--
2.9.3
^ permalink raw reply related
* [PATCH net-next 1/3] net: mdio-gpio: Use devm_gpio_request_one instead of devm_gpio_request
From: Florian Fainelli @ 2017-01-11 20:59 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, vivien.didelot, cphealy, linux, Florian Fainelli
In-Reply-To: <20170111205951.32363-1-f.fainelli@gmail.com>
From: Guenter Roeck <linux@roeck-us.net>
Using devm_gpio_request_one lets us request gpio pins with initial state
in one go.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/mdio-gpio.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 27ab63064f95..f6e773256c82 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -137,6 +137,9 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
struct mii_bus *new_bus;
struct mdio_gpio_info *bitbang;
int i;
+ unsigned long mdc_flags = GPIOF_OUT_INIT_LOW;
+ unsigned long mdio_flags = GPIOF_DIR_IN;
+ unsigned long mdo_flags = GPIOF_OUT_INIT_HIGH;
bitbang = devm_kzalloc(dev, sizeof(*bitbang), GFP_KERNEL);
if (!bitbang)
@@ -174,21 +177,17 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
else
strncpy(new_bus->id, "gpio", MII_BUS_ID_SIZE);
- if (devm_gpio_request(dev, bitbang->mdc, "mdc"))
+ if (devm_gpio_request_one(dev, bitbang->mdc, mdc_flags, "mdc"))
goto out_free_bus;
- if (devm_gpio_request(dev, bitbang->mdio, "mdio"))
+ if (devm_gpio_request_one(dev, bitbang->mdio, mdio_flags, "mdio"))
goto out_free_bus;
if (bitbang->mdo) {
- if (devm_gpio_request(dev, bitbang->mdo, "mdo"))
+ if (devm_gpio_request_one(dev, bitbang->mdo, mdo_flags, "mdo"))
goto out_free_bus;
- gpio_direction_output(bitbang->mdo, 1);
- gpio_direction_input(bitbang->mdio);
}
- gpio_direction_output(bitbang->mdc, 0);
-
dev_set_drvdata(dev, new_bus);
return new_bus;
--
2.9.3
^ permalink raw reply related
* [PATCH net-next 0/3] net: mdio-gpio: Use modern GPIO helpers
From: Florian Fainelli @ 2017-01-11 20:59 UTC (permalink / raw)
To: netdev; +Cc: davem, andrew, vivien.didelot, cphealy, linux, Florian Fainelli
Hi David,
This patch series modernizes the mdio-gpio and makes it switch to the
latest and greatest API for manipulating GPIO lines, thus allowing
some simplifications in the driver.
Thanks!
Guenter Roeck (3):
net: mdio-gpio: Use devm_gpio_request_one instead of devm_gpio_request
net: mdio-gpio: Convert to use gpiod functions where possible
net: mdio-gpio: Use gpio subsystem to handle low-active pins
drivers/net/phy/mdio-gpio.c | 60 ++++++++++++++++++++++-----------------------
1 file changed, 30 insertions(+), 30 deletions(-)
--
2.9.3
^ permalink raw reply
* Re: TCP using IPv4-mapped IPv6 address as source
From: Sowmini Varadhan @ 2017-01-11 20:58 UTC (permalink / raw)
To: Eric Dumazet
Cc: Jonathan T. Leighton, netdev, edumazet, Yuchung Cheng,
Neal Cardwell
In-Reply-To: <1484167422.15816.1.camel@edumazet-glaptop3.roam.corp.google.com>
On (01/11/17 12:43), Eric Dumazet wrote:
>
> On Wed, 2017-01-11 at 14:59 -0500, Sowmini Varadhan wrote:
>
> > I think the RFC states somewhere that you should never ever
> > send out a v4 mapped address on the wire.
>
> Can you point the exact RFC ?
>
> https://tools.ietf.org/html/rfc2765 seems to allow just that.
I have not read the details of 2765, but from a cursory look,
it talks about "IPv4-translatable addresses", not v4-mapped
addrs, and says,
"The address translation mechanisms for the stateless and the stateful
translations are defined in [RFC6052]"
It's also not clear to me that 2765 warrants the use of these
as ip6 src, or ip6 dst, or the target(s) of NS/NA.
https://www.rfc-editor.org/rfc/rfc4038.txt refers to security
considerations about sending v4-mapped addrs on the wire
Looks like these security considerations are discussed in
https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02
In general, I think BSD and Solaris (and probably most
router implementations, esp the BSD-based ones) will not allow
v4 mapped addresses as src or dst of ip6 packets.
> Jonathan issue is about terminating such flows in TCP stack, which is
> likely not needed/useful.
sure. but if you configure the v4 mapped address as
a src addr "everything should be fine!"
--Sowmini
^ permalink raw reply
* Re: TCP using IPv4-mapped IPv6 address as source
From: Eric Dumazet @ 2017-01-11 20:43 UTC (permalink / raw)
To: Sowmini Varadhan
Cc: Jonathan T. Leighton, netdev, edumazet, Yuchung Cheng,
Neal Cardwell
In-Reply-To: <20170111195909.GL24086@oracle.com>
On Wed, 2017-01-11 at 14:59 -0500, Sowmini Varadhan wrote:
> I think the RFC states somewhere that you should never ever
> send out a v4 mapped address on the wire.
Can you point the exact RFC ?
https://tools.ietf.org/html/rfc2765 seems to allow just that.
Jonathan issue is about terminating such flows in TCP stack, which is
likely not needed/useful.
^ permalink raw reply
* Re: [PATCH] wext: handle NULL exta data in iwe_stream_add_point better
From: Arnd Bergmann @ 2017-01-11 20:39 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, David S. Miller, Networking, linux-kernel
In-Reply-To: <1484147177.29931.14.camel@sipsolutions.net>
On Wednesday, January 11, 2017 4:06:17 PM CET Johannes Berg wrote:
>
> Applied. Also fixed the typo in the subject :)
Thanks! Unfortunately I now got another warning for the same function,
and though I would have expected the patch to fix it, that did not work:
In file included from /git/arm-soc/drivers/net/wireless/intersil/prism54/islpci_dev.h:27:0,
from /git/arm-soc/drivers/net/wireless/intersil/prism54/isl_ioctl.h:24,
from /git/arm-soc/drivers/net/wireless/intersil/prism54/isl_ioctl.c:32:
/git/arm-soc/drivers/net/wireless/intersil/prism54/isl_ioctl.c: In function 'prism54_get_scan':
/git/arm-soc/include/net/iw_handler.h:560:4: error: argument 2 null where non-null expected [-Werror=nonnull]
memcpy(stream + point_len, extra, iwe->u.data.length);
The change below kills that warning too, but it gets even uglier there:
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index 1a41043688bc..c2aa73e5e6bb 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -556,7 +556,7 @@ iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends,
memcpy(stream + lcp_len,
((char *) &iwe->u) + IW_EV_POINT_OFF,
IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
- if (iwe->u.data.length)
+ if (iwe->u.data.length && extra)
memcpy(stream + point_len, extra, iwe->u.data.length);
stream += event_len;
}
Let me know if you want a proper follow-up patch, or if you can amend your
commit, or you have a better idea for resolving that warning.
Arnd
^ permalink raw reply related
* [PATCH 6/6 net-next] inet: reset tb->fastreuseport when adding a reuseport sk
From: Josef Bacik @ 2017-01-11 20:22 UTC (permalink / raw)
To: davem, hannes, kraigatgoog, eric.dumazet, tom, netdev,
kernel-team
In-Reply-To: <1484166164-21250-1-git-send-email-jbacik@fb.com>
If we have non reuseport sockets on a tb we will set tb->fastreuseport to 0 and
never set it again. Which means that in the future if we end up adding a bunch
of reuseport sk's to that tb we'll have to do the expensive scan every time.
Instead add the ipv4/ipv6 saddr fields to the bind bucket, as well as the family
so we know what comparison to make, and the ipv6 only setting so we can make
sure to compare with new sockets appropriately. Once one sk has made it onto
the list we know that there are no potential bind conflicts on the owners list
that match that sk's rcv_addr. So copy the sk's information into our bind
bucket and set tb->fastruseport to FASTREUSESOCK_STRICT so we know we have to do
an extra check for subsequent reuseport sockets and skip the expensive bind
conflict check.
Signed-off-by: Josef Bacik <jbacik@fb.com>
---
include/net/inet_hashtables.h | 9 ++++
net/ipv4/inet_connection_sock.c | 106 ++++++++++++++++++++++++++++++++--------
2 files changed, 95 insertions(+), 20 deletions(-)
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 3fc0366..1178931 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -74,12 +74,21 @@ struct inet_ehash_bucket {
* users logged onto your box, isn't it nice to know that new data
* ports are created in O(1) time? I thought so. ;-) -DaveM
*/
+#define FASTREUSEPORT_ANY 1
+#define FASTREUSEPORT_STRICT 2
+
struct inet_bind_bucket {
possible_net_t ib_net;
unsigned short port;
signed char fastreuse;
signed char fastreuseport;
kuid_t fastuid;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct in6_addr fast_v6_rcv_saddr;
+#endif
+ __be32 fast_rcv_saddr;
+ unsigned short fast_sk_family;
+ bool fast_ipv6_only;
struct hlist_node node;
struct hlist_head owners;
};
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index bbe2892..096a085 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -38,20 +38,21 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg);
* IPV6_ADDR_ANY only equals to IPV6_ADDR_ANY,
* and 0.0.0.0 equals to 0.0.0.0 only
*/
-static int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
+static int ipv6_rcv_saddr_equal(const struct in6_addr *sk1_rcv_saddr6,
+ const struct in6_addr *sk2_rcv_saddr6,
+ __be32 sk1_rcv_saddr, __be32 sk2_rcv_saddr,
+ bool sk1_ipv6only, bool sk2_ipv6only,
bool match_wildcard)
{
- const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
- int sk2_ipv6only = inet_v6_ipv6only(sk2);
- int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr);
+ int addr_type = ipv6_addr_type(sk1_rcv_saddr6);
int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
/* if both are mapped, treat as IPv4 */
if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) {
if (!sk2_ipv6only) {
- if (sk->sk_rcv_saddr == sk2->sk_rcv_saddr)
+ if (sk1_rcv_saddr == sk2_rcv_saddr)
return 1;
- if (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr)
+ if (!sk1_rcv_saddr || !sk2_rcv_saddr)
return match_wildcard;
}
return 0;
@@ -65,11 +66,11 @@ static int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
return 1;
if (addr_type == IPV6_ADDR_ANY && match_wildcard &&
- !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED))
+ !(sk1_ipv6only && addr_type2 == IPV6_ADDR_MAPPED))
return 1;
if (sk2_rcv_saddr6 &&
- ipv6_addr_equal(&sk->sk_v6_rcv_saddr, sk2_rcv_saddr6))
+ ipv6_addr_equal(sk1_rcv_saddr6, sk2_rcv_saddr6))
return 1;
return 0;
@@ -80,13 +81,13 @@ static int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
* match_wildcard == false: addresses must be exactly the same, i.e.
* 0.0.0.0 only equals to 0.0.0.0
*/
-static int ipv4_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
- bool match_wildcard)
+static int ipv4_rcv_saddr_equal(__be32 sk1_rcv_saddr, __be32 sk2_rcv_saddr,
+ bool sk2_ipv6only, bool match_wildcard)
{
- if (!ipv6_only_sock(sk2)) {
- if (sk->sk_rcv_saddr == sk2->sk_rcv_saddr)
+ if (!sk2_ipv6only) {
+ if (sk1_rcv_saddr == sk2_rcv_saddr)
return 1;
- if (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr)
+ if (!sk1_rcv_saddr || !sk2_rcv_saddr)
return match_wildcard;
}
return 0;
@@ -97,9 +98,16 @@ int inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
{
#if IS_ENABLED(CONFIG_IPV6)
if (sk->sk_family == AF_INET6)
- return ipv6_rcv_saddr_equal(sk, sk2, match_wildcard);
+ return ipv6_rcv_saddr_equal(&sk->sk_v6_rcv_saddr,
+ &sk2->sk_v6_rcv_saddr,
+ sk->sk_rcv_saddr,
+ sk2->sk_rcv_saddr,
+ ipv6_only_sock(sk),
+ ipv6_only_sock(sk2),
+ match_wildcard);
#endif
- return ipv4_rcv_saddr_equal(sk, sk2, match_wildcard);
+ return ipv4_rcv_saddr_equal(sk->sk_rcv_saddr, sk2->sk_rcv_saddr,
+ ipv6_only_sock(sk2), match_wildcard);
}
EXPORT_SYMBOL(inet_rcv_saddr_equal);
@@ -234,6 +242,39 @@ inet_csk_find_open_port(struct sock *sk, struct inet_bind_bucket **tb_ret, int *
return head;
}
+static inline int sk_reuseport_match(struct inet_bind_bucket *tb,
+ struct sock *sk)
+{
+ kuid_t uid = sock_i_uid(sk);
+
+ if (tb->fastreuseport <= 0)
+ return 0;
+ if (!sk->sk_reuseport)
+ return 0;
+ if (rcu_access_pointer(sk->sk_reuseport_cb))
+ return 0;
+ if (!uid_eq(tb->fastuid, uid))
+ return 0;
+ /* We only need to check the rcv_saddr if this tb was once marked
+ * without fastreuseport and then was reset, as we can only know that
+ * the fast_*rcv_saddr doesn't have any conflicts with the socks on the
+ * owners list.
+ */
+ if (tb->fastreuseport == FASTREUSEPORT_ANY)
+ return 1;
+#if IS_ENABLED(CONFIG_IPV6)
+ if (tb->fast_sk_family == AF_INET6)
+ return ipv6_rcv_saddr_equal(&tb->fast_v6_rcv_saddr,
+ &sk->sk_v6_rcv_saddr,
+ tb->fast_rcv_saddr,
+ sk->sk_rcv_saddr,
+ tb->fast_ipv6_only,
+ ipv6_only_sock(sk), true);
+#endif
+ return ipv4_rcv_saddr_equal(tb->fast_rcv_saddr, sk->sk_rcv_saddr,
+ ipv6_only_sock(sk), true);
+}
+
/* Obtain a reference to a local port for the given sock,
* if snum is zero it means select any available local port.
* We try to allocate an odd port (and leave even ports for connect())
@@ -273,9 +314,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
goto success;
if ((tb->fastreuse > 0 && reuse) ||
- (tb->fastreuseport > 0 &&
- !rcu_access_pointer(sk->sk_reuseport_cb) &&
- sk->sk_reuseport && uid_eq(tb->fastuid, uid)))
+ sk_reuseport_match(tb, sk))
goto success;
if (inet_csk_bind_conflict(sk, tb, true, true))
goto fail_unlock;
@@ -284,16 +323,43 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
if (!hlist_empty(&tb->owners)) {
tb->fastreuse = reuse;
if (sk->sk_reuseport) {
- tb->fastreuseport = 1;
+ tb->fastreuseport = FASTREUSEPORT_ANY;
tb->fastuid = uid;
+ tb->fast_rcv_saddr = sk->sk_rcv_saddr;
+ tb->fast_ipv6_only = ipv6_only_sock(sk);
+#if IS_ENABLED(CONFIG_IPV6)
+ tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
+#endif
} else {
tb->fastreuseport = 0;
}
} else {
if (!reuse)
tb->fastreuse = 0;
- if (!sk->sk_reuseport || !uid_eq(tb->fastuid, uid))
+ if (sk->sk_reuseport) {
+ /* We didn't match or we don't have fastreuseport set on
+ * the tb, but we have sk_reuseport set on this socket
+ * and we know that there are no bind conflicts with
+ * this socket in this tb, so reset our tb's reuseport
+ * settings so that any subsequent sockets that match
+ * our current socket will be put on the fast path.
+ *
+ * If we reset we need to set FASTREUSEPORT_STRICT so we
+ * do extra checking for all subsequent sk_reuseport
+ * socks.
+ */
+ if (!sk_reuseport_match(tb, sk)) {
+ tb->fastreuseport = FASTREUSEPORT_STRICT;
+ tb->fastuid = uid;
+ tb->fast_rcv_saddr = sk->sk_rcv_saddr;
+ tb->fast_ipv6_only = ipv6_only_sock(sk);
+#if IS_ENABLED(CONFIG_IPV6)
+ tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
+#endif
+ }
+ } else {
tb->fastreuseport = 0;
+ }
}
if (!inet_csk(sk)->icsk_bind_hash)
inet_bind_hash(sk, tb, port);
--
2.5.5
^ permalink raw reply related
* [PATCH 4/6 net-next] inet: don't check for bind conflicts twice when searching for a port
From: Josef Bacik @ 2017-01-11 20:22 UTC (permalink / raw)
To: davem, hannes, kraigatgoog, eric.dumazet, tom, netdev,
kernel-team
In-Reply-To: <1484166164-21250-1-git-send-email-jbacik@fb.com>
This is just wasted time, we've already found a tb that doesn't have a bind
conflict, and we don't drop the head lock so scanning again isn't going to give
us a different answer. Instead move the tb->reuse setting logic outside of the
found_tb path and put it in the success: path. Then make it so that we don't
goto again if we find a bind conflict in the found_tb path as we won't reach
this anymore when we are scanning for an ephemeral port.
Signed-off-by: Josef Bacik <jbacik@fb.com>
---
net/ipv4/inet_connection_sock.c | 31 +++++++++++--------------------
1 file changed, 11 insertions(+), 20 deletions(-)
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index d352366..f7e844d 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -164,7 +164,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
{
bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
- int ret = 1, attempts = 5, port = snum;
+ int ret = 1, port = snum;
struct inet_bind_hashbucket *head;
struct net *net = sock_net(sk);
int i, low, high, attempt_half;
@@ -183,7 +183,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
goto tb_not_found;
}
-again:
attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0;
other_half_scan:
inet_get_local_port_range(net, &low, &high);
@@ -221,7 +220,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
inet_bind_bucket_for_each(tb, &head->chain)
if (net_eq(ib_net(tb), net) && tb->port == port) {
if (!inet_csk_bind_conflict(sk, tb, false, reuseport_ok))
- goto tb_found;
+ goto success;
goto next_port;
}
goto tb_not_found;
@@ -256,23 +255,11 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
!rcu_access_pointer(sk->sk_reuseport_cb) &&
sk->sk_reuseport && uid_eq(tb->fastuid, uid)))
goto success;
- if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok)) {
- if ((reuse ||
- (tb->fastreuseport > 0 &&
- sk->sk_reuseport &&
- !rcu_access_pointer(sk->sk_reuseport_cb) &&
- uid_eq(tb->fastuid, uid))) && !snum &&
- --attempts >= 0) {
- spin_unlock_bh(&head->lock);
- goto again;
- }
+ if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok))
goto fail_unlock;
- }
- if (!reuse)
- tb->fastreuse = 0;
- if (!sk->sk_reuseport || !uid_eq(tb->fastuid, uid))
- tb->fastreuseport = 0;
- } else {
+ }
+success:
+ if (!hlist_empty(&tb->owners)) {
tb->fastreuse = reuse;
if (sk->sk_reuseport) {
tb->fastreuseport = 1;
@@ -280,8 +267,12 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
} else {
tb->fastreuseport = 0;
}
+ } else {
+ if (!reuse)
+ tb->fastreuse = 0;
+ if (!sk->sk_reuseport || !uid_eq(tb->fastuid, uid))
+ tb->fastreuseport = 0;
}
-success:
if (!inet_csk(sk)->icsk_bind_hash)
inet_bind_hash(sk, tb, port);
WARN_ON(inet_csk(sk)->icsk_bind_hash != tb);
--
2.5.5
^ permalink raw reply related
* [PATCH 5/6 net-next] inet: split inet_csk_get_port into two functions
From: Josef Bacik @ 2017-01-11 20:22 UTC (permalink / raw)
To: davem, hannes, kraigatgoog, eric.dumazet, tom, netdev,
kernel-team
In-Reply-To: <1484166164-21250-1-git-send-email-jbacik@fb.com>
inet_csk_get_port does two different things, it either scans for an open port,
or it tries to see if the specified port is available for use. Since these two
operations have different rules and are basically independent lets split them
into two different functions to make them both more readable.
Signed-off-by: Josef Bacik <jbacik@fb.com>
---
net/ipv4/inet_connection_sock.c | 66 +++++++++++++++++++++++++++--------------
1 file changed, 44 insertions(+), 22 deletions(-)
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index f7e844d..bbe2892 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -156,33 +156,21 @@ static int inet_csk_bind_conflict(const struct sock *sk,
return sk2 != NULL;
}
-/* Obtain a reference to a local port for the given sock,
- * if snum is zero it means select any available local port.
- * We try to allocate an odd port (and leave even ports for connect())
+/*
+ * Find an open port number for the socket. Returns with the
+ * inet_bind_hashbucket lock held.
*/
-int inet_csk_get_port(struct sock *sk, unsigned short snum)
+static struct inet_bind_hashbucket *
+inet_csk_find_open_port(struct sock *sk, struct inet_bind_bucket **tb_ret, int *port_ret)
{
- bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
- int ret = 1, port = snum;
+ int port = 0;
struct inet_bind_hashbucket *head;
struct net *net = sock_net(sk);
int i, low, high, attempt_half;
struct inet_bind_bucket *tb;
- kuid_t uid = sock_i_uid(sk);
u32 remaining, offset;
- bool reuseport_ok = !!snum;
- if (port) {
- head = &hinfo->bhash[inet_bhashfn(net, port,
- hinfo->bhash_size)];
- spin_lock_bh(&head->lock);
- inet_bind_bucket_for_each(tb, &head->chain)
- if (net_eq(ib_net(tb), net) && tb->port == port)
- goto tb_found;
-
- goto tb_not_found;
- }
attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0;
other_half_scan:
inet_get_local_port_range(net, &low, &high);
@@ -219,11 +207,12 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
spin_lock_bh(&head->lock);
inet_bind_bucket_for_each(tb, &head->chain)
if (net_eq(ib_net(tb), net) && tb->port == port) {
- if (!inet_csk_bind_conflict(sk, tb, false, reuseport_ok))
+ if (!inet_csk_bind_conflict(sk, tb, false, false))
goto success;
goto next_port;
}
- goto tb_not_found;
+ tb = NULL;
+ goto success;
next_port:
spin_unlock_bh(&head->lock);
cond_resched();
@@ -238,8 +227,41 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
attempt_half = 2;
goto other_half_scan;
}
- return ret;
+ return NULL;
+success:
+ *port_ret = port;
+ *tb_ret = tb;
+ return head;
+}
+
+/* Obtain a reference to a local port for the given sock,
+ * if snum is zero it means select any available local port.
+ * We try to allocate an odd port (and leave even ports for connect())
+ */
+int inet_csk_get_port(struct sock *sk, unsigned short snum)
+{
+ bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
+ struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
+ int ret = 1, port = snum;
+ struct inet_bind_hashbucket *head;
+ struct net *net = sock_net(sk);
+ struct inet_bind_bucket *tb = NULL;
+ kuid_t uid = sock_i_uid(sk);
+ if (!port) {
+ head = inet_csk_find_open_port(sk, &tb, &port);
+ if (!head)
+ return ret;
+ if (!tb)
+ goto tb_not_found;
+ goto success;
+ }
+ head = &hinfo->bhash[inet_bhashfn(net, port,
+ hinfo->bhash_size)];
+ spin_lock_bh(&head->lock);
+ inet_bind_bucket_for_each(tb, &head->chain)
+ if (net_eq(ib_net(tb), net) && tb->port == port)
+ goto tb_found;
tb_not_found:
tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
net, head, port);
@@ -255,7 +277,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
!rcu_access_pointer(sk->sk_reuseport_cb) &&
sk->sk_reuseport && uid_eq(tb->fastuid, uid)))
goto success;
- if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok))
+ if (inet_csk_bind_conflict(sk, tb, true, true))
goto fail_unlock;
}
success:
--
2.5.5
^ permalink raw reply related
* [PATCH 3/6 net-next] inet: kill smallest_size and smallest_port
From: Josef Bacik @ 2017-01-11 20:22 UTC (permalink / raw)
To: davem, hannes, kraigatgoog, eric.dumazet, tom, netdev,
kernel-team
In-Reply-To: <1484166164-21250-1-git-send-email-jbacik@fb.com>
In inet_csk_get_port we seem to be using smallest_port to figure out where the
best place to look for a SO_REUSEPORT sk that matches with an existing set of
SO_REUSEPORT's. However if we get to the logic
if (smallest_size != -1) {
port = smallest_port;
goto have_port;
}
we will do a useless search, because we would have already done the
inet_csk_bind_conflict for that port and it would have returned 1, otherwise we
would have gone to found_tb and succeeded. Since this logic makes us do yet
another trip through inet_csk_bind_conflict for a port we know won't work just
delete this code and save us the time.
Signed-off-by: Josef Bacik <jbacik@fb.com>
---
include/net/inet_hashtables.h | 1 -
net/ipv4/inet_connection_sock.c | 26 ++++----------------------
net/ipv4/inet_hashtables.c | 3 ---
3 files changed, 4 insertions(+), 26 deletions(-)
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 756ed16..3fc0366 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -80,7 +80,6 @@ struct inet_bind_bucket {
signed char fastreuse;
signed char fastreuseport;
kuid_t fastuid;
- int num_owners;
struct hlist_node node;
struct hlist_head owners;
};
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index a1c9055..d352366 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -165,7 +165,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
int ret = 1, attempts = 5, port = snum;
- int smallest_size = -1, smallest_port;
struct inet_bind_hashbucket *head;
struct net *net = sock_net(sk);
int i, low, high, attempt_half;
@@ -175,7 +174,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
bool reuseport_ok = !!snum;
if (port) {
-have_port:
head = &hinfo->bhash[inet_bhashfn(net, port,
hinfo->bhash_size)];
spin_lock_bh(&head->lock);
@@ -209,8 +207,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
* We do the opposite to not pollute connect() users.
*/
offset |= 1U;
- smallest_size = -1;
- smallest_port = low; /* avoid compiler warning */
other_parity_scan:
port = low + offset;
@@ -224,15 +220,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
spin_lock_bh(&head->lock);
inet_bind_bucket_for_each(tb, &head->chain)
if (net_eq(ib_net(tb), net) && tb->port == port) {
- if (((tb->fastreuse > 0 && reuse) ||
- (tb->fastreuseport > 0 &&
- sk->sk_reuseport &&
- !rcu_access_pointer(sk->sk_reuseport_cb) &&
- uid_eq(tb->fastuid, uid))) &&
- (tb->num_owners < smallest_size || smallest_size == -1)) {
- smallest_size = tb->num_owners;
- smallest_port = port;
- }
if (!inet_csk_bind_conflict(sk, tb, false, reuseport_ok))
goto tb_found;
goto next_port;
@@ -243,10 +230,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
cond_resched();
}
- if (smallest_size != -1) {
- port = smallest_port;
- goto have_port;
- }
offset--;
if (!(offset & 1))
goto other_parity_scan;
@@ -268,19 +251,18 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
if (sk->sk_reuse == SK_FORCE_REUSE)
goto success;
- if (((tb->fastreuse > 0 && reuse) ||
+ if ((tb->fastreuse > 0 && reuse) ||
(tb->fastreuseport > 0 &&
!rcu_access_pointer(sk->sk_reuseport_cb) &&
- sk->sk_reuseport && uid_eq(tb->fastuid, uid))) &&
- smallest_size == -1)
+ sk->sk_reuseport && uid_eq(tb->fastuid, uid)))
goto success;
if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok)) {
if ((reuse ||
(tb->fastreuseport > 0 &&
sk->sk_reuseport &&
!rcu_access_pointer(sk->sk_reuseport_cb) &&
- uid_eq(tb->fastuid, uid))) &&
- !snum && smallest_size != -1 && --attempts >= 0) {
+ uid_eq(tb->fastuid, uid))) && !snum &&
+ --attempts >= 0) {
spin_unlock_bh(&head->lock);
goto again;
}
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 2ef9b01..8bea742 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -73,7 +73,6 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
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);
}
@@ -96,7 +95,6 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
{
inet_sk(sk)->inet_num = snum;
sk_add_bind_node(sk, &tb->owners);
- tb->num_owners++;
inet_csk(sk)->icsk_bind_hash = tb;
}
@@ -114,7 +112,6 @@ static void __inet_put_port(struct sock *sk)
spin_lock(&head->lock);
tb = inet_csk(sk)->icsk_bind_hash;
__sk_del_bind_node(sk);
- tb->num_owners--;
inet_csk(sk)->icsk_bind_hash = NULL;
inet_sk(sk)->inet_num = 0;
inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
--
2.5.5
^ permalink raw reply related
* [PATCH 2/6 net-next] inet: drop ->bind_conflict
From: Josef Bacik @ 2017-01-11 20:22 UTC (permalink / raw)
To: davem, hannes, kraigatgoog, eric.dumazet, tom, netdev,
kernel-team
In-Reply-To: <1484165171-19210-1-git-send-email-jbacik@fb.com>
The only difference between inet6_csk_bind_conflict and inet_csk_bind_conflict
is how they check the rcv_saddr, so delete this call back and simply
change inet_csk_bind_conflict to call inet_rcv_saddr_equal.
Signed-off-by: Josef Bacik <jbacik@fb.com>
---
include/net/inet6_connection_sock.h | 5 -----
include/net/inet_connection_sock.h | 6 ------
net/dccp/ipv4.c | 2 +-
net/dccp/ipv6.c | 2 --
net/ipv4/inet_connection_sock.c | 22 +++++++-------------
net/ipv4/tcp_ipv4.c | 2 +-
net/ipv6/inet6_connection_sock.c | 40 -------------------------------------
net/ipv6/tcp_ipv6.c | 2 --
8 files changed, 9 insertions(+), 72 deletions(-)
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index 3212b39..8ec87b6 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -15,16 +15,11 @@
#include <linux/types.h>
-struct inet_bind_bucket;
struct request_sock;
struct sk_buff;
struct sock;
struct sockaddr;
-int inet6_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax,
- bool soreuseport_ok);
-
struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct flowi6 *fl6,
const struct request_sock *req, u8 proto);
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 85ee387..add75c7 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -62,9 +62,6 @@ struct inet_connection_sock_af_ops {
char __user *optval, int __user *optlen);
#endif
void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
- int (*bind_conflict)(const struct sock *sk,
- const struct inet_bind_bucket *tb,
- bool relax, bool soreuseport_ok);
void (*mtu_reduced)(struct sock *sk);
};
@@ -261,9 +258,6 @@ inet_csk_rto_backoff(const struct inet_connection_sock *icsk,
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
-int inet_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax,
- bool soreuseport_ok);
int inet_csk_get_port(struct sock *sk, unsigned short snum);
struct dst_entry *inet_csk_route_req(const struct sock *sk, struct flowi4 *fl4,
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index d859a5c..ed6f99b 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -17,6 +17,7 @@
#include <linux/skbuff.h>
#include <linux/random.h>
+#include <net/addrconf.h>
#include <net/icmp.h>
#include <net/inet_common.h>
#include <net/inet_hashtables.h>
@@ -904,7 +905,6 @@ static const struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
.getsockopt = ip_getsockopt,
.addr2sockaddr = inet_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in),
- .bind_conflict = inet_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index adfc790..08bcdc3 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -937,7 +937,6 @@ static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
.getsockopt = ipv6_getsockopt,
.addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6),
- .bind_conflict = inet6_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -958,7 +957,6 @@ static const struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
.getsockopt = ipv6_getsockopt,
.addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6),
- .bind_conflict = inet6_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index ba597cb..a1c9055 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -116,9 +116,9 @@ void inet_get_local_port_range(struct net *net, int *low, int *high)
}
EXPORT_SYMBOL(inet_get_local_port_range);
-int inet_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax,
- bool reuseport_ok)
+static int inet_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb,
+ bool relax, bool reuseport_ok)
{
struct sock *sk2;
bool reuse = sk->sk_reuse;
@@ -134,7 +134,6 @@ int inet_csk_bind_conflict(const struct sock *sk,
sk_for_each_bound(sk2, &tb->owners) {
if (sk != sk2 &&
- !inet_v6_ipv6only(sk2) &&
(!sk->sk_bound_dev_if ||
!sk2->sk_bound_dev_if ||
sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
@@ -144,23 +143,18 @@ int inet_csk_bind_conflict(const struct sock *sk,
rcu_access_pointer(sk->sk_reuseport_cb) ||
(sk2->sk_state != TCP_TIME_WAIT &&
!uid_eq(uid, sock_i_uid(sk2))))) {
-
- if (!sk2->sk_rcv_saddr || !sk->sk_rcv_saddr ||
- sk2->sk_rcv_saddr == sk->sk_rcv_saddr)
+ if (inet_rcv_saddr_equal(sk, sk2, true))
break;
}
if (!relax && reuse && sk2->sk_reuse &&
sk2->sk_state != TCP_LISTEN) {
-
- if (!sk2->sk_rcv_saddr || !sk->sk_rcv_saddr ||
- sk2->sk_rcv_saddr == sk->sk_rcv_saddr)
+ if (inet_rcv_saddr_equal(sk, sk2, true))
break;
}
}
}
return sk2 != NULL;
}
-EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
/* Obtain a reference to a local port for the given sock,
* if snum is zero it means select any available local port.
@@ -239,8 +233,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
smallest_size = tb->num_owners;
smallest_port = port;
}
- if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false,
- reuseport_ok))
+ if (!inet_csk_bind_conflict(sk, tb, false, reuseport_ok))
goto tb_found;
goto next_port;
}
@@ -281,8 +274,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
sk->sk_reuseport && uid_eq(tb->fastuid, uid))) &&
smallest_size == -1)
goto success;
- if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true,
- reuseport_ok)) {
+ if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok)) {
if ((reuse ||
(tb->fastreuseport > 0 &&
sk->sk_reuseport &&
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 56d756e..dc07734 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -63,6 +63,7 @@
#include <linux/times.h>
#include <linux/slab.h>
+#include <net/addrconf.h>
#include <net/net_namespace.h>
#include <net/icmp.h>
#include <net/inet_hashtables.h>
@@ -1817,7 +1818,6 @@ const struct inet_connection_sock_af_ops ipv4_specific = {
.getsockopt = ip_getsockopt,
.addr2sockaddr = inet_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in),
- .bind_conflict = inet_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 55ee2ea..97074c4 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -28,46 +28,6 @@
#include <net/inet6_connection_sock.h>
#include <net/sock_reuseport.h>
-int inet6_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax,
- bool reuseport_ok)
-{
- const struct sock *sk2;
- bool reuse = !!sk->sk_reuse;
- bool reuseport = !!sk->sk_reuseport && reuseport_ok;
- kuid_t uid = sock_i_uid((struct sock *)sk);
-
- /* We must walk the whole port owner list in this case. -DaveM */
- /*
- * See comment in inet_csk_bind_conflict about sock lookup
- * vs net namespaces issues.
- */
- sk_for_each_bound(sk2, &tb->owners) {
- if (sk != sk2 &&
- (!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) &&
- (!reuseport || !sk2->sk_reuseport ||
- rcu_access_pointer(sk->sk_reuseport_cb) ||
- (sk2->sk_state != TCP_TIME_WAIT &&
- !uid_eq(uid,
- sock_i_uid((struct sock *)sk2))))) {
- if (inet_rcv_saddr_equal(sk, sk2, true))
- break;
- }
- if (!relax && reuse && sk2->sk_reuse &&
- sk2->sk_state != TCP_LISTEN &&
- inet_rcv_saddr_equal(sk, sk2, true))
- break;
- }
- }
-
- return sk2 != NULL;
-}
-EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);
-
struct dst_entry *inet6_csk_route_req(const struct sock *sk,
struct flowi6 *fl6,
const struct request_sock *req,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 228965d..13ba53a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1621,7 +1621,6 @@ static const struct inet_connection_sock_af_ops ipv6_specific = {
.getsockopt = ipv6_getsockopt,
.addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6),
- .bind_conflict = inet6_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -1652,7 +1651,6 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = {
.getsockopt = ipv6_getsockopt,
.addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6),
- .bind_conflict = inet6_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
--
2.5.5
^ permalink raw reply related
* [PATCH 1/6 net-next] inet: collapse ipv4/v6 rcv_saddr_equal functions into one
From: Josef Bacik @ 2017-01-11 20:19 UTC (permalink / raw)
To: davem, hannes, kraigatgoog, eric.dumazet, tom, netdev,
kernel-team
In-Reply-To: <1484165171-19210-1-git-send-email-jbacik@fb.com>
We pass these per-protocol equal functions around in various places, but
we can just have one function that checks the sk->sk_family and then do
the right comparison function. I've also changed the ipv4 version to
not cast to inet_sock since it is unneeded.
Signed-off-by: Josef Bacik <jbacik@fb.com>
---
include/net/addrconf.h | 4 +--
include/net/inet_hashtables.h | 5 +--
include/net/udp.h | 1 -
net/ipv4/inet_connection_sock.c | 72 ++++++++++++++++++++++++++++++++++++++++
net/ipv4/inet_hashtables.c | 16 +++------
net/ipv4/udp.c | 58 +++++++-------------------------
net/ipv6/inet6_connection_sock.c | 4 +--
net/ipv6/inet6_hashtables.c | 46 +------------------------
net/ipv6/udp.c | 2 +-
9 files changed, 95 insertions(+), 113 deletions(-)
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 8f998af..17c6fd8 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -88,9 +88,7 @@ int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
u32 banned_flags);
int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
u32 banned_flags);
-int ipv4_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
- bool match_wildcard);
-int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
+int inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
bool match_wildcard);
void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);
void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr);
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 0574493..756ed16 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -203,10 +203,7 @@ void inet_hashinfo_init(struct inet_hashinfo *h);
bool inet_ehash_insert(struct sock *sk, struct sock *osk);
bool inet_ehash_nolisten(struct sock *sk, struct sock *osk);
-int __inet_hash(struct sock *sk, struct sock *osk,
- int (*saddr_same)(const struct sock *sk1,
- const struct sock *sk2,
- bool match_wildcard));
+int __inet_hash(struct sock *sk, struct sock *osk);
int inet_hash(struct sock *sk);
void inet_unhash(struct sock *sk);
diff --git a/include/net/udp.h b/include/net/udp.h
index 1661791..c9d8b8e 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -204,7 +204,6 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
}
int udp_lib_get_port(struct sock *sk, unsigned short snum,
- int (*)(const struct sock *, const struct sock *, bool),
unsigned int hash2_nulladdr);
u32 udp_flow_hashrnd(void);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 19ea045..ba597cb 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -31,6 +31,78 @@ const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n";
EXPORT_SYMBOL(inet_csk_timer_bug_msg);
#endif
+#if IS_ENABLED(CONFIG_IPV6)
+/* match_wildcard == true: IPV6_ADDR_ANY equals to any IPv6 addresses if IPv6
+ * only, and any IPv4 addresses if not IPv6 only
+ * match_wildcard == false: addresses must be exactly the same, i.e.
+ * IPV6_ADDR_ANY only equals to IPV6_ADDR_ANY,
+ * and 0.0.0.0 equals to 0.0.0.0 only
+ */
+static int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
+ bool match_wildcard)
+{
+ const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
+ int sk2_ipv6only = inet_v6_ipv6only(sk2);
+ int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr);
+ int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
+
+ /* if both are mapped, treat as IPv4 */
+ if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) {
+ if (!sk2_ipv6only) {
+ if (sk->sk_rcv_saddr == sk2->sk_rcv_saddr)
+ return 1;
+ if (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr)
+ return match_wildcard;
+ }
+ return 0;
+ }
+
+ if (addr_type == IPV6_ADDR_ANY && addr_type2 == IPV6_ADDR_ANY)
+ return 1;
+
+ if (addr_type2 == IPV6_ADDR_ANY && match_wildcard &&
+ !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))
+ return 1;
+
+ if (addr_type == IPV6_ADDR_ANY && match_wildcard &&
+ !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED))
+ return 1;
+
+ if (sk2_rcv_saddr6 &&
+ ipv6_addr_equal(&sk->sk_v6_rcv_saddr, sk2_rcv_saddr6))
+ return 1;
+
+ return 0;
+}
+#endif
+
+/* match_wildcard == true: 0.0.0.0 equals to any IPv4 addresses
+ * match_wildcard == false: addresses must be exactly the same, i.e.
+ * 0.0.0.0 only equals to 0.0.0.0
+ */
+static int ipv4_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
+ bool match_wildcard)
+{
+ if (!ipv6_only_sock(sk2)) {
+ if (sk->sk_rcv_saddr == sk2->sk_rcv_saddr)
+ return 1;
+ if (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr)
+ return match_wildcard;
+ }
+ return 0;
+}
+
+int inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
+ bool match_wildcard)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6)
+ return ipv6_rcv_saddr_equal(sk, sk2, match_wildcard);
+#endif
+ return ipv4_rcv_saddr_equal(sk, sk2, match_wildcard);
+}
+EXPORT_SYMBOL(inet_rcv_saddr_equal);
+
void inet_get_local_port_range(struct net *net, int *low, int *high)
{
unsigned int seq;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ca97835..2ef9b01 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -435,10 +435,7 @@ bool inet_ehash_nolisten(struct sock *sk, struct sock *osk)
EXPORT_SYMBOL_GPL(inet_ehash_nolisten);
static int inet_reuseport_add_sock(struct sock *sk,
- struct inet_listen_hashbucket *ilb,
- int (*saddr_same)(const struct sock *sk1,
- const struct sock *sk2,
- bool match_wildcard))
+ struct inet_listen_hashbucket *ilb)
{
struct inet_bind_bucket *tb = inet_csk(sk)->icsk_bind_hash;
struct sock *sk2;
@@ -451,7 +448,7 @@ static int inet_reuseport_add_sock(struct sock *sk,
sk2->sk_bound_dev_if == sk->sk_bound_dev_if &&
inet_csk(sk2)->icsk_bind_hash == tb &&
sk2->sk_reuseport && uid_eq(uid, sock_i_uid(sk2)) &&
- saddr_same(sk, sk2, false))
+ inet_rcv_saddr_equal(sk, sk2, false))
return reuseport_add_sock(sk, sk2);
}
@@ -461,10 +458,7 @@ static int inet_reuseport_add_sock(struct sock *sk,
return 0;
}
-int __inet_hash(struct sock *sk, struct sock *osk,
- int (*saddr_same)(const struct sock *sk1,
- const struct sock *sk2,
- bool match_wildcard))
+int __inet_hash(struct sock *sk, struct sock *osk)
{
struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
struct inet_listen_hashbucket *ilb;
@@ -479,7 +473,7 @@ int __inet_hash(struct sock *sk, struct sock *osk,
spin_lock(&ilb->lock);
if (sk->sk_reuseport) {
- err = inet_reuseport_add_sock(sk, ilb, saddr_same);
+ err = inet_reuseport_add_sock(sk, ilb);
if (err)
goto unlock;
}
@@ -503,7 +497,7 @@ int inet_hash(struct sock *sk)
if (sk->sk_state != TCP_CLOSE) {
local_bh_disable();
- err = __inet_hash(sk, NULL, ipv4_rcv_saddr_equal);
+ err = __inet_hash(sk, NULL);
local_bh_enable();
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 4318d72..d6dddcf 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -137,11 +137,7 @@ EXPORT_SYMBOL(udp_memory_allocated);
static int udp_lib_lport_inuse(struct net *net, __u16 num,
const struct udp_hslot *hslot,
unsigned long *bitmap,
- struct sock *sk,
- int (*saddr_comp)(const struct sock *sk1,
- const struct sock *sk2,
- bool match_wildcard),
- unsigned int log)
+ struct sock *sk, unsigned int log)
{
struct sock *sk2;
kuid_t uid = sock_i_uid(sk);
@@ -153,7 +149,7 @@ 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) &&
- saddr_comp(sk, sk2, true)) {
+ inet_rcv_saddr_equal(sk, sk2, true)) {
if (sk2->sk_reuseport && sk->sk_reuseport &&
!rcu_access_pointer(sk->sk_reuseport_cb) &&
uid_eq(uid, sock_i_uid(sk2))) {
@@ -176,10 +172,7 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num,
*/
static int udp_lib_lport_inuse2(struct net *net, __u16 num,
struct udp_hslot *hslot2,
- struct sock *sk,
- int (*saddr_comp)(const struct sock *sk1,
- const struct sock *sk2,
- bool match_wildcard))
+ struct sock *sk)
{
struct sock *sk2;
kuid_t uid = sock_i_uid(sk);
@@ -193,7 +186,7 @@ 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) &&
- saddr_comp(sk, sk2, true)) {
+ inet_rcv_saddr_equal(sk, sk2, true)) {
if (sk2->sk_reuseport && sk->sk_reuseport &&
!rcu_access_pointer(sk->sk_reuseport_cb) &&
uid_eq(uid, sock_i_uid(sk2))) {
@@ -208,10 +201,7 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num,
return res;
}
-static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot,
- int (*saddr_same)(const struct sock *sk1,
- const struct sock *sk2,
- bool match_wildcard))
+static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot)
{
struct net *net = sock_net(sk);
kuid_t uid = sock_i_uid(sk);
@@ -225,7 +215,7 @@ static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot,
(udp_sk(sk2)->udp_port_hash == udp_sk(sk)->udp_port_hash) &&
(sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
sk2->sk_reuseport && uid_eq(uid, sock_i_uid(sk2)) &&
- (*saddr_same)(sk, sk2, false)) {
+ inet_rcv_saddr_equal(sk, sk2, false)) {
return reuseport_add_sock(sk, sk2);
}
}
@@ -241,14 +231,10 @@ static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot,
*
* @sk: socket struct in question
* @snum: port number to look up
- * @saddr_comp: AF-dependent comparison of bound local IP addresses
* @hash2_nulladdr: AF-dependent hash value in secondary hash chains,
* with NULL address
*/
int udp_lib_get_port(struct sock *sk, unsigned short snum,
- int (*saddr_comp)(const struct sock *sk1,
- const struct sock *sk2,
- bool match_wildcard),
unsigned int hash2_nulladdr)
{
struct udp_hslot *hslot, *hslot2;
@@ -277,7 +263,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
bitmap_zero(bitmap, PORTS_PER_CHAIN);
spin_lock_bh(&hslot->lock);
udp_lib_lport_inuse(net, snum, hslot, bitmap, sk,
- saddr_comp, udptable->log);
+ udptable->log);
snum = first;
/*
@@ -310,12 +296,11 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
if (hslot->count < hslot2->count)
goto scan_primary_hash;
- exist = udp_lib_lport_inuse2(net, snum, hslot2,
- sk, saddr_comp);
+ exist = udp_lib_lport_inuse2(net, snum, hslot2, sk);
if (!exist && (hash2_nulladdr != slot2)) {
hslot2 = udp_hashslot2(udptable, hash2_nulladdr);
exist = udp_lib_lport_inuse2(net, snum, hslot2,
- sk, saddr_comp);
+ sk);
}
if (exist)
goto fail_unlock;
@@ -323,8 +308,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
goto found;
}
scan_primary_hash:
- if (udp_lib_lport_inuse(net, snum, hslot, NULL, sk,
- saddr_comp, 0))
+ if (udp_lib_lport_inuse(net, snum, hslot, NULL, sk, 0))
goto fail_unlock;
}
found:
@@ -333,7 +317,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
udp_sk(sk)->udp_portaddr_hash ^= snum;
if (sk_unhashed(sk)) {
if (sk->sk_reuseport &&
- udp_reuseport_add_sock(sk, hslot, saddr_comp)) {
+ udp_reuseport_add_sock(sk, hslot)) {
inet_sk(sk)->inet_num = 0;
udp_sk(sk)->udp_port_hash = 0;
udp_sk(sk)->udp_portaddr_hash ^= snum;
@@ -365,24 +349,6 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
}
EXPORT_SYMBOL(udp_lib_get_port);
-/* match_wildcard == true: 0.0.0.0 equals to any IPv4 addresses
- * match_wildcard == false: addresses must be exactly the same, i.e.
- * 0.0.0.0 only equals to 0.0.0.0
- */
-int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2,
- bool match_wildcard)
-{
- struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
-
- if (!ipv6_only_sock(sk2)) {
- if (inet1->inet_rcv_saddr == inet2->inet_rcv_saddr)
- return 1;
- if (!inet1->inet_rcv_saddr || !inet2->inet_rcv_saddr)
- return match_wildcard;
- }
- return 0;
-}
-
static u32 udp4_portaddr_hash(const struct net *net, __be32 saddr,
unsigned int port)
{
@@ -398,7 +364,7 @@ int udp_v4_get_port(struct sock *sk, unsigned short snum)
/* precompute partial secondary hash */
udp_sk(sk)->udp_portaddr_hash = hash2_partial;
- return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal, hash2_nulladdr);
+ return udp_lib_get_port(sk, snum, hash2_nulladdr);
}
static int compute_score(struct sock *sk, struct net *net,
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 7396e75..55ee2ea 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -54,12 +54,12 @@ int inet6_csk_bind_conflict(const struct sock *sk,
(sk2->sk_state != TCP_TIME_WAIT &&
!uid_eq(uid,
sock_i_uid((struct sock *)sk2))))) {
- if (ipv6_rcv_saddr_equal(sk, sk2, true))
+ if (inet_rcv_saddr_equal(sk, sk2, true))
break;
}
if (!relax && reuse && sk2->sk_reuse &&
sk2->sk_state != TCP_LISTEN &&
- ipv6_rcv_saddr_equal(sk, sk2, true))
+ inet_rcv_saddr_equal(sk, sk2, true))
break;
}
}
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 02761c9..d090091 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -268,54 +268,10 @@ int inet6_hash(struct sock *sk)
if (sk->sk_state != TCP_CLOSE) {
local_bh_disable();
- err = __inet_hash(sk, NULL, ipv6_rcv_saddr_equal);
+ err = __inet_hash(sk, NULL);
local_bh_enable();
}
return err;
}
EXPORT_SYMBOL_GPL(inet6_hash);
-
-/* match_wildcard == true: IPV6_ADDR_ANY equals to any IPv6 addresses if IPv6
- * only, and any IPv4 addresses if not IPv6 only
- * match_wildcard == false: addresses must be exactly the same, i.e.
- * IPV6_ADDR_ANY only equals to IPV6_ADDR_ANY,
- * and 0.0.0.0 equals to 0.0.0.0 only
- */
-int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
- bool match_wildcard)
-{
- const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
- int sk2_ipv6only = inet_v6_ipv6only(sk2);
- int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr);
- int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
-
- /* if both are mapped, treat as IPv4 */
- if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) {
- if (!sk2_ipv6only) {
- if (sk->sk_rcv_saddr == sk2->sk_rcv_saddr)
- return 1;
- if (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr)
- return match_wildcard;
- }
- return 0;
- }
-
- if (addr_type == IPV6_ADDR_ANY && addr_type2 == IPV6_ADDR_ANY)
- return 1;
-
- if (addr_type2 == IPV6_ADDR_ANY && match_wildcard &&
- !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))
- return 1;
-
- if (addr_type == IPV6_ADDR_ANY && match_wildcard &&
- !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED))
- return 1;
-
- if (sk2_rcv_saddr6 &&
- ipv6_addr_equal(&sk->sk_v6_rcv_saddr, sk2_rcv_saddr6))
- return 1;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(ipv6_rcv_saddr_equal);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 4d5c4ee..05d6932 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -103,7 +103,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
/* precompute partial secondary hash */
udp_sk(sk)->udp_portaddr_hash = hash2_partial;
- return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr);
+ return udp_lib_get_port(sk, snum, hash2_nulladdr);
}
static void udp_v6_rehash(struct sock *sk)
--
2.5.5
^ permalink raw reply related
* Re: net: ti: cpsw-phy-sel: RGMII is not working on AM335x
From: Alex @ 2017-01-11 20:18 UTC (permalink / raw)
To: Teresa Remmet, Andrew Lunn
Cc: David S. Miller, Mugunthan V N, Grygorii Strashko, linux-omap,
netdev
In-Reply-To: <1484150255.3777.13.camel@phytec.de>
Hi Teresa
On 01/11/2017 07:57 AM, Teresa Remmet wrote:
> The phy we use is a KSZ9021. And yes we add delays to the
> phy, as you can see. When looking to the dts documentation I probably
> need to set the phy-mode to "rgmii-id" instead, as the phy is providing
> the delays.
Before the change I submitted, every "rgmii*" link was being set up as
"rgmii-id", regardless of phy-mode. I suspected there might have been
the odd board here or there that used "rgmii" when the actual mode is
"rgmii-id".
What confused me the first time around was that I didn't realize the
delay applies to the phy, not the mac. So "-id" means "the PHY provides
the delays, so don't add delays on the MAC", just like you realized.
> I make a quick test with that change and it is working. So this seems
> to solve my problem. Thank you for the hint.
I'm glad it was an easy fix. Last time I had issues with RGMII, I had to
pull out the oscilloscope.
Alex
> Regards,
> Teresa
>
^ permalink raw reply
* [PATCH 0/6 net-next][V3] Rework inet_csk_get_port
From: Josef Bacik @ 2017-01-11 20:06 UTC (permalink / raw)
To: davem, hannes, kraigatgoog, eric.dumazet, tom, netdev,
kernel-team
Sorry the holidays delayed this a bit. I've made the changes requested and I
also sat down and wrote a reproducer so everybody could see what was happening.
Without my patches my reproducer takes about 50 seconds to run on my 48 CPU
devel box. With my patches it takes 8 seconds.
V2->V3:
-Dropped the fastsock from the tb and instead just carry the saddrs, family, and
ipv6 only flag.
-Reworked the helper functions to deal with this change so I could still use
them when checking the fast path.
-Killed tb->num_owners as per Eric's request.
-Attached a reproducer to the bottom of this email.
V1->V2:
-Added a new patch 'inet: collapse ipv4/v6 rcv_saddr_equal functions into one'
at Hannes' suggestion.
-Dropped ->bind_conflict and just use the new helper.
-Fixed a compile bug from the original ->bind_conflict patch.
The original description of the series follows
=========================================================
At some point recently the guys working on our load balancer added the ability
to use SO_REUSEPORT. When they restarted their app with this option enabled
they immediately hit a softlockup on what appeared to be the
inet_bind_bucket->lock. Eventually what all of our debugging and discussion led
us to was the fact that the application comes up without SO_REUSEPORT, shuts
down which creates around 100k twsk's, and then comes up and tries to open a
bunch of sockets using SO_REUSEPORT, which meant traversing the inet_bind_bucket
owners list under the lock. Since this lock is needed for dealing with the
twsk's and basically anything else related to connections we would softlockup,
and sometimes not ever recover.
To solve this problem I did what you see in Path 5/5. Once we have a
SO_REUSEPORT socket on the tb->owners list we know that the socket has no
conflicts with any of the other sockets on that list. So we can add a copy of
the sock_common (really all we need is the recv_saddr but it seemed ugly to copy
just the ipv6, ipv4, and flag to indicate if we were ipv6 only in there so I've
copied the whole common) in order to check subsequent SO_REUSEPORT sockets. If
they match the previous one then we can skip the expensive
inet_csk_bind_conflict check. This is what eliminated the soft lockup that we
were seeing.
Patches 1-4 are cleanups and re-workings. For instance when we specify port ==
0 we need to find an open port, but we would do two passes through
inet_csk_bind_conflict every time we found a possible port. We would also keep
track of the smallest_port value in order to try and use it if we found no
port our first run through. This however made no sense as it would have had to
fail the first pass through inet_csk_bind_conflict, so would not actually pass
the second pass through either. Finally I split the function into two functions
in order to make it easier to read and to distinguish between the two behaviors.
I have tested this on one of our load balancing boxes during peak traffic and it
hasn't fallen over. But this is not my area, so obviously feel free to point
out where I'm being stupid and I'll get it fixed up and retested. Thanks,
Josef
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <errno.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
static int ready = 0;
static int done = 0;
static void sigint_handler(int s)
{
ready = 1;
}
static int create_sock(int socktype, int soreuseport)
{
struct addrinfo hints;
struct addrinfo *ai, *ai_orig;
const char *addrs[] = {"::", "0.0.0.0", NULL};
const char *port = "9999";
int sock;
int num_socks = 0;
int i, ret;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = (socktype == 0) ? AF_INET6 : AF_INET;
hints.ai_protocol = IPPROTO_TCP;
ret = getaddrinfo(addrs[socktype], port, &hints, &ai);
if (ret < 0) {
fprintf(stderr, "couldn't get addr info %d\n", errno);
return -1;
}
ai_orig = ai;
while (ai != NULL) {
int yes = 1;
sock = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (sock < 0) {
fprintf(stderr, "socket failed %d\n", errno);
goto next;
}
if (soreuseport) {
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &yes,
sizeof(yes)) < 0) {
fprintf(stderr, "setsockopt failed %d\n", errno);
close(sock);
goto next;
}
}
if (bind(sock, ai->ai_addr, ai->ai_addrlen)) {
fprintf(stderr, "bind failed %d\n", errno);
close(sock);
goto next;
}
if (listen(sock, 1024) < 0) {
fprintf(stderr, "listen failed %d\n", errno);
close(sock);
goto next;
}
num_socks++;
break;
next:
ai = ai->ai_next;
}
freeaddrinfo(ai_orig);
if (!num_socks) {
fprintf(stderr, "failed to open any sockets\n");
return -1;
}
return sock;
}
#define SOCK_PATH "THIS_SHIT_IS_FUCKING_INSANE"
#define TAKEOVER_REQUEST 1
#define CLOSE_REQUEST 2
static int *takeover_sockets(int *num_fds_ret)
{
struct sockaddr_un remote;
struct msghdr msg = {};
struct cmsghdr *cmsg;
struct iovec iov;
int *fds;
int req, num_fds, fd, i, len;
char *buf;
*num_fds_ret = 0;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
fprintf(stderr, "Couldn't open our unix sock\n");
return NULL;
}
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SOCK_PATH);
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
if (connect(fd, (struct sockaddr *)&remote, len) < 0) {
fprintf(stderr, "Couldn't connect, %d\n", errno);
close(fd);
return NULL;
}
req = TAKEOVER_REQUEST;
if (send(fd, &req, sizeof(req), 0) < 0) {
fprintf(stderr, "Couldn't send our request, %d\n", errno);
close(fd);
return NULL;
}
buf = malloc(CMSG_SPACE(sizeof(int) * 32));
if (!buf) {
fprintf(stderr, "Failed to allocate cmsg buffer\n");
free(fds);
close(fd);
return NULL;
}
iov.iov_base = &num_fds;
iov.iov_len = sizeof(num_fds);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = buf;
msg.msg_controllen = CMSG_SPACE(sizeof(int) * 1);
if (recvmsg(fd, &msg, 0) < 0) {
fprintf(stderr, "Couldn't get our array of fd's, %d\n", errno);
free(fds);
close(fd);
return NULL;
}
fds = malloc(sizeof(int) * num_fds);
if (!fds) {
fprintf(stderr, "Couldn't allocate an array for %d fd's\n", num_fds);
close(fd);
return NULL;
}
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
int *fdsptr = (int *)CMSG_DATA(cmsg);
for (i = 0; i < num_fds; i++) {
int newfd = fdsptr[i];
int yes = 1;
if (newfd < 0) {
fprintf(stderr, "Couldn't dup the old socket, %d\n", errno);
close(fd);
num_fds = i;
break;
}
if (setsockopt(newfd, SOL_SOCKET, SO_REUSEPORT, &yes,
sizeof(yes)) < 0) {
fprintf(stderr, "setsockopt failed on taken over socket %d\n",
errno);
close(newfd);
close(fd);
break;
}
fds[i] = newfd;
}
}
req = CLOSE_REQUEST;
if (send(fd, &req, sizeof(req), 0) < 0)
fprintf(stderr, "Couldn't send the close request, %d\n", errno);
close(fd);
*num_fds_ret = num_fds;
return fds;
}
static int listen_for_takeover(pid_t child, int *fds, int num_fds)
{
struct sockaddr_un local, remote;
int sock, len;
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "Couldn't open unix sock %d\n", errno);
kill(child, SIGINT);
return -1;
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(sock, (struct sockaddr *)&local, len) < 0) {
fprintf(stderr, "Couldn't bind to unix sock %d\n", errno);
kill(child, SIGINT);
return -1;
}
if (listen(sock, 1) < 0) {
fprintf(stderr, "Couldn't listen on unix sock %d\n", errno);
kill(child, SIGINT);
return -1;
}
kill(child, SIGINT);
while (!done) {
int newsock, req, len = sizeof(remote);
if ((newsock = accept(sock, (struct sockaddr *)&remote,
&len)) < 0) {
fprintf(stderr, "Couldn't accept connection %d\n", errno);
return -1;
}
while (recv(newsock, &req, sizeof(req), 0) > 0) {
if (req == TAKEOVER_REQUEST) {
struct msghdr msg = {};
struct cmsghdr *cmsg;
struct iovec iov = {.iov_base = &num_fds, .iov_len = sizeof(num_fds), };
char *buf;
int *fdptr;
buf = malloc(CMSG_SPACE(sizeof(int) * num_fds));
if (!buf) {
fprintf(stderr, "Couldn't allocate cmsg buf\n");
return -1;
}
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = buf;
msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
fdptr = (int *)CMSG_DATA(cmsg);
memcpy(fdptr, fds, num_fds * sizeof(int));
msg.msg_controllen = cmsg->cmsg_len;
if (sendmsg(newsock, &msg, 0) < 0) {
fprintf(stderr, "Failed to send fds %d\n", errno);
return -1;
}
} else if (req == CLOSE_REQUEST) {
break;
}
}
done = 1;
}
return 0;
}
static void *thread_main(void *arg)
{
int i;
for (i = 0; i < 256; i++) {
int fd = create_sock(0, 1);
if (fd < 0)
return (void *)(unsigned long)fd;
}
return NULL;
}
static int do_spawn_threads(int num_threads)
{
struct sigaction sa;
pthread_t *threads;
int *fds;
int num_fds;
int error = 0;
int i;
threads = calloc(sizeof(pthread_t), num_threads);
if (!threads) {
fprintf(stderr, "Not enough memory\n");
return -1;
}
sa.sa_handler = sigint_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGINT, &sa, NULL) < 0) {
fprintf(stderr, "Couldn't set our sigaction\n");
return -1;
}
while (!ready)
sleep(1);
fds = takeover_sockets(&num_fds);
printf("Starting new threads\n");
for (i = 0; i < num_threads; i++) {
if (pthread_create(&threads[i], NULL, thread_main, NULL) < 0) {
done = 1;
break;
}
}
while (i--) {
void *retval;
pthread_join(threads[i], &retval);
if ((unsigned long)retval != 0)
error = (int)(unsigned long)retval;
}
return error;
}
int main(int argc, char **argv)
{
int *fds;
int num_fds;
pthread_t *threads;
unsigned long i;
int ret = -1;
int childstatus;
pid_t child;
child = fork();
if (child < 0) {
fprintf(stderr, "Failed to create child! %d\n", errno);
return -1;
}
if (!child) {
return do_spawn_threads(64);
}
fds = malloc(sizeof(int));
if (!fds) {
kill(child, SIGINT);
goto out;
}
fds[0] = create_sock(0, 0);
if (fds[0] < 0) {
free(fds);
kill(child, SIGINT);
fprintf(stderr, "Couldn't create a socket\n");
goto out;
}
ret = listen_for_takeover(child, fds, 1);
out:
waitpid(child, &childstatus, 0);
if (!ret)
ret = WEXITSTATUS(childstatus);
return ret;
}
^ permalink raw reply
* Re: [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs.
From: Guenter Roeck @ 2017-01-11 20:00 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Vivien Didelot, David Miller, netdev, Florian Fainelli
In-Reply-To: <20170111191643.GC13033@lunn.ch>
On Wed, Jan 11, 2017 at 08:16:43PM +0100, Andrew Lunn wrote:
> > This makes it kind
> > of a circular argument (not that the dsa hwmon driver supports the
> > new API anyway, but still).
>
> Actually, the code i posted does. I didn't just move it, i re-wrote it
> to use devm_hwmon_device_register_with_info().
>
Cool. Sorry, I didn't remember. Then maybe you should ask for the core
to support the necessary callback ;-).
Guenter
^ permalink raw reply
* Re: TCP using IPv4-mapped IPv6 address as source
From: Sowmini Varadhan @ 2017-01-11 19:59 UTC (permalink / raw)
To: Jonathan T. Leighton
Cc: Eric Dumazet, netdev, edumazet, Yuchung Cheng, Neal Cardwell
In-Reply-To: <14f352f9-6c0a-17da-f28f-b23fe8ecd2a2@udel.edu>
On (01/11/17 14:48), Jonathan T. Leighton wrote:
>
> I would say that an IPv6 socket binds to an IPv4-mapped IPv6
> address, but yes - using it to connect to an IPv6 address would be
> an application bug. It also think that having connect() spend 2
> minutes sending packets containing an illegal source address is a
> bug. (And unfriendly!) I'll look into writing a patch for this, and
> let you know whether or not I think I'm up to it.
>
BTW, linux probably has a number of bugs in this space.
you can do a number of "interesting" things, where the
v4-mapped address ends up being treated as a global address.
E.g., you can configure a v4 mapped address on an interface
using /sbin/ip, then you can add an onlink route, like
# ip -6 route add ::ffff:13.0.0.1 nexthop onlink dev eth1
and you can ping6 ::ffff:13.0.0.1, and (if you do this
on both sides) watch a merry little packet exchange on
the wire, where we send out an NS for ::ffff:13.0.0.1
to the solmcast of the v4 mapped address, the peer politely
responds, and the 2 nodes then have a nice chat.
I think the RFC states somewhere that you should never ever
send out a v4 mapped address on the wire.
--Sowmini
^ permalink raw reply
* Re: [PATCH net-next 5/6] bnxt_en: Pass RoCE app priority to firmware.
From: Michael Chan @ 2017-01-11 19:53 UTC (permalink / raw)
To: Doug Ledford; +Cc: David Miller, Selvin Xavier, Netdev
In-Reply-To: <1484159648.2149.42.camel@redhat.com>
On Wed, Jan 11, 2017 at 10:34 AM, Doug Ledford <dledford@redhat.com> wrote:
> On Wed, 2017-01-11 at 09:17 -0800, Michael Chan wrote:
>> On Wed, Jan 11, 2017 at 7:46 AM, David Miller <davem@davemloft.net>
>> wrote:
>> >
>> > From: Michael Chan <michael.chan@broadcom.com>
>> > Date: Tue, 10 Jan 2017 20:12:38 -0500
>> >
>> > >
>> > > diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h
>> > > b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h
>> > > index 35a0d28..f2630cc 100644
>> > > --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h
>> > > +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h
>> > > @@ -36,6 +36,9 @@ struct bnxt_cos2bw_cfg {
>> > >
>> > > #define HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL 0x0300
>> > >
>> > > +#define ETH_P_ROCE 0x8915
>> >
>> > There's also a similar define in the qedr infiniband driver, this
>> > doesn't
>> > make much sense.
>> >
>> > Please add this to if_ether.h, and reference it from there in the
>> > drivers.
>> >
>> My colleague informed me that he has submitted a patch to do that
>> through the rdma tree:
>>
>> http://marc.info/?l=linux-rdma&m=148217575500983&w=2
>>
>> But it hasn't been merged yet. I can drop this patch now and wait
>> for
>> the RDMA patch to show up on net-next. Or I make the change later to
>> use the common define when the RDMA patch is merged. Thanks.
>
> The patch for this is in my for-next area:
>
> 69ae543969ab RDMA: Adding ethertype ETH_P_IBOE
>
David, can you take the patch now and I will fix it later to use
ETH_P_IBOE when the RDMA patch is pulled into net-next? Or should I
drop the patch for now?
^ permalink raw reply
* Re: TCP using IPv4-mapped IPv6 address as source
From: Jonathan T. Leighton @ 2017-01-11 19:48 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, edumazet, Yuchung Cheng, Neal Cardwell
In-Reply-To: <1484159519.21472.72.camel@edumazet-glaptop3.roam.corp.google.com>
On 1/11/17 1:31 PM, Eric Dumazet wrote:
> On Wed, 2017-01-11 at 12:34 -0500, Jonathan T. Leighton wrote:
>> On 1/11/17 11:20 AM, Eric Dumazet wrote:
>>> On Thu, 2017-01-05 at 16:25 -0500, Jonathan T. Leighton wrote:
>>>> I've observed TCP using an IPv4-mapped IPv6 address as the source
>>>> address, which I believe contradicts
>>>> https://tools.ietf.org/html/rfc6890#page-14 (BCP 153). This occurs when
>>>> an IPv6 TCP socket, bound to a local IPv4-mapped IPv6 address, attempts
>>>> to connect to a remote IPv6 address. Presumable connect() should return
>>>> EAFNOSUPPORT in this case. Please advise me if this is not to
>>>> appropriate list to report this.
>>> Hi Jonathan
>>>
>>> I believe your concern makes sense.
>>> Do you have a patch to address this issue ?
>> Thanks for responding Eric. I have limited experience with kernel
>> patches. Nevertheless, unless there's someone with the experience and
>> time to jump on this, I'm interested in taking a crack at it. I think
>> the issue certainly warrants attention: instead of returning immediately
>> with EAFNOSUPPPORT, connect() retransmits its SYN 6 times, ultimately
>> returning ETIMEDOUT after 127 sec (1+2+4+...+64).
> I am not aware of an application trying to perform a bind() to an IPV4
> address before a connect() to an IPv6 destination.
>
> A kernel fix is certainly something that would detect application bugs
> in a more friendly way.
I would say that an IPv6 socket binds to an IPv4-mapped IPv6 address,
but yes - using it to connect to an IPv6 address would be an application
bug. It also think that having connect() spend 2 minutes sending packets
containing an illegal source address is a bug. (And unfriendly!) I'll
look into writing a patch for this, and let you know whether or not I
think I'm up to it.
- Jon
> Thanks !
>
>
^ 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