* Re: [PATCH] net: can: sja1000: peak_pcmcia.c: Cleaning up missing null-terminate in conjunction with strncpy
From: Stephane Grosjean @ 2014-09-15 8:02 UTC (permalink / raw)
To: Rickard Strandqvist, Wolfgang Grandegger, Marc Kleine-Budde
Cc: Christopher R. Baker, linux-can, netdev, linux-kernel
In-Reply-To: <1410715833-15809-1-git-send-email-rickard_strandqvist@spectrumdigital.se>
Acked-by: Stephane Grosjean <s.grosjean@peak-system.com>
Le 14/09/2014 19:30, Rickard Strandqvist a écrit :
> Replacing strncpy with strlcpy to avoid strings that lacks null terminate.
>
> Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
> ---
> drivers/net/can/sja1000/peak_pcmcia.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c
> index dd56133..fc9f8b01 100644
> --- a/drivers/net/can/sja1000/peak_pcmcia.c
> +++ b/drivers/net/can/sja1000/peak_pcmcia.c
> @@ -487,7 +487,7 @@ static void pcan_free_channels(struct pcan_pccard *card)
> if (!netdev)
> continue;
>
> - strncpy(name, netdev->name, IFNAMSIZ);
> + strlcpy(name, netdev->name, IFNAMSIZ);
>
> unregister_sja1000dev(netdev);
>
--
PEAK-System Technik GmbH, Otto-Roehm-Strasse 69, D-64293 Darmstadt
Geschaeftsleitung: A.Gach/U.Wilhelm,St.Nr.:007/241/13586 FA Darmstadt
HRB-9183 Darmstadt, Ust.IdNr.:DE 202220078, WEE-Reg.-Nr.: DE39305391
Tel.+49 (0)6151-817320 / Fax:+49 (0)6151-817329, info@peak-system.com
--
^ permalink raw reply
* Re: [PATCH] net: can: usb: peak_usb: pcan_usb_core.c: Cleaning up missing null-terminate in conjunction with strncpy
From: Stephane Grosjean @ 2014-09-15 8:01 UTC (permalink / raw)
To: Rickard Strandqvist, Wolfgang Grandegger, Marc Kleine-Budde
Cc: Oliver Hartkopp, Alexey Khoroshilov, Christopher R. Baker,
linux-can, netdev, linux-kernel
In-Reply-To: <1410715898-15904-1-git-send-email-rickard_strandqvist@spectrumdigital.se>
Acked-by: Stephane Grosjean <s.grosjean@peak-system.com>
Le 14/09/2014 19:31, Rickard Strandqvist a écrit :
> Replacing strncpy with strlcpy to avoid strings that lacks null terminate.
>
> Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
> ---
> drivers/net/can/usb/peak_usb/pcan_usb_core.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
> index 644e6ab..d4fe8ac 100644
> --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
> +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
> @@ -830,7 +830,7 @@ static void peak_usb_disconnect(struct usb_interface *intf)
> char name[IFNAMSIZ];
>
> dev->state &= ~PCAN_USB_STATE_CONNECTED;
> - strncpy(name, netdev->name, IFNAMSIZ);
> + strlcpy(name, netdev->name, IFNAMSIZ);
>
> unregister_netdev(netdev);
> free_candev(netdev);
--
PEAK-System Technik GmbH, Otto-Roehm-Strasse 69, D-64293 Darmstadt
Geschaeftsleitung: A.Gach/U.Wilhelm,St.Nr.:007/241/13586 FA Darmstadt
HRB-9183 Darmstadt, Ust.IdNr.:DE 202220078, WEE-Reg.-Nr.: DE39305391
Tel.+49 (0)6151-817320 / Fax:+49 (0)6151-817329, info@peak-system.com
--
^ permalink raw reply
* Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
From: Richard Alpe @ 2014-09-15 7:55 UTC (permalink / raw)
To: David Miller; +Cc: netdev, tipc-discussion
In-Reply-To: <20140912.171038.1165432718811920305.davem@davemloft.net>
On 09/12/2014 11:10 PM, David Miller wrote:
> From: <richard.alpe@ericsson.com>
> Date: Thu, 11 Sep 2014 10:29:17 +0200
>
>> + list_for_each_entry_from(p, &tsk->publications, pport_list) {
>> + publ = nla_nest_start(skb, TIPC_NLA_SOCK_PUBL);
>> + if (nla_put_u32(skb, TIPC_NLA_PUBL_TYPE, p->type))
>> + goto msg_full;
>> + if (nla_put_u32(skb, TIPC_NLA_PUBL_LOWER, p->lower))
>> + goto msg_full;
>> + if (nla_put_u32(skb, TIPC_NLA_PUBL_UPPER, p->upper))
>> + goto msg_full;
>> + nla_nest_end(skb, publ);
>> + }
>> +
>> + *prev_publ = 0;
>> +
>> + return 0;
>> +
>> +msg_full:
>> + *prev_publ = p->key;
>> + nla_nest_cancel(skb, publ);
>
> This restart mechanism is broken.
>
> You can't public nested information this way.
>
> What happens in your code is that if we hit the limit in the middle of
> adding the publications, the next time we'll put the same socket into
> the netlink message and then the rest of the nested publications.
> That's malformed.
Yes, that's true.
> You can't just say sometimes you'll partially list the set of nested
> attributes in an object, you must public the entire object fully in
> the netlink message or skip the object entirely.
Ok. I bluntly assumed we could put some reassemble logic in the client
as the end integrity should still be preserved(?).
> I would suggest that you instead size the amount of space you'll
> need for at least the first socket being listed, and if NLMSG_GOODSIZE
> is insufficient, allocate as much as you will actually need.
>
> Then you put full socket netlink blobs in there, including all nested
> attributes, and then stop and reset back the the most recent full socket
> published if you run out of space.
The amount of publications a socket can have is large (~65 000). Do you
still think this a viable solution?
I thought about querying socket publications individually. Meaning that
the user-space tool would have to first list sockets, then ask for there
publications. This would remove the nested malformation but create some
overhead and increase the potential port-gone window. What do you think?
Thanks for the review, much appreciated!
/Richard
^ permalink raw reply
* Re: [PATCH v2] net/phy: micrel: Disable asymmetric pause for KSZ9031
From: Mike Looijmans @ 2014-09-15 7:44 UTC (permalink / raw)
To: David Miller; +Cc: f.fainelli, netdev, linux-kernel
In-Reply-To: <20140912.181820.1440041146938289489.davem@davemloft.net>
On 09/13/2014 12:18 AM, David Miller wrote:
> From: Mike Looijmans <mike.looijmans@topic.nl>
> Date: Fri, 12 Sep 2014 14:40:37 +0200
>
>> The KSZ9031 appears to suffer from the same hardware bug as described
>> for the KSZ9021 in commit 32fcafbcd1c9f6c7013016a22a5369b4acb93577
>> ("net/phy: micrel: Disable asymmetric pause for KSZ9021")
>> you have to unplug the cable and plug it back to get it to work.
>>
>> Remove the SUPPORTED_Asym_Pause flag for the KSZ9031 to fix this.
>>
>> Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>
>
> This patch does not apply cleanly to the net tree, please respin.
>
Okay, just tell me where to find this branch?
Mike.
Met vriendelijke groet / kind regards,
Mike Looijmans
TOPIC Embedded Systems
Eindhovenseweg 32-C, NL-5683 KH Best
Postbus 440, NL-5680 AK Best
Telefoon: (+31) (0) 499 33 69 79
Telefax: (+31) (0) 499 33 69 70
E-mail: mike.looijmans@topic.nl
Website: www.topic.nl
Please consider the environment before printing this e-mail
Topic zoekt gedreven (embedded) software specialisten!
http://topic.nl/vacatures/topic-zoekt-software-engineers/
^ permalink raw reply
* Re: [Patch v4 net-next 04/12] net: fec: parser max queue number from dt file
From: Lothar Waßmann @ 2014-09-15 7:39 UTC (permalink / raw)
To: Frank.Li
Cc: b38611, davem, netdev, lznuaa, devicetree, linux, shawn.guo,
linux-arm-kernel
In-Reply-To: <1410555657-10744-5-git-send-email-Frank.Li@freescale.com>
Hi,
Frank.Li@freescale.com wrote:
> From: Fugang Duan <B38611@freescale.com>
>
> By default, the tx/rx queue number is 1, user can config the queue number
> at DTS file like this:
> fsl,num-tx-queues=<3>;
> fsl,num-rx-queues=<3>
>
> Since i.MX6SX enet-AVB IP support multi queues, so use multi queues
> interface to allocate and set up an Ethernet device.
>
> Signed-off-by: Fugang Duan <B38611@freescale.com>
> Signed-off-by: Frank Li <Frank.Li@freescale.com>
> ---
> drivers/net/ethernet/freescale/fec.h | 2 ++
> drivers/net/ethernet/freescale/fec_main.c | 46 ++++++++++++++++++++++++++++++-
> 2 files changed, 47 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
> index b2b91f8..72fb90f 100644
> --- a/drivers/net/ethernet/freescale/fec.h
> +++ b/drivers/net/ethernet/freescale/fec.h
> @@ -356,6 +356,8 @@ struct fec_enet_private {
>
> bool ptp_clk_on;
> struct mutex ptp_clk_mutex;
> + unsigned int num_tx_queues;
> + unsigned int num_rx_queues;
>
> /* The saved address of a sent-in-place packet/buffer, for skfree(). */
> struct fec_enet_priv_tx_q *tx_queue[FEC_ENET_MAX_TX_QS];
> diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
> index 4c0d2ee..2240df0 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -2709,6 +2709,42 @@ static void fec_reset_phy(struct platform_device *pdev)
> }
> #endif /* CONFIG_OF */
>
> +static void
> +fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + int err;
> +
> + *num_tx = *num_rx = 1;
> +
> + if (!np || !of_device_is_available(np))
> + return;
> +
> + /* parse the num of tx and rx queues */
> + err = of_property_read_u32(np, "fsl,num-tx-queues", num_tx);
> + err |= of_property_read_u32(np, "fsl,num-rx-queues", num_rx);
> + if (err) {
> + *num_tx = 1;
> + *num_rx = 1;
Shouldn't these be handled seperately? So that if only one of those
properties is given in DT the specified value for that property should
be used?
> + return;
> + }
> +
> + if (*num_tx < 1 || *num_tx > FEC_ENET_MAX_TX_QS) {
> + dev_err(&pdev->dev, "Invalidate num_tx(=%d), fail back to 1\n",
>
s/Invalidate/Invalid/
s/fail/fall/
If the problem is fixed up by the driver rather than leading to an
error exit it should be dev_warn() rather than dev_err().
> + *num_tx);
> + *num_tx = 1;
> + return;
> + }
> +
> + if (*num_rx < 1 || *num_rx > FEC_ENET_MAX_RX_QS) {
> + dev_err(&pdev->dev, "Invalidate num_rx(=%d), fail back to 1\n",
dto.
> + *num_rx);
> + *num_rx = 1;
> + return;
> + }
> +
> +}
> +
> static int
> fec_probe(struct platform_device *pdev)
> {
> @@ -2720,13 +2756,18 @@ fec_probe(struct platform_device *pdev)
> const struct of_device_id *of_id;
> static int dev_id;
> struct device_node *np = pdev->dev.of_node, *phy_node;
> + int num_tx_qs = 1;
> + int num_rx_qs = 1;
>
useless initialization. These variables are initialized in
fec_enet_get_queue_num() anyway.
> of_id = of_match_device(fec_dt_ids, &pdev->dev);
> if (of_id)
> pdev->id_entry = of_id->data;
>
> + fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
> +
Lothar Waßmann
--
___________________________________________________________
Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Geschäftsführer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996
www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________
^ permalink raw reply
* Re: [Patch v4 net-next 12/12] ARM: dts: imx6sx: add multi-queue support enet
From: Lothar Waßmann @ 2014-09-15 7:31 UTC (permalink / raw)
To: Frank.Li
Cc: b38611, davem, netdev, lznuaa, devicetree, shawn.guo, linux,
linux-arm-kernel
In-Reply-To: <1410555657-10744-13-git-send-email-Frank.Li@freescale.com>
Hi,
Frank.Li@freescale.com wrote:
> From: Frank Li <Frank.Li@freescale.com>
>
> Enable 3 queues suppport for ethernet
>
> Signed-off-by: Frank Li <Frank.Li@freescale.com>
> ---
> arch/arm/boot/dts/imx6sx.dtsi | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
> index f4b9da6..0a03260 100644
> --- a/arch/arm/boot/dts/imx6sx.dtsi
> +++ b/arch/arm/boot/dts/imx6sx.dtsi
> @@ -776,6 +776,8 @@
> <&clks IMX6SX_CLK_ENET_PTP>;
> clock-names = "ipg", "ahb", "ptp",
> "enet_clk_ref", "enet_out";
> + fsl,num-tx-queues=<3>;
> + fsl,num-rx-queues=<3>;
missing spaces around '='
Lothar Waßmann
--
___________________________________________________________
Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Geschäftsführer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996
www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________
^ permalink raw reply
* Ring parameter information
From: Hosam Hittini @ 2014-09-15 6:14 UTC (permalink / raw)
To: netdev
In-Reply-To: <06FE00B9-3F10-48CD-ABC7-7817006FDBDD@gmail.com>
Hi,
I have two network interfaces and I used "ethtool -g" to get their ring parameters, but I don’t quite understand the output
For the ethernet interface the output says the operation is not supported
For the wireless interface the output says the sending and receiving buffer sizes are equal to zero
I wonder if anyone can help me with that
hosam@Robin-01:~$ sudo ethtool -g eth0
Ring parameters for eth0:
Cannot get device ring settings: Operation not supported
hosam@Robin-01:~$ sudo ethtool -g wlan1
Ring parameters for wlan1:
Pre-set maximums:
RX: 0
RX Mini: 0
RX Jumbo: 0
TX: 0
Current hardware settings:
RX: 0
RX Mini: 0
RX Jumbo: 0
TX: 0
Regards,
Eng. Hosam Hittini
^ permalink raw reply
* Re: [PATCH v2] zd1211rw: replace ZD_ASSERT with lockdep_assert_held()
From: Julian Calaby @ 2014-09-15 6:02 UTC (permalink / raw)
To: Sharma, Sanjeev
Cc: Johannes Berg, dsd@gentoo.org, kune@deine-taler.de,
linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <FDC088D3B5555644AE135ED28A7ABDE94DF5256D@EU-MBX-02.mgc.mentorg.com>
Hi Sanjeev,
On Thu, Sep 11, 2014 at 8:36 PM, Sharma, Sanjeev
<Sanjeev_Sharma@mentor.com> wrote:
> -----Original Message-----
> From: Johannes Berg [mailto:johannes@sipsolutions.net]
> Sent: Thursday, September 11, 2014 3:42 PM
> To: Sharma, Sanjeev
> Cc: dsd@gentoo.org; kune@deine-taler.de; linux-wireless@vger.kernel.org; linux-kernel@vger.kernel.org; netdev@vger.kernel.org
> Subject: Re: [PATCH v2] zd1211rw: replace ZD_ASSERT with lockdep_assert_held()
>
> On Thu, 2014-09-11 at 15:39 +0530, Sanjeev Sharma wrote:
>> on some architecture spin_is_locked() always return false in
>> uniprocessor configuration and therefore it would be advise to replace
>> with lockdep_assert_held().
>>
>> Signed-off-by: Sanjeev Sharma <Sanjeev_Sharma@mentor.com>
>> ---
>> Changes in v2:
>> - corrected the typo
>
>> Now it compiles, but you got the logic wrong.
>
>> +++ b/drivers/net/wireless/zd1211rw/zd_mac.c
>> @@ -235,7 +235,7 @@ void zd_mac_clear(struct zd_mac *mac) {
>> flush_workqueue(zd_workqueue);
>> zd_chip_clear(&mac->chip);
>> - ZD_ASSERT(!spin_is_locked(&mac->lock));
>> + lockdep_assert_held(&mac->lock);
>> ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); }
>
>>Look closely at this again.
>
> I didn't understand where I put wrong logic ?
I find it helps to spell out what code is doing in words.
E.g. the line you're removing is:
ZD_ASSERT(!spin_is_locked(&mac->lock));
So, we'll assert when spin_is_locked(&mac->lock) is false, i.e. when
mac->lock is not spin locked.
This isn't the same as what you're replacing it with.
Thanks,
--
Julian Calaby
Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/
^ permalink raw reply
* [PATCH] iproute: update dsfield file values
From: Stephen Hemminger @ 2014-09-15 3:43 UTC (permalink / raw)
To: netdev
Update the rt_dsfield file to contain values defined in current RFC.
The days of TOS precedence are gone, even Cisco doesn't refer
to these in the documents.
---
etc/iproute2/rt_dsfield | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/etc/iproute2/rt_dsfield b/etc/iproute2/rt_dsfield
index 496ef66..c0f3679 100644
--- a/etc/iproute2/rt_dsfield
+++ b/etc/iproute2/rt_dsfield
@@ -1,17 +1,6 @@
-0x00 default
-0x10 lowdelay
-0x08 throughput
-0x04 reliability
-# This value overlap with ECT, do not use it!
-0x02 mincost
-# These values seems do not want to die, Cisco likes them by a strange reason.
-0x20 priority
-0x40 immediate
-0x60 flash
-0x80 flash-override
-0xa0 critical
-0xc0 internet
-0xe0 network
+# Differentiated field values
+# These include the DSCP and unused bits
+0x0 default
# Newer RFC2597 values
0x28 AF11
0x30 AF12
@@ -25,3 +14,12 @@
0x88 AF41
0x90 AF42
0x98 AF43
+# Older values RFC2474
+0x20 CS1
+0x40 CS2
+0x60 CS3
+0x80 CS4
+0xA0 CS5
+0xC0 CS6
+0xE0 CS7
+0x5C EF
--
2.1.0
^ permalink raw reply related
* RE: [PATCH net 1/2] r8169: fix the default setting of rx vlan
From: Hayes Wang @ 2014-09-15 3:22 UTC (permalink / raw)
To: Francois Romieu
Cc: netdev@vger.kernel.org, nic_swsd, linux-kernel@vger.kernel.org
In-Reply-To: <20140912194014.GA15496@electric-eye.fr.zoreil.com>
Francois Romieu [mailto:romieu@fr.zoreil.com]
> Sent: Saturday, September 13, 2014 3:40 AM
[...]
> The same fix should be relevant for NETIF_F_RXCSUM. You may thus as
> well remove the "changed" test in __rtl8169_set_features and keep
> everything there.
In the probe function (rtl_init_one), RxChkSum has been assgined to
tp->cp_cmd, so only the vlan setting is incorrect. Therefore, I fix
it only. Do I still have to remove the "changed" test?
Best Regards,
Hayes
^ permalink raw reply
* Re: [PATCH] net: ethernet: marvell: sky2.c: Cleaning up missing null-terminate in conjunction with strncpy
From: Stephen Hemminger @ 2014-09-15 3:19 UTC (permalink / raw)
To: Rickard Strandqvist; +Cc: Mirko Lindner, netdev, linux-kernel
In-Reply-To: <1410716023-16068-1-git-send-email-rickard_strandqvist@spectrumdigital.se>
On Sun, 14 Sep 2014 19:33:43 +0200
Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se> wrote:
> Replacing strncpy with strlcpy to avoid strings that lacks null terminate.
>
> Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
> ---
> drivers/net/ethernet/marvell/sky2.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
> index dba48a5c..7053d38 100644
> --- a/drivers/net/ethernet/marvell/sky2.c
> +++ b/drivers/net/ethernet/marvell/sky2.c
> @@ -4907,7 +4907,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
> };
>
> if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OP_2)
> - strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
> + strlcpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
> else
> snprintf(buf, sz, "(chip %#x)", chipid);
> return buf;
Useless and unnecessary since the list of names is right there.
Why not avoid the copy?
^ permalink raw reply
* linux-next: manual merge of the net-next tree with the mips tree
From: Stephen Rothwell @ 2014-09-15 3:19 UTC (permalink / raw)
To: David Miller, netdev, Ralf Baechle
Cc: linux-next, linux-kernel, Hannes Frederic Sowa, Andrey Utkin
[-- Attachment #1: Type: text/plain, Size: 570 bytes --]
Hi all,
Today's linux-next merge of the net-next tree got a conflict in
arch/mips/net/bpf_jit.c between commit 98fb24af5e68
("arch/mips/net/bpf_jit.c: fix failure check") from the mips tree and
commit 233577a22089 ("net: filter: constify detection of
pkt_type_offset") from the net-next tree.
I fixed it up (the latter removed the code fixed up by the former, so I
effectively reverted the former and just used the latter) and can carry
the fix as necessary (no action is required).
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* [PATCH v2 net-next 7/7] gre: TX path for GRE/UDP foo-over-udp encapsulation
From: Tom Herbert @ 2014-09-15 3:08 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1410750483-3236-1-git-send-email-therbert@google.com>
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/uapi/linux/if_tunnel.h | 4 ++
net/ipv4/ip_gre.c | 98 +++++++++++++++++++++++++++++++++++++++---
2 files changed, 95 insertions(+), 7 deletions(-)
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 9fedca7..7c832af 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -106,6 +106,10 @@ enum {
IFLA_GRE_ENCAP_LIMIT,
IFLA_GRE_FLOWINFO,
IFLA_GRE_FLAGS,
+ IFLA_GRE_ENCAP_TYPE,
+ IFLA_GRE_ENCAP_FLAGS,
+ IFLA_GRE_ENCAP_SPORT,
+ IFLA_GRE_ENCAP_DPORT,
__IFLA_GRE_MAX,
};
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 9b84254..5681344 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -239,7 +239,7 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
tpi.seq = htonl(tunnel->o_seqno);
/* Push GRE header. */
- gre_build_header(skb, &tpi, tunnel->hlen);
+ gre_build_header(skb, &tpi, tunnel->tun_hlen);
ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
}
@@ -310,7 +310,7 @@ out:
static int ipgre_tunnel_ioctl(struct net_device *dev,
struct ifreq *ifr, int cmd)
{
- int err = 0;
+ int err;
struct ip_tunnel_parm p;
if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
@@ -470,13 +470,18 @@ static void ipgre_tunnel_setup(struct net_device *dev)
static void __gre_tunnel_init(struct net_device *dev)
{
struct ip_tunnel *tunnel;
+ int t_hlen;
tunnel = netdev_priv(dev);
- tunnel->hlen = ip_gre_calc_hlen(tunnel->parms.o_flags);
+ tunnel->tun_hlen = ip_gre_calc_hlen(tunnel->parms.o_flags);
tunnel->parms.iph.protocol = IPPROTO_GRE;
- dev->needed_headroom = LL_MAX_HEADER + sizeof(struct iphdr) + 4;
- dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4;
+ tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
+
+ t_hlen = tunnel->hlen + sizeof(struct iphdr);
+
+ dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
+ dev->mtu = ETH_DATA_LEN - t_hlen - 4;
dev->features |= GRE_FEATURES;
dev->hw_features |= GRE_FEATURES;
@@ -628,6 +633,40 @@ static void ipgre_netlink_parms(struct nlattr *data[], struct nlattr *tb[],
parms->iph.frag_off = htons(IP_DF);
}
+/* This function returns true when ENCAP attributes are present in the nl msg */
+static bool ipgre_netlink_encap_parms(struct nlattr *data[],
+ struct ip_tunnel_encap *ipencap)
+{
+ bool ret = false;
+
+ memset(ipencap, 0, sizeof(*ipencap));
+
+ if (!data)
+ return ret;
+
+ if (data[IFLA_GRE_ENCAP_TYPE]) {
+ ret = true;
+ ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
+ }
+
+ if (data[IFLA_GRE_ENCAP_FLAGS]) {
+ ret = true;
+ ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
+ }
+
+ if (data[IFLA_GRE_ENCAP_SPORT]) {
+ ret = true;
+ ipencap->sport = nla_get_u16(data[IFLA_GRE_ENCAP_SPORT]);
+ }
+
+ if (data[IFLA_GRE_ENCAP_DPORT]) {
+ ret = true;
+ ipencap->dport = nla_get_u16(data[IFLA_GRE_ENCAP_DPORT]);
+ }
+
+ return ret;
+}
+
static int gre_tap_init(struct net_device *dev)
{
__gre_tunnel_init(dev);
@@ -657,18 +696,40 @@ static int ipgre_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct ip_tunnel_parm p;
+ struct ip_tunnel *nt = netdev_priv(dev);
+ struct ip_tunnel_encap ipencap;
+ int err;
+
+ if (ipgre_netlink_encap_parms(data, &ipencap)) {
+ err = ip_tunnel_encap_setup(nt, &ipencap);
+ if (err < 0)
+ return err;
+ }
ipgre_netlink_parms(data, tb, &p);
- return ip_tunnel_newlink(dev, tb, &p);
+ err = ip_tunnel_newlink(dev, tb, &p);
+
+ return err;
}
static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[])
{
+ struct ip_tunnel *t = netdev_priv(dev);
struct ip_tunnel_parm p;
+ struct ip_tunnel_encap ipencap;
+ int err;
+
+ if (ipgre_netlink_encap_parms(data, &ipencap)) {
+ err = ip_tunnel_encap_setup(t, &ipencap);
+ if (err < 0)
+ return err;
+ }
ipgre_netlink_parms(data, tb, &p);
- return ip_tunnel_changelink(dev, tb, &p);
+ err = ip_tunnel_changelink(dev, tb, &p);
+
+ return err;
}
static size_t ipgre_get_size(const struct net_device *dev)
@@ -694,6 +755,14 @@ static size_t ipgre_get_size(const struct net_device *dev)
nla_total_size(1) +
/* IFLA_GRE_PMTUDISC */
nla_total_size(1) +
+ /* IFLA_GRE_ENCAP_TYPE */
+ nla_total_size(2) +
+ /* IFLA_GRE_ENCAP_FLAGS */
+ nla_total_size(2) +
+ /* IFLA_GRE_ENCAP_SPORT */
+ nla_total_size(2) +
+ /* IFLA_GRE_ENCAP_DPORT */
+ nla_total_size(2) +
0;
}
@@ -714,6 +783,17 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_u8(skb, IFLA_GRE_PMTUDISC,
!!(p->iph.frag_off & htons(IP_DF))))
goto nla_put_failure;
+
+ if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
+ t->encap.type) ||
+ nla_put_u16(skb, IFLA_GRE_ENCAP_SPORT,
+ t->encap.sport) ||
+ nla_put_u16(skb, IFLA_GRE_ENCAP_DPORT,
+ t->encap.dport) ||
+ nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
+ t->encap.dport))
+ goto nla_put_failure;
+
return 0;
nla_put_failure:
@@ -731,6 +811,10 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
[IFLA_GRE_TTL] = { .type = NLA_U8 },
[IFLA_GRE_TOS] = { .type = NLA_U8 },
[IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
+ [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 },
+ [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 },
+ [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 },
+ [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 },
};
static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH v2 net-next 6/7] ipip: TX path for IPIP/UDP foo-over-udp encapsulation
From: Tom Herbert @ 2014-09-15 3:08 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1410750483-3236-1-git-send-email-therbert@google.com>
Signed-off-by: Tom Herbert <therbert@google.com>
---
net/ipv4/ipip.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 83 insertions(+), 3 deletions(-)
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 62eaa00..2985551 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -301,7 +301,8 @@ static int ipip_tunnel_init(struct net_device *dev)
memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
- tunnel->hlen = 0;
+ tunnel->tun_hlen = 0;
+ tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
tunnel->parms.iph.protocol = IPPROTO_IPIP;
return ip_tunnel_init(dev);
}
@@ -340,19 +341,73 @@ static void ipip_netlink_parms(struct nlattr *data[],
parms->iph.frag_off = htons(IP_DF);
}
+/* This function returns true when ENCAP attributes are present in the nl msg */
+static bool ipip_netlink_encap_parms(struct nlattr *data[],
+ struct ip_tunnel_encap *ipencap)
+{
+ bool ret = false;
+
+ memset(ipencap, 0, sizeof(*ipencap));
+
+ if (!data)
+ return ret;
+
+ if (data[IFLA_IPTUN_ENCAP_TYPE]) {
+ ret = true;
+ ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
+ ret = true;
+ ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_SPORT]) {
+ ret = true;
+ ipencap->sport = nla_get_u16(data[IFLA_IPTUN_ENCAP_SPORT]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_DPORT]) {
+ ret = true;
+ ipencap->dport = nla_get_u16(data[IFLA_IPTUN_ENCAP_DPORT]);
+ }
+
+ return ret;
+}
+
static int ipip_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct ip_tunnel_parm p;
+ struct ip_tunnel *t = netdev_priv(dev);
+ struct ip_tunnel_encap ipencap;
+ int err;
+
+ if (ipip_netlink_encap_parms(data, &ipencap)) {
+ err = ip_tunnel_encap_setup(t, &ipencap);
+ if (err < 0)
+ return err;
+ }
ipip_netlink_parms(data, &p);
- return ip_tunnel_newlink(dev, tb, &p);
+ err = ip_tunnel_newlink(dev, tb, &p);
+
+ return err;
}
static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[])
{
+ struct ip_tunnel *t = netdev_priv(dev);
struct ip_tunnel_parm p;
+ struct ip_tunnel_encap ipencap;
+ int err;
+
+ if (ipip_netlink_encap_parms(data, &ipencap)) {
+ err = ip_tunnel_encap_setup(t, &ipencap);
+ if (err < 0)
+ return err;
+ }
ipip_netlink_parms(data, &p);
@@ -360,7 +415,9 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
(!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
return -EINVAL;
- return ip_tunnel_changelink(dev, tb, &p);
+ err = ip_tunnel_changelink(dev, tb, &p);
+
+ return err;
}
static size_t ipip_get_size(const struct net_device *dev)
@@ -378,6 +435,14 @@ static size_t ipip_get_size(const struct net_device *dev)
nla_total_size(1) +
/* IFLA_IPTUN_PMTUDISC */
nla_total_size(1) +
+ /* IFLA_IPTUN_ENCAP_TYPE */
+ nla_total_size(2) +
+ /* IFLA_IPTUN_ENCAP_FLAGS */
+ nla_total_size(2) +
+ /* IFLA_IPTUN_ENCAP_SPORT */
+ nla_total_size(2) +
+ /* IFLA_IPTUN_ENCAP_DPORT */
+ nla_total_size(2) +
0;
}
@@ -394,6 +459,17 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
!!(parm->iph.frag_off & htons(IP_DF))))
goto nla_put_failure;
+
+ if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
+ tunnel->encap.type) ||
+ nla_put_u16(skb, IFLA_IPTUN_ENCAP_SPORT,
+ tunnel->encap.sport) ||
+ nla_put_u16(skb, IFLA_IPTUN_ENCAP_DPORT,
+ tunnel->encap.dport) ||
+ nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
+ tunnel->encap.dport))
+ goto nla_put_failure;
+
return 0;
nla_put_failure:
@@ -407,6 +483,10 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_TTL] = { .type = NLA_U8 },
[IFLA_IPTUN_TOS] = { .type = NLA_U8 },
[IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
+ [IFLA_IPTUN_ENCAP_TYPE] = { .type = NLA_U16 },
+ [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
+ [IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 },
+ [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
};
static struct rtnl_link_ops ipip_link_ops __read_mostly = {
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH v2 net-next 5/7] sit: TX path for sit/UDP foo-over-udp encapsulation
From: Tom Herbert @ 2014-09-15 3:08 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1410750483-3236-1-git-send-email-therbert@google.com>
Signed-off-by: Tom Herbert <therbert@google.com>
---
net/ipv6/sit.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 97 insertions(+), 10 deletions(-)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 86e3fa8..db75809 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -822,6 +822,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
int addr_type;
u8 ttl;
int err;
+ u8 protocol = IPPROTO_IPV6;
+ int t_hlen = tunnel->hlen + sizeof(struct iphdr);
if (skb->protocol != htons(ETH_P_IPV6))
goto tx_error;
@@ -911,8 +913,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
goto tx_error;
}
+ skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT);
+ if (IS_ERR(skb)) {
+ ip_rt_put(rt);
+ goto out;
+ }
+
if (df) {
- mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
+ mtu = dst_mtu(&rt->dst) - t_hlen;
if (mtu < 68) {
dev->stats.collisions++;
@@ -947,7 +955,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
/*
* Okay, now see if we can stuff it in the buffer as-is.
*/
- max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr);
+ max_headroom = LL_RESERVED_SPACE(tdev) + t_hlen;
if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
(skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
@@ -969,14 +977,13 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
ttl = iph6->hop_limit;
tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
- skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT);
- if (IS_ERR(skb)) {
+ if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) {
ip_rt_put(rt);
- goto out;
+ goto tx_error;
}
err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr,
- IPPROTO_IPV6, tos, ttl, df,
+ protocol, tos, ttl, df,
!net_eq(tunnel->net, dev_net(dev)));
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
return NETDEV_TX_OK;
@@ -1059,8 +1066,10 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
if (tdev) {
+ int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+
dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
- dev->mtu = tdev->mtu - sizeof(struct iphdr);
+ dev->mtu = tdev->mtu - t_hlen;
if (dev->mtu < IPV6_MIN_MTU)
dev->mtu = IPV6_MIN_MTU;
}
@@ -1307,7 +1316,10 @@ done:
static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr))
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+ int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+
+ if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - t_hlen)
return -EINVAL;
dev->mtu = new_mtu;
return 0;
@@ -1338,12 +1350,15 @@ static void ipip6_dev_free(struct net_device *dev)
static void ipip6_tunnel_setup(struct net_device *dev)
{
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+ int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+
dev->netdev_ops = &ipip6_netdev_ops;
dev->destructor = ipip6_dev_free;
dev->type = ARPHRD_SIT;
- dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr);
- dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr);
+ dev->hard_header_len = LL_MAX_HEADER + t_hlen;
+ dev->mtu = ETH_DATA_LEN - t_hlen;
dev->flags = IFF_NOARP;
dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
dev->iflink = 0;
@@ -1466,6 +1481,40 @@ static void ipip6_netlink_parms(struct nlattr *data[],
}
+/* This function returns true when ENCAP attributes are present in the nl msg */
+static bool ipip6_netlink_encap_parms(struct nlattr *data[],
+ struct ip_tunnel_encap *ipencap)
+{
+ bool ret = false;
+
+ memset(ipencap, 0, sizeof(*ipencap));
+
+ if (!data)
+ return ret;
+
+ if (data[IFLA_IPTUN_ENCAP_TYPE]) {
+ ret = true;
+ ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
+ ret = true;
+ ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_SPORT]) {
+ ret = true;
+ ipencap->sport = nla_get_u16(data[IFLA_IPTUN_ENCAP_SPORT]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_DPORT]) {
+ ret = true;
+ ipencap->dport = nla_get_u16(data[IFLA_IPTUN_ENCAP_DPORT]);
+ }
+
+ return ret;
+}
+
#ifdef CONFIG_IPV6_SIT_6RD
/* This function returns true when 6RD attributes are present in the nl msg */
static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
@@ -1509,12 +1558,20 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev,
{
struct net *net = dev_net(dev);
struct ip_tunnel *nt;
+ struct ip_tunnel_encap ipencap;
#ifdef CONFIG_IPV6_SIT_6RD
struct ip_tunnel_6rd ip6rd;
#endif
int err;
nt = netdev_priv(dev);
+
+ if (ipip6_netlink_encap_parms(data, &ipencap)) {
+ err = ip_tunnel_encap_setup(nt, &ipencap);
+ if (err < 0)
+ return err;
+ }
+
ipip6_netlink_parms(data, &nt->parms);
if (ipip6_tunnel_locate(net, &nt->parms, 0))
@@ -1537,15 +1594,23 @@ static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
{
struct ip_tunnel *t = netdev_priv(dev);
struct ip_tunnel_parm p;
+ struct ip_tunnel_encap ipencap;
struct net *net = t->net;
struct sit_net *sitn = net_generic(net, sit_net_id);
#ifdef CONFIG_IPV6_SIT_6RD
struct ip_tunnel_6rd ip6rd;
#endif
+ int err;
if (dev == sitn->fb_tunnel_dev)
return -EINVAL;
+ if (ipip6_netlink_encap_parms(data, &ipencap)) {
+ err = ip_tunnel_encap_setup(t, &ipencap);
+ if (err < 0)
+ return err;
+ }
+
ipip6_netlink_parms(data, &p);
if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
@@ -1599,6 +1664,14 @@ static size_t ipip6_get_size(const struct net_device *dev)
/* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */
nla_total_size(2) +
#endif
+ /* IFLA_IPTUN_ENCAP_TYPE */
+ nla_total_size(2) +
+ /* IFLA_IPTUN_ENCAP_FLAGS */
+ nla_total_size(2) +
+ /* IFLA_IPTUN_ENCAP_SPORT */
+ nla_total_size(2) +
+ /* IFLA_IPTUN_ENCAP_DPORT */
+ nla_total_size(2) +
0;
}
@@ -1630,6 +1703,16 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
goto nla_put_failure;
#endif
+ if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
+ tunnel->encap.type) ||
+ nla_put_u16(skb, IFLA_IPTUN_ENCAP_SPORT,
+ tunnel->encap.sport) ||
+ nla_put_u16(skb, IFLA_IPTUN_ENCAP_DPORT,
+ tunnel->encap.dport) ||
+ nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
+ tunnel->encap.dport))
+ goto nla_put_failure;
+
return 0;
nla_put_failure:
@@ -1651,6 +1734,10 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 },
[IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
#endif
+ [IFLA_IPTUN_ENCAP_TYPE] = { .type = NLA_U16 },
+ [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
+ [IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 },
+ [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
};
static void ipip6_dellink(struct net_device *dev, struct list_head *head)
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH v2 net-next 4/7] net: Changes to ip_tunnel to support foo-over-udp encapsulation
From: Tom Herbert @ 2014-09-15 3:08 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1410750483-3236-1-git-send-email-therbert@google.com>
This patch changes IP tunnel to support (secondary) encapsulation,
Foo-over-UDP. Changes include:
1) Adding tun_hlen as the tunnel header length, encap_hlen as the
encapsulation header length, and hlen becomes the grand total
of these.
2) Added common netlink define to support FOU encapsulation.
3) Routines to perform FOU encapsulation.
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/net/ip_tunnels.h | 19 ++++++++-
include/uapi/linux/if_tunnel.h | 12 ++++++
net/ipv4/ip_tunnel.c | 91 +++++++++++++++++++++++++++++++++++++++++-
3 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 8dd8cab..7f538ba 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -10,6 +10,7 @@
#include <net/gro_cells.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
+#include <net/netns/generic.h>
#include <net/rtnetlink.h>
#if IS_ENABLED(CONFIG_IPV6)
@@ -31,6 +32,13 @@ struct ip_tunnel_6rd_parm {
};
#endif
+struct ip_tunnel_encap {
+ __u16 type;
+ __u16 flags;
+ __be16 sport;
+ __be16 dport;
+};
+
struct ip_tunnel_prl_entry {
struct ip_tunnel_prl_entry __rcu *next;
__be32 addr;
@@ -56,13 +64,18 @@ struct ip_tunnel {
/* These four fields used only by GRE */
__u32 i_seqno; /* The last seen seqno */
__u32 o_seqno; /* The last output seqno */
- int hlen; /* Precalculated header length */
+ int tun_hlen; /* Precalculated header length */
int mlink;
struct ip_tunnel_dst __percpu *dst_cache;
struct ip_tunnel_parm parms;
+ int encap_hlen; /* Encap header length (FOU,GUE) */
+ struct ip_tunnel_encap encap;
+
+ int hlen; /* tun_hlen + encap_hlen */
+
/* for SIT */
#ifdef CONFIG_IPV6_SIT_6RD
struct ip_tunnel_6rd_parm ip6rd;
@@ -114,6 +127,8 @@ void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops);
void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
const struct iphdr *tnl_params, const u8 protocol);
int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
+int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
+ u8 *protocol, struct flowi4 *fl4);
int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
@@ -131,6 +146,8 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
struct ip_tunnel_parm *p);
void ip_tunnel_setup(struct net_device *dev, int net_id);
void ip_tunnel_dst_reset_all(struct ip_tunnel *t);
+int ip_tunnel_encap_setup(struct ip_tunnel *t,
+ struct ip_tunnel_encap *ipencap);
/* Extract dsfield from inner protocol */
static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 3bce9e9..9fedca7 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -53,10 +53,22 @@ enum {
IFLA_IPTUN_6RD_RELAY_PREFIX,
IFLA_IPTUN_6RD_PREFIXLEN,
IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+ IFLA_IPTUN_ENCAP_TYPE,
+ IFLA_IPTUN_ENCAP_FLAGS,
+ IFLA_IPTUN_ENCAP_SPORT,
+ IFLA_IPTUN_ENCAP_DPORT,
__IFLA_IPTUN_MAX,
};
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
+enum tunnel_encap_types {
+ TUNNEL_ENCAP_NONE,
+ TUNNEL_ENCAP_FOU,
+};
+
+#define TUNNEL_ENCAP_FLAG_CSUM (1<<0)
+#define TUNNEL_ENCAP_FLAG_CSUM6 (1<<1)
+
/* SIT-mode i_flags */
#define SIT_ISATAP 0x0001
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index afed1aa..e3a3dc9 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -55,6 +55,7 @@
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
+#include <net/udp.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
@@ -487,6 +488,91 @@ drop:
}
EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
+static int ip_encap_hlen(struct ip_tunnel_encap *e)
+{
+ switch (e->type) {
+ case TUNNEL_ENCAP_NONE:
+ return 0;
+ case TUNNEL_ENCAP_FOU:
+ return sizeof(struct udphdr);
+ default:
+ return -EINVAL;
+ }
+}
+
+int ip_tunnel_encap_setup(struct ip_tunnel *t,
+ struct ip_tunnel_encap *ipencap)
+{
+ int hlen;
+
+ memset(&t->encap, 0, sizeof(t->encap));
+
+ hlen = ip_encap_hlen(ipencap);
+ if (hlen < 0)
+ return hlen;
+
+ t->encap.type = ipencap->type;
+ t->encap.sport = ipencap->sport;
+ t->encap.dport = ipencap->dport;
+ t->encap.flags = ipencap->flags;
+
+ t->encap_hlen = hlen;
+ t->hlen = t->encap_hlen + t->tun_hlen;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);
+
+static int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+ size_t hdr_len, u8 *protocol, struct flowi4 *fl4)
+{
+ struct udphdr *uh;
+ __be16 sport;
+ bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
+ int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+
+ skb = iptunnel_handle_offloads(skb, csum, type);
+
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ /* Get length and hash before making space in skb */
+
+ sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
+ skb, 0, 0, false);
+
+ skb_push(skb, hdr_len);
+
+ skb_reset_transport_header(skb);
+ uh = udp_hdr(skb);
+
+ uh->dest = e->dport;
+ uh->source = sport;
+ uh->len = htons(skb->len);
+ uh->check = 0;
+ udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
+ fl4->saddr, fl4->daddr, skb->len);
+
+ *protocol = IPPROTO_UDP;
+
+ return 0;
+}
+
+int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
+ u8 *protocol, struct flowi4 *fl4)
+{
+ switch (t->encap.type) {
+ case TUNNEL_ENCAP_NONE:
+ return 0;
+ case TUNNEL_ENCAP_FOU:
+ return fou_build_header(skb, &t->encap, t->encap_hlen,
+ protocol, fl4);
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL(ip_tunnel_encap);
+
static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
struct rtable *rt, __be16 df)
{
@@ -536,7 +622,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
}
void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
- const struct iphdr *tnl_params, const u8 protocol)
+ const struct iphdr *tnl_params, u8 protocol)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
const struct iphdr *inner_iph;
@@ -617,6 +703,9 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link);
+ if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
+ goto tx_error;
+
rt = connected ? tunnel_rtable_get(tunnel, 0, &fl4.saddr) : NULL;
if (!rt) {
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH v2 net-next 3/7] fou: Add GRO support
From: Tom Herbert @ 2014-09-15 3:07 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1410750483-3236-1-git-send-email-therbert@google.com>
Implement fou_gro_receive and fou_gro_complete, and populate these
in the correponsing udp_offloads for the socket. Added ipproto to
udp_offloads and pass this from UDP to the fou GRO routine in proto
field of napi_gro_cb structure.
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/linux/netdevice.h | 3 +-
net/ipv4/fou.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/udp_offload.c | 5 ++-
3 files changed, 96 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f9e81d1..d380574 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1874,7 +1874,7 @@ struct napi_gro_cb {
/* jiffies when first packet was created/queued */
unsigned long age;
- /* Used in ipv6_gro_receive() */
+ /* Used in ipv6_gro_receive() and foo-over-udp */
u16 proto;
/* Used in udp_gro_receive */
@@ -1925,6 +1925,7 @@ struct packet_offload {
struct udp_offload {
__be16 port;
+ u8 ipproto;
struct offload_callbacks callbacks;
};
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index de2af74..2ddd3b8 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <net/genetlink.h>
#include <net/ip.h>
+#include <net/protocol.h>
#include <net/udp.h>
#include <net/udp_tunnel.h>
#include <net/xfrm.h>
@@ -21,6 +22,7 @@ struct fou {
struct socket *sock;
u8 protocol;
u16 port;
+ struct udp_offload udp_offloads;
struct list_head list;
};
@@ -62,6 +64,70 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
sizeof(struct udphdr));
}
+static inline struct sk_buff **fou_gro_receive(struct sk_buff **head,
+ struct sk_buff *skb,
+ const struct net_offload
+ **offloads)
+{
+ const struct net_offload *ops;
+ struct sk_buff **pp = NULL;
+ u8 proto = NAPI_GRO_CB(skb)->proto;
+
+ rcu_read_lock();
+ ops = rcu_dereference(offloads[proto]);
+ if (!ops || !ops->callbacks.gro_receive)
+ goto out_unlock;
+
+ pp = ops->callbacks.gro_receive(head, skb);
+
+out_unlock:
+ rcu_read_unlock();
+
+ return pp;
+}
+
+static inline int fou_gro_complete(struct sk_buff *skb, int nhoff,
+ const struct net_offload **offloads)
+{
+ const struct net_offload *ops;
+ u8 proto = NAPI_GRO_CB(skb)->proto;
+ int err = -ENOSYS;
+
+ rcu_read_lock();
+ ops = rcu_dereference(offloads[proto]);
+ if (WARN_ON(!ops || !ops->callbacks.gro_complete))
+ goto out_unlock;
+
+ err = ops->callbacks.gro_complete(skb, nhoff);
+
+out_unlock:
+ rcu_read_unlock();
+
+ return err;
+}
+
+static struct sk_buff **fou4_gro_receive(struct sk_buff **head,
+ struct sk_buff *skb)
+{
+ return fou_gro_receive(head, skb, inet_offloads);
+}
+
+static int fou4_gro_complete(struct sk_buff *skb, int nhoff)
+{
+ return fou_gro_complete(skb, nhoff, inet_offloads);
+}
+
+static struct sk_buff **fou6_gro_receive(struct sk_buff **head,
+ struct sk_buff *skb)
+{
+ return fou_gro_receive(head, skb, inet6_offloads);
+}
+
+static int fou6_gro_complete(struct sk_buff *skb, int nhoff)
+{
+ return fou_gro_complete(skb, nhoff, inet6_offloads);
+}
+
static int fou_add_to_port_list(struct fou *fou)
{
struct fou *fout;
@@ -134,6 +200,29 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
sk->sk_allocation = GFP_ATOMIC;
+ switch (cfg->udp_config.family) {
+ case AF_INET:
+ fou->udp_offloads.callbacks.gro_receive = fou4_gro_receive;
+ fou->udp_offloads.callbacks.gro_complete = fou4_gro_complete;
+ break;
+ case AF_INET6:
+ fou->udp_offloads.callbacks.gro_receive = fou6_gro_receive;
+ fou->udp_offloads.callbacks.gro_complete = fou6_gro_complete;
+ break;
+ default:
+ err = -EPFNOSUPPORT;
+ goto error;
+ }
+
+ fou->udp_offloads.port = cfg->udp_config.local_udp_port;
+ fou->udp_offloads.ipproto = cfg->protocol;
+
+ if (cfg->udp_config.family == AF_INET) {
+ err = udp_add_offload(&fou->udp_offloads);
+ if (err)
+ goto error;
+ }
+
err = fou_add_to_port_list(fou);
if (err)
goto error;
@@ -160,6 +249,7 @@ static int fou_destroy(struct net *net, struct fou_cfg *cfg)
spin_lock(&fou_lock);
list_for_each_entry(fou, &fou_list, list) {
if (fou->port == port) {
+ udp_del_offload(&fou->udp_offloads);
fou_release(fou);
err = 0;
break;
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index adab393..d7c43f7 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -276,6 +276,7 @@ unflush:
skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */
skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr));
+ NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto;
pp = uo_priv->offload->callbacks.gro_receive(head, skb);
out_unlock:
@@ -329,8 +330,10 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff)
break;
}
- if (uo_priv != NULL)
+ if (uo_priv != NULL) {
+ NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto;
err = uo_priv->offload->callbacks.gro_complete(skb, nhoff + sizeof(struct udphdr));
+ }
rcu_read_unlock();
return err;
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH v2 net-next 2/7] fou: Support for foo-over-udp RX path
From: Tom Herbert @ 2014-09-15 3:07 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1410750483-3236-1-git-send-email-therbert@google.com>
This patch provides a receive path for foo-over-udp. This allows
direct encapsulation of IP protocols over UDP. The bound destination
port is used to map to an IP protocol, and the XFRM framework
(udp_encap_rcv) is used to receive encapsulated packets. Upon
reception, the encapsulation header is logically removed (pointer
to transport header is advanced) and the packet is reinjected into
the receive path with the IP protocol indicated by the mapping.
Netlink is used to configure FOU ports. The configuration information
includes the port number to bind to and the IP protocol corresponding
to that port.
This should support GRE/UDP
(http://tools.ietf.org/html/draft-yong-tsvwg-gre-in-udp-encap-02),
as will as the other IP tunneling protocols (IPIP, SIT).
Signed-off-by: Tom Herbert <therbert@google.com>
---
include/uapi/linux/fou.h | 32 ++++++
net/ipv4/Kconfig | 10 ++
net/ipv4/Makefile | 1 +
net/ipv4/fou.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 322 insertions(+)
create mode 100644 include/uapi/linux/fou.h
create mode 100644 net/ipv4/fou.c
diff --git a/include/uapi/linux/fou.h b/include/uapi/linux/fou.h
new file mode 100644
index 0000000..e03376d
--- /dev/null
+++ b/include/uapi/linux/fou.h
@@ -0,0 +1,32 @@
+/* fou.h - FOU Interface */
+
+#ifndef _UAPI_LINUX_FOU_H
+#define _UAPI_LINUX_FOU_H
+
+/* NETLINK_GENERIC related info
+ */
+#define FOU_GENL_NAME "fou"
+#define FOU_GENL_VERSION 0x1
+
+enum {
+ FOU_ATTR_UNSPEC,
+ FOU_ATTR_PORT, /* u16 */
+ FOU_ATTR_AF, /* u8 */
+ FOU_ATTR_IPPROTO, /* u8 */
+
+ __FOU_ATTR_MAX,
+};
+
+#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1)
+
+enum {
+ FOU_CMD_UNSPEC,
+ FOU_CMD_ADD,
+ FOU_CMD_DEL,
+
+ __FOU_CMD_MAX,
+};
+
+#define FOU_CMD_MAX (__FOU_CMD_MAX - 1)
+
+#endif /* _UAPI_LINUX_FOU_H */
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index dbc10d8..84f710b 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -311,6 +311,16 @@ config NET_UDP_TUNNEL
tristate
default n
+config NET_FOU
+ tristate "IP: Foo (IP protocols) over UDP"
+ select XFRM
+ select NET_UDP_TUNNEL
+ ---help---
+ Foo over UDP allows any IP protocol to be directly encapsulated
+ over UDP include tunnels (IPIP, GRE, SIT). By encapsulating in UDP
+ network mechanisms and optimizations for UDP (such as ECMP
+ and RSS) can be leveraged to provide better service.
+
config INET_AH
tristate "IP: AH transformation"
select XFRM_ALGO
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 8ee1cd4..d78d404 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
obj-$(CONFIG_IP_MROUTE) += ipmr.o
obj-$(CONFIG_NET_IPIP) += ipip.o
gre-y := gre_demux.o
+obj-$(CONFIG_NET_FOU) += fou.o
obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
obj-$(CONFIG_NET_IPGRE) += ip_gre.o
obj-$(CONFIG_NET_UDP_TUNNEL) += udp_tunnel.o
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
new file mode 100644
index 0000000..de2af74
--- /dev/null
+++ b/net/ipv4/fou.c
@@ -0,0 +1,279 @@
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <net/genetlink.h>
+#include <net/ip.h>
+#include <net/udp.h>
+#include <net/udp_tunnel.h>
+#include <net/xfrm.h>
+#include <uapi/linux/fou.h>
+#include <uapi/linux/genetlink.h>
+
+static DEFINE_SPINLOCK(fou_lock);
+static LIST_HEAD(fou_list);
+
+struct fou {
+ struct socket *sock;
+ u8 protocol;
+ u16 port;
+ struct list_head list;
+};
+
+struct fou_cfg {
+ u8 protocol;
+ struct udp_port_cfg udp_config;
+};
+
+static inline struct fou *fou_from_sock(struct sock *sk)
+{
+ return (struct fou *)sk->sk_user_data;
+}
+
+static int fou_udp_encap_recv_deliver(struct sk_buff *skb,
+ u8 protocol, size_t len)
+{
+ struct iphdr *iph = ip_hdr(skb);
+
+ /* Remove 'len' bytes from the packet (UDP header and
+ * FOU header if present), modify the protocol to the one
+ * we found, and then call rcv_encap.
+ */
+ iph->tot_len = htons(ntohs(iph->tot_len) - len);
+ __skb_pull(skb, len);
+ skb_postpull_rcsum(skb, udp_hdr(skb), len);
+ skb_reset_transport_header(skb);
+
+ return -protocol;
+}
+
+static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
+{
+ struct fou *fou = fou_from_sock(sk);
+
+ if (!fou)
+ return 1;
+
+ return fou_udp_encap_recv_deliver(skb, fou->protocol,
+ sizeof(struct udphdr));
+}
+
+static int fou_add_to_port_list(struct fou *fou)
+{
+ struct fou *fout;
+
+ spin_lock(&fou_lock);
+ list_for_each_entry(fout, &fou_list, list) {
+ if (fou->port == fout->port) {
+ spin_unlock(&fou_lock);
+ return -EALREADY;
+ }
+ }
+
+ list_add(&fou->list, &fou_list);
+ spin_unlock(&fou_lock);
+
+ return 0;
+}
+
+static void fou_release(struct fou *fou)
+{
+ struct socket *sock = fou->sock;
+ struct sock *sk = sock->sk;
+
+ udp_del_offload(&fou->udp_offloads);
+
+ list_del(&fou->list);
+
+ /* Remove hooks into tunnel socket */
+ sk->sk_user_data = NULL;
+
+ sock_release(sock);
+
+ kfree(fou);
+}
+
+static int fou_create(struct net *net, struct fou_cfg *cfg,
+ struct socket **sockp)
+{
+ struct fou *fou = NULL;
+ int err;
+ struct socket *sock = NULL;
+ struct sock *sk;
+
+ /* Open UDP socket */
+ err = udp_sock_create(net, &cfg->udp_config, &sock);
+ if (err < 0)
+ goto error;
+
+ sk = sock->sk;
+
+ /* Allocate FOU port structure */
+ fou = kzalloc(sizeof(*fou), GFP_KERNEL);
+ if (!fou) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
+ fou->protocol = cfg->protocol;
+ fou->port = cfg->udp_config.local_udp_port;
+ udp_sk(sk)->encap_rcv = fou_udp_recv;
+
+ udp_sk(sk)->encap_type = 1;
+ udp_encap_enable();
+
+ sk->sk_user_data = fou;
+ fou->sock = sock;
+
+ udp_set_convert_csum(sock->sk, true);
+
+ sk->sk_allocation = GFP_ATOMIC;
+
+ err = fou_add_to_port_list(fou);
+ if (err)
+ goto error;
+
+ if (sockp)
+ *sockp = sock;
+
+ return 0;
+
+error:
+ kfree(fou);
+ if (sock)
+ sock_release(sock);
+
+ return err;
+}
+
+static int fou_destroy(struct net *net, struct fou_cfg *cfg)
+{
+ struct fou *fou;
+ u16 port = htons(cfg->udp_config.local_udp_port);
+ int err = -EINVAL;
+
+ spin_lock(&fou_lock);
+ list_for_each_entry(fou, &fou_list, list) {
+ if (fou->port == port) {
+ fou_release(fou);
+ err = 0;
+ break;
+ }
+ }
+ spin_unlock(&fou_lock);
+
+ return err;
+}
+
+static struct genl_family fou_nl_family = {
+ .id = GENL_ID_GENERATE,
+ .hdrsize = 0,
+ .name = FOU_GENL_NAME,
+ .version = FOU_GENL_VERSION,
+ .maxattr = FOU_ATTR_MAX,
+ .netnsok = true,
+};
+
+static struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = {
+ [FOU_ATTR_PORT] = { .type = NLA_U16, },
+ [FOU_ATTR_AF] = { .type = NLA_U8, },
+ [FOU_ATTR_IPPROTO] = { .type = NLA_U8, },
+};
+
+static int parse_nl_config(struct genl_info *info,
+ struct fou_cfg *cfg)
+{
+ memset(cfg, 0, sizeof(*cfg));
+
+ cfg->udp_config.family = AF_INET;
+
+ if (info->attrs[FOU_ATTR_AF]) {
+ u8 family = nla_get_u8(info->attrs[FOU_ATTR_AF]);
+
+ if (family != AF_INET && family != AF_INET6)
+ return -EINVAL;
+
+ cfg->udp_config.family = family;
+ }
+
+ if (info->attrs[FOU_ATTR_PORT]) {
+ u16 port = nla_get_u16(info->attrs[FOU_ATTR_PORT]);
+
+ cfg->udp_config.local_udp_port = port;
+ }
+
+ if (info->attrs[FOU_ATTR_IPPROTO])
+ cfg->protocol = nla_get_u8(info->attrs[FOU_ATTR_IPPROTO]);
+
+ return 0;
+}
+
+static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info)
+{
+ struct fou_cfg cfg;
+ int err;
+
+ err = parse_nl_config(info, &cfg);
+ if (err)
+ return err;
+
+ return fou_create(&init_net, &cfg, NULL);
+}
+
+static int fou_nl_cmd_rm_port(struct sk_buff *skb, struct genl_info *info)
+{
+ struct fou_cfg cfg;
+
+ parse_nl_config(info, &cfg);
+
+ return fou_destroy(&init_net, &cfg);
+}
+
+static const struct genl_ops fou_nl_ops[] = {
+ {
+ .cmd = FOU_CMD_ADD,
+ .doit = fou_nl_cmd_add_port,
+ .policy = fou_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = FOU_CMD_DEL,
+ .doit = fou_nl_cmd_rm_port,
+ .policy = fou_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+};
+
+static int __init fou_init(void)
+{
+ int ret;
+
+ ret = genl_register_family_with_ops(&fou_nl_family,
+ fou_nl_ops);
+
+ return ret;
+}
+
+static void __exit fou_fini(void)
+{
+ struct fou *fou, *next;
+
+ genl_unregister_family(&fou_nl_family);
+
+ /* Close all the FOU sockets */
+
+ spin_lock(&fou_lock);
+ list_for_each_entry_safe(fou, next, &fou_list, list)
+ fou_release(fou);
+ spin_unlock(&fou_lock);
+}
+
+module_init(fou_init);
+module_exit(fou_fini);
+MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
+MODULE_LICENSE("GPL");
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH v2 net-next 1/7] net: Export inet_offloads and inet6_offloads
From: Tom Herbert @ 2014-09-15 3:07 UTC (permalink / raw)
To: davem, netdev
In-Reply-To: <1410750483-3236-1-git-send-email-therbert@google.com>
Want to be able to call this in foo-over-udp offloads, etc.
Signed-off-by: Tom Herbert <therbert@google.com>
---
net/ipv4/protocol.c | 1 +
net/ipv6/protocol.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c
index 46d6a1c..4b7c0ec 100644
--- a/net/ipv4/protocol.c
+++ b/net/ipv4/protocol.c
@@ -30,6 +30,7 @@
const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly;
const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS] __read_mostly;
+EXPORT_SYMBOL(inet_offloads);
int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
{
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index e048cf1..e3770ab 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -51,6 +51,7 @@ EXPORT_SYMBOL(inet6_del_protocol);
#endif
const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly;
+EXPORT_SYMBOL(inet6_offloads);
int inet6_add_offload(const struct net_offload *prot, unsigned char protocol)
{
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH v2 net-next 0/7] net: foo-over-udp (fou)
From: Tom Herbert @ 2014-09-15 3:07 UTC (permalink / raw)
To: davem, netdev
This patch series implements foo-over-udp. The idea is that we can
encapsulate different IP protocols in UDP packets. The rationale for
this is that networking devices such as NICs and switches are usually
implemented with UDP (and TCP) specific mechanims for processing. For
instance, many switches and routers will implement a 5-tuple hash
for UDP packets to perform Equal Cost Multipath Routing (ECMP) or
RSS (on NICs). Many NICs also only provide rudimentary checksum
offload (basic TCP and UDP packet), with foo-over-udp we may be
able to leverage these NICs to offload checksums of tunneled packets
(using checksum unnecessary conversion and eventually remote checksum
offload)
An example encapsulation of IPIP over FOU is diagrammed below. As
illustrated, the packet overhead for FOU is the 8 byte UDP header.
+------------------+
| IPv4 hdr |
+------------------+
| UDP hdr |
+------------------+
| IPv4 hdr |
+------------------+
| TCP hdr |
+------------------+
| TCP payload |
+------------------+
Conceptually, FOU should be able to encapsulate any IP protocol.
The FOU header (UDP hdr.) is essentially an inserted header between the
IP header and transport, so in the case of TCP or UDP encapsulation
the pseudo header would be based on the outer IP header and its length
field must not include the UDP header.
* Receive
In this patch set the RX path for FOU is implemented in a new fou
module. To enable FOU for a particular protocol, a UDP-FOU socket is
opened to the port to receive FOU packets. The socket is mapped to the
IP protocol for the packets. The XFRM mechanism used to receive
encapsulated packets (udp_encap_rcv) for the port. Upon reception, the
UDP is removed and packet is reinjected in the stack for the
corresponding protocol associated with the socket (return -protocol
from udp_encap_rcv function).
GRO is provided with the appropriate fou_gro_receive and
fou_gro_complete. These routines need to know the encapsulation
protocol so we save that in udp_offloads structure with the port
and pass it in the napi_gro_cb structure.
* TX
This patch series implements FOU transmit encapsulation for IPIP, GRE, and
SIT. This done by some common infrastructure in ip_tunnel including an
ip_tunnel_encap to perform FOU encapsulation and common configuration
to enable FOU on IP tunnels. FOU is configured on existing tunnels and
does not create any new interfaces. The transmit and receive paths are
independent, so use of FOU may be assymetric between tunnel endpoints.
* Configuration
The fou module using netlink to configure FOU receive ports. The ip
command can be augmented with a fou subcommand to support this. e.g. to
configure FOU for IPIP on port 5555:
ip fou add port 5555 ipproto 4
GRE, IPIP, and SIT have been modified with netlink commands to
configure use of FOU on transmit. The "ip link" command will be
augmented with an encap subcommand (for supporting various forms of
secondary encapsulation). For instance, to configure an ipip tunnel
with FOU on port 5555:
ip link add name tun1 type ipip \
remote 192.168.1.1 local 192.168.1.2 ttl 225 \
encap fou encap-sport auto encap-dport 5555
* Notes
- This patch set does not implement GSO for FOU. The UDP encapsulation
code assumes TEB, so that will need to be reimplemented.
- When a packet is received through FOU, the UDP header is not
actually removed for the skbuf, pointers to transport header
and length in the IP header are updated (like in ESP/UDP RX). A
side effect is the IP header will now appear to have an incorrect
checksum by an external observer (e.g. tcpdump), it will be off
by sizeof UDP header. If necessary we could adjust the checksum
to compensate.
- Performance results are below. My expectation is that FOU should
entail little overhead (clearly there is some work to do :-) ).
Optimizing UDP socket lookup for encapsulation ports should help
significantly.
- I really don't expect/want devices to have special support for any
of this. Generic checksum offload mechanisms (NETIF_HW_CSUM
and use of CHECKSUM_COMPLETE) should be sufficient. RSS and flow
steering is provided by commonly implemented UDP hashing. GRO/GSO
seem fairly comparable with LRO/TSO already.
* Performance
Ran netperf TCP_RR and TCP_STREAM tests across various configurations.
This was performed on bnx2x and I disabled TSO/GSO on sender to get
fair comparison for FOU versus non-FOU. CPU utilization is reported
for receive in TCP_STREAM.
GRE
IPv4, FOU, UDP checksum enabled
TCP_STREAM
24.85% CPU utilization
9310.6 Mbps
TCP_RR
94.2% CPU utilization
155/249/460 90/95/99% latencies
1.17018e+06 tps
IPv4, FOU, UDP checksum disabled
TCP_STREAM
31.04% CPU utilization
9302.22 Mbps
TCP_RR
94.13% CPU utilization
154/239/419 90/95/99% latencies
1.17555e+06 tps
IPv4, no FOU
TCP_STREAM
23.13% CPU utilization
9354.58 Mbps
TCP_RR
90.24% CPU utilization
156/228/360 90/95/99% latencies
1.18169e+06 tps
IPIP
FOU, UDP checksum enabled
TCP_STREAM
24.13% CPU utilization
9328 Mbps
TCP_RR
94.23
149/237/429 90/95/99% latencies
1.19553e+06 tps
FOU, UDP checksum disabled
TCP_STREAM
29.13% CPU utilization
9370.25 Mbps
TCP_RR
94.13% CPU utilization
149/232/398 90/95/99% latencies
1.19225e+06 tps
No FOU
TCP_STREAM
10.43% CPU utilization
5302.03 Mbps
TCP_RR
51.53% CPU utilization
215/324/475 90/95/99% latencies
864998 tps
SIT
FOU, UDP checksum enabled
TCP_STREAM
30.38% CPU utilization
9176.76 Mbps
TCP_RR
96.9% CPU utilization
170/281/581 90/95/99% latencies
1.03372e+06 tps
FOU, UDP checksum disabled
TCP_STREAM
39.6% CPU utilization
9176.57 Mbps
TCP_RR
97.14% CPU utilization
167/272/548 90/95/99% latencies
1.03203e+06 tps
No FOU
TCP_STREAM
11.2% CPU utilization
4636.05 Mbps
TCP_RR
59.51% CPU utilization
232/346/489 90/95/99% latencies
813199 tps
v2:
- Removed encap IP tunnel ioctls, configuration is done by netlink
only.
- Don't export fou_create and fou_destroy, they are currently
intended to be called within fou module only.
- Filled on tunnel netlink structures and functions for new values.
Tom Herbert (7):
net: Export inet_offloads and inet6_offloads
fou: Support for foo-over-udp RX path
fou: Add GRO support
net: Changes to ip_tunnel to support foo-over-udp encapsulation
sit: TX path for sit/UDP foo-over-udp encapsulation
ipip: TX path for IPIP/UDP foo-over-udp encapsulation
gre: TX path for GRE/UDP foo-over-udp encapsulation
include/linux/netdevice.h | 3 +-
include/net/ip_tunnels.h | 19 ++-
include/uapi/linux/fou.h | 32 ++++
include/uapi/linux/if_tunnel.h | 16 ++
net/ipv4/Kconfig | 10 ++
net/ipv4/Makefile | 1 +
net/ipv4/fou.c | 369 +++++++++++++++++++++++++++++++++++++++++
net/ipv4/ip_gre.c | 98 ++++++++++-
net/ipv4/ip_tunnel.c | 91 +++++++++-
net/ipv4/ipip.c | 86 +++++++++-
net/ipv4/protocol.c | 1 +
net/ipv4/udp_offload.c | 5 +-
net/ipv6/protocol.c | 1 +
net/ipv6/sit.c | 107 ++++++++++--
14 files changed, 815 insertions(+), 24 deletions(-)
create mode 100644 include/uapi/linux/fou.h
create mode 100644 net/ipv4/fou.c
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply
* [PATCH net-next 3/3] tcp: do not copy headers in tcp_collapse()
From: Eric Dumazet @ 2014-09-15 2:56 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Yuchung Cheng, Neal Cardwell, Eric Dumazet
In-Reply-To: <1410749780-30613-1-git-send-email-edumazet@google.com>
tcp_collapse() wants to shrink skb so that the overhead is minimal.
Now we store tcp flags into TCP_SKB_CB(skb)->tcp_flags, we no longer
need to keep around full headers.
Whole available space is dedicated to the payload.
Signed-of-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/tcp_input.c | 17 ++---------------
1 file changed, 2 insertions(+), 15 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 228bf0c5ff19..ea92f23ffaf1 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4535,26 +4535,13 @@ restart:
return;
while (before(start, end)) {
+ int copy = min_t(int, SKB_MAX_ORDER(0, 0), end - start);
struct sk_buff *nskb;
- unsigned int header = skb_headroom(skb);
- int copy = SKB_MAX_ORDER(header, 0);
- /* Too big header? This can happen with IPv6. */
- if (copy < 0)
- return;
- if (end - start < copy)
- copy = end - start;
- nskb = alloc_skb(copy + header, GFP_ATOMIC);
+ nskb = alloc_skb(copy, GFP_ATOMIC);
if (!nskb)
return;
- skb_set_mac_header(nskb, skb_mac_header(skb) - skb->head);
- skb_set_network_header(nskb, (skb_network_header(skb) -
- skb->head));
- skb_set_transport_header(nskb, (skb_transport_header(skb) -
- skb->head));
- skb_reserve(nskb, header);
- memcpy(nskb->head, skb->head, header);
memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start;
__skb_queue_before(list, skb, nskb);
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH net-next 2/3] tcp: allow segment with FIN in tcp_try_coalesce()
From: Eric Dumazet @ 2014-09-15 2:56 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Yuchung Cheng, Neal Cardwell, Eric Dumazet
In-Reply-To: <1410749780-30613-1-git-send-email-edumazet@google.com>
There is nothing special with allowing a segment with FIN to be aggregated,
if we take care to add tcp flags.
Signed-of-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/tcp_input.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 8f639a4face9..228bf0c5ff19 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4143,9 +4143,6 @@ static bool tcp_try_coalesce(struct sock *sk,
*fragstolen = false;
- if (tcp_hdr(from)->fin)
- return false;
-
/* Its possible this segment overlaps with prior segment in queue */
if (TCP_SKB_CB(from)->seq != TCP_SKB_CB(to)->end_seq)
return false;
@@ -4158,6 +4155,7 @@ static bool tcp_try_coalesce(struct sock *sk,
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOALESCE);
TCP_SKB_CB(to)->end_seq = TCP_SKB_CB(from)->end_seq;
TCP_SKB_CB(to)->ack_seq = TCP_SKB_CB(from)->ack_seq;
+ TCP_SKB_CB(to)->tcp_flags |= TCP_SKB_CB(from)->tcp_flags;
return true;
}
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH net-next 1/3] tcp: use TCP_SKB_CB(skb)->tcp_flags in input path
From: Eric Dumazet @ 2014-09-15 2:56 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Yuchung Cheng, Neal Cardwell, Eric Dumazet
In-Reply-To: <1410749780-30613-1-git-send-email-edumazet@google.com>
Input path of TCP do not currently uses TCP_SKB_CB(skb)->tcp_flags,
which is only used in output path.
tcp_recvmsg(), looks at tcp_hdr(skb)->syn for every skb found in receive queue,
and it is unfortunate because this bit is located in a cache line right before
the payload.
We can simplify TCP by copying tcp flags into TCP_SKB_CB(skb)->tcp_flags.
This patch does so, and avoids the cache line miss in tcp_recvmsg()
Following patches will
- allow a segment with FIN being coalesced in tcp_try_coalesce()
- simplify tcp_collapse() by not copying the headers.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/tcp.c | 18 ++++++++++--------
net/ipv4/tcp_input.c | 10 +++++-----
net/ipv4/tcp_ipv4.c | 1 +
net/ipv6/tcp_ipv6.c | 1 +
4 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 541f26a67ba2..070aeff1b131 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1510,9 +1510,9 @@ static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) {
offset = seq - TCP_SKB_CB(skb)->seq;
- if (tcp_hdr(skb)->syn)
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
offset--;
- if (offset < skb->len || tcp_hdr(skb)->fin) {
+ if (offset < skb->len || (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)) {
*off = offset;
return skb;
}
@@ -1585,7 +1585,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
if (offset + 1 != skb->len)
continue;
}
- if (tcp_hdr(skb)->fin) {
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) {
sk_eat_skb(sk, skb, false);
++seq;
break;
@@ -1722,11 +1722,11 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
break;
offset = *seq - TCP_SKB_CB(skb)->seq;
- if (tcp_hdr(skb)->syn)
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
offset--;
if (offset < skb->len)
goto found_ok_skb;
- if (tcp_hdr(skb)->fin)
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
goto found_fin_ok;
WARN(!(flags & MSG_PEEK),
"recvmsg bug 2: copied %X seq %X rcvnxt %X fl %X\n",
@@ -1959,7 +1959,7 @@ skip_copy:
if (used + offset < skb->len)
continue;
- if (tcp_hdr(skb)->fin)
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
goto found_fin_ok;
if (!(flags & MSG_PEEK)) {
sk_eat_skb(sk, skb, copied_early);
@@ -2160,8 +2160,10 @@ void tcp_close(struct sock *sk, long timeout)
* reader process may not have drained the data yet!
*/
while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
- u32 len = TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq -
- tcp_hdr(skb)->fin;
+ u32 len = TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq;
+
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
+ len--;
data_was_unread += len;
__kfree_skb(skb);
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index f97003ad0af5..8f639a4face9 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4093,7 +4093,7 @@ static void tcp_ofo_queue(struct sock *sk)
__skb_unlink(skb, &tp->out_of_order_queue);
__skb_queue_tail(&sk->sk_receive_queue, skb);
tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
- if (tcp_hdr(skb)->fin)
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
tcp_fin(sk);
}
}
@@ -4513,7 +4513,7 @@ restart:
* - bloated or contains data before "start" or
* overlaps to the next one.
*/
- if (!tcp_hdr(skb)->syn && !tcp_hdr(skb)->fin &&
+ if (!(TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)) &&
(tcp_win_from_space(skb->truesize) > skb->len ||
before(TCP_SKB_CB(skb)->seq, start))) {
end_of_skbs = false;
@@ -4532,7 +4532,8 @@ restart:
/* Decided to skip this, advance start seq. */
start = TCP_SKB_CB(skb)->end_seq;
}
- if (end_of_skbs || tcp_hdr(skb)->syn || tcp_hdr(skb)->fin)
+ if (end_of_skbs ||
+ (TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)))
return;
while (before(start, end)) {
@@ -4579,8 +4580,7 @@ restart:
skb = tcp_collapse_one(sk, skb, list);
if (!skb ||
skb == tail ||
- tcp_hdr(skb)->syn ||
- tcp_hdr(skb)->fin)
+ (TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)))
return;
}
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 7881b96d2b72..006b045716d8 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1638,6 +1638,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
skb->len - th->doff * 4);
TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
+ TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
TCP_SKB_CB(skb)->tcp_tw_isn = 0;
TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph);
TCP_SKB_CB(skb)->sacked = 0;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 1835480336ac..de51a88bec6f 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1415,6 +1415,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
skb->len - th->doff*4);
TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
+ TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
TCP_SKB_CB(skb)->tcp_tw_isn = 0;
TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);
TCP_SKB_CB(skb)->sacked = 0;
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply related
* [PATCH net-next 0/3] tcp: no longer keep around headers in input path
From: Eric Dumazet @ 2014-09-15 2:56 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Yuchung Cheng, Neal Cardwell, Eric Dumazet
Looking at tcp_try_coalesce() I was wondering why I did :
if (tcp_hdr(from)->fin)
return false;
The answer would be to allow the aggregation, if we simply OR the FIN and PSH
flags eventually present in @from to @to packet.
Then, looking at tcp_recvmsg(), I realized we access tcp_hdr(skb)->syn
(and maybe tcp_hdr(skb)->fin) for every packet we process from socket
receive queue.
We have to understand TCP flags are cold in cpu caches most of the time
(assuming RPS/RFS is used, or that application calls recvmsg() a long
time after incoming packet was processed), and bringing a whole
cache line only to access one bit is not very nice.
It would make sense to use in TCP input path TCP_SKB_CB(skb)->tcp_flags
as we do in output path.
This saves one cache line miss, and TCP tcp_collapse() could avoid dealing
with the headers.
Eric Dumazet (3):
tcp: use TCP_SKB_CB(skb)->tcp_flags in input path
tcp: allow segment with FIN in tcp_try_coalesce()
tcp: do not copy headers in tcp_collapse()
net/ipv4/tcp.c | 18 ++++++++++--------
net/ipv4/tcp_input.c | 31 ++++++++-----------------------
net/ipv4/tcp_ipv4.c | 1 +
net/ipv6/tcp_ipv6.c | 1 +
4 files changed, 20 insertions(+), 31 deletions(-)
--
2.1.0.rc2.206.gedb03e5
^ permalink raw reply
* Re: [PATCH] net: ethernet: marvell: sky2.c: Cleaning up missing null-terminate in conjunction with strncpy
From: Stephen Hemminger @ 2014-09-15 2:05 UTC (permalink / raw)
To: Rickard Strandqvist; +Cc: Mirko Lindner, netdev, linux-kernel
In-Reply-To: <1410716023-16068-1-git-send-email-rickard_strandqvist@spectrumdigital.se>
On Sun, 14 Sep 2014 19:33:43 +0200
Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se> wrote:
> Replacing strncpy with strlcpy to avoid strings that lacks null terminate.
>
> Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
> ---
> drivers/net/ethernet/marvell/sky2.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
> index dba48a5c..7053d38 100644
> --- a/drivers/net/ethernet/marvell/sky2.c
> +++ b/drivers/net/ethernet/marvell/sky2.c
> @@ -4907,7 +4907,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
> };
>
> if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OP_2)
> - strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
> + strlcpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
> else
> snprintf(buf, sz, "(chip %#x)", chipid);
> return buf;
Useless and unnecessary since the list of names is right there.
Why not avoid the copy all together?
Subject: sky2: avoid strncpy
Don't use strncpy() since security thought police think it is bad.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
--- a/drivers/net/ethernet/marvell/sky2.c 2014-08-25 09:01:16.292060455 -0700
+++ b/drivers/net/ethernet/marvell/sky2.c 2014-09-14 19:02:26.731034094 -0700
@@ -4889,7 +4889,7 @@ static int sky2_test_msi(struct sky2_hw
}
/* This driver supports yukon2 chipset only */
-static const char *sky2_name(u8 chipid, char *buf, int sz)
+static const char *sky2_name(u8 chipid)
{
const char *name[] = {
"XL", /* 0xb3 */
@@ -4905,11 +4905,12 @@ static const char *sky2_name(u8 chipid,
"OptimaEEE", /* 0xbd */
"Optima 2", /* 0xbe */
};
+ static char buf[16];
if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OP_2)
- strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
- else
- snprintf(buf, sz, "(chip %#x)", chipid);
+ return name[chipid - CHIP_ID_YUKON_XL];
+
+ snprintf(buf, sizeof(buf), "(chip %#x)", chipid);
return buf;
}
@@ -4919,7 +4920,6 @@ static int sky2_probe(struct pci_dev *pd
struct sky2_hw *hw;
int err, using_dac = 0, wol_default;
u32 reg;
- char buf1[16];
err = pci_enable_device(pdev);
if (err) {
@@ -5014,7 +5014,7 @@ static int sky2_probe(struct pci_dev *pd
}
dev_info(&pdev->dev, "Yukon-2 %s chip revision %d\n",
- sky2_name(hw->chip_id, buf1, sizeof(buf1)), hw->chip_rev);
+ sky2_name(hw->chip_id), hw->chip_rev);
sky2_reset(hw);
^ 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