here was a race within packet buffering that could result in first packt being dropped. It could happen under following conditions and topology: S1 == R1 == public == R2 == S2 SNAT on R1 and DGP on port connecting R1 with public.
1) The GARP is sent for the GDP SNAT 2) The GARP is delayed on R2 because it's multicast 3) Some traffic that get's buffered on S2 4) An ARP is sent as consequence of the buffering 5) The delayed MAC binding is added to SB 6) Response for the ARP is ignored because the MAC binding already exists 7) The buffered packet is never sent out and times out In order to prevent this behavior use the recent MAC bidning node. Signed-off-by: Ales Musil <[email protected]> --- v4: Rebase on top of current main. Split into three patches. --- controller/ovn-controller.c | 7 ++-- controller/pinctrl.c | 67 +++++-------------------------------- controller/pinctrl.h | 5 ++- 3 files changed, 14 insertions(+), 65 deletions(-) diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index d465f00e9..ce0976070 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -5033,6 +5033,8 @@ main(int argc, char *argv[]) engine_get_internal_data(&en_template_vars); struct ed_type_lb_data *lb_data = engine_get_internal_data(&en_lb_data); + struct hmap *recent_mac_bindings = + engine_get_internal_data(&en_recent_mac_bindings); ofctrl_init(&lflow_output_data->group_table, &lflow_output_data->meter_table, @@ -5385,14 +5387,13 @@ main(int argc, char *argv[]) ovnsb_idl_loop.idl), sbrec_service_monitor_table_get( ovnsb_idl_loop.idl), - sbrec_mac_binding_table_get( - ovnsb_idl_loop.idl), sbrec_bfd_table_get(ovnsb_idl_loop.idl), br_int, chassis, &runtime_data->local_datapaths, &runtime_data->active_tunnels, &runtime_data->local_active_ports_ipv6_pd, - &runtime_data->local_active_ports_ras); + &runtime_data->local_active_ports_ras, + recent_mac_bindings); stopwatch_stop(PINCTRL_RUN_STOPWATCH_NAME, time_msec()); mirror_run(ovs_idl_txn, diff --git a/controller/pinctrl.c b/controller/pinctrl.c index fcc278c8c..66dcb856c 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -180,9 +180,7 @@ static struct pinctrl pinctrl; static void init_buffered_packets_data(void); static void destroy_buffered_packets_data(void); -static void -run_buffered_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - const struct sbrec_mac_binding_table *mac_binding_table) +static void run_buffered_binding(const struct hmap *recent_mbs) OVS_REQUIRES(pinctrl_mutex); static void pinctrl_handle_put_mac_binding(const struct flow *md, @@ -3448,14 +3446,14 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_dns_table *dns_table, const struct sbrec_controller_event_table *ce_table, const struct sbrec_service_monitor_table *svc_mon_table, - const struct sbrec_mac_binding_table *mac_binding_table, const struct sbrec_bfd_table *bfd_table, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct hmap *local_datapaths, const struct sset *active_tunnels, const struct shash *local_active_ports_ipv6_pd, - const struct shash *local_active_ports_ras) + const struct shash *local_active_ports_ras, + const struct hmap *recent_mac_bindings) { ovs_mutex_lock(&pinctrl_mutex); run_put_mac_bindings(ovnsb_idl_txn, sbrec_datapath_binding_by_key, @@ -3478,7 +3476,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, sbrec_port_binding_by_key, sbrec_igmp_groups, sbrec_ip_multicast_opts); - run_buffered_binding(sbrec_port_binding_by_name, mac_binding_table); + run_buffered_binding(recent_mac_bindings); sync_svc_monitors(ovnsb_idl_txn, svc_mon_table, sbrec_port_binding_by_name, chassis); bfd_monitor_run(ovnsb_idl_txn, bfd_table, sbrec_port_binding_by_name, @@ -4269,67 +4267,18 @@ run_put_mac_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, } static void -run_buffered_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - const struct sbrec_mac_binding_table *mac_binding_table) +run_buffered_binding(const struct hmap *recent_mbs) OVS_REQUIRES(pinctrl_mutex) { - if (!hmap_count(&buffered_packets_map)) { + if (!hmap_count(&buffered_packets_map) || + !hmap_count(recent_mbs)) { return; } - struct hmap recent_mbs; - - hmap_init(&recent_mbs); - - const struct sbrec_mac_binding *smb; - SBREC_MAC_BINDING_TABLE_FOR_EACH_TRACKED (smb, mac_binding_table) { - const struct sbrec_port_binding *pb = lport_lookup_by_name( - sbrec_port_binding_by_name, smb->logical_port); - if (!pb || !pb->datapath) { - continue; - } - - struct eth_addr mac; - struct in6_addr ip; - ovs_be32 ip4; - - if (ip_parse(smb->ip, &ip4)) { - ip = in6_addr_mapped_ipv4(ip4); - } else if (!ipv6_parse(smb->ip, &ip)) { - continue; - } - - if (!eth_addr_from_string(smb->mac, &mac)) { - continue; - } - - ovn_mac_binding_add(&recent_mbs, smb->datapath->tunnel_key, - pb->tunnel_key, &ip, mac, 0, false); - - const char *redirect_port = - smap_get(&pb->options, "chassis-redirect-port"); - if (!redirect_port) { - continue; - } - - pb = lport_lookup_by_name(sbrec_port_binding_by_name, redirect_port); - if (!pb || pb->datapath->tunnel_key != smb->datapath->tunnel_key || - strcmp(pb->type, "chassisredirect")) { - continue; - } - - /* Add the same entry also for chassisredirect port as the buffered - * traffic might be buffered on the cr port. */ - ovn_mac_binding_add(&recent_mbs, smb->datapath->tunnel_key, - pb->tunnel_key, &ip, mac, 0, false); - } - ovn_buffured_packets_prepare_ready(&buffered_packets_map, - &recent_mbs, + recent_mbs, &ready_packets_data); - ovn_mac_bindings_destroy(&recent_mbs); - if (!ovs_list_is_empty(&ready_packets_data)) { notify_pinctrl_handler(); } diff --git a/controller/pinctrl.h b/controller/pinctrl.h index 279a49fbc..d45086b71 100644 --- a/controller/pinctrl.h +++ b/controller/pinctrl.h @@ -36,7 +36,6 @@ struct sbrec_controller_event_table; struct sbrec_service_monitor_table; struct sbrec_bfd_table; struct sbrec_port_binding; -struct sbrec_mac_binding_table; void pinctrl_init(void); void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, @@ -51,13 +50,13 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_dns_table *, const struct sbrec_controller_event_table *, const struct sbrec_service_monitor_table *, - const struct sbrec_mac_binding_table *, const struct sbrec_bfd_table *, const struct ovsrec_bridge *, const struct sbrec_chassis *, const struct hmap *local_datapaths, const struct sset *active_tunnels, const struct shash *local_active_ports_ipv6_pd, - const struct shash *local_active_ports_ras); + const struct shash *local_active_ports_ras, + const struct hmap *recent_mac_bindings); void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn); void pinctrl_destroy(void); void pinctrl_set_br_int_name(const char *br_int_name); -- 2.39.2 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
