From patchwork Wed Dec 6 04:32:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guoshuai Li X-Patchwork-Id: 845027 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ys5Mf4fDxz9sNV for ; Wed, 6 Dec 2017 15:33:18 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 27071124F; Wed, 6 Dec 2017 04:33:15 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id C4952123D for ; Wed, 6 Dec 2017 04:33:13 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from smtp2203-239.mail.aliyun.com (smtp2203-239.mail.aliyun.com [121.197.203.239]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id F39A8F4 for ; Wed, 6 Dec 2017 04:33:09 +0000 (UTC) X-Alimail-AntiSpam: AC=CONTINUE; BC=0.07445756|-1; CH=green; FP=0|0|0|0|0|-1|-1|-1; HT=e02c03299; MF=ligs@dtdream.com; NM=1; PH=DS; RN=2; RT=2; SR=0; TI=SMTPD_---.9c34cQh_1512534779; Received: from localhost.localdomain(mailfrom:ligs@dtdream.com fp:222.128.6.202) by smtp.aliyun-inc.com(10.147.41.158); Wed, 06 Dec 2017 12:33:02 +0800 From: Guoshuai Li To: dev@openvswitch.org Date: Wed, 6 Dec 2017 12:32:39 +0800 Message-Id: <20171206043240.6980-2-ligs@dtdream.com> X-Mailer: git-send-email 2.13.2.windows.1 In-Reply-To: <20171206043240.6980-1-ligs@dtdream.com> References: <20171206043240.6980-1-ligs@dtdream.com> X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v5 1/2] ovn-controller: Add extend_table instead of group_table to expand meter. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org The structure and function of the group table and meter table are similar, refactoring code is used to extend for add the meter table. The following function as lib: table init/destroy/clear, install contents from desired, remove contents from existing, Move the contents of desired to existing. Signed-off-by: Guoshuai Li --- include/ovn/actions.h | 21 +---- ovn/controller/lflow.c | 8 +- ovn/controller/lflow.h | 4 +- ovn/controller/ofctrl.c | 180 +++++++++++++----------------------- ovn/controller/ofctrl.h | 7 +- ovn/controller/ovn-controller.c | 20 +--- ovn/lib/actions.c | 58 ++---------- ovn/lib/automake.mk | 2 + ovn/lib/extend-table.c | 198 ++++++++++++++++++++++++++++++++++++++++ ovn/lib/extend-table.h | 69 ++++++++++++++ tests/test-ovn.c | 8 +- 11 files changed, 356 insertions(+), 219 deletions(-) create mode 100644 ovn/lib/extend-table.c create mode 100644 ovn/lib/extend-table.h diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 85a484ffa..ea90dbb2a 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -31,6 +31,7 @@ struct lexer; struct ofpbuf; struct shash; struct simap; +struct ovn_extend_table; /* List of OVN logical actions. * @@ -338,24 +339,6 @@ void *ovnact_put(struct ofpbuf *, enum ovnact_type, size_t len); OVNACTS #undef OVNACT -#define MAX_OVN_GROUPS 65535 - -struct group_table { - unsigned long *group_ids; /* Used as a bitmap with value set - * for allocated group ids in either - * desired_groups or existing_groups. */ - struct hmap desired_groups; - struct hmap existing_groups; -}; - -struct group_info { - struct hmap_node hmap_node; - struct ds group; - uint32_t group_id; - bool new_group_id; /* 'True' if 'group_id' was reserved from - * group_table's 'group_ids' bitmap. */ -}; - enum action_opcode { /* "arp { ...actions... }". * @@ -505,7 +488,7 @@ struct ovnact_encode_params { bool is_gateway_router; /* A struct to figure out the group_id for group actions. */ - struct group_table *group_table; + struct ovn_extend_table *group_table; /* OVN maps each logical flow table (ltable), one-to-one, onto a physical * OpenFlow flow table (ptable). A number of parameters describe this diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c index a62ec6ebe..3d990c49c 100644 --- a/ovn/controller/lflow.c +++ b/ovn/controller/lflow.c @@ -61,7 +61,7 @@ static void consider_logical_flow(struct controller_ctx *ctx, const struct chassis_index *chassis_index, const struct sbrec_logical_flow *lflow, const struct hmap *local_datapaths, - struct group_table *group_table, + struct ovn_extend_table *group_table, const struct sbrec_chassis *chassis, struct hmap *dhcp_opts, struct hmap *dhcpv6_opts, @@ -143,7 +143,7 @@ static void add_logical_flows(struct controller_ctx *ctx, const struct chassis_index *chassis_index, const struct hmap *local_datapaths, - struct group_table *group_table, + struct ovn_extend_table *group_table, const struct sbrec_chassis *chassis, const struct shash *addr_sets, struct hmap *flow_table, @@ -190,7 +190,7 @@ consider_logical_flow(struct controller_ctx *ctx, const struct chassis_index *chassis_index, const struct sbrec_logical_flow *lflow, const struct hmap *local_datapaths, - struct group_table *group_table, + struct ovn_extend_table *group_table, const struct sbrec_chassis *chassis, struct hmap *dhcp_opts, struct hmap *dhcpv6_opts, @@ -434,7 +434,7 @@ lflow_run(struct controller_ctx *ctx, const struct sbrec_chassis *chassis, const struct chassis_index *chassis_index, const struct hmap *local_datapaths, - struct group_table *group_table, + struct ovn_extend_table *group_table, const struct shash *addr_sets, struct hmap *flow_table, struct sset *active_tunnels, diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h index bfb7415e2..087b0ed8d 100644 --- a/ovn/controller/lflow.h +++ b/ovn/controller/lflow.h @@ -37,7 +37,7 @@ struct chassis_index; struct controller_ctx; -struct group_table; +struct ovn_extend_table; struct hmap; struct sbrec_chassis; struct simap; @@ -66,7 +66,7 @@ void lflow_run(struct controller_ctx *, const struct sbrec_chassis *chassis, const struct chassis_index *, const struct hmap *local_datapaths, - struct group_table *group_table, + struct ovn_extend_table *group_table, const struct shash *addr_sets, struct hmap *flow_table, struct sset *active_tunnels, diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index 90afddbb3..24894cb64 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -36,6 +36,7 @@ #include "openvswitch/vlog.h" #include "ovn-controller.h" #include "ovn/actions.h" +#include "ovn/lib/extend-table.h" #include "openvswitch/poll-loop.h" #include "physical.h" #include "openvswitch/rconn.h" @@ -68,6 +69,9 @@ 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 *); +static void add_group(uint32_t table_id, struct ds *ds, struct ovs_list *msgs); +static void delete_group(uint32_t table_id, struct ovs_list *msgs); + /* OpenFlow connection to the switch. */ static struct rconn *swconn; @@ -131,7 +135,7 @@ static struct rconn_packet_counter *tx_counter; static struct hmap installed_flows; /* A reference to the group_table. */ -static struct group_table *groups; +static struct ovn_extend_table *groups; /* MFF_* field ID for our Geneve option. In S_TLV_TABLE_MOD_SENT, this is * the option we requested (we don't know whether we obtained it yet). In @@ -150,7 +154,7 @@ static void ovn_flow_table_destroy(struct hmap *flow_table); static void ofctrl_recv(const struct ofp_header *, enum ofptype); void -ofctrl_init(struct group_table *group_table) +ofctrl_init(struct ovn_extend_table *group_table) { swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP13_VERSION); tx_counter = rconn_packet_counter_create(); @@ -158,6 +162,8 @@ ofctrl_init(struct group_table *group_table) ovs_list_init(&flow_updates); ovn_init_symtab(&symtab); groups = group_table; + groups->create = add_group; + groups->remove = delete_group; } /* S_NEW, for a new connection. @@ -385,7 +391,7 @@ run_S_CLEAR_FLOWS(void) /* Clear existing groups, to match the state of the switch. */ if (groups) { - ovn_group_table_clear(groups, true); + ovn_extend_table_clear(groups, true); } /* All flow updates are irrelevant now. */ @@ -747,44 +753,6 @@ add_flow_mod(struct ofputil_flow_mod *fm, struct ovs_list *msgs) /* group_table. */ -/* Finds and returns a group_info in 'existing_groups' whose key is identical - * to 'target''s key, or NULL if there is none. */ -static struct group_info * -ovn_group_lookup(struct hmap *exisiting_groups, - const struct group_info *target) -{ - struct group_info *e; - - HMAP_FOR_EACH_WITH_HASH(e, hmap_node, target->hmap_node.hash, - exisiting_groups) { - if (e->group_id == target->group_id) { - return e; - } - } - return NULL; -} - -/* Clear either desired_groups or existing_groups in group_table. */ -void -ovn_group_table_clear(struct group_table *group_table, bool existing) -{ - struct group_info *g, *next; - struct hmap *target_group = existing - ? &group_table->existing_groups - : &group_table->desired_groups; - - HMAP_FOR_EACH_SAFE (g, next, hmap_node, target_group) { - hmap_remove(target_group, &g->hmap_node); - /* Don't unset bitmap for desired group_info if the group_id - * was not freshly reserved. */ - if (existing || g->new_group_id) { - bitmap_set0(group_table->group_ids, g->group_id); - } - ds_destroy(&g->group); - free(g); - } -} - static struct ofpbuf * encode_group_mod(const struct ofputil_group_mod *gm) { @@ -797,6 +765,54 @@ add_group_mod(const struct ofputil_group_mod *gm, struct ovs_list *msgs) struct ofpbuf *msg = encode_group_mod(gm); ovs_list_push_back(msgs, &msg->list_node); } + +static void +add_group(uint32_t table_id, struct ds *ds, struct ovs_list *msgs) { + /* Create and install new group. */ + struct ofputil_group_mod gm; + enum ofputil_protocol usable_protocols; + char *error; + struct ds group_string = DS_EMPTY_INITIALIZER; + ds_put_format(&group_string, "group_id=%"PRIu32",%s", + table_id, ds_cstr(ds)); + + error = parse_ofp_group_mod_str(&gm, OFPGC11_ADD, ds_cstr(&group_string), + NULL, &usable_protocols); + if (!error) { + add_group_mod(&gm, msgs); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_ERR_RL(&rl, "new group %s %s", error, + ds_cstr(&group_string)); + free(error); + } + ds_destroy(&group_string); + ofputil_uninit_group_mod(&gm); +} + +static void +delete_group(uint32_t table_id, struct ovs_list *msgs) { + /* Delete the group. */ + struct ofputil_group_mod gm; + enum ofputil_protocol usable_protocols; + char *error; + struct ds group_string = DS_EMPTY_INITIALIZER; + ds_put_format(&group_string, "group_id=%"PRIu32"", table_id); + + error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE, + ds_cstr(&group_string), NULL, + &usable_protocols); + if (!error) { + add_group_mod(&gm, msgs); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_ERR_RL(&rl, "Error deleting group %"PRIu32": %s", + table_id, error); + free(error); + } + ds_destroy(&group_string); + ofputil_uninit_group_mod(&gm); +} static void add_ct_flush_zone(uint16_t zone_id, struct ovs_list *msgs) @@ -844,7 +860,7 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, { if (!ofctrl_can_put()) { ovn_flow_table_clear(flow_table); - ovn_group_table_clear(groups, false); + ovn_extend_table_clear(groups, false); return; } @@ -862,34 +878,7 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, } } - /* Iterate through all the desired groups. If there are new ones, - * add them to the switch. */ - struct group_info *desired; - HMAP_FOR_EACH(desired, hmap_node, &groups->desired_groups) { - if (!ovn_group_lookup(&groups->existing_groups, desired)) { - /* Create and install new group. */ - struct ofputil_group_mod gm; - enum ofputil_protocol usable_protocols; - char *error; - struct ds group_string = DS_EMPTY_INITIALIZER; - ds_put_format(&group_string, "group_id=%u,%s", - desired->group_id, ds_cstr(&desired->group)); - - error = parse_ofp_group_mod_str(&gm, OFPGC11_ADD, - ds_cstr(&group_string), NULL, - &usable_protocols); - if (!error) { - add_group_mod(&gm, &msgs); - } else { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_ERR_RL(&rl, "new group %s %s", error, - ds_cstr(&group_string)); - free(error); - } - ds_destroy(&group_string); - ofputil_uninit_group_mod(&gm); - } - } + ovn_extend_table_install_desired(groups, &msgs); /* Iterate through all of the installed flows. If any of them are no * longer desired, delete them; if any of them should have different @@ -962,55 +951,10 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, hmap_insert(&installed_flows, &d->hmap_node, d->hmap_node.hash); } - /* Iterate through the installed groups from previous runs. If they - * are not needed delete them. */ - struct group_info *installed, *next_group; - HMAP_FOR_EACH_SAFE(installed, next_group, hmap_node, - &groups->existing_groups) { - if (!ovn_group_lookup(&groups->desired_groups, installed)) { - /* Delete the group. */ - struct ofputil_group_mod gm; - enum ofputil_protocol usable_protocols; - char *error; - struct ds group_string = DS_EMPTY_INITIALIZER; - ds_put_format(&group_string, "group_id=%u", installed->group_id); - - error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE, - ds_cstr(&group_string), NULL, - &usable_protocols); - if (!error) { - add_group_mod(&gm, &msgs); - } else { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_ERR_RL(&rl, "Error deleting group %d: %s", - installed->group_id, error); - free(error); - } - ds_destroy(&group_string); - ofputil_uninit_group_mod(&gm); - - /* Remove 'installed' from 'groups->existing_groups' */ - hmap_remove(&groups->existing_groups, &installed->hmap_node); - ds_destroy(&installed->group); - - /* Dealloc group_id. */ - bitmap_set0(groups->group_ids, installed->group_id); - free(installed); - } - } + ovn_extend_table_remove_existing(groups, &msgs); - /* Move the contents of desired_groups to existing_groups. */ - HMAP_FOR_EACH_SAFE(desired, next_group, hmap_node, - &groups->desired_groups) { - hmap_remove(&groups->desired_groups, &desired->hmap_node); - if (!ovn_group_lookup(&groups->existing_groups, desired)) { - hmap_insert(&groups->existing_groups, &desired->hmap_node, - desired->hmap_node.hash); - } else { - ds_destroy(&desired->group); - free(desired); - } - } + /* Move the contents of groups->desired to groups->existing. */ + ovn_extend_table_move(groups); 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 d83f6aec4..9b5eab1f4 100644 --- a/ovn/controller/ofctrl.h +++ b/ovn/controller/ofctrl.h @@ -23,7 +23,7 @@ #include "ovsdb-idl.h" struct controller_ctx; -struct group_table; +struct ovn_extend_table; struct hmap; struct match; struct ofpbuf; @@ -31,7 +31,7 @@ struct ovsrec_bridge; struct shash; /* Interface for OVN main loop. */ -void ofctrl_init(struct group_table *group_table); +void ofctrl_init(struct ovn_extend_table *group_table); enum mf_field_id ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones); bool ofctrl_can_put(void); @@ -55,7 +55,4 @@ void ofctrl_add_flow(struct hmap *desired_flows, uint8_t table_id, void ofctrl_flow_table_clear(void); -void ovn_group_table_clear(struct group_table *group_table, - bool existing); - #endif /* ovn/ofctrl.h */ diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index c286ccbca..c486887a5 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -42,6 +42,7 @@ #include "openvswitch/vlog.h" #include "ovn/actions.h" #include "ovn/lib/chassis-index.h" +#include "ovn/lib/extend-table.h" #include "ovn/lib/ovn-sb-idl.h" #include "ovn/lib/ovn-util.h" #include "patch.h" @@ -593,11 +594,8 @@ main(int argc, char *argv[]) unixctl_command_register("exit", "", 0, 0, ovn_controller_exit, &exiting); /* Initialize group ids for loadbalancing. */ - struct group_table group_table; - group_table.group_ids = bitmap_allocate(MAX_OVN_GROUPS); - bitmap_set1(group_table.group_ids, 0); /* Group id 0 is invalid. */ - hmap_init(&group_table.desired_groups); - hmap_init(&group_table.existing_groups); + struct ovn_extend_table group_table; + ovn_extend_table_init(&group_table); daemonize_complete(); @@ -845,17 +843,7 @@ main(int argc, char *argv[]) simap_destroy(&ct_zones); shash_destroy(&pending_ct_zones); - bitmap_free(group_table.group_ids); - hmap_destroy(&group_table.desired_groups); - - struct group_info *installed, *next_group; - HMAP_FOR_EACH_SAFE(installed, next_group, hmap_node, - &group_table.existing_groups) { - hmap_remove(&group_table.existing_groups, &installed->hmap_node); - ds_destroy(&installed->group); - free(installed); - } - hmap_destroy(&group_table.existing_groups); + ovn_extend_table_destroy(&group_table); ovsdb_idl_loop_destroy(&ovs_idl_loop); ovsdb_idl_loop_destroy(&ovnsb_idl_loop); diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c index 69a2172a8..8a7fe4f59 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -35,6 +35,7 @@ #include "ovn/expr.h" #include "ovn/lex.h" #include "ovn/lib/acl-log.h" +#include "ovn/lib/extend-table.h" #include "packets.h" #include "openvswitch/shash.h" #include "simap.h" @@ -1026,8 +1027,7 @@ encode_CT_LB(const struct ovnact_ct_lb *cl, return; } - uint32_t group_id = 0, hash; - struct group_info *group_info; + uint32_t table_id = 0; struct ofpact_group *og; uint32_t zone_reg = ep->is_switch ? MFF_LOG_CT_ZONE - MFF_REG0 : MFF_LOG_DNAT_ZONE - MFF_REG0; @@ -1059,59 +1059,17 @@ encode_CT_LB(const struct ovnact_ct_lb *cl, recirc_table, zone_reg); } - hash = hash_string(ds_cstr(&ds), 0); - - /* Check whether we have non installed but allocated group_id. */ - HMAP_FOR_EACH_WITH_HASH (group_info, hmap_node, hash, - &ep->group_table->desired_groups) { - if (!strcmp(ds_cstr(&group_info->group), ds_cstr(&ds))) { - group_id = group_info->group_id; - break; - } - } - - if (!group_id) { - /* Check whether we already have an installed entry for this - * combination. */ - HMAP_FOR_EACH_WITH_HASH (group_info, hmap_node, hash, - &ep->group_table->existing_groups) { - if (!strcmp(ds_cstr(&group_info->group), ds_cstr(&ds))) { - group_id = group_info->group_id; - } - } - - bool new_group_id = false; - if (!group_id) { - /* Reserve a new group_id. */ - group_id = bitmap_scan(ep->group_table->group_ids, 0, 1, - MAX_OVN_GROUPS + 1); - new_group_id = true; - } - - if (group_id == MAX_OVN_GROUPS + 1) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_ERR_RL(&rl, "out of group ids"); - - ds_destroy(&ds); - return; - } - bitmap_set1(ep->group_table->group_ids, group_id); - - group_info = xmalloc(sizeof *group_info); - group_info->group = ds; - group_info->group_id = group_id; - group_info->hmap_node.hash = hash; - group_info->new_group_id = new_group_id; - - hmap_insert(&ep->group_table->desired_groups, - &group_info->hmap_node, group_info->hmap_node.hash); - } else { + table_id = ovn_extend_table_assign_id(ep->group_table, &ds); + if (table_id == EXT_TABLE_ID_INVALID) { ds_destroy(&ds); + return; } + ds_destroy(&ds); + /* Create an action to set the group. */ og = ofpact_put_GROUP(ofpacts); - og->group_id = group_id; + og->group_id = table_id; } static void diff --git a/ovn/lib/automake.mk b/ovn/lib/automake.mk index dae06a5c1..6178fc2d5 100644 --- a/ovn/lib/automake.mk +++ b/ovn/lib/automake.mk @@ -10,6 +10,8 @@ ovn_lib_libovn_la_SOURCES = \ ovn/lib/chassis-index.c \ ovn/lib/chassis-index.h \ ovn/lib/expr.c \ + ovn/lib/extend-table.h \ + ovn/lib/extend-table.c \ ovn/lib/lex.c \ ovn/lib/ovn-l7.h \ ovn/lib/ovn-util.c \ diff --git a/ovn/lib/extend-table.c b/ovn/lib/extend-table.c new file mode 100644 index 000000000..dfd1a9413 --- /dev/null +++ b/ovn/lib/extend-table.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2017 DtDream Technology Co.,Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "bitmap.h" +#include "hash.h" +#include "openvswitch/vlog.h" +#include "ovn/lib/extend-table.h" + +VLOG_DEFINE_THIS_MODULE(extend_table); + +void ovn_extend_table_init(struct ovn_extend_table *table) +{ + table->table_ids = bitmap_allocate(MAX_EXT_TABLE_ID); + bitmap_set1(table->table_ids, 0); /* table id 0 is invalid. */ + hmap_init(&table->desired); + hmap_init(&table->existing); +} + +void ovn_extend_table_destroy(struct ovn_extend_table *table) +{ + bitmap_free(table->table_ids); + + struct ovn_extend_table_info *desired, *desired_next; + HMAP_FOR_EACH_SAFE (desired, desired_next, hmap_node, &table->existing) { + hmap_remove(&table->existing, &desired->hmap_node); + ds_destroy(&desired->info); + free(desired); + } + hmap_destroy(&table->desired); + + struct ovn_extend_table_info *existing, *existing_next; + HMAP_FOR_EACH_SAFE (existing, existing_next, hmap_node, &table->existing) { + hmap_remove(&table->existing, &existing->hmap_node); + ds_destroy(&existing->info); + free(existing); + } + hmap_destroy(&table->existing); +} + +/* Finds and returns a group_info in 'existing' whose key is identical + * to 'target''s key, or NULL if there is none. */ +static struct ovn_extend_table_info * +ovn_extend_table_lookup(struct hmap *exisiting, + const struct ovn_extend_table_info *target) +{ + struct ovn_extend_table_info *e; + + HMAP_FOR_EACH_WITH_HASH (e, hmap_node, target->hmap_node.hash, + exisiting) { + if (e->table_id == target->table_id) { + return e; + } + } + return NULL; +} + +/* Clear either desired or existing in ovn_extend_table. */ +void +ovn_extend_table_clear(struct ovn_extend_table *table, bool existing) +{ + struct ovn_extend_table_info *g, *next; + struct hmap *target = existing ? &table->existing : &table->desired; + + HMAP_FOR_EACH_SAFE (g, next, hmap_node, target) { + hmap_remove(target, &g->hmap_node); + /* Don't unset bitmap for desired group_info if the group_id + * was not freshly reserved. */ + if (existing || g->new_table_id) { + bitmap_set0(table->table_ids, g->table_id); + } + ds_destroy(&g->info); + free(g); + } +} + +void +ovn_extend_table_install_desired(struct ovn_extend_table *table, + struct ovs_list *msgs) +{ + struct ovn_extend_table_info *desired; + + /* Iterate through all the desired tables. If there are new ones, + * add them to the switch. */ + HMAP_FOR_EACH (desired, hmap_node, &table->desired) { + if (!ovn_extend_table_lookup(&table->existing, desired)) { + /* Create and install new group. */ + table->create(desired->table_id, &desired->info, msgs); + } + } +} + +void +ovn_extend_table_remove_existing(struct ovn_extend_table *table, + struct ovs_list *msgs) +{ + struct ovn_extend_table_info *existing, *next; + + /* Iterate through the installed tables from previous runs. If they + * are not needed delete them. */ + HMAP_FOR_EACH_SAFE (existing, next, hmap_node, &table->existing) { + if (!ovn_extend_table_lookup(&table->desired, existing)) { + + table->remove(existing->table_id, msgs); + + /* Remove 'installed' from 'groups->existing' */ + hmap_remove(&table->existing, &existing->hmap_node); + ds_destroy(&existing->info); + + /* Dealloc group_id. */ + bitmap_set0(table->table_ids, existing->table_id); + free(existing); + } + } +} + +void +ovn_extend_table_move(struct ovn_extend_table *table) +{ + struct ovn_extend_table_info *desired, *next; + + /* Move 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); + } + } +} + +/* 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) +{ + uint32_t table_id = 0, hash; + struct ovn_extend_table_info *table_info; + + hash = hash_string(ds_cstr(ds), 0); + + /* Check whether we have non installed but allocated group_id. */ + HMAP_FOR_EACH_WITH_HASH (table_info, hmap_node, hash, &table->desired) { + if (!strcmp(ds_cstr(&table_info->info), ds_cstr(ds))) { + return table_info->table_id; + } + } + + /* Check whether we already have an installed entry for this + * combination. */ + HMAP_FOR_EACH_WITH_HASH (table_info, hmap_node, hash, &table->existing) { + if (!strcmp(ds_cstr(&table_info->info), ds_cstr(ds))) { + table_id = table_info->table_id; + } + } + + bool new_table_id = false; + if (!table_id) { + /* Reserve a new group_id. */ + table_id = bitmap_scan(table->table_ids, 0, 1, MAX_EXT_TABLE_ID + 1); + new_table_id = true; + } + + if (table_id == MAX_EXT_TABLE_ID + 1) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_ERR_RL(&rl, "%"PRIu32" out of table ids.", table_id); + return EXT_TABLE_ID_INVALID; + } + bitmap_set1(table->table_ids, table_id); + + table_info = xmalloc(sizeof *table_info); + ds_clone(&table_info->info, ds); + table_info->table_id = table_id; + table_info->hmap_node.hash = hash; + table_info->new_table_id = new_table_id; + + hmap_insert(&table->desired, + &table_info->hmap_node, table_info->hmap_node.hash); + + return table_id; +} diff --git a/ovn/lib/extend-table.h b/ovn/lib/extend-table.h new file mode 100644 index 000000000..ededba59d --- /dev/null +++ b/ovn/lib/extend-table.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017 DtDream Technology Co.,Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EXTEND_TABLE_H +#define EXTEND_TABLE_H 1 + +#define MAX_EXT_TABLE_ID 65535 +#define EXT_TABLE_ID_INVALID 0 + +#include "openvswitch/dynamic-string.h" +#include "openvswitch/hmap.h" +#include "openvswitch/list.h" + +/* Used to manage expansion tables associated with Flow table, + * such as the Group Table or Meter Table. */ +struct ovn_extend_table { + unsigned long *table_ids; /* Used as a bitmap with value set + * for allocated group ids in either + * desired or existing. */ + struct hmap desired; + struct hmap existing; + + /* Used to create a form entity through the openflow channel. */ + void (*create)(uint32_t, struct ds *, struct ovs_list *); + + /* Used to remove a form entity through the openflow channel. */ + void (*remove)(uint32_t, struct ovs_list *); +}; + +struct ovn_extend_table_info { + struct hmap_node hmap_node; + struct ds info; /* Details string for the table entity. */ + uint32_t table_id; + bool new_table_id; /* 'True' if 'table_id' was reserved from + * ovn_extend_table's 'table_ids' bitmap. */ +}; + +void ovn_extend_table_init(struct ovn_extend_table *table); + +void ovn_extend_table_destroy(struct ovn_extend_table *table); + +void ovn_extend_table_install_desired(struct ovn_extend_table *table, + struct ovs_list *msgs); + +void ovn_extend_table_remove_existing(struct ovn_extend_table *table, + struct ovs_list *msgs); + +/* Move the contents of desired to existing. */ +void ovn_extend_table_move(struct ovn_extend_table *table); + +void ovn_extend_table_clear(struct ovn_extend_table *table, bool existing); + +uint32_t ovn_extend_table_assign_id(struct ovn_extend_table *table, + struct ds *ds); + +#endif /* ovn/lib/extend-table.h */ diff --git a/tests/test-ovn.c b/tests/test-ovn.c index f9a5085f7..4f65ee9d1 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -33,6 +33,7 @@ #include "ovn/lex.h" #include "ovn/lib/logical-fields.h" #include "ovn/lib/ovn-l7.h" +#include "ovn/lib/extend-table.h" #include "ovs-thread.h" #include "ovstest.h" #include "openvswitch/shash.h" @@ -1207,11 +1208,8 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts); /* Initialize group ids. */ - struct group_table group_table; - group_table.group_ids = bitmap_allocate(MAX_OVN_GROUPS); - bitmap_set1(group_table.group_ids, 0); /* Group id 0 is invalid. */ - hmap_init(&group_table.desired_groups); - hmap_init(&group_table.existing_groups); + struct ovn_extend_table group_table; + ovn_extend_table_init(&group_table); simap_init(&ports); simap_put(&ports, "eth0", 5);