On 10/9/23 17:39, Ilya Maximets wrote: > On 10/4/23 18:33, Dumitru Ceara wrote: >> OVS actually supports way more. Use the real numbers instead. >> To avoid preallocating huge bitmaps for the group/meter IDs, switch to >> id-pool instead (as suggested by Ilya). >> >> Reported-at: https://issues.redhat.com/browse/FDP-70 >> Suggested-by: Ilya Maximets <i.maxim...@ovn.org> >> Signed-off-by: Dumitru Ceara <dce...@redhat.com> >> --- >> V2: >> - Addressed Ilya's comment: fixed the way id_pool_create() is called. >> - renamed max_size to max_id, it's more accurate. >> --- >> controller/ovn-controller.c | 4 ++-- >> lib/extend-table.c | 28 ++++++++++++---------------- >> lib/extend-table.h | 7 +++---- >> tests/test-ovn.c | 4 ++-- >> 4 files changed, 19 insertions(+), 24 deletions(-) >> >> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c >> index 9a81f1a80f..50a101f0e8 100644 >> --- a/controller/ovn-controller.c >> +++ b/controller/ovn-controller.c >> @@ -3936,8 +3936,8 @@ en_lflow_output_init(struct engine_node *node >> OVS_UNUSED, >> { >> struct ed_type_lflow_output *data = xzalloc(sizeof *data); >> ovn_desired_flow_table_init(&data->flow_table); >> - ovn_extend_table_init(&data->group_table); >> - ovn_extend_table_init(&data->meter_table); >> + ovn_extend_table_init(&data->group_table, OFPG_MAX); >> + ovn_extend_table_init(&data->meter_table, OFPM13_MAX); >> objdep_mgr_init(&data->lflow_deps_mgr); >> lflow_conj_ids_init(&data->conj_ids); >> uuidset_init(&data->objs_processed); >> diff --git a/lib/extend-table.c b/lib/extend-table.c >> index ebb1a054cb..90a1cf92b2 100644 >> --- a/lib/extend-table.c >> +++ b/lib/extend-table.c >> @@ -17,7 +17,6 @@ >> #include <config.h> >> #include <string.h> >> >> -#include "bitmap.h" >> #include "extend-table.h" >> #include "hash.h" >> #include "lib/uuid.h" >> @@ -30,10 +29,10 @@ ovn_extend_table_delete_desired(struct ovn_extend_table >> *table, >> struct ovn_extend_table_lflow_to_desired >> *l); >> >> void >> -ovn_extend_table_init(struct ovn_extend_table *table) >> +ovn_extend_table_init(struct ovn_extend_table *table, uint32_t max_id) >> { >> - table->table_ids = bitmap_allocate(MAX_EXT_TABLE_ID); >> - bitmap_set1(table->table_ids, 0); /* table id 0 is invalid. */ >> + /* Table id 0 is invalid, set id-pool base to 1. */ >> + table->table_ids = id_pool_create(1, max_id); >> hmap_init(&table->desired); >> hmap_init(&table->lflow_to_desired); >> hmap_init(&table->existing); >> @@ -192,7 +191,7 @@ ovn_extend_table_clear(struct ovn_extend_table *table, >> bool existing) >> g->peer->peer = NULL; >> } else { >> /* Unset the bitmap because the peer is deleted already. */ > > bitmap? > >> - bitmap_set0(table->table_ids, g->table_id); >> + id_pool_free_id(table->table_ids, g->table_id); > > Just to double check. This is called only once per id? > Asking because it's fine to clear the same bit multiple > times, but it's not OK to free the same id-pool ID twice.
Hmm. This is not a problem for id-pool. I mixed up things with id-fpool. Basic id-pool handles double free case just fine. > >> } >> ovn_extend_table_info_destroy(g); >> } >> @@ -206,7 +205,7 @@ ovn_extend_table_destroy(struct ovn_extend_table *table) >> hmap_destroy(&table->lflow_to_desired); >> ovn_extend_table_clear(table, true); >> hmap_destroy(&table->existing); >> - bitmap_free(table->table_ids); >> + id_pool_destroy(table->table_ids); >> } >> >> /* Remove an entry from existing table */ >> @@ -221,7 +220,7 @@ ovn_extend_table_remove_existing(struct ovn_extend_table >> *table, >> existing->peer->peer = NULL; >> } else { >> /* Dealloc the ID. */ >> - bitmap_set0(table->table_ids, existing->table_id); >> + id_pool_free_id(table->table_ids, existing->table_id); >> } >> ovn_extend_table_info_destroy(existing); >> } >> @@ -242,7 +241,7 @@ ovn_extend_table_delete_desired(struct ovn_extend_table >> *table, >> if (e->peer) { >> e->peer->peer = NULL; >> } else { >> - bitmap_set0(table->table_ids, e->table_id); >> + id_pool_free_id(table->table_ids, e->table_id); >> } >> ovn_extend_table_info_destroy(e); >> } >> @@ -320,15 +319,12 @@ ovn_extend_table_assign_id(struct ovn_extend_table >> *table, const char *name, > > Comment for this function is also talking about bitmap. > >> >> if (!existing_info) { >> /* Reserve a new id. */ >> - table_id = bitmap_scan(table->table_ids, 0, 1, MAX_EXT_TABLE_ID + >> 1); >> - } >> - >> - if (table_id == MAX_EXT_TABLE_ID + 1) { >> - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); >> - VLOG_ERR_RL(&rl, "%"PRIu32" out of table ids.", table_id); >> - return EXT_TABLE_ID_INVALID; >> + if (!id_pool_alloc_id(table->table_ids, &table_id)) { >> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); > > Maybe an empty line here? > >> + VLOG_ERR_RL(&rl, "%"PRIu32" out of table ids.", table_id); > > Table ID is always zero at this point, so the error message > is not very informative. Not that it was particularly useful > before... > >> + return EXT_TABLE_ID_INVALID; >> + } >> } >> - bitmap_set1(table->table_ids, table_id); >> >> table_info = ovn_extend_table_info_alloc(name, table_id, existing_info, >> hash); > > So, we're creating a new hash map entry here with pre-existing ID. > Wouldn't this cause a double free for that ID later? Again, not a problem for id-pool. > >> diff --git a/lib/extend-table.h b/lib/extend-table.h >> index b43a146b4f..56d54afe93 100644 >> --- a/lib/extend-table.h >> +++ b/lib/extend-table.h >> @@ -17,18 +17,17 @@ >> #ifndef EXTEND_TABLE_H >> #define EXTEND_TABLE_H 1 >> >> -#define MAX_EXT_TABLE_ID 65535 >> #define EXT_TABLE_ID_INVALID 0 >> >> #include "openvswitch/hmap.h" >> #include "openvswitch/list.h" >> #include "openvswitch/uuid.h" >> +#include "id-pool.h" > > I'd say the include should be in the .c file. In the header we should > only have: > > struct id_pool; > >> >> /* Used to manage expansion tables associated with Flow table, >> * such as the Group Table or Meter Table. */ >> struct ovn_extend_table { >> - unsigned long *table_ids; /* Used as a bitmap with value set >> - * for allocated ids in either desired or >> + struct id_pool *table_ids; /* Used to allocated ids in either desired or > > s/allocated/allocate/ > >> * existing (or both). If the same "name" >> * exists in both desired and existing >> tables, >> * they must share the same ID. The "peer" >> @@ -81,7 +80,7 @@ struct ovn_extend_table_lflow_ref { >> struct ovn_extend_table_info *desired; >> }; >> >> -void ovn_extend_table_init(struct ovn_extend_table *); >> +void ovn_extend_table_init(struct ovn_extend_table *, uint32_t max_id); >> >> void ovn_extend_table_destroy(struct ovn_extend_table *); >> >> diff --git a/tests/test-ovn.c b/tests/test-ovn.c >> index 1f1e27b51f..e4f03806a3 100644 >> --- a/tests/test-ovn.c >> +++ b/tests/test-ovn.c >> @@ -1300,11 +1300,11 @@ test_parse_actions(struct ovs_cmdl_context *ctx >> OVS_UNUSED) >> >> /* Initialize group ids. */ >> struct ovn_extend_table group_table; >> - ovn_extend_table_init(&group_table); >> + ovn_extend_table_init(&group_table, OFPG_MAX); >> >> /* Initialize meter ids for QoS. */ >> struct ovn_extend_table meter_table; >> - ovn_extend_table_init(&meter_table); >> + ovn_extend_table_init(&meter_table, OFPM13_MAX); > > I did a bit more digging in this topic and instead of using these > constants we should technically ask OVS about real limits > with OFPMP13_METER_FEATURES_REQUEST and OFPST12_GROUP_FEATURES_REQUEST > respectively. They will report how many meters and groups are actually > supported. > > At the same time OVN may not do that at the expense of getting and > OpenFlow error reply on attempt to create more meters/groups than > the implementation supports. For example, userspace datapath supprts > 2^18 meters, and kernel allows creating meters up to filling 3% of > physical memory. :) > > Currently OVS always reports OFPG_MAX as the maximum number of groups > though anyway. > > Does it matter if we fail a table ID allocation vs the OF request > failure later? > > Best regards, Ilya Maximets. _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev