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++) { + 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) { -- 2.53.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
