From 316fcc631a47c51c35f46a884e2c628febd19d99 Mon Sep 17 00:00:00 2001 From: Eelco Chaudron Date: Mon, 14 Oct 2024 14:09:04 +0200 Subject: [PATCH] netdev-offload-tc: Add don't fragment support to encap action. This patch adds "Don't Fragment" (DF) flag support to the encap action, if supported by the kernel. If the kernel does not support this, it falls back to the previous behavior of ignoring the DF request. Acked-by: Roi Dayan Acked-by: Simon Horman Signed-off-by: Eelco Chaudron --- NEWS | 2 ++ acinclude.m4 | 6 +++--- include/linux/tc_act/tc_tunnel_key.h | 3 ++- lib/netdev-offload-tc.c | 16 +++++++++++----- lib/tc.c | 6 ++++++ lib/tc.h | 1 + 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 7bae8bbc1..200a8bb40 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ Post-v3.4.0 the kernel datapath. - Linux TC offload: * Add support for matching tunnel flags if the kernel supports it. + * Add support for the "Don't Fragment" (DF) flag in the encap action, + if the kernel supports it. - Python: * Added tool called "ovs-flowviz" capable of parsing OpenFlow and datapath flow dumps and displaying them in several different diff --git a/acinclude.m4 b/acinclude.m4 index f4cb4a146..8658bcfcb 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -193,10 +193,10 @@ AC_DEFUN([OVS_CHECK_LINUX_TC], [ AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([#include ], [ - int x = TCA_TUNNEL_KEY_ENC_OPTS_VXLAN; + int x = TCA_TUNNEL_KEY_NO_FRAG; ])], - [AC_DEFINE([HAVE_TCA_TUNNEL_KEY_ENC_OPTS_VXLAN], [1], - [Define to 1 if TCA_TUNNEL_KEY_ENC_OPTS_VXLAN is available.])]) + [AC_DEFINE([HAVE_TCA_TUNNEL_KEY_NO_FRAG], [1], + [Define to 1 if TCA_TUNNEL_KEY_NO_FRAG is available.])]) AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([#include ], [ diff --git a/include/linux/tc_act/tc_tunnel_key.h b/include/linux/tc_act/tc_tunnel_key.h index 17291b90b..edb64262e 100644 --- a/include/linux/tc_act/tc_tunnel_key.h +++ b/include/linux/tc_act/tc_tunnel_key.h @@ -1,7 +1,7 @@ #ifndef __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H #define __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H 1 -#if defined(__KERNEL__) || defined(HAVE_TCA_TUNNEL_KEY_ENC_OPTS_VXLAN) +#if defined(__KERNEL__) || defined(HAVE_TCA_TUNNEL_KEY_NO_FRAG) #include_next #else @@ -42,6 +42,7 @@ enum { */ TCA_TUNNEL_KEY_ENC_TOS, /* u8 */ TCA_TUNNEL_KEY_ENC_TTL, /* u8 */ + TCA_TUNNEL_KEY_NO_FRAG, /* flag */ __TCA_TUNNEL_KEY_MAX, }; diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index c6aa51c68..74e60d0f7 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -919,6 +919,9 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf, if (!action->encap.no_csum) { nl_msg_put_flag(buf, OVS_TUNNEL_KEY_ATTR_CSUM); } + if (action->encap.dont_fragment) { + nl_msg_put_flag(buf, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT); + } ret = parse_tc_flower_vxlan_tun_opts(action, buf); if (ret) { return ret; @@ -1641,11 +1644,14 @@ parse_put_flow_set_action(struct tc_flower *flower, struct tc_action *action, } break; case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT: { - /* XXX: This is wrong! We're ignoring the DF flag configuration - * requested by the user. However, TC for now has no way to pass - * that flag and it is set by default, meaning tunnel offloading - * will not work if 'options:df_default=false' is not set. - * Keeping incorrect behavior for now. */ + if (enc_flags_support) { + action->encap.dont_fragment = true; + } else { + /* For kernels not supporting the DF flag, we ignoring the + * configuration requested by the user. This to keep the old, + * incorrect behaviour, and allow tunnels to be offloaded by + * TC with these kernels. */ + } } break; case OVS_TUNNEL_KEY_ATTR_CSUM: { diff --git a/lib/tc.c b/lib/tc.c index 6c853b8e6..175e770d4 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -1229,6 +1229,7 @@ static const struct nl_policy tunnel_key_policy[] = { [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NL_A_U8, .optional = true, }, [TCA_TUNNEL_KEY_ENC_OPTS] = { .type = NL_A_NESTED, .optional = true, }, [TCA_TUNNEL_KEY_NO_CSUM] = { .type = NL_A_U8, .optional = true, }, + [TCA_TUNNEL_KEY_NO_FRAG] = { .type = NL_A_FLAG, .optional = true, }, }; static int @@ -1394,6 +1395,7 @@ nl_parse_act_tunnel_key(struct nlattr *options, struct tc_flower *flower) struct nlattr *ttl = tun_attrs[TCA_TUNNEL_KEY_ENC_TTL]; struct nlattr *tun_opt = tun_attrs[TCA_TUNNEL_KEY_ENC_OPTS]; struct nlattr *no_csum = tun_attrs[TCA_TUNNEL_KEY_NO_CSUM]; + struct nlattr *no_frag = tun_attrs[TCA_TUNNEL_KEY_NO_FRAG]; action = &flower->actions[flower->action_count++]; action->type = TC_ACT_ENCAP; @@ -1411,6 +1413,7 @@ nl_parse_act_tunnel_key(struct nlattr *options, struct tc_flower *flower) action->encap.tos = tos ? nl_attr_get_u8(tos) : 0; action->encap.ttl = ttl ? nl_attr_get_u8(ttl) : 0; action->encap.no_csum = no_csum ? nl_attr_get_u8(no_csum) : 0; + action->encap.dont_fragment = no_frag ? true : false; err = nl_parse_act_tunnel_opts(tun_opt, action); if (err) { @@ -2747,6 +2750,9 @@ nl_msg_put_act_tunnel_key_set(struct ofpbuf *request, nl_msg_put_be16(request, TCA_TUNNEL_KEY_ENC_DST_PORT, encap->tp_dst); } + if (encap->dont_fragment) { + nl_msg_put_flag(request, TCA_TUNNEL_KEY_NO_FRAG); + } nl_msg_put_act_tunnel_vxlan_opts(request, encap); nl_msg_put_act_tunnel_geneve_option(request, &encap->data); nl_msg_put_u8(request, TCA_TUNNEL_KEY_NO_CSUM, encap->no_csum); diff --git a/lib/tc.h b/lib/tc.h index ccd1da90c..883e21f4c 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -228,6 +228,7 @@ struct tc_action_encap { uint8_t tos; uint8_t ttl; uint8_t no_csum; + bool dont_fragment; struct { ovs_be32 ipv4_src; ovs_be32 ipv4_dst;