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;