All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wang Shanker <shankerwangmiao@gmail.com>
To: James Chapman <jchapman@katalix.com>
Cc: netdev@vger.kernel.org
Subject: Re: [PATCH] ip: add udp_csum, udp6_csum_tx, udp6_csum_rx control flags to ip l2tp add tunnel
Date: Thu, 28 Apr 2016 01:06:30 +0800	[thread overview]
Message-ID: <AFE6B2C1-93B5-4782-870D-2C6C81BF6F52@gmail.com> (raw)
In-Reply-To: <FD67CA88-0731-4DD7-AC78-5A4B922810D6@gmail.com>



> 在 2016年4月27日,23:33,Wang Shanker <shankerwangmiao@gmail.com> 写道:
> 
> 
> 
>> 在 2016年4月27日,20:21,James Chapman <jchapman@katalix.com> 写道:
>> 
>> On 26 April 2016 at 15:15, Wang Shanker <shankerwangmiao@gmail.com> wrote:
>>> Hi, all
>>> 
>>> It’s my first time to contribute to such an important open source project. Things began when I upgraded my server, called "Server A", form ubuntu 14.04 to 16.04, which is shipped with new kernel version, 4.4. After upgrade, I soon found a l2tp tunnel between this server and another linux server, called "Server B", via ipv6 broke down. Here is the network topology:
>>> 
>>> +----------+                    +----------+
>>> | Server A | -- IPV6 Network -- | Server B |
>>> +----------+                    +----------+
>>> 
>>> The l2tp tunnel was encapsulated in udp datagrams. All the configuration was normal and could work after I reverted the kernel on Server A to original version.
>>> 
>>> Here is what i did to create the tunnel:
>>> 
>>> ```
>>> on Server A:
>>> 
>>> ip l2tp add tunnel tunnel_id 86 peer_tunnel_id 86 remote 2001:db8::aaaa local 2001:db8::bbbb udp_sport 1086 udp_dport 1086
>>> ip l2tp add session name l2tpeth0 tunnel_id 86 session_id 86 peer_session_id 86
>>> ip l s l2tpeth0 up
>>> 
>>> on Server B:
>>> 
>>> ip l2tp add tunnel tunnel_id 86 peer_tunnel_id 86 local 2001:db8::aaaa remote 2001:db8::bbbb udp_sport 1086 udp_dport 1086
>>> ip l2tp add session name l2tpeth0 tunnel_id 86 session_id 86 peer_session_id 86
>>> ip l s l2tpeth0 up
>>> 
>>> ```
>>> 
>>> When I used tcpdump to diagnose the problem, I got such result:
>>> 
>>> ```
>>> on Server A:
>>> 
>>> arping -i l2tpeth0 -0 1.2.3.4
>>> 
>>> on Server B:
>>> 
>>> tcpdump -i eth0 -n port 1086  -v
>>> 
>>> 21:35:57.818810 IP6 (flowlabel 0x8f028, hlim 64, next-header UDP (17) payload length: 62) 2001:db8::aaaa.1086 > 2001:db8::bbbb.1086: [bad udp cksum 0x0000 -> 0x1140!] UDP, length 54
>>> 21:35:58.820572 IP6 (flowlabel 0x8f028, hlim 64, next-header UDP (17) payload length: 62) 2001:db8::aaaa.1086 > 2001:db8::bbbb.1086: [bad udp cksum 0x0000 -> 0x1140!] UDP, length 54
>>> 21:35:59.822216 IP6 (flowlabel 0x8f028, hlim 64, next-header UDP (17) payload length: 62) 2001:db8::aaaa.1086 > 2001:db8::bbbb.1086: [bad udp cksum 0x0000 -> 0x1140!] UDP, length 54
>>> 
>>> ```
>>> 
>>> After looking into kernel source, I found out that in this commit a new feature to set udp6 checksum to zero in commit 6b649fe, which added `L2TP_ATTR_UDP_ZERO_CSUM6_TX` and `L2TP_ATTR_UDP_ZERO_CSUM6_TX`.
>>> 
>>> As a result, I added `udp_csum`, `udp6_csum_tx`, `udp6_csum_rx` control flags to `ip l2tp add tunnel` to control those attributes about checksum.
>>> 
>>> Using this to create the tunnel instead on Server A:
>>> 
>>> ```
>>> ip l2tp add tunnel tunnel_id 86 peer_tunnel_id 86 remote 2001:db8::aaaa local 2001:db8::bbbb udp_sport 1086 udp_dport 1086 udp6_csum_tx on udp6_csum_rx on
>>> ```
>>> 
>>> I finally got:
>>> 
>>> ```
>>> on Server A:
>>> 
>>> arping -i l2tpeth0 -0 1.2.3.4
>>> 
>>> on Server B:
>>> 
>>> tcpdump -i eth0 -n port 1086  -v
>>> 
>>> 22:07:03.844297 IP6 (flowlabel 0x8f028, hlim 64, next-header UDP (17) payload length: 62) 2001:db8::aaaa.1086 > 2001:db8::bbbb.1086: [udp sum ok] UDP, length 54
>>> 22:07:04.845717 IP6 (flowlabel 0x8f028, hlim 64, next-header UDP (17) payload length: 62) 2001:db8::aaaa.1086 > 2001:db8::bbbb.1086: [udp sum ok] UDP, length 54
>>> 22:07:05.847965 IP6 (flowlabel 0x8f028, hlim 64, next-header UDP (17) payload length: 62) 2001:db8::aaaa.1086 > 2001:db8::bbbb.1086: [udp sum ok] UDP, length 54
>>> 
>>> tcpdump -i l2tpeth0 -v
>>> 
>>> 22:10:35.691326 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 1.2.3.4 tell 0.0.0.0, length 28
>>> 22:10:36.693627 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 1.2.3.4 tell 0.0.0.0, length 28
>>> 22:10:37.695010 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 1.2.3.4 tell 0.0.0.0, length 28
>>> 22:10:38.697121 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 1.2.3.4 tell 0.0.0.0, length 28
>>> 
>>> ```
>>> 
>>> It seems to work. However, is it the real point that should be fixed and does my patch fix it well? I need your suggestion.
>> 
>> This seems reasonable to me. It is good to provide user control of
>> L2TP checksum options.
>> 
>> However, there is a problem with your patch. The netlink attributes
>> you are accessing to control checksums are flags, not u8 values.
> 
> I’m not so familiar with kernel code. However, in `<linux/l2tp.h>` : 
> 
> ```
> 
> /*
> * ATTR types defined for L2TP
> */
> enum {
> 	L2TP_ATTR_NONE,			/* no data */
> // ...
> 	L2TP_ATTR_IP6_DADDR,		/* struct in6_addr */
> 	L2TP_ATTR_UDP_ZERO_CSUM6_TX,	/* u8 */
> 	L2TP_ATTR_UDP_ZERO_CSUM6_RX,	/* u8 */
> // ...
> 
> }
> ```
> 
> isn’t L2TP_ATTR_UDP_ZERO_CSUM6_TX a u8 value? Or should I use `addattr` instead of `addattr8`? 
> 
>> 
>> Maybe the default checksum setting for such l2tp tunnels should be
>> changed in the l2tp kernel code to match the previous behaviour where
>> IPv6 checksums were disabled?
> 
> I think so. However, I’m confused with those code.
> 
> From the name of the attrs `L2TP_ATTR_UDP_ZERO_CSUM6_TX` and `L2TP_ATTR_UDP_ZERO_CSUM6_RX`, I 
> can tell that when those flags are set, the checksum will be zero. Also, according to the 
> comment of commit 6b649fe in kernel source, “Added new L2TP configuration options to allow 
> TX and RX of zero checksums in IPv6. Default is not to use them.”, checksums shouldn't have
> been zero by default. However, in fact, they are. I think there may be some bugs in kernel
> source. 

I think I’ve got the bug. Here is the patch for kernel

---
 net/l2tp/l2tp_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index afca2eb..6edfa99 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1376,9 +1376,9 @@ static int l2tp_tunnel_sock_create(struct net *net,
                        memcpy(&udp_conf.peer_ip6, cfg->peer_ip6,
                               sizeof(udp_conf.peer_ip6));
                        udp_conf.use_udp6_tx_checksums =
-                           cfg->udp6_zero_tx_checksums;
+                         ! cfg->udp6_zero_tx_checksums;
                        udp_conf.use_udp6_rx_checksums =
-                           cfg->udp6_zero_rx_checksums;
+                         ! cfg->udp6_zero_rx_checksums;
                } else
 #endif
                {
-- 


>> 
>>> 
>>> 
>>> ---
>>> ip/ipl2tp.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 45 insertions(+)
>>> 
>>> diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
>>> index 3c8ee93..67a6482 100644
>>> --- a/ip/ipl2tp.c
>>> +++ b/ip/ipl2tp.c
>>> @@ -56,6 +56,8 @@ struct l2tp_parm {
>>> 
>>>       uint16_t pw_type;
>>>       uint16_t mtu;
>>> +       int udp6_csum_tx:1;
>>> +       int udp6_csum_rx:1;
>>>       int udp_csum:1;
>>>       int recv_seq:1;
>>>       int send_seq:1;
>>> @@ -117,6 +119,9 @@ static int create_tunnel(struct l2tp_parm *p)
>>>       if (p->encap == L2TP_ENCAPTYPE_UDP) {
>>>               addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port);
>>>               addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
>>> +               addattr8 (&req.n, 1024, L2TP_ATTR_UDP_CSUM, p->udp_csum);
>>> +               addattr8 (&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_TX, p->udp6_csum_tx);
>>> +               addattr8 (&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_RX, p->udp6_csum_rx);
>>>       }
>>> 
>>>       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
>>> @@ -282,6 +287,14 @@ static int get_response(struct nlmsghdr *n, void *arg)
>>>               p->l2spec_len = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_LEN]);
>>> 
>>>       p->udp_csum = !!attrs[L2TP_ATTR_UDP_CSUM];
>>> +       if (attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX])
>>> +         p->udp6_csum_tx = rta_getattr_u8(attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX]);
>>> +       else
>>> +         p->udp6_csum_tx = 1;
>>> +       if (attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX])
>>> +         p->udp6_csum_rx = rta_getattr_u8(attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX]);
>>> +       else
>>> +         p->udp6_csum_rx = 1;
>>>       if (attrs[L2TP_ATTR_COOKIE])
>>>               memcpy(p->cookie, RTA_DATA(attrs[L2TP_ATTR_COOKIE]),
>>>                      p->cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_COOKIE]));
>>> @@ -470,6 +483,9 @@ static void usage(void)
>>>       fprintf(stderr, "          tunnel_id ID peer_tunnel_id ID\n");
>>>       fprintf(stderr, "          [ encap { ip | udp } ]\n");
>>>       fprintf(stderr, "          [ udp_sport PORT ] [ udp_dport PORT ]\n");
>>> +       fprintf(stderr, "          [ udp_csum { on | off } ]\n");
>>> +       fprintf(stderr, "          [ udp6_csum_tx { on | off } ]\n");
>>> +       fprintf(stderr, "          [ udp6_csum_rx { on | off } ]\n");
>>>       fprintf(stderr, "Usage: ip l2tp add session [ name NAME ]\n");
>>>       fprintf(stderr, "          tunnel_id ID\n");
>>>       fprintf(stderr, "          session_id ID peer_session_id ID\n");
>>> @@ -500,6 +516,8 @@ static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
>>>       /* Defaults */
>>>       p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
>>>       p->l2spec_len = 4;
>>> +       p->udp6_csum_rx = 1;
>>> +       p->udp6_csum_tx = 1;
>>> 
>>>       while (argc > 0) {
>>>               if (strcmp(*argv, "encap") == 0) {
>>> @@ -569,6 +587,33 @@ static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
>>>                       if (get_u16(&uval, *argv, 0))
>>>                               invarg("invalid port\n", *argv);
>>>                       p->peer_udp_port = uval;
>>> +               } else if (strcmp(*argv, "udp_csum") == 0) {
>>> +                       NEXT_ARG();
>>> +                       if (strcmp(*argv, "on") == 0) {
>>> +                               p->udp_csum = 1;
>>> +                       } else if (strcmp(*argv, "off") == 0) {
>>> +                               p->udp_csum = 0;
>>> +                       } else {
>>> +                               invarg("invalid option for udp_csum\n", *argv);
>>> +                       }
>>> +               } else if (strcmp(*argv, "udp6_csum_rx") == 0) {
>>> +                       NEXT_ARG();
>>> +                       if (strcmp(*argv, "on") == 0) {
>>> +                               p->udp6_csum_rx = 1;
>>> +                       } else if (strcmp(*argv, "off") == 0) {
>>> +                               p->udp6_csum_rx = 0;
>>> +                       } else {
>>> +                               invarg("invalid option for udp6_csum_rx\n", *argv);
>>> +                       }
>>> +               } else if (strcmp(*argv, "udp6_csum_tx") == 0) {
>>> +                       NEXT_ARG();
>>> +                       if (strcmp(*argv, "on") == 0) {
>>> +                               p->udp6_csum_tx = 1;
>>> +                       } else if (strcmp(*argv, "off") == 0) {
>>> +                               p->udp6_csum_tx = 0;
>>> +                       } else {
>>> +                               invarg("invalid option for udp6_csum_tx\n", *argv);
>>> +                       }
>>>               } else if (strcmp(*argv, "offset") == 0) {
>>>                       __u8 uval;
>>> 
>>> --
>>> 2.5.2

  reply	other threads:[~2016-04-27 17:06 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-27 12:21 [PATCH] ip: add udp_csum, udp6_csum_tx, udp6_csum_rx control flags to ip l2tp add tunnel James Chapman
2016-04-27 15:33 ` Wang Shanker
2016-04-27 17:06   ` Wang Shanker [this message]
2016-04-28 14:50     ` James Chapman
2016-05-02 22:19       ` Stephen Hemminger
2016-05-03  2:40         ` Wang Shanker
  -- strict thread matches above, loose matches on Subject: below --
2016-04-26 14:15 Wang Shanker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=AFE6B2C1-93B5-4782-870D-2C6C81BF6F52@gmail.com \
    --to=shankerwangmiao@gmail.com \
    --cc=jchapman@katalix.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.