On Mon, Mar 13, 2023 at 7:31 AM Ales Musil <[email protected]> wrote:
>
> There 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 binding
> node.
>
> At the same time simplify the packet buffering process
> and move it to mac-learn module.
>
> Signed-off-by: Ales Musil <[email protected]>
Hi Ales,
A few higher level comments. I haven't reviewed completely
1. In the file controller/mac-learn.c, can you please add
non-static functions before the start of static
functions as per the coding guidelines
(https://github.com/ovn-org/ovn/blob/main/Documentation/internals/contributing/coding-style.rst)
2. Can you please add a new patch - patch 2 to just move the
buffering related functions from pinctrl.c to mac-learn.c ? And then
make this patch as patch 3 which really fixes the issue.
It would help in reviewing the code and understand the changes
required to fix the issue.
Thanks
Numan
> ---
> v2: Rebase on top of current main.
> v3: Split into two patches.
> ---
> controller/mac-learn.c | 138 ++++++++++++++-
> controller/mac-learn.h | 38 ++++-
> controller/ovn-controller.c | 7 +-
> controller/pinctrl.c | 325 ++++++++----------------------------
> controller/pinctrl.h | 4 +-
> 5 files changed, 246 insertions(+), 266 deletions(-)
>
> diff --git a/controller/mac-learn.c b/controller/mac-learn.c
> index 29c8b1fbb..c1acf03d2 100644
> --- a/controller/mac-learn.c
> +++ b/controller/mac-learn.c
> @@ -18,10 +18,10 @@
> #include "mac-learn.h"
>
> /* OpenvSwitch lib includes. */
> +#include "dp-packet.h"
> #include "openvswitch/poll-loop.h"
> #include "openvswitch/vlog.h"
> #include "lib/packets.h"
> -#include "lib/random.h"
> #include "lib/smap.h"
> #include "lib/timeval.h"
>
> @@ -29,10 +29,11 @@ VLOG_DEFINE_THIS_MODULE(mac_learn);
>
> #define MAX_MAC_BINDINGS 1000
> #define MAX_FDB_ENTRIES 1000
> +#define BUFFER_QUEUE_DEPTH 4
>
> static size_t keys_ip_hash(uint32_t dp_key, uint32_t port_key,
> struct in6_addr *);
> -static struct mac_binding *mac_binding_find(struct hmap *mac_bindings,
> +static struct mac_binding *mac_binding_find(const struct hmap *mac_bindings,
> uint32_t dp_key,
> uint32_t port_key,
> struct in6_addr *ip, size_t
> hash);
> @@ -165,8 +166,8 @@ keys_ip_hash(uint32_t dp_key, uint32_t port_key, struct
> in6_addr *ip)
> }
>
> static struct mac_binding *
> -mac_binding_find(struct hmap *mac_bindings, uint32_t dp_key,
> - uint32_t port_key, struct in6_addr *ip, size_t hash)
> +mac_binding_find(const struct hmap *mac_bindings, uint32_t dp_key,
> + uint32_t port_key, struct in6_addr *ip, size_t hash)
> {
> struct mac_binding *mb;
> HMAP_FOR_EACH_WITH_HASH (mb, hmap_node, hash, mac_bindings) {
> @@ -201,3 +202,132 @@ fdb_entry_find(struct hmap *fdbs, uint32_t dp_key,
>
> return NULL;
> }
> +
> +static struct buffered_packets *
> +buffered_packets_find(struct hmap *hmap, uint64_t dp_key, uint64_t port_key,
> + struct in6_addr *ip, uint32_t hash)
> +{
> + struct buffered_packets *mb;
> + HMAP_FOR_EACH_WITH_HASH (mb, hmap_node, hash, hmap) {
> + if (mb->dp_key == dp_key && mb->port_key == port_key &&
> + IN6_ARE_ADDR_EQUAL(&mb->ip, ip)) {
> + return mb;
> + }
> + }
> +
> + return NULL;
> +}
> +
> +static void
> +buffered_packets_destroy(struct buffered_packets *bp)
> +{
> + ovn_packet_data_list_destroy(&bp->queue);
> + free(bp);
> +}
> +
> +struct buffered_packets *
> +ovn_buffered_packets_add(struct hmap *hmap, uint64_t dp_key, uint64_t
> port_key,
> + struct in6_addr ip)
> +{
> + struct buffered_packets *bp;
> +
> + uint32_t hash = keys_ip_hash(dp_key, port_key, &ip);
> + bp = buffered_packets_find(hmap, dp_key, port_key, &ip, hash);
> + if (!bp) {
> + if (hmap_count(hmap) >= 1000) {
> + return NULL;
> + }
> +
> + bp = xmalloc(sizeof *bp);
> + hmap_insert(hmap, &bp->hmap_node, hash);
> + bp->ip = ip;
> + bp->dp_key = dp_key;
> + bp->port_key = port_key;
> + ovs_list_init(&bp->queue);
> + }
> +
> + bp->expire = time_msec() + OVN_BUFFERED_PACKETS_TIMEOUT;
> +
> + return bp;
> +}
> +
> +void
> +ovn_buffered_packets_add_packet_data(struct buffered_packets *bp,
> + struct ofpbuf ofpacts,
> + struct dp_packet *packet)
> +{
> + struct packet_data *pd = xmalloc(sizeof *pd);
> +
> + pd->ofpacts = ofpacts;
> + pd->p = packet;
> +
> + if (ovs_list_size(&bp->queue) == BUFFER_QUEUE_DEPTH) {
> + struct packet_data *p = CONTAINER_OF(ovs_list_pop_front(&bp->queue),
> + struct packet_data, node);
> + ovn_packet_data_destroy(p);
> + }
> +
> + ovs_list_push_back(&bp->queue, &pd->node);
> +}
> +
> +void
> +ovn_buffured_packets_prepare_ready(struct hmap *bp_hmap,
> + const struct hmap *recent_mac_bindings,
> + struct ovs_list *ready_packet_data)
> +{
> + long long now = time_msec();
> +
> + struct buffered_packets *bp;
> + HMAP_FOR_EACH_SAFE (bp, hmap_node, bp_hmap) {
> + if (now > bp->expire) {
> + hmap_remove(bp_hmap, &bp->hmap_node);
> + buffered_packets_destroy(bp);
> + continue;
> + }
> +
> + uint32_t hash = keys_ip_hash(bp->dp_key, bp->port_key, &bp->ip);
> + struct mac_binding *mb = mac_binding_find(recent_mac_bindings,
> + bp->dp_key, bp->port_key,
> + &bp->ip, hash);
> + if (!mb) {
> + continue;
> + }
> +
> + struct packet_data *pd;
> + LIST_FOR_EACH_POP (pd, node, &bp->queue) {
> + struct eth_header *eth = dp_packet_data(pd->p);
> + eth->eth_dst = mb->mac;
> +
> + ovs_list_push_back(ready_packet_data, &pd->node);
> + }
> +
> + hmap_remove(bp_hmap, &bp->hmap_node);
> + buffered_packets_destroy(bp);
> + }
> +}
> +
> +void
> +ovn_packet_data_destroy(struct packet_data *pd)
> +{
> + dp_packet_delete(pd->p);
> + ofpbuf_uninit(&pd->ofpacts);
> + free(pd);
> +}
> +
> +void
> +ovn_packet_data_list_destroy(struct ovs_list *list)
> +{
> + struct packet_data *pd;
> + LIST_FOR_EACH_POP (pd, node, list) {
> + ovn_packet_data_destroy(pd);
> + }
> +}
> +
> +void
> +ovn_buffered_packets_hmap_destroy(struct hmap *hmap)
> +{
> + struct buffered_packets *bp;
> + HMAP_FOR_EACH_POP (bp, hmap_node, hmap) {
> + buffered_packets_destroy(bp);
> + }
> +}
> diff --git a/controller/mac-learn.h b/controller/mac-learn.h
> index 20b6e3b63..7b342d339 100644
> --- a/controller/mac-learn.h
> +++ b/controller/mac-learn.h
> @@ -19,7 +19,11 @@
>
> #include <sys/types.h>
> #include <netinet/in.h>
> +
> +#include "dp-packet.h"
> #include "openvswitch/hmap.h"
> +#include "openvswitch/list.h"
> +#include "openvswitch/ofpbuf.h"
>
> struct mac_binding {
> struct hmap_node hmap_node; /* In a hmap. */
> @@ -32,7 +36,6 @@ struct mac_binding {
> /* Value. */
> struct eth_addr mac;
>
> - /* Timestamp when to commit to SB. */
> long long expire;
> };
>
> @@ -70,6 +73,39 @@ struct fdb_entry *ovn_fdb_add(struct hmap *fdbs,
> uint32_t dp_key, struct eth_addr mac,
> uint32_t port_key);
>
> +struct packet_data {
> + struct ovs_list node;
> +
> + struct ofpbuf ofpacts;
> + struct dp_packet *p;
> +};
> +
> +struct buffered_packets {
> + struct hmap_node hmap_node;
> +
> + struct in6_addr ip;
> + uint64_t dp_key;
> + uint64_t port_key;
> +
> + struct ovs_list queue;
> +
> + long long int expire;
> +};
> +
> #define OVN_BUFFERED_PACKETS_TIMEOUT 10000
>
> +struct buffered_packets *ovn_buffered_packets_add(struct hmap *hmap,
> + uint64_t dp_key,
> + uint64_t port_key,
> + struct in6_addr ip);
> +void ovn_buffered_packets_add_packet_data(struct buffered_packets *bp,
> + struct ofpbuf ofpacts,
> + struct dp_packet *packet);
> +void ovn_buffured_packets_prepare_ready(struct hmap *bp_hmap,
> + const struct hmap
> *recent_mac_bindings,
> + struct ovs_list *ready_packet_data);
> +void ovn_packet_data_destroy(struct packet_data *pd);
> +void ovn_packet_data_list_destroy(struct ovs_list *list);
> +void ovn_buffered_packets_hmap_destroy(struct hmap *hmap);
> +
> #endif /* OVN_MAC_LEARN_H */
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index a42c1affe..4bf841903 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -5035,6 +5035,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,
> @@ -5387,14 +5389,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 611c19568..e57fd4da1 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -178,11 +178,9 @@ struct pinctrl {
>
> static struct pinctrl pinctrl;
>
> -static void init_buffered_packets_map(void);
> -static void destroy_buffered_packets_map(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 init_buffered_packets_data(void);
> +static void destroy_buffered_packets_data(void);
> +static void run_buffered_binding(const struct hmap *recent_mac_bidnings)
> OVS_REQUIRES(pinctrl_mutex);
>
> static void pinctrl_handle_put_mac_binding(const struct flow *md,
> @@ -535,7 +533,7 @@ pinctrl_init(void)
> init_send_garps_rarps();
> init_ipv6_ras();
> init_ipv6_prefixd();
> - init_buffered_packets_map();
> + init_buffered_packets_data();
> init_activated_ports();
> init_event_table();
> ip_mcast_snoop_init();
> @@ -1416,221 +1414,72 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn
> *ovnsb_idl_txn,
> }
> }
>
> -struct buffer_info {
> - struct ofpbuf ofpacts;
> - struct dp_packet *p;
> -};
> -
> -#define BUFFER_QUEUE_DEPTH 4
> -struct buffered_packets {
> - struct hmap_node hmap_node;
> - struct ovs_list list;
> -
> - /* key */
> - struct in6_addr ip;
> - struct eth_addr ea;
> -
> - uint64_t dp_key;
> - uint64_t port_key;
> -
> - long long int timestamp;
> -
> - struct buffer_info data[BUFFER_QUEUE_DEPTH];
> - uint32_t head, tail;
> -};
> -
> static struct hmap buffered_packets_map;
> -static struct ovs_list buffered_mac_bindings;
> +/* List of 'struct packet_data' that is ready to be sent. */
> +static struct ovs_list ready_packets_data;
>
> static void
> -init_buffered_packets_map(void)
> +init_buffered_packets_data(void)
> {
> hmap_init(&buffered_packets_map);
> - ovs_list_init(&buffered_mac_bindings);
> -}
> -
> -static void
> -destroy_buffered_packets(struct buffered_packets *bp)
> -{
> - struct buffer_info *bi;
> -
> - while (bp->head != bp->tail) {
> - bi = &bp->data[bp->head];
> - dp_packet_delete(bi->p);
> - ofpbuf_uninit(&bi->ofpacts);
> -
> - bp->head = (bp->head + 1) % BUFFER_QUEUE_DEPTH;
> - }
> -}
> -
> -static void
> -destroy_buffered_packets_map(void)
> -{
> - struct buffered_packets *bp;
> - HMAP_FOR_EACH_SAFE (bp, hmap_node, &buffered_packets_map) {
> - destroy_buffered_packets(bp);
> - hmap_remove(&buffered_packets_map, &bp->hmap_node);
> - free(bp);
> - }
> - hmap_destroy(&buffered_packets_map);
> -
> - LIST_FOR_EACH_POP (bp, list, &buffered_mac_bindings) {
> - destroy_buffered_packets(bp);
> - free(bp);
> - }
> + ovs_list_init(&ready_packets_data);
> }
>
> static void
> -buffered_push_packet(struct buffered_packets *bp,
> - struct dp_packet *packet,
> - const struct match *md)
> -{
> - uint32_t next = (bp->tail + 1) % BUFFER_QUEUE_DEPTH;
> - struct buffer_info *bi = &bp->data[bp->tail];
> -
> - ofpbuf_init(&bi->ofpacts, 4096);
> -
> - reload_metadata(&bi->ofpacts, md);
> - /* reload pkt_mark field */
> - const struct mf_field *pkt_mark_field = mf_from_id(MFF_PKT_MARK);
> - union mf_value pkt_mark_value;
> - mf_get_value(pkt_mark_field, &md->flow, &pkt_mark_value);
> - ofpact_put_set_field(&bi->ofpacts, pkt_mark_field, &pkt_mark_value,
> NULL);
> -
> - struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&bi->ofpacts);
> - resubmit->in_port = OFPP_CONTROLLER;
> - resubmit->table_id = OFTABLE_REMOTE_OUTPUT;
> -
> - bi->p = packet;
> -
> - if (next == bp->head) {
> - bi = &bp->data[bp->head];
> - dp_packet_delete(bi->p);
> - ofpbuf_uninit(&bi->ofpacts);
> - bp->head = (bp->head + 1) % BUFFER_QUEUE_DEPTH;
> - }
> - bp->tail = next;
> -}
> -
> -static void
> -buffered_send_packets(struct rconn *swconn, struct buffered_packets *bp,
> - struct eth_addr *addr)
> -{
> - enum ofp_version version = rconn_get_version(swconn);
> - enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version);
> -
> - while (bp->head != bp->tail) {
> - struct buffer_info *bi = &bp->data[bp->head];
> - struct eth_header *eth = dp_packet_data(bi->p);
> -
> - eth->eth_dst = *addr;
> - struct ofputil_packet_out po = {
> - .packet = dp_packet_data(bi->p),
> - .packet_len = dp_packet_size(bi->p),
> - .buffer_id = UINT32_MAX,
> - .ofpacts = bi->ofpacts.data,
> - .ofpacts_len = bi->ofpacts.size,
> - };
> - match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER);
> - queue_msg(swconn, ofputil_encode_packet_out(&po, proto));
> -
> - ofpbuf_uninit(&bi->ofpacts);
> - dp_packet_delete(bi->p);
> -
> - bp->head = (bp->head + 1) % BUFFER_QUEUE_DEPTH;
> - }
> -}
> -
> -static void
> -buffered_packets_map_gc(void)
> -{
> - struct buffered_packets *cur_qp;
> - long long int now = time_msec();
> -
> - HMAP_FOR_EACH_SAFE (cur_qp, hmap_node, &buffered_packets_map) {
> - if (now > cur_qp->timestamp + OVN_BUFFERED_PACKETS_TIMEOUT) {
> - destroy_buffered_packets(cur_qp);
> - hmap_remove(&buffered_packets_map, &cur_qp->hmap_node);
> - free(cur_qp);
> - }
> - }
> -}
> -
> -static uint32_t
> -pinctrl_buffer_packet_hash(uint64_t dp_key, uint64_t port_key,
> - const struct in6_addr *addr)
> -{
> - uint32_t hash = 0;
> - hash = hash_add64(hash, port_key);
> - hash = hash_add64(hash, dp_key);
> - hash = hash_bytes(addr, sizeof addr, hash);
> - return hash_finish(hash, 16);
> -}
> -
> -static struct buffered_packets *
> -pinctrl_find_buffered_packets(uint64_t dp_key, uint64_t port_key,
> - const struct in6_addr *ip, uint32_t hash)
> -{
> - struct buffered_packets *qp;
> - HMAP_FOR_EACH_WITH_HASH (qp, hmap_node, hash, &buffered_packets_map) {
> - if (qp->dp_key == dp_key && qp->port_key == port_key &&
> - IN6_ARE_ADDR_EQUAL(&qp->ip, ip)) {
> - return qp;
> - }
> - }
> - return NULL;
> -}
> -
> -static struct buffered_packets *
> -pinctrl_find_buffered_packets_with_hash(uint64_t dp_key, uint64_t port_key,
> - const struct in6_addr *ip)
> +destroy_buffered_packets_data(void)
> {
> - uint32_t hash = pinctrl_buffer_packet_hash(dp_key, port_key, ip);
> -
> - return pinctrl_find_buffered_packets(dp_key, port_key, ip, hash);
> + ovn_buffered_packets_hmap_destroy(&buffered_packets_map);
> + ovn_packet_data_list_destroy(&ready_packets_data);
> }
>
> /* Called with in the pinctrl_handler thread context. */
> -static int
> +static void
> pinctrl_handle_buffered_packets(struct dp_packet *pkt_in,
> const struct match *md, bool is_arp)
> OVS_REQUIRES(pinctrl_mutex)
> {
> - struct buffered_packets *bp;
> + struct in6_addr ip;
> + struct ofpbuf ofpacts;
> struct dp_packet *clone;
> - struct in6_addr addr;
> + struct buffered_packets *bp;
> uint64_t dp_key = ntohll(md->flow.metadata);
> uint64_t oport_key = md->flow.regs[MFF_LOG_OUTPORT - MFF_REG0];
>
> if (is_arp) {
> - addr = in6_addr_mapped_ipv4(htonl(md->flow.regs[0]));
> + ip = in6_addr_mapped_ipv4(htonl(md->flow.regs[0]));
> } else {
> ovs_be128 ip6 = hton128(flow_get_xxreg(&md->flow, 0));
> - memcpy(&addr, &ip6, sizeof addr);
> + memcpy(&ip, &ip6, sizeof ip);
> }
>
> - uint32_t hash = pinctrl_buffer_packet_hash(dp_key, oport_key, &addr);
> - bp = pinctrl_find_buffered_packets(dp_key, oport_key, &addr, hash);
> + bp = ovn_buffered_packets_add(&buffered_packets_map, dp_key,
> + oport_key, ip);
> if (!bp) {
> - if (hmap_count(&buffered_packets_map) >= 1000) {
> - COVERAGE_INC(pinctrl_drop_buffered_packets_map);
> - return -ENOMEM;
> - }
> -
> - bp = xmalloc(sizeof *bp);
> - hmap_insert(&buffered_packets_map, &bp->hmap_node, hash);
> - bp->head = bp->tail = 0;
> - bp->ip = addr;
> - bp->dp_key = dp_key;
> - bp->port_key = oport_key;
> + COVERAGE_INC(pinctrl_drop_buffered_packets_map);
> + return;
> }
> - bp->timestamp = time_msec();
> +
> /* clone the packet to send it later with correct L2 address */
> clone = dp_packet_clone_data(dp_packet_data(pkt_in),
> dp_packet_size(pkt_in));
> - buffered_push_packet(bp, clone, md);
>
> - return 0;
> +
> + ofpbuf_init(&ofpacts, 4096);
> + reload_metadata(&ofpacts, md);
> + /* reload pkt_mark field */
> + const struct mf_field *pkt_mark_field = mf_from_id(MFF_PKT_MARK);
> + union mf_value pkt_mark_value;
> + mf_get_value(pkt_mark_field, &md->flow, &pkt_mark_value);
> + ofpact_put_set_field(&ofpacts, pkt_mark_field, &pkt_mark_value, NULL);
> +
> + struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts);
> + resubmit->in_port = OFPP_CONTROLLER;
> + resubmit->table_id = OFTABLE_REMOTE_OUTPUT;
> +
> + ovn_buffered_packets_add_packet_data(bp, ofpacts, clone);
> +
> + /* There is a chance that the MAC binding was already created. */
> + notify_pinctrl_main();
> }
>
> /* Called with in the pinctrl_handler thread context. */
> @@ -3597,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,
> @@ -3627,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,
> @@ -4153,7 +4002,7 @@ pinctrl_destroy(void)
> destroy_send_garps_rarps();
> destroy_ipv6_ras();
> destroy_ipv6_prefixd();
> - destroy_buffered_packets_map();
> + destroy_buffered_packets_data();
> destroy_activated_ports();
> event_table_destroy();
> destroy_put_mac_bindings();
> @@ -4240,12 +4089,25 @@ static void
> send_mac_binding_buffered_pkts(struct rconn *swconn)
> OVS_REQUIRES(pinctrl_mutex)
> {
> - struct buffered_packets *bp;
> - LIST_FOR_EACH_POP (bp, list, &buffered_mac_bindings) {
> - buffered_send_packets(swconn, bp, &bp->ea);
> - free(bp);
> + enum ofp_version version = rconn_get_version(swconn);
> + enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version);
> +
> + struct packet_data *pd;
> + LIST_FOR_EACH_POP (pd, node, &ready_packets_data) {
> + struct ofputil_packet_out po = {
> + .packet = dp_packet_data(pd->p),
> + .packet_len = dp_packet_size(pd->p),
> + .buffer_id = UINT32_MAX,
> + .ofpacts = pd->ofpacts.data,
> + .ofpacts_len = pd->ofpacts.size,
> + };
> + match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER);
> + queue_msg(swconn, ofputil_encode_packet_out(&po, proto));
> +
> + ovn_packet_data_destroy(pd);
> }
> - ovs_list_init(&buffered_mac_bindings);
> +
> + ovs_list_init(&ready_packets_data);
> }
>
> static const struct sbrec_mac_binding *
> @@ -4405,68 +4267,19 @@ 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_mac_bidnings)
> OVS_REQUIRES(pinctrl_mutex)
> {
> - bool notify = false;
> -
> - if (!hmap_count(&buffered_packets_map)) {
> + if (!hmap_count(&buffered_packets_map) ||
> + !hmap_count(recent_mac_bidnings)) {
> return;
> }
>
> - const struct sbrec_mac_binding *mb;
> - SBREC_MAC_BINDING_TABLE_FOR_EACH_TRACKED (mb, mac_binding_table) {
> - const struct sbrec_port_binding *pb = lport_lookup_by_name(
> - sbrec_port_binding_by_name, mb->logical_port);
> - if (!pb || !pb->datapath) {
> - continue;
> - }
> + ovn_buffured_packets_prepare_ready(&buffered_packets_map,
> + recent_mac_bidnings,
> + &ready_packets_data);
>
> - struct in6_addr ip;
> - ovs_be32 ip4;
> - if (ip_parse(mb->ip, &ip4)) {
> - ip = in6_addr_mapped_ipv4(ip4);
> - } else if (!ipv6_parse(mb->ip, &ip)) {
> - continue;
> - }
> -
> - struct buffered_packets *bp =
> pinctrl_find_buffered_packets_with_hash(
> - pb->datapath->tunnel_key, pb->tunnel_key, &ip);
> - if (!bp) {
> - if (!smap_get(&pb->options, "chassis-redirect-port")) {
> - continue;
> - }
> -
> - char *redirect_name = xasprintf("cr-%s", pb->logical_port);
> - pb = lport_lookup_by_name(sbrec_port_binding_by_name,
> - redirect_name);
> - free(redirect_name);
> -
> - if (!pb || !pb->datapath || strcmp(pb->type, "chassisredirect"))
> {
> - continue;
> - }
> -
> - bp = pinctrl_find_buffered_packets_with_hash(
> - pb->datapath->tunnel_key, pb->tunnel_key, &ip);
> - }
> -
> - if (!bp) {
> - continue;
> - }
> -
> - if (!ovs_scan(mb->mac, ETH_ADDR_SCAN_FMT,
> - ETH_ADDR_SCAN_ARGS(bp->ea))) {
> - continue;
> - }
> -
> - hmap_remove(&buffered_packets_map, &bp->hmap_node);
> - ovs_list_push_back(&buffered_mac_bindings, &bp->list);
> - notify = true;
> - }
> - buffered_packets_map_gc();
> -
> - if (notify) {
> + if (!ovs_list_is_empty(&ready_packets_data)) {
> notify_pinctrl_handler();
> }
> }
> @@ -6073,7 +5886,7 @@ may_inject_pkts(void)
> !shash_is_empty(&send_garp_rarp_data) ||
> ipv6_prefixd_should_inject() ||
> !ovs_list_is_empty(&mcast_query_list) ||
> - !ovs_list_is_empty(&buffered_mac_bindings) ||
> + !ovs_list_is_empty(&ready_packets_data) ||
> bfd_monitor_should_inject());
> }
>
> diff --git a/controller/pinctrl.h b/controller/pinctrl.h
> index 279a49fbc..cf4071952 100644
> --- a/controller/pinctrl.h
> +++ b/controller/pinctrl.h
> @@ -51,13 +51,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
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev