Persistents flow-table and implements change handler of flow_output for SB lflow changes.
(TODO: test case 2338 failed) Signed-off-by: Han Zhou <hzh...@ebay.com> --- include/ovn/actions.h | 3 + ovn/controller/lflow.c | 104 ++++++++++++++++---- ovn/controller/lflow.h | 10 +- ovn/controller/ofctrl.c | 205 ++++++++++++++++++++++++++++------------ ovn/controller/ofctrl.h | 11 ++- ovn/controller/ovn-controller.c | 79 +++++++++++----- ovn/controller/physical.c | 100 +++++++++++--------- ovn/controller/physical.h | 2 +- ovn/lib/actions.c | 6 +- ovn/lib/extend-table.c | 31 ++++-- ovn/lib/extend-table.h | 9 +- 11 files changed, 391 insertions(+), 169 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 9554a39..0f40199 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -501,6 +501,9 @@ struct ovnact_encode_params { /* A struct to figure out the meter_id for meter actions. */ struct ovn_extend_table *meter_table; + /* The logical flow uuid that drove this action. */ + struct uuid lflow_uuid; + /* OVN maps each logical flow table (ltable), one-to-one, onto a physical * OpenFlow flow table (ptable). A number of parameters describe this * mapping and data related to flow tables: diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c index df125b1..3d465a5 100644 --- a/ovn/controller/lflow.c +++ b/ovn/controller/lflow.c @@ -70,7 +70,6 @@ static void consider_logical_flow(struct controller_ctx *ctx, struct hmap *nd_ra_opts, uint32_t *conj_id_ofs, const struct shash *addr_sets, - struct hmap *flow_table, struct sset *active_tunnels, struct sset *local_lport_ids); @@ -149,7 +148,6 @@ add_logical_flows(struct controller_ctx *ctx, struct ovn_extend_table *meter_table, const struct sbrec_chassis *chassis, const struct shash *addr_sets, - struct hmap *flow_table, struct sset *active_tunnels, struct sset *local_lport_ids) { @@ -179,7 +177,7 @@ add_logical_flows(struct controller_ctx *ctx, lflow, local_datapaths, group_table, meter_table, chassis, &dhcp_opts, &dhcpv6_opts, &nd_ra_opts, - &conj_id_ofs, addr_sets, flow_table, + &conj_id_ofs, addr_sets, active_tunnels, local_lport_ids); } @@ -188,6 +186,69 @@ add_logical_flows(struct controller_ctx *ctx, nd_ra_opts_destroy(&nd_ra_opts); } +void +lflow_handle_changed_flows(struct controller_ctx *ctx, + const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + const struct hmap *local_datapaths, + struct ovn_extend_table *group_table, + struct ovn_extend_table *meter_table, + const struct shash *addr_sets, + struct sset *active_tunnels, + struct sset *local_lport_ids) +{ + // TODO: how to set conj_id_ofs in incremental processing? + uint32_t conj_id_ofs = 1; + const struct sbrec_logical_flow *lflow; + + struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts); + struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts); + const struct sbrec_dhcp_options *dhcp_opt_row; + SBREC_DHCP_OPTIONS_FOR_EACH(dhcp_opt_row, ctx->ovnsb_idl) { + dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code, + dhcp_opt_row->type); + } + + + const struct sbrec_dhcpv6_options *dhcpv6_opt_row; + SBREC_DHCPV6_OPTIONS_FOR_EACH(dhcpv6_opt_row, ctx->ovnsb_idl) { + dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name, dhcpv6_opt_row->code, + dhcpv6_opt_row->type); + } + + struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts); + nd_ra_opts_init(&nd_ra_opts); + + SBREC_LOGICAL_FLOW_FOR_EACH_TRACKED (lflow, ctx->ovnsb_idl) { + /* Remove any flows that should be removed. */ + if (sbrec_logical_flow_is_deleted(lflow)) { + VLOG_DBG("handle deleted lflow "UUID_FMT, + UUID_ARGS(&lflow->header_.uuid)); + ofctrl_remove_flows(&lflow->header_.uuid); + } else { + /* Now, add/modify existing flows. If the logical + * flow is a modification, just remove the flows + * for this row, and then add new flows. */ + if (!sbrec_logical_flow_is_new(lflow)) { + VLOG_DBG("handle updated lflow "UUID_FMT, + UUID_ARGS(&lflow->header_.uuid)); + ofctrl_remove_flows(&lflow->header_.uuid); + } + VLOG_DBG("handle new lflow "UUID_FMT, + UUID_ARGS(&lflow->header_.uuid)); + consider_logical_flow(ctx, chassis_index, + lflow, local_datapaths, + group_table, meter_table, chassis, + &dhcp_opts, &dhcpv6_opts, &nd_ra_opts, + &conj_id_ofs, addr_sets, + active_tunnels, local_lport_ids); + } + } + dhcp_opts_destroy(&dhcp_opts); + dhcp_opts_destroy(&dhcpv6_opts); + nd_ra_opts_destroy(&nd_ra_opts); +} + static void consider_logical_flow(struct controller_ctx *ctx, const struct chassis_index *chassis_index, @@ -201,7 +262,6 @@ consider_logical_flow(struct controller_ctx *ctx, struct hmap *nd_ra_opts, uint32_t *conj_id_ofs, const struct shash *addr_sets, - struct hmap *flow_table, struct sset *active_tunnels, struct sset *local_lport_ids) { @@ -210,9 +270,13 @@ consider_logical_flow(struct controller_ctx *ctx, const struct sbrec_datapath_binding *ldp = lflow->logical_datapath; if (!ldp) { + VLOG_DBG("lflow "UUID_FMT" has no datapath binding, skip", + UUID_ARGS(&lflow->header_.uuid)); return; } if (!get_local_datapath(local_datapaths, ldp->tunnel_key)) { + VLOG_DBG("lflow "UUID_FMT" is not for local datapath, skip", + UUID_ARGS(&lflow->header_.uuid)); return; } @@ -290,6 +354,8 @@ consider_logical_flow(struct controller_ctx *ctx, expr_destroy(expr); if (hmap_is_empty(&matches)) { + VLOG_DBG("lflow "UUID_FMT" matches are empty, skip", + UUID_ARGS(&lflow->header_.uuid)); ovnacts_free(ovnacts.data, ovnacts.size); ofpbuf_uninit(&ovnacts); expr_matches_destroy(&matches); @@ -306,6 +372,7 @@ consider_logical_flow(struct controller_ctx *ctx, .is_gateway_router = is_gateway_router(ldp, local_datapaths), .group_table = group_table, .meter_table = meter_table, + .lflow_uuid = lflow->header_.uuid, .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS, .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE, @@ -334,13 +401,18 @@ consider_logical_flow(struct controller_ctx *ctx, char buf[16]; snprintf(buf, sizeof(buf), "%"PRId64"_%"PRId64, dp_id, port_id); if (!sset_contains(local_lport_ids, buf)) { + VLOG_DBG("lflow "UUID_FMT + " port %s in match is not local, skip", + UUID_ARGS(&lflow->header_.uuid), + buf); continue; } } } if (!m->n) { - ofctrl_add_flow(flow_table, ptable, lflow->priority, - lflow->header_.uuid.parts[0], &m->match, &ofpacts); + ofctrl_add_flow(ptable, lflow->priority, + lflow->header_.uuid.parts[0], &m->match, &ofpacts, + &lflow->header_.uuid); } else { uint64_t conj_stubs[64 / 8]; struct ofpbuf conj; @@ -355,8 +427,8 @@ consider_logical_flow(struct controller_ctx *ctx, dst->clause = src->clause; dst->n_clauses = src->n_clauses; } - ofctrl_add_flow(flow_table, ptable, lflow->priority, 0, &m->match, - &conj); + ofctrl_add_flow(ptable, lflow->priority, 0, &m->match, + &conj, &lflow->header_.uuid); ofpbuf_uninit(&conj); } } @@ -381,8 +453,7 @@ put_load(const uint8_t *data, size_t len, static void consider_neighbor_flow(struct controller_ctx *ctx, - const struct sbrec_mac_binding *b, - struct hmap *flow_table) + const struct sbrec_mac_binding *b) { const struct sbrec_port_binding *pb = lport_lookup_by_name(ctx->ovnsb_idl, b->logical_port); @@ -424,19 +495,19 @@ consider_neighbor_flow(struct controller_ctx *ctx, uint64_t stub[1024 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub); put_load(mac.ea, sizeof mac.ea, MFF_ETH_DST, 0, 48, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100, 0, &match, &ofpacts); + ofctrl_add_flow(OFTABLE_MAC_BINDING, 100, 0, &match, &ofpacts, + &b->header_.uuid); ofpbuf_uninit(&ofpacts); } /* Adds an OpenFlow flow to flow tables for each MAC binding in the OVN * southbound database. */ static void -add_neighbor_flows(struct controller_ctx *ctx, - struct hmap *flow_table) +add_neighbor_flows(struct controller_ctx *ctx) { const struct sbrec_mac_binding *b; SBREC_MAC_BINDING_FOR_EACH (b, ctx->ovnsb_idl) { - consider_neighbor_flow(ctx, b, flow_table); + consider_neighbor_flow(ctx, b); } } @@ -450,14 +521,13 @@ lflow_run(struct controller_ctx *ctx, struct ovn_extend_table *group_table, struct ovn_extend_table *meter_table, const struct shash *addr_sets, - struct hmap *flow_table, struct sset *active_tunnels, struct sset *local_lport_ids) { add_logical_flows(ctx, chassis_index, local_datapaths, - group_table, meter_table, chassis, addr_sets, flow_table, + group_table, meter_table, chassis, addr_sets, active_tunnels, local_lport_ids); - add_neighbor_flows(ctx, flow_table); + add_neighbor_flows(ctx); } void diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h index 22bf534..ef4ed0e 100644 --- a/ovn/controller/lflow.h +++ b/ovn/controller/lflow.h @@ -69,9 +69,17 @@ void lflow_run(struct controller_ctx *, struct ovn_extend_table *group_table, struct ovn_extend_table *meter_table, const struct shash *addr_sets, - struct hmap *flow_table, struct sset *active_tunnels, struct sset *local_lport_ids); +void lflow_handle_changed_flows(struct controller_ctx *ctx, + const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + const struct hmap *local_datapaths, + struct ovn_extend_table *group_table, + struct ovn_extend_table *extend_table, + const struct shash *addr_sets, + struct sset *active_tunnels, + struct sset *local_lport_ids); void lflow_destroy(void); #endif /* ovn/lflow.h */ diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index e6b25af..723f9a7 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -20,6 +20,7 @@ #include "dp-packet.h" #include "flow.h" #include "hash.h" +#include "hindex.h" #include "lflow.h" #include "ofctrl.h" #include "openflow/openflow.h" @@ -52,7 +53,8 @@ VLOG_DEFINE_THIS_MODULE(ofctrl); /* An OpenFlow flow. */ struct ovn_flow { - struct hmap_node hmap_node; /* For match based hashing. */ + struct hmap_node match_hmap_node; /* For match based hashing. */ + struct hindex_node uuid_hindex_node; /* For uuid based hashing. */ struct ovs_list list_node; /* For handling lists of flows. */ /* Key. */ @@ -61,12 +63,13 @@ struct ovn_flow { struct match match; /* Data. */ + struct uuid sb_uuid; struct ofpact *ofpacts; size_t ofpacts_len; uint64_t cookie; }; -static uint32_t ovn_flow_hash(const struct ovn_flow *); +static uint32_t ovn_flow_match_hash(const struct ovn_flow *); static struct ovn_flow *ovn_flow_lookup(struct hmap *flow_table, const struct ovn_flow *target); static char *ovn_flow_to_string(const struct ovn_flow *); @@ -154,11 +157,16 @@ static struct ofpbuf *encode_group_mod(const struct ofputil_group_mod *); static struct ofpbuf *encode_meter_mod(const struct ofputil_meter_mod *); -static void ovn_flow_table_clear(struct hmap *flow_table); -static void ovn_flow_table_destroy(struct hmap *flow_table); +static void ovn_desired_flow_table_clear(void); +static void ovn_installed_flow_table_clear(void); +static void ovn_desired_flow_table_destroy(void); +static void ovn_installed_flow_table_destroy(void); static void ofctrl_recv(const struct ofp_header *, enum ofptype); +static struct hmap match_flow_table = HMAP_INITIALIZER(&match_flow_table); +static struct hindex uuid_flow_table = HINDEX_INITIALIZER(&uuid_flow_table); + void ofctrl_init(struct ovn_extend_table *group_table, struct ovn_extend_table *meter_table) @@ -382,9 +390,6 @@ run_S_CLEAR_FLOWS(void) queue_msg(encode_flow_mod(&fm)); VLOG_DBG("clearing all flows"); - /* Clear installed_flows, to match the state of the switch. */ - ovn_flow_table_clear(&installed_flows); - /* Send a group_mod to delete all groups. */ struct ofputil_group_mod gm; memset(&gm, 0, sizeof gm); @@ -395,6 +400,9 @@ run_S_CLEAR_FLOWS(void) queue_msg(encode_group_mod(&gm)); ofputil_uninit_group_mod(&gm); + /* Clear installed_flows, to match the state of the switch. */ + ovn_installed_flow_table_clear(); + /* Clear existing groups, to match the state of the switch. */ if (groups) { ovn_extend_table_clear(groups, true); @@ -578,7 +586,8 @@ void ofctrl_destroy(void) { rconn_destroy(swconn); - ovn_flow_table_destroy(&installed_flows); + ovn_desired_flow_table_destroy(); + ovn_installed_flow_table_destroy(); rconn_packet_counter_destroy(tx_counter); expr_symtab_destroy(&symtab); shash_destroy(&symtab); @@ -630,15 +639,17 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) * the OpenFlow table numbered 'table_id' with the given 'priority' and * OpenFlow 'cookie'. The caller retains ownership of 'match' and 'actions'. * + * The flow is also added to a hash index based on sb_uuid. + * * This just assembles the desired flow table in memory. Nothing is actually * sent to the switch until a later call to ofctrl_put(). * * The caller should initialize its own hmap to hold the flows. */ void -ofctrl_add_flow(struct hmap *desired_flows, - uint8_t table_id, uint16_t priority, uint64_t cookie, +ofctrl_add_flow(uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *match, - const struct ofpbuf *actions) + const struct ofpbuf *actions, + const struct uuid *sb_uuid) { struct ovn_flow *f = xmalloc(sizeof *f); f->table_id = table_id; @@ -646,10 +657,14 @@ ofctrl_add_flow(struct hmap *desired_flows, f->match = *match; f->ofpacts = xmemdup(actions->data, actions->size); f->ofpacts_len = actions->size; - f->hmap_node.hash = ovn_flow_hash(f); + f->sb_uuid = *sb_uuid; + f->match_hmap_node.hash = ovn_flow_match_hash(f); + f->uuid_hindex_node.hash = uuid_hash(&f->sb_uuid); f->cookie = cookie; - if (ovn_flow_lookup(desired_flows, f)) { + ovn_flow_log(f, "ofctrl_add_flow"); + + if (ovn_flow_lookup(&match_flow_table, f)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); if (!VLOG_DROP_DBG(&rl)) { char *s = ovn_flow_to_string(f); @@ -661,19 +676,65 @@ ofctrl_add_flow(struct hmap *desired_flows, return; } - hmap_insert(desired_flows, &f->hmap_node, f->hmap_node.hash); + hmap_insert(&match_flow_table, &f->match_hmap_node, + f->match_hmap_node.hash); + hindex_insert(&uuid_flow_table, &f->uuid_hindex_node, + f->uuid_hindex_node.hash); +} + +void +ofctrl_flow_table_clear(void) +{ + ovn_desired_flow_table_clear(); +} + +/* Removes a bundles of flows from the flow table. */ +void +ofctrl_remove_flows(const struct uuid *sb_uuid) +{ + struct ovn_flow *f, *next; + HINDEX_FOR_EACH_WITH_HASH_SAFE (f, next, uuid_hindex_node, + uuid_hash(sb_uuid), + &uuid_flow_table) { + if (uuid_equals(&f->sb_uuid, sb_uuid)) { + ovn_flow_log(f, "ofctrl_remove_flow"); + hmap_remove(&match_flow_table, &f->match_hmap_node); + hindex_remove(&uuid_flow_table, &f->uuid_hindex_node); + ovn_flow_destroy(f); + } + } + + // TODO: refactor to a function + /* Remove any group information created by this logical flow. */ + struct ovn_extend_table_info *g, *next_g; + HMAP_FOR_EACH_SAFE (g, next_g, hmap_node, &groups->desired) { + if (uuid_equals(&g->lflow_uuid, sb_uuid)) { + hmap_remove(&groups->desired, &g->hmap_node); + ds_destroy(&g->info); + free(g); + } + } + + /* Remove any meter information created by this logical flow. */ + struct ovn_extend_table_info *m, *next_m; + HMAP_FOR_EACH_SAFE (m, next_m, hmap_node, &meters->desired) { + if (uuid_equals(&m->lflow_uuid, sb_uuid)) { + hmap_remove(&meters->desired, &m->hmap_node); + ds_destroy(&m->info); + free(m); + } + } } /* ovn_flow. */ -/* Returns a hash of the key in 'f'. */ +/* Returns a hash of the match key in 'f'. */ static uint32_t -ovn_flow_hash(const struct ovn_flow *f) +ovn_flow_match_hash(const struct ovn_flow *f) { return hash_2words((f->table_id << 16) | f->priority, match_hash(&f->match, 0)); - } /* Duplicate an ovn_flow structure. */ @@ -686,7 +747,9 @@ ofctrl_dup_flow(struct ovn_flow *src) dst->match = src->match; dst->ofpacts = xmemdup(src->ofpacts, src->ofpacts_len); dst->ofpacts_len = src->ofpacts_len; - dst->hmap_node.hash = ovn_flow_hash(dst); + dst->sb_uuid = src->sb_uuid; + dst->match_hmap_node.hash = ovn_flow_match_hash(dst); + dst->uuid_hindex_node.hash = uuid_hash(&src->sb_uuid); return dst; } @@ -697,7 +760,7 @@ ovn_flow_lookup(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, + HMAP_FOR_EACH_WITH_HASH (f, match_hmap_node, target->match_hmap_node.hash, flow_table) { if (f->table_id == target->table_id && f->priority == target->priority @@ -712,6 +775,7 @@ static char * ovn_flow_to_string(const struct ovn_flow *f) { struct ds s = DS_EMPTY_INITIALIZER; + ds_put_format(&s, "sb_uuid="UUID_FMT", ", UUID_ARGS(&f->sb_uuid)); ds_put_format(&s, "table_id=%"PRIu8", ", f->table_id); ds_put_format(&s, "priority=%"PRIu16", ", f->priority); match_format(&f->match, NULL, &s, OFP_DEFAULT_PRIORITY); @@ -743,20 +807,39 @@ ovn_flow_destroy(struct ovn_flow *f) /* Flow tables of struct ovn_flow. */ static void -ovn_flow_table_clear(struct hmap *flow_table) +ovn_desired_flow_table_clear(void) { struct ovn_flow *f, *next; - HMAP_FOR_EACH_SAFE (f, next, hmap_node, flow_table) { - hmap_remove(flow_table, &f->hmap_node); + HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, &match_flow_table) { + hmap_remove(&match_flow_table, &f->match_hmap_node); + hindex_remove(&uuid_flow_table, &f->uuid_hindex_node); ovn_flow_destroy(f); } } static void -ovn_flow_table_destroy(struct hmap *flow_table) +ovn_desired_flow_table_destroy(void) { - ovn_flow_table_clear(flow_table); - hmap_destroy(flow_table); + ovn_desired_flow_table_clear(); + hmap_destroy(&match_flow_table); + hindex_destroy(&uuid_flow_table); +} + +static void +ovn_installed_flow_table_clear(void) +{ + struct ovn_flow *f, *next; + HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, &installed_flows) { + hmap_remove(&installed_flows, &f->match_hmap_node); + ovn_flow_destroy(f); + } +} + +static void +ovn_installed_flow_table_destroy(void) +{ + ovn_installed_flow_table_clear(); + hmap_destroy(&installed_flows); } /* Flow table update. */ @@ -836,9 +919,7 @@ ofctrl_can_put(void) * with ofctrl_add_flow(). * * Replaces the group table and meter table on the switch, if possible, by the - * contents of 'groups->desired'. Regardless of whether the group table - * is updated, this deletes all the groups from the 'groups->desired' and frees - * them. (The hmap itself isn't destroyed.) + * contents of 'desired'. * * Sends conntrack flush messages to each zone in 'pending_ct_zones' that * is in the CT_ZONE_OF_QUEUED state and then moves the zone into the @@ -846,16 +927,14 @@ ofctrl_can_put(void) * * This should be called after ofctrl_run() within the main loop. */ void -ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, +ofctrl_put(struct shash *pending_ct_zones, int64_t nb_cfg) { if (!ofctrl_can_put()) { - ovn_flow_table_clear(flow_table); - ovn_extend_table_clear(groups, false); - ovn_extend_table_clear(meters, false); return; } + VLOG_DBG("ofctrl can put"); /* OpenFlow messages to send to the switch to bring it up-to-date. */ struct ovs_list msgs = OVS_LIST_INITIALIZER(&msgs); @@ -919,8 +998,8 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, * longer desired, delete them; if any of them should have different * actions, update them. */ struct ovn_flow *i, *next; - HMAP_FOR_EACH_SAFE (i, next, hmap_node, &installed_flows) { - struct ovn_flow *d = ovn_flow_lookup(flow_table, i); + HMAP_FOR_EACH_SAFE (i, next, match_hmap_node, &installed_flows) { + struct ovn_flow *d = ovn_flow_lookup(&match_flow_table, i); if (!d) { /* Installed flow is no longer desirable. Delete it from the * switch and from installed_flows. */ @@ -933,9 +1012,13 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, add_flow_mod(&fm, &msgs); ovn_flow_log(i, "removing installed"); - hmap_remove(&installed_flows, &i->hmap_node); + hmap_remove(&installed_flows, &i->match_hmap_node); ovn_flow_destroy(i); } else { + if (!uuid_equals(&i->sb_uuid, &d->sb_uuid)) { + /* Update installed flow's UUID. */ + i->sb_uuid = d->sb_uuid; + } if (!ofpacts_equal(i->ofpacts, i->ofpacts_len, d->ofpacts, d->ofpacts_len)) { /* Update actions in installed flow. */ @@ -952,38 +1035,36 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, /* Replace 'i''s actions by 'd''s. */ free(i->ofpacts); - i->ofpacts = d->ofpacts; + i->ofpacts = xmemdup(d->ofpacts, d->ofpacts_len); i->ofpacts_len = d->ofpacts_len; - d->ofpacts = NULL; - d->ofpacts_len = 0; } - hmap_remove(flow_table, &d->hmap_node); - ovn_flow_destroy(d); } } - /* 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. */ + /* Iterate through the desired flows and add those that aren't found + * 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, - .new_cookie = htonll(d->cookie), - .command = OFPFC_ADD, - }; - add_flow_mod(&fm, &msgs); - ovn_flow_log(d, "adding installed"); - - /* 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); + HMAP_FOR_EACH (d, match_hmap_node, &match_flow_table) { + 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, + }; + add_flow_mod(&fm, &msgs); + ovn_flow_log(d, "adding installed"); + + /* Copy 'd' from 'flow_table' to installed_flows. */ + struct ovn_flow *new_node = ofctrl_dup_flow(d); + hmap_insert(&installed_flows, &new_node->match_hmap_node, + new_node->match_hmap_node.hash); + } } /* Iterate through the installed groups from previous runs. If they @@ -1012,7 +1093,7 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, } /* Move the contents of groups->desired to groups->existing. */ - ovn_extend_table_move(groups); + ovn_extend_table_sync(groups); /* Iterate through the installed meters from previous runs. If they * are not needed delete them. */ @@ -1039,7 +1120,7 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, } /* Move the contents of meters->desired to meters->existing. */ - ovn_extend_table_move(meters); + ovn_extend_table_sync(meters); if (!ovs_list_is_empty(&msgs)) { /* Add a barrier to the list of messages. */ diff --git a/ovn/controller/ofctrl.h b/ovn/controller/ofctrl.h index e25f7d1..3ba5e61 100644 --- a/ovn/controller/ofctrl.h +++ b/ovn/controller/ofctrl.h @@ -37,7 +37,7 @@ void ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones); enum mf_field_id ofctrl_get_mf_field_id(void); bool ofctrl_can_put(void); -void ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, +void ofctrl_put(struct shash *pending_ct_zones, int64_t nb_cfg); void ofctrl_wait(void); void ofctrl_destroy(void); @@ -51,8 +51,13 @@ char *ofctrl_inject_pkt(const struct ovsrec_bridge *br_int, const char *flow_s, const struct shash *addr_sets); /* Flow table interfaces to the rest of ovn-controller. */ -void ofctrl_add_flow(struct hmap *desired_flows, uint8_t table_id, +void ofctrl_add_flow(uint8_t table_id, uint16_t priority, uint64_t cookie, - const struct match *, const struct ofpbuf *ofpacts); + const struct match *, const struct ofpbuf *ofpacts, + const struct uuid *lflow_uuid); + +void ofctrl_remove_flows(const struct uuid *lflow_uuid); + +void ofctrl_flow_table_clear(void); #endif /* ovn/ofctrl.h */ diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 38432ac..8a7d2c6 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -659,7 +659,6 @@ runtime_data_run(struct engine_node *node) } struct ed_type_flow_output { - struct hmap *flow_table; struct ovn_extend_table *group_table; struct ovn_extend_table *meter_table; }; @@ -688,26 +687,23 @@ flow_output_run(struct engine_node *node) ovs_assert(br_int && chassis); - struct hmap *flow_table = - ((struct ed_type_flow_output *)node->data)->flow_table; - struct ovn_extend_table *group_table = - ((struct ed_type_flow_output *)node->data)->group_table; - struct ovn_extend_table *meter_table = - ((struct ed_type_flow_output *)node->data)->meter_table; - if (ctx->ovs_idl_txn) { static bool first_run = true; if (first_run) { first_run = false; } else { - hmap_clear(flow_table); + ofctrl_flow_table_clear(); } + struct ovn_extend_table *group_table = + ((struct ed_type_flow_output *)node->data)->group_table; + struct ovn_extend_table *meter_table = + ((struct ed_type_flow_output *)node->data)->meter_table; /* requires ctx->ovs_idl_txn */ commit_ct_zones(br_int, ctx->pending_ct_zones); lflow_run(ctx, chassis, chassis_index, local_datapaths, group_table, - meter_table, addr_sets, flow_table, active_tunnels, + meter_table, addr_sets, active_tunnels, local_lport_ids); bfd_run(ctx, br_int, chassis, local_datapaths, @@ -716,12 +712,49 @@ flow_output_run(struct engine_node *node) physical_run(ctx, mff_ovn_geneve, br_int, chassis, ctx->ct_zones, - flow_table, local_datapaths, local_lports, + local_datapaths, local_lports, chassis_index, active_tunnels); } node->changed = true; } +static bool +flow_output_sb_logical_flow_handler(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)engine_get_input( + "runtime_data", node)->data; + struct hmap *local_datapaths = data->local_datapaths; + struct sset *local_lport_ids = data->local_lport_ids; + struct sset *active_tunnels = data->active_tunnels; + struct chassis_index *chassis_index = data->chassis_index; + struct shash *addr_sets = data->addr_sets; + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + + + const struct sbrec_chassis *chassis = NULL; + if (chassis_id) { + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + } + + ovs_assert(br_int && chassis); + + // TODO: move group_table from node data to ofctrl module data + struct ovn_extend_table *group_table = + ((struct ed_type_flow_output *)node->data)->group_table; + struct ovn_extend_table *meter_table = + ((struct ed_type_flow_output *)node->data)->meter_table; + lflow_handle_changed_flows(ctx, chassis, + chassis_index, local_datapaths, group_table, meter_table, + addr_sets, active_tunnels, local_lport_ids); + + node->changed = true; + return true; +} + int main(int argc, char *argv[]) { @@ -822,10 +855,7 @@ main(int argc, char *argv[]) .addr_sets = &addr_sets }; - struct hmap flow_table = HMAP_INITIALIZER(&flow_table); - struct ed_type_flow_output ed_flow_output = { - .flow_table = &flow_table, .group_table = &group_table, .meter_table = &meter_table }; @@ -858,7 +888,7 @@ main(int argc, char *argv[]) engine_add_input(&en_flow_output, &en_sb_datapath_binding, NULL); engine_add_input(&en_flow_output, &en_sb_port_binding, NULL); engine_add_input(&en_flow_output, &en_sb_mac_binding, NULL); - engine_add_input(&en_flow_output, &en_sb_logical_flow, NULL); + engine_add_input(&en_flow_output, &en_sb_logical_flow, flow_output_sb_logical_flow_handler); engine_add_input(&en_flow_output, &en_sb_dhcp_options, NULL); engine_add_input(&en_flow_output, &en_sb_dhcpv6_options, NULL); engine_add_input(&en_flow_output, &en_sb_dns, NULL); @@ -875,6 +905,8 @@ main(int argc, char *argv[]) uint64_t engine_run_id = 0; uint64_t old_engine_run_id = 0; + bool ofctrl_put_skipped = false; + /* Main loop. */ exiting = false; while (!exiting) { @@ -911,13 +943,16 @@ main(int argc, char *argv[]) patch_run(&ctx, br_int, chassis); encaps_run(&ctx, br_int, chassis_id); - if (ofctrl_can_put()) { - engine_run(&en_flow_output, ++engine_run_id); - if (en_flow_output.changed) { - ofctrl_put(&flow_table, &pending_ct_zones, - get_nb_cfg(ctx.ovnsb_idl)); - } + engine_run(&en_flow_output, ++engine_run_id); + if (en_flow_output.changed || ofctrl_put_skipped) { + VLOG_DBG("before ofctrl_put: skipped = %s", + ofctrl_put_skipped ? "true" : "false"); + ofctrl_put(&pending_ct_zones, + get_nb_cfg(ctx.ovnsb_idl)); } + ofctrl_put_skipped = !ofctrl_can_put(); + VLOG_DBG("after ofctrl_put: skipped = %s", + ofctrl_put_skipped ? "true" : "false"); pinctrl_run(&ctx, br_int, chassis, &chassis_index, &local_datapaths, &active_tunnels); @@ -1012,8 +1047,6 @@ main(int argc, char *argv[]) } hmap_destroy(&local_datapaths); - hmap_destroy(&flow_table); - /* It's time to exit. Clean up the databases. */ bool done = false; while (!done) { diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index aa6f973..41ea9fe 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -44,6 +44,9 @@ VLOG_DEFINE_THIS_MODULE(physical); +/* UUID to identify OF flows not associated with ovsdb rows. */ +static struct uuid *hc_uuid = NULL; + void physical_register_ovs_idl(struct ovsdb_idl *ovs_idl) { @@ -190,7 +193,7 @@ get_zone_ids(const struct sbrec_port_binding *binding, static void put_local_common_flows(uint32_t dp_key, uint32_t port_key, bool nested_container, const struct zone_ids *zone_ids, - struct ofpbuf *ofpacts_p, struct hmap *flow_table) + struct ofpbuf *ofpacts_p) { struct match match; @@ -223,8 +226,8 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, /* Resubmit to table 34. */ put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); - ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100, 0, + &match, ofpacts_p, hc_uuid); /* Table 34, Priority 100. * ======================= @@ -238,8 +241,8 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, 0, MLF_ALLOW_LOOPBACK); match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, port_key); match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key); - ofctrl_add_flow(flow_table, OFTABLE_CHECK_LOOPBACK, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_CHECK_LOOPBACK, 100, 0, + &match, ofpacts_p, hc_uuid); /* Table 64, Priority 100. * ======================= @@ -262,8 +265,8 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, put_load(0, MFF_IN_PORT, 0, 16, ofpacts_p); put_resubmit(OFTABLE_LOG_TO_PHY, ofpacts_p); put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p)); - ofctrl_add_flow(flow_table, OFTABLE_SAVE_INPORT, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_SAVE_INPORT, 100, 0, + &match, ofpacts_p, hc_uuid); } static void @@ -299,8 +302,7 @@ consider_port_binding(struct controller_ctx *ctx, struct hmap *local_datapaths, const struct sbrec_port_binding *binding, const struct sbrec_chassis *chassis, - struct ofpbuf *ofpacts_p, - struct hmap *flow_table) + struct ofpbuf *ofpacts_p) { uint32_t dp_key = binding->datapath->tunnel_key; uint32_t port_key = binding->tunnel_key; @@ -329,7 +331,7 @@ consider_port_binding(struct controller_ctx *ctx, struct zone_ids binding_zones = get_zone_ids(binding, ct_zones); put_local_common_flows(dp_key, port_key, false, &binding_zones, - ofpacts_p, flow_table); + ofpacts_p); match_init_catchall(&match); ofpbuf_clear(ofpacts_p); @@ -355,8 +357,8 @@ consider_port_binding(struct controller_ctx *ctx, ofpacts_p->header = clone; ofpact_finish_CLONE(ofpacts_p, &clone); - ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_LOG_TO_PHY, 100, 0, + &match, ofpacts_p, hc_uuid); return; } @@ -423,8 +425,8 @@ consider_port_binding(struct controller_ctx *ctx, put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); } - ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100, 0, + &match, ofpacts_p, hc_uuid); goto out; } @@ -512,7 +514,7 @@ consider_port_binding(struct controller_ctx *ctx, struct zone_ids zone_ids = get_zone_ids(binding, ct_zones); put_local_common_flows(dp_key, port_key, nested_container, &zone_ids, - ofpacts_p, flow_table); + ofpacts_p); /* Table 0, Priority 150 and 100. * ============================== @@ -555,8 +557,8 @@ consider_port_binding(struct controller_ctx *ctx, /* Resubmit to first logical ingress pipeline table. */ put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p); - ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, - tag ? 150 : 100, 0, &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_PHY_TO_LOG, + tag ? 150 : 100, 0, &match, ofpacts_p, hc_uuid); if (!tag && (!strcmp(binding->type, "localnet") || !strcmp(binding->type, "l2gateway"))) { @@ -566,7 +568,7 @@ consider_port_binding(struct controller_ctx *ctx, * action. */ ofpbuf_pull(ofpacts_p, ofpacts_orig_size); match_set_dl_tci_masked(&match, 0, htons(VLAN_CFI)); - ofctrl_add_flow(flow_table, 0, 100, 0, &match, ofpacts_p); + ofctrl_add_flow(0, 100, 0, &match, ofpacts_p, hc_uuid); } /* Table 65, Priority 100. @@ -593,8 +595,8 @@ consider_port_binding(struct controller_ctx *ctx, * switch will also contain the tag. */ ofpact_put_STRIP_VLAN(ofpacts_p); } - ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_LOG_TO_PHY, 100, 0, + &match, ofpacts_p, hc_uuid); } else if (!tun && !is_ha_remote) { /* Remote port connected by localnet port */ /* Table 33, priority 100. @@ -616,8 +618,8 @@ consider_port_binding(struct controller_ctx *ctx, /* Resubmit to table 33. */ put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p); - ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100, 0, + &match, ofpacts_p, hc_uuid); } else { /* Remote port connected by tunnel */ @@ -707,8 +709,8 @@ consider_port_binding(struct controller_ctx *ctx, bundle->fields = NX_HASH_FIELDS_ETH_SRC; ofpact_finish_BUNDLE(ofpacts_p, &bundle); } - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 100, 0, + &match, ofpacts_p, hc_uuid); } out: if (gateway_chassis) { @@ -723,8 +725,7 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve, const struct sbrec_chassis *chassis, const struct sbrec_multicast_group *mc, struct ofpbuf *ofpacts_p, - struct ofpbuf *remote_ofpacts_p, - struct hmap *flow_table) + struct ofpbuf *remote_ofpacts_p) { uint32_t dp_key = mc->datapath->tunnel_key; if (!get_local_datapath(local_datapaths, dp_key)) { @@ -799,8 +800,8 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve, * group as the logical output port. */ put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p); - ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p); + ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100, 0, + &match, ofpacts_p, hc_uuid); } /* Table 32, priority 100. @@ -837,8 +838,8 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve, if (local_ports) { put_resubmit(OFTABLE_LOCAL_OUTPUT, remote_ofpacts_p); } - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100, 0, - &match, remote_ofpacts_p); + ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 100, 0, + &match, remote_ofpacts_p, hc_uuid); } } sset_destroy(&remote_chassis); @@ -860,12 +861,17 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct simap *ct_zones, - struct hmap *flow_table, struct hmap *local_datapaths, + struct hmap *local_datapaths, const struct sset *local_lports, struct chassis_index *chassis_index, struct sset *active_tunnels) { + if (!hc_uuid) { + hc_uuid = xmalloc(sizeof(struct uuid)); + uuid_generate(hc_uuid); + } + /* This bool tracks physical mapping changes. */ bool physical_map_changed = false; @@ -987,7 +993,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, consider_port_binding(ctx, mff_ovn_geneve, ct_zones, chassis_index, active_tunnels, local_datapaths, binding, chassis, - &ofpacts, flow_table); + &ofpacts); } /* Handle output to multicast groups, in tables 32 and 33. */ @@ -1007,11 +1013,11 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, MLF_LOCAL_ONLY, MLF_LOCAL_ONLY); ofpbuf_clear(&ofpacts); put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, &match, - &ofpacts); + ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 150, 0, &match, + &ofpacts, hc_uuid); consider_mc_group(mff_ovn_geneve, ct_zones, local_datapaths, chassis, - mc, &ofpacts, &remote_ofpacts, flow_table); + mc, &ofpacts, &remote_ofpacts); } ofpbuf_uninit(&remote_ofpacts); @@ -1051,8 +1057,8 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, 0, &match, - &ofpacts); + ofctrl_add_flow(OFTABLE_PHY_TO_LOG, 100, 0, &match, + &ofpacts, hc_uuid); } /* Add flows for VXLAN encapsulations. Due to the limited amount of @@ -1084,8 +1090,8 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, put_load(1, MFF_LOG_FLAGS, MLF_RCV_FROM_VXLAN_BIT, 1, &ofpacts); put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, 0, &match, - &ofpacts); + ofctrl_add_flow(OFTABLE_PHY_TO_LOG, 100, 0, &match, + &ofpacts, hc_uuid); } } @@ -1105,8 +1111,8 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, /* Resubmit to table 33. */ ofpbuf_clear(&ofpacts); put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, - &match, &ofpacts); + ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 150, 0, + &match, &ofpacts, hc_uuid); /* Table 32, priority 150. * ======================= @@ -1128,8 +1134,8 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, if (pb && !strcmp(pb->type, "localport")) { match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, pb->tunnel_key); match_set_metadata(&match, htonll(pb->datapath->tunnel_key)); - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, - &match, &ofpacts); + ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 150, 0, + &match, &ofpacts, hc_uuid); } } @@ -1141,7 +1147,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, match_init_catchall(&match); ofpbuf_clear(&ofpacts); put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 0, 0, &match, &ofpacts); + ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 0, 0, &match, &ofpacts, hc_uuid); /* Table 34, Priority 0. * ======================= @@ -1155,8 +1161,8 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, put_load(0, MFF_REG0 + i, 0, 32, &ofpacts); } put_resubmit(OFTABLE_LOG_EGRESS_PIPELINE, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_CHECK_LOOPBACK, 0, 0, &match, - &ofpacts); + ofctrl_add_flow(OFTABLE_CHECK_LOOPBACK, 0, 0, &match, + &ofpacts, hc_uuid); /* Table 64, Priority 0. * ======================= @@ -1166,7 +1172,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, match_init_catchall(&match); ofpbuf_clear(&ofpacts); put_resubmit(OFTABLE_LOG_TO_PHY, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_SAVE_INPORT, 0, 0, &match, &ofpacts); + ofctrl_add_flow(OFTABLE_SAVE_INPORT, 0, 0, &match, &ofpacts, hc_uuid); ofpbuf_uninit(&ofpacts); diff --git a/ovn/controller/physical.h b/ovn/controller/physical.h index f8dbb49..4aeec04 100644 --- a/ovn/controller/physical.h +++ b/ovn/controller/physical.h @@ -47,7 +47,7 @@ void physical_run(struct controller_ctx *, enum mf_field_id mff_ovn_geneve, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct simap *ct_zones, - struct hmap *flow_table, struct hmap *local_datapaths, + struct hmap *local_datapaths, const struct sset *local_lports, struct chassis_index *chassis_index, struct sset *active_tunnels); diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c index fde3bff..fb13ed5 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -1059,7 +1059,8 @@ encode_CT_LB(const struct ovnact_ct_lb *cl, recirc_table, zone_reg); } - table_id = ovn_extend_table_assign_id(ep->group_table, &ds); + table_id = ovn_extend_table_assign_id(ep->group_table, &ds, + ep->lflow_uuid); ds_destroy(&ds); if (table_id == EXT_TABLE_ID_INVALID) { return; @@ -2158,7 +2159,8 @@ encode_SET_METER(const struct ovnact_set_meter *cl, cl->rate); } - table_id = ovn_extend_table_assign_id(ep->meter_table, &ds); + table_id = ovn_extend_table_assign_id(ep->meter_table, &ds, + ep->lflow_uuid); if (table_id == EXT_TABLE_ID_INVALID) { ds_destroy(&ds); return; diff --git a/ovn/lib/extend-table.c b/ovn/lib/extend-table.c index e18713b..7e4f471 100644 --- a/ovn/lib/extend-table.c +++ b/ovn/lib/extend-table.c @@ -102,21 +102,30 @@ ovn_extend_table_remove(struct ovn_extend_table *table, free(existing); } +static struct ovn_extend_table_info* +ovn_extend_info_clone(struct ovn_extend_table_info *source) +{ + struct ovn_extend_table_info *clone = xmalloc(sizeof *clone); + ds_clone(&clone->info, &source->info); + clone->table_id = source->table_id; + clone->new_table_id = source->new_table_id; + clone->hmap_node.hash = source->hmap_node.hash; + clone->lflow_uuid = source->lflow_uuid; + return clone; +} + void -ovn_extend_table_move(struct ovn_extend_table *table) +ovn_extend_table_sync(struct ovn_extend_table *table) { struct ovn_extend_table_info *desired, *next; - /* Move the contents of desired to existing. */ + /* Copy the contents of desired to existing. */ HMAP_FOR_EACH_SAFE (desired, next, hmap_node, &table->desired) { - hmap_remove(&table->desired, &desired->hmap_node); - if (!ovn_extend_table_lookup(&table->existing, desired)) { - hmap_insert(&table->existing, &desired->hmap_node, - desired->hmap_node.hash); - } else { - ds_destroy(&desired->info); - free(desired); + struct ovn_extend_table_info *clone = + ovn_extend_info_clone(desired); + hmap_insert(&table->existing, &clone->hmap_node, + clone->hmap_node.hash); } } } @@ -124,7 +133,8 @@ ovn_extend_table_move(struct ovn_extend_table *table) /* Assign a new table ID for the table information from the bitmap. * If it already exists, return the old ID. */ uint32_t -ovn_extend_table_assign_id(struct ovn_extend_table *table, struct ds *ds) +ovn_extend_table_assign_id(struct ovn_extend_table *table, struct ds *ds, + struct uuid lflow_uuid) { uint32_t table_id = 0, hash; struct ovn_extend_table_info *table_info; @@ -165,6 +175,7 @@ ovn_extend_table_assign_id(struct ovn_extend_table *table, struct ds *ds) table_info->table_id = table_id; table_info->hmap_node.hash = hash; table_info->new_table_id = new_table_id; + table_info->lflow_uuid = lflow_uuid; hmap_insert(&table->desired, &table_info->hmap_node, table_info->hmap_node.hash); diff --git a/ovn/lib/extend-table.h b/ovn/lib/extend-table.h index d9ae549..6539127 100644 --- a/ovn/lib/extend-table.h +++ b/ovn/lib/extend-table.h @@ -23,6 +23,7 @@ #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" +#include "openvswitch/uuid.h" /* Used to manage expansion tables associated with Flow table, * such as the Group Table or Meter Table. */ @@ -37,6 +38,7 @@ struct ovn_extend_table { struct ovn_extend_table_info { struct hmap_node hmap_node; struct ds info; /* Details string for the table entity. */ + struct uuid lflow_uuid; uint32_t table_id; bool new_table_id; /* 'True' if 'table_id' was reserved from * ovn_extend_table's 'table_ids' bitmap. */ @@ -54,11 +56,12 @@ void ovn_extend_table_clear(struct ovn_extend_table *, bool); void ovn_extend_table_remove(struct ovn_extend_table *, struct ovn_extend_table_info *); -/* Move the contents of desired to existing. */ -void ovn_extend_table_move(struct ovn_extend_table *); +/* Copy the contents of desired to existing. */ +void ovn_extend_table_sync(struct ovn_extend_table *); uint32_t ovn_extend_table_assign_id(struct ovn_extend_table *, - struct ds *); + struct ds *, + struct uuid lflow_uuid); /* Iterates 'DESIRED' through all of the 'ovn_extend_table_info's in * 'TABLE'->desired that are not in 'TABLE'->existing. (The loop body -- 2.1.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev