On 14/10/2024 15:09, Eelco Chaudron wrote:
> This patch checks to see if the TCA_FLOWER_KEY_ENC_FLAGS key is supported.
>
> Signed-off-by: Eelco Chaudron <[email protected]>
> ---
> acinclude.m4 | 6 +++---
> include/linux/pkt_cls.h | 28 +++++++++++++++++++++++-
> lib/netdev-offload-tc.c | 47 ++++++++++++++++++++++++++++++++++++++++-
> lib/tc.c | 29 ++++++++++++++++++++++---
> lib/tc.h | 15 ++++++++++---
> 5 files changed, 114 insertions(+), 11 deletions(-)
>
> diff --git a/acinclude.m4 b/acinclude.m4
> index 1ace70c92..f4cb4a146 100644
> --- a/acinclude.m4
> +++ b/acinclude.m4
> @@ -163,10 +163,10 @@ dnl Configure Linux tc compat.
> AC_DEFUN([OVS_CHECK_LINUX_TC], [
> AC_COMPILE_IFELSE([
> AC_LANG_PROGRAM([#include <linux/pkt_cls.h>], [
> - int x = TCA_ACT_FLAGS_SKIP_HW;
> + int x = TCA_FLOWER_KEY_ENC_FLAGS_MASK;
> ])],
> - [AC_DEFINE([HAVE_TCA_ACT_FLAGS_SKIP_HW], [1],
> - [Define to 1 if TCA_ACT_FLAGS_SKIP_HW is available.])])
> + [AC_DEFINE([HAVE_TCA_FLOWER_KEY_ENC_FLAGS_MASK], [1],
> + [Define to 1 if TCA_FLOWER_KEY_ENC_FLAGS_MASK is
> available.])])
>
> AC_CHECK_MEMBERS([struct tcf_t.firstuse], [], [], [#include
> <linux/pkt_cls.h>])
>
> diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
> index fb4a7ecea..5890dc157 100644
> --- a/include/linux/pkt_cls.h
> +++ b/include/linux/pkt_cls.h
> @@ -1,7 +1,7 @@
> #ifndef __LINUX_PKT_CLS_WRAPPER_H
> #define __LINUX_PKT_CLS_WRAPPER_H 1
>
> -#if defined(__KERNEL__) || defined(HAVE_TCA_ACT_FLAGS_SKIP_HW)
> +#if defined(__KERNEL__) || defined(HAVE_TCA_FLOWER_KEY_ENC_FLAGS_MASK)
> #include_next <linux/pkt_cls.h>
> #else
>
> @@ -252,6 +252,28 @@ enum {
> TCA_FLOWER_KEY_CT_LABELS, /* u128 */
> TCA_FLOWER_KEY_CT_LABELS_MASK, /* u128 */
>
> + TCA_FLOWER_KEY_MPLS_OPTS,
> +
> + TCA_FLOWER_KEY_HASH, /* u32 */
> + TCA_FLOWER_KEY_HASH_MASK, /* u32 */
> +
> + TCA_FLOWER_KEY_NUM_OF_VLANS, /* u8 */
> +
> + TCA_FLOWER_KEY_PPPOE_SID, /* be16 */
> + TCA_FLOWER_KEY_PPP_PROTO, /* be16 */
> +
> + TCA_FLOWER_KEY_L2TPV3_SID, /* be32 */
> +
> + TCA_FLOWER_L2_MISS, /* u8 */
> +
> + TCA_FLOWER_KEY_CFM, /* nested */
> +
> + TCA_FLOWER_KEY_SPI, /* be32 */
> + TCA_FLOWER_KEY_SPI_MASK, /* be32 */
> +
> + TCA_FLOWER_KEY_ENC_FLAGS, /* be32 */
> + TCA_FLOWER_KEY_ENC_FLAGS_MASK, /* be32 */
> +
> __TCA_FLOWER_MAX,
> };
>
> @@ -306,6 +328,10 @@ enum {
> enum {
> TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
> TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
> + TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM = (1 << 2),
> + TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT = (1 << 3),
> + TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM = (1 << 4),
> + TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT = (1 << 5),
> };
>
> /* Match-all classifier */
> diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
> index 3be1c08d2..a2aa4062a 100644
> --- a/lib/netdev-offload-tc.c
> +++ b/lib/netdev-offload-tc.c
> @@ -53,6 +53,7 @@ static bool multi_mask_per_prio = false;
> static bool block_support = false;
> static uint16_t ct_state_support;
> static bool vxlan_gbp_support = false;
> +static bool enc_flags_support = false;
>
> struct netlink_field {
> int offset;
> @@ -407,7 +408,7 @@ get_next_available_prio(ovs_be16 protocol)
>
> /* last_prio can overflow if there will be many different kinds of
> * flows which shouldn't happen organically. */
> - if (last_prio == UINT16_MAX) {
> + if (last_prio == TC_MAX_PRIORITY) {
> return TC_RESERVED_PRIORITY_NONE;
> }
>
> @@ -2863,6 +2864,49 @@ out:
> tc_add_del_qdisc(ifindex, false, block_id, TC_INGRESS);
> }
>
> +static void
> +probe_enc_flags_support(int ifindex)
> +{
> + struct tc_flower flower;
> + struct tcf_id id;
> + int block_id = 0;
> + int prio = TC_RESERVED_PRIORITY_FEATURE_PROBE;
> + int error;
> +
> + error = tc_add_del_qdisc(ifindex, true, block_id, TC_INGRESS);
> + if (error) {
> + return;
> + }
> +
> + memset(&flower, 0, sizeof flower);
> + flower.tc_policy = TC_POLICY_SKIP_HW;
> + flower.key.eth_type = htons(ETH_P_IP);
> + flower.mask.eth_type = OVS_BE16_MAX;
> + flower.tunnel = true;
> + flower.mask.tunnel.id = OVS_BE64_MAX;
> + flower.mask.tunnel.ipv4.ipv4_src = OVS_BE32_MAX;
> + flower.mask.tunnel.ipv4.ipv4_dst = OVS_BE32_MAX;
> + flower.mask.tunnel.tp_dst = OVS_BE16_MAX;
> + flower.mask.tunnel.tc_enc_flags = TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT;
> + flower.key.tunnel.ipv4.ipv4_src = htonl(0x01010101);
> + flower.key.tunnel.ipv4.ipv4_dst = htonl(0x01010102);
> + flower.key.tunnel.tp_dst = htons(46354);
> + flower.key.tunnel.tc_enc_flags = TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT;
> +
> + id = tc_make_tcf_id(ifindex, block_id, prio, TC_INGRESS);
> + error = tc_replace_flower(&id, &flower);
> + if (error) {
> + goto out;
> + }
> +
> + tc_del_flower_filter(&id);
> +
> + enc_flags_support = true;
> + VLOG_INFO("probe tc: enc flags are supported.");
> +out:
> + tc_add_del_qdisc(ifindex, false, block_id, TC_INGRESS);
> +}
> +
> static int
> tc_get_policer_action_ids(struct hmap *map)
> {
> @@ -2991,6 +3035,7 @@ netdev_tc_init_flow_api(struct netdev *netdev)
> probe_multi_mask_per_prio(ifindex);
> probe_ct_state_support(ifindex);
> probe_vxlan_gbp_support(ifindex);
> + probe_enc_flags_support(ifindex);
>
> ovs_mutex_lock(&meter_police_ids_mutex);
> meter_police_ids = id_pool_create(METER_POLICE_IDS_BASE,
> diff --git a/lib/tc.c b/lib/tc.c
> index e55ba3b1b..6c853b8e6 100644
> --- a/lib/tc.c
> +++ b/lib/tc.c
> @@ -454,6 +454,9 @@ static const struct nl_policy tca_flower_policy[] = {
> [TCA_FLOWER_KEY_ENC_OPTS] = { .type = NL_A_NESTED, .optional = true, },
> [TCA_FLOWER_KEY_ENC_OPTS_MASK] = { .type = NL_A_NESTED,
> .optional = true, },
> + [TCA_FLOWER_KEY_ENC_FLAGS] = { .type = NL_A_BE32, .optional = true, },
> + [TCA_FLOWER_KEY_ENC_FLAGS_MASK] = { .type = NL_A_BE32,
> + .optional = true, },
> [TCA_FLOWER_KEY_CT_STATE] = { .type = NL_A_U16, .optional = true, },
> [TCA_FLOWER_KEY_CT_STATE_MASK] = { .type = NL_A_U16, .optional = true, },
> [TCA_FLOWER_KEY_CT_ZONE] = { .type = NL_A_U16, .optional = true, },
> @@ -865,6 +868,13 @@ nl_parse_flower_tunnel(struct nlattr **attrs, struct
> tc_flower *flower)
> flower->tunnel = true;
> }
>
> + if (attrs[TCA_FLOWER_KEY_ENC_FLAGS_MASK]) {
> + flower->key.tunnel.tc_enc_flags = ntohl(
> + nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ENC_FLAGS]));
> + flower->mask.tunnel.tc_enc_flags = ntohl(
> + nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ENC_FLAGS_MASK]));
> + }
> +
> if (attrs[TCA_FLOWER_KEY_ENC_OPTS] &&
> attrs[TCA_FLOWER_KEY_ENC_OPTS_MASK]) {
> err = nl_parse_flower_tunnel_opts(attrs[TCA_FLOWER_KEY_ENC_OPTS],
> @@ -3611,6 +3621,7 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request, struct
> tc_flower *flower)
> struct in6_addr *ipv6_src = &flower->key.tunnel.ipv6.ipv6_src;
> struct in6_addr *ipv6_dst = &flower->key.tunnel.ipv6.ipv6_dst;
> ovs_be32 id = be64_to_be32(flower->key.tunnel.id);
> + ovs_be32 enc_flags = htonl(flower->key.tunnel.tc_enc_flags);
> ovs_be16 tp_src = flower->key.tunnel.tp_src;
> ovs_be16 tp_dst = flower->key.tunnel.tp_dst;
> uint8_t tos = flower->key.tunnel.tos;
> @@ -3618,6 +3629,7 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request, struct
> tc_flower *flower)
> uint8_t tos_mask = flower->mask.tunnel.tos;
> uint8_t ttl_mask = flower->mask.tunnel.ttl;
> ovs_be64 id_mask = flower->mask.tunnel.id;
> + ovs_be32 enc_flags_mask = htonl(flower->mask.tunnel.tc_enc_flags);
> ovs_be16 tp_src_mask = flower->mask.tunnel.tp_src;
> ovs_be16 tp_dst_mask = flower->mask.tunnel.tp_dst;
>
> @@ -3655,6 +3667,11 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request,
> struct tc_flower *flower)
> nl_msg_put_be16(request, TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,
> tp_dst_mask);
> }
> + if (enc_flags_mask) {
> + nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_FLAGS, enc_flags);
> + nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_FLAGS_MASK,
> + enc_flags_mask);
> + }
> if (id_mask) {
> nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_KEY_ID, id);
> }
> @@ -3961,6 +3978,7 @@ tc_replace_flower(struct tcf_id *id, struct tc_flower
> *flower)
> struct ofpbuf b = ofpbuf_const_initializer(reply->data, reply->size);
> struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
> struct tcmsg *tc = ofpbuf_try_pull(&b, sizeof *tc);
> + bool is_probe = id->prio == TC_RESERVED_PRIORITY_FEATURE_PROBE;
>
> if (!nlmsg || !tc) {
> COVERAGE_INC(tc_netlink_malformed_reply);
> @@ -3980,9 +3998,14 @@ tc_replace_flower(struct tcf_id *id, struct tc_flower
> *flower)
> false);
>
> if (ret || !cmp_tc_flower_match_action(flower, &flower_out)) {
> - VLOG_WARN_RL(&error_rl, "Kernel flower acknowledgment does "
> - "not match request! Set dpif_netlink to dbg to
> "
> - "see which rule caused this error.");
> + if (is_probe) {
> + error = EINVAL;
> + } else {
> + VLOG_WARN_RL(&error_rl, "Kernel flower acknowledgment "
> + "does not match request! Set "
> + "dpif_netlink to dbg to see "
> + "which rule caused this error.");
> + }
> }
> }
> ofpbuf_delete(reply);
> diff --git a/lib/tc.h b/lib/tc.h
> index 8442c8d8b..c0a1d5d0e 100644
> --- a/lib/tc.h
> +++ b/lib/tc.h
> @@ -46,15 +46,23 @@
>
> #define TC_POLICY_DEFAULT "none"
>
> -enum tc_flower_reserved_prio {
> +enum tc_flower_reserved_prio
> +{
> TC_RESERVED_PRIORITY_NONE,
> TC_RESERVED_PRIORITY_POLICE,
> TC_RESERVED_PRIORITY_IPV4,
> TC_RESERVED_PRIORITY_IPV6,
> TC_RESERVED_PRIORITY_VLAN,
> - __TC_RESERVED_PRIORITY_MAX
> + __TC_RESERVED_PRIORITY_MAX,
> +
> + TC_MAX_PRIORITY = UINT16_MAX - 1,
> + /* This priority is reserved solely for probing purposes.
> + * Since it's not used in actual traffic flows, we assign it a high value
> + * to avoid impacting vendor specific hardware offload implementations.
> */
> + TC_RESERVED_PRIORITY_FEATURE_PROBE
> };
> -#define TC_RESERVED_PRIORITY_MAX (__TC_RESERVED_PRIORITY_MAX -1)
> +#define TC_RESERVED_PRIORITY_MAX (__TC_RESERVED_PRIORITY_MAX - 1)
> +
>
> enum tc_qdisc_hook {
> TC_INGRESS,
> @@ -125,6 +133,7 @@ struct tc_flower_tunnel {
> uint8_t ttl;
> ovs_be16 tp_src;
> ovs_be16 tp_dst;
> + uint32_t tc_enc_flags;
> struct tc_tunnel_gbp gbp;
> ovs_be64 id;
> struct tun_metadata metadata;
Acked-by: Roi Dayan <[email protected]>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev