Acked-by: Justin Pettit <jpet...@nicira.com> --Justin
> On Jul 28, 2015, at 8:44 AM, Ben Pfaff <b...@nicira.com> wrote: > > These two pieces of code have different requirements and hardly anything in > common, and I found it easier to understand and reasonably modify the > overall structure of the program when they were separated. > > Signed-off-by: Ben Pfaff <b...@nicira.com> > --- > ovn/controller/automake.mk | 2 + > ovn/controller/chassis.c | 315 ++------------------------------- > ovn/controller/chassis.h | 6 +- > ovn/controller/{chassis.c => encaps.c} | 129 ++------------ > ovn/controller/{chassis.h => encaps.h} | 12 +- > ovn/controller/ovn-controller.c | 12 +- > 6 files changed, 49 insertions(+), 427 deletions(-) > copy ovn/controller/{chassis.c => encaps.c} (72%) > copy ovn/controller/{chassis.h => encaps.h} (79%) > > diff --git a/ovn/controller/automake.mk b/ovn/controller/automake.mk > index 25b5f8b..9ed6bec 100644 > --- a/ovn/controller/automake.mk > +++ b/ovn/controller/automake.mk > @@ -4,6 +4,8 @@ ovn_controller_ovn_controller_SOURCES = \ > ovn/controller/binding.h \ > ovn/controller/chassis.c \ > ovn/controller/chassis.h \ > + ovn/controller/encaps.c \ > + ovn/controller/encaps.h \ > ovn/controller/ofctrl.c \ > ovn/controller/ofctrl.h \ > ovn/controller/ovn-controller.c \ > diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c > index 4bd39e7..5f1c194 100644 > --- a/ovn/controller/chassis.c > +++ b/ovn/controller/chassis.c > @@ -16,10 +16,6 @@ > #include <config.h> > #include "chassis.h" > > -#include "lib/hash.h" > -#include "lib/poll-loop.h" > -#include "lib/sset.h" > -#include "lib/util.h" > #include "lib/vswitch-idl.h" > #include "openvswitch/vlog.h" > #include "ovn/lib/ovn-sb-idl.h" > @@ -32,21 +28,15 @@ chassis_init(struct controller_ctx *ctx) > { > ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_open_vswitch); > ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_open_vswitch_col_external_ids); > - ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_bridge); > - ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_bridge_col_ports); > - ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_port); > - ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_port_col_name); > - ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_port_col_interfaces); > - ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_port_col_external_ids); > - ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_interface); > - ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_name); > - ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_type); > - ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_options); > } > > -static void > -register_chassis(struct controller_ctx *ctx) > +void > +chassis_run(struct controller_ctx *ctx) > { > + if (!ctx->ovnsb_idl_txn) { > + return; > + } > + > const struct sbrec_chassis *chassis_rec; > const struct ovsrec_open_vswitch *cfg; > const char *encap_type, *encap_ip; > @@ -109,303 +99,22 @@ register_chassis(struct controller_ctx *ctx) > inited = true; > } > > -/* Enough context to create a new tunnel, using tunnel_add(). */ > -struct tunnel_ctx { > - /* Contains "struct port_hash_node"s. Used to figure out what > - * existing tunnels should be deleted: we index all of the OVN encap > - * rows into this data structure, then as existing rows are > - * generated we remove them. After generating all the rows, any > - * remaining in 'tunnel_hmap' must be deleted from the database. */ > - struct hmap tunnel_hmap; > - > - /* Names of all ports in the bridge, to allow checking uniqueness when > - * adding a new tunnel. */ > - struct sset port_names; > - > - struct ovsdb_idl_txn *ovs_txn; > - const struct ovsrec_bridge *br_int; > -}; > - > -struct port_hash_node { > - struct hmap_node node; > - const struct ovsrec_port *port; > - const struct ovsrec_bridge *bridge; > -}; > - > -static size_t > -port_hash(const char *chassis_id, const char *type, const char *ip) > -{ > - size_t hash = hash_string(chassis_id, 0); > - hash = hash_string(type, hash); > - return hash_string(ip, hash); > -} > - > -static size_t > -port_hash_rec(const struct ovsrec_port *port) > -{ > - const char *chassis_id, *ip; > - const struct ovsrec_interface *iface; > - > - chassis_id = smap_get(&port->external_ids, "ovn-chassis-id"); > - > - if (!chassis_id || !port->n_interfaces) { > - /* This should not happen for an OVN-created port. */ > - return 0; > - } > - > - iface = port->interfaces[0]; > - ip = smap_get(&iface->options, "remote_ip"); > - > - return port_hash(chassis_id, iface->type, ip); > -} > - > -static char * > -tunnel_create_name(struct tunnel_ctx *tc, const char *chassis_id) > -{ > - int i; > - > - for (i = 0; i < UINT16_MAX; i++) { > - char *port_name; > - port_name = xasprintf("ovn-%.6s-%x", chassis_id, i); > - > - if (!sset_contains(&tc->port_names, port_name)) { > - return port_name; > - } > - > - free(port_name); > - } > - > - return NULL; > -} > - > - > -static void > -tunnel_add(struct tunnel_ctx *tc, const char *new_chassis_id, > - const struct sbrec_encap *encap) > -{ > - struct port_hash_node *hash_node; > - > - /* Check whether such a row already exists in OVS. If so, remove it > - * from 'tc->tunnel_hmap' and we're done. */ > - HMAP_FOR_EACH_WITH_HASH (hash_node, node, > - port_hash(new_chassis_id, > - encap->type, encap->ip), > - &tc->tunnel_hmap) { > - const struct ovsrec_port *port = hash_node->port; > - const char *chassis_id = smap_get(&port->external_ids, > - "ovn-chassis-id"); > - const struct ovsrec_interface *iface; > - const char *ip; > - > - if (!chassis_id || !port->n_interfaces) { > - continue; > - } > - > - iface = port->interfaces[0]; > - ip = smap_get(&iface->options, "remote_ip"); > - if (!ip) { > - continue; > - } > - > - if (!strcmp(new_chassis_id, chassis_id) > - && !strcmp(encap->type, iface->type) > - && !strcmp(encap->ip, ip)) { > - hmap_remove(&tc->tunnel_hmap, &hash_node->node); > - free(hash_node); > - return; > - } > - } > - > - /* No such port, so add one. */ > - struct smap external_ids = SMAP_INITIALIZER(&external_ids); > - struct smap options = SMAP_INITIALIZER(&options); > - struct ovsrec_port *port, **ports; > - struct ovsrec_interface *iface; > - char *port_name; > - size_t i; > - > - port_name = tunnel_create_name(tc, new_chassis_id); > - if (!port_name) { > - VLOG_WARN("Unable to allocate unique name for '%s' tunnel", > - new_chassis_id); > - return; > - } > - > - iface = ovsrec_interface_insert(tc->ovs_txn); > - ovsrec_interface_set_name(iface, port_name); > - ovsrec_interface_set_type(iface, encap->type); > - smap_add(&options, "remote_ip", encap->ip); > - smap_add(&options, "key", "flow"); > - ovsrec_interface_set_options(iface, &options); > - smap_destroy(&options); > - > - port = ovsrec_port_insert(tc->ovs_txn); > - ovsrec_port_set_name(port, port_name); > - ovsrec_port_set_interfaces(port, &iface, 1); > - smap_add(&external_ids, "ovn-chassis-id", new_chassis_id); > - ovsrec_port_set_external_ids(port, &external_ids); > - smap_destroy(&external_ids); > - > - ports = xmalloc(sizeof *tc->br_int->ports * (tc->br_int->n_ports + 1)); > - for (i = 0; i < tc->br_int->n_ports; i++) { > - ports[i] = tc->br_int->ports[i]; > - } > - ports[tc->br_int->n_ports] = port; > - ovsrec_bridge_verify_ports(tc->br_int); > - ovsrec_bridge_set_ports(tc->br_int, ports, tc->br_int->n_ports + 1); > - > - sset_add(&tc->port_names, port_name); > - free(port_name); > - free(ports); > -} > - > -static void > -bridge_delete_port(const struct ovsrec_bridge *br, > - const struct ovsrec_port *port) > -{ > - struct ovsrec_port **ports; > - size_t i, n; > - > - ports = xmalloc(sizeof *br->ports * br->n_ports); > - for (i = n = 0; i < br->n_ports; i++) { > - if (br->ports[i] != port) { > - ports[n++] = br->ports[i]; > - } > - } > - ovsrec_bridge_verify_ports(br); > - ovsrec_bridge_set_ports(br, ports, n); > - free(ports); > -} > - > -static struct sbrec_encap * > -preferred_encap(const struct sbrec_chassis *chassis_rec) > -{ > - size_t i; > - > - /* For hypervisors, we only support Geneve and STT encapsulations. > - * Sets are returned alphabetically, so "geneve" will be preferred > - * over "stt". */ > - for (i = 0; i < chassis_rec->n_encaps; i++) { > - if (!strcmp(chassis_rec->encaps[i]->type, "geneve") > - || !strcmp(chassis_rec->encaps[i]->type, "stt")) { > - return chassis_rec->encaps[i]; > - } > - } > - > - return NULL; > -} > - > -static void > -update_encaps(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int) > -{ > - const struct sbrec_chassis *chassis_rec; > - const struct ovsrec_bridge *br; > - > - struct tunnel_ctx tc = { > - .tunnel_hmap = HMAP_INITIALIZER(&tc.tunnel_hmap), > - .port_names = SSET_INITIALIZER(&tc.port_names), > - .br_int = br_int > - }; > - > - tc.ovs_txn = ctx->ovs_idl_txn; > - ovsdb_idl_txn_add_comment(tc.ovs_txn, > - "ovn-controller: modifying OVS tunnels '%s'", > - ctx->chassis_id); > - > - /* Collect all port names into tc.port_names. > - * > - * Collect all the OVN-created tunnels into tc.tunnel_hmap. */ > - OVSREC_BRIDGE_FOR_EACH(br, ctx->ovs_idl) { > - size_t i; > - > - for (i = 0; i < br->n_ports; i++) { > - const struct ovsrec_port *port = br->ports[i]; > - > - sset_add(&tc.port_names, port->name); > - > - if (smap_get(&port->external_ids, "ovn-chassis-id")) { > - struct port_hash_node *hash_node = xzalloc(sizeof > *hash_node); > - hash_node->bridge = br; > - hash_node->port = port; > - hmap_insert(&tc.tunnel_hmap, &hash_node->node, > - port_hash_rec(port)); > - } > - } > - } > - > - SBREC_CHASSIS_FOR_EACH(chassis_rec, ctx->ovnsb_idl) { > - if (strcmp(chassis_rec->name, ctx->chassis_id)) { > - /* Create tunnels to the other chassis. */ > - const struct sbrec_encap *encap = preferred_encap(chassis_rec); > - if (!encap) { > - VLOG_INFO("No supported encaps for '%s'", chassis_rec->name); > - continue; > - } > - tunnel_add(&tc, chassis_rec->name, encap); > - } > - } > - > - /* Delete any existing OVN tunnels that were not still around. */ > - struct port_hash_node *hash_node, *next_hash_node; > - HMAP_FOR_EACH_SAFE (hash_node, next_hash_node, node, &tc.tunnel_hmap) { > - hmap_remove(&tc.tunnel_hmap, &hash_node->node); > - bridge_delete_port(hash_node->bridge, hash_node->port); > - free(hash_node); > - } > - hmap_destroy(&tc.tunnel_hmap); > - sset_destroy(&tc.port_names); > -} > - > -void > -chassis_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int) > -{ > - if (ctx->ovnsb_idl_txn) { > - register_chassis(ctx); > - } > - > - if (ctx->ovs_idl_txn) { > - update_encaps(ctx, br_int); > - } > -} > - > /* Returns true if the database is all cleaned up, false if more work is > * required. */ > bool > -chassis_cleanup(struct controller_ctx *ctx, const struct ovsrec_bridge > *br_int) > +chassis_cleanup(struct controller_ctx *ctx) > { > - if (!ctx->ovnsb_idl_txn || !ctx->ovs_idl_txn) { > - return false; > - } > - > - bool any_changes = false; > - > /* Delete Chassis row. */ > const struct sbrec_chassis *chassis_rec > = get_chassis_by_name(ctx->ovnsb_idl, ctx->chassis_id); > - if (chassis_rec) { > + if (!chassis_rec) { > + return true; > + } > + if (ctx->ovnsb_idl_txn) { > ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, > "ovn-controller: unregistering chassis > '%s'", > ctx->chassis_id); > sbrec_chassis_delete(chassis_rec); > - any_changes = true; > - } > - > - /* Delete all the OVS-created tunnels from the integration bridge. */ > - ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn, > - "ovn-controller: destroying tunnels"); > - struct ovsrec_port **ports > - = xmalloc(sizeof *br_int->ports * br_int->n_ports); > - size_t n = 0; > - for (size_t i = 0; i < br_int->n_ports; i++) { > - if (!smap_get(&br_int->ports[i]->external_ids, > - "ovn-chassis-id")) { > - ports[n++] = br_int->ports[i]; > - any_changes = true; > - } > } > - ovsrec_bridge_verify_ports(br_int); > - ovsrec_bridge_set_ports(br_int, ports, n); > - free(ports); > - > - return !any_changes; > + return false; > } > diff --git a/ovn/controller/chassis.h b/ovn/controller/chassis.h > index bfacde1..18582ec 100644 > --- a/ovn/controller/chassis.h > +++ b/ovn/controller/chassis.h > @@ -22,9 +22,7 @@ struct controller_ctx; > struct ovsrec_bridge; > > void chassis_init(struct controller_ctx *); > -void chassis_run(struct controller_ctx *, > - const struct ovsrec_bridge *br_int); > -bool chassis_cleanup(struct controller_ctx *, > - const struct ovsrec_bridge *br_int); > +void chassis_run(struct controller_ctx *); > +bool chassis_cleanup(struct controller_ctx *); > > #endif /* ovn/chassis.h */ > diff --git a/ovn/controller/chassis.c b/ovn/controller/encaps.c > similarity index 72% > copy from ovn/controller/chassis.c > copy to ovn/controller/encaps.c > index 4bd39e7..529bf1e 100644 > --- a/ovn/controller/chassis.c > +++ b/ovn/controller/encaps.c > @@ -14,10 +14,9 @@ > */ > > #include <config.h> > -#include "chassis.h" > +#include "encaps.h" > > #include "lib/hash.h" > -#include "lib/poll-loop.h" > #include "lib/sset.h" > #include "lib/util.h" > #include "lib/vswitch-idl.h" > @@ -25,13 +24,11 @@ > #include "ovn/lib/ovn-sb-idl.h" > #include "ovn-controller.h" > > -VLOG_DEFINE_THIS_MODULE(chassis); > +VLOG_DEFINE_THIS_MODULE(encaps); > > void > -chassis_init(struct controller_ctx *ctx) > +encaps_init(struct controller_ctx *ctx) > { > - ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_open_vswitch); > - ovsdb_idl_add_column(ctx->ovs_idl, > &ovsrec_open_vswitch_col_external_ids); > ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_bridge); > ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_bridge_col_ports); > ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_port); > @@ -44,71 +41,6 @@ chassis_init(struct controller_ctx *ctx) > ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_options); > } > > -static void > -register_chassis(struct controller_ctx *ctx) > -{ > - const struct sbrec_chassis *chassis_rec; > - const struct ovsrec_open_vswitch *cfg; > - const char *encap_type, *encap_ip; > - struct sbrec_encap *encap_rec; > - static bool inited = false; > - > - chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, ctx->chassis_id); > - > - /* xxx Need to support more than one encap. Also need to support > - * xxx encap options. */ > - cfg = ovsrec_open_vswitch_first(ctx->ovs_idl); > - if (!cfg) { > - VLOG_INFO("No Open_vSwitch row defined."); > - return; > - } > - > - encap_type = smap_get(&cfg->external_ids, "ovn-encap-type"); > - encap_ip = smap_get(&cfg->external_ids, "ovn-encap-ip"); > - if (!encap_type || !encap_ip) { > - VLOG_INFO("Need to specify an encap type and ip"); > - return; > - } > - > - if (chassis_rec) { > - int i; > - > - for (i = 0; i < chassis_rec->n_encaps; i++) { > - if (!strcmp(chassis_rec->encaps[i]->type, encap_type) > - && !strcmp(chassis_rec->encaps[i]->ip, encap_ip)) { > - /* Nothing changed. */ > - inited = true; > - return; > - } else if (!inited) { > - VLOG_WARN("Chassis config changing on startup, make sure " > - "multiple chassis are not configured : > %s/%s->%s/%s", > - chassis_rec->encaps[i]->type, > - chassis_rec->encaps[i]->ip, > - encap_type, encap_ip); > - } > - > - } > - } > - > - ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, > - "ovn-controller: registering chassis '%s'", > - ctx->chassis_id); > - > - if (!chassis_rec) { > - chassis_rec = sbrec_chassis_insert(ctx->ovnsb_idl_txn); > - sbrec_chassis_set_name(chassis_rec, ctx->chassis_id); > - } > - > - encap_rec = sbrec_encap_insert(ctx->ovnsb_idl_txn); > - > - sbrec_encap_set_type(encap_rec, encap_type); > - sbrec_encap_set_ip(encap_rec, encap_ip); > - > - sbrec_chassis_set_encaps(chassis_rec, &encap_rec, 1); > - > - inited = true; > -} > - > /* Enough context to create a new tunnel, using tunnel_add(). */ > struct tunnel_ctx { > /* Contains "struct port_hash_node"s. Used to figure out what > @@ -295,9 +227,13 @@ preferred_encap(const struct sbrec_chassis *chassis_rec) > return NULL; > } > > -static void > -update_encaps(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int) > +void > +encaps_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int) > { > + if (!ctx->ovs_idl_txn) { > + return; > + } > + > const struct sbrec_chassis *chassis_rec; > const struct ovsrec_bridge *br; > > @@ -356,55 +292,28 @@ update_encaps(struct controller_ctx *ctx, const struct > ovsrec_bridge *br_int) > sset_destroy(&tc.port_names); > } > > -void > -chassis_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int) > -{ > - if (ctx->ovnsb_idl_txn) { > - register_chassis(ctx); > - } > - > - if (ctx->ovs_idl_txn) { > - update_encaps(ctx, br_int); > - } > -} > - > /* Returns true if the database is all cleaned up, false if more work is > * required. */ > bool > -chassis_cleanup(struct controller_ctx *ctx, const struct ovsrec_bridge > *br_int) > +encaps_cleanup(struct controller_ctx *ctx, const struct ovsrec_bridge > *br_int) > { > - if (!ctx->ovnsb_idl_txn || !ctx->ovs_idl_txn) { > - return false; > - } > - > - bool any_changes = false; > - > - /* Delete Chassis row. */ > - const struct sbrec_chassis *chassis_rec > - = get_chassis_by_name(ctx->ovnsb_idl, ctx->chassis_id); > - if (chassis_rec) { > - ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, > - "ovn-controller: unregistering chassis > '%s'", > - ctx->chassis_id); > - sbrec_chassis_delete(chassis_rec); > - any_changes = true; > - } > - > /* Delete all the OVS-created tunnels from the integration bridge. */ > - ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn, > - "ovn-controller: destroying tunnels"); > struct ovsrec_port **ports > = xmalloc(sizeof *br_int->ports * br_int->n_ports); > size_t n = 0; > for (size_t i = 0; i < br_int->n_ports; i++) { > - if (!smap_get(&br_int->ports[i]->external_ids, > - "ovn-chassis-id")) { > + if (!smap_get(&br_int->ports[i]->external_ids, "ovn-chassis-id")) { > ports[n++] = br_int->ports[i]; > - any_changes = true; > } > } > - ovsrec_bridge_verify_ports(br_int); > - ovsrec_bridge_set_ports(br_int, ports, n); > + > + bool any_changes = n != br_int->n_ports; > + if (any_changes && ctx->ovs_idl_txn) { > + ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn, > + "ovn-controller: destroying tunnels"); > + ovsrec_bridge_verify_ports(br_int); > + ovsrec_bridge_set_ports(br_int, ports, n); > + } > free(ports); > > return !any_changes; > diff --git a/ovn/controller/chassis.h b/ovn/controller/encaps.h > similarity index 79% > copy from ovn/controller/chassis.h > copy to ovn/controller/encaps.h > index bfacde1..0ec132d 100644 > --- a/ovn/controller/chassis.h > +++ b/ovn/controller/encaps.h > @@ -13,18 +13,18 @@ > * limitations under the License. > */ > > -#ifndef OVN_CHASSIS_H > -#define OVN_CHASSIS_H 1 > +#ifndef OVN_ENCAPS_H > +#define OVN_ENCAPS_H 1 > > #include <stdbool.h> > > struct controller_ctx; > struct ovsrec_bridge; > > -void chassis_init(struct controller_ctx *); > -void chassis_run(struct controller_ctx *, > +void encaps_init(struct controller_ctx *); > +void encaps_run(struct controller_ctx *, > const struct ovsrec_bridge *br_int); > -bool chassis_cleanup(struct controller_ctx *, > +bool encaps_cleanup(struct controller_ctx *, > const struct ovsrec_bridge *br_int); > > -#endif /* ovn/chassis.h */ > +#endif /* ovn/encaps.h */ > diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c > index 0657140..f3fb3a4 100644 > --- a/ovn/controller/ovn-controller.c > +++ b/ovn/controller/ovn-controller.c > @@ -42,6 +42,7 @@ > #include "ofctrl.h" > #include "binding.h" > #include "chassis.h" > +#include "encaps.h" > #include "physical.h" > #include "pipeline.h" > > @@ -255,6 +256,7 @@ main(int argc, char *argv[]) > ovsdb_idl_add_column(ctx.ovs_idl, &ovsrec_open_vswitch_col_external_ids); > > chassis_init(&ctx); > + encaps_init(&ctx); > binding_init(&ctx); > physical_init(&ctx); > pipeline_init(); > @@ -286,7 +288,8 @@ main(int argc, char *argv[]) > goto exit; > } > > - chassis_run(&ctx, br_int); > + chassis_run(&ctx); > + encaps_run(&ctx, br_int); > binding_run(&ctx, br_int); > > struct hmap flow_table = HMAP_INITIALIZER(&flow_table); > @@ -324,10 +327,11 @@ main(int argc, char *argv[]) > goto exit; > } > > - /* Run both the binding and chassis cleanup, even if one of them > - * returns false. We're done if both return true. */ > + /* Run all of the cleanup functions, even if one of them returns > false. > + * We're done if all of them return true. */ > done = binding_cleanup(&ctx); > - done = chassis_cleanup(&ctx, br_int) && done; > + done = chassis_cleanup(&ctx) && done; > + done = encaps_cleanup(&ctx, br_int) && done; > if (done) { > poll_immediate_wake(); > } > -- > 2.1.3 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev