- Make outport optional in 'nf-add'.
- Accept 'vtap' mode in 'nfg-add'.

Signed-off-by: Naveen Yerramneni <[email protected]>
Acked-by: Sragdhara Datta Chaudhuri <[email protected]>
Acked-by: Aditya Mehakare <[email protected]>
---
 tests/ovn-nbctl.at        | 46 ++++++++++++++++++++++---
 utilities/ovn-nbctl.8.xml | 55 +++++++++++++++++++++++-------
 utilities/ovn-nbctl.c     | 72 +++++++++++++++++++++++++++++++++------
 3 files changed, 145 insertions(+), 28 deletions(-)

diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
index bf3896361..51c576f6e 100644
--- a/tests/ovn-nbctl.at
+++ b/tests/ovn-nbctl.at
@@ -3319,13 +3319,13 @@ AT_CHECK([ovn-nbctl nfg-add nfg0 2 inline nf0], [1], [],
 ])
 AT_CHECK([ovn-nbctl --may-exist nfg-add nfg0 1 inline nf0])
 AT_CHECK([ovn-nbctl nfg-list | uuidfilt], [0], [dnl
-<0> (nfg0)
+<0> (nfg0) mode:inline
 ])
 
 # Test --may-exist overwrite behavior: update existing network function group 
with new config
 AT_CHECK([ovn-nbctl --may-exist nfg-add nfg0 5 inline nf1 nf2])
 AT_CHECK([ovn-nbctl nfg-list | uuidfilt], [0], [dnl
-<0> (nfg0)
+<0> (nfg0) mode:inline
 ])
 # nf1 and nf2 are already in the group, so adding them should fail without 
--may-exist
 AT_CHECK([ovn-nbctl nfg-add-nf nfg0 nf1], [1], [],
@@ -3336,8 +3336,8 @@ AT_CHECK([ovn-nbctl nfg-add-nf nfg0 nf0])
 AT_CHECK([ovn-nbctl nfg-del-nf nfg0 nf0])
 AT_CHECK([ovn-nbctl nfg-add nfg1 2 inline nf1])
 AT_CHECK([ovn-nbctl nfg-list | uuidfilt], [0], [dnl
-<0> (nfg0)
-<1> (nfg1)
+<0> (nfg0) mode:inline
+<1> (nfg1) mode:inline
 ])
 
 # Access-list with network-function-group.
@@ -3386,6 +3386,44 @@ 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])
+
+# Create network-function with only inport (vtap mode).
+AT_CHECK([ovn-nbctl nf-add nf0 1 svc-port6])
+AT_CHECK([ovn-nbctl nf-list | uuidfilt], [0], [dnl
+<0> (nf0) id:1 in:svc-port6 out:<not_set>
+])
+
+# Create a network-function-group in vtap mode.
+AT_CHECK([ovn-nbctl nfg-add nfg0 1 vtap nf0])
+AT_CHECK([ovn-nbctl nfg-list | uuidfilt], [0], [dnl
+<0> (nfg0) mode:vtap
+])
+AT_CHECK([ovn-nbctl nfg-del nfg0])
+
+# Validation: nf0 has only inport, attempting to use it in an inline
+# network-function-group must be rejected.
+AT_CHECK([ovn-nbctl nfg-add nfg0 1 inline nf0], [1], [], [dnl
+ovn-nbctl: network-function nf0 has no outport set; outport is required for 
inline mode network functions
+])
+AT_CHECK([ovn-nbctl nfg-add nfg0 1 inline])
+AT_CHECK([ovn-nbctl nfg-add-nf nfg0 nf0], [1], [], [dnl
+ovn-nbctl: network-function nf0 has no outport set; outport is required for 
inline mode network functions
+])
+AT_CHECK([ovn-nbctl nfg-del nfg0])
+
+# Validation: an NF with outport set must not be allowed in a vtap
+# network-function-group.
+AT_CHECK([ovn-nbctl nf-add nf-inline 11 svc-port6 svc-port7])
+AT_CHECK([ovn-nbctl nfg-add nfg0 1 vtap nf-inline], [1], [], [dnl
+ovn-nbctl: network-function nf-inline has outport set; outport must not be set 
for vtap mode network functions
+])
+AT_CHECK([ovn-nbctl nfg-add nfg0 1 vtap])
+AT_CHECK([ovn-nbctl nfg-add-nf nfg0 nf-inline], [1], [], [dnl
+ovn-nbctl: network-function nf-inline has outport set; outport must not be set 
for vtap mode network functions
+])
+AT_CHECK([ovn-nbctl nfg-del nfg0])
+AT_CHECK([ovn-nbctl nf-del nf-inline])
+AT_CHECK([ovn-nbctl nf-del nf0])
 ])
 
 AT_SETUP([ovn-nbctl - TLS server name indication (SNI) with --ssl-server-name])
diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml
index 6ce6f9322..ce09bdce5 100644
--- a/utilities/ovn-nbctl.8.xml
+++ b/utilities/ovn-nbctl.8.xml
@@ -475,17 +475,31 @@
     <h2>Network Function Commands</h2>
 
     <dl>
-      <dt>[<code>--may-exist</code>] <code>nf-add</code> <var>nf</var> 
<var>id</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 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.
+          <var>inport</var> and (optionally) <var>outport</var>. The ports must
+          be on the same logical switch and must be already created.
+        </p>
+
+        <p>
+          When the network function is used in an
+          <code>inline</code>-mode network function group, both
+          <var>inport</var> and <var>outport</var> must be specified.
+          Traffic matching the ACL is redirected to the <var>inport</var> for
+          from-lport ACLs and to the <var>outport</var> for to-lport ACLs.
+          The response packets are sent through the same ports in reverse
+          order.
+        </p>
+
+        <p>
+          When the network function is used in a <code>vtap</code>-mode
+          network function group, only <var>inport</var> is used; traffic
+          matching the ACL is mirrored (cloned) to <var>inport</var> in both
+          directions while the original packet continues to its destination.
+          <var>outport</var> must not be specified for vtap network functions.
         </p>
 
         <p>
@@ -517,16 +531,31 @@
         <p>
           Creates a new network function group named <var>nfg</var> with
           optionally one of more <code>nf</code> added to the group. The nfs
-          must be already created. Traffic redirection would be done towards
-          one of the active network functions, based on health monitoring.
-          If all are down, any one would be chosen for redirection.
+          must be already created. Traffic redirection/mirroring is performed
+          towards one of the active network functions, based on health
+          monitoring (inline) or port binding status (vtap). If all are down,
+          the configured fallback behavior applies.
         </p>
 
         <p>
           Each network function group must have a unique <var>id</var> between
-          <code>1</code> and <code>255</code>. The <var>mode</var> must be
-          <code>inline</code> which is currently the only supported mode.
-        </p>
+          <code>1</code> and <code>255</code>. The supported values for
+          <var>mode</var> are:
+        </p>
+
+        <ul>
+          <li>
+            <code>inline</code>: traffic matching the ACL is redirected
+            through the active network function. Both <code>inport</code> and
+            <code>outport</code> must be set on every member network function.
+          </li>
+          <li>
+            <code>vtap</code>: traffic matching the ACL is mirrored (cloned)
+            to the active network function while the original packet
+            continues to its destination. Only <code>inport</code> is used on
+            member network functions.
+          </li>
+        </ul>
 
         <p>
           Without any options, this command regards it as an error if
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index 4e2271d07..0c111a9fd 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -414,7 +414,7 @@ Network function group commands:\n\
 \n\
 Network function commands:\n\
   [--may-exist]\n\
-  nf-add NETWORK-FUNCTION ID PORT-IN PORT-OUT\n\
+  nf-add NETWORK-FUNCTION ID PORT-IN [PORT-OUT]\n\
                            create a network-function\n\
   [--if-exists]\n\
   nf-del NETWORK-FUNCTION  delete a network-function\n\
@@ -2248,6 +2248,8 @@ static void
 nbctl_pre_nf_group_add(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_inport);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_outport);
     ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
     ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_id);
     ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_mode);
@@ -2255,10 +2257,35 @@ nbctl_pre_nf_group_add(struct ctl_context *ctx)
         ctx->idl, &nbrec_network_function_group_col_network_function);
 }
 
+/* Validates that 'nf' is compatible with the given 'mode'.  In inline
+ * mode both inport and outport must be set; in vtap mode only inport is
+ * used and outport must not be set.  Returns NULL on success or a
+ * dynamically allocated error string on failure. */
+static char * OVS_WARN_UNUSED_RESULT
+nf_check_mode_compatibility(const struct nbrec_network_function *nf,
+                            const char *mode)
+{
+    if (!strcmp(mode, "vtap")) {
+        if (nf->outport) {
+            return xasprintf("network-function %s has outport set; outport "
+                             "must not be set for vtap mode network "
+                             "functions", nf->name);
+        }
+    } else { /* inline */
+        if (!nf->outport) {
+            return xasprintf("network-function %s has no outport set; "
+                             "outport is required for inline mode network "
+                             "functions", nf->name);
+        }
+    }
+    return NULL;
+}
+
 static char *
 set_network_function_in_network_function_group(
     struct ctl_context *ctx,
     const struct nbrec_network_function_group *nf_group,
+    const char *mode,
     char **new_network_function, size_t num_new_network_function)
 {
     struct nbrec_network_function **nfs =
@@ -2272,6 +2299,11 @@ set_network_function_in_network_function_group(
             free(nfs);
             return error;
         }
+        error = nf_check_mode_compatibility(nf, mode);
+        if (error) {
+            free(nfs);
+            return error;
+        }
         nfs[i] = CONST_CAST(struct nbrec_network_function *, nf);
     }
     nbrec_network_function_group_verify_network_function(nf_group);
@@ -2319,9 +2351,9 @@ nbctl_nf_group_add(struct ctl_context *ctx)
 
     /* Validate and set mode */
     const char *nfg_mode = ctx->argv[3];
-    if (strcmp(nfg_mode, "inline")) {
+    if (strcmp(nfg_mode, "inline") && strcmp(nfg_mode, "vtap")) {
         ctl_error(ctx, "Unsupported mode provided for "
-                  "network-function-group:%s, supported values: inline",
+                  "network-function-group:%s, supported values: inline, vtap",
                   nfg_name);
         return;
     }
@@ -2330,7 +2362,7 @@ nbctl_nf_group_add(struct ctl_context *ctx)
     /* Set network functions if provided */
     if (ctx->argc > 4) {
         ctx->error = set_network_function_in_network_function_group(
-            ctx, nf_group, ctx->argv + 4, ctx->argc - 4);
+            ctx, nf_group, nfg_mode, ctx->argv + 4, ctx->argc - 4);
     }
 }
 
@@ -2365,6 +2397,7 @@ nbctl_pre_nf_group_list(struct ctl_context *ctx)
     ovsdb_idl_add_column(ctx->idl,
                          &nbrec_network_function_group_col_network_function);
     ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_mode);
 }
 
 static void
@@ -2375,9 +2408,10 @@ nbctl_nf_group_list(struct ctl_context *ctx)
 
     NBREC_NETWORK_FUNCTION_GROUP_FOR_EACH (nf_group, ctx->idl) {
         smap_add_format(&nf_groups, nf_group->name,
-                        UUID_FMT " (%s)",
+                        UUID_FMT " (%s) mode:%s",
                         UUID_ARGS(&nf_group->header_.uuid),
-                        nf_group->name);
+                        nf_group->name,
+                        nf_group->mode ? nf_group->mode : "inline");
     }
     const struct smap_node **nodes = smap_sort(&nf_groups);
     for (size_t i = 0; i < smap_count(&nf_groups); i++) {
@@ -2394,7 +2428,10 @@ nbctl_pre_nf_group_add_network_function(struct 
ctl_context *ctx)
     ovsdb_idl_add_column(ctx->idl,
                          &nbrec_network_function_group_col_network_function);
     ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_mode);
     ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_inport);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_outport);
 }
 
 static void
@@ -2421,6 +2458,15 @@ nbctl_nf_group_add_network_function(struct ctl_context 
*ctx)
         return;
     }
 
+    /* Validate mode compatibility of the network function. */
+    const char *mode = nf_group->mode ? nf_group->mode : "inline";
+    error = nf_check_mode_compatibility(nf, mode);
+    if (error) {
+        ctl_error(ctx, "%s", error);
+        free(error);
+        return;
+    }
+
     /* Do not add network_function more than once in a given
      * network-function-group */
     for (size_t i = 0; i < nf_group->n_network_function; i++) {
@@ -2520,10 +2566,14 @@ nbctl_nf_add(struct ctl_context *ctx)
         ctx->error = error;
         return;
     }
-    error = lsp_by_name_or_uuid(ctx, ctx->argv[4], true, &lsp_out);
-    if (error) {
-        ctx->error = error;
-        return;
+    if (ctx->argc == 5) {
+        error = lsp_by_name_or_uuid(ctx, ctx->argv[4], true, &lsp_out);
+        if (error) {
+            ctx->error = error;
+            return;
+        }
+    } else {
+        lsp_out = NULL;
     }
 
     /* Validate and parse ID */
@@ -9367,7 +9417,7 @@ static const struct ctl_command_syntax nbctl_commands[] = 
{
       nbctl_nf_group_del_network_function, NULL, "--if-exists", RW },
 
     /* network-function commands. */
-    { "nf-add", 4, 4, "NETWORK-FUNCTION ID PORT-IN PORT-OUT",
+    { "nf-add", 3, 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