On Fri, Jul 8, 2022 at 9:22 AM Ihar Hrachyshka <ihrac...@redhat.com> wrote: > > On Thu, Jul 7, 2022 at 4:39 PM Numan Siddique <num...@ovn.org> wrote: > > > > On Fri, Jul 1, 2022 at 1:52 PM Mark Michelson <mmich...@redhat.com> wrote: > > > > > > Looks good to me. Thanks, Ihar. > > > > > > Acked-by: Mark Michelson <mmich...@redhat.com> > > > > > > On 6/24/22 18:35, Ihar Hrachyshka wrote: > > > > Before the patch, for switches with a localnet port, > > > > > > > > - traffic to a multichassis port was funneled through tunnels; but > > > > - traffic from a multichassis port was sent through localnet. > > > > > > > > This is not optimal because: > > > > - bidirectional sessions are sent through two separate paths; > > > > - leaking multichassis traffic to physical makes upstream switch flip > > > > port's mac address location. > > > > > > > > One of the effects of this behavior is prolonged network downtime when > > > > live migrating a VM attached to a physical network (compared to > > > > downtime observed for pure geneve networks). > > > > > > > > As per my unscientific local testing, this patch reduces network > > > > downtime during OpenStack VM live migration from 1.0s+ to 0.05-0.10s, > > > > on par with geneve networks. > > > > > > > > Fixes: 10398c1f51d5 ("Clone packets to all port chassis") > > > > Signed-off-by: Ihar Hrachyshka <ihrac...@redhat.com> > > > > --- > > > > v2: fixed a memory leak caught by asan job. > > > > v1: initial commit. > > > > --- > > > > controller/binding.c | 38 ++++++++++++++ > > > > controller/local_data.c | 30 ++++++++++- > > > > controller/local_data.h | 6 +++ > > > > controller/ovn-controller.c | 6 +++ > > > > controller/physical.c | 99 +++++++++++++++++++++++++++++++++++-- > > > > controller/physical.h | 1 + > > > > tests/ovn.at | 30 +++++++++++ > > > > 7 files changed, 206 insertions(+), 4 deletions(-) > > > > > > > > diff --git a/controller/binding.c b/controller/binding.c > > > > index 2279570f9..9025681db 100644 > > > > --- a/controller/binding.c > > > > +++ b/controller/binding.c > > > > @@ -386,6 +386,23 @@ update_ld_external_ports(const struct > > > > sbrec_port_binding *binding_rec, > > > > } > > > > } > > > > > > > > +static void > > > > +update_ld_multichassis_ports(const struct sbrec_port_binding > > > > *binding_rec, > > > > + struct hmap *local_datapaths) > > > > +{ > > > > + struct local_datapath *ld = get_local_datapath( > > > > + local_datapaths, binding_rec->datapath->tunnel_key); > > > > + if (!ld) { > > > > + return; > > > > + } > > > > + if (binding_rec->additional_chassis) { > > > > + add_local_datapath_multichassis_port(ld, > > > > binding_rec->logical_port, > > > > + binding_rec); > > > > + } else { > > > > + remove_local_datapath_multichassis_port(ld, > > > > binding_rec->logical_port); > > > > + } > > > > +} > > > > + > > > > static void > > > > update_ld_localnet_port(const struct sbrec_port_binding *binding_rec, > > > > struct shash *bridge_mappings, > > > > @@ -1752,6 +1769,8 @@ binding_run(struct binding_ctx_in *b_ctx_in, > > > > struct binding_ctx_out *b_ctx_out) > > > > > > > > struct ovs_list localnet_lports = > > > > OVS_LIST_INITIALIZER(&localnet_lports); > > > > struct ovs_list external_lports = > > > > OVS_LIST_INITIALIZER(&external_lports); > > > > + struct ovs_list multichassis_ports = OVS_LIST_INITIALIZER( > > > > + > > > > &multichassis_ports); > > > > > > > > struct lport { > > > > struct ovs_list list_node; > > > > @@ -1787,6 +1806,13 @@ binding_run(struct binding_ctx_in *b_ctx_in, > > > > struct binding_ctx_out *b_ctx_out) > > > > > > > > case LP_VIF: > > > > consider_vif_lport(pb, b_ctx_in, b_ctx_out, NULL, > > > > qos_map_ptr); > > > > + if (pb->additional_chassis) { > > > > + struct lport *multichassis_lport = xmalloc( > > > > + sizeof *multichassis_lport); > > > > + multichassis_lport->pb = pb; > > > > + ovs_list_push_back(&multichassis_ports, > > > > + &multichassis_lport->list_node); > > > > + } > > > > break; > > > > > > > > case LP_CONTAINER: > > > > @@ -1862,6 +1888,16 @@ binding_run(struct binding_ctx_in *b_ctx_in, > > > > struct binding_ctx_out *b_ctx_out) > > > > free(ext_lport); > > > > } > > > > > > > > + /* Run through multichassis lport list to see if these are ports > > > > + * on local datapaths discovered from above loop, and update the > > > > + * corresponding local datapath accordingly. */ > > > > + struct lport *multichassis_lport; > > > > + LIST_FOR_EACH_POP (multichassis_lport, list_node, > > > > &multichassis_ports) { > > > > + update_ld_multichassis_ports(multichassis_lport->pb, > > > > + b_ctx_out->local_datapaths); > > > > + free(multichassis_lport); > > > > + } > > > > + > > > > shash_destroy(&bridge_mappings); > > > > > > > > if (!sset_is_empty(b_ctx_out->egress_ifaces) > > > > @@ -1934,6 +1970,7 @@ remove_pb_from_local_datapath(const struct > > > > sbrec_port_binding *pb, > > > > } else if (!strcmp(pb->type, "external")) { > > > > remove_local_datapath_external_port(ld, pb->logical_port); > > > > } > > > > + remove_local_datapath_multichassis_port(ld, pb->logical_port); > > > > } > > > > > > > > static void > > > > @@ -2677,6 +2714,7 @@ delete_done: > > > > case LP_VIF: > > > > case LP_CONTAINER: > > > > case LP_VIRTUAL: > > > > + update_ld_multichassis_ports(pb, > > > > b_ctx_out->local_datapaths); > > > > handled = handle_updated_vif_lport(pb, lport_type, > > > > b_ctx_in, > > > > b_ctx_out, > > > > qos_map_ptr); > > > > break; > > > > diff --git a/controller/local_data.c b/controller/local_data.c > > > > index 98445902b..7f874fc19 100644 > > > > --- a/controller/local_data.c > > > > +++ b/controller/local_data.c > > > > @@ -72,6 +72,7 @@ local_datapath_alloc(const struct > > > > sbrec_datapath_binding *dp) > > > > ld->is_switch = datapath_is_switch(dp); > > > > ld->is_transit_switch = datapath_is_transit_switch(dp); > > > > shash_init(&ld->external_ports); > > > > + shash_init(&ld->multichassis_ports); > > > > /* memory accounting - common part. */ > > > > local_datapath_usage += sizeof *ld; > > > > > > > > @@ -97,13 +98,20 @@ local_datapath_destroy(struct local_datapath *ld) > > > > SHASH_FOR_EACH (node, &ld->external_ports) { > > > > local_datapath_usage -= strlen(node->name); > > > > } > > > > - local_datapath_usage -= shash_count(&ld->external_ports) * sizeof > > > > *node; > > > > + SHASH_FOR_EACH (node, &ld->multichassis_ports) { > > > > + local_datapath_usage -= strlen(node->name); > > > > + } > > > > + local_datapath_usage -= (shash_count(&ld->external_ports) > > > > + * sizeof *node); > > > > + local_datapath_usage -= (shash_count(&ld->multichassis_ports) > > > > + * sizeof *node); > > > > local_datapath_usage -= sizeof *ld; > > > > local_datapath_usage -= > > > > ld->n_allocated_peer_ports * sizeof *ld->peer_ports; > > > > > > > > free(ld->peer_ports); > > > > shash_destroy(&ld->external_ports); > > > > + shash_destroy(&ld->multichassis_ports); > > > > free(ld); > > > > } > > > > > > > > @@ -274,6 +282,26 @@ remove_local_datapath_external_port(struct > > > > local_datapath *ld, > > > > } > > > > } > > > > > > > > +void > > > > +add_local_datapath_multichassis_port(struct local_datapath *ld, > > > > + char *logical_port, const void > > > > *data) > > > > +{ > > > > + if (!shash_replace(&ld->multichassis_ports, logical_port, data)) { > > > > + local_datapath_usage += sizeof(struct shash_node) + > > > > + strlen(logical_port); > > > > + } > > > > +} > > > > + > > > > +void > > > > +remove_local_datapath_multichassis_port(struct local_datapath *ld, > > > > + char *logical_port) > > > > +{ > > > > + if (shash_find_and_delete(&ld->multichassis_ports, logical_port)) { > > > > + local_datapath_usage -= sizeof(struct shash_node) + > > > > + strlen(logical_port); > > > > + } > > > > +} > > > > + > > > > void > > > > local_datapath_memory_usage(struct simap *usage) > > > > { > > > > diff --git a/controller/local_data.h b/controller/local_data.h > > > > index 9306ddf15..d898c8aa5 100644 > > > > --- a/controller/local_data.h > > > > +++ b/controller/local_data.h > > > > @@ -58,6 +58,7 @@ struct local_datapath { > > > > size_t n_allocated_peer_ports; > > > > > > > > struct shash external_ports; > > > > + struct shash multichassis_ports; > > > > }; > > > > > > > > struct local_datapath *local_datapath_alloc( > > > > @@ -155,5 +156,10 @@ void add_local_datapath_external_port(struct > > > > local_datapath *ld, > > > > char *logical_port, const void > > > > *data); > > > > void remove_local_datapath_external_port(struct local_datapath *ld, > > > > char *logical_port); > > > > +void add_local_datapath_multichassis_port(struct local_datapath *ld, > > > > + char *logical_port, > > > > + const void *data); > > > > +void remove_local_datapath_multichassis_port(struct local_datapath *ld, > > > > + char *logical_port); > > > > > > > > #endif /* controller/local_data.h */ > > > > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > > > > index 69615308e..2e9138036 100644 > > > > --- a/controller/ovn-controller.c > > > > +++ b/controller/ovn-controller.c > > > > @@ -3000,6 +3000,11 @@ static void init_physical_ctx(struct engine_node > > > > *node, > > > > engine_get_input("SB_port_binding", node), > > > > "name"); > > > > > > > > + struct ovsdb_idl_index *sbrec_port_binding_by_datapath = > > > > + engine_ovsdb_node_get_index( > > > > + engine_get_input("SB_port_binding", node), > > > > + "datapath"); > > > > + > > > > struct sbrec_multicast_group_table *multicast_group_table = > > > > (struct sbrec_multicast_group_table *)EN_OVSDB_GET( > > > > engine_get_input("SB_multicast_group", node)); > > > > @@ -3039,6 +3044,7 @@ static void init_physical_ctx(struct engine_node > > > > *node, > > > > struct simap *ct_zones = &ct_zones_data->current; > > > > > > > > p_ctx->sbrec_port_binding_by_name = sbrec_port_binding_by_name; > > > > + p_ctx->sbrec_port_binding_by_datapath = > > > > sbrec_port_binding_by_datapath; > > > > p_ctx->port_binding_table = port_binding_table; > > > > p_ctx->mc_group_table = multicast_group_table; > > > > p_ctx->br_int = br_int; > > > > diff --git a/controller/physical.c b/controller/physical.c > > > > index fc8280a99..816a557e7 100644 > > > > --- a/controller/physical.c > > > > +++ b/controller/physical.c > > > > @@ -1074,6 +1074,67 @@ setup_activation_strategy(const struct > > > > sbrec_port_binding *binding, > > > > } > > > > } > > > > > > > > +static void > > > > +enforce_tunneling_for_multichassis_ports( > > > > + struct local_datapath *ld, > > > > + const struct sbrec_port_binding *binding, > > > > + const struct sbrec_chassis *chassis, > > > > + const struct hmap *chassis_tunnels, > > > > + enum mf_field_id mff_ovn_geneve, > > > > + struct ovn_desired_flow_table *flow_table) > > > > +{ > > > > + if (shash_is_empty(&ld->multichassis_ports)) { > > > > + return; > > > > + } > > > > + > > > > + struct ovs_list *tuns = get_remote_tunnels(binding, chassis, > > > > + chassis_tunnels); > > > > + if (ovs_list_is_empty(tuns)) { > > > > + free(tuns); > > > > + return; > > > > + } > > > > + > > > > + uint32_t dp_key = binding->datapath->tunnel_key; > > > > + uint32_t port_key = binding->tunnel_key; > > > > + > > > > + struct shash_node *node; > > > > + SHASH_FOR_EACH (node, &ld->multichassis_ports) { > > > > + const struct sbrec_port_binding *mcp = node->data; > > > > + > > > > + struct ofpbuf ofpacts; > > > > + ofpbuf_init(&ofpacts, 0); > > > > + > > > > + bool is_vtep_port = !strcmp(binding->type, "vtep"); > > > > + /* rewrite MFF_IN_PORT to bypass OpenFlow loopback check for > > > > ARP/ND > > > > + * responder in L3 networks. */ > > > > + if (is_vtep_port) { > > > > + put_load(ofp_to_u16(OFPP_NONE), MFF_IN_PORT, 0, 16, > > > > &ofpacts); > > > > + } > > > > + > > > > + struct match match; > > > > + match_outport_dp_and_port_keys(&match, dp_key, port_key); > > > > + match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, > > > > mcp->tunnel_key); > > > > + > > > > + struct tunnel *tun; > > > > + LIST_FOR_EACH (tun, list_node, tuns) { > > > > + put_encapsulation(mff_ovn_geneve, tun->tun, > > > > + binding->datapath, port_key, > > > > is_vtep_port, > > > > + &ofpacts); > > > > + ofpact_put_OUTPUT(&ofpacts)->port = tun->tun->ofport; > > > > + } > > > > + ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 110, > > > > + binding->header_.uuid.parts[0], &match, > > > > &ofpacts, > > > > + &binding->header_.uuid); > > > > + ofpbuf_uninit(&ofpacts); > > > > + } > > > > + > > > > + struct tunnel *tun_elem; > > > > + LIST_FOR_EACH_POP (tun_elem, list_node, tuns) { > > > > + free(tun_elem); > > > > + } > > > > + free(tuns); > > > > +} > > > > + > > > > static void > > > > consider_port_binding(struct ovsdb_idl_index > > > > *sbrec_port_binding_by_name, > > > > enum mf_field_id mff_ovn_geneve, > > > > @@ -1509,6 +1570,9 @@ consider_port_binding(struct ovsdb_idl_index > > > > *sbrec_port_binding_by_name, > > > > binding->header_.uuid.parts[0], > > > > &match, ofpacts_p, &binding->header_.uuid); > > > > > > > > + enforce_tunneling_for_multichassis_ports( > > > > + ld, binding, chassis, chassis_tunnels, mff_ovn_geneve, > > > > flow_table); > > > > + > > > > /* No more tunneling to set up. */ > > > > goto out; > > > > } > > > > @@ -1827,20 +1891,49 @@ physical_handle_flows_for_lport(const struct > > > > sbrec_port_binding *pb, > > > > > > > > ofctrl_remove_flows(flow_table, &pb->header_.uuid); > > > > > > > > + struct local_datapath *ldp = > > > > + get_local_datapath(p_ctx->local_datapaths, > > > > + pb->datapath->tunnel_key); > > > > if (!strcmp(pb->type, "external")) { > > > > /* External lports have a dependency on the localnet port. > > > > * We need to remove the flows of the localnet port as well > > > > * and re-consider adding the flows for it. > > > > */ > > > > - struct local_datapath *ldp = > > > > - get_local_datapath(p_ctx->local_datapaths, > > > > - pb->datapath->tunnel_key); > > > > if (ldp && ldp->localnet_port) { > > > > ofctrl_remove_flows(flow_table, > > > > &ldp->localnet_port->header_.uuid); > > > > physical_eval_port_binding(p_ctx, ldp->localnet_port, > > > > flow_table); > > > > } > > > > } > > > > > > > > + if (ldp) { > > > > + bool multichassis_state_changed = ( > > > > + !!pb->additional_chassis == > > > > + !!shash_find(&ldp->multichassis_ports, pb->logical_port) > > > > + ); > > > > + if (multichassis_state_changed) { > > > > + if (pb->additional_chassis) { > > > > + add_local_datapath_multichassis_port( > > > > + ldp, pb->logical_port, pb); > > > > + } else { > > > > + remove_local_datapath_multichassis_port( > > > > + ldp, pb->logical_port); > > > > + } > > > > + > > > > + struct sbrec_port_binding *target = > > > > + sbrec_port_binding_index_init_row( > > > > + p_ctx->sbrec_port_binding_by_datapath); > > > > + sbrec_port_binding_index_set_datapath(target, > > > > ldp->datapath); > > > > + > > > > + const struct sbrec_port_binding *port; > > > > + SBREC_PORT_BINDING_FOR_EACH_EQUAL ( > > > > + port, target, > > > > p_ctx->sbrec_port_binding_by_datapath) { > > > > + ofctrl_remove_flows(flow_table, &port->header_.uuid); > > > > + physical_eval_port_binding(p_ctx, port, flow_table); > > > > + } > > > > + sbrec_port_binding_index_destroy_row(target); > > > > Hi Ihar, > > > > One question. Why is the above loop required ? Why is it necessary to > > consider port binding for all the ports of the datapath if multi > > chassis state changes for one port. > > > > Because once this port is multichassis, every other chassis must know > that any traffic directed towards this (multichassis) port must be > tunneled through (and not sent through localnet port as usual for a > switch with such a - localnet - port). [Vice versa is also true: once > a port becomes single-chassis, traffic towards the port is sent > through localnet again.]
Thanks for the explanation. I applied this patch to the main branch and backported to branch-22.06. Numan > > > Thanks > > Numan > > > > > > + } > > > > + } > > > > + > > > > if (!removed) { > > > > physical_eval_port_binding(p_ctx, pb, flow_table); > > > > if (!strcmp(pb->type, "patch")) { > > > > diff --git a/controller/physical.h b/controller/physical.h > > > > index ee4b1ae1f..1b8f1ea55 100644 > > > > --- a/controller/physical.h > > > > +++ b/controller/physical.h > > > > @@ -45,6 +45,7 @@ struct local_nonvif_data; > > > > > > > > struct physical_ctx { > > > > struct ovsdb_idl_index *sbrec_port_binding_by_name; > > > > + struct ovsdb_idl_index *sbrec_port_binding_by_datapath; > > > > const struct sbrec_port_binding_table *port_binding_table; > > > > const struct sbrec_multicast_group_table *mc_group_table; > > > > const struct ovsrec_bridge *br_int; > > > > diff --git a/tests/ovn.at b/tests/ovn.at > > > > index bfaa41962..a82a33aa7 100644 > > > > --- a/tests/ovn.at > > > > +++ b/tests/ovn.at > > > > @@ -14657,6 +14657,14 @@ reset_env() { > > > > for port in hv1/migrator hv2/migrator hv1/first hv2/second > > > > hv3/third; do > > > > : > $port.expected > > > > done > > > > + > > > > + for hv in hv1 hv2 hv3; do > > > > + : > $hv/n1.expected > > > > + done > > > > + > > > > + reset_pcap_file hv1 br-phys_n1 hv1/br-phys_n1 > > > > + reset_pcap_file hv2 br-phys_n1 hv2/br-phys_n1 > > > > + reset_pcap_file hv3 br-phys_n1 hv3/br-phys_n1 > > > > } > > > > > > > > check_packets() { > > > > @@ -14667,6 +14675,10 @@ check_packets() { > > > > OVN_CHECK_PACKETS_CONTAIN([hv1/first-tx.pcap], > > > > [hv1/first.expected]) > > > > OVN_CHECK_PACKETS_CONTAIN([hv2/second-tx.pcap], > > > > [hv2/second.expected]) > > > > OVN_CHECK_PACKETS_CONTAIN([hv3/third-tx.pcap], > > > > [hv3/third.expected]) > > > > + > > > > + OVN_CHECK_PACKETS_CONTAIN([hv1/br-phys_n1-tx.pcap], > > > > [hv1/n1.expected]) > > > > + OVN_CHECK_PACKETS_CONTAIN([hv2/br-phys_n1-tx.pcap], > > > > [hv2/n1.expected]) > > > > + OVN_CHECK_PACKETS_CONTAIN([hv3/br-phys_n1-tx.pcap], > > > > [hv3/n1.expected]) > > > > } > > > > > > > > migrator_tpa=$(ip_to_hex 10 0 0 100) > > > > @@ -14714,6 +14726,7 @@ echo $request >> hv3/third.expected > > > > # unicast from Second doesn't arrive to hv2:Migrator > > > > request=$(send_arp hv2 second 000000000002 0000000000ff $second_spa > > > > $migrator_tpa) > > > > echo $request >> hv1/migrator.expected > > > > +echo $request >> hv2/n1.expected > > > > > > > > # mcast from Second arrives to hv1:Migrator > > > > # mcast from Second doesn't arrive to hv2:Migrator > > > > @@ -14721,11 +14734,13 @@ request=$(send_arp hv2 second 000000000002 > > > > ffffffffffff $second_spa $migrator_tp > > > > echo $request >> hv1/migrator.expected > > > > echo $request >> hv1/first.expected > > > > echo $request >> hv3/third.expected > > > > +echo $request >> hv2/n1.expected > > > > > > > > # unicast from Third arrives to hv1:Migrator > > > > # unicast from Third doesn't arrive to hv2:Migrator > > > > request=$(send_arp hv3 third 000000000003 0000000000ff $third_spa > > > > $migrator_tpa) > > > > echo $request >> hv1/migrator.expected > > > > +echo $request >> hv3/n1.expected > > > > > > > > # mcast from Third arrives to hv1:Migrator > > > > # mcast from Third doesn't arrive to hv2:Migrator > > > > @@ -14733,14 +14748,17 @@ request=$(send_arp hv3 third 000000000003 > > > > ffffffffffff $third_spa $migrator_tpa) > > > > echo $request >> hv1/migrator.expected > > > > echo $request >> hv1/first.expected > > > > echo $request >> hv2/second.expected > > > > +echo $request >> hv3/n1.expected > > > > > > > > # unicast from hv1:Migrator arrives to First, Second, and Third > > > > request=$(send_arp hv1 migrator 0000000000ff 000000000001 > > > > $migrator_tpa $first_spa) > > > > echo $request >> hv1/first.expected > > > > request=$(send_arp hv1 migrator 0000000000ff 000000000002 > > > > $migrator_tpa $second_spa) > > > > echo $request >> hv2/second.expected > > > > +echo $request >> hv1/n1.expected > > > > request=$(send_arp hv1 migrator 0000000000ff 000000000003 > > > > $migrator_tpa $third_spa) > > > > echo $request >> hv3/third.expected > > > > +echo $request >> hv1/n1.expected > > > > > > > > # unicast from hv2:Migrator doesn't arrive to First, Second, or Third > > > > request=$(send_arp hv2 migrator 0000000000ff 000000000001 > > > > $migrator_tpa $first_spa) > > > > @@ -14752,6 +14770,7 @@ request=$(send_arp hv1 migrator 0000000000ff > > > > ffffffffffff $migrator_tpa $first_s > > > > echo $request >> hv1/first.expected > > > > echo $request >> hv2/second.expected > > > > echo $request >> hv3/third.expected > > > > +echo $request >> hv1/n1.expected > > > > > > > > # mcast from hv2:Migrator doesn't arrive to First, Second, or Third > > > > request=$(send_arp hv2 migrator 0000000000ff ffffffffffff > > > > $migrator_tpa $first_spa) > > > > @@ -14838,6 +14857,10 @@ echo $request >> hv1/first.expected > > > > echo $request >> hv2/second.expected > > > > echo $request >> hv3/third.expected > > > > > > > > +# unicast from Second arrives to Third through localnet port > > > > +request=$(send_arp hv2 second 000000000002 000000000003 $second_spa > > > > $third_spa) > > > > +echo $request >> hv2/n1.expected > > > > + > > > > check_packets > > > > > > > > # Complete migration: destination is bound > > > > @@ -14860,6 +14883,7 @@ reset_env > > > > # unicast from Third arrives to hv2:Migrator > > > > request=$(send_arp hv3 third 000000000003 0000000000ff $third_spa > > > > $migrator_tpa) > > > > echo $request >> hv2/migrator.expected > > > > +echo $request >> hv3/n1.expected > > > > > > > > # mcast from Third doesn't arrive to hv1:Migrator > > > > # mcast from Third arrives to hv2:Migrator > > > > @@ -14867,11 +14891,13 @@ request=$(send_arp hv3 third 000000000003 > > > > ffffffffffff $third_spa $migrator_tpa) > > > > echo $request >> hv2/migrator.expected > > > > echo $request >> hv1/first.expected > > > > echo $request >> hv2/second.expected > > > > +echo $request >> hv3/n1.expected > > > > > > > > # unicast from First doesn't arrive to hv1:Migrator > > > > # unicast from First arrives to hv2:Migrator > > > > request=$(send_arp hv1 first 000000000001 0000000000ff $first_spa > > > > $migrator_tpa) > > > > echo $request >> hv2/migrator.expected > > > > +echo $request >> hv1/n1.expected > > > > > > > > # mcast from First doesn't arrive to hv1:Migrator > > > > # mcast from First arrives to hv2:Migrator binding > > > > @@ -14879,6 +14905,7 @@ request=$(send_arp hv1 first 000000000001 > > > > ffffffffffff $first_spa $migrator_tpa) > > > > echo $request >> hv2/migrator.expected > > > > echo $request >> hv2/second.expected > > > > echo $request >> hv3/third.expected > > > > +echo $request >> hv1/n1.expected > > > > > > > > # unicast from Second doesn't arrive to hv1:Migrator > > > > # unicast from Second arrives to hv2:Migrator > > > > @@ -14900,10 +14927,12 @@ request=$(send_arp hv1 migrator 0000000000ff > > > > 000000000003 $migrator_tpa $third_s > > > > # unicast from hv2:Migrator arrives to First, Second, and Third > > > > request=$(send_arp hv2 migrator 0000000000ff 000000000001 > > > > $migrator_tpa $first_spa) > > > > echo $request >> hv1/first.expected > > > > +echo $request >> hv2/n1.expected > > > > request=$(send_arp hv2 migrator 0000000000ff 000000000002 > > > > $migrator_tpa $second_spa) > > > > echo $request >> hv2/second.expected > > > > request=$(send_arp hv2 migrator 0000000000ff 000000000003 > > > > $migrator_tpa $third_spa) > > > > echo $request >> hv3/third.expected > > > > +echo $request >> hv2/n1.expected > > > > > > > > # mcast from hv1:Migrator doesn't arrive to First, Second, or Third > > > > request=$(send_arp hv1 migrator 0000000000ff ffffffffffff > > > > $migrator_tpa $first_spa) > > > > @@ -14913,6 +14942,7 @@ request=$(send_arp hv2 migrator 0000000000ff > > > > ffffffffffff $migrator_tpa $first_s > > > > echo $request >> hv1/first.expected > > > > echo $request >> hv2/second.expected > > > > echo $request >> hv3/third.expected > > > > +echo $request >> hv2/n1.expected > > > > > > > > check_packets > > > > > > > > > > > > > > _______________________________________________ > > > dev mailing list > > > d...@openvswitch.org > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > > > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev