This patch fixes the "raceful" situation that occurs when ovn-nbctl configures the OVN Northbound database till the point when the ovn-controller picks up the corresponding logical flows and applies them as OpenFlow rules on the hypervisor.
The algorithm is outlined in the email - http://openvswitch.org/pipermail/dev/2016-April/070042.html which began as a thread here - http://openvswitch.org/pipermail/dev/2016-April/069602.html A new table, Config, is added to OVN_Northbound and OVN_Southbound DBs. This table is restricted to a single row in both the DBs. The OVN_Northbound Config contains a single row, with next_cfg and cur_cfg. The next_cfg is updated by ovn-nbctl whenever it commits an update to the OVN_Northbound DB. The ovn-northd picks up the next_cfg from the OVN_Northbound DB and sets the same value in the OVN_Southbound's Config table next_cfg column. A new column (cur_cfg) is added to the Chassis table in the OVN_Southbound DB. Every ovn-controller updates the cur_cfg in its Chassis row (to the value in the OVN_Southbound DB cur_cfg column). This is done in the next iteration after the ovn-controller picks up the latest logical flows and pends them to be applied as OpenFlow rules. The ovn-northd computes the mimumum of all the cur_cfg values in the Chassis table and sets the OVN_Northbound's DB cur_cfg value. The ovn-nbctl utility increments the OVN_Northbound's next_cfg value whenever it commits a transaction that modifies the OVN_Northbound DB. A "--wait" option is added to the ovn-nbctl utility. When the "--wait" option is used, the ovn-nbctl waits for the OVN_Northbound's cur_cfg to equal next_cfg before it exits. A new operation "nop" is added to use when the ovn-nbctl does not have any read or write operation but wants to wait for all previous configurations to have been picked up by the ovn-controllers by using - "ovn-nbctl --wait nop" command. The ovn E2E test cases have been modified to use the "ovn-nbctl --wait nop" command instead of using "sleep 1" to assume synchronization between the OVN_Northbound settings and the ovn-controllers. Caveats: Not all ovn-nbctl operations that modify the OVN_Northbound DB and therefore increment the next_cfg value actually result in OpenFlow rules being modified in the hypervisors. So a --wait option must not be used under such circumstances. If a logical datapath doesn't exist on a particular hypervisor, the ovn-controller will not apply any OpenFlow rules associated with that datapath and not update the cur_cfg. Use caution with the "--wait" option. Signed-off-by: Amitabha Biswas <abis...@us.ibm.com> Reported-by: Ryan Moats <rmo...@us.ibm.com> Reported-at: http://openvswitch.org/pipermail/dev/2016-April/069602.html --- ovn/controller/ofctrl.c | 15 ++++++++--- ovn/controller/ofctrl.h | 2 +- ovn/controller/ovn-controller.c | 43 ++++++++++++++++++++++++++++++- ovn/northd/ovn-northd.c | 56 +++++++++++++++++++++++++++++++++++++++++ ovn/ovn-nb.ovsschema | 10 ++++++-- ovn/ovn-nb.xml | 21 +++++++++++++++- ovn/ovn-sb.ovsschema | 12 +++++++-- ovn/ovn-sb.xml | 19 ++++++++++++++ ovn/utilities/ovn-nbctl.8.xml | 29 +++++++++++++++++++++ ovn/utilities/ovn-nbctl.c | 56 ++++++++++++++++++++++++++++++++++++----- tests/ovn.at | 37 ++++++++++++++++----------- 11 files changed, 269 insertions(+), 31 deletions(-) diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index f537bc0..9d211bb 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -597,10 +597,14 @@ queue_flow_mod(struct ofputil_flow_mod *fm) * flows from 'flow_table' and frees them. (The hmap itself isn't * destroyed.) * - * This called be called be ofctrl_run() within the main loop. */ -void + * This called be called be ofctrl_run() within the main loop. + * Returns true if the installed flows were updated (queued) false otherwise. + */ +bool ofctrl_put(struct hmap *flow_table) { + bool flows_updated = false; + /* The flow table can be updated if the connection to the switch is up and * in the correct state and not backlogged with existing flow_mods. (Our * criteria for being backlogged appear very conservative, but the socket @@ -610,7 +614,7 @@ ofctrl_put(struct hmap *flow_table) if (state != S_UPDATE_FLOWS || rconn_packet_counter_n_packets(tx_counter)) { ovn_flow_table_clear(flow_table); - return; + return flows_updated; } /* Iterate through all of the installed flows. If any of them are no @@ -629,6 +633,7 @@ ofctrl_put(struct hmap *flow_table) .command = OFPFC_DELETE_STRICT, }; queue_flow_mod(&fm); + flows_updated = true; ovn_flow_log(i, "removing"); hmap_remove(&installed_flows, &i->hmap_node); @@ -647,6 +652,7 @@ ofctrl_put(struct hmap *flow_table) }; queue_flow_mod(&fm); ovn_flow_log(i, "updating"); + flows_updated = true; /* Replace 'i''s actions by 'd''s. */ free(i->ofpacts); @@ -676,10 +682,13 @@ ofctrl_put(struct hmap *flow_table) .command = OFPFC_ADD, }; queue_flow_mod(&fm); + flows_updated = true; ovn_flow_log(d, "adding"); /* Move 'd' from 'flow_table' to installed_flows. */ hmap_remove(flow_table, &d->hmap_node); hmap_insert(&installed_flows, &d->hmap_node, d->hmap_node.hash); } + + return flows_updated; } diff --git a/ovn/controller/ofctrl.h b/ovn/controller/ofctrl.h index bc9cfba..dd26f6e 100644 --- a/ovn/controller/ofctrl.h +++ b/ovn/controller/ofctrl.h @@ -30,7 +30,7 @@ struct ovsrec_bridge; /* Interface for OVN main loop. */ void ofctrl_init(void); enum mf_field_id ofctrl_run(const struct ovsrec_bridge *br_int); -void ofctrl_put(struct hmap *flows); +bool ofctrl_put(struct hmap *flows); void ofctrl_wait(void); void ofctrl_destroy(void); diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 511b184..2a06f7c 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -252,6 +252,34 @@ get_ovnsb_remote_probe_interval(struct ovsdb_idl *ovs_idl, int *value) return false; } +/* Set the current configuration of the local chassis to the OVN Southbound + * next_cfg value. This indicates that the ovn-controller has picked up and + * applied (queued) the latest flows. + */ +static bool +update_chassis_config(struct controller_ctx *ctx, const char *chassis_id) +{ + const struct sbrec_chassis *chassis_rec; + + if (!ctx->ovnsb_idl || !ctx->ovnsb_idl_txn) { + return false; + } + + chassis_rec = get_chassis(ctx->ovnsb_idl, chassis_id); + if (!chassis_rec) { + return false; + } + + const struct sbrec_config *sb_config + = sbrec_config_first(ctx->ovnsb_idl); + if (!sb_config) { + return false; + } + + sbrec_chassis_set_cur_cfg(chassis_rec, sb_config->next_cfg); + return true; +} + int main(int argc, char *argv[]) { @@ -384,7 +412,20 @@ main(int argc, char *argv[]) br_int, chassis_id, &ct_zones, &flow_table, &local_datapaths, &patched_datapaths); } - ofctrl_put(&flow_table); + /* Update the cur_cfg of the local chassis if the flow table + * was (pended to be) modified in a previous iteration but no + * modified in the current iteration. This indicates that the + * flow modification has reached a steady state (for now). + */ + static bool new_flows_pended = false; + if (ofctrl_put(&flow_table)) { + new_flows_pended = true; + } + else if (new_flows_pended && chassis_id) { + if (update_chassis_config(&ctx, chassis_id)) { + new_flows_pended = false; + } + } hmap_destroy(&flow_table); mcgroup_index_destroy(&mcgroups); lport_index_destroy(&lports); diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 44e9430..954978a 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -2382,6 +2382,54 @@ add_column_noalert(struct ovsdb_idl *idl, ovsdb_idl_omit_alert(idl, column); } +static void +cp_nextcfg_to_sb(struct northd_context *ctx) +{ + const struct nbrec_config *nb; + const struct sbrec_config *sb; + + nb = nbrec_config_first(ctx->ovnnb_idl); + if (!nb && ctx->ovnnb_txn) { + /* XXX add verification that table is empty */ + nb = nbrec_config_insert(ctx->ovnnb_txn); + } + + sb = sbrec_config_first(ctx->ovnsb_idl); + if (!sb && ctx->ovnsb_txn) { + /* XXX add verification that table is empty */ + sb = sbrec_config_insert(ctx->ovnsb_txn); + } + + if (sb && nb && ctx->ovnsb_txn && sb->next_cfg < nb->next_cfg) { + sbrec_config_set_next_cfg(sb, nb->next_cfg); + } +} + +/* Compute the cur_cfg of the OVN_Northbound as the minimum of all cur_cfg + * values in the Chassis Table. + */ +static void +compute_curcfg(struct northd_context *ctx) +{ + const struct nbrec_config *nb; + const struct sbrec_chassis *chassis_rec; + int64_t cur_cfg_min = (((int64_t)1) << 62) - 1; + bool cur_cfg_modified = false; + + SBREC_CHASSIS_FOR_EACH(chassis_rec, ctx->ovnsb_idl) { + if (cur_cfg_min > chassis_rec->cur_cfg) { + cur_cfg_min = chassis_rec->cur_cfg; + cur_cfg_modified = true; + } + } + + nb = nbrec_config_first(ctx->ovnnb_idl); + if (nb && ctx->ovnnb_txn && cur_cfg_modified && + nb->cur_cfg < cur_cfg_min) { + nbrec_config_set_cur_cfg(nb, cur_cfg_min); + } +} + int main(int argc, char *argv[]) { @@ -2452,6 +2500,12 @@ main(int argc, char *argv[]) add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_mac); ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_port_binding_col_chassis); + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_cur_cfg); + + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_config); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_config_col_next_cfg); + /* Main loop. */ exiting = false; while (!exiting) { @@ -2462,6 +2516,8 @@ main(int argc, char *argv[]) .ovnsb_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop), }; + cp_nextcfg_to_sb(&ctx); + compute_curcfg(&ctx); ovnnb_db_run(&ctx); ovnsb_db_run(&ctx); diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema index 8163f6a..fd6e16f 100644 --- a/ovn/ovn-nb.ovsschema +++ b/ovn/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", "version": "2.1.1", - "cksum": "2615511875 5108", + "cksum": "3226126619 5306", "tables": { "Logical_Switch": { "columns": { @@ -99,6 +99,12 @@ "ip_prefix": {"type": "string"}, "nexthop": {"type": "string"}, "output_port": {"type": {"key": "string", "min": 0, "max": 1}}}, - "isRoot": false} + "isRoot": false}, + "Config": { + "columns": { + "cur_cfg": {"type": "integer"}, + "next_cfg": {"type": "integer"}}, + "isRoot": true, + "maxRows": 1} } } diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml index c01455d..96dabd4 100644 --- a/ovn/ovn-nb.xml +++ b/ovn/ovn-nb.xml @@ -637,7 +637,7 @@ column is set to <code>false</code>, the router is disabled. A disabled router has all ingress and egress traffic dropped. </column> - + <group title="Common Columns"> <column name="external_ids"> See <em>External IDs</em> at the beginning of this document. @@ -757,4 +757,23 @@ </column> </table> + <table name="Config" title="OVN Northbound configuration."> + Configuration for an OVN Northbound DB. There must be exactly + one record in the <ref table="Config"/> table. + + <group title="Status"> + <column name="next_cfg"> + Sequence number for client to increment. When a client + modifies any part of the database configuration and wishes to + wait for all the ovn-controllers to finish applying the + changes, it may increment this sequence number. + </column> + + <column name="cur_cfg"> + Sequence number that ovn-northd sets to the current value of + <ref column="next_cfg"/> after all the ovn-controllers have + applied a (configuration) sequence number. + </column> + </group> + </table> </database> diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema index 06e8a07..5d266e2 100644 --- a/ovn/ovn-sb.ovsschema +++ b/ovn/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", "version": "1.3.0", - "cksum": "654726257 5528", + "cksum": "329629017 5732", "tables": { "Chassis": { "columns": { @@ -13,6 +13,7 @@ "vtep_logical_switches" : {"type": {"key": "string", "min": 0, "max": "unlimited"}}, + "cur_cfg": {"type": "integer"}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, @@ -110,4 +111,11 @@ "ip": {"type": "string"}, "mac": {"type": "string"}}, "indexes": [["logical_port", "ip"]], - "isRoot": true}}} + "isRoot": true}, + "Config": { + "columns": { + "next_cfg": {"type": "integer"}}, + "isRoot": true, + "maxRows": 1} + } +} diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml index efd2f9a..28938ee 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -179,6 +179,13 @@ information. </column> + <column name='cur_cfg'> + <code>ovn-controller</code> populates this value with the value + of <ref column="next_cfg"/> in <ref table='Config'/> after it + successfully applies all the logical flows in the OVN + Southbound database as open flow rules. + </column> + <group title="Common Columns"> The overall purpose of these columns is described under <code>Common Columns</code> at the beginning of this document. @@ -1511,4 +1518,16 @@ tcp.flags = RST; The Ethernet address to which the IP is bound. </column> </table> + + <table name="Config" title="OVN Southbound configuration."> + Configuration for an OVN Northbound DB. There must be exactly + one record in the <ref table="Config"/> table. + + <group title="Status"> + <column name="next_cfg"> + Sequence number copied by <code>ovn-northd</code> from the + OVN Northbound database when that value changes. + </column> + </group> + </table> </database> diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml index 8375ab7..52b092a 100644 --- a/ovn/utilities/ovn-nbctl.8.xml +++ b/ovn/utilities/ovn-nbctl.8.xml @@ -12,6 +12,35 @@ <h1>General Commands</h1> <dl> + <dt><code>nop</code></dt> + <dd> + <p> + Implements an empty action. It should be used with the + <var>--wait</var> to wait for the ovn-controllers to sync up with + the OVN Northbound DB. + </p> + <p> + The <code>ovn-nbctl</code> utility increments the <var>next_cfg</var> + in the <code>Config</code> Table of the OVN Northbound. When + a <code>ovn-controllers</code> picks up and pends the corresponding + OpenFlow rules on the hypervisors, it sets its own + <code>Chassis's</code> <var>cur_cfg</var > to the <var>next_cfg</var> + of the OVN Southbound DB, which is essentially a copy of + <var>next_cfg</var> of the OVN Northbound DB. The + <code>ovn-northd</code> sets the <var>cur_cfg</var> of in the + OVN Northbound to the minimum value of <var>cur_cfg</var> + reported by the <code>Chassis'</code>. + </p> + <p> + The <var>--wait</var> option informs <code>ovn-nbctl</code> to + wait for <var>cur_cfg</var> to equal <var>next_cfg</var>. It should + be noted that there may be <code>ovn-nbctl</code> actions that + modify the OVN Northbound <var>next_cfg</var> but do not result in + OpenFlow rules. In such cases the <var>cur_cfg</var> will not equal + the <var>next_cfg</var> till a future operation updates the OpenFlow + rules in the hypervisor. + </p> + </dd> <dt><code>show [<var>lswitch</var>]</code></dt> <dd> Prints a brief overview of the database contents. If diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index d267829..fd1620c 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -48,6 +48,9 @@ static bool oneline; /* --dry-run: Do not commit any changes. */ static bool dry_run; +/* --wait: Wait for all ovn-controllers to apply open flow rules. */ +static bool wait_for_controllers = false; + /* --timeout: Time to wait for a connection to 'db'. */ static int timeout; @@ -68,7 +71,7 @@ static const char *nbctl_default_db(void); static void run_prerequisites(struct ctl_command[], size_t n_commands, struct ovsdb_idl *); static bool do_nbctl(const char *args, struct ctl_command *, size_t n, - struct ovsdb_idl *); + struct ovsdb_idl *, bool might_write_to_db); int main(int argc, char *argv[]) @@ -79,6 +82,7 @@ main(int argc, char *argv[]) unsigned int seqno; size_t n_commands; char *args; + bool might_write_to_db; set_program_name(argv[0]); fatal_ignore_sigpipe(); @@ -90,8 +94,8 @@ main(int argc, char *argv[]) /* Log our arguments. This is often valuable for debugging systems. */ args = process_escape_args(argv); - VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG, - "Called as %s", args); + might_write_to_db = ctl_might_write_to_db(argv); + VLOG(might_write_to_db ? VLL_INFO : VLL_DBG, "Called as %s", args); /* Parse command line. */ shash_init(&local_options); @@ -125,7 +129,8 @@ main(int argc, char *argv[]) if (seqno != ovsdb_idl_get_seqno(idl)) { seqno = ovsdb_idl_get_seqno(idl); - if (do_nbctl(args, commands, n_commands, idl)) { + if (do_nbctl(args, commands, n_commands, idl, + might_write_to_db)) { free(args); exit(EXIT_SUCCESS); } @@ -157,6 +162,7 @@ parse_options(int argc, char *argv[], struct shash *local_options) enum { OPT_DB = UCHAR_MAX + 1, OPT_NO_SYSLOG, + OPT_WAIT, OPT_DRY_RUN, OPT_ONELINE, OPT_LOCAL, @@ -168,6 +174,7 @@ parse_options(int argc, char *argv[], struct shash *local_options) static const struct option global_long_options[] = { {"db", required_argument, NULL, OPT_DB}, {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, + {"wait", optional_argument, NULL, OPT_WAIT}, {"dry-run", no_argument, NULL, OPT_DRY_RUN}, {"oneline", no_argument, NULL, OPT_ONELINE}, {"timeout", required_argument, NULL, 't'}, @@ -224,6 +231,10 @@ parse_options(int argc, char *argv[], struct shash *local_options) vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN); break; + case OPT_WAIT: + wait_for_controllers = true; + break; + case OPT_DRY_RUN: dry_run = true; break; @@ -339,6 +350,7 @@ Options:\n\ --db=DATABASE connect to DATABASE\n\ (default: %s)\n\ -t, --timeout=SECS wait at most SECS seconds\n\ + --wait wait for ovn-controllers to sync with NB\n\ --dry-run do not commit changes to database\n\ --oneline print exactly one line of output per command\n", program_name, program_name, ctl_get_db_cmd_usage(), nbctl_default_db()); @@ -1162,22 +1174,36 @@ run_prerequisites(struct ctl_command *commands, size_t n_commands, static bool do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands, - struct ovsdb_idl *idl) + struct ovsdb_idl *idl, bool might_write_to_db) { struct ovsdb_idl_txn *txn; + const struct nbrec_config *nb; enum ovsdb_idl_txn_status status; struct ovsdb_symbol_table *symtab; struct ctl_context ctx; struct ctl_command *c; struct shash_node *node; char *error = NULL; + int64_t next_cfg = 0; txn = the_idl_txn = ovsdb_idl_txn_create(idl); if (dry_run) { ovsdb_idl_txn_set_dry_run(txn); } - ovsdb_idl_txn_add_comment(txn, "ovs-nbctl: %s", args); + ovsdb_idl_txn_add_comment(txn, "ovn-nbctl: %s", args); + + nb = nbrec_config_first(idl); + if (!nb) { + /* XXX add verification that table is empty */ + nb = nbrec_config_insert(txn); + } + + next_cfg = nb->next_cfg; + if (might_write_to_db) { + ovsdb_idl_txn_increment(txn, &nb->header_, + &nbrec_config_col_next_cfg); + } symtab = ovsdb_symbol_table_create(); for (c = commands; c < &commands[n_commands]; c++) { @@ -1220,6 +1246,9 @@ do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands, } status = ovsdb_idl_txn_commit_block(txn); + if (status == TXN_SUCCESS && might_write_to_db) { + next_cfg = ovsdb_idl_txn_get_increment_new_value(txn); + } if (status == TXN_UNCHANGED || status == TXN_SUCCESS) { for (c = commands; c < &commands[n_commands]; c++) { if (c->syntax->postprocess) { @@ -1296,6 +1325,20 @@ do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands, shash_destroy_free_data(&c->options); } free(commands); + + if (wait_for_controllers) { + for (;;) { + ovsdb_idl_run(idl); + NBREC_CONFIG_FOR_EACH(nb, idl) { + if (nb->cur_cfg >= next_cfg) { + goto done; + } + } + ovsdb_idl_wait(idl); + poll_block(); + } + done: ; + } ovsdb_idl_txn_destroy(txn); ovsdb_idl_destroy(idl); @@ -1337,6 +1380,7 @@ nbctl_exit(int status) } static const struct ctl_command_syntax nbctl_commands[] = { + { "nop", 0, 1, "[]", NULL, NULL, NULL, "", RO }, { "show", 0, 1, "[LSWITCH]", NULL, nbctl_show, NULL, "", RO }, /* lswitch commands. */ diff --git a/tests/ovn.at b/tests/ovn.at index e6ac1d7..1458134 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -589,8 +589,7 @@ ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport == "lp33"' d ovn_populate_arp # Allow some time for ovn-northd and ovn-controller to catch up. -# XXX This should be more systematic. -sleep 1 +ovn-nbctl --wait nop # Given the name of a logical port, prints the name of the hypervisor # on which it is located. @@ -762,6 +761,10 @@ done # set address for lp13 with invalid characters. # lp13 should be configured with only 192.168.0.13. ovn-nbctl lport-set-addresses lp13 "f0:00:00:00:00:13 192.168.0.13 invalid 192.169.0.13" + +# Allow some time for ovn-northd and ovn-controller to catch up. +ovn-nbctl --wait nop + sip=`ip_to_hex 192 168 0 11` tip=`ip_to_hex 192 168 0 13` test_arp 11 f00000000011 $sip $tip f00000000013 @@ -898,6 +901,9 @@ for i in 1 2; do done done +# Allow some time for ovn-northd and ovn-controller to catch up. +ovn-nbctl --wait nop + ovn_populate_arp # XXX This is now the 3rd copy of these functions in this file ... @@ -1108,8 +1114,7 @@ ovs-vsctl add-port br-phys vif3 -- set Interface vif3 options:tx_pcap=hv3/vif3-t ovn_populate_arp # Allow some time for ovn-northd and ovn-controller to catch up. -# XXX This should be more systematic. -sleep 1 +ovn-nbctl --wait nop # test_packet INPORT DST SRC ETHTYPE OUTPORT... # @@ -1339,8 +1344,7 @@ done ovn_populate_arp # Allow some time for ovn-northd and ovn-controller to catch up. -# XXX This should be more systematic. -sleep 1 +ovn-nbctl --wait nop # test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT... # @@ -1698,8 +1702,7 @@ done ovn_populate_arp # Allow some time for ovn-northd and ovn-controller to catch up. -# XXX This should be more systematic. -sleep 1 +ovn-nbctl --wait nop # Given the name of a logical port, prints the name of the hypervisor # on which it is located. @@ -1937,7 +1940,8 @@ done # configure lport13 to send and received IPv4 packets with an address range ovn-nbctl lport-set-port-security lp13 "f0:00:00:00:00:13 192.168.0.13 20.0.0.4/24 10.0.0.0/24" -sleep 2 +# Allow some time for ovn-northd and ovn-controller to catch up. +ovn-nbctl --wait nop sip=`ip_to_hex 10 0 0 13` tip=`ip_to_hex 192 168 0 22` @@ -2130,8 +2134,7 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \ ovn_populate_arp # Allow some time for ovn-northd and ovn-controller to catch up. -# XXX This should be more systematic. -sleep 1 +ovn-nbctl --wait nop # Send ip packets between the two ports. ip_to_hex() { @@ -2262,8 +2265,7 @@ ovs-vsctl -- add-port br-int vif2 -- \ # Allow some time for ovn-northd and ovn-controller to catch up. -# XXX This should be more systematic. -sleep 1 +ovn-nbctl --wait nop # Send ip packets between the two ports. ip_to_hex() { @@ -2303,6 +2305,9 @@ as hv1 ovs-ofctl dump-flows br-int #Disable router R1 ovn-nbctl set Logical_Router R1 enabled=false +# Allow some time for ovn-northd and ovn-controller to catch up. +ovn-nbctl --wait nop + echo "---------SB dump-----" ovn-sbctl list datapath_binding echo "---------------------" @@ -2459,8 +2464,7 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \ ovn_populate_arp # Allow some time for ovn-northd and ovn-controller to catch up. -# XXX This should be more systematic. -sleep 1 +ovn-nbctl --wait nop ip_to_hex() { printf "%02x%02x%02x%02x" "$@" @@ -2577,6 +2581,9 @@ AT_CHECK([ovn-nbctl lport-set-options ln_port network_name=physnet1]) AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1 external_ids:iface-id=localvif1]) +# Allow some time for ovn-northd and ovn-controller to catch up. +ovn-nbctl --wait nop + # Wait for packet to be received. OVS_WAIT_UNTIL([test `wc -c < "hv/snoopvif-tx.pcap"` -ge 50]) trim_zeros() { -- 2.7.4 (Apple Git-66) _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev