Hi Ales

Thanks for the review and the comments.
Some comments below.

On Mon, Feb 17, 2025 at 3:21 PM Ales Musil <[email protected]> wrote:

>
>
> On Thu, Feb 13, 2025 at 5:01 PM Xavier Simonart <[email protected]>
> wrote:
>
>> Handle container ports migration in a similar way as vif migration.
>> When a container port is migrated (i.e. when requested-chassis is
>> configured
>> for its parent port), install flows in both src and dst hypervisors.
>> When migration completes, remove flows from src hypervisor.
>>
>> Reported-at: https://issues.redhat.com/browse/FDP-1037
>>
>> Signed-off-by: Xavier Simonart <[email protected]>
>> ---
>>
>
> Hi Xavier,
>
> thank you for the patch, I have a couple of comments down below.
>
>
>  controller/binding.c  |  44 +++++---
>>  controller/physical.c |   4 +-
>>  tests/multinode.at    | 257 ++++++++++++++++++++++++++++++++++++++++++
>>  tests/ovn.at          | 160 +++++++++++++++++++++++++-
>>  4 files changed, 447 insertions(+), 18 deletions(-)
>>
>> diff --git a/controller/binding.c b/controller/binding.c
>> index 7d4143008..7f1027b02 100644
>> --- a/controller/binding.c
>> +++ b/controller/binding.c
>> @@ -1147,6 +1147,9 @@ set_pb_chassis_in_sbrec(const struct
>> sbrec_port_binding *pb,
>>                  VLOG_INFO("%s: Claiming %s", pb->logical_port,
>> pb->mac[i]);
>>              }
>>              sbrec_port_binding_set_chassis(pb, chassis_rec);
>> +            if (is_additional_chassis(pb, chassis_rec)) {
>> +                remove_additional_chassis(pb, chassis_rec);
>> +            }
>>
>
>
> This feels like a separate issue or am I missing something?
>
You're right. In fact, as such this change is not strictly necessary as the
removal from additional chassis is done in claim_lport. However, moving it
to here would
avoid some potential recompute if sb is read only in claim_lport. But as
you said, this should not be part of this patch.
So, I'll remove it in v2.

>
>          }
>>      } else if (!is_set) {
>>          sbrec_port_binding_set_chassis(pb, NULL);
>> @@ -1357,9 +1360,9 @@ claim_lport(const struct sbrec_port_binding *pb,
>>              bool sb_readonly, bool is_vif,
>>              struct hmap *tracked_datapaths,
>>              struct if_status_mgr *if_mgr,
>> -            struct sset *postponed_ports)
>> +            struct sset *postponed_ports,
>> +            enum can_bind can_bind)
>>  {
>> -    enum can_bind can_bind = lport_can_bind_on_this_chassis(chassis_rec,
>> pb);
>>      bool update_tracked = false;
>>
>>      if (can_bind == CAN_BIND_AS_MAIN) {
>> @@ -1561,7 +1564,7 @@ release_binding_lport(const struct sbrec_chassis
>> *chassis_rec,
>>
>>  static bool
>>  consider_vif_lport_(const struct sbrec_port_binding *pb,
>> -                    bool can_bind,
>> +                    enum can_bind can_bind,
>>                      struct binding_ctx_in *b_ctx_in,
>>                      struct binding_ctx_out *b_ctx_out,
>>                      struct binding_lport *b_lport)
>> @@ -1579,7 +1582,7 @@ consider_vif_lport_(const struct sbrec_port_binding
>> *pb,
>>                               !b_ctx_in->ovnsb_idl_txn,
>>                               !parent_pb, b_ctx_out->tracked_dp_bindings,
>>                               b_ctx_out->if_mgr,
>> -                             b_ctx_out->postponed_ports)) {
>> +                             b_ctx_out->postponed_ports, can_bind)) {
>>                  return false;
>>              }
>>
>> @@ -1632,8 +1635,15 @@ consider_vif_lport_(const struct
>> sbrec_port_binding *pb,
>>                                   b_ctx_out->if_mgr);
>>          }
>>      }
>> +
>> +    struct binding_lport *parent_b_lport = b_lport && b_lport->lbinding ?
>> +        local_binding_get_primary_lport(b_lport->lbinding) : NULL;
>> +
>>      if (pb->chassis && pb->chassis != b_ctx_in->chassis_rec
>>              && !is_requested_additional_chassis(pb,
>> b_ctx_in->chassis_rec)
>> +            && (!parent_b_lport
>> +                || !is_requested_additional_chassis(parent_b_lport->pb,
>> +
>> b_ctx_in->chassis_rec))
>>              && if_status_is_port_claimed(b_ctx_out->if_mgr,
>>                                           pb->logical_port)) {
>>          update_lport_tracking(pb, b_ctx_out->tracked_dp_bindings, false);
>> @@ -1651,7 +1661,8 @@ consider_vif_lport(const struct sbrec_port_binding
>> *pb,
>>                     struct binding_ctx_out *b_ctx_out,
>>                     struct local_binding *lbinding)
>>  {
>> -    bool can_bind =
>> lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, pb);
>> +    enum can_bind can_bind =
>> +        lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, pb);
>>
>>      if (!lbinding) {
>>          lbinding =
>> local_binding_find(&b_ctx_out->lbinding_data->bindings,
>> @@ -1767,10 +1778,12 @@ consider_container_lport(const struct
>> sbrec_port_binding *pb,
>>      ovs_assert(parent_b_lport && parent_b_lport->pb);
>>      /* cannot bind to this chassis if the parent_port cannot be bounded.
>> */
>>      /* Do not bind neither if parent is postponed */
>> -    bool can_bind = lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec,
>> -                                                   parent_b_lport->pb) &&
>> -                    !is_postponed_port(parent_b_lport->pb->logical_port)
>> &&
>> -
>> lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, pb);
>> +
>> +    enum can_bind can_bind =
>> +        (!is_postponed_port(parent_b_lport->pb->logical_port) &&
>> +         lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, pb)) ?
>> +         lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec,
>> +                                        parent_b_lport->pb) :
>> CANNOT_BIND;
>>
>>      return consider_vif_lport_(pb, can_bind, b_ctx_in, b_ctx_out,
>>                                 container_b_lport);
>> @@ -1820,7 +1833,7 @@ consider_virtual_lport(const struct
>> sbrec_port_binding *pb,
>>          }
>>      }
>>
>> -    if (!consider_vif_lport_(pb, true, b_ctx_in, b_ctx_out,
>> +    if (!consider_vif_lport_(pb, CAN_BIND_AS_MAIN, b_ctx_in, b_ctx_out,
>>                               virtual_b_lport)) {
>>          return false;
>>      }
>> @@ -1916,11 +1929,13 @@ consider_nonvif_lport_(const struct
>> sbrec_port_binding *pb,
>>          }
>>
>>          update_related_lport(pb, b_ctx_out);
>> +        enum can_bind can_bind = lport_can_bind_on_this_chassis(
>> +                                     b_ctx_in->chassis_rec, pb);
>>          return claim_lport(pb, NULL, b_ctx_in->chassis_rec, NULL,
>>                             !b_ctx_in->ovnsb_idl_txn, false,
>>                             b_ctx_out->tracked_dp_bindings,
>>                             b_ctx_out->if_mgr,
>> -                           b_ctx_out->postponed_ports);
>> +                           b_ctx_out->postponed_ports, can_bind);
>>      }
>>      if (!is_ha_chassis) {
>>          remove_related_lport(pb, b_ctx_out);
>> @@ -2900,7 +2915,8 @@ handle_updated_vif_lport(const struct
>> sbrec_port_binding *pb,
>>      bool now_claimed = (pb->chassis == b_ctx_in->chassis_rec);
>>
>>      if (lport_type == LP_VIRTUAL || lport_type == LP_CONTAINER ||
>> -            claimed == now_claimed) {
>> +            (claimed == now_claimed &&
>> +             !is_additional_chassis(pb, b_ctx_in->chassis_rec))) {
>>          return true;
>>      }
>>
>> @@ -2917,7 +2933,9 @@ handle_updated_vif_lport(const struct
>> sbrec_port_binding *pb,
>>      }
>>
>>      struct binding_lport *b_lport;
>> +
>>      LIST_FOR_EACH (b_lport, list_node, &lbinding->binding_lports) {
>> +
>>
>
> nit: Unrelated changes.
>
>          if (b_lport->type == LP_CONTAINER) {
>>              handled = consider_container_lport(b_lport->pb, b_ctx_in,
>>                                                 b_ctx_out);
>> @@ -2987,7 +3005,7 @@ consider_patch_port_for_local_datapaths(const
>> struct sbrec_port_binding *pb,
>>                             !b_ctx_in->ovnsb_idl_txn, false,
>>                             b_ctx_out->tracked_dp_bindings,
>>                             b_ctx_out->if_mgr,
>> -                           b_ctx_out->postponed_ports);
>> +                           b_ctx_out->postponed_ports, CAN_BIND_AS_MAIN);
>>      }
>>      /* If this chassis is claimed, but not requested to be; or requested
>> for
>>       * some other chassis, but claimed by us - release. */
>> diff --git a/controller/physical.c b/controller/physical.c
>> index 9cab3ae26..69bf05347 100644
>> --- a/controller/physical.c
>> +++ b/controller/physical.c
>> @@ -1773,8 +1773,8 @@ consider_port_binding(const struct physical_ctx
>> *ctx,
>>                  ctx->sbrec_port_binding_by_name, binding->parent_port);
>>
>>              if (parent_port
>> -                && (lport_can_bind_on_this_chassis(ctx->chassis,
>> -                    parent_port) != CAN_BIND_AS_MAIN)) {
>> +                && !lport_can_bind_on_this_chassis(ctx->chassis,
>> +                                                   parent_port)) {
>>                  /* Even though there is an ofport for this container
>>                   * parent port, it is requested on different chassis
>> ignore
>>                   * this container port.
>> diff --git a/tests/multinode.at b/tests/multinode.at
>> index c1bd3123a..6d0f2910d 100644
>> --- a/tests/multinode.at
>> +++ b/tests/multinode.at
>> @@ -2776,3 +2776,260 @@ for i in 1 2; do
>>  done
>>
>>  AT_CLEANUP
>> +
>> +AT_SETUP([Migration of container ports])
>> +# Migrate vif port between chassis-1 and chassis-3; send packets between
>> +# chassis-2 and chassis-1/chassis-3, and check that
>> +# - packet handing on src works before migration.
>> +# - packet handing on src & dst works during migration.
>> +# - packet handing on dst works after migration.
>> +# Do the same for container ports.
>> +# The container port migration is tested in two different orders,
>> +# setting iface-id on dst resp. before and after requested-chassis.
>> +
>> +# Check that ovn-fake-multinode setup is up and running
>> +# check_fake_multinode_setup
>> +check_fake_multinode_setup_by_nodes 'ovn-chassis-1 ovn-chassis-2
>> ovn-chassis-3'
>> +
>> +# Delete the multinode NB and OVS resources before starting the test.
>> +cleanup_multinode_resources_by_nodes 'ovn-chassis-1 ovn-chassis-2
>> ovn-chassis-3'
>> +
>> +OVS_WAIT_UNTIL([m_as ovn-chassis-1 ip link show | grep -q genev_sys])
>> +OVS_WAIT_UNTIL([m_as ovn-chassis-2 ip link show | grep -q genev_sys])
>> +OVS_WAIT_UNTIL([m_as ovn-chassis-3 ip link show | grep -q genev_sys])
>> +
>> +check multinode_nbctl ls-add sw0
>> +check multinode_nbctl lsp-add sw0 migrator
>> +check multinode_nbctl lsp-set-addresses migrator "50:54:00:00:00:03
>> 10.0.0.3 1000::3"
>> +check multinode_nbctl lsp-add sw0 sw0-port2
>> +check multinode_nbctl lsp-set-addresses sw0-port2 "50:54:00:00:00:04
>> 10.0.0.4 1000::4"
>> +
>> +# Set requested chassis before creating migrator on chassis-3
>> +check multinode_nbctl --wait=hv set Logical_Switch_Port migrator
>> options:requested-chassis=ovn-chassis-1
>> +
>> +m_as ovn-chassis-1 /data/create_fake_vm.sh migrator migrator
>> 50:54:00:00:00:03 1342 10.0.0.3 24 10.0.0.1 1000::3/64 1000::a
>> +m_as ovn-chassis-3 /data/create_fake_vm.sh migrator migrator
>> 50:54:00:00:00:03 1342 10.0.0.3 24 10.0.0.1 1000::3/64 1000::a
>> +m_as ovn-chassis-2 /data/create_fake_vm.sh sw0-port2 sw0p2
>> 50:54:00:00:00:04 1342 10.0.0.4 24 10.0.0.1 1000::4/64 1000::a
>> +
>> +m_wait_for_ports_up
>> +
>> +M_START_TCPDUMP([ovn-chassis-1], [-neei genev_sys_6081 arp or ip],
>> [ch1_genev])
>> +M_START_TCPDUMP([ovn-chassis-1], [-neei migrator-p arp or ip],
>> [ch1_migrator])
>> +M_START_TCPDUMP([ovn-chassis-2], [-neei genev_sys_6081 arp or ip],
>> [ch2_genev])
>> +M_START_TCPDUMP([ovn-chassis-2], [-neei sw0p2-p arp or ip], [ch2_sw0p2])
>> +M_START_TCPDUMP([ovn-chassis-3], [-neei genev_sys_6081 arp or ip],
>> [ch3_genev])
>> +M_START_TCPDUMP([ovn-chassis-3], [-neei migrator-p arp or ip],
>> [ch3_migrator])
>> +
>> +AS_BOX([Migration with vifs])
>> +echo "Migrator on chassis-1 => sw0p2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 10.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "sw0p2 on chassis-2 => Migrator on chassis-1"
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ping -q -c 3 -i 0.3 -w 2
>> 10.0.0.3 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "== Starting migration =="
>> +check multinode_nbctl --wait=hv set Logical_Switch_Port migrator
>> options:requested-chassis=ovn-chassis-1,ovn-chassis-3
>> +
>> +echo "Migrator on chassis-1 => sw0p2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 10.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +
>> +echo "Migrator on chassis-3 => sw0p2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 10.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "sw0p2 on chassis-2 => migrator on  ..."
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ping -q -c 3 -i 0.3 -w 2
>> 10.0.0.3 | FORMAT_PING], \
>> +[0], [stdout])
>> +
>> +# Both VM are running ... We might get duplicates replies.
>> +AT_CHECK([cat stdout | grep "3 packets transmitted" | grep -c "3
>> received"], [0],[dnl
>> +1
>> +])
>> +
>> +echo "== Finalizing migration =="
>> +check multinode_nbctl --wait=hv set Logical_Switch_Port migrator
>> options:requested-chassis=ovn-chassis-3
>> +
>> +echo "Migrator on chassis-1 => sw0p2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 10.0.0.4 | FORMAT_PING], \
>> +[0], [stdout])
>> +
>> +# VM still running on chassis-1 but flows should have been deleted as
>> migration completed.
>> +AT_CHECK([cat stdout | grep -c "100% packet loss"], [0],[dnl
>> +1
>> +])
>> +
>> +echo "Migrator on chassis-3 => sw0p2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 10.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +# We should not have duplicates anymore
>> +echo "sw0p2 on chassis-2 => migrator on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ping -q -c 3 -i 0.3 -w 2
>> 10.0.0.3 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +AS_BOX([Migration with container ports])
>> +# Create container ports.
>> +check multinode_nbctl ls-add sw1
>> +check multinode_nbctl lsp-add sw1 mig-cont migrator 10 \
>> +                   -- lsp-set-addresses mig-cont "f0:00:00:01:02:03
>> 20.0.0.3"
>> +check multinode_nbctl lsp-add sw1 cont2 sw0-port2 10 \
>> +                   -- lsp-set-addresses cont2 "f0:00:00:01:02:04
>> 20.0.0.4"
>> +
>> +# Create the interface for lport mig-cont
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ip link add link migrator
>> name cont type vlan id 10], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ip link set cont address
>> f0:00:00:01:02:03], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ip link set cont up], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ip addr add 20.0.0.3/24
>> dev cont], [0])
>> +
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ip link add link migrator
>> name cont type vlan id 10], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ip link set cont address
>> f0:00:00:01:02:03], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ip link set cont up], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ip addr add 20.0.0.3/24
>> dev cont], [0])
>> +
>> +# Create the interface for lport sw1-port2
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ip link add link sw0p2 name
>> cont2 type vlan id 10], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ip link set cont2 address
>> f0:00:00:01:02:04], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ip link set cont2 up], [0])
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ip addr add 20.0.0.4/24 dev
>> cont2], [0])
>> +
>> +echo "mig-cont on chassis-3 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "cont2 on chassis-2 => mig-count on chassis-3"
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.3 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "== Starting migration back =="
>> +check multinode_nbctl --wait=hv set Logical_Switch_Port migrator
>> options:requested-chassis=ovn-chassis-3,ovn-chassis-1
>> +
>> +echo "mig-cont on chassis-3 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "mig-count on chassis-1 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "cont2 on chassis-2 => migrator on  ..."
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.3 | FORMAT_PING], \
>> +[0], [stdout])
>> +
>> +# Both VM are running ... We might get duplicates replies.
>> +AT_CHECK([cat stdout | grep "3 packets transmitted" | grep -c "3
>> received"], [0],[dnl
>> +1
>> +])
>> +
>> +echo "== Finalizing migration =="
>> +check multinode_nbctl --wait=hv set Logical_Switch_Port migrator
>> options:requested-chassis=ovn-chassis-1
>> +
>> +echo "mig-cont on chassis-3 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [stdout])
>> +
>> +# VM still running on chassis-3 but flows should have been deleted....
>> +AT_CHECK([cat stdout | grep -c "100% packet loss"], [0],[dnl
>> +1
>> +])
>> +
>> +echo "mig-cont on chassis-1 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +# We should not have duplicates anymore
>> +echo "cont2 on chassis-2 => mig-cont on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.3 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "== Starting another migration, this time before starting dst VM =="
>> +# Unbind migrator from chassis-3
>> +m_as ovn-chassis-3 ovs-vsctl -- set Interface migrator-p
>> external_ids:iface-id=foo
>> +
>> +check multinode_nbctl --wait=hv set Logical_Switch_Port migrator
>> options:requested-chassis=ovn-chassis-1,ovn-chassis-3
>> +sleep 1
>> +m_as ovn-chassis-3 ovs-vsctl -- set Interface migrator-p
>> external_ids:iface-id=migrator
>> +
>> +
>> +echo "mig-cont on chassis-3 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "mig-count on chassis-1 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +echo "cont2 on chassis-2 => migrator on  ..."
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.3 | FORMAT_PING], \
>> +[0], [stdout])
>> +
>> +# Both VM are running ... We might get duplicates replies.
>> +AT_CHECK([cat stdout | grep "3 packets transmitted" | grep -c "3
>> received"], [0],[dnl
>> +1
>> +])
>> +
>> +echo "== Finalizing migration =="
>> +check multinode_nbctl --wait=hv set Logical_Switch_Port migrator
>> options:requested-chassis=ovn-chassis-3
>> +
>> +echo "mig-cont on chassis-1 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-1], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [stdout])
>> +
>> +# VM still running on chassis-1 but flows should have been deleted....
>> +AT_CHECK([cat stdout | grep -c "100% packet loss"], [0],[dnl
>> +1
>> +])
>> +
>> +echo "mig-cont on chassis-3 => cont2 on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-3], [migrator], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.4 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +# We should not have duplicates anymore
>> +echo "cont2 on chassis-2 => mig-cont on chassis-2"
>> +M_NS_CHECK_EXEC([ovn-chassis-2], [sw0p2], [ping -q -c 3 -i 0.3 -w 2
>> 20.0.0.3 | FORMAT_PING], \
>> +[0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +m_as ovn-chassis-1 killall tcpdump
>> +m_as ovn-chassis-2 killall tcpdump
>> +m_as ovn-chassis-3 killall tcpdump
>> +rm -f *.tcpdump
>> +rm -f *.stderr
>>
>
> Shouldn't we keep those tcpdump logs for debugging purposes?
>
If the test reached those lines, it means that the test succeeded, so we
usually do not need much debugging.
However, I do not have a strong opinion, so we can keep them if we feel it
might help understanding (those dumps are not big).
I'll keep those logs in v2.

>
> +
>> +AT_CLEANUP
>> +
>> +
>> diff --git a/tests/ovn.at b/tests/ovn.at
>> index d105ed253..08323f372 100644
>> --- a/tests/ovn.at
>> +++ b/tests/ovn.at
>> @@ -16785,6 +16785,160 @@ OVN_CLEANUP([hv1],[hv2])
>>  AT_CLEANUP
>>  ])
>>
>> +OVN_FOR_EACH_NORTHD([
>> +AT_SETUP([No fight between two chassis for the same port])
>> +ovn_start
>> +
>> +# lsp1 on hv1, lsp2 on hv2.
>> +# migrator1 (and its mig1-cont container) initially on hv1.
>> +# migrator2 (and its mig2-cont container) initially on hv2.
>> +# For migrator1, iface-id is set (in both hv) before starting migration.
>> +# For migrator2, iface-id is set (in dst hv) after initiating migration.
>> +check ovn-nbctl ls-add ls0
>> +check ovn-nbctl lsp-add ls0 lsp1
>> +check ovn-nbctl lsp-add ls0 lsp2
>> +check ovn-nbctl lsp-add ls0 migrator1
>> +check ovn-nbctl lsp-add ls0 migrator2
>> +check ovn-nbctl lsp-add ls0 mig1-cont migrator1 1
>> +check ovn-nbctl lsp-add ls0 mig2-cont migrator2 1
>> +check ovn-nbctl set Logical_Switch_Port migrator1
>> options:requested-chassis=hv1
>> +check ovn-nbctl set Logical_Switch_Port migrator2
>> options:requested-chassis=hv2
>> +
>> +net_add n1
>> +for i in 1 2; do
>> +    sim_add hv$i
>> +    as hv$i
>> +    ovs-vsctl add-br br-phys
>> +    ovn_attach n1 br-phys 192.168.0.$i
>> +done
>> +
>> +# Set iface-id in both hv1 and hv2.
>> +as hv2 ovs-vsctl -- add-port br-int vif-migrator2 \
>> +                 -- set Interface vif-migrator2
>> external-ids:iface-id=migrator2
>> +
>> +for i in 1 2; do
>> +    as hv$i
>> +    ovs-vsctl -- add-port br-int vif-migrator1 \
>> +              -- set Interface vif-migrator1
>> external-ids:iface-id=migrator1
>> +    ovs-vsctl -- add-port br-int vif$i \
>> +              -- set Interface vif$i external-ids:iface-id=lsp$i
>> +done
>> +
>> +hv1_uuid=$(ovn-sbctl --bare --columns _uuid list chassis hv1)
>> +hv2_uuid=$(ovn-sbctl --bare --columns _uuid list chassis hv2)
>> +
>> +check_in_port_flows_count() {
>> +  hv=$1
>> +  of=$2
>> +  count=$3
>> +  AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int
>> table=OFTABLE_PHY_TO_LOG | grep "in_port=$of" | wc -l], [0], [dnl
>> +$count
>> +])
>> +}
>> +
>> +check_claims() {
>> +    port=$1
>> +    hv1_claims=$(grep -c "Claiming lport $port\|Changing chassis for
>> lport $port" hv1/ovn-controller.log)
>> +    hv2_claims=$(grep -c "Claiming lport $port\|Changing chassis for
>> lport $port" hv2/ovn-controller.log)
>> +    echo "$hv1_claims claims for port $port in hv1"
>> +    echo "$hv2_claims claims for port $port in hv2"
>> +    AT_CHECK([test "${hv1_claims}" -le "${max_claims}"], [0], [])
>> +    AT_CHECK([test "${hv2_claims}" -le "${max_claims}"], [0], [])
>> +}
>> +
>> +# Waiting for flows in hv1 && hv2 for resp. lsp1 and lsp2.
>> +OVS_WAIT_UNTIL([
>> +    of_hv1=$(as hv1 ovs-vsctl --bare --columns ofport find Interface
>> name=vif1)
>> +    of_hv2=$(as hv2 ovs-vsctl --bare --columns ofport find Interface
>> name=vif2)
>>
>
> We can request a unique ofport number, we should probably do that instead
> WDYT?
>
I usually avoid requesting a unique number as I feel it is not 100%
"reliable".
It works if we request a "high" number (e.g. 10), but one might wonder why
using high numbers...
If we request an ofport such as 1 or 2, which might clash with ofport
initially/internally attributed by ovn to interfaces such as ovn-hv1-0, the
requested ofport number might not be correct before some time.

>
>
>> +    test -n of_hv1 && test -n $of_hv1 &&
>> +        test 1 -le $(as hv1 ovs-ofctl dump-flows br-int
>> table=OFTABLE_PHY_TO_LOG | grep "in_port=$of_hv1" | wc -l) &&
>> +        test 1 -le $(as hv2 ovs-ofctl dump-flows br-int
>> table=OFTABLE_PHY_TO_LOG | grep "in_port=$of_hv2" | wc -l)
>> +])
>> +
>> +of1=$(as hv1 ovs-vsctl --bare --columns ofport find Interface
>> name=vif-migrator1)
>> +of2=$(as hv2 ovs-vsctl --bare --columns ofport find Interface
>> name=vif-migrator1)
>> +
>> +AS_BOX([$(date +%H:%M:%S.%03N) Before migrating migrator1])
>> +wait_column "" Port_Binding additional_chassis logical_port=migrator1
>> +wait_column "" Port_Binding additional_chassis logical_port=mig1-cont
>> +# We should have two flows in table OFTABLE_PHY_TO_LOG from
>> in_port=migrator1 in hv1 (one for vif and one for the container) and 0
>> flows in hv2.
>> +check_in_port_flows_count hv1 $of1 2
>> +check_in_port_flows_count hv2 $of2 0
>> +
>> +
>> +AS_BOX([$(date +%H:%M:%S.%03N) Starting migrating migrator1])
>> +check ovn-nbctl --wait=hv set Logical_Switch_Port migrator1
>> options:requested-chassis=hv1,hv2
>> +wait_column "$hv2_uuid" Port_Binding additional_chassis
>> logical_port=migrator1
>> +wait_column "$hv2_uuid" Port_Binding additional_chassis
>> logical_port=mig1-cont
>> +# We should have two flows in table OFTABLE_PHY_TO_LOG from
>> in_port=migrator1 in hv1 and hv2.
>> +check_in_port_flows_count hv1 $of1 2
>> +check_in_port_flows_count hv2 $of2 2
>> +
>> +# While migration in underway, check that there is no fight between hv
>> +sleep 3
>> +max_claims=2
>> +check_claims migrator1
>> +check_claims mig1-cont
>> +
>> +AS_BOX([$(date +%H:%M:%S.%03N) After migrating migrator1])
>> +check ovn-nbctl --wait=hv set Logical_Switch_Port migrator1
>> options:requested-chassis=hv2
>> +wait_column "" Port_Binding additional_chassis logical_port=migrator1
>> +wait_column "" Port_Binding additional_chassis logical_port=mig1-cont
>> +check_in_port_flows_count hv1 $of1 0
>> +check_in_port_flows_count hv2 $of2 2
>> +
>> +# Now do the same, but with iface-id set after starting migration
>> +of2=$(as hv2 ovs-vsctl --bare --columns ofport find Interface
>> name=vif-migrator2)
>> +# There is no ofport yet for hv1 => we cannot check/find a flows with
>> in_port=of1
>> +
>> +AS_BOX([$(date +%H:%M:%S.%03N) Before migrating migrator2])
>> +# We should have zero flows in table OFTABLE_PHY_TO_LOG from
>> in_port=migrator2 in hv1 and two flows in hv2.
>> +wait_column "" Port_Binding additional_chassis logical_port=migrator2
>> +wait_column "" Port_Binding additional_chassis logical_port=mig2-cont
>> +check_in_port_flows_count hv2 $of2 2
>> +
>> +check ovn-nbctl --wait=hv set Logical_Switch_Port migrator2
>> options:requested-chassis=hv2,hv1
>> +wait_column "" Port_Binding additional_chassis logical_port=migrator2
>> +wait_column "" Port_Binding additional_chassis logical_port=mig2-cont
>> +# As no iface-id for migrator2 yet, migration not really started
>> +# We should have zero flows in table OFTABLE_PHY_TO_LOG from
>> in_port=migrator2 in hv1 and two flows in hv2.
>> +check_in_port_flows_count hv2 $of2 2
>> +
>> +AS_BOX([$(date +%H:%M:%S.%03N) Starting migrating migrator2])
>> +as hv1 ovs-vsctl -- add-port br-int vif-migrator2 \
>> +                 -- set Interface vif-migrator2
>> external-ids:iface-id=migrator2
>> +
>> +wait_column "$hv1_uuid" Port_Binding additional_chassis
>> logical_port=migrator2
>> +wait_column "$hv1_uuid" Port_Binding additional_chassis
>> logical_port=mig2-cont
>> +# We need for oflow to be created and handled by ovn-controller. Wait
>> sync would not be enough.
>> +OVS_WAIT_UNTIL([
>> +    of1=$(as hv1 ovs-vsctl --bare --columns ofport find Interface
>> name=vif-migrator2)
>> +    test 1 -le "$of1"
>> +])
>> +
>> +check ovn-nbctl --wait=hv sync
>> +
>> +# We should have two flows in table OFTABLE_PHY_TO_LOG from
>> in_port=migrator2 in hv1 and hv2.
>> +check_in_port_flows_count hv1 $of1 2
>> +check_in_port_flows_count hv2 $of2 2
>> +
>> +# While migration in underway, check that there is no fight between hv
>> +sleep 3
>> +check_claims migrator2
>> +check_claims mig2-cont
>> +
>> +AS_BOX([$(date +%H:%M:%S.%03N) After migrating migrator2])
>> +check ovn-nbctl --wait=hv set Logical_Switch_Port migrator2
>> options:requested-chassis=hv1
>> +wait_column "" Port_Binding additional_chassis logical_port=migrator2
>> +wait_column "" Port_Binding additional_chassis logical_port=mig2-cont
>> +check_in_port_flows_count hv1 $of1 2
>> +check_in_port_flows_count hv2 $of2 0
>> +
>> +OVN_CLEANUP([hv1],[hv2])
>> +
>> +AT_CLEANUP
>> +])
>> +
>>  OVN_FOR_EACH_NORTHD([
>>  AT_SETUP([options:requested-chassis with hostname])
>>
>> @@ -39199,7 +39353,7 @@ OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows
>> br-int table=OFTABLE_PHY_TO_LOG
>>  ])
>>
>>  # Add hv2 to lport Additional requested chassis as MAIN chassis
>> -# and check that no flows installed in table 0 in hv1
>> +# and check that flows remain installed in table 0 in hv1
>>  check ovn-nbctl set Logical_Switch_Port lsp1 \
>>      options:requested-chassis=hv2,hv1
>>
>> @@ -39214,8 +39368,8 @@ wait_column "$hv2_uuid" Port_Binding chassis
>> logical_port=lsp1
>>  OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int
>> table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c
>> in_port=8], [0],[dnl
>>  1
>>  ])
>> -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int
>> table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c
>> in_port=8], [1],[dnl
>> -0
>> +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int
>> table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c
>> in_port=8], [0],[dnl
>> +1
>>  ])
>>
>
> This seems to be a "side effect" from the main chassis removal from
> the additional chassis. If that's the case we should keep that change
> separately. Would you agree?
>
I do not think so. This test tells that, when both hv are requested
chassis, so when hv1 is an additional_chassis, the flows remain installed
in hv1 - which is what we want as we are in the middle of the migration.
The change you refer to was somehow related to sb only, and was to avoid a
chassis to be main and additional chassis at the same time (which is
useless)

>
>
>>  OVN_CLEANUP([hv1])
>> --
>> 2.47.1
>>
>> _______________________________________________
>> dev mailing list
>> [email protected]
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>>
> Thanks,
> Ales
>
Thanks
Xavier
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to