Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2221007/?format=api
{ "id": 2221007, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2221007/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/20260408170613.587902-6-aconole@redhat.com/", "project": { "id": 47, "url": "http://patchwork.ozlabs.org/api/1.1/projects/47/?format=api", "name": "Open vSwitch", "link_name": "openvswitch", "list_id": "ovs-dev.openvswitch.org", "list_email": "ovs-dev@openvswitch.org", "web_url": "http://openvswitch.org/", "scm_url": "git@github.com:openvswitch/ovs.git", "webscm_url": "https://github.com/openvswitch/ovs" }, "msgid": "<20260408170613.587902-6-aconole@redhat.com>", "date": "2026-04-08T17:06:01", "name": "[ovs-dev,RFC,05/12] ct-offload: Add a new interface as an offload provider.", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "29b041e6d9ea4493d33af3316e5254dc774d095b", "submitter": { "id": 67184, "url": "http://patchwork.ozlabs.org/api/1.1/people/67184/?format=api", "name": "Aaron Conole", "email": "aconole@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/20260408170613.587902-6-aconole@redhat.com/mbox/", "series": [ { "id": 499163, "url": "http://patchwork.ozlabs.org/api/1.1/series/499163/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=499163", "date": "2026-04-08T17:05:56", "name": "ct-offload: Introduce a conntrack offload infrastructure.", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/499163/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2221007/comments/", "check": "success", "checks": "http://patchwork.ozlabs.org/api/patches/2221007/checks/", "tags": {}, "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=i0sf5DiW;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)", "smtp2.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=i0sf5DiW", "smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com", "smtp1.osuosl.org;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.a=rsa-sha256 header.s=mimecast20190719 header.b=i0sf5DiW" ], "Received": [ "from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4frTxt4XzVz1xv0\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 03:06:58 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby smtp2.osuosl.org (Postfix) with ESMTP id 441FE40817;\n\tWed, 8 Apr 2026 17:06:57 +0000 (UTC)", "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id x6q5vM9UP41Z; Wed, 8 Apr 2026 17:06:56 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp2.osuosl.org (Postfix) with ESMTPS id 1BA7A40818;\n\tWed, 8 Apr 2026 17:06:56 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id EFB65C054A;\n\tWed, 8 Apr 2026 17:06:55 +0000 (UTC)", "from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 1B5F2C054A\n for <dev@openvswitch.org>; Wed, 8 Apr 2026 17:06:54 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 96C10826C0\n for <dev@openvswitch.org>; Wed, 8 Apr 2026 17:06:36 +0000 (UTC)", "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id WgrOwOyGn_Xq for <dev@openvswitch.org>;\n Wed, 8 Apr 2026 17:06:33 +0000 (UTC)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 0044A82656\n for <dev@openvswitch.org>; Wed, 8 Apr 2026 17:06:32 +0000 (UTC)", "from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-425-Qu5TMTdLM76d9drApvikSw-1; Wed,\n 08 Apr 2026 13:06:28 -0400", "from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 7CE28195608F; Wed, 8 Apr 2026 17:06:27 +0000 (UTC)", "from RHTRH0061144.redhat.com (unknown [10.22.89.172])\n by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id BE0A530001BB; Wed, 8 Apr 2026 17:06:25 +0000 (UTC)" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp2.osuosl.org 1BA7A40818", "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 0044A82656" ], "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=aconole@redhat.com;\n receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp1.osuosl.org 0044A82656", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775667991;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=PBRrfpMJPqrYCC6af7jFsEFTfg7JHg4h1hjzGfoVX6Y=;\n b=i0sf5DiW4oJDg2wuIpefMglOvpqNkDfkizKrUi2Gv4p3VXYQwRQeVioAkEHyqPwjF8Fv0a\n W//4DHRAKELw+PZaV93cAefJttWiyQgLjuJopYnjteOheWpaLVi1BspjZRMStYngbtE3IZ\n UEcwYxbnWeQJg6tWNuIqP/PxH9LeGUs=", "X-MC-Unique": "Qu5TMTdLM76d9drApvikSw-1", "X-Mimecast-MFC-AGG-ID": "Qu5TMTdLM76d9drApvikSw_1775667987", "To": "dev@openvswitch.org", "Date": "Wed, 8 Apr 2026 13:06:01 -0400", "Message-ID": "<20260408170613.587902-6-aconole@redhat.com>", "In-Reply-To": "<20260408170613.587902-1-aconole@redhat.com>", "References": "<20260408170613.587902-1-aconole@redhat.com>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.4", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "-pmcfD26oibaG6dOTNk9qhy_wrn746CYZU7yZz3Q3Rw_1775667987", "X-Mimecast-Originator": "redhat.com", "Subject": "[ovs-dev] [RFC 05/12] ct-offload: Add a new interface as an offload\n provider.", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "<ovs-dev.openvswitch.org>", "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>", "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>", "List-Post": "<mailto:ovs-dev@openvswitch.org>", "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>", "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>", "From": "Aaron Conole via dev <ovs-dev@openvswitch.org>", "Reply-To": "Aaron Conole <aconole@redhat.com>", "Cc": "Eli Britstein <elibr@nvidia.com>, Florian Westphal <fwestpha@redhat.com>,\n Flavio Leitner <fbl@redhat.com>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "ovs-dev-bounces@openvswitch.org", "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>" }, "content": "This adds the basic primitives, initialization, and operations that\nconntrack offload providers will need to implement in order to\noffer a path to offloading.\n\nSigned-off-by: Aaron Conole <aconole@redhat.com>\n---\n lib/automake.mk | 2 +\n lib/ct-offload.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++\n lib/ct-offload.h | 97 ++++++++++++++++++\n 3 files changed, 356 insertions(+)\n create mode 100644 lib/ct-offload.c\n create mode 100644 lib/ct-offload.h", "diff": "diff --git a/lib/automake.mk b/lib/automake.mk\nindex 027dd986ba..f11e3de27c 100644\n--- a/lib/automake.mk\n+++ b/lib/automake.mk\n@@ -97,6 +97,8 @@ lib_libopenvswitch_la_SOURCES = \\\n \tlib/conntrack-other.c \\\n \tlib/conntrack.c \\\n \tlib/conntrack.h \\\n+\tlib/ct-offload.c \\\n+\tlib/ct-offload.h \\\n \tlib/cooperative-multitasking.c \\\n \tlib/cooperative-multitasking.h \\\n \tlib/cooperative-multitasking-private.h \\\ndiff --git a/lib/ct-offload.c b/lib/ct-offload.c\nnew file mode 100644\nindex 0000000000..3bd6200e37\n--- /dev/null\n+++ b/lib/ct-offload.c\n@@ -0,0 +1,257 @@\n+/*\n+ * Copyright (c) 2026 Red Hat, Inc.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at:\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+#include <config.h>\n+#include <errno.h>\n+\n+#include \"ct-offload.h\"\n+#include \"ovs-thread.h\"\n+#include \"util.h\"\n+\n+#include \"openvswitch/list.h\"\n+#include \"openvswitch/vlog.h\"\n+\n+VLOG_DEFINE_THIS_MODULE(ct_offload);\n+\n+/* Node in the registered-provider list. */\n+struct ct_offload_class_node {\n+ const struct ct_offload_class *class;\n+ struct ovs_list list_node;\n+};\n+\n+/* Global list of registered CT offload classes and a mutex to protect it.\n+ * Providers are expected to be registered at module init time and\n+ * unregistered only at module teardown, so contention is minimal. */\n+static struct ovs_mutex ct_offload_mutex = OVS_MUTEX_INITIALIZER;\n+static struct ovs_list ct_offload_classes\n+ OVS_GUARDED_BY(ct_offload_mutex)\n+ = OVS_LIST_INITIALIZER(&ct_offload_classes);\n+\n+\n+/* ct_offload_register() - register a CT offload provider class.\n+ *\n+ * Calls class->init() if provided. Returns 0 on success or a positive\n+ * errno value on failure. Attempting to register the same class twice\n+ * returns EEXIST. */\n+int\n+ct_offload_register(const struct ct_offload_class *class)\n+{\n+ struct ct_offload_class_node *node;\n+ int error = 0;\n+\n+ ovs_assert(class);\n+ ovs_assert(class->name);\n+\n+ ovs_mutex_lock(&ct_offload_mutex);\n+\n+ /* Detect duplicate registrations. */\n+ LIST_FOR_EACH (node, list_node, &ct_offload_classes) {\n+ if (!strcmp(node->class->name, class->name)) {\n+ VLOG_WARN(\"attempted to register duplicate ct offload class: %s\",\n+ class->name);\n+ error = EEXIST;\n+ goto out;\n+ }\n+ }\n+\n+ error = class->init ? class->init() : 0;\n+ if (error) {\n+ VLOG_WARN(\"failed to initialize ct offload class %s: %s\",\n+ class->name, ovs_strerror(error));\n+ goto out;\n+ }\n+\n+ node = xmalloc(sizeof *node);\n+ node->class = class;\n+ ovs_list_push_back(&ct_offload_classes, &node->list_node);\n+ VLOG_DBG(\"registered ct offload class: %s\", class->name);\n+\n+out:\n+ ovs_mutex_unlock(&ct_offload_mutex);\n+ return error;\n+}\n+\n+/* ct_offload_unregister() - unregister a previously registered class.\n+ *\n+ * Safe to call even if the class was never registered (no-op in that\n+ * case). */\n+void\n+ct_offload_unregister(const struct ct_offload_class *class)\n+{\n+ struct ct_offload_class_node *node;\n+\n+ ovs_assert(class);\n+\n+ ovs_mutex_lock(&ct_offload_mutex);\n+ LIST_FOR_EACH (node, list_node, &ct_offload_classes) {\n+ if (node->class == class) {\n+ ovs_list_remove(&node->list_node);\n+ free(node);\n+ VLOG_DBG(\"unregistered ct offload class: %s\", class->name);\n+ goto out;\n+ }\n+ }\n+ VLOG_WARN(\"attempted to unregister unknown ct offload class: %s\",\n+ class->name);\n+\n+out:\n+ ovs_mutex_unlock(&ct_offload_mutex);\n+}\n+\n+/* ct_offload_module_init() - register built-in CT offload providers.\n+ *\n+ * Must be called once before any connections are created. */\n+void\n+ct_offload_module_init(void)\n+{\n+ /* No built-in providers yet; third parties call ct_offload_register()\n+ * directly from their own module-init routines. */\n+}\n+\n+/* ct_offload_conn_add() - notify all eligible providers of a new connection.\n+ *\n+ * Iterates over registered providers and calls conn_add() on each one that\n+ * reports can_offload() == true for this context. Returns the first non-zero\n+ * error encountered, but continues notifying remaining providers. This allows\n+ * the underlying hardware conntrack details across providers function. */\n+int\n+ct_offload_conn_add(const struct ct_offload_ctx *ctx)\n+{\n+ struct ct_offload_class_node *node;\n+ int ret = 0;\n+\n+ ovs_mutex_lock(&ct_offload_mutex);\n+ LIST_FOR_EACH (node, list_node, &ct_offload_classes) {\n+ const struct ct_offload_class *class = node->class;\n+\n+ if (class->can_offload && !class->can_offload(ctx)) {\n+ continue;\n+ }\n+ if (class->conn_add) {\n+ int error = class->conn_add(ctx);\n+\n+ if (error && !ret) {\n+ ret = error;\n+ }\n+ }\n+ }\n+ ovs_mutex_unlock(&ct_offload_mutex);\n+\n+ return ret;\n+}\n+\n+/* ct_offload_conn_del() - notify all providers that a connection was removed.\n+ *\n+ * Called unconditionally on all providers so that each can clean up any\n+ * state it may have installed. */\n+void\n+ct_offload_conn_del(const struct ct_offload_ctx *ctx)\n+{\n+ struct ct_offload_class_node *node;\n+\n+ ovs_mutex_lock(&ct_offload_mutex);\n+ LIST_FOR_EACH (node, list_node, &ct_offload_classes) {\n+ const struct ct_offload_class *class = node->class;\n+\n+ if (class->conn_del) {\n+ class->conn_del(ctx);\n+ }\n+ }\n+ ovs_mutex_unlock(&ct_offload_mutex);\n+}\n+\n+void\n+ct_offload_conn_established(const struct ct_offload_ctx *ctx)\n+{\n+ struct ct_offload_class_node *node;\n+\n+ ovs_mutex_lock(&ct_offload_mutex);\n+ LIST_FOR_EACH (node, list_node, &ct_offload_classes) {\n+ const struct ct_offload_class *class = node->class;\n+\n+ if (class->conn_established) {\n+ class->conn_established(ctx);\n+ }\n+ }\n+ ovs_mutex_unlock(&ct_offload_mutex);\n+}\n+\n+/* ct_offload_conn_update() - query the hardware last-used timestamp.\n+ *\n+ * Iterates over providers and returns the first non-zero timestamp returned\n+ * by a provider's conn_update() callback. Returns 0 if no provider\n+ * supplies a timestamp. */\n+long long\n+ct_offload_conn_update(const struct ct_offload_ctx *ctx)\n+{\n+ struct ct_offload_class_node *node;\n+ long long last_used = 0;\n+\n+ ovs_mutex_lock(&ct_offload_mutex);\n+ LIST_FOR_EACH (node, list_node, &ct_offload_classes) {\n+ const struct ct_offload_class *class = node->class;\n+\n+ if (class->conn_update) {\n+ long long ts = class->conn_update(ctx);\n+\n+ if (ts) {\n+ last_used = ts;\n+ break;\n+ }\n+ }\n+ }\n+ ovs_mutex_unlock(&ct_offload_mutex);\n+\n+ return last_used;\n+}\n+\n+/* ct_offload_can_offload() - returns true if any provider can offload ctx. */\n+bool\n+ct_offload_can_offload(const struct ct_offload_ctx *ctx)\n+{\n+ struct ct_offload_class_node *node;\n+ bool result = false;\n+\n+ ovs_mutex_lock(&ct_offload_mutex);\n+ LIST_FOR_EACH (node, list_node, &ct_offload_classes) {\n+ const struct ct_offload_class *class = node->class;\n+\n+ if (class->can_offload && class->can_offload(ctx)) {\n+ result = true;\n+ break;\n+ }\n+ }\n+ ovs_mutex_unlock(&ct_offload_mutex);\n+\n+ return result;\n+}\n+\n+/* ct_offload_flush() - flush all offloaded connections from every provider. */\n+void\n+ct_offload_flush(void)\n+{\n+ struct ct_offload_class_node *node;\n+\n+ ovs_mutex_lock(&ct_offload_mutex);\n+ LIST_FOR_EACH (node, list_node, &ct_offload_classes) {\n+ const struct ct_offload_class *class = node->class;\n+\n+ if (class->flush) {\n+ class->flush();\n+ }\n+ }\n+ ovs_mutex_unlock(&ct_offload_mutex);\n+}\ndiff --git a/lib/ct-offload.h b/lib/ct-offload.h\nnew file mode 100644\nindex 0000000000..824b94a5c1\n--- /dev/null\n+++ b/lib/ct-offload.h\n@@ -0,0 +1,97 @@\n+/*\n+ * Copyright (c) 2026 Red Hat, Inc.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at:\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+#ifndef CT_OFFLOAD_H\n+#define CT_OFFLOAD_H\n+\n+#include \"openvswitch/types.h\"\n+\n+struct conn;\n+struct netdev;\n+\n+/* Context for offload as part of the callbacks that all connection\n+ * offload APIs receive.\n+ */\n+struct ct_offload_ctx {\n+ const struct conn *conn; /* Connection object being offloaded. */\n+ struct netdev *netdev_in; /* Input netdev. */\n+ odp_port_t input_port_id; /* ODP port number. */\n+};\n+\n+enum ct_offload_op_type {\n+ CT_OFFLOAD_OP_ADD, /* Add operation. */\n+ CT_OFFLOAD_OP_DEL, /* Del operation. */\n+ CT_OFFLOAD_OP_UPD, /* Update operation. */\n+ CT_OFFLOAD_OP_POLICY, /* Policy check operation. */\n+ CT_OFFLOAD_OP_FLUSH, /* Flush. */\n+ CT_OFFLOAD_OP_EST, /* Established - notify that a connection\n+ * has a reply seen. */\n+};\n+\n+struct ct_offload_op {\n+ enum ct_offload_op_type type;\n+ struct ct_offload_ctx ctx;\n+ int error;\n+};\n+\n+/* Batched set of offload contexts and operations.*/\n+struct ct_offload_op_batch {\n+ struct ct_offload_op *ops;\n+ size_t n_ops;\n+ size_t allocated;\n+};\n+\n+\n+/* CT offload class describes a conntrack offload provider implementation. */\n+struct ct_offload_class {\n+ const char *name;\n+\n+ /* Initialization routine for the provider. */\n+ int (*init)(void);\n+\n+ /* Per-connection operation callbacks get called for individual operations\n+ * on the fast path or when batching is not in use. */\n+ int (*conn_add)(const struct ct_offload_ctx *);\n+ void (*conn_del)(const struct ct_offload_ctx *);\n+ /* Populate the last-used timestamp for the connection. Returns the\n+ * last-used time in milliseconds since epoch, or 0 on failure. */\n+ long long (*conn_update)(const struct ct_offload_ctx *);\n+ /* Called exactly once when the first reply-direction packet is seen\n+ * for an offloaded connection. */\n+ void (*conn_established)(const struct ct_offload_ctx *);\n+ /* Check whether this provider can offload a connection. */\n+ bool (*can_offload)(const struct ct_offload_ctx *);\n+ /* Flush all offloaded connections. */\n+ void (*flush)(void);\n+};\n+\n+/* Register/unregister a provider. Must be called at module init, before\n+ * any connections are created. */\n+int ct_offload_register(const struct ct_offload_class *);\n+void ct_offload_unregister(const struct ct_offload_class *);\n+\n+/* Module initialization (register built-in providers). */\n+void ct_offload_module_init(void);\n+\n+/* Per-connection offload API that dispatches to all registered providers. */\n+int ct_offload_conn_add(const struct ct_offload_ctx *);\n+void ct_offload_conn_del(const struct ct_offload_ctx *);\n+long long ct_offload_conn_update(const struct ct_offload_ctx *);\n+void ct_offload_conn_established(const struct ct_offload_ctx *);\n+bool ct_offload_can_offload(const struct ct_offload_ctx *);\n+void ct_offload_flush(void);\n+\n+#endif /* CT_OFFLOAD_H */\n", "prefixes": [ "ovs-dev", "RFC", "05/12" ] }