On Wed, Dec 14, 2022 at 7:40 PM Ihar Hrachyshka <[email protected]> wrote:
>
> Acked-By: Ihar Hrachyshka <[email protected]>
Thanks Ihar for the reviews.
I applied this patch with the below small changes
---------------------------------------------------------------------------------
diff --git a/ovn-nb.xml b/ovn-nb.xml
index c2d05c6ef4..4cceef14e0 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2594,8 +2594,8 @@ or
<table name="Mirror" title="Mirror Entry">
<p>
- Each row in this table represents one Mirror that can be used for
- port mirroring. These Mirrors are referenced by the
+ Each row in this table represents a mirror that can be used for
+ port mirroring. These mirrors are referenced by the
<ref column="mirror_rules" table="Logical_Switch_Port"/> column in
the <ref table="Logical_Switch_Port"/> table.
</p>
@@ -2609,9 +2609,8 @@ or
<column name="filter">
<p>
The value of this field represents selection criteria of the mirror.
- Supported values for filter to-lport / from-lport
- to-lport - to mirror packets coming into logical port
- from-lport - to mirror packets going out of logical port.
+ <code>to-lport</code> mirrors the packets coming into logical port.
+ <code>from-lport</code> mirrors the packets going out of logical port.
</p>
</column>
@@ -2625,15 +2624,16 @@ or
<column name="type">
<p>
The value of this field represents the type of the tunnel used for
- sending the mirrored packets. Supported Tunnel types gre and erspan
+ sending the mirrored packets.
</p>
</column>
<column name="index">
<p>
- The value of this field represents the tunnel ID. Depending on the
- tunnel type configured, GRE key value if type GRE and erspan_idx value
- if ERSPAN
+ The value of this field represents the tunnel ID. If the configured
+ tunnel type is <code>gre</code>, this field represents the
+ <code>GRE</code> key value and if the configured tunnel type is
+ <code>erspan</code> it represents the <code>erspan_idx</code> value.
</p>
</column>
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index d25b60e786..9d4fb8c757 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -1785,7 +1785,6 @@ nbctl_lsp_attach_mirror(struct ctl_context *ctx)
ctl_error(ctx, "mirror %s is already attached to the "
"logical port %s.",
lsp->mirror_rules[i]->name, ctx->argv[1]);
- return;
}
return;
}
-------------------------------------------------
Numan
>
> On Tue, Dec 13, 2022 at 2:33 PM Abhiram R N <[email protected]> wrote:
> >
> > In order to support Remote Port Mirroring
> > added the required schemas in NB and related xml.
> > Also, ovn-nbctl.c changes are added.
> > Futher added test cases to test nbctl commands.
> >
> > Co-authored-by: Veda Barrenkala <[email protected]>
> > Signed-off-by: Veda Barrenkala <[email protected]>
> > Signed-off-by: Abhiram R N <[email protected]>
> > Acked-By: Ihar Hrachyshka <[email protected]>
> > ---
> > ovn-nb.ovsschema | 25 ++-
> > ovn-nb.xml | 55 +++++++
> > tests/ovn-nbctl.at | 102 ++++++++++++
> > utilities/ovn-nbctl.8.xml | 51 ++++++
> > utilities/ovn-nbctl.c | 334 ++++++++++++++++++++++++++++++++++++++
> > 5 files changed, 565 insertions(+), 2 deletions(-)
> >
> > diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
> > index 6f9d38f47..4836a219f 100644
> > --- a/ovn-nb.ovsschema
> > +++ b/ovn-nb.ovsschema
> > @@ -1,7 +1,7 @@
> > {
> > "name": "OVN_Northbound",
> > - "version": "6.4.0",
> > - "cksum": "3512158873 32360",
> > + "version": "7.0.0",
> > + "cksum": "94023179 33468",
> > "tables": {
> > "NB_Global": {
> > "columns": {
> > @@ -132,6 +132,11 @@
> > "refType": "weak"},
> > "min": 0,
> > "max": 1}},
> > + "mirror_rules": {"type": {"key": {"type": "uuid",
> > + "refTable": "Mirror",
> > + "refType": "weak"},
> > + "min": 0,
> > + "max": "unlimited"}},
> > "ha_chassis_group": {
> > "type": {"key": {"type": "uuid",
> > "refTable": "HA_Chassis_Group",
> > @@ -301,6 +306,22 @@
> > "type": {"key": "string", "value": "string",
> > "min": 0, "max": "unlimited"}}},
> > "isRoot": false},
> > + "Mirror": {
> > + "columns": {
> > + "name": {"type": "string"},
> > + "filter": {"type": {"key": {"type": "string",
> > + "enum": ["set", ["from-lport",
> > +
> > "to-lport"]]}}},
> > + "sink":{"type": "string"},
> > + "type": {"type": {"key": {"type": "string",
> > + "enum": ["set", ["gre",
> > + "erspan"]]}}},
> > + "index": {"type": "integer"},
> > + "external_ids": {
> > + "type": {"key": "string", "value": "string",
> > + "min": 0, "max": "unlimited"}}},
> > + "indexes": [["name"]],
> > + "isRoot": true},
> > "Meter": {
> > "columns": {
> > "name": {"type": "string"},
> > diff --git a/ovn-nb.xml b/ovn-nb.xml
> > index 0edc3da96..c2d05c6ef 100644
> > --- a/ovn-nb.xml
> > +++ b/ovn-nb.xml
> > @@ -1582,6 +1582,11 @@
> > </column>
> > </group>
> >
> > + <column name="mirror_rules">
> > + Mirror rules that apply to logical switch port which is the source.
> > + Please see the <ref table="Mirror"/> table.
> > + </column>
> > +
> > <column name="ha_chassis_group">
> > References a row in the OVN Northbound database's
> > <ref table="HA_Chassis_Group" db="OVN_Northbound"/> table.
> > @@ -2587,6 +2592,56 @@ or
> > </column>
> > </table>
> >
> > + <table name="Mirror" title="Mirror Entry">
> > + <p>
> > + Each row in this table represents one Mirror that can be used for
> > + port mirroring. These Mirrors are referenced by the
> > + <ref column="mirror_rules" table="Logical_Switch_Port"/> column in
> > + the <ref table="Logical_Switch_Port"/> table.
> > + </p>
> > +
> > + <column name="name">
> > + <p>
> > + Represents the name of the mirror.
> > + </p>
> > + </column>
> > +
> > + <column name="filter">
> > + <p>
> > + The value of this field represents selection criteria of the
> > mirror.
> > + Supported values for filter to-lport / from-lport
> > + to-lport - to mirror packets coming into logical port
> > + from-lport - to mirror packets going out of logical port.
> > + </p>
> > + </column>
> > +
> > + <column name="sink">
> > + <p>
> > + The value of this field represents the destination/sink of the
> > mirror.
> > + The value it takes is an IP address of the sink port.
> > + </p>
> > + </column>
> > +
> > + <column name="type">
> > + <p>
> > + The value of this field represents the type of the tunnel used for
> > + sending the mirrored packets. Supported Tunnel types gre and erspan
> > + </p>
> > + </column>
> > +
> > + <column name="index">
> > + <p>
> > + The value of this field represents the tunnel ID. Depending on the
> > + tunnel type configured, GRE key value if type GRE and erspan_idx
> > value
> > + if ERSPAN
> > + </p>
> > + </column>
> > +
> > + <column name="external_ids">
> > + See <em>External IDs</em> at the beginning of this document.
> > + </column>
> > + </table>
> > +
> > <table name="Meter" title="Meter entry">
> > <p>
> > Each row in this table represents a meter that can be used for QoS or
> > diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
> > index 91d8d338e..8885ac9fc 100644
> > --- a/tests/ovn-nbctl.at
> > +++ b/tests/ovn-nbctl.at
> > @@ -435,6 +435,108 @@ AT_CHECK([ovn-nbctl meter-list], [0], [dnl
> >
> > dnl ---------------------------------------------------------------------
> >
> > +OVN_NBCTL_TEST([ovn_nbctl_mirrors], [mirrors], [
> > +check ovn-nbctl mirror-add mirror1 gre 0 from-lport 10.10.10.1
> > +check ovn-nbctl mirror-add mirror2 erspan 1 to-lport 10.10.10.2
> > +check ovn-nbctl mirror-add mirror3 gre 2 to-lport 10.10.10.3
> > +check ovn-nbctl ls-add sw0
> > +check ovn-nbctl lsp-add sw0 sw0-port1
> > +check ovn-nbctl lsp-add sw0 sw0-port2
> > +check ovn-nbctl lsp-add sw0 sw0-port3
> > +
> > +dnl Add duplicate mirror name
> > +AT_CHECK([ovn-nbctl mirror-add mirror1 gre 0 from-lport 10.10.10.5], [1],
> > [], [stderr])
> > +AT_CHECK([grep 'already exists' stderr], [0], [ignore])
> > +
> > +dnl Attach invalid source port to mirror
> > +AT_CHECK([ovn-nbctl lsp-attach-mirror sw0-port4 mirror3], [1], [],
> > [stderr])
> > +AT_CHECK([grep 'port name not found' stderr], [0], [ignore])
> > +
> > +dnl Attach source port to invalid mirror
> > +AT_CHECK([ovn-nbctl lsp-attach-mirror sw0-port3 mirror4], [1], [],
> > [stderr])
> > +AT_CHECK([grep 'mirror name not found' stderr], [0], [ignore])
> > +
> > +mirror3uuid=$(fetch_column nb:Mirror _uuid name=mirror3)
> > +dnl Attach source port to mirror
> > +check ovn-nbctl lsp-attach-mirror sw0-port1 mirror3
> > +check_column "$mirror3uuid" nb:Logical_Switch_Port mirror_rules
> > name=sw0-port1
> > +
> > +dnl Attach one more source port to mirror
> > +check ovn-nbctl lsp-attach-mirror sw0-port3 mirror3
> > +check_column "$mirror3uuid" nb:Logical_Switch_Port mirror_rules
> > name=sw0-port3
> > +
> > +dnl Verify if multiple ports are attached to the same mirror properly
> > +AT_CHECK([ovn-nbctl mirror-list], [0], [dnl
> > +mirror1:
> > + Type : gre
> > + Sink : 10.10.10.1
> > + Filter : from-lport
> > + Index/Key: 0
> > +
> > +mirror2:
> > + Type : erspan
> > + Sink : 10.10.10.2
> > + Filter : to-lport
> > + Index/Key: 1
> > +
> > +mirror3:
> > + Type : gre
> > + Sink : 10.10.10.3
> > + Filter : to-lport
> > + Index/Key: 2
> > +
> > +])
> > +
> > +dnl Detach one source port from mirror
> > +check ovn-nbctl lsp-detach-mirror sw0-port3 mirror3
> > +
> > +dnl Check if the detach happened from source properly
> > +check_column "" nb:Logical_Switch_Port mirror_rules name=sw0-port3
> > +
> > +dnl Delete a single mirror which has source attached.
> > +check ovn-nbctl mirror-del mirror3
> > +
> > +dnl Check if the detach happened from source properly
> > +check_column "" nb:Logical_Switch_Port mirror_rules name=sw0-port1
> > +
> > +dnl Check if the mirror deleted properly
> > +AT_CHECK([ovn-nbctl mirror-list], [0], [dnl
> > +mirror1:
> > + Type : gre
> > + Sink : 10.10.10.1
> > + Filter : from-lport
> > + Index/Key: 0
> > +
> > +mirror2:
> > + Type : erspan
> > + Sink : 10.10.10.2
> > + Filter : to-lport
> > + Index/Key: 1
> > +
> > +])
> > +
> > +dnl Delete another mirror
> > +check ovn-nbctl mirror-del mirror2
> > +
> > +dnl Update the Sink address
> > +check ovn-nbctl set mirror . sink=192.168.1.13
> > +
> > +AT_CHECK([ovn-nbctl mirror-list], [0], [dnl
> > +mirror1:
> > + Type : gre
> > + Sink : 192.168.1.13
> > + Filter : from-lport
> > + Index/Key: 0
> > +
> > +])
> > +
> > +dnl Delete all mirrors
> > +check ovn-nbctl mirror-del
> > +AT_CHECK([ovn-nbctl mirror-list], [0], [dnl
> > +])])
> > +
> > +dnl ---------------------------------------------------------------------
> > +
> > OVN_NBCTL_TEST([ovn_nbctl_nats], [NATs], [
> > AT_CHECK([ovn-nbctl lr-add lr0])
> > AT_CHECK([ovn-nbctl lr-nat-add lr0 snatt 30.0.0.2 192.168.1.2], [1], [],
> > diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml
> > index 5f9eb186b..92e10c012 100644
> > --- a/utilities/ovn-nbctl.8.xml
> > +++ b/utilities/ovn-nbctl.8.xml
> > @@ -809,6 +809,15 @@
> > Get the logical switch which the <var>port</var> belongs to.
> > </dd>
> >
> > + <dt><code>lsp-attach-mirror</code> <var>port</var> <var>m</var></dt>
> > + <dd>
> > + Attaches the mirror <var>m</var> to the logical port
> > <var>port</var>.
> > + </dd>
> > +
> > + <dt><code>lsp-dettach-mirror</code> <var>port</var> <var>m</var></dt>
> > + <dd>
> > + Detaches the mirror <var>m</var> from the logical port
> > <var>port</var>.
> > + </dd>
> > </dl>
> >
> > <h2>Forwarding Group Commands</h2>
> > @@ -1534,6 +1543,48 @@
> > </dd>
> > </dl>
> >
> > + <h2> Mirror commands</h2>
> > + <dl>
> > + <dt><code>mirror-add</code> <var>m</var> <var>type</var>
> > + <var>index</var> <var>filter</var> <var>dest</var></dt>
> > + <dd>
> > + <p>
> > + Creates a new mirror in the <code>Mirror</code>
> > + table with the name <code>m</code> with the below mandatory
> > + arguments.
> > + </p>
> > +
> > + <p>
> > + <var>type</var> specifies the mirror type - <code>gre</code>
> > + or <code>erspan</code>.
> > + </p>
> > +
> > + <p>
> > + <var>index</var> specifies the tunnel index value (which is
> > + an integer).
> > + </p>
> > +
> > + <p>
> > + <var>filter</var> specifies the mirror source selection.
> > + Can be <code>from-lport</code> or <code>to-lport</code>.
> > + </p>
> > +
> > + <p>
> > + <var>dest</var> specifies the mirror destination IP (v4 or v6).
> > + </p>
> > + </dd>
> > +
> > + <dt><code>mirror-del</code> <var>m</var></dt>
> > + <dd>
> > + Deletes the mirror <code>m</code>.
> > + </dd>
> > +
> > + <dt><code>mirror-list</code></dt>
> > + <dd>
> > + Lists the mirrors.
> > + </dd>
> > + </dl>
> > +
> > <h2>Synchronization Commands</h2>
> >
> > <dl>
> > diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
> > index 3bc4a8d82..d25b60e78 100644
> > --- a/utilities/ovn-nbctl.c
> > +++ b/utilities/ovn-nbctl.c
> > @@ -272,6 +272,19 @@ QoS commands:\n\
> > remove QoS rules from SWITCH\n\
> > qos-list SWITCH print QoS rules for SWITCH\n\
> > \n\
> > +Mirror commands:\n\
> > + mirror-add NAME TYPE INDEX FILTER IP\n\
> > + add a mirror with given name\n\
> > + specify TYPE 'gre' or 'erspan'\n\
> > + specify the tunnel INDEX value\n\
> > + (indicates key if GRE\n\
> > + erpsan_idx if ERSPAN)\n\
> > + specify FILTER for mirroring selection\n\
> > + 'to-lport' / 'from-lport'\n\
> > + specify Sink / Destination i.e. Remote IP\n\
> > + mirror-del [NAME] remove mirrors\n\
> > + mirror-list print mirrors\n\
> > +\n\
> > Meter commands:\n\
> > [--fair]\n\
> > meter-add NAME ACTION RATE UNIT [BURST]\n\
> > @@ -312,6 +325,8 @@ Logical switch port commands:\n\
> > set dhcpv6 options for PORT\n\
> > lsp-get-dhcpv6-options PORT get the dhcpv6 options for PORT\n\
> > lsp-get-ls PORT get the logical switch which the port belongs
> > to\n\
> > + lsp-attach-mirror PORT MIRROR attach source PORT to MIRROR\n\
> > + lsp-detach-mirror PORT MIRROR detach source PORT from MIRROR\n\
> > \n\
> > Forwarding group commands:\n\
> > [--liveness]\n\
> > @@ -1686,6 +1701,126 @@ nbctl_pre_lsp_type(struct ctl_context *ctx)
> > ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_type);
> > }
> >
> > +static void
> > +nbctl_pre_lsp_mirror(struct ctl_context *ctx)
> > +{
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name);
> > + ovsdb_idl_add_column(ctx->idl,
> > + &nbrec_logical_switch_port_col_mirror_rules);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_name);
> > +}
> > +
> > +static int
> > +mirror_cmp(const void *mirror1_, const void *mirror2_)
> > +{
> > + const struct nbrec_mirror *const *mirror_1 = mirror1_;
> > + const struct nbrec_mirror *const *mirror_2 = mirror2_;
> > +
> > + const struct nbrec_mirror *mirror1 = *mirror_1;
> > + const struct nbrec_mirror *mirror2 = *mirror_2;
> > +
> > + return strcmp(mirror1->name, mirror2->name);
> > +}
> > +
> > +static char * OVS_WARN_UNUSED_RESULT
> > +mirror_by_name_or_uuid(struct ctl_context *ctx, const char *id,
> > + bool must_exist,
> > + const struct nbrec_mirror **mirror_p)
> > +{
> > + const struct nbrec_mirror *mirror = NULL;
> > + *mirror_p = NULL;
> > +
> > + struct uuid mirror_uuid;
> > + bool is_uuid = uuid_from_string(&mirror_uuid, id);
> > + if (is_uuid) {
> > + mirror = nbrec_mirror_get_for_uuid(ctx->idl, &mirror_uuid);
> > + }
> > +
> > + if (!mirror) {
> > + NBREC_MIRROR_FOR_EACH (mirror, ctx->idl) {
> > + if (!strcmp(mirror->name, id)) {
> > + break;
> > + }
> > + }
> > + }
> > +
> > + if (!mirror && must_exist) {
> > + return xasprintf("%s: mirror %s not found",
> > + id, is_uuid ? "UUID" : "name");
> > + }
> > +
> > + *mirror_p = mirror;
> > + return NULL;
> > +}
> > +
> > +static void
> > +nbctl_lsp_attach_mirror(struct ctl_context *ctx)
> > +{
> > + const char *port = ctx->argv[1];
> > + const char *mirror_name = ctx->argv[2];
> > + const struct nbrec_logical_switch_port *lsp = NULL;
> > + const struct nbrec_mirror *mirror;
> > +
> > + char *error;
> > +
> > + error = lsp_by_name_or_uuid(ctx, port, true, &lsp);
> > + if (error) {
> > + ctx->error = error;
> > + return;
> > + }
> > +
> > + /*check if a mirror rule actually exists on that name or not*/
> > + error = mirror_by_name_or_uuid(ctx, mirror_name, true, &mirror);
> > + if (error) {
> > + ctx->error = error;
> > + return;
> > + }
> > +
> > + /* Check if same mirror rule already exists for the lsp */
> > + for (size_t i = 0; i < lsp->n_mirror_rules; i++) {
> > + if (uuid_equals(&lsp->mirror_rules[i]->header_.uuid,
> > + &mirror->header_.uuid)) {
> > + bool may_exist = shash_find(&ctx->options, "--may-exist") !=
> > NULL;
> > + if (!may_exist) {
> > + ctl_error(ctx, "mirror %s is already attached to the "
> > + "logical port %s.",
> > + lsp->mirror_rules[i]->name, ctx->argv[1]);
> > + return;
> > + }
> > + return;
> > + }
> > + }
> > +
> > + nbrec_logical_switch_port_update_mirror_rules_addvalue(lsp, mirror);
> > +}
> > +
> > +static void
> > +nbctl_lsp_detach_mirror(struct ctl_context *ctx)
> > +{
> > + const char *port = ctx->argv[1];
> > + const char *mirror_name = ctx->argv[2];
> > + const struct nbrec_logical_switch_port *lsp = NULL;
> > + const struct nbrec_mirror *mirror;
> > +
> > + char *error;
> > +
> > + error = lsp_by_name_or_uuid(ctx, port, true, &lsp);
> > + if (error) {
> > + ctx->error = error;
> > + return;
> > + }
> > +
> > +
> > + /*check if a mirror rule actually exists on that name or not*/
> > + error = mirror_by_name_or_uuid(ctx, mirror_name, true, &mirror);
> > + if (error) {
> > + ctx->error = error;
> > + return;
> > + }
> > +
> > + nbrec_logical_switch_port_update_mirror_rules_delvalue(lsp, mirror);
> > +}
> > +
> > static void
> > nbctl_lsp_set_type(struct ctl_context *ctx)
> > {
> > @@ -7250,6 +7385,192 @@ cmd_ha_ch_grp_set_chassis_prio(struct ctl_context
> > *ctx)
> > nbrec_ha_chassis_set_priority(ha_chassis, priority);
> > }
> >
> > +static char * OVS_WARN_UNUSED_RESULT
> > +parse_mirror_filter(const char *arg, const char **selection_p)
> > +{
> > + /* Validate selection. Only require the first letter. */
> > + if (arg[0] == 't') {
> > + *selection_p = "to-lport";
> > + } else if (arg[0] == 'f') {
> > + *selection_p = "from-lport";
> > + } else {
> > + *selection_p = NULL;
> > + return xasprintf("%s: selection must be \"to-lport\" or "
> > + "\"from-lport\"", arg);
> > + }
> > + return NULL;
> > +}
> > +
> > +static char * OVS_WARN_UNUSED_RESULT
> > +parse_mirror_tunnel_type(const char *arg, const char **type_p)
> > +{
> > + /* Validate type. Only require the first letter. */
> > + if (arg[0] == 'g') {
> > + *type_p = "gre";
> > + } else if (arg[0] == 'e') {
> > + *type_p = "erspan";
> > + } else {
> > + *type_p = NULL;
> > + return xasprintf("%s: type must be \"gre\" or "
> > + "\"erspan\"", arg);
> > + }
> > + return NULL;
> > +}
> > +
> > +static void
> > +nbctl_pre_mirror_add(struct ctl_context *ctx)
> > +{
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_name);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_filter);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_index);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_sink);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_type);
> > +}
> > +
> > +static void
> > +nbctl_mirror_add(struct ctl_context *ctx)
> > +{
> > + const char *filter = NULL;
> > + const char *sink_ip = NULL;
> > + const char *type = NULL;
> > + const char *name = NULL;
> > + char *new_sink_ip = NULL;
> > + int64_t index;
> > + char *error = NULL;
> > + const struct nbrec_mirror *mirror_check = NULL;
> > +
> > + /* Mirror Name */
> > + name = ctx->argv[1];
> > + NBREC_MIRROR_FOR_EACH (mirror_check, ctx->idl) {
> > + if (!strcmp(mirror_check->name, name)) {
> > + ctl_error(ctx, "Mirror with %s name already exists.",
> > + name);
> > + return;
> > + }
> > + }
> > +
> > + /* Tunnel Type - GRE/ERSPAN */
> > + error = parse_mirror_tunnel_type(ctx->argv[2], &type);
> > + if (error) {
> > + ctx->error = error;
> > + return;
> > + }
> > +
> > + /* tunnel index / GRE key / ERSPAN idx */
> > + if (!str_to_long(ctx->argv[3], 10, (long int *) &index)) {
> > + ctl_error(ctx, "Invalid Index");
> > + return;
> > + }
> > +
> > + /* Filter for mirroring */
> > + error = parse_mirror_filter(ctx->argv[4], &filter);
> > + if (error) {
> > + ctx->error = error;
> > + return;
> > + }
> > +
> > + /* Destination / Sink details */
> > + sink_ip = ctx->argv[5];
> > +
> > + /* check if it is a valid ip */
> > + new_sink_ip = normalize_ipv4_addr_str(sink_ip);
> > + if (!new_sink_ip) {
> > + new_sink_ip = normalize_ipv6_addr_str(sink_ip);
> > + }
> > +
> > + if (!new_sink_ip) {
> > + ctl_error(ctx, "Invalid sink ip: %s", sink_ip);
> > + return;
> > + }
> > + free(new_sink_ip);
> > +
> > + /* Create the mirror. */
> > + struct nbrec_mirror *mirror = nbrec_mirror_insert(ctx->txn);
> > + nbrec_mirror_set_name(mirror, name);
> > + nbrec_mirror_set_index(mirror, index);
> > + nbrec_mirror_set_filter(mirror, filter);
> > + nbrec_mirror_set_type(mirror, type);
> > + nbrec_mirror_set_sink(mirror, sink_ip);
> > +
> > +}
> > +
> > +static void
> > +nbctl_pre_mirror_del(struct ctl_context *ctx)
> > +{
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_name);
> > +}
> > +
> > +static void
> > +nbctl_mirror_del(struct ctl_context *ctx)
> > +{
> > + const struct nbrec_mirror *mirror, *next;
> > +
> > + /* If a name is not specified, delete all mirrors. */
> > + if (ctx->argc == 1) {
> > + NBREC_MIRROR_FOR_EACH_SAFE (mirror, next, ctx->idl) {
> > + nbrec_mirror_delete(mirror);
> > + }
> > + return;
> > + }
> > +
> > + /* Remove the matching mirror. */
> > + NBREC_MIRROR_FOR_EACH (mirror, ctx->idl) {
> > + if (strcmp(ctx->argv[1], mirror->name)) {
> > + continue;
> > + }
> > + nbrec_mirror_delete(mirror);
> > + return;
> > + }
> > +}
> > +
> > +static void
> > +nbctl_pre_mirror_list(struct ctl_context *ctx)
> > +{
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_name);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_filter);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_index);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_sink);
> > + ovsdb_idl_add_column(ctx->idl, &nbrec_mirror_col_type);
> > +}
> > +
> > +static void
> > +nbctl_mirror_list(struct ctl_context *ctx)
> > +{
> > +
> > + const struct nbrec_mirror **mirrors = NULL;
> > + const struct nbrec_mirror *mirror;
> > + size_t n_capacity = 0;
> > + size_t n_mirrors = 0;
> > +
> > + NBREC_MIRROR_FOR_EACH (mirror, ctx->idl) {
> > + if (n_mirrors == n_capacity) {
> > + mirrors = x2nrealloc(mirrors, &n_capacity, sizeof *mirrors);
> > + }
> > +
> > + mirrors[n_mirrors] = mirror;
> > + n_mirrors++;
> > + }
> > +
> > + if (n_mirrors) {
> > + qsort(mirrors, n_mirrors, sizeof *mirrors, mirror_cmp);
> > + }
> > +
> > + for (size_t i = 0; i < n_mirrors; i++) {
> > + mirror = mirrors[i];
> > + ds_put_format(&ctx->output, "%s:\n", mirror->name);
> > + /* print all the values */
> > + ds_put_format(&ctx->output, " Type : %s\n", mirror->type);
> > + ds_put_format(&ctx->output, " Sink : %s\n", mirror->sink);
> > + ds_put_format(&ctx->output, " Filter : %s\n", mirror->filter);
> > + ds_put_format(&ctx->output, " Index/Key: %ld\n",
> > + (long int) mirror->index);
> > + ds_put_cstr(&ctx->output, "\n");
> > + }
> > +
> > + free(mirrors);
> > +}
> > +
> > static const struct ctl_table_class tables[NBREC_N_TABLES] = {
> > [NBREC_TABLE_DHCP_OPTIONS].row_ids
> > = {{&nbrec_logical_switch_port_col_name, NULL,
> > @@ -7346,6 +7667,15 @@ static const struct ctl_command_syntax
> > nbctl_commands[] = {
> > { "qos-list", 1, 1, "SWITCH", nbctl_pre_qos_list, nbctl_qos_list,
> > NULL, "", RO },
> >
> > + /* mirror commands. */
> > + { "mirror-add", 5, 5,
> > + "NAME TYPE INDEX FILTER IP",
> > + nbctl_pre_mirror_add, nbctl_mirror_add, NULL, "--may-exist", RW },
> > + { "mirror-del", 0, 1, "[NAME]",
> > + nbctl_pre_mirror_del, nbctl_mirror_del, NULL, "", RW },
> > + { "mirror-list", 0, 0, "", nbctl_pre_mirror_list, nbctl_mirror_list,
> > + NULL, "", RO },
> > +
> > /* meter commands. */
> > { "meter-add", 4, 5, "NAME ACTION RATE UNIT [BURST]",
> > nbctl_pre_meter_add,
> > nbctl_meter_add, NULL, "--fair,--may-exist", RW },
> > @@ -7400,6 +7730,10 @@ static const struct ctl_command_syntax
> > nbctl_commands[] = {
> > nbctl_lsp_get_dhcpv6_options, NULL, "", RO },
> > { "lsp-get-ls", 1, 1, "PORT", nbctl_pre_lsp_get_ls, nbctl_lsp_get_ls,
> > NULL, "", RO },
> > + { "lsp-attach-mirror", 2, 2, "PORT MIRROR", nbctl_pre_lsp_mirror,
> > + nbctl_lsp_attach_mirror, NULL, "--may-exist", RW },
> > + { "lsp-detach-mirror", 2, 2, "PORT MIRROR", nbctl_pre_lsp_mirror,
> > + nbctl_lsp_detach_mirror, NULL, "", RW },
> >
> > /* forwarding group commands. */
> > { "fwd-group-add", 4, INT_MAX, "SWITCH GROUP VIP VMAC PORT...",
> > --
> > 2.31.1
> >
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev