Simplify the logic behind packet buffering and house those simplified helpers in mac-learn.c.
Signed-off-by: Ales Musil <[email protected]> --- v4: Rebase on top of current main. Split into three patches. --- controller/mac-learn.c | 171 ++++++++++++++++++--- controller/mac-learn.h | 50 ++++++- controller/pinctrl.c | 329 ++++++++++++----------------------------- 3 files changed, 298 insertions(+), 252 deletions(-) diff --git a/controller/mac-learn.c b/controller/mac-learn.c index a27607016..9d51693a7 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,11 +29,11 @@ VLOG_DEFINE_THIS_MODULE(mac_learn); #define MAX_MAC_BINDINGS 1000 #define MAX_FDB_ENTRIES 1000 -#define MAX_MAC_BINDING_DELAY_MSEC 50 +#define BUFFER_QUEUE_DEPTH 4 -static size_t mac_binding_hash(uint32_t dp_key, uint32_t port_key, - struct in6_addr *); -static struct mac_binding *mac_binding_find(struct hmap *mac_bindings, +static size_t keys_ip_hash(uint32_t dp_key, uint32_t port_key, + struct in6_addr *); +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); @@ -41,6 +41,12 @@ static size_t fdb_entry_hash(uint32_t dp_key, struct eth_addr *); static struct fdb_entry *fdb_entry_find(struct hmap *fdbs, uint32_t dp_key, struct eth_addr *mac, size_t hash); +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); +static void buffered_packets_destroy(struct buffered_packets *bp); /* mac_binding functions. */ void @@ -62,24 +68,23 @@ ovn_mac_bindings_destroy(struct hmap *mac_bindings) struct mac_binding * ovn_mac_binding_add(struct hmap *mac_bindings, uint32_t dp_key, uint32_t port_key, struct in6_addr *ip, - struct eth_addr mac, bool is_unicast) + struct eth_addr mac, uint32_t timestamp_offset, + bool limited_capacity) { - uint32_t hash = mac_binding_hash(dp_key, port_key, ip); + uint32_t hash = keys_ip_hash(dp_key, port_key, ip); struct mac_binding *mb = mac_binding_find(mac_bindings, dp_key, port_key, ip, hash); if (!mb) { - if (hmap_count(mac_bindings) >= MAX_MAC_BINDINGS) { + if (limited_capacity && hmap_count(mac_bindings) >= MAX_MAC_BINDINGS) { return NULL; } - uint32_t delay = is_unicast - ? 0 : random_range(MAX_MAC_BINDING_DELAY_MSEC) + 1; mb = xmalloc(sizeof *mb); mb->dp_key = dp_key; mb->port_key = port_key; mb->ip = *ip; - mb->commit_at_ms = time_msec() + delay; + mb->expire = time_msec() + timestamp_offset; hmap_insert(mac_bindings, &mb->hmap_node, hash); } mb->mac = mac; @@ -94,7 +99,7 @@ ovn_mac_binding_wait(struct hmap *mac_bindings) struct mac_binding *mb; HMAP_FOR_EACH (mb, hmap_node, mac_bindings) { - poll_timer_wait_until(mb->commit_at_ms); + poll_timer_wait_until(mb->expire); } } @@ -106,9 +111,9 @@ ovn_mac_binding_remove(struct mac_binding *mb, struct hmap *mac_bindings) } bool -ovn_mac_binding_can_commit(const struct mac_binding *mb, long long now) +ovn_mac_binding_is_expired(const struct mac_binding *mb, long long now) { - return now >= mb->commit_at_ms; + return now >= mb->expire; } /* fdb functions. */ @@ -158,17 +163,126 @@ ovn_fdb_add(struct hmap *fdbs, uint32_t dp_key, struct eth_addr mac, } +/* packet buffering functions */ +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); + } +} + + /* mac_binding related static functions. */ static size_t -mac_binding_hash(uint32_t dp_key, uint32_t port_key, struct in6_addr *ip) +keys_ip_hash(uint32_t dp_key, uint32_t port_key, struct in6_addr *ip) { return hash_bytes(ip, sizeof *ip, hash_2words(dp_key, port_key)); } 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) { @@ -203,3 +317,26 @@ fdb_entry_find(struct hmap *fdbs, uint32_t dp_key, return NULL; } + +/* packet buffering static functions. */ +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); +} diff --git a/controller/mac-learn.h b/controller/mac-learn.h index 57c50c58b..b6ff28650 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,20 +36,22 @@ struct mac_binding { /* Value. */ struct eth_addr mac; - /* Timestamp when to commit to SB. */ - long long commit_at_ms; + /* Timestamp in ms indicating when the MAC binding should expire. */ + long long expire; }; void ovn_mac_bindings_init(struct hmap *mac_bindings); void ovn_mac_bindings_destroy(struct hmap *mac_bindings); void ovn_mac_binding_wait(struct hmap *mac_bindings); void ovn_mac_binding_remove(struct mac_binding *mb, struct hmap *mac_bindings); -bool ovn_mac_binding_can_commit(const struct mac_binding *mb, long long now); +bool ovn_mac_binding_is_expired(const struct mac_binding *mb, long long now); struct mac_binding *ovn_mac_binding_add(struct hmap *mac_bindings, uint32_t dp_key, uint32_t port_key, struct in6_addr *ip, - struct eth_addr mac, bool is_unicast); + struct eth_addr mac, + uint32_t timestamp_offset, + bool limited_capacity); @@ -68,4 +74,40 @@ 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/pinctrl.c b/controller/pinctrl.c index 795847729..fcc278c8c 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -178,8 +178,8 @@ struct pinctrl { static struct pinctrl pinctrl; -static void init_buffered_packets_map(void); -static void destroy_buffered_packets_map(void); +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) @@ -535,7 +535,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,222 +1416,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); - } -} - -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; + ovs_list_init(&ready_packets_data); } 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; - } -} - -#define BUFFER_MAP_TIMEOUT 10000 -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 + BUFFER_MAP_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) +destroy_buffered_packets_data(void) { - 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) -{ - 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. */ @@ -4154,7 +4004,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(); @@ -4196,6 +4046,8 @@ destroy_put_mac_bindings(void) ovn_mac_bindings_destroy(&put_mac_bindings); } +#define MAX_MAC_BINDING_DELAY_MSEC 50 + /* Called with in the pinctrl_handler thread context. */ static void pinctrl_handle_put_mac_binding(const struct flow *md, @@ -4216,11 +4068,13 @@ pinctrl_handle_put_mac_binding(const struct flow *md, /* If the ARP reply was unicast we should not delay it, * there won't be any race. */ - bool is_unicast = !eth_addr_is_multicast(headers->dl_dst); + uint32_t delay = eth_addr_is_multicast(headers->dl_dst) + ? random_range(MAX_MAC_BINDING_DELAY_MSEC) + 1 + : 0; struct mac_binding *mb = ovn_mac_binding_add(&put_mac_bindings, dp_key, port_key, &ip_key, headers->dl_src, - is_unicast); + delay, true); if (!mb) { COVERAGE_INC(pinctrl_drop_put_mac_binding); return; @@ -4237,12 +4091,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 * @@ -4391,7 +4258,7 @@ run_put_mac_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, struct mac_binding *mb; HMAP_FOR_EACH_SAFE (mb, hmap_node, &put_mac_bindings) { - if (ovn_mac_binding_can_commit(mb, now)) { + if (ovn_mac_binding_is_expired(mb, now)) { run_put_mac_binding(ovnsb_idl_txn, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, @@ -4406,64 +4273,64 @@ run_buffered_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, const struct sbrec_mac_binding_table *mac_binding_table) OVS_REQUIRES(pinctrl_mutex) { - bool notify = false; - if (!hmap_count(&buffered_packets_map)) { return; } - const struct sbrec_mac_binding *mb; - SBREC_MAC_BINDING_TABLE_FOR_EACH_TRACKED (mb, mac_binding_table) { + 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, mb->logical_port); + 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(mb->ip, &ip4)) { + + if (ip_parse(smb->ip, &ip4)) { ip = in6_addr_mapped_ipv4(ip4); - } else if (!ipv6_parse(mb->ip, &ip)) { + } else if (!ipv6_parse(smb->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 (!eth_addr_from_string(smb->mac, &mac)) { + continue; } - if (!bp) { + 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; } - if (!ovs_scan(mb->mac, ETH_ADDR_SCAN_FMT, - ETH_ADDR_SCAN_ARGS(bp->ea))) { + 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; } - hmap_remove(&buffered_packets_map, &bp->hmap_node); - ovs_list_push_back(&buffered_mac_bindings, &bp->list); - notify = true; + /* 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); } - buffered_packets_map_gc(); - if (notify) { + ovn_buffured_packets_prepare_ready(&buffered_packets_map, + &recent_mbs, + &ready_packets_data); + + ovn_mac_bindings_destroy(&recent_mbs); + + if (!ovs_list_is_empty(&ready_packets_data)) { notify_pinctrl_handler(); } } @@ -6070,7 +5937,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()); } -- 2.39.2 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
