139 lines
5.6 KiB
Diff
139 lines
5.6 KiB
Diff
From b8657dada9641fbd2bd3a3f882e0862448d60910 Mon Sep 17 00:00:00 2001
|
|
From: Timothy Redaelli <tredaelli@redhat.com>
|
|
Date: Thu, 23 Nov 2023 19:47:54 +0100
|
|
Subject: [PATCH] netdev-offload-tc: Check geneve metadata length.
|
|
|
|
Currently ovs-vswitchd crashes, with hw offloading enabled, if a geneve
|
|
packet with corrupted metadata is received, because the metadata header
|
|
is not verified correctly.
|
|
|
|
This commit adds a check for geneve metadata length and, if the header
|
|
is wrong, the packet is not sent to flower.
|
|
|
|
It also includes a system-traffic test for geneve packets with corrupted
|
|
metadata.
|
|
|
|
Fixes: a468645c6d33 ("lib/tc: add geneve with option match offload")
|
|
Reported-by: Haresh Khandelwal <hakhande@redhat.com>
|
|
Signed-off-by: Timothy Redaelli <tredaelli@redhat.com>
|
|
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
|
|
|
|
Reference:https://github.com/openvswitch/ovs/commit/b8657dada9641fbd2bd3a3f882e0862448d60910
|
|
Conflict:The return value is not modified in flower_match_to_tun_opt function
|
|
|
|
---
|
|
lib/netdev-offload-tc.c | 21 +++++++++++++++++---
|
|
tests/system-offloads-traffic.at | 34 ++++++++++++++++++++++++++++++++
|
|
2 files changed, 52 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
|
|
index b8c3738..e248d0b 100644
|
|
--- a/lib/netdev-offload-tc.c
|
|
+++ b/lib/netdev-offload-tc.c
|
|
@@ -42,6 +42,7 @@
|
|
VLOG_DEFINE_THIS_MODULE(netdev_offload_tc);
|
|
|
|
static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5);
|
|
+static struct vlog_rate_limit warn_rl = VLOG_RATE_LIMIT_INIT(10, 2);
|
|
|
|
static struct hmap ufid_tc = HMAP_INITIALIZER(&ufid_tc);
|
|
static bool multi_mask_per_prio = false;
|
|
@@ -1068,12 +1069,12 @@ test_key_and_mask(struct match *match)
|
|
return 0;
|
|
}
|
|
|
|
-static void
|
|
+static int
|
|
flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl,
|
|
const struct flow_tnl *tnl_mask)
|
|
{
|
|
struct geneve_opt *opt, *opt_mask;
|
|
- int len, cnt = 0;
|
|
+ int tot_opt_len, len, cnt = 0;
|
|
|
|
memcpy(flower->key.tunnel.metadata.opts.gnv, tnl->metadata.opts.gnv,
|
|
tnl->metadata.present.len);
|
|
@@ -1084,7 +1085,16 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl,
|
|
|
|
len = flower->key.tunnel.metadata.present.len;
|
|
while (len) {
|
|
+ if (len < sizeof *opt) {
|
|
+ return EOPNOTSUPP;
|
|
+ }
|
|
+
|
|
opt = &flower->key.tunnel.metadata.opts.gnv[cnt];
|
|
+ tot_opt_len = sizeof *opt + opt->length * 4;
|
|
+ if (len < tot_opt_len) {
|
|
+ return EOPNOTSUPP;
|
|
+ }
|
|
+
|
|
opt_mask = &flower->mask.tunnel.metadata.opts.gnv[cnt];
|
|
|
|
opt_mask->length = opt->length;
|
|
@@ -1096,6 +1106,7 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl,
|
|
/* Copying from the key and not from the mask, since in the 'flower'
|
|
* the length for a mask is not a mask, but the actual length. */
|
|
flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len;
|
|
+ return 0;
|
|
}
|
|
|
|
static int
|
|
@@ -1149,7 +1160,11 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
|
|
flower.mask.tunnel.ttl = tnl_mask->ip_ttl;
|
|
flower.mask.tunnel.id = (tnl->flags & FLOW_TNL_F_KEY) ? tnl_mask->tun_id : 0;
|
|
if (!strcmp(netdev_get_type(netdev), "geneve")) {
|
|
- flower_match_to_tun_opt(&flower, tnl, tnl_mask);
|
|
+ err = flower_match_to_tun_opt(&flower, tnl, tnl_mask);
|
|
+ if (err) {
|
|
+ VLOG_WARN_RL(&warn_rl, "Unable to parse geneve options");
|
|
+ return err;
|
|
+ }
|
|
}
|
|
flower.tunnel = true;
|
|
}
|
|
diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at
|
|
index bfad66e..9643535 100644
|
|
--- a/tests/system-offloads-traffic.at
|
|
+++ b/tests/system-offloads-traffic.at
|
|
@@ -116,3 +116,37 @@ matchall
|
|
])
|
|
OVS_TRAFFIC_VSWITCHD_STOP
|
|
AT_CLEANUP
|
|
+
|
|
+AT_SETUP([offloads - handling of geneve corrupted metadata - offloads enabled])
|
|
+OVS_CHECK_GENEVE()
|
|
+
|
|
+OVS_TRAFFIC_VSWITCHD_START(
|
|
+ [_ADD_BR([br-underlay]) -- \
|
|
+ set bridge br0 other-config:hwaddr=f2:ff:00:00:00:01 -- \
|
|
+ set bridge br-underlay other-config:hwaddr=f2:ff:00:00:00:02])
|
|
+
|
|
+AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
|
|
+
|
|
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
|
|
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
|
|
+
|
|
+ADD_NAMESPACES(at_ns0)
|
|
+
|
|
+dnl Set up underlay link from host into the namespace using veth pair.
|
|
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24", f2:ff:00:00:00:03)
|
|
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
|
|
+AT_CHECK([ip link set dev br-underlay up])
|
|
+
|
|
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
|
|
+dnl linux device inside the namespace.
|
|
+ADD_OVS_TUNNEL([geneve], [br0], [at_gnv0], [172.31.1.1], [10.1.1.100/24])
|
|
+ADD_NATIVE_TUNNEL([geneve], [ns_gnv0], [at_ns0], [172.31.1.100], [10.1.1.1/24],
|
|
+ [vni 0], [address f2:ff:00:00:00:04])
|
|
+
|
|
+NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 03 08 00 45 00 00 52 00 01 00 00 40 11 1f f7 ac 1f 01 01 ac 1f 01 64 de c1 17 c1 00 3e 59 e9 01 00 65 58 00 00 00 00 00 03 00 02 f2 ff 00 00 00 01 f2 ff 00 00 00 04 08 00 45 00 00 1c 00 01 00 00 40 01 64 7a 0a 01 01 01 0a 01 01 64 08 00 f7 ff 00 00 00 00 > /dev/null])
|
|
+
|
|
+OVS_WAIT_UNTIL([grep -q 'Invalid Geneve tunnel metadata' ovs-vswitchd.log])
|
|
+
|
|
+OVS_TRAFFIC_VSWITCHD_STOP(["/Invalid Geneve tunnel metadata on bridge br0 while processing icmp,in_port=1,vlan_tci=0x0000,dl_src=f2:ff:00:00:00:04,dl_dst=f2:ff:00:00:00:01,nw_src=10.1.1.1,nw_dst=10.1.1.100,nw_tos=0,nw_ecn=0,nw_ttl=64,nw_frag=no,icmp_type=8,icmp_code=0/d
|
|
+/Unable to parse geneve options/d"])
|
|
+AT_CLEANUP
|
|
--
|
|
2.33.0
|
|
|