Hi Naveen,

Dumitru or Numan may have a different opinion from me on this, but I
don't think it makes sense to integrate this patch into 26.03 without
the rest of the active-active patches. I'm imagining a user that is
using the Network Function support in ovn25.09 upgrading to ovn26.03.
Now they find that they need to insert an ID for the network functions
that they didn't have to before. When they look into why they need to
do it, the answer is...no reason. Yes, the ID will be used in a future
version, but in the current version, it's being required for no
apparent reason. IMO, this should be deferred until the entire
active-active patch series is posted. This way, it is more clear why
the ID is being required.

On a secondary note, if someone is not going to use the active-active,
feature, it would be good if the ID on the NF is optional. This way
we're less likely to cause problems during upgrades.

Thanks,
Mark Michelson

On Tue, Jan 20, 2026 at 11:55 PM Naveen Yerramneni
<[email protected]> wrote:
>
> Hi Dumitru, Mark, Numan,
>
>
>
> Could you please consider this patch for OVN 26.03  release ?
>
> Since there is no enough time to review entire Active/Active  patch for 26.03 
> , we thought it is better to commit this schema changes for 26.03.
>
> The plan is to modify the code to store nf-id in CT label instead of nfg-id 
> in Active/Active patch. This is required to avoid switching existing 
> connections going to healthy NFs when no.of healthy NFs count in an NFG 
> changes.
>
> Please let us know if there any concerns or other suggestions.
>
>
>
> Thanks,
>
> Naveen
>
>
>
> From: Aditya Mehakare <[email protected]>
> Date: Tuesday, 20 January 2026 at 8:16 PM
> To: [email protected] <[email protected]>
> Cc: Aditya Mehakare <[email protected]>, Naveen Yerramneni 
> <[email protected]>
> Subject: [PATCH ovn] ovn-nb, ovn-nbctl: Add ID column to Network_Function 
> table.
>
> This commit introduces a new 'id' column to the Network_Function table
> in the OVN Northbound database schema. The ID is a mandatory integer
> field (range 1-255) with a unique index constraint.
>
> This change is required to support network function active-active mode
> in future releases. The ID will be used to uniquely identify network
> functions in scenarios where multiple instances need to be managed
> simultaneously.
>
> Since this is a schema change that is not backward compatible, it is
> being introduced in the current release to ensure smoother upgrades
> when active-active mode support is added in subsequent releases.
>
> Schema changes:
> - Added 'id' column to Network_Function table (integer, 1-255)
> - Added unique index on 'id' column alongside existing 'name' index
>
> Changes to ovn-nbctl:
> - Updated nf-add command to require ID parameter:
>   nf-add NETWORK-FUNCTION ID PORT-IN PORT-OUT
> - Modified nf-list to display the ID field
> - Updated related documentation, and tests
>
> Signed-off-by: Aditya Mehakare <[email protected]>
> Acked-by: Naveen Yerramneni <[email protected]>
> ---
>  ovn-nb.ovsschema          | 10 +++++---
>  ovn-nb.xml                |  5 ++++
>  tests/ovn-nbctl.at        | 48 +++++++++++++++++++++++++++------------
>  tests/ovn-northd.at       |  8 +++----
>  tests/ovn.at              |  6 ++---
>  tests/system-ovn.at       |  4 ++--
>  utilities/ovn-nbctl.8.xml | 19 ++++++++--------
>  utilities/ovn-nbctl.c     | 25 +++++++++++++++-----
>  8 files changed, 84 insertions(+), 41 deletions(-)
>
> diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
> index 8c2c1d861..2c60d000c 100644
> --- a/ovn-nb.ovsschema
> +++ b/ovn-nb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>      "name": "OVN_Northbound",
> -    "version": "7.15.0",
> -    "cksum": "4060410729 43708",
> +    "version": "7.16.0",
> +    "cksum": "3182666148 43912",
>      "tables": {
>          "NB_Global": {
>              "columns": {
> @@ -213,10 +213,14 @@
>                              "refTable": "Network_Function_Health_Check",
>                              "refType": "strong"},
>                      "min": 0, "max": 1}},
> +                "id": {
> +                     "type": {"key": {"type": "integer",
> +                                      "minInteger": 1,
> +                                      "maxInteger": 255}}},
>                  "external_ids": {
>                      "type": {"key": "string", "value": "string",
>                               "min": 0, "max": "unlimited"}}},
> -            "indexes": [["name"]],
> +            "indexes": [["name"], ["id"]],
>              "isRoot": true},
>          "Network_Function_Group": {
>              "columns": {
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index e74c0d010..4f71fe0e7 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -6382,6 +6382,11 @@ or
>        Name of the <ref table="Network_Function"/>. Name should be unique.
>      </column>
>
> +    <column name="id">
> +      A unique integer between 1 and 255 must be assigned to each
> +      <code>Network_Function</code>.
> +    </column>
> +
>      <column name="inport">
>        <ref table="Logical_Switch_Port"/>  where request traffic for 
> from-lport
>        ACL and response traffic for to-lport ACL is redirected.
> diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
> index dccf30758..f4cb89b82 100644
> --- a/tests/ovn-nbctl.at
> +++ b/tests/ovn-nbctl.at
> @@ -3245,13 +3245,13 @@ AT_CHECK([check ovn-nbctl set logical_switch_port 
> svc-port1 \
>      options:is-nf=true options:nf-linked-port=svc-port0])
>
>  # Create network-function.
> -AT_CHECK([ovn-nbctl nf-add nf0 svc-port0 svc-port1])
> -AT_CHECK([ovn-nbctl nf-add nf0 svc-port0 svc-port1], [1], [],
> +AT_CHECK([ovn-nbctl nf-add nf0 1 svc-port0 svc-port1])
> +AT_CHECK([ovn-nbctl nf-add nf0 1 svc-port0 svc-port1], [1], [],
>    [ovn-nbctl: nf0: same name network-function already exists
>  ])
> -AT_CHECK([ovn-nbctl --may-exist nf-add nf0 svc-port0 svc-port1])
> +AT_CHECK([ovn-nbctl --may-exist nf-add nf0 1 svc-port0 svc-port1])
>  AT_CHECK([ovn-nbctl nf-list | uuidfilt], [0], [dnl
> -<0> (nf0) in:svc-port0 out:svc-port1
> +<0> (nf0) id:1 in:svc-port0 out:svc-port1
>  ])
>
>  # Test --may-exist overwrite behavior: update existing network function with 
> new ports
> @@ -3263,25 +3263,25 @@ AT_CHECK([check ovn-nbctl set logical_switch_port 
> svc-port4 \
>  AT_CHECK([check ovn-nbctl set logical_switch_port svc-port5 \
>      options:receive_multicast=false options:lsp_learn_fdb=false \
>      options:is-nf=true options:nf-linked-port=svc-port4])
> -AT_CHECK([ovn-nbctl --may-exist nf-add nf0 svc-port4 svc-port5])
> +AT_CHECK([ovn-nbctl --may-exist nf-add nf0 1 svc-port4 svc-port5])
>  AT_CHECK([ovn-nbctl nf-list | uuidfilt], [0], [dnl
> -<0> (nf0) in:svc-port4 out:svc-port5
> +<0> (nf0) id:1 in:svc-port4 out:svc-port5
>  ])
>
>  # Create two more network-functions, one with same inport and outport.
>  AT_CHECK([check ovn-nbctl lsp-add ls0 svc-port2])
>  AT_CHECK([check ovn-nbctl lsp-add ls0 svc-port3])
> -AT_CHECK([ovn-nbctl nf-add nf1 svc-port2 svc-port3])
> +AT_CHECK([ovn-nbctl nf-add nf1 2 svc-port2 svc-port3])
>  AT_CHECK([ovn-nbctl nf-list | uuidfilt], [0], [dnl
> -<0> (nf0) in:svc-port4 out:svc-port5
> -<1> (nf1) in:svc-port2 out:svc-port3
> +<0> (nf0) id:1 in:svc-port4 out:svc-port5
> +<1> (nf1) id:2 in:svc-port2 out:svc-port3
>  ])
>
> -AT_CHECK([ovn-nbctl nf-add nf2 svc-port2 svc-port2])
> +AT_CHECK([ovn-nbctl nf-add nf2 3 svc-port2 svc-port2])
>  AT_CHECK([ovn-nbctl nf-list | uuidfilt], [0], [dnl
> -<0> (nf0) in:svc-port4 out:svc-port5
> -<1> (nf1) in:svc-port2 out:svc-port3
> -<2> (nf2) in:svc-port2 out:svc-port2
> +<0> (nf0) id:1 in:svc-port4 out:svc-port5
> +<1> (nf1) id:2 in:svc-port2 out:svc-port3
> +<2> (nf2) id:3 in:svc-port2 out:svc-port2
>  ])
>
>  # Create a network-function-group.
> @@ -3334,10 +3334,30 @@ AT_CHECK([ovn-nbctl nfg-list | uuidfilt], [0], [])
>  AT_CHECK([ovn-nbctl nf-del nf1])
>  AT_CHECK([ovn-nbctl nf-del nf0])
>  AT_CHECK([ovn-nbctl nf-list | uuidfilt], [0], [dnl
> -<0> (nf2) in:svc-port2 out:svc-port2
> +<0> (nf2) id:3 in:svc-port2 out:svc-port2
>  ])
>  AT_CHECK([ovn-nbctl nf-del nf2])
>  AT_CHECK([ovn-nbctl nf-list | uuidfilt], [0], [])
> +
> +# Test ID validation and uniqueness
> +AT_CHECK([check ovn-nbctl lsp-add ls0 svc-port6])
> +AT_CHECK([check ovn-nbctl lsp-add ls0 svc-port7])
> +# Test invalid ID (out of range)
> +AT_CHECK([ovn-nbctl nf-add nf3 0 svc-port6 svc-port7], [1], [],
> +  [ovn-nbctl: network-function id must be between 1 and 255
> +])
> +AT_CHECK([ovn-nbctl nf-add nf3 256 svc-port6 svc-port7], [1], [],
> +  [ovn-nbctl: network-function id must be between 1 and 255
> +])
> +AT_CHECK([ovn-nbctl nf-add nf3 abc svc-port6 svc-port7], [1], [],
> +  [ovn-nbctl: network-function id must be between 1 and 255
> +])
> +# Test valid ID
> +AT_CHECK([ovn-nbctl nf-add nf3 10 svc-port6 svc-port7])
> +AT_CHECK([ovn-nbctl nf-list | uuidfilt], [0], [dnl
> +<0> (nf3) id:10 in:svc-port6 out:svc-port7
> +])
> +AT_CHECK([ovn-nbctl nf-del nf3])
>  ])
>
>  AT_SETUP([ovn-nbctl - TLS server name indication (SNI) with 
> --ssl-server-name])
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 25655c456..9a1cfdb99 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -18438,7 +18438,7 @@ check ovn-nbctl set logical_switch_port sw0-nf-p1 \
>  check ovn-nbctl set logical_switch_port sw0-nf-p2 \
>      options:receive_multicast=false options:lsp_learn_mac=false \
>      options:is-nf=true options:nf-linked-port=sw0-nf-p1
> -check ovn-nbctl nf-add nf0 sw0-nf-p1 sw0-nf-p2
> +check ovn-nbctl nf-add nf0 1 sw0-nf-p1 sw0-nf-p2
>  check ovn-nbctl nfg-add nfg0 1 inline nf0
>
>  check ovn-nbctl lsp-add sw0 sw0-p1 -- lsp-set-addresses sw0-p1 
> "00:00:00:00:00:01 10.0.0.2"
> @@ -18551,7 +18551,7 @@ check ovn-nbctl set logical_switch_port sw0-nf-p3 \
>  check ovn-nbctl set logical_switch_port sw0-nf-p4 \
>      options:receive_multicast=false options:lsp_learn_mac=false \
>      options:is-nf=true options:nf-linked-port=sw0-nf-p3
> -check ovn-nbctl nf-add nf1 sw0-nf-p3 sw0-nf-p4
> +check ovn-nbctl nf-add nf1 2 sw0-nf-p3 sw0-nf-p4
>  check ovn-nbctl nfg-add nfg1 2 inline nf1
>  check ovn-nbctl acl-add pg0 to-lport 1003 "outport == @pg0 && ip4.src == 
> 10.0.0.4" allow-related nfg1
>  check ovn-sbctl lsp-bind sw0-nf-p3 hv1
> @@ -18729,8 +18729,8 @@ check ovn-nbctl set logical_switch_port $nfsw-p4 \
>      options:receive_multicast=false options:lsp_learn_fdb=false \
>      options:is-nf=true options:nf-linked-port=$nfsw-p3
>
> -check ovn-nbctl nf-add nf0 $nfsw-p1 $nfsw-p2
> -check ovn-nbctl nf-add nf1 $nfsw-p3 $nfsw-p4
> +check ovn-nbctl nf-add nf0 1 $nfsw-p1 $nfsw-p2
> +check ovn-nbctl nf-add nf1 2 $nfsw-p3 $nfsw-p4
>  nf0_uuid=$(fetch_column nb:network_function _uuid name=nf0)
>  nf1_uuid=$(fetch_column nb:network_function _uuid name=nf1)
>  AT_CHECK(
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 445a74ce5..3babe1636 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -35816,7 +35816,7 @@ check ovs-vsctl add-port br-int ls0-hv -- set 
> Interface ls0-hv external-ids:ifac
>  check ovn-nbctl lr-add lr0
>
>  check ovn-nbctl ls-add ls0
> -check ovn-nbctl lsp-add ls0 ls0-lr0
> +check ovn-nbctl lsp-add ls0 ls0-lr0
>  check ovn-nbctl lsp-set-type ls0-lr0 router
>  check ovn-nbctl lsp-set-addresses ls0-lr0 router
>  check ovn-nbctl lrp-add lr0 lr0-ls0 00:00:00:00:00:01 10.0.0.1
> @@ -43563,7 +43563,7 @@ create_logical_topology() {
>      check ovn-nbctl set logical_switch_port $sw-nf-p2 \
>          options:receive_multicast=false options:lsp_learn_mac=false \
>          options:is-nf=true options:nf-linked-port=$sw-nf-p1
> -    check ovn-nbctl nf-add nf0 $sw-nf-p1 $sw-nf-p2
> +    check ovn-nbctl nf-add nf0 1 $sw-nf-p1 $sw-nf-p2
>      check ovn-nbctl nfg-add nfg0 1 inline nf0
>      check ovn-nbctl pg-add pg0 $sw-p1
>      check ovn-nbctl acl-add pg0 from-lport 1002 "inport == @pg0 && ip4.dst 
> == 192.168.0.12" allow-related nfg0
> @@ -43753,7 +43753,7 @@ create_logical_topology() {
>      check ovn-nbctl set logical_switch_port $sw-nf-p2 \
>          options:receive_multicast=false options:lsp_learn_mac=false \
>          options:is-nf=true options:nf-linked-port=$sw-nf-p1
> -    check ovn-nbctl nf-add nf0 $sw-nf-p1 $sw-nf-p2
> +    check ovn-nbctl nf-add nf0 1 $sw-nf-p1 $sw-nf-p2
>      check ovn-nbctl nfg-add nfg0 1 inline nf0
>      check ovn-nbctl pg-add pg0 $sw-p1
>      check ovn-nbctl acl-add pg0 to-lport 1002 "outport == @pg0 && ip4.src == 
> 192.168.0.12" allow-related nfg0
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index fc601dd1b..a10f3e591 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -19417,7 +19417,7 @@ check ovn-nbctl set logical_switch_port child-4 
> options:receive_multicast=false
>
>  AS_BOX([Test-1: Single NF without health check])
>
> -check ovn-nbctl nf-add nf0 nf-p1 nf-p2
> +check ovn-nbctl nf-add nf0 1 nf-p1 nf-p2
>  nf0_uuid=$(fetch_column nb:network_function _uuid name=nf0)
>  check ovn-nbctl nfg-add nfg0 1 inline nf0
>  nfg_uuid=$(fetch_column nb:network_function_group _uuid name=nfg0)
> @@ -19519,7 +19519,7 @@ validate_single_nf_no_health_check "server" "client" 
> "192.168.1.10" "Outbound"
>  AS_BOX([Test-2: Two NFs with health check config enabled])
>
>  # Add second NF
> -check ovn-nbctl nf-add nf1 nf-p3 nf-p4
> +check ovn-nbctl nf-add nf1 2 nf-p3 nf-p4
>  nf1_uuid=$(fetch_column nb:network_function _uuid name=nf1)
>
>  # Add bridge for nf1
> diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml
> index 7df902944..253f6d8fc 100644
> --- a/utilities/ovn-nbctl.8.xml
> +++ b/utilities/ovn-nbctl.8.xml
> @@ -475,16 +475,17 @@
>      <h2>Network Function Commands</h2>
>
>      <dl>
> -      <dt>[<code>--may-exist</code>] <code>nf-add</code> <var>nf</var> 
> <var>inport</var> <var>outport</var></dt>
> +      <dt>[<code>--may-exist</code>] <code>nf-add</code> <var>nf</var> 
> <var>id</var> <var>inport</var> <var>outport</var></dt>
>        <dd>
>          <p>
> -          Creates a new network function named <var>nf</var> with logical
> -          switch ports <var>inport</var> and <var>outport</var>. Both the
> -          ports must be on the same logical switch and must be already
> -          created. When used in an ACL action, traffic matching the ACL
> -          are redirected to the <var>inport</var> if it is from-lport ACL
> -          and to the <var>outport</var> if it is to-lport ACL. The response
> -          packets are sent through the same ports in reverse order.
> +          Creates a new network function named <var>nf</var> with the 
> specified
> +          <var>id</var> (an integer between 1 and 255) and logical switch 
> ports
> +          <var>inport</var> and <var>outport</var>. Both the ports must be on
> +          the same logical switch and must be already created. When used in 
> an
> +          ACL action, traffic matching the ACL are redirected to the
> +          <var>inport</var> if it is from-lport ACL and to <var>outport</var>
> +          if it is to-lport ACL. The response packets are sent through the 
> same
> +          ports in reverse order.
>          </p>
>
>          <p>
> @@ -1498,7 +1499,7 @@
>           The optional argument <var>protocol</var> must be either
>           <code>tcp</code>,  <code>udp</code> or <code>sctp</code>. This 
> argument
>           is useful when a port number is provided as part of the 
> <var>vip</var>.
> -         If the <var>protocol</var> is unspecified and a port number is 
> provided
> +         If the <var>protocol</var> is unspecified and a port number is 
> provided
>           as part of the <var>vip</var>, OVN assumes the <var>protocol</var> 
> to
>           be <code>tcp</code>.
>          </p>
> diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
> index cdf6b578a..2b674cad3 100644
> --- a/utilities/ovn-nbctl.c
> +++ b/utilities/ovn-nbctl.c
> @@ -393,7 +393,7 @@ Network function group commands:\n\
>                              network-function-group\n\
>  \n\
>  Network function commands:\n\
> -  nf-add NETWORK-FUNCTION PORT-IN PORT-OUT\n\
> +  nf-add NETWORK-FUNCTION ID PORT-IN PORT-OUT\n\
>                             create a network-function\n\
>    nf-del NETWORK-FUNCTION  delete a network-function\n\
>    nf-list                  print all network-functions\n\
> @@ -2483,6 +2483,7 @@ nbctl_pre_nf_add(struct ctl_context *ctx)
>
>      ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name);
>      ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_id);
>      ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_inport);
>      ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_outport);
>  }
> @@ -2495,17 +2496,25 @@ nbctl_nf_add(struct ctl_context *ctx)
>
>      bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
>
> -    char * error = lsp_by_name_or_uuid(ctx, ctx->argv[2], true, &lsp_in);
> +    char * error = lsp_by_name_or_uuid(ctx, ctx->argv[3], true, &lsp_in);
>      if (error) {
>          ctx->error = error;
>          return;
>      }
> -    error = lsp_by_name_or_uuid(ctx, ctx->argv[3], true, &lsp_out);
> +    error = lsp_by_name_or_uuid(ctx, ctx->argv[4], true, &lsp_out);
>      if (error) {
>          ctx->error = error;
>          return;
>      }
>
> +    /* Validate and parse ID */
> +    int64_t nf_id = 0;
> +    if (!ovs_scan(ctx->argv[2], "%"SCNd64, &nf_id)
> +            || nf_id < 1 || nf_id > 255) {
> +        ctl_error(ctx, "network-function id must be between 1 and 255");
> +        return;
> +    }
> +
>      const char *nf_name = ctx->argv[1];
>
>      /* Check if network function already exists */
> @@ -2528,6 +2537,9 @@ nbctl_nf_add(struct ctl_context *ctx)
>          nbrec_network_function_set_name(nf, nf_name);
>      }
>
> +    /* Set ID */
> +    nbrec_network_function_set_id(nf, nf_id);
> +
>      /* Set/update the ports */
>      nbrec_network_function_set_inport(nf, lsp_in);
>      nbrec_network_function_set_outport(nf, lsp_out);
> @@ -2560,6 +2572,7 @@ static void
>  nbctl_pre_nf_list(struct ctl_context *ctx)
>  {
>      ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_id);
>      ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_inport);
>      ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_outport);
>      ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name);
> @@ -2577,9 +2590,9 @@ nbctl_nf_list(struct ctl_context *ctx)
>          const char *linport_name = linport ? linport->name : "<not_set>";
>          const char *loutport_name = loutport ? loutport->name : "<not_set>";
>          smap_add_format(&nfs, nf->name,
> -                        UUID_FMT " (%s) in:%s out:%s",
> +                        UUID_FMT " (%s) id:%"PRId64" in:%s out:%s",
>                          UUID_ARGS(&nf->header_.uuid),
> -                        nf->name, linport_name, loutport_name);
> +                        nf->name, nf->id, linport_name, loutport_name);
>      }
>      const struct smap_node **nodes = smap_sort(&nfs);
>      for (size_t i = 0; i < smap_count(&nfs); i++) {
> @@ -8877,7 +8890,7 @@ static const struct ctl_command_syntax nbctl_commands[] 
> = {
>        nbctl_nf_group_del_network_function, NULL, "--if-exists", RW },
>
>      /* network-function commands. */
> -    { "nf-add", 3, 3, "NETWORK-FUNCTION PORT-IN PORT-OUT",
> +    { "nf-add", 4, 4, "NETWORK-FUNCTION ID PORT-IN PORT-OUT",
>        nbctl_pre_nf_add,
>        nbctl_nf_add,
>        NULL, "--may-exist", RW },
> --
> 2.43.5

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

Reply via email to