Re: [ovs-dev] [PATCH ovn] controller: Fix an issue wrt cleanup of stale patch port.

2024-04-19 Thread Dumitru Ceara
On 3/28/24 13:28, Priyankar Jain wrote:
> Issue:
> Upon updating the network_name option of localnet port from one physical
> bridge to another, ovn-controller fails to cleanup the peer localnet
> patch port from the old bridge and ends up creating a duplicate peer
> localnet patch port which fails in the following ovsdb transaction:
> 
> ```
> "Transaction causes multiple rows in \"Interface\" table to have
> identical values
> (patch-localnet_a7d47490-8a90-4c4d-8266-2915ad07c185-to-br-int)
> ```
> 
> Current workflow:
> 1. Keep a set of all existing localnet ports on br-int. Let us call this
>set: existing_ports.
> 2. For each localnet port in SB:
>2.1 Create a patch port on br-int. (if it already exists on br-int,
>do not create but remove the entry from exisitng_ports set).
>2.2 Create a peer patch port on br-phys-x. (if it already exists on the
>bridge, do not create but remove the entry from exisitng_ports set).
> 3. Finally, cleanup all the ports and its peers from exisiting_ports.
> 
> With the above workflow, upon network_name change of localnet LSP, since
> ports on br-int does not change, only peer port needs to be move from
> br-phys-x to br-phys-y, the localnet port is removed from
> exisiting_ports in #2.1 and its peer never becomes eligible for cleanup.
> 
> Fix:
> Include both patch port on br-int and its peer port in the
> exisiting_ports set as part of #1.
> This make sures that the peer port is only removed from existing_ports
> only if it is already present on the correct bridge. (#2.1/#2.2)
> Otherwise, during the cleanup in #3 it will be considered.
> 

Hi Priyankar,

Thanks for the patch!

> Fixes: b600316 ("Don't delete patch ports that don't belong to br-int")

This should actually be:

Fixes: b600316f252a ("Don't delete patch ports that don't belong to br-int")

> Signed-off-by: Priyankar Jain 
> ---
>  controller/patch.c |  32 +++--
>  tests/ovn.at   | 109 +
>  2 files changed, 124 insertions(+), 17 deletions(-)
> 
> diff --git a/controller/patch.c b/controller/patch.c
> index c1cd5060d..4fed6e375 100644
> --- a/controller/patch.c
> +++ b/controller/patch.c
> @@ -314,6 +314,21 @@ patch_run(struct ovsdb_idl_txn *ovs_idl_txn,
>  || smap_get(>external_ids, "ovn-l3gateway-port")
>  || smap_get(>external_ids, "ovn-logical-patch-port")) {
>  shash_add(_ports, port->name, port);
> +/* Also add peer ports to the list. */
> +for (size_t j = 0; j < port->n_interfaces; j++) {
> +struct ovsrec_interface *p_iface = port->interfaces[j];
> +if (strcmp(p_iface->type, "patch")) {
> +continue;
> +}
> +const char *peer_name = smap_get(_iface->options, "peer");
> +if (peer_name) {
> +const struct ovsrec_port *peer_port =
> +get_port(ovsrec_port_by_name, peer_name);
> +if (peer_port) {
> +shash_add(_ports, peer_port->name, 
> peer_port);
> +}
> +}
> +}
>  }
>  }
>  
> @@ -336,23 +351,6 @@ patch_run(struct ovsdb_idl_txn *ovs_idl_txn,
>   * ovn-controller.  Otherwise it may cause unncessary dataplane
>   * interruption during restart/upgrade. */
>  if (!daemon_started_recently()) {
> -/* delete peer patch port first */
> -for (size_t i = 0; i < port->n_interfaces; i++) {
> -struct ovsrec_interface *iface = port->interfaces[i];
> -if (strcmp(iface->type, "patch")) {
> -continue;
> -}
> -const char *iface_peer = smap_get(>options, "peer");
> -if (iface_peer) {
> -const struct ovsrec_port *peer_port =
> -get_port(ovsrec_port_by_name, iface_peer);
> -if (peer_port) {
> -remove_port(bridge_table, peer_port);
> -}
> -}
> -}
> -
> -/* now delete integration bridge patch port */
>  remove_port(bridge_table, port);
>  }
>  }

The fix looks correct to me.

> diff --git a/tests/ovn.at b/tests/ovn.at
> index 4d0c7ad53..487e727c0 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -36454,6 +36454,115 @@ OVN_CLEANUP([hv1])
>  AT_CLEANUP
>  ])
>  
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([ovn-controller update network_name option for localnet port])
> +ovn_start
> +net_add n1
> +
> +sim_add hv1
> +as hv1
> +
> +# Bridge Topology
> +# Initial: br-int and br-phys-1 connected through ovn-localnet patch port.
> +#
> +# br-phys-1 -- br-int
> +#
> +# Final: br-int and br-phys-3 connected through ovn-localnet patch port.
> +# Similarly br-int-2 and br-hys-2 connected through localnet patch port
> +# but not owned by this 

Re: [ovs-dev] [PATCH ovn] controller: Fix an issue wrt cleanup of stale patch port.

2024-03-28 Thread 0-day Robot
References:  <20240328122842.36708-1-priyankar.j...@nutanix.com>
 

Bleep bloop.  Greetings Priyankar Jain, I am a robot and I have tried out your 
patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


checkpatch:
ERROR: "Fixes" tag is malformed.
Use the following format:
  git log -1 --pretty=format:"Fixes: %h (\"%s\")" --abbrev=12 COMMIT_REF

39: Fixes: b600316 ("Don't delete patch ports that don't belong to br-int")

Lines checked: 220, Warnings: 0, Errors: 1


Please check this out.  If you feel there has been an error, please email 
acon...@redhat.com

Thanks,
0-day Robot
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn] controller: Fix an issue wrt cleanup of stale patch port.

2024-03-28 Thread Priyankar Jain
Issue:
Upon updating the network_name option of localnet port from one physical
bridge to another, ovn-controller fails to cleanup the peer localnet
patch port from the old bridge and ends up creating a duplicate peer
localnet patch port which fails in the following ovsdb transaction:

```
"Transaction causes multiple rows in \"Interface\" table to have
identical values
(patch-localnet_a7d47490-8a90-4c4d-8266-2915ad07c185-to-br-int)
```

Current workflow:
1. Keep a set of all existing localnet ports on br-int. Let us call this
   set: existing_ports.
2. For each localnet port in SB:
   2.1 Create a patch port on br-int. (if it already exists on br-int,
   do not create but remove the entry from exisitng_ports set).
   2.2 Create a peer patch port on br-phys-x. (if it already exists on the
   bridge, do not create but remove the entry from exisitng_ports set).
3. Finally, cleanup all the ports and its peers from exisiting_ports.

With the above workflow, upon network_name change of localnet LSP, since
ports on br-int does not change, only peer port needs to be move from
br-phys-x to br-phys-y, the localnet port is removed from
exisiting_ports in #2.1 and its peer never becomes eligible for cleanup.

Fix:
Include both patch port on br-int and its peer port in the
exisiting_ports set as part of #1.
This make sures that the peer port is only removed from existing_ports
only if it is already present on the correct bridge. (#2.1/#2.2)
Otherwise, during the cleanup in #3 it will be considered.

Fixes: b600316 ("Don't delete patch ports that don't belong to br-int")
Signed-off-by: Priyankar Jain 
---
 controller/patch.c |  32 +++--
 tests/ovn.at   | 109 +
 2 files changed, 124 insertions(+), 17 deletions(-)

diff --git a/controller/patch.c b/controller/patch.c
index c1cd5060d..4fed6e375 100644
--- a/controller/patch.c
+++ b/controller/patch.c
@@ -314,6 +314,21 @@ patch_run(struct ovsdb_idl_txn *ovs_idl_txn,
 || smap_get(>external_ids, "ovn-l3gateway-port")
 || smap_get(>external_ids, "ovn-logical-patch-port")) {
 shash_add(_ports, port->name, port);
+/* Also add peer ports to the list. */
+for (size_t j = 0; j < port->n_interfaces; j++) {
+struct ovsrec_interface *p_iface = port->interfaces[j];
+if (strcmp(p_iface->type, "patch")) {
+continue;
+}
+const char *peer_name = smap_get(_iface->options, "peer");
+if (peer_name) {
+const struct ovsrec_port *peer_port =
+get_port(ovsrec_port_by_name, peer_name);
+if (peer_port) {
+shash_add(_ports, peer_port->name, peer_port);
+}
+}
+}
 }
 }
 
@@ -336,23 +351,6 @@ patch_run(struct ovsdb_idl_txn *ovs_idl_txn,
  * ovn-controller.  Otherwise it may cause unncessary dataplane
  * interruption during restart/upgrade. */
 if (!daemon_started_recently()) {
-/* delete peer patch port first */
-for (size_t i = 0; i < port->n_interfaces; i++) {
-struct ovsrec_interface *iface = port->interfaces[i];
-if (strcmp(iface->type, "patch")) {
-continue;
-}
-const char *iface_peer = smap_get(>options, "peer");
-if (iface_peer) {
-const struct ovsrec_port *peer_port =
-get_port(ovsrec_port_by_name, iface_peer);
-if (peer_port) {
-remove_port(bridge_table, peer_port);
-}
-}
-}
-
-/* now delete integration bridge patch port */
 remove_port(bridge_table, port);
 }
 }
diff --git a/tests/ovn.at b/tests/ovn.at
index 4d0c7ad53..487e727c0 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -36454,6 +36454,115 @@ OVN_CLEANUP([hv1])
 AT_CLEANUP
 ])
 
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn-controller update network_name option for localnet port])
+ovn_start
+net_add n1
+
+sim_add hv1
+as hv1
+
+# Bridge Topology
+# Initial: br-int and br-phys-1 connected through ovn-localnet patch port.
+#
+# br-phys-1 -- br-int
+#
+# Final: br-int and br-phys-3 connected through ovn-localnet patch port.
+# Similarly br-int-2 and br-hys-2 connected through localnet patch port
+# but not owned by this controller.
+#
+# br-phys-1  br-int -- br-phys-3
+# br-int-2 -- br-phys-2
+
+# Create bridges
+ovs-vsctl add-br br-int
+ovs-vsctl add-br br-int-2
+ovs-vsctl add-br br-phys-1
+ovs-vsctl add-br br-phys-2
+ovs-vsctl add-br br-phys-3
+ovs-vsctl set open . 
external-ids:ovn-bridge-mappings-hv1=phys-1:br-phys-1,phy-2:br-phys-2,phys-3:br-phys-3
+
+ovn_attach n1 br-phys-1 192.168.1.1 24
+
+ovs-vsctl -- add-port br-int vif1 -- \
+set interface vif1