Skip to content

Commit d7e7714

Browse files
mkp-rhigsilya
authored andcommitted
tunnel: Allow UDP zero checksum with IPv6 tunnels.
This patch adopts the proposed RFC 6935 by allowing null UDP checksums even if the tunnel protocol is IPv6. This is already supported by Linux through the udp6zerocsumtx tunnel option. It is disabled by default and IPv6 tunnels are flagged as requiring a checksum, but this patch enables the user to set csum=false on IPv6 tunnels. Acked-by: Simon Horman <horms@ovn.org> Signed-off-by: Mike Pattrick <mkp@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
1 parent 4935e89 commit d7e7714

9 files changed

+78
-10
lines changed

NEWS

+11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ Post-v3.3.0
1111
* Conntrack now supports 'random' flag for selecting ports in a range
1212
while natting and 'persistent' flag for selection of the IP address
1313
from a range.
14+
* IPv6 UDP tunnel encapsulation including Geneve and VXLAN will now
15+
honour the csum option. Configuring the interface with
16+
"options:csum=false" now has the same effect as the udp6zerocsumtx
17+
option has with Linux kernel UDP tunnels.
1418
- The primary development branch has been renamed from 'master' to 'main'.
1519
The OVS tree remains hosted on GitHub.
1620
https://github.com/openvswitch/ovs.git
@@ -23,6 +27,13 @@ Post-v3.3.0
2327
* Added custom transaction support to the Idl via add_op().
2428
* Added support for different output formats like 'json' to Python's
2529
unixctl classes.
30+
- Tunnels:
31+
* Previously the kernel datapath did not enable UDP checksums by default
32+
in IPv6 tunnels. This behaviour is non-standard, differs from the
33+
Linux kernel, and as also different than the userspace datapath. Now
34+
these tunnels will calculate checksums by default and that behaviour can
35+
be changed with "options:csum=false" just as with the userspace
36+
datapath.
2637

2738

2839
v3.3.0 - 16 Feb 2024

lib/netdev-native-tnl.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ udp_build_header(const struct netdev_tunnel_config *tnl_cfg,
384384
udp = netdev_tnl_ip_build_header(data, params, IPPROTO_UDP, 0);
385385
udp->udp_dst = tnl_cfg->dst_port;
386386

387-
if (params->is_ipv6 || params->flow->tunnel.flags & FLOW_TNL_F_CSUM) {
387+
if (params->flow->tunnel.flags & FLOW_TNL_F_CSUM) {
388388
/* Write a value in now to mark that we should compute the checksum
389389
* later. 0xffff is handy because it is transparent to the
390390
* calculation. */

lib/netdev-vport.c

+15-2
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,9 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
702702
tnl_cfg.dst_port = htons(atoi(node->value));
703703
} else if (!strcmp(node->key, "csum") && has_csum) {
704704
if (!strcmp(node->value, "true")) {
705-
tnl_cfg.csum = true;
705+
tnl_cfg.csum = NETDEV_TNL_CSUM_ENABLED;
706+
} else if (!strcmp(node->value, "false")) {
707+
tnl_cfg.csum = NETDEV_TNL_CSUM_DISABLED;
706708
}
707709
} else if (!strcmp(node->key, "seq") && has_seq) {
708710
if (!strcmp(node->value, "true")) {
@@ -850,6 +852,15 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
850852
}
851853
}
852854

855+
/* The default csum state for GRE is special as it does have an optional
856+
* checksum but the default configuration isn't correlated with IP version
857+
* like UDP tunnels are. Likewise, tunnels with no checksum at all must be
858+
* in this state. */
859+
if (tnl_cfg.csum == NETDEV_TNL_CSUM_DEFAULT &&
860+
(!has_csum || strstr(type, "gre"))) {
861+
tnl_cfg.csum = NETDEV_TNL_DEFAULT_NO_CSUM;
862+
}
863+
853864
enum tunnel_layers layers = tunnel_supported_layers(type, &tnl_cfg);
854865
const char *full_type = (strcmp(type, "vxlan") ? type
855866
: (tnl_cfg.exts & (1 << OVS_VXLAN_EXT_GPE)
@@ -1026,8 +1037,10 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
10261037
}
10271038
}
10281039

1029-
if (tnl_cfg->csum) {
1040+
if (tnl_cfg->csum == NETDEV_TNL_CSUM_ENABLED) {
10301041
smap_add(args, "csum", "true");
1042+
} else if (tnl_cfg->csum == NETDEV_TNL_CSUM_DISABLED) {
1043+
smap_add(args, "csum", "false");
10311044
}
10321045

10331046
if (tnl_cfg->set_seq) {

lib/netdev.h

+17-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,22 @@ enum netdev_srv6_flowlabel {
111111
SRV6_FLOWLABEL_COMPUTE,
112112
};
113113

114+
enum netdev_tnl_csum {
115+
/* Default value for UDP tunnels if no configurations is present. Enforce
116+
* checksum calculation in IPv6 tunnels, disable in IPv4 tunnels. */
117+
NETDEV_TNL_CSUM_DEFAULT = 0,
118+
119+
/* Checksum explicitly to be calculated. */
120+
NETDEV_TNL_CSUM_ENABLED,
121+
122+
/* Checksum calculation explicitly disabled. */
123+
NETDEV_TNL_CSUM_DISABLED,
124+
125+
/* A value for when there is no checksum or the default value is no
126+
* checksum regardless of IP version. */
127+
NETDEV_TNL_DEFAULT_NO_CSUM,
128+
};
129+
114130
/* Configuration specific to tunnels. */
115131
struct netdev_tunnel_config {
116132
ovs_be64 in_key;
@@ -139,7 +155,7 @@ struct netdev_tunnel_config {
139155
uint8_t tos;
140156
bool tos_inherit;
141157

142-
bool csum;
158+
enum netdev_tnl_csum csum;
143159
bool dont_fragment;
144160
enum netdev_pt_mode pt_mode;
145161

ofproto/tunnel.c

+8-2
Original file line numberDiff line numberDiff line change
@@ -465,9 +465,13 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow,
465465

466466
flow->tunnel.flags &= ~(FLOW_TNL_F_MASK & ~FLOW_TNL_PUB_F_MASK);
467467
flow->tunnel.flags |= (cfg->dont_fragment ? FLOW_TNL_F_DONT_FRAGMENT : 0)
468-
| (cfg->csum ? FLOW_TNL_F_CSUM : 0)
469468
| (cfg->out_key_present ? FLOW_TNL_F_KEY : 0);
470469

470+
if (cfg->csum == NETDEV_TNL_CSUM_ENABLED ||
471+
(cfg->csum == NETDEV_TNL_CSUM_DEFAULT && !flow->tunnel.ip_dst)) {
472+
flow->tunnel.flags |= FLOW_TNL_F_CSUM;
473+
}
474+
471475
if (cfg->set_egress_pkt_mark) {
472476
flow->pkt_mark = cfg->egress_pkt_mark;
473477
wc->masks.pkt_mark = UINT32_MAX;
@@ -706,8 +710,10 @@ tnl_port_format(const struct tnl_port *tnl_port, struct ds *ds)
706710
ds_put_cstr(ds, ", df=false");
707711
}
708712

709-
if (cfg->csum) {
713+
if (cfg->csum == NETDEV_TNL_CSUM_ENABLED) {
710714
ds_put_cstr(ds, ", csum=true");
715+
} else if (cfg->csum == NETDEV_TNL_CSUM_DISABLED) {
716+
ds_put_cstr(ds, ", csum=false");
711717
}
712718

713719
ds_put_cstr(ds, ")\n");

tests/tunnel-push-pop-ipv6.at

+9
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,15 @@ AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl
610610
2001:cafe::93 f8:bc:12:44:34:b7 br0
611611
])
612612

613+
dnl Disable checksum from VXLAN port.
614+
AT_CHECK([ovs-vsctl set Interface t3 options:csum=false])
615+
AT_CHECK([ovs-ofctl del-flows int-br])
616+
AT_CHECK([ovs-ofctl add-flow int-br action=4])
617+
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=36:b1:ee:7c:01:01,dst=36:b1:ee:7c:01:02),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
618+
AT_CHECK([tail -1 stdout], [0],
619+
[Datapath actions: tnl_push(tnl_port(4789),header(size=70,type=4,eth(dst=f8:bc:12:44:34:b7,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::93,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x8000000,vni=0x0)),out_port(100)),1
620+
])
621+
613622
ovs-appctl time/warp 10000
614623

615624
AT_CHECK([ovs-vsctl del-port int-br t3 \

tests/tunnel-push-pop.at

+7
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,13 @@ AT_CHECK([tail -1 stdout], [0],
642642
[Datapath actions: tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x8000000,vni=0x7b)),out_port(100)),1
643643
])
644644

645+
dnl Check VXLAN tunnel push with checksum.
646+
AT_CHECK([ovs-vsctl set Interface t2 options:csum=true])
647+
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=36:b1:ee:7c:01:01,dst=36:b1:ee:7c:01:02),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
648+
AT_CHECK([tail -1 stdout], [0],
649+
[Datapath actions: tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0xffff),vxlan(flags=0x8000000,vni=0x7b)),out_port(100)),1
650+
])
651+
645652
AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
646653
1.1.2.92 f8:bc:12:44:34:b6 br0
647654
1.1.2.93 f8:bc:12:44:34:b7 br0

tests/tunnel.at

+1-1
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
10381038

10391039
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0,src=1.1.1.1,dst=1.1.1.2,ttl=64),in_port(4789)'], [0], [stdout])
10401040
AT_CHECK([tail -1 stdout], [0],
1041-
[Datapath actions: set(tunnel(ipv6_dst=2001:cafe::1,ttl=64,tp_dst=4789,flags(df))),4789
1041+
[Datapath actions: set(tunnel(ipv6_dst=2001:cafe::1,ttl=64,tp_dst=4789,flags(df|csum))),4789
10421042
])
10431043

10441044
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,ipv6_src=2001:cafe::1,ipv6_dst=2001:cafe::2,ttl=64),in_port(4789)'], [0], [stdout])

vswitchd/vswitch.xml

+9-3
Original file line numberDiff line numberDiff line change
@@ -3207,9 +3207,15 @@
32073207
<column name="options" key="csum" type='{"type": "boolean"}'>
32083208
<p>
32093209
Optional. Compute encapsulation header (either GRE or UDP)
3210-
checksums on outgoing packets. Default is disabled, set to
3211-
<code>true</code> to enable. Checksums present on incoming
3212-
packets will be validated regardless of this setting.
3210+
checksums on outgoing packets. When unset (the default value),
3211+
checksum computing for outgoing packets is enabled for UDP IPv6
3212+
tunnels, and disabled for GRE and IPv4 UDP tunnels. When set to
3213+
<code>false</code>, no checksums will be computed for outgoing
3214+
tunnel encapsulation headers. When <code>true</code>, checksums
3215+
will be computed for all outgoing tunnel encapsulation headers.
3216+
Checksums present on incoming packets will be validated
3217+
regardless of this setting. Incoming packets without a checksum
3218+
will also be accepted regardless of this setting.
32133219
</p>
32143220

32153221
<p>

0 commit comments

Comments
 (0)