From: RYAN D. MOATS <rmo...@us.ibm.com> Make flow table persistent in ovn controller
This is a prerequisite for incremental processing. Signed-off-by: RYAN D. MOATS <rmo...@us.ibm.com> --- ovn/controller/ofctrl.c | 99 ++++++++++++++++++++++++++++----------- ovn/controller/ofctrl.h | 2 + ovn/controller/ovn-controller.c | 4 +- 3 files changed, 75 insertions(+), 30 deletions(-) diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index 3297fb3..e5f4ebf 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -50,6 +50,8 @@ struct ovn_flow { static uint32_t ovn_flow_hash(const struct ovn_flow *); static struct ovn_flow *ovn_flow_lookup(struct hmap *flow_table, const struct ovn_flow *target); +static struct ovn_flow *ovn_flow_lookup2(struct hmap *flow_table, + const struct ovn_flow *target); static char *ovn_flow_to_string(const struct ovn_flow *); static void ovn_flow_log(const struct ovn_flow *, const char *action); static void ovn_flow_destroy(struct ovn_flow *); @@ -484,21 +486,41 @@ ofctrl_add_flow(struct hmap *desired_flows, f->ofpacts_len = actions->size; f->hmap_node.hash = ovn_flow_hash(f); - if (ovn_flow_lookup(desired_flows, f)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); - if (!VLOG_DROP_INFO(&rl)) { - char *s = ovn_flow_to_string(f); - VLOG_INFO("dropping duplicate flow: %s", s); - free(s); - } + struct ovn_flow *d = ovn_flow_lookup2(desired_flows, f); + if (d) { + if (!match_equal(&d->match, &f->match)) { - ovn_flow_destroy(f); - return; + hmap_remove(desired_flows, &d->hmap_node); + ovn_flow_destroy(d); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); + if (!VLOG_DROP_INFO(&rl)) { + char *s = ovn_flow_to_string(f); + VLOG_INFO("dropping duplicate flow: %s", s); + free(s); + } + + ovn_flow_destroy(f); + return; + } } hmap_insert(desired_flows, &f->hmap_node, f->hmap_node.hash); } +/* duplicate an ovn_flow structure */ +struct ovn_flow *ofctrl_dup_flow(struct ovn_flow *source) +{ + struct ovn_flow *answer = xmalloc(sizeof *answer); + answer->table_id = source->table_id; + answer->priority = source->priority; + answer->match = source->match; + answer->ofpacts = xmemdup(source->ofpacts, source->ofpacts_len); + answer->ofpacts_len = source->ofpacts_len; + answer->hmap_node.hash = ovn_flow_hash(answer); + return answer; +} + /* ovn_flow. */ /* Returns a hash of the key in 'f'. */ @@ -528,6 +550,25 @@ ovn_flow_lookup(struct hmap *flow_table, const struct ovn_flow *target) return NULL; } +/* Finds and returns an ovn_flow in 'flow_table" whose table_id, priority + * and actions are the same as the target, or NULL if there is none */ +static struct ovn_flow * +ovn_flow_lookup2(struct hmap *flow_table, const struct ovn_flow *target) +{ + struct ovn_flow *f; + + HMAP_FOR_EACH_WITH_HASH (f, hmap_node, target->hmap_node.hash, + flow_table) { + if (f->table_id == target->table_id + && f->priority == target->priority + && ofpacts_equal(f->ofpacts, f->ofpacts_len, + target->ofpacts, target->ofpacts_len)) { + return f; + } + } + return NULL; +} + static char * ovn_flow_to_string(const struct ovn_flow *f) { @@ -607,7 +648,6 @@ ofctrl_put(struct hmap *flow_table) * to wake up and retry. */ if (state != S_UPDATE_FLOWS || rconn_packet_counter_n_packets(tx_counter)) { - ovn_flow_table_clear(flow_table); return; } @@ -659,25 +699,28 @@ ofctrl_put(struct hmap *flow_table) } } - /* The previous loop removed from 'flow_table' all of the flows that are - * already installed. Thus, any flows remaining in 'flow_table' need to - * be added to the flow table. */ + /* Since flow table has all flows, now we need to add the ones that + * aren't in the installed flow table. */ struct ovn_flow *d; HMAP_FOR_EACH_SAFE (d, next, hmap_node, flow_table) { - /* Send flow_mod to add flow. */ - struct ofputil_flow_mod fm = { - .match = d->match, - .priority = d->priority, - .table_id = d->table_id, - .ofpacts = d->ofpacts, - .ofpacts_len = d->ofpacts_len, - .command = OFPFC_ADD, - }; - queue_flow_mod(&fm); - 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); + struct ovn_flow *i = ovn_flow_lookup(&installed_flows, d); + if (!i) { + /* Send flow_mod to add flow. */ + struct ofputil_flow_mod fm = { + .match = d->match, + .priority = d->priority, + .table_id = d->table_id, + .ofpacts = d->ofpacts, + .ofpacts_len = d->ofpacts_len, + .command = OFPFC_ADD, + }; + queue_flow_mod(&fm); + ovn_flow_log(d, "adding"); + + /* Copy 'd' from 'flow_table' to installed_flows. */ + struct ovn_flow *new_node = ofctrl_dup_flow(d); + hmap_insert(&installed_flows, &new_node->hmap_node, + new_node->hmap_node.hash); + } } } diff --git a/ovn/controller/ofctrl.h b/ovn/controller/ofctrl.h index 93ef8ea..d3fabc0 100644 --- a/ovn/controller/ofctrl.h +++ b/ovn/controller/ofctrl.h @@ -34,6 +34,8 @@ void ofctrl_put(struct hmap *flows); void ofctrl_wait(void); void ofctrl_destroy(void); +struct ovn_flow *ofctrl_dup_flow(struct ovn_flow *source); + /* Flow table interface to the rest of ovn-controller. */ void ofctrl_add_flow(struct hmap *flows, uint8_t table_id, uint16_t priority, const struct match *, const struct ofpbuf *ofpacts); diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 3638342..5a4174e 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -205,6 +205,8 @@ main(int argc, char *argv[]) bool exiting; int retval; + struct hmap flow_table = HMAP_INITIALIZER(&flow_table); + ovs_cmdl_proctitle_init(argc, argv); set_program_name(argv[0]); service_start(&argc, &argv); @@ -299,14 +301,12 @@ main(int argc, char *argv[]) pinctrl_run(&ctx, br_int); - struct hmap flow_table = HMAP_INITIALIZER(&flow_table); lflow_run(&ctx, &flow_table, &ct_zones, &local_datapaths); if (chassis_id) { physical_run(&ctx, mff_ovn_geneve, br_int, chassis_id, &ct_zones, &flow_table); } ofctrl_put(&flow_table); - hmap_destroy(&flow_table); } /* local_datapaths contains bare hmap_node instances. -- 1.7.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev