On 4/28/23 11:42, Ales Musil wrote: > Move the refactored packet buffering infrastructure into > mac-learn module. This encapsulates the whole packet buffering > process behind few functions. > > Signed-off-by: Ales Musil <amu...@redhat.com> > --- > controller/mac-learn.c | 231 ++++++++++++++++++++++++++++++++++++----- > controller/mac-learn.h | 63 +++++++++-- > controller/pinctrl.c | 198 ++--------------------------------- > 3 files changed, 271 insertions(+), 221 deletions(-) > > diff --git a/controller/mac-learn.c b/controller/mac-learn.c > index ecc3c2acc..a2d3417eb 100644 > --- a/controller/mac-learn.c > +++ b/controller/mac-learn.c > @@ -18,21 +18,34 @@ > #include "mac-learn.h" > > /* OpenvSwitch lib includes. */ > +#include "dp-packet.h"
Nit: It's already included by "mac-learn.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" > > VLOG_DEFINE_THIS_MODULE(mac_learn); > > -#define MAX_FDB_ENTRIES 1000 > +#define MAX_FDB_ENTRIES 1000 > +#define MAX_BUFFERED_PACKETS 1000 > +#define BUFFER_QUEUE_DEPTH 4 > > +static size_t keys_ip_hash(uint32_t dp_key, uint32_t port_key, > + struct in6_addr *ip); > +static struct mac_binding *mac_binding_find(const struct mac_bindings_map > + *mac_bindings, uint32_t dp_key, > + uint32_t port_key, > + struct in6_addr *ip, size_t > hash); > 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 buffered_packets_ctx *ctx, uint64_t dp_key, > + uint64_t port_key, struct in6_addr *ip, uint32_t hash); > +static void ovn_buffered_packets_remove(struct buffered_packets_ctx *ctx, > + struct buffered_packets *bp); > > /* mac_binding functions. */ > void > @@ -62,7 +75,7 @@ ovn_mac_binding_add(struct mac_bindings_map *mac_bindings, > uint32_t dp_key, > uint32_t hash = keys_ip_hash(dp_key, port_key, ip); > > struct mac_binding *mb = > - ovn_mac_binding_find(mac_bindings, dp_key, port_key, ip, hash); > + mac_binding_find(mac_bindings, dp_key, port_key, ip, hash); > size_t max_size = mac_bindings->max_size; > if (!mb) { > if (max_size && hmap_count(&mac_bindings->map) >= max_size) { > @@ -109,29 +122,6 @@ ovn_is_mac_binding_timestamp_past(const struct > mac_binding *mb, long long now) > return now >= mb->timestamp; > } > > -size_t > -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)); > -} > - > -struct mac_binding * > -ovn_mac_binding_find(const struct mac_bindings_map *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->map) { > - if (mb->dp_key == dp_key && mb->port_key == port_key && > - IN6_ARE_ADDR_EQUAL(&mb->ip, ip)) { > - return mb; > - } > - } > - > - return NULL; > -} > - > /* fdb functions. */ > void > ovn_fdb_init(struct hmap *fdbs) > @@ -179,6 +169,164 @@ ovn_fdb_add(struct hmap *fdbs, uint32_t dp_key, struct > eth_addr mac, > > } > > +/* packet buffering functions */ > + > +struct packet_data * > +ovn_packet_data_create(struct ofpbuf ofpacts, > + const struct dp_packet *original_packet) > +{ > + struct packet_data *pd = xmalloc(sizeof *pd); > + > + pd->ofpacts = ofpacts; > + /* clone the packet to send it later with correct L2 address */ > + pd->p = dp_packet_clone_data(dp_packet_data(original_packet), > + dp_packet_size(original_packet)); > + > + return pd; > +} > + > + > +void > +ovn_packet_data_destroy(struct packet_data *pd) > +{ > + dp_packet_delete(pd->p); > + ofpbuf_uninit(&pd->ofpacts); > + free(pd); > +} > + > +struct buffered_packets * > +ovn_buffered_packets_add(struct buffered_packets_ctx *ctx, 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(ctx, dp_key, port_key, &ip, hash); > + if (!bp) { > + if (hmap_count(&ctx->buffered_packets) >= MAX_BUFFERED_PACKETS) { > + return NULL; > + } > + > + bp = xmalloc(sizeof *bp); > + hmap_insert(&ctx->buffered_packets, &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_packet_data_enqueue(struct buffered_packets *bp, > + struct packet_data *pd) > +{ > + 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_buffered_packets_ctx_run(struct buffered_packets_ctx *ctx, > + const struct mac_bindings_map *recent_mbs) > +{ > + long long now = time_msec(); > + > + struct buffered_packets *bp; > + > + HMAP_FOR_EACH_SAFE (bp, hmap_node, &ctx->buffered_packets) { > + /* Remove expired buffered packets. */ > + if (now > bp->expire) { > + ovn_buffered_packets_remove(ctx, bp); > + continue; > + } > + > + uint32_t hash = keys_ip_hash(bp->dp_key, bp->port_key, &bp->ip); > + struct mac_binding *mb = mac_binding_find(recent_mbs, 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(&ctx->ready_packets_data, &pd->node); > + } > + > + ovn_buffered_packets_remove(ctx, bp); > + } > +} > + > +bool > +ovn_buffered_packets_ctx_is_ready_to_send(struct buffered_packets_ctx *ctx) > +{ > + return !ovs_list_is_empty(&ctx->ready_packets_data); > +} > + > +bool > +ovn_buffered_packets_ctx_has_packets(struct buffered_packets_ctx *ctx) > +{ > + return !hmap_is_empty(&ctx->buffered_packets); > +} > + > +void > +ovn_buffered_packets_ctx_init(struct buffered_packets_ctx *ctx) > +{ > + hmap_init(&ctx->buffered_packets); > + ovs_list_init(&ctx->ready_packets_data); > +} > + > +void > +ovn_buffered_packets_ctx_destroy(struct buffered_packets_ctx *ctx) > +{ > + struct packet_data *pd; > + LIST_FOR_EACH_POP (pd, node, &ctx->ready_packets_data) { > + ovn_packet_data_destroy(pd); > + } > + > + struct buffered_packets *bp; > + HMAP_FOR_EACH_SAFE (bp, hmap_node, &ctx->buffered_packets) { > + ovn_buffered_packets_remove(ctx, bp); > + } > + hmap_destroy(&ctx->buffered_packets); > +} > + > +/* mac_binding related static functions. */ > +static size_t > +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(const struct mac_bindings_map *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->map) { > + if (mb->dp_key == dp_key && mb->port_key == port_key && > + IN6_ARE_ADDR_EQUAL(&mb->ip, ip)) { > + return mb; > + } > + } > + > + return NULL; > +} > + > /* fdb related static functions. */ > > static size_t > @@ -201,3 +349,34 @@ fdb_entry_find(struct hmap *fdbs, uint32_t dp_key, > > return NULL; > } > + > +/* packet buffering static functions. */ > +static struct buffered_packets * > +buffered_packets_find(struct buffered_packets_ctx *ctx, 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, &ctx->buffered_packets) { > + if (mb->dp_key == dp_key && mb->port_key == port_key && > + IN6_ARE_ADDR_EQUAL(&mb->ip, ip)) { > + return mb; > + } > + } > + > + return NULL; > +} > + > +static void > +ovn_buffered_packets_remove(struct buffered_packets_ctx *ctx, > + struct buffered_packets *bp) > +{ > + struct packet_data *pd; > + > + LIST_FOR_EACH_POP (pd, node, &bp->queue) { > + ovn_packet_data_destroy(pd); > + } > + > + hmap_remove(&ctx->buffered_packets, &bp->hmap_node); > + free(bp); > +} > diff --git a/controller/mac-learn.h b/controller/mac-learn.h > index 55375cf90..3de57bf4c 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. */ > @@ -57,11 +61,6 @@ struct mac_binding *ovn_mac_binding_add(struct > mac_bindings_map *mac_bindings, > struct in6_addr *ip, > struct eth_addr mac, > uint32_t timestamp_offset); > -size_t keys_ip_hash(uint32_t dp_key, uint32_t port_key, struct in6_addr *ip); > -struct mac_binding * > -ovn_mac_binding_find(const struct mac_bindings_map *mac_bindings, > - uint32_t dp_key, uint32_t port_key, struct in6_addr *ip, > - size_t hash); > > > struct fdb_entry { > @@ -80,7 +79,57 @@ void ovn_fdbs_flush(struct hmap *fdbs); > void ovn_fdbs_destroy(struct hmap *fdbs); > > struct fdb_entry *ovn_fdb_add(struct hmap *fdbs, > - uint32_t dp_key, struct eth_addr mac, > - uint32_t port_key); > + uint32_t dp_key, struct eth_addr mac, > + uint32_t port_key); > + > +#define OVN_BUFFERED_PACKETS_TIMEOUT 10000 > + > +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; > + > + /* Queue of packet_data associated with this struct. */ > + struct ovs_list queue; > + > + /* Timestamp in ms when the buffered packet should expire. */ > + long long int expire; > +}; > + > +struct buffered_packets_ctx { > + /* Map of all buffered packets waiting for the MAC address. */ > + struct hmap buffered_packets; > + /* List of packet data that are ready to be sent. */ > + struct ovs_list ready_packets_data; > +}; > + > +#define OVN_BUFFERED_PACKETS_TIMEOUT 10000 Re-definition. > + > +struct packet_data * > +ovn_packet_data_create(struct ofpbuf ofpacts, > + const struct dp_packet *original_packet); > +void ovn_packet_data_destroy(struct packet_data *pd); > +struct buffered_packets * > +ovn_buffered_packets_add(struct buffered_packets_ctx *ctx, uint64_t dp_key, > + uint64_t port_key, struct in6_addr ip); > +void ovn_buffered_packets_packet_data_enqueue(struct buffered_packets *bp, > + struct packet_data *pd); > +void > +ovn_buffered_packets_ctx_run(struct buffered_packets_ctx *ctx, > + const struct mac_bindings_map *recent_mbs); > +void ovn_buffered_packets_ctx_init(struct buffered_packets_ctx *ctx); > +void ovn_buffered_packets_ctx_destroy(struct buffered_packets_ctx *ctx); > +bool > +ovn_buffered_packets_ctx_is_ready_to_send(struct buffered_packets_ctx *ctx); > +bool ovn_buffered_packets_ctx_has_packets(struct buffered_packets_ctx *ctx); > > #endif /* OVN_MAC_LEARN_H */ > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > index 9b5147753..b29033703 100644 > --- a/controller/pinctrl.c > +++ b/controller/pinctrl.c > @@ -1416,196 +1416,18 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn > *ovnsb_idl_txn, > } > } > > -#define BUFFERED_PACKETS_TIMEOUT 10000 > -#define MAX_BUFFERED_PACKETS 1000 > -#define BUFFER_QUEUE_DEPTH 4 > - > -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; > - > - /* Queue of packet_data associated with this struct. */ > - struct ovs_list queue; > - > - /* Timestamp in ms when the buffered packet should expire. */ > - long long int expire; > -}; > - > -struct buffered_packets_ctx { > - /* Map of all buffered packets waiting for the MAC address. */ > - struct hmap buffered_packets; > - /* List of packet data that are ready to be sent. */ > - struct ovs_list ready_packets_data; > -}; > - > static struct buffered_packets_ctx buffered_packets_ctx; > > -static struct buffered_packets * > -buffered_packets_find(struct buffered_packets_ctx *ctx, 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, &ctx->buffered_packets) { > - if (mb->dp_key == dp_key && mb->port_key == port_key && > - IN6_ARE_ADDR_EQUAL(&mb->ip, ip)) { > - return mb; > - } > - } > - > - return NULL; > -} > - > -static struct buffered_packets * > -buffered_packets_add(struct buffered_packets_ctx *ctx, 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(ctx, dp_key, port_key, &ip, hash); > - if (!bp) { > - if (hmap_count(&ctx->buffered_packets) >= MAX_BUFFERED_PACKETS) { > - return NULL; > - } > - > - bp = xmalloc(sizeof *bp); > - hmap_insert(&ctx->buffered_packets, &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() + BUFFERED_PACKETS_TIMEOUT; > - > - return bp; > -} > - > -static struct packet_data * > -packet_data_create(struct ofpbuf ofpacts, > - const struct dp_packet *original_packet) > -{ > - struct packet_data *pd = xmalloc(sizeof *pd); > - > - pd->ofpacts = ofpacts; > - /* clone the packet to send it later with correct L2 address */ > - pd->p = dp_packet_clone_data(dp_packet_data(original_packet), > - dp_packet_size(original_packet)); > - > - return pd; > -} > - > -static void > -packet_data_destroy(struct packet_data *pd) > -{ > - dp_packet_delete(pd->p); > - ofpbuf_uninit(&pd->ofpacts); > - free(pd); > -} > - > -static void > -buffered_packets_packet_data_enqueue(struct buffered_packets *bp, > - struct packet_data *pd) > -{ > - 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); > - packet_data_destroy(p); > - } > - ovs_list_push_back(&bp->queue, &pd->node); > -} > - > - > -static void > -buffered_packets_remove(struct buffered_packets_ctx *ctx, > - struct buffered_packets *bp) > -{ > - struct packet_data *pd; > - LIST_FOR_EACH_POP (pd, node, &bp->queue) { > - packet_data_destroy(pd); > - } > - > - hmap_remove(&ctx->buffered_packets, &bp->hmap_node); > - free(bp); > -} > - > -static void > -buffered_packets_ctx_run(struct buffered_packets_ctx *ctx, > - const struct mac_bindings_map *recent_mac_bindings) > -{ > - long long now = time_msec(); > - > - struct buffered_packets *bp; > - HMAP_FOR_EACH_SAFE (bp, hmap_node, &ctx->buffered_packets) { > - /* Remove expired buffered packets. */ > - if (now > bp->expire) { > - buffered_packets_remove(ctx, bp); > - continue; > - } > - > - uint32_t hash = keys_ip_hash(bp->dp_key, bp->port_key, &bp->ip); > - struct mac_binding *mb = ovn_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(&ctx->ready_packets_data, &pd->node); > - } > - > - buffered_packets_remove(ctx, bp); > - } > -} > - > -static bool > -buffered_packets_ctx_is_ready_to_send(struct buffered_packets_ctx *ctx) > -{ > - return !ovs_list_is_empty(&ctx->ready_packets_data); > -} > - > -static bool > -ovn_buffered_packets_ctx_has_packets(struct buffered_packets_ctx *ctx) > -{ > - return !hmap_is_empty(&ctx->buffered_packets); > -} > - > static void > init_buffered_packets_ctx(void) > { > - hmap_init(&buffered_packets_ctx.buffered_packets); > - ovs_list_init(&buffered_packets_ctx.ready_packets_data); > + ovn_buffered_packets_ctx_init(&buffered_packets_ctx); > } > > static void > destroy_buffered_packets_ctx(void) > { > - struct packet_data *pd; > - LIST_FOR_EACH_POP (pd, node, &buffered_packets_ctx.ready_packets_data) { > - packet_data_destroy(pd); > - } > - > - struct buffered_packets *bp; > - HMAP_FOR_EACH_SAFE (bp, hmap_node, > - &buffered_packets_ctx.buffered_packets) { > - buffered_packets_remove(&buffered_packets_ctx, bp); > - } > - hmap_destroy(&buffered_packets_ctx.buffered_packets); > + ovn_buffered_packets_ctx_destroy(&buffered_packets_ctx); > } > > /* Called with in the pinctrl_handler thread context. */ > @@ -1625,8 +1447,8 @@ OVS_REQUIRES(pinctrl_mutex) > memcpy(&ip, &ip6, sizeof ip); > } > > - struct buffered_packets *bp = buffered_packets_add(&buffered_packets_ctx, > - dp_key, oport_key, > ip); > + struct buffered_packets *bp = > + ovn_buffered_packets_add(&buffered_packets_ctx, dp_key, oport_key, > ip); > if (!bp) { > COVERAGE_INC(pinctrl_drop_buffered_packets_map); > return; > @@ -1645,8 +1467,8 @@ OVS_REQUIRES(pinctrl_mutex) > resubmit->in_port = OFPP_CONTROLLER; > resubmit->table_id = OFTABLE_REMOTE_OUTPUT; > > - struct packet_data *pd = packet_data_create(ofpacts, pkt_in); > - buffered_packets_packet_data_enqueue(bp, pd); > + struct packet_data *pd = ovn_packet_data_create(ofpacts, pkt_in); > + ovn_buffered_packets_packet_data_enqueue(bp, pd); > > /* There is a chance that the MAC binding was already created. */ > notify_pinctrl_main(); > @@ -4274,7 +4096,7 @@ send_mac_binding_buffered_pkts(struct rconn *swconn) > match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER); > queue_msg(swconn, ofputil_encode_packet_out(&po, proto)); > > - packet_data_destroy(pd); > + ovn_packet_data_destroy(pd); > } > > ovs_list_init(&buffered_packets_ctx.ready_packets_data); > @@ -4487,11 +4309,11 @@ run_buffered_binding(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > pb->tunnel_key, &ip, mac, 0); > } > > - buffered_packets_ctx_run(&buffered_packets_ctx, &recent_mbs); > + ovn_buffered_packets_ctx_run(&buffered_packets_ctx, &recent_mbs); > > ovn_mac_bindings_map_destroy(&recent_mbs); > > - if (buffered_packets_ctx_is_ready_to_send(&buffered_packets_ctx)) { > + if (ovn_buffered_packets_ctx_is_ready_to_send(&buffered_packets_ctx)) { > notify_pinctrl_handler(); > } > } > @@ -6095,7 +5917,7 @@ may_inject_pkts(void) > !shash_is_empty(&send_garp_rarp_data) || > ipv6_prefixd_should_inject() || > !ovs_list_is_empty(&mcast_query_list) || > - buffered_packets_ctx_is_ready_to_send(&buffered_packets_ctx) || > + ovn_buffered_packets_ctx_is_ready_to_send(&buffered_packets_ctx) > || > bfd_monitor_should_inject()); > } > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev