2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

tc: Add vxlan encap action with gbp option offload.

Add TC offload support for vxlan encap with gbp option.

Reviewed-by: Gavi Teitz <gavi@nvidia.com>
Reviewed-by: Roi Dayan <roid@nvidia.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Gavin Li <gavinl@nvidia.com>
Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
This commit is contained in:
Gavin Li 2023-06-27 13:48:12 +03:00 committed by Eelco Chaudron
parent 256c1e5819
commit a2a3f1983f
8 changed files with 143 additions and 17 deletions

2
NEWS
View File

@ -44,6 +44,8 @@ Post-v3.1.0
* IP and L4 checksum offload support is now enabled by default for * IP and L4 checksum offload support is now enabled by default for
interfaces that support it. See the 'status' column in the 'interface' interfaces that support it. See the 'status' column in the 'interface'
table to check the status. table to check the status.
- Linux TC offload:
* Add support for offloading VXLAN tunnels with the GBP extensions.
v3.1.0 - 16 Feb 2023 v3.1.0 - 16 Feb 2023

View File

@ -191,6 +191,13 @@ AC_DEFUN([OVS_CHECK_LINUX_TC], [
[AC_DEFINE([HAVE_TCA_TUNNEL_KEY_ENC_TTL], [1], [AC_DEFINE([HAVE_TCA_TUNNEL_KEY_ENC_TTL], [1],
[Define to 1 if TCA_TUNNEL_KEY_ENC_TTL is available.])]) [Define to 1 if TCA_TUNNEL_KEY_ENC_TTL is available.])])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([#include <linux/tc_act/tc_tunnel_key.h>], [
int x = TCA_TUNNEL_KEY_ENC_OPTS_VXLAN;
])],
[AC_DEFINE([HAVE_TCA_TUNNEL_KEY_ENC_OPTS_VXLAN], [1],
[Define to 1 if TCA_TUNNEL_KEY_ENC_OPTS_VXLAN is available.])])
AC_COMPILE_IFELSE([ AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([#include <linux/tc_act/tc_pedit.h>], [ AC_LANG_PROGRAM([#include <linux/tc_act/tc_pedit.h>], [
int x = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP; int x = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP;

View File

@ -1,7 +1,7 @@
#ifndef __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H #ifndef __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H
#define __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H 1 #define __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H 1
#if defined(__KERNEL__) || defined(HAVE_TCA_TUNNEL_KEY_ENC_TTL) #if defined(__KERNEL__) || defined(HAVE_TCA_TUNNEL_KEY_ENC_OPTS_VXLAN)
#include_next <linux/tc_act/tc_tunnel_key.h> #include_next <linux/tc_act/tc_tunnel_key.h>
#else #else
@ -53,6 +53,10 @@ enum {
* TCA_TUNNEL_KEY_ENC_OPTS_GENEVE * TCA_TUNNEL_KEY_ENC_OPTS_GENEVE
* attributes * attributes
*/ */
TCA_TUNNEL_KEY_ENC_OPTS_VXLAN, /* Nested
* TCA_TUNNEL_KEY_ENC_OPTS_VXLAN
* attributes
*/
__TCA_TUNNEL_KEY_ENC_OPTS_MAX, __TCA_TUNNEL_KEY_ENC_OPTS_MAX,
}; };
@ -70,6 +74,15 @@ enum {
#define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX \ #define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX \
(__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1) (__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1)
#endif /* __KERNEL__ || HAVE_TCA_TUNNEL_KEY_ENC_TTL */ enum {
TCA_TUNNEL_KEY_ENC_OPT_VXLAN_UNSPEC,
TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, /* u32 */
__TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX,
};
#define TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX \
(__TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX - 1)
#endif /* __KERNEL__ || HAVE_TCA_TUNNEL_KEY_ENC_OPTS_VXLAN */
#endif /* __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H */ #endif /* __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H */

View File

@ -668,6 +668,23 @@ static void parse_tc_flower_geneve_opts(struct tc_action *action,
nl_msg_end_nested(buf, geneve_off); nl_msg_end_nested(buf, geneve_off);
} }
static void
parse_tc_flower_vxlan_tun_opts(struct tc_action *action, struct ofpbuf *buf)
{
size_t gbp_off;
uint32_t gbp_raw;
if (!action->encap.gbp.id_present) {
return;
}
gbp_off = nl_msg_start_nested(buf, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
gbp_raw = odp_encode_gbp_raw(action->encap.gbp.flags,
action->encap.gbp.id);
nl_msg_put_u32(buf, OVS_VXLAN_EXT_GBP, gbp_raw);
nl_msg_end_nested(buf, gbp_off);
}
static void static void
flower_tun_opt_to_match(struct match *match, struct tc_flower *flower) flower_tun_opt_to_match(struct match *match, struct tc_flower *flower)
{ {
@ -863,7 +880,7 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
if (!action->encap.no_csum) { if (!action->encap.no_csum) {
nl_msg_put_flag(buf, OVS_TUNNEL_KEY_ATTR_CSUM); nl_msg_put_flag(buf, OVS_TUNNEL_KEY_ATTR_CSUM);
} }
parse_tc_flower_vxlan_tun_opts(action, buf);
parse_tc_flower_geneve_opts(action, buf); parse_tc_flower_geneve_opts(action, buf);
nl_msg_end_nested(buf, tunnel_offset); nl_msg_end_nested(buf, tunnel_offset);
nl_msg_end_nested(buf, set_offset); nl_msg_end_nested(buf, set_offset);
@ -1552,6 +1569,7 @@ parse_put_flow_set_action(struct tc_flower *flower, struct tc_action *action,
action->type = TC_ACT_ENCAP; action->type = TC_ACT_ENCAP;
action->encap.id_present = false; action->encap.id_present = false;
action->encap.gbp.id_present = false;
action->encap.no_csum = 1; action->encap.no_csum = 1;
flower->action_count++; flower->action_count++;
NL_ATTR_FOR_EACH_UNSAFE(tun_attr, tun_left, tunnel, tunnel_len) { NL_ATTR_FOR_EACH_UNSAFE(tun_attr, tun_left, tunnel, tunnel_len) {
@ -1613,6 +1631,16 @@ parse_put_flow_set_action(struct tc_flower *flower, struct tc_action *action,
action->encap.data.present.len = nl_attr_get_size(tun_attr); action->encap.data.present.len = nl_attr_get_size(tun_attr);
} }
break; break;
case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: {
if (odp_vxlan_tun_opts_from_attr(tun_attr,
&action->encap.gbp.id,
&action->encap.gbp.flags,
&action->encap.gbp.id_present)) {
VLOG_ERR_RL(&rl, "error parsing VXLAN options");
return EINVAL;
}
}
break;
default: default:
VLOG_DBG_RL(&rl, "unsupported tunnel key attribute %d", VLOG_DBG_RL(&rl, "unsupported tunnel key attribute %d",
nl_attr_type(tun_attr)); nl_attr_type(tun_attr));

View File

@ -3149,22 +3149,12 @@ odp_tun_key_from_attr__(const struct nlattr *attr, bool is_mask,
tun->flags |= FLOW_TNL_F_OAM; tun->flags |= FLOW_TNL_F_OAM;
break; break;
case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: { case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: {
static const struct nl_policy vxlan_opts_policy[] = { if (odp_vxlan_tun_opts_from_attr(a, &tun->gbp_id,
[OVS_VXLAN_EXT_GBP] = { .type = NL_A_U32 }, &tun->gbp_flags,
}; NULL)) {
struct nlattr *ext[ARRAY_SIZE(vxlan_opts_policy)];
if (!nl_parse_nested(a, vxlan_opts_policy, ext, ARRAY_SIZE(ext))) {
odp_parse_error(&rl, errorp, "error parsing VXLAN options"); odp_parse_error(&rl, errorp, "error parsing VXLAN options");
return ODP_FIT_ERROR; return ODP_FIT_ERROR;
} }
if (ext[OVS_VXLAN_EXT_GBP]) {
uint32_t gbp = nl_attr_get_u32(ext[OVS_VXLAN_EXT_GBP]);
odp_decode_gbp_raw(gbp, &tun->gbp_id, &tun->gbp_flags);
}
break; break;
} }
case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS: case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
@ -8844,3 +8834,29 @@ commit_odp_actions(const struct flow *flow, struct flow *base,
return slow1 ? slow1 : slow2; return slow1 ? slow1 : slow2;
} }
int
odp_vxlan_tun_opts_from_attr(const struct nlattr *tun_attr, ovs_be16 *id,
uint8_t *flags, bool *id_present)
{
static const struct nl_policy vxlan_opts_policy[] = {
[OVS_VXLAN_EXT_GBP] = { .type = NL_A_U32 },
};
struct nlattr *ext[ARRAY_SIZE(vxlan_opts_policy)];
if (!nl_parse_nested(tun_attr, vxlan_opts_policy, ext, ARRAY_SIZE(ext))) {
return EINVAL;
}
if (ext[OVS_VXLAN_EXT_GBP]) {
uint32_t gbp_raw = nl_attr_get_u32(ext[OVS_VXLAN_EXT_GBP]);
odp_decode_gbp_raw(gbp_raw, id, flags);
}
if (id_present) {
*id_present = !!ext[OVS_VXLAN_EXT_GBP];
}
return 0;
}

View File

@ -292,6 +292,9 @@ enum slow_path_reason commit_odp_actions(const struct flow *,
bool pending_decap, bool pending_decap,
struct ofpbuf *encap_data); struct ofpbuf *encap_data);
int odp_vxlan_tun_opts_from_attr(const struct nlattr *tun_attr, ovs_be16 *id,
uint8_t *flags, bool *id_present);
/* ofproto-dpif interface. /* ofproto-dpif interface.
* *
* The following types and functions are logically part of ofproto-dpif. * The following types and functions are logically part of ofproto-dpif.

View File

@ -1290,6 +1290,35 @@ nl_parse_act_geneve_opts(const struct nlattr *in_nlattr,
return 0; return 0;
} }
static int
nl_parse_act_vxlan_opts(struct nlattr *in_nlattr, struct tc_action *action)
{
const struct ofpbuf *msg;
struct nlattr *nla;
struct ofpbuf buf;
size_t left;
nl_attr_get_nested(in_nlattr, &buf);
msg = &buf;
NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, 0, 0), msg->size) {
uint16_t type = nl_attr_type(nla);
int32_t gbp_raw;
switch (type) {
case TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP:
gbp_raw = nl_attr_get_u32(nla);
odp_decode_gbp_raw(gbp_raw, &action->encap.gbp.id,
&action->encap.gbp.flags);
action->encap.gbp.id_present = true;
break;
}
}
return 0;
}
static int static int
nl_parse_act_tunnel_opts(struct nlattr *options, struct tc_action *action) nl_parse_act_tunnel_opts(struct nlattr *options, struct tc_action *action)
{ {
@ -1314,7 +1343,12 @@ nl_parse_act_tunnel_opts(struct nlattr *options, struct tc_action *action)
if (err) { if (err) {
return err; return err;
} }
break;
case TCA_TUNNEL_KEY_ENC_OPTS_VXLAN:
err = nl_parse_act_vxlan_opts(nla, action);
if (err) {
return err;
}
break; break;
} }
} }
@ -2640,6 +2674,27 @@ nl_msg_put_act_tunnel_geneve_option(struct ofpbuf *request,
nl_msg_end_nested(request, outer); nl_msg_end_nested(request, outer);
} }
static void
nl_msg_put_act_tunnel_vxlan_opts(struct ofpbuf *request,
struct tc_action_encap *encap)
{
size_t outer, inner;
uint32_t gbp_raw;
if (!encap->gbp.id_present) {
return;
}
gbp_raw = odp_encode_gbp_raw(encap->gbp.flags,
encap->gbp.id);
outer = nl_msg_start_nested_with_flag(request, TCA_TUNNEL_KEY_ENC_OPTS);
inner = nl_msg_start_nested_with_flag(request,
TCA_TUNNEL_KEY_ENC_OPTS_VXLAN);
nl_msg_put_u32(request, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, gbp_raw);
nl_msg_end_nested(request, inner);
nl_msg_end_nested(request, outer);
}
static void static void
nl_msg_put_act_tunnel_key_set(struct ofpbuf *request, nl_msg_put_act_tunnel_key_set(struct ofpbuf *request,
struct tc_action_encap *encap, struct tc_action_encap *encap,
@ -2680,6 +2735,7 @@ nl_msg_put_act_tunnel_key_set(struct ofpbuf *request,
nl_msg_put_be16(request, TCA_TUNNEL_KEY_ENC_DST_PORT, nl_msg_put_be16(request, TCA_TUNNEL_KEY_ENC_DST_PORT,
encap->tp_dst); encap->tp_dst);
} }
nl_msg_put_act_tunnel_vxlan_opts(request, encap);
nl_msg_put_act_tunnel_geneve_option(request, &encap->data); nl_msg_put_act_tunnel_geneve_option(request, &encap->data);
nl_msg_put_u8(request, TCA_TUNNEL_KEY_NO_CSUM, encap->no_csum); nl_msg_put_u8(request, TCA_TUNNEL_KEY_NO_CSUM, encap->no_csum);
} }

View File

@ -227,6 +227,7 @@ struct tc_action_encap {
struct in6_addr ipv6_dst; struct in6_addr ipv6_dst;
} ipv6; } ipv6;
struct tun_metadata data; struct tun_metadata data;
struct tc_tunnel_gbp gbp;
}; };
struct tc_action { struct tc_action {