On 15 Mar 2024, at 17:37, Eric Garver wrote:

> On Fri, Mar 15, 2024 at 04:55:50PM +0100, Eelco Chaudron wrote:
>>
>>
>> On 11 Mar 2024, at 18:51, Eric Garver wrote:
>>
>>> Kernel support has been added for this action. As such, we need to probe
>>> the datapath for support.
>>>
>>> Signed-off-by: Eric Garver <e...@garver.life>
>>
>> Thanks for submitting the changes requested. Some comments below.
>>
>> Cheers,
>>
>> Eelco
>>
>>
>>> ---
>>>  include/linux/openvswitch.h |  2 +-
>>>  lib/dpif.c                  |  6 ++-
>>>  lib/dpif.h                  |  2 +-
>>>  ofproto/ofproto-dpif.c      | 77 ++++++++++++++++++++++++++++++++++---
>>>  ofproto/ofproto-dpif.h      |  4 +-
>>>  5 files changed, 81 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
>>> index a265e05ad253..fce6456f47c8 100644
>>> --- a/include/linux/openvswitch.h
>>> +++ b/include/linux/openvswitch.h
>>> @@ -1086,11 +1086,11 @@ enum ovs_action_attr {
>>>     OVS_ACTION_ATTR_CHECK_PKT_LEN, /* Nested OVS_CHECK_PKT_LEN_ATTR_*. */
>>>     OVS_ACTION_ATTR_ADD_MPLS,     /* struct ovs_action_add_mpls. */
>>>     OVS_ACTION_ATTR_DEC_TTL,      /* Nested OVS_DEC_TTL_ATTR_*. */
>>> +   OVS_ACTION_ATTR_DROP,         /* u32 xlate_error. */
>>>
>>>  #ifndef __KERNEL__
>>>     OVS_ACTION_ATTR_TUNNEL_PUSH,   /* struct ovs_action_push_tnl*/
>>>     OVS_ACTION_ATTR_TUNNEL_POP,    /* u32 port number. */
>>> -   OVS_ACTION_ATTR_DROP,          /* u32 xlate_error. */
>>>     OVS_ACTION_ATTR_LB_OUTPUT,     /* u32 bond-id. */
>>>  #endif
>>>     __OVS_ACTION_ATTR_MAX,        /* Nothing past this will be accepted
>>> diff --git a/lib/dpif.c b/lib/dpif.c
>>> index 0f480bec48d0..23eb18495a66 100644
>>> --- a/lib/dpif.c
>>> +++ b/lib/dpif.c
>>> @@ -28,6 +28,7 @@
>>>  #include "dpctl.h"
>>>  #include "dpif-netdev.h"
>>>  #include "flow.h"
>>> +#include "netdev-offload.h"
>>>  #include "netdev-provider.h"
>>>  #include "netdev.h"
>>>  #include "netlink.h"
>>> @@ -1935,9 +1936,10 @@ dpif_supports_tnl_push_pop(const struct dpif *dpif)
>>>  }
>>>
>>>  bool
>>> -dpif_supports_explicit_drop_action(const struct dpif *dpif)
>>> +dpif_may_support_explicit_drop_action(const struct dpif *dpif)
>>>  {
>>> -    return dpif_is_netdev(dpif);
>>> +    /* TC does not support offloading this action. */
>>> +    return dpif_is_netdev(dpif) || !netdev_is_flow_api_enabled();
>>>  }
>>>
>>>  bool
>>> diff --git a/lib/dpif.h b/lib/dpif.h
>>> index 0f2dc2ef3c55..a764e8a592bd 100644
>>> --- a/lib/dpif.h
>>> +++ b/lib/dpif.h
>>> @@ -940,7 +940,7 @@ int dpif_get_pmds_for_port(const struct dpif * dpif, 
>>> odp_port_t port_no,
>>>
>>>  char *dpif_get_dp_version(const struct dpif *);
>>>  bool dpif_supports_tnl_push_pop(const struct dpif *);
>>> -bool dpif_supports_explicit_drop_action(const struct dpif *);
>>> +bool dpif_may_support_explicit_drop_action(const struct dpif *);
>>>  bool dpif_synced_dp_layers(struct dpif *);
>>>
>>>  /* Log functions. */
>>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
>>> index 2ec1cd1854ab..7bacd2120c78 100644
>>> --- a/ofproto/ofproto-dpif.c
>>> +++ b/ofproto/ofproto-dpif.c
>>> @@ -221,6 +221,7 @@ static void ct_zone_config_init(struct dpif_backer 
>>> *backer);
>>>  static void ct_zone_config_uninit(struct dpif_backer *backer);
>>>  static void ct_zone_timeout_policy_sweep(struct dpif_backer *backer);
>>>  static void ct_zone_limits_commit(struct dpif_backer *backer);
>>> +static bool recheck_support_explicit_drop_action(struct dpif_backer 
>>> *backer);
>>>
>>>  static inline struct ofproto_dpif *
>>>  ofproto_dpif_cast(const struct ofproto *ofproto)
>>> @@ -391,6 +392,10 @@ type_run(const char *type)
>>>          udpif_set_threads(backer->udpif, n_handlers, n_revalidators);
>>>      }
>>>
>>> +    if (recheck_support_explicit_drop_action(backer)) {
>>> +        backer->need_revalidate = REV_RECONFIGURE;
>>> +    }
>>> +
>>>      if (backer->need_revalidate) {
>>>          struct ofproto_dpif *ofproto;
>>>          struct simap_node *node;
>>> @@ -807,6 +812,7 @@ open_dpif_backer(const char *type, struct dpif_backer 
>>> **backerp)
>>>
>>>      shash_add(&all_dpif_backers, type, backer);
>>>
>>> +    atomic_init(&backer->rt_support.explicit_drop_action, false);
>>>      check_support(backer);
>>>      atomic_count_init(&backer->tnl_count, 0);
>>>
>>> @@ -855,7 +861,10 @@ ovs_native_tunneling_is_on(struct ofproto_dpif 
>>> *ofproto)
>>>  bool
>>>  ovs_explicit_drop_action_supported(struct ofproto_dpif *ofproto)
>>>  {
>>> -    return ofproto->backer->rt_support.explicit_drop_action;
>>> +    bool value;
>>
>> nit: I would add a new line here.
>
> ACK.
>
>>> +    atomic_read_relaxed(&ofproto->backer->rt_support.explicit_drop_action,
>>> +                        &value);
>>> +    return value;
>>>  }
>>>
>>>  bool
>>> @@ -1379,6 +1388,41 @@ check_ct_timeout_policy(struct dpif_backer *backer)
>>>      return !error;
>>>  }
>>>
>>> +/* Tests whether backer's datapath supports the OVS_ACTION_ATTR_DROP 
>>> action. */
>>> +static bool
>>> +check_drop_action(struct dpif_backer *backer)
>>> +{
>>> +    struct odputil_keybuf keybuf;
>>> +    uint8_t actbuf[NL_A_U32_SIZE];
>>> +    struct ofpbuf actions;
>>> +    struct ofpbuf key;
>>> +    struct flow flow;
>>> +    bool supported;
>>> +    bool hw_offload;
>>> +
>>> +    struct odp_flow_key_parms odp_parms = {
>>> +        .flow = &flow,
>>> +        .probe = true,
>>> +    };
>>> +
>>> +    memset(&flow, 0, sizeof flow);
>>> +    ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
>>> +    odp_flow_key_from_flow(&odp_parms, &key);
>>> +
>>> +    ofpbuf_use_stack(&actions, &actbuf, sizeof actbuf);
>>> +    nl_msg_put_u32(&actions, OVS_ACTION_ATTR_DROP, XLATE_OK);
>>> +
>>> +    supported = dpif_probe_feature(backer->dpif, "drop", &key, &actions, 
>>> NULL);
>>> +    hw_offload = !dpif_may_support_explicit_drop_action(backer->dpif);
>>
>> The use case of this function seems odd here. This since 
>> dpif_may_support_explicit_drop_action() doesn't imply that we're 
>> specifically checking for HW offload being the issue. If someone updates the 
>> function with another reason for it not being supported we will break the 
>> implementation here. What do you think?
>
> The reason it was changed to user
> dpif_may_support_explicit_drop_action() was because it was suggested to
> avoid calling dpif_is_netdev() from ofproto. I assume it's similar for
> netdev_is_flow_api_enabled().
>
> "hw_offload" is probably a bad variable name. Maybe we completely avoid
> mentioning hw_offload here and in the log. Instead we do:
>
> +    supported = dpif_may_support_explicit_drop_action(backer->dpif)
>                  && dpif_probe_feature(backer->dpif, "drop", &key, &actions, 
> NULL);
>
>
> Is this agreeable?
>
>>> +
>>> +    VLOG_INFO("%s: Datapath %s explicit drop action%s",
>>> +              dpif_name(backer->dpif),
>>> +              (supported) ? "supports" : "does not support",
>>> +              (hw_offload) ? ", but not enabled due to hardware offload" : 
>>> "");
>
> We would simply remove the log mentioning hardware offload.

Yes, we might just remove hw_offload, and do something like:

             (may_support) ? ", but not enabled due to a conflicting 
configuration" : "");

But this might just raise the question, of what the conflicting configuration 
might be ;)

>>> +    VLOG_INFO("%s: Datapath %s explicit drop action%s",
>>> +              dpif_name(backer->dpif),
>>> +              (supported) ? "supports" : "does not support",
>>> +              (hw_offload) ? ", but not enabled due to hardware offload" : 
>>> "");


>>> +
>>> +    return supported && !hw_offload;
>>> +}
>>> +
>>>  /* Tests whether 'backer''s datapath supports the all-zero SNAT case. */
>>>  static bool
>>>  dpif_supports_ct_zero_snat(struct dpif_backer *backer)
>>> @@ -1649,8 +1693,8 @@ check_support(struct dpif_backer *backer)
>>>      backer->rt_support.max_hash_alg = check_max_dp_hash_alg(backer);
>>>      backer->rt_support.check_pkt_len = check_check_pkt_len(backer);
>>>      backer->rt_support.ct_timeout = check_ct_timeout_policy(backer);
>>> -    backer->rt_support.explicit_drop_action =
>>> -        dpif_supports_explicit_drop_action(backer->dpif);
>>> +    atomic_store_relaxed(&backer->rt_support.explicit_drop_action,
>>> +                         check_drop_action(backer));
>>>      backer->rt_support.lb_output_action =
>>>          dpif_supports_lb_output_action(backer->dpif);
>>>      backer->rt_support.ct_zero_snat = dpif_supports_ct_zero_snat(backer);
>>> @@ -1667,6 +1711,27 @@ check_support(struct dpif_backer *backer)
>>>      backer->rt_support.odp.nd_ext = check_nd_extensions(backer);
>>>  }
>>>
>>> +/* For TC, if vswitchd started with other_config:hw-offload set to 
>>> "false", and
>>> + * the configuration is now "true", then we need to re-probe datapath 
>>> support
>>> + * for the "drop" action. */
>>> +static bool
>>> +recheck_support_explicit_drop_action(struct dpif_backer *backer)
>>> +{
>>> +    bool explicit_drop_action;
>>> +
>>> +    atomic_read_relaxed(&backer->rt_support.explicit_drop_action,
>>> +                        &explicit_drop_action);
>>> +
>>> +    if (explicit_drop_action
>>> +        && !dpif_may_support_explicit_drop_action(backer->dpif)
>>> +        && !check_drop_action(backer)) {
>>> +        atomic_store_relaxed(&backer->rt_support.explicit_drop_action, 
>>> false);
>>> +        return true;
>>
>> This should probably also work in the reverse direction. If it´s enabled on 
>> startup, but now disabled?
>
> I'll make the change.
>
> IIRC, unsetting "hw-offload" requires a restart. Setting it does not.

In theory, unsetting it will keep active flows in TC, only new/updated flows 
will be put in the kernel. So triggering the reconfigure in both will at least 
solve some of the potential problems ;)

> Even though it's documented that a restart is required.
>
>        other_config : hw-offload: optional string, either true or false
>               Set this value to true to enable netdev flow offload.
>
>               The  default  value  is  false.  Changing  this  value  requires
>               restarting the daemon
>        [..]
>
> https://www.openvswitch.org/support/dist-docs/ovs-vswitchd.conf.db.5.html
>
>>> +    }
>>> +
>>> +    return false;
>>> +}
>>> +
>>>  static int
>>>  construct(struct ofproto *ofproto_)
>>>  {
>>> @@ -5708,6 +5773,7 @@ ct_zone_limit_protection_update(const char 
>>> *datapath_type, bool protected)
>>>  static void
>>>  get_datapath_cap(const char *datapath_type, struct smap *cap)
>>>  {
>>> +    bool explicit_drop_action;
>>>      struct dpif_backer_support *s;
>>>      struct dpif_backer *backer = shash_find_data(&all_dpif_backers,
>>>                                                   datapath_type);
>>> @@ -5743,8 +5809,9 @@ get_datapath_cap(const char *datapath_type, struct 
>>> smap *cap)
>>>      smap_add_format(cap, "max_hash_alg", "%"PRIuSIZE, s->max_hash_alg);
>>>      smap_add(cap, "check_pkt_len", s->check_pkt_len ? "true" : "false");
>>>      smap_add(cap, "ct_timeout", s->ct_timeout ? "true" : "false");
>>> +    atomic_read_relaxed(&s->explicit_drop_action, &explicit_drop_action);
>>>      smap_add(cap, "explicit_drop_action",
>>> -             s->explicit_drop_action ? "true" :"false");
>>> +             explicit_drop_action ? "true" :"false");
>>>      smap_add(cap, "lb_output_action", s->lb_output_action ? "true" : 
>>> "false");
>>>      smap_add(cap, "ct_zero_snat", s->ct_zero_snat ? "true" : "false");
>>>      smap_add(cap, "add_mpls", s->add_mpls ? "true" : "false");
>>> @@ -6273,7 +6340,7 @@ show_dp_feature_bool(struct ds *ds, const char 
>>> *feature, const bool *b)
>>>      ds_put_format(ds, "%s: %s\n", feature, *b ? "Yes" : "No");
>>>  }
>>>
>>> -static void OVS_UNUSED
>>> +static void
>>>  show_dp_feature_atomic_bool(struct ds *ds, const char *feature,
>>>                              const atomic_bool *b)
>>>  {
>>> diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
>>> index 92d33aa64709..d33f73df8aed 100644
>>> --- a/ofproto/ofproto-dpif.h
>>> +++ b/ofproto/ofproto-dpif.h
>>> @@ -51,6 +51,7 @@
>>>  #include "hmapx.h"
>>>  #include "odp-util.h"
>>>  #include "id-pool.h"
>>> +#include "ovs-atomic.h"
>>>  #include "ovs-thread.h"
>>>  #include "ofproto-provider.h"
>>>  #include "util.h"
>>> @@ -202,7 +203,8 @@ struct group_dpif *group_dpif_lookup(struct 
>>> ofproto_dpif *,
>>>      DPIF_SUPPORT_FIELD(bool, ct_timeout, "Conntrack timeout policy")       
>>>  \
>>>                                                                             
>>>  \
>>>      /* True if the datapath supports explicit drop action. */              
>>>  \
>>> -    DPIF_SUPPORT_FIELD(bool, explicit_drop_action, "Explicit Drop action") 
>>>  \
>>> +    DPIF_SUPPORT_FIELD(atomic_bool, explicit_drop_action,                  
>>>  \
>>> +                       "Explicit Drop action")                             
>>>  \
>>>                                                                             
>>>  \
>>>      /* True if the datapath supports balance_tcp optimization */           
>>>  \
>>>      DPIF_SUPPORT_FIELD(bool, lb_output_action, "Optimized Balance TCP 
>>> mode")\
>>> -- 
>>> 2.43.0
>>>
>>> _______________________________________________
>>> dev mailing list
>>> d...@openvswitch.org
>>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>> _______________________________________________
>> dev mailing list
>> d...@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to