Aaron Conole via dev <[email protected]> writes:

> This allows configuring hardware offload on/off.  The ct_sweep
> expiration is always trying to fill the ops batch anyway, so it
> doesn't need an actual check for enabled / disabled.  Wrapping that
> code in a check may also be harmful in the event that offload is
> disabled with offloaded connections.
>
> Signed-off-by: Aaron Conole <[email protected]>
> ---
>  lib/conntrack.c    | 25 +++++++++++++----------
>  lib/ct-offload.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++-
>  lib/ct-offload.h   |  8 ++++++++
>  lib/dpif-offload.c | 13 ++++++++++++
>  lib/dpif-offload.h |  1 +
>  vswitchd/bridge.c  |  4 ++++
>  6 files changed, 90 insertions(+), 12 deletions(-)
>
> diff --git a/lib/conntrack.c b/lib/conntrack.c
> index 9872d7af51..e59630aa2b 100644
> --- a/lib/conntrack.c
> +++ b/lib/conntrack.c
> @@ -534,12 +534,14 @@ conn_clean(struct conntrack *ct, struct conn *conn)
>          atomic_count_dec(&zl->czl.count);
>      }
>  
> -    struct ct_offload_ctx offload_ctx = {
> -        .conn           = conn,
> -        .netdev_in      = NULL,
> -        .input_port_id  = ODPP_NONE,
> -    };
> -    ct_offload_conn_del(&offload_ctx);
> +    if (ct_offload_enabled()) {
> +        struct ct_offload_ctx offload_ctx = {
> +            .conn           = conn,
> +            .netdev_in      = NULL,
> +            .input_port_id  = ODPP_NONE,
> +        };
> +        ct_offload_conn_del(&offload_ctx);
> +    }
>  
>      ovsrcu_postpone(delete_conn, conn);
>      atomic_count_dec(&ct->n_conn);
> @@ -1405,7 +1407,7 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
>          }
>          ovs_mutex_unlock(&ct->ct_lock);
>  
> -        if (conn) {
> +        if (conn && ct_offload_enabled()) {
>              struct ct_offload_ctx offload_ctx = {
>                  .conn           = conn,
>                  .netdev_in      = NULL,
> @@ -1417,6 +1419,7 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
>  
>      if (!create_new_conn && conn && ctx->reply &&
>          (pkt->md.ct_state & CS_ESTABLISHED) &&
> +        ct_offload_enabled() &&
>          ct_offload_conn_is_offloaded(conn) &&
>          !ct_offload_conn_is_established(conn)) {
>          /* Notify offload providers that the connection is established.
> @@ -1581,7 +1584,6 @@ ct_sweep(struct conntrack *ct, struct rculist *list, 
> long long now,
>      size_t cleaned = 0;
>      size_t count = 0;
>  
> -
>      ct_offload_op_batch_init(&batch);
>  
>      RCULIST_FOR_EACH (conn, node, list) {
> @@ -1595,7 +1597,6 @@ ct_sweep(struct conntrack *ct, struct rculist *list, 
> long long now,
>                      .netdev_in      = NULL,
>                      .input_port_id  = ODPP_NONE,
>                  };
> -
>                  ct_offload_op_batch_add(&batch, CT_OFFLOAD_OP_UPD,
>                                          &offload_ctx);
>              }
> @@ -1603,12 +1604,14 @@ ct_sweep(struct conntrack *ct, struct rculist *list, 
> long long now,
>          count++;
>      }
>  
> -    /* Run the batch. */
> +    /* Run the batch: providers that can supply a hw last-used timestamp
> +     * return error==0, allowing us to extend the expiration.  A non-zero
> +     * error (typically ENODATA) means the connection has no hw activity
> +     * and should be expired normally. */
>      ct_offload_op_batch_submit(&batch);
>  
>      CT_OFFLOAD_BATCH_OP_FOR_EACH (idx, op, &batch) {
>          struct conn *c = CONST_CAST(struct conn *, op->ctx.conn);
> -
>          if (op->error) {
>              conn_clean(ct, c);
>              cleaned++;
> diff --git a/lib/ct-offload.c b/lib/ct-offload.c
> index 618bd655d0..b777801ab9 100644
> --- a/lib/ct-offload.c
> +++ b/lib/ct-offload.c
> @@ -20,8 +20,10 @@
>  #include "conntrack.h"
>  #include "conntrack-private.h"
>  #include "ct-offload.h"
> +#include "dpif-offload.h"
>  #include "ovs-thread.h"
>  #include "util.h"
> +#include "vswitch-idl.h"
>  
>  #include "openvswitch/list.h"
>  #include "openvswitch/vlog.h"
> @@ -51,6 +53,12 @@ static struct ovs_list  ct_offload_classes
>      OVS_GUARDED_BY(ct_offload_mutex)
>      = OVS_LIST_INITIALIZER(&ct_offload_classes);
>  
> +/* Built-in CT offload provider classes.  Only those whose name matches a
> + * registered dpif offload class will be activated by 
> ct_offload_module_init().
> + */
> +static const struct ct_offload_class *base_ct_offload_classes[] = {
> +};
> +
>  
>  /* ct_offload_register() - register a CT offload provider class.
>   *
> @@ -140,11 +148,52 @@ ct_offload_alloc_private_slot(void)
>  
>  /* ct_offload_module_init() - register built-in CT offload providers.
>   *
> - * Must be called once before any connections are created. */
> + * Only registers providers whose name matches a currently-registered dpif
> + * offload class, so CT offload is automatically tied to the active hardware
> + * offload provider.  Safe to call multiple times; subsequent calls are
> + * no-ops (duplicate registration is detected and skipped). */
>  void
>  ct_offload_module_init(void)
>  {
>      ct_offload_alloc_private_slot();
> +
> +    for (int i = 0; i < ARRAY_SIZE(base_ct_offload_classes); i++) {

NOTE: As correctly pointed out by the github builds, this should
actually be a size_t index var.

> +        const struct ct_offload_class *class = base_ct_offload_classes[i];
> +
> +        if (dpif_offload_class_is_registered(class->name)) {
> +            ct_offload_register(class);
> +        }
> +    }
> +}
> +
> +/* ct_offload_enabled() - returns true when hardware offload is active.
> + *
> + * Delegates to dpif_offload_enabled() so CT offload shares the same global
> + * enable/disable knob as datapath hardware offload. */
> +bool
> +ct_offload_enabled(void)
> +{
> +    return dpif_offload_enabled();
> +}
> +
> +/* ct_offload_set_global_cfg() - configure CT offload from OVSDB.
> + *
> + * Must be called alongside dpif_offload_set_global_cfg() so that CT offload
> + * providers are registered once hardware offload has been enabled and the
> + * appropriate dpif offload classes are known. */
> +void
> +ct_offload_set_global_cfg(const struct ovsrec_open_vswitch *cfg OVS_UNUSED)
> +{
> +    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
> +
> +    if (!dpif_offload_enabled()) {
> +        return;
> +    }
> +
> +    if (ovsthread_once_start(&once)) {
> +        ct_offload_module_init();
> +        ovsthread_once_done(&once);
> +    }
>  }
>  
>  /* ct_offload_conn_add_() - notify all eligible providers of a new 
> connection.
> diff --git a/lib/ct-offload.h b/lib/ct-offload.h
> index fcb3170fa1..fe4ecd33b8 100644
> --- a/lib/ct-offload.h
> +++ b/lib/ct-offload.h
> @@ -21,6 +21,7 @@
>  
>  struct conn;
>  struct netdev;
> +struct ovsrec_open_vswitch;
>  
>  /* Context for offload as part of the callbacks that all connection
>   * offload APIs receive.
> @@ -91,6 +92,13 @@ void ct_offload_unregister(const struct ct_offload_class 
> *);
>  void ct_offload_alloc_private_slot(void);
>  /* Module initialization (register built-in providers). */
>  void ct_offload_module_init(void);
> +/* Global configuration: call alongside dpif_offload_set_global_cfg() to
> + * enable CT offload when hardware offload is active. */
> +void ct_offload_set_global_cfg(const struct ovsrec_open_vswitch *);
> +
> +/* Returns true when CT offload is enabled (delegates to 
> dpif_offload_enabled).
> + */
> +bool ct_offload_enabled(void);
>  
>  /* Per-connection offload API that dispatches to all registered providers. */
>  int       ct_offload_conn_add(const struct ct_offload_ctx *);
> diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
> index bb2feced9e..30cc4fd271 100644
> --- a/lib/dpif-offload.c
> +++ b/lib/dpif-offload.c
> @@ -516,6 +516,19 @@ dpif_offload_enabled(void)
>      return enabled;
>  }
>  
> +/* dpif_offload_class_is_registered() - returns true if a dpif offload class
> + * with the given name has been successfully registered. */
> +bool
> +dpif_offload_class_is_registered(const char *name)
> +{
> +    bool found;
> +
> +    ovs_mutex_lock(&dpif_offload_mutex);
> +    found = shash_find(&dpif_offload_classes, name) != NULL;
> +    ovs_mutex_unlock(&dpif_offload_mutex);
> +    return found;
> +}
> +
>  bool
>  dpif_offload_rebalance_policy_enabled(void)
>  {
> diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
> index 7fad3ebee3..d95e4b9463 100644
> --- a/lib/dpif-offload.h
> +++ b/lib/dpif-offload.h
> @@ -45,6 +45,7 @@ enum dpif_offload_impl_type {
>  void dpif_offload_set_global_cfg(const struct ovsrec_open_vswitch *);
>  bool dpif_offload_enabled(void);
>  bool dpif_offload_rebalance_policy_enabled(void);
> +bool dpif_offload_class_is_registered(const char *name);
>  
>  
>  /* Per dpif specific functions. */
> diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> index 7a68e19ac3..91ffe76648 100644
> --- a/vswitchd/bridge.c
> +++ b/vswitchd/bridge.c
> @@ -28,6 +28,7 @@
>  #include "daemon.h"
>  #include "dirs.h"
>  #include "dpif.h"
> +#include "ct-offload.h"
>  #include "dpif-offload.h"
>  #include "dpdk.h"
>  #include "hash.h"
> @@ -543,6 +544,8 @@ bridge_init(const char *remote)
>  void
>  bridge_exit(bool delete_datapath)
>  {
> +    ct_offload_flush();
> +
>      if_notifier_manual_set_cb(NULL);
>      if_notifier_destroy(ifnotifier);
>      seq_destroy(ifaces_changed);
> @@ -3396,6 +3399,7 @@ bridge_run(void)
>  
>      if (cfg && ovsdb_idl_get_seqno(idl) != idl_seqno) {
>          dpif_offload_set_global_cfg(cfg);
> +        ct_offload_set_global_cfg(cfg);
>      }
>  
>      if (cfg) {

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to