On 11/16/22 22:33, Mark Michelson wrote: > Hi Dumitru, I have a few comments below.
Hi Mark, Thanks for your review! > > On 11/4/22 18:11, Dumitru Ceara wrote: >> Propagate the contents of the NB table to the Southbound. >> >> Signed-off-by: Dumitru Ceara <dce...@redhat.com> >> --- >> Note: >> - ovn-trace doesn't support template variables (yet). >> >> V2: >> - Fixed TEMPLATE_VAR_TABLE_INITIALIZER definition so that GCC doesn't >> complain anymore. >> - Addressed Han's comments: >> - Rename tables to Chassis_Template_Var. >> - Fix man page. >> - Simplify function prototypes. >> - Changed schema as suggested by Ilya. >> --- >> northd/automake.mk | 4 ++ >> northd/en-northd.c | 4 ++ >> northd/inc-proc-northd.c | 8 ++++- >> northd/northd.c | 41 +++++++++++++++++++++++++ >> northd/northd.h | 4 ++ >> northd/template-var.c | 74 >> ++++++++++++++++++++++++++++++++++++++++++++++ >> northd/template-var.h | 58 ++++++++++++++++++++++++++++++++++++ >> ovn-nb.ovsschema | 17 +++++++++-- >> ovn-nb.xml | 29 ++++++++++++++++++ >> ovn-sb.ovsschema | 12 ++++++- >> ovn-sb.xml | 15 +++++++++ >> tests/ovn-northd.at | 35 ++++++++++++++++++++++ >> utilities/ovn-nbctl.c | 3 ++ >> utilities/ovn-sbctl.c | 3 ++ >> 14 files changed, 299 insertions(+), 8 deletions(-) >> create mode 100644 northd/template-var.c >> create mode 100644 northd/template-var.h >> >> diff --git a/northd/automake.mk b/northd/automake.mk >> index 81582867dc..31134bc329 100644 >> --- a/northd/automake.mk >> +++ b/northd/automake.mk >> @@ -13,7 +13,9 @@ northd_ovn_northd_SOURCES = \ >> northd/inc-proc-northd.c \ >> northd/inc-proc-northd.h \ >> northd/ipam.c \ >> - northd/ipam.h >> + northd/ipam.h \ >> + northd/template-var.c \ >> + northd/template-var.h >> northd_ovn_northd_LDADD = \ >> lib/libovn.la \ >> $(OVSDB_LIBDIR)/libovsdb.la \ >> diff --git a/northd/en-northd.c b/northd/en-northd.c >> index 7fe83db642..030ee25d8f 100644 >> --- a/northd/en-northd.c >> +++ b/northd/en-northd.c >> @@ -80,6 +80,8 @@ void en_northd_run(struct engine_node *node, void >> *data) >> EN_OVSDB_GET(engine_get_input("NB_acl", node)); >> input_data.nbrec_static_mac_binding_table = >> EN_OVSDB_GET(engine_get_input("NB_static_mac_binding", node)); >> + input_data.nbrec_chassis_template_var_table = >> + EN_OVSDB_GET(engine_get_input("NB_chassis_template_var", node)); >> input_data.sbrec_sb_global_table = >> EN_OVSDB_GET(engine_get_input("SB_sb_global", node)); >> @@ -113,6 +115,8 @@ void en_northd_run(struct engine_node *node, void >> *data) >> EN_OVSDB_GET(engine_get_input("SB_chassis_private", node)); >> input_data.sbrec_static_mac_binding_table = >> EN_OVSDB_GET(engine_get_input("SB_static_mac_binding", node)); >> + input_data.sbrec_chassis_template_var_table = >> + EN_OVSDB_GET(engine_get_input("SB_chassis_template_var", node)); >> northd_run(&input_data, data, >> eng_ctx->ovnnb_idl_txn, >> diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c >> index 54e0ad3b05..da791f035d 100644 >> --- a/northd/inc-proc-northd.c >> +++ b/northd/inc-proc-northd.c >> @@ -64,7 +64,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_northd); >> NB_NODE(ha_chassis_group, "ha_chassis_group") \ >> NB_NODE(ha_chassis, "ha_chassis") \ >> NB_NODE(bfd, "bfd") \ >> - NB_NODE(static_mac_binding, "static_mac_binding") >> + NB_NODE(static_mac_binding, "static_mac_binding") \ >> + NB_NODE(chassis_template_var, "chassis_template_var") >> enum nb_engine_node { >> #define NB_NODE(NAME, NAME_STR) NB_##NAME, >> @@ -114,7 +115,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_northd); >> SB_NODE(load_balancer, "load_balancer") \ >> SB_NODE(bfd, "bfd") \ >> SB_NODE(fdb, "fdb") \ >> - SB_NODE(static_mac_binding, "static_mac_binding") >> + SB_NODE(static_mac_binding, "static_mac_binding") \ >> + SB_NODE(chassis_template_var, "chassis_template_var") >> enum sb_engine_node { >> #define SB_NODE(NAME, NAME_STR) SB_##NAME, >> @@ -186,6 +188,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, >> engine_add_input(&en_northd, &en_nb_ha_chassis_group, NULL); >> engine_add_input(&en_northd, &en_nb_ha_chassis, NULL); >> engine_add_input(&en_northd, &en_nb_static_mac_binding, NULL); >> + engine_add_input(&en_northd, &en_nb_chassis_template_var, NULL); >> engine_add_input(&en_northd, &en_sb_sb_global, NULL); >> engine_add_input(&en_northd, &en_sb_chassis, NULL); >> @@ -215,6 +218,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, >> engine_add_input(&en_northd, &en_sb_load_balancer, NULL); >> engine_add_input(&en_northd, &en_sb_fdb, NULL); >> engine_add_input(&en_northd, &en_sb_static_mac_binding, NULL); >> + engine_add_input(&en_northd, &en_sb_chassis_template_var, NULL); >> engine_add_input(&en_mac_binding_aging, &en_nb_nb_global, NULL); >> engine_add_input(&en_mac_binding_aging, &en_sb_mac_binding, NULL); >> engine_add_input(&en_mac_binding_aging, &en_northd, NULL); >> diff --git a/northd/northd.c b/northd/northd.c >> index b7388afc58..170b4f95c8 100644 >> --- a/northd/northd.c >> +++ b/northd/northd.c >> @@ -51,6 +51,7 @@ >> #include "lib/stopwatch-names.h" >> #include "stream.h" >> #include "timeval.h" >> +#include "template-var.h" >> #include "util.h" >> #include "uuid.h" >> #include "ovs-thread.h" >> @@ -15129,6 +15130,44 @@ sync_dns_entries(struct northd_input >> *input_data, >> } >> hmap_destroy(&dns_map); >> } >> + >> +static void >> +sync_template_vars(struct northd_input *input_data, >> + struct ovsdb_idl_txn *ovnsb_txn) >> +{ >> + struct template_var_table nb_tvs = >> TEMPLATE_VAR_TABLE_INITIALIZER(&nb_tvs); >> + >> + const struct nbrec_chassis_template_var *nb_tv; >> + const struct sbrec_chassis_template_var *sb_tv; >> + struct template_var *tv; >> + >> + NBREC_CHASSIS_TEMPLATE_VAR_TABLE_FOR_EACH ( >> + nb_tv, input_data->nbrec_chassis_template_var_table) { >> + template_var_insert(&nb_tvs, nb_tv); >> + } >> + >> + SBREC_CHASSIS_TEMPLATE_VAR_TABLE_FOR_EACH_SAFE ( >> + sb_tv, input_data->sbrec_chassis_template_var_table) { >> + tv = template_var_find(&nb_tvs, sb_tv->chassis); >> + if (!tv) { >> + sbrec_chassis_template_var_delete(sb_tv); >> + continue; >> + } >> + if (!smap_equal(&sb_tv->variables, &tv->nb->variables)) { >> + sbrec_chassis_template_var_set_variables(sb_tv, >> + >> &tv->nb->variables); >> + } > > I was looking at this and wondering what would happen here if you > skipped the smap_equal() call and just unconditionally called > sbrec_chassis_template_var_set_variables(). My thought here was that it > would save the O(n^2) smap_equal() call, but it would also result in In my initial code I actually didn't have te smap_equal(). I added it because without it there's a significant performance hit. On my machine, when simulating 250 nodes with 10K LBs, "ovn-nbctl --wait=sb sync": - with smap_equal(): northd loops take ~600ms - without: northd loops take ~8000ms (most of which is in sync_template_vars() Taking some perf samples we see: - 63.76% 0.00% ovn-northd ovn-northd [.] inc_proc_northd_run inc_proc_northd_run engine_run - engine_recompute - 61.08% en_northd_run - 60.96% northd_run - 60.93% ovnnb_db_run - 59.88% sbrec_chassis_template_var_set_variables + 27.00% ovsdb_datum_from_smap + 18.76% ovsdb_idl_txn_write + 8.11% ovsdb_datum_destroy + 5.68% ovsdb_idl_txn_write__ So we see it's actually more efficient to do the explicit smap_equal() ourselves. Also, I don't think smap_equal() takes O(n^2). It's backed by a hashmap so it should be more like O(n) if we assume constant length values. > spurious writes to the SBDB. Those writes would result in more wakeups > of ovn-controller. But ovn-controller has I-P for template vars, so > those wakeups would hopefully not result in many wasted cycles. > > So...I'm not really sure here. However, I think this would be a good > (and hopefully easy) candidate for I-P in a future release. > I agree, we should do it in the future. It shouldn't be too different from the I-P I do for template variables in ovn-controller. >> + template_var_remove(&nb_tvs, tv); >> + template_var_destroy(tv); >> + } >> + >> + TEMPLATE_VAR_TABLE_FOR_EACH (tv, &nb_tvs) { >> + sb_tv = sbrec_chassis_template_var_insert(ovnsb_txn); >> + sbrec_chassis_template_var_set_chassis(sb_tv, tv->nb->chassis); >> + sbrec_chassis_template_var_set_variables(sb_tv, >> &tv->nb->variables); >> + } >> + template_var_table_destroy(&nb_tvs); >> +} >> >> static void >> destroy_datapaths_and_ports(struct hmap *datapaths, struct hmap *ports, >> @@ -15645,6 +15684,8 @@ ovnnb_db_run(struct northd_input *input_data, >> sync_port_groups(input_data, ovnsb_txn, &data->port_groups); >> sync_meters(input_data, ovnsb_txn, &data->meter_groups); >> sync_dns_entries(input_data, ovnsb_txn, &data->datapaths); >> + sync_template_vars(input_data, ovnsb_txn); >> + >> cleanup_stale_fdb_entries(input_data, &data->datapaths); >> stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec()); >> diff --git a/northd/northd.h b/northd/northd.h >> index da90e28155..1935c80d40 100644 >> --- a/northd/northd.h >> +++ b/northd/northd.h >> @@ -36,6 +36,8 @@ struct northd_input { >> const struct nbrec_acl_table *nbrec_acl_table; >> const struct nbrec_static_mac_binding_table >> *nbrec_static_mac_binding_table; >> + const struct nbrec_chassis_template_var_table >> + *nbrec_chassis_template_var_table; >> /* Southbound table references */ >> const struct sbrec_sb_global_table *sbrec_sb_global_table; >> @@ -55,6 +57,8 @@ struct northd_input { >> const struct sbrec_chassis_private_table >> *sbrec_chassis_private_table; >> const struct sbrec_static_mac_binding_table >> *sbrec_static_mac_binding_table; >> + const struct sbrec_chassis_template_var_table >> + *sbrec_chassis_template_var_table; >> /* Indexes */ >> struct ovsdb_idl_index *sbrec_chassis_by_name; >> diff --git a/northd/template-var.c b/northd/template-var.c >> new file mode 100644 >> index 0000000000..a1069a5b51 >> --- /dev/null >> +++ b/northd/template-var.c >> @@ -0,0 +1,74 @@ >> +/* Copyright (c) 2022, Red Hat, Inc. >> + * >> + * Licensed under the Apache License, Version 2.0 (the "License"); >> + * you may not use this file except in compliance with the License. >> + * You may obtain a copy of the License at: >> + * >> + * http://www.apache.org/licenses/LICENSE-2.0 >> + * >> + * Unless required by applicable law or agreed to in writing, software >> + * distributed under the License is distributed on an "AS IS" BASIS, >> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >> implied. >> + * See the License for the specific language governing permissions and >> + * limitations under the License. >> + */ >> + >> +#include <config.h> >> + >> +#include "template-var.h" >> + >> +struct template_var_table * >> +template_var_table_create(void) >> +{ >> + struct template_var_table *table = xmalloc(sizeof *table); >> + >> + hmap_init(&table->vars); >> + return table; >> +} >> + >> +void >> +template_var_table_destroy(struct template_var_table *table) >> +{ >> + struct template_var *tv; >> + >> + HMAP_FOR_EACH_POP (tv, hmap_node, &table->vars) { >> + template_var_destroy(tv); >> + } >> + hmap_destroy(&table->vars); >> +} >> + >> +void >> +template_var_insert(struct template_var_table *table, >> + const struct nbrec_chassis_template_var *nbrec_tv) >> +{ >> + struct template_var *tv = xmalloc(sizeof *tv); >> + tv->nb = nbrec_tv; >> + hmap_insert(&table->vars, &tv->hmap_node, >> + template_var_hash(nbrec_tv->chassis)); >> +} >> + >> +struct template_var * >> +template_var_find(struct template_var_table *table, const char >> *chassis_name) >> +{ >> + struct template_var *tv; >> + >> + HMAP_FOR_EACH_WITH_HASH (tv, hmap_node, >> template_var_hash(chassis_name), > > Nit: Since HMAP_FOR_EACH_WITH_HASH() is a macro, you should probably > call template_var_hash() before HMAP_FOR_EACH_WITH_HASH(). Otherwise, > the hash will be recalculated many times unnecessarily (assuming the > compiler doesn't optimize this on its own). > >> + &table->vars) { >> + if (!strcmp(chassis_name, tv->nb->chassis)) { >> + return tv; >> + } >> + } >> + return NULL; >> +} >> + >> +void >> +template_var_remove(struct template_var_table *table, struct >> template_var *tv) >> +{ >> + hmap_remove(&table->vars, &tv->hmap_node); >> +} >> + >> +void >> +template_var_destroy(struct template_var *tv) >> +{ >> + free(tv); >> +} >> diff --git a/northd/template-var.h b/northd/template-var.h >> new file mode 100644 >> index 0000000000..2de0e6cfe4 >> --- /dev/null >> +++ b/northd/template-var.h >> @@ -0,0 +1,58 @@ >> +/* Copyright (c) 2022, Red Hat, Inc. >> + * >> + * Licensed under the Apache License, Version 2.0 (the "License"); >> + * you may not use this file except in compliance with the License. >> + * You may obtain a copy of the License at: >> + * >> + * http://www.apache.org/licenses/LICENSE-2.0 >> + * >> + * Unless required by applicable law or agreed to in writing, software >> + * distributed under the License is distributed on an "AS IS" BASIS, >> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >> implied. >> + * See the License for the specific language governing permissions and >> + * limitations under the License. >> + */ >> + >> +#ifndef OVN_NORTHD_TEMPLATE_VAR_H >> +#define OVN_NORTHD_TEMPLATE_VAR_H 1 >> + >> +#include "openvswitch/hmap.h" >> +#include "lib/ovn-nb-idl.h" >> + >> +struct template_var { >> + struct hmap_node hmap_node; >> + >> + const struct nbrec_chassis_template_var *nb; >> +}; >> + >> +struct template_var_table { >> + struct hmap vars; > > Question: Why did you choose to use an hmap? This seems like a good fit > for shash to me. > No good reason, I should've just used shash. I removed template-var.[ch] in v3. >> +}; >> + >> +#define TEMPLATE_VAR_TABLE_INITIALIZER(TBL) \ >> + { .vars = HMAP_INITIALIZER(&(TBL)->vars) } >> + >> +#define TEMPLATE_VAR_TABLE_FOR_EACH(NODE, TBL) \ >> + HMAP_FOR_EACH (NODE, hmap_node, &(TBL)->vars) >> + >> +struct template_var_table *template_var_table_create(void); >> +void template_var_table_destroy(struct template_var_table *); >> + >> +static inline uint32_t >> +template_var_hash(const char *tv_chassis) >> +{ >> + return hash_string(tv_chassis, 0); >> +} >> + >> +void template_var_insert(struct template_var_table *, >> + const struct nbrec_chassis_template_var *); >> + >> +struct template_var * >> +template_var_find(struct template_var_table *, const char >> *chassis_name); >> + >> +void template_var_remove(struct template_var_table *, >> + struct template_var *); >> + >> +void template_var_destroy(struct template_var *); >> + >> +#endif /* OVN_NORTHD_TEMPLATE_VAR_H 1 */ >> diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema >> index 174364c8b1..6f9d38f47b 100644 >> --- a/ovn-nb.ovsschema >> +++ b/ovn-nb.ovsschema >> @@ -1,7 +1,7 @@ >> { >> "name": "OVN_Northbound", >> - "version": "6.3.0", >> - "cksum": "4042813038 31869", >> + "version": "6.4.0", >> + "cksum": "3512158873 32360", >> "tables": { >> "NB_Global": { >> "columns": { >> @@ -620,6 +620,17 @@ >> "mac": {"type": "string"}, >> "override_dynamic_mac": {"type": "boolean"}}, >> "indexes": [["logical_port", "ip"]], >> - "isRoot": true} >> + "isRoot": true}, >> + "Chassis_Template_Var": { >> + "columns": { >> + "chassis": {"type": "string"}, >> + "variables": { >> + "type": {"key": "string", "value": "string", >> + "min": 0, "max": "unlimited"}}, >> + "external_ids": { >> + "type": {"key": "string", "value": "string", >> + "min": 0, "max": "unlimited"}}}, >> + "indexes": [["chassis"]], >> + "isRoot": true} >> } >> } >> diff --git a/ovn-nb.xml b/ovn-nb.xml >> index f41e9d7c0e..45b75e66df 100644 >> --- a/ovn-nb.xml >> +++ b/ovn-nb.xml >> @@ -4436,4 +4436,33 @@ >> </column> >> </group> >> </table> >> + >> + <table name="Chassis_Template_Var"> >> + <p> >> + One record per chassis, each containing a map, >> <code>variables</code>, >> + between template variable names and their value for that specific >> + chassis. A template variable has a name and potentially different >> + values on different hypervisors in the OVN cluster. For example, >> + two rows, <code>R1 = (.chassis=C1, variables={(N: V1)}</code> and >> + <code>R2 = (.chassis=C2, variables={(N: V2)}</code> will make >> + <code>ovn-controller</code> running on chassis <code>C1</code> and >> + <code>C2</code> interpret the token <code>N</code> either as >> + <code>V1</code> (on <code>C1</code>) or as <code>V2</code> (on >> + <code>C2</code>). Users can refer to template variables from >> + within other logical components, e.g., within ACL, QoS or >> + Logical_Router_Policy matches or from Load_Balancer VIP and >> + backend definitions. > > One thing the documentation does not make clear is what happens if a > chassis template variable is referenced on a chassis for which that > variable is not defined. > Good point. In that case ovn-controller will just treat it as a plain literal. I added a note to mention that. >> + </p> >> + <column name="chassis"> >> + The chassis this set of variable values applies to. >> + </column> >> + <column name="variables"> >> + The set of variable values for a given chassis. >> + </column> >> + <group title="Common Columns"> >> + <column name="external_ids"> >> + See <em>External IDs</em> at the beginning of this document. >> + </column> >> + </group> >> + </table> >> </database> >> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema >> index 576ebbdeb0..95c7c2d7e3 100644 >> --- a/ovn-sb.ovsschema >> +++ b/ovn-sb.ovsschema >> @@ -1,7 +1,7 @@ >> { >> "name": "OVN_Southbound", >> - "version": "20.25.0", >> - "cksum": "53184112 28845", >> + "version": "20.26.0", >> + "cksum": "3311869408 29176", >> "tables": { >> "SB_Global": { >> "columns": { >> @@ -565,6 +565,14 @@ >> "key": {"type": "uuid", >> "refTable": >> "Datapath_Binding"}}}}, >> "indexes": [["logical_port", "ip"]], >> + "isRoot": true}, >> + "Chassis_Template_Var": { >> + "columns": { >> + "chassis": {"type": "string"}, >> + "variables": { >> + "type": {"key": "string", "value": "string", >> + "min": 0, "max": "unlimited"}}}, >> + "indexes": [["chassis"]], >> "isRoot": true} >> } >> } >> diff --git a/ovn-sb.xml b/ovn-sb.xml >> index 315d608534..169a53aaa9 100644 >> --- a/ovn-sb.xml >> +++ b/ovn-sb.xml >> @@ -4801,4 +4801,19 @@ tcp.flags = RST; >> The logical datapath to which the logical router port belongs. >> </column> >> </table> >> + >> + <table name="Chassis_Template_Var"> >> + <p> >> + Each record represents the set of template variable instantiations >> + for a given chassis and is populated by <code>ovn-northd</code> >> + from the contents of the >> <code>OVN_Northbound.Chassis_Template_Var</code> >> + table. >> + </p> >> + <column name="chassis"> >> + The chassis this set of variable values applies to. >> + </column> >> + <column name="variables"> >> + The set of variable values for a given chassis. >> + </column> >> + </table> >> </database> >> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at >> index 4f399eccb6..c7112b805d 100644 >> --- a/tests/ovn-northd.at >> +++ b/tests/ovn-northd.at >> @@ -7929,3 +7929,38 @@ AT_CHECK([grep "lr_in_arp_resolve" R1flows | >> grep priority=90 | sort], [0], [dnl >> AT_CLEANUP >> ]) >> + >> +OVN_FOR_EACH_NORTHD_NO_HV([ >> +AT_SETUP([NB to SB Chassis_Template_Var propagation]) >> +AT_KEYWORDS([templates]) >> +ovn_start >> + >> +AT_CHECK([ovn-nbctl create Chassis_Template_Var chassis="hv1"], [0], >> [ignore]) >> +AT_CHECK([ovn-nbctl create Chassis_Template_Var chassis="hv2"], [0], >> [ignore]) >> + >> +check ovn-nbctl set Chassis_Template_Var hv1 variables:tv=v1 >> +check ovn-nbctl set Chassis_Template_Var hv2 variables:tv=v2 >> + >> +AS_BOX([Ensure values are propagated to SB]) >> +check ovn-nbctl --wait=sb sync >> +check_column "tv=v1" sb:Chassis_Template_Var variables chassis="hv1" >> +check_column "tv=v2" sb:Chassis_Template_Var variables chassis="hv2" >> + >> +AS_BOX([Ensure SB is reconciled]) >> +check ovn-sbctl --all destroy Chassis_Template_Var >> +check ovn-nbctl --wait=sb sync >> +check_column "tv=v1" sb:Chassis_Template_Var variables chassis="hv1" >> +check_column "tv=v2" sb:Chassis_Template_Var variables chassis="hv2" >> + >> +AS_BOX([Ensure SB is reconciled - deletion]) >> +check ovn-nbctl destroy Chassis_Template_Var hv1 >> +check ovn-nbctl --wait=sb sync >> +check_column "tv=v2" sb:Chassis_Template_Var variables chassis="hv2" >> + >> +AS_BOX([Ensure SB is reconciled - cleanup]) >> +check ovn-nbctl destroy Chassis_Template_Var hv2 >> +check ovn-nbctl --wait=sb sync >> +check_row_count sb:Chassis_Template_Var 0 >> + >> +AT_CLEANUP >> +]) >> diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c >> index 811468dc66..d2dee6b31c 100644 >> --- a/utilities/ovn-nbctl.c >> +++ b/utilities/ovn-nbctl.c >> @@ -7300,6 +7300,9 @@ static const struct ctl_table_class >> tables[NBREC_N_TABLES] = { >> [NBREC_TABLE_NAT].row_ids[0] >> = {&nbrec_nat_col_external_ip, NULL, NULL}, >> + [NBREC_TABLE_CHASSIS_TEMPLATE_VAR].row_ids[0] >> + = {&nbrec_chassis_template_var_col_chassis, NULL, NULL}, >> + >> [NBREC_TABLE_CONNECTION].row_ids[0] >> = {&nbrec_connection_col_target, NULL, NULL}, >> }; >> diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c >> index f60dde1b67..00b2f785a5 100644 >> --- a/utilities/ovn-sbctl.c >> +++ b/utilities/ovn-sbctl.c >> @@ -1457,6 +1457,9 @@ static const struct ctl_table_class >> tables[SBREC_N_TABLES] = { >> [SBREC_TABLE_LOAD_BALANCER].row_ids[0] >> = {&sbrec_load_balancer_col_name, NULL, NULL}, >> + >> + [SBREC_TABLE_CHASSIS_TEMPLATE_VAR].row_ids[0] >> + = {&sbrec_chassis_template_var_col_chassis, NULL, NULL}, >> }; >> static const struct ctl_command_syntax sbctl_commands[] = { >> > Thanks, Dumitru _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev