On 12/09/2015 06:38 AM, Ben Pfaff wrote: > This was more or less implemented inside lflow.c until now, but some > upcoming code that shouldn't be in that file needs to use it too. > > This also adds a second index on lports, so that lports can be looked up > based on the logical datapath tunnel key and the logical port tunnel key. > An upcoming commit will add a user for this new index. > > Signed-off-by: Ben Pfaff <b...@ovn.org> > --- > ovn/controller/automake.mk | 2 + > ovn/controller/lflow.c | 165 > +++++++++------------------------------- > ovn/controller/lflow.h | 7 +- > ovn/controller/lport.c | 157 ++++++++++++++++++++++++++++++++++++++ > ovn/controller/lport.h | 69 +++++++++++++++++ > ovn/controller/ovn-controller.c | 33 ++++---- > 6 files changed, 288 insertions(+), 145 deletions(-) > create mode 100644 ovn/controller/lport.c > create mode 100644 ovn/controller/lport.h > > diff --git a/ovn/controller/automake.mk b/ovn/controller/automake.mk > index cadfa9c..cf57bbd 100644 > --- a/ovn/controller/automake.mk > +++ b/ovn/controller/automake.mk > @@ -8,6 +8,8 @@ ovn_controller_ovn_controller_SOURCES = \ > ovn/controller/encaps.h \ > ovn/controller/lflow.c \ > ovn/controller/lflow.h \ > + ovn/controller/lport.c \ > + ovn/controller/lport.h \ > ovn/controller/ofctrl.c \ > ovn/controller/ofctrl.h \ > ovn/controller/pinctrl.c \ > diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c > index dcabe2f..2bfc9e1 100644 > --- a/ovn/controller/lflow.c > +++ b/ovn/controller/lflow.c > @@ -15,12 +15,13 @@ > > #include <config.h> > #include "lflow.h" > +#include "lport.h" > #include "dynamic-string.h" > #include "ofctrl.h" > #include "ofp-actions.h" > #include "ofpbuf.h" > #include "openvswitch/vlog.h" > -#include "ovn/controller/ovn-controller.h" > +#include "ovn-controller.h" > #include "ovn/lib/actions.h" > #include "ovn/lib/expr.h" > #include "ovn/lib/ovn-sb-idl.h" > @@ -42,8 +43,8 @@ add_logical_register(struct shash *symtab, enum mf_field_id > id) > expr_symtab_add_field(symtab, name, id, NULL, false); > } > > -static void > -symtab_init(void) > +void > +lflow_init(void) > { > shash_init(&symtab); > > @@ -147,149 +148,48 @@ symtab_init(void) > expr_symtab_add_field(&symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false); > } > > -/* Logical datapaths and logical port numbers. */ > - > -/* A logical datapath. > - * > - * 'ports' maps 'logical_port' names to 'tunnel_key' values in the OVN_SB > - * Port_Binding table within the logical datapath. */ > -struct logical_datapath { > - struct hmap_node hmap_node; /* Indexed on 'uuid'. */ > - struct uuid uuid; /* UUID from Datapath_Binding row. */ > - uint32_t tunnel_key; /* 'tunnel_key' from Datapath_Binding row. */ > - struct simap ports; /* Logical port name to port number. */ > +struct lookup_port_aux { > + const struct lport_index *lports; > + const struct mcgroup_index *mcgroups; > + const struct sbrec_datapath_binding *dp; > }; > > -/* Contains "struct logical_datapath"s. */ > -static struct hmap logical_datapaths = HMAP_INITIALIZER(&logical_datapaths); > - > -/* Finds and returns the logical_datapath for 'binding', or NULL if no such > - * logical_datapath exists. */ > -static struct logical_datapath * > -ldp_lookup(const struct sbrec_datapath_binding *binding) > -{ > - struct logical_datapath *ldp; > - HMAP_FOR_EACH_IN_BUCKET (ldp, hmap_node, > uuid_hash(&binding->header_.uuid), > - &logical_datapaths) { > - if (uuid_equals(&ldp->uuid, &binding->header_.uuid)) { > - return ldp; > - } > - } > - return NULL; > -} > - > -/* Creates a new logical_datapath for the given 'binding'. */ > -static struct logical_datapath * > -ldp_create(const struct sbrec_datapath_binding *binding) > -{ > - struct logical_datapath *ldp; > - > - ldp = xmalloc(sizeof *ldp); > - hmap_insert(&logical_datapaths, &ldp->hmap_node, > - uuid_hash(&binding->header_.uuid)); > - ldp->uuid = binding->header_.uuid; > - ldp->tunnel_key = binding->tunnel_key; > - simap_init(&ldp->ports); > - return ldp; > -} > - > -static struct logical_datapath * > -ldp_lookup_or_create(const struct sbrec_datapath_binding *binding) > -{ > - struct logical_datapath *ldp = ldp_lookup(binding); > - return ldp ? ldp : ldp_create(binding); > -} > - > -static void > -ldp_free(struct logical_datapath *ldp) > -{ > - simap_destroy(&ldp->ports); > - hmap_remove(&logical_datapaths, &ldp->hmap_node); > - free(ldp); > -} > - > -/* Iterates through all of the records in the Port_Binding table, updating > the > - * table of logical_datapaths to match the values found in active > - * Port_Bindings. */ > -static void > -ldp_run(struct controller_ctx *ctx) > +static bool > +lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp) > { > - struct logical_datapath *ldp; > - HMAP_FOR_EACH (ldp, hmap_node, &logical_datapaths) { > - simap_clear(&ldp->ports); > - } > - > - const struct sbrec_port_binding *binding; > - SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) { > - struct logical_datapath *ldp = > ldp_lookup_or_create(binding->datapath); > + const struct lookup_port_aux *aux = aux_; > > - simap_put(&ldp->ports, binding->logical_port, binding->tunnel_key); > + const struct sbrec_port_binding *pb > + = lport_lookup_by_name(aux->lports, port_name); > + if (pb && pb->datapath == aux->dp) { > + *portp = pb->tunnel_key; > + return true; > } > > - const struct sbrec_multicast_group *mc; > - SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) { > - struct logical_datapath *ldp = ldp_lookup_or_create(mc->datapath); > - simap_put(&ldp->ports, mc->name, mc->tunnel_key); > + const struct sbrec_multicast_group *mg > + = mcgroup_lookup_by_dp_name(aux->mcgroups, aux->dp, port_name); > + if (mg) { > + *portp = mg->tunnel_key; > + return true; > } > > - struct logical_datapath *next_ldp; > - HMAP_FOR_EACH_SAFE (ldp, next_ldp, hmap_node, &logical_datapaths) { > - if (simap_is_empty(&ldp->ports)) { > - ldp_free(ldp); > - } > - } > -} > + VLOG_WARN("unknown lport name %s", port_name); > I am seeing a lot of this warning log print because 'inport = \"\"' for the logical flows pertaining to "ARP reply for known IPs". May be this warning print can be removed.
Thanks Numan > -static void > -ldp_destroy(void) > -{ > - struct logical_datapath *ldp, *next_ldp; > - HMAP_FOR_EACH_SAFE (ldp, next_ldp, hmap_node, &logical_datapaths) { > - ldp_free(ldp); > - } > -} > - > -void > -lflow_init(void) > -{ > - symtab_init(); > -} > - > -static bool > -lookup_port_cb(const void *ldp_, const char *port_name, unsigned int *portp) > -{ > - const struct logical_datapath *ldp = ldp_; > - const struct simap_node *node = simap_find(&ldp->ports, port_name); > - if (!node) { > - return false; > - } > - *portp = node->data; > - return true; > + return false; > } > > /* Translates logical flows in the Logical_Flow table in the OVN_SB database > * into OpenFlow flows. See ovn-architecture(7) for more information. */ > void > -lflow_run(struct controller_ctx *ctx, struct hmap *flow_table, > - const struct simap *ct_zones) > +lflow_run(struct controller_ctx *ctx, const struct lport_index *lports, > + const struct mcgroup_index *mcgroups, > + const struct simap *ct_zones, struct hmap *flow_table) > { > struct hmap flows = HMAP_INITIALIZER(&flows); > uint32_t conj_id_ofs = 1; > > - ldp_run(ctx); > - > const struct sbrec_logical_flow *lflow; > SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) { > - /* Find the "struct logical_datapath" asssociated with this > - * Logical_Flow row. If there's no such struct, that must be because > - * no logical ports are bound to that logical datapath, so there's no > - * point in maintaining any flows for it anyway, so skip it. */ > - const struct logical_datapath *ldp; > - ldp = ldp_lookup(lflow->logical_datapath); > - if (!ldp) { > - continue; > - } > - > /* Determine translation of logical table IDs to physical table IDs. > */ > bool ingress = !strcmp(lflow->pipeline, "ingress"); > uint8_t first_ptable = (ingress > @@ -309,10 +209,15 @@ lflow_run(struct controller_ctx *ctx, struct hmap > *flow_table, > char *error; > > ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub); > + struct lookup_port_aux aux = { > + .lports = lports, > + .mcgroups = mcgroups, > + .dp = lflow->logical_datapath > + }; > struct action_params ap = { > .symtab = &symtab, > .lookup_port = lookup_port_cb, > - .aux = ldp, > + .aux = &aux, > .ct_zones = ct_zones, > > .n_tables = LOG_PIPELINE_LEN, > @@ -353,14 +258,15 @@ lflow_run(struct controller_ctx *ctx, struct hmap > *flow_table, > > expr = expr_simplify(expr); > expr = expr_normalize(expr); > - uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, ldp, > + uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux, > &matches); > expr_destroy(expr); > > /* Prepare the OpenFlow matches for adding to the flow table. */ > struct expr_match *m; > HMAP_FOR_EACH (m, hmap_node, &matches) { > - match_set_metadata(&m->match, htonll(ldp->tunnel_key)); > + match_set_metadata(&m->match, > + htonll(lflow->logical_datapath->tunnel_key)); > if (m->match.wc.masks.conj_id) { > m->match.flow.conj_id += conj_id_ofs; > } > @@ -398,5 +304,4 @@ void > lflow_destroy(void) > { > expr_symtab_destroy(&symtab); > - ldp_destroy(); > } > diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h > index 4a4fa83..b8c53ce 100644 > --- a/ovn/controller/lflow.h > +++ b/ovn/controller/lflow.h > @@ -37,6 +37,8 @@ > > struct controller_ctx; > struct hmap; > +struct lport_index; > +struct mcgroup_index; > struct simap; > struct uuid; > > @@ -56,8 +58,9 @@ struct uuid; > #define LOG_PIPELINE_LEN 16 > > void lflow_init(void); > -void lflow_run(struct controller_ctx *, struct hmap *flow_table, > - const struct simap *ct_zones); > +void lflow_run(struct controller_ctx *, const struct lport_index *, > + const struct mcgroup_index *, const struct simap *ct_zones, > + struct hmap *flow_table); > void lflow_destroy(void); > > #endif /* ovn/lflow.h */ > diff --git a/ovn/controller/lport.c b/ovn/controller/lport.c > new file mode 100644 > index 0000000..b9df8bd > --- /dev/null > +++ b/ovn/controller/lport.c > @@ -0,0 +1,157 @@ > +/* Copyright (c) 2015 Nicira, Inc. > + * > + * 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 <config.h> > + > +#include "lport.h" > +#include "hash.h" > +#include "openvswitch/vlog.h" > +#include "ovn/lib/ovn-sb-idl.h" > + > +VLOG_DEFINE_THIS_MODULE(lport); > + > +/* A logical port. */ > +struct lport { > + struct hmap_node name_node; /* Index by name. */ > + struct hmap_node key_node; /* Index by (dp->tunnel_key, tunnel_key). */ > + const struct sbrec_port_binding *sb; > +}; > + > +/* Finds and returns the lport with the given 'name', or NULL if no such > lport > + * exists. */ > +const struct sbrec_port_binding * > +lport_lookup_by_name(const struct lport_index *lports, const char *name) > +{ > + const struct lport *lport; > + HMAP_FOR_EACH_WITH_HASH (lport, name_node, hash_string(name, 0), > + &lports->by_name) { > + if (!strcmp(lport->sb->logical_port, name)) { > + return lport->sb; > + } > + } > + return NULL; > +} > + > +const struct sbrec_port_binding * > +lport_lookup_by_key(const struct lport_index *lports, > + uint32_t dp_key, uint16_t port_key) > +{ > + const struct lport *lport; > + HMAP_FOR_EACH_WITH_HASH (lport, key_node, hash_int(port_key, dp_key), > + &lports->by_key) { > + if (port_key == lport->sb->tunnel_key > + && dp_key == lport->sb->datapath->tunnel_key) { > + return lport->sb; > + } > + } > + return NULL; > +} > + > +void > +lport_index_init(struct lport_index *lports, struct ovsdb_idl *ovnsb_idl) > +{ > + hmap_init(&lports->by_name); > + hmap_init(&lports->by_key); > + > + const struct sbrec_port_binding *sb; > + SBREC_PORT_BINDING_FOR_EACH (sb, ovnsb_idl) { > + if (lport_lookup_by_name(lports, sb->logical_port)) { > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); > + VLOG_WARN_RL(&rl, "duplicate logical port name '%s'", > + sb->logical_port); > + continue; > + } > + > + struct lport *p = xmalloc(sizeof *p); > + hmap_insert(&lports->by_name, &p->name_node, > + hash_string(sb->logical_port, 0)); > + hmap_insert(&lports->by_key, &p->key_node, > + hash_int(sb->tunnel_key, sb->datapath->tunnel_key)); > + p->sb = sb; > + } > +} > + > +void > +lport_index_destroy(struct lport_index *lports) > +{ > + /* Destroy all of the "struct lport"s. > + * > + * We don't have to remove the node from both indexes. */ > + struct lport *port, *next; > + HMAP_FOR_EACH_SAFE (port, next, name_node, &lports->by_name) { > + hmap_remove(&lports->by_name, &port->name_node); > + free(port); > + } > + > + hmap_destroy(&lports->by_name); > + hmap_destroy(&lports->by_key); > +} > + > +struct mcgroup { > + struct hmap_node dp_name_node; /* Index by (logical datapath, name). */ > + const struct sbrec_multicast_group *sb; > +}; > + > +void > +mcgroup_index_init(struct mcgroup_index *mcgroups, struct ovsdb_idl > *ovnsb_idl) > +{ > + hmap_init(&mcgroups->by_dp_name); > + > + const struct sbrec_multicast_group *sb; > + SBREC_MULTICAST_GROUP_FOR_EACH (sb, ovnsb_idl) { > + const struct uuid *dp_uuid = &sb->datapath->header_.uuid; > + if (mcgroup_lookup_by_dp_name(mcgroups, sb->datapath, sb->name)) { > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); > + VLOG_WARN_RL(&rl, "datapath "UUID_FMT" contains duplicate " > + "multicast group '%s'", UUID_ARGS(dp_uuid), > sb->name); > + continue; > + } > + > + struct mcgroup *m = xmalloc(sizeof *m); > + hmap_insert(&mcgroups->by_dp_name, &m->dp_name_node, > + hash_string(sb->name, uuid_hash(dp_uuid))); > + m->sb = sb; > + } > +} > + > +void > +mcgroup_index_destroy(struct mcgroup_index *mcgroups) > +{ > + struct mcgroup *mcgroup, *next; > + HMAP_FOR_EACH_SAFE (mcgroup, next, dp_name_node, &mcgroups->by_dp_name) { > + hmap_remove(&mcgroups->by_dp_name, &mcgroup->dp_name_node); > + free(mcgroup); > + } > + > + hmap_destroy(&mcgroups->by_dp_name); > +} > + > +const struct sbrec_multicast_group * > +mcgroup_lookup_by_dp_name(const struct mcgroup_index *mcgroups, > + const struct sbrec_datapath_binding *dp, > + const char *name) > +{ > + const struct uuid *dp_uuid = &dp->header_.uuid; > + const struct mcgroup *mcgroup; > + HMAP_FOR_EACH_WITH_HASH (mcgroup, dp_name_node, > + hash_string(name, uuid_hash(dp_uuid)), > + &mcgroups->by_dp_name) { > + if (uuid_equals(&mcgroup->sb->datapath->header_.uuid, dp_uuid) > + && !strcmp(mcgroup->sb->name, name)) { > + return mcgroup->sb; > + } > + } > + return NULL; > +} > diff --git a/ovn/controller/lport.h b/ovn/controller/lport.h > new file mode 100644 > index 0000000..661638d > --- /dev/null > +++ b/ovn/controller/lport.h > @@ -0,0 +1,69 @@ > +/* Copyright (c) 2015 Nicira, Inc. > + * > + * 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 OVN_LPORT_H > +#define OVN_LPORT_H 1 > + > +#include <stdint.h> > +#include "hmap.h" > + > +struct ovsdb_idl; > +struct sbrec_datapath_binding; > + > +/* Logical port and multicast group indexes > + * ======================================== > + * > + * This data structure holds multiple indexes over logical ports, to allow > for > + * efficient searching for logical ports by name or number. > + */ > + > +struct lport_index { > + struct hmap by_name; > + struct hmap by_key; > +}; > + > +void lport_index_init(struct lport_index *, struct ovsdb_idl *); > +void lport_index_destroy(struct lport_index *); > + > +const struct sbrec_port_binding *lport_lookup_by_name( > + const struct lport_index *, const char *name); > +const struct sbrec_port_binding *lport_lookup_by_key( > + const struct lport_index *, uint32_t dp_key, uint16_t port_key); > + > +/* Multicast group index > + * ===================== > + * > + * This is separate from the logical port index because of namespace issues: > + * logical port names are globally unique, but multicast group names are only > + * unique within the scope of a logical datapath. */ > + > +/* A multicast group. > + * > + * Multicast groups could be indexed by number also, but so far the clients > do > + * not need this index. */ > + > +struct mcgroup_index { > + struct hmap by_dp_name; > +}; > + > +void mcgroup_index_init(struct mcgroup_index *, struct ovsdb_idl *); > +void mcgroup_index_destroy(struct mcgroup_index *); > + > +const struct sbrec_multicast_group *mcgroup_lookup_by_dp_name( > + const struct mcgroup_index *, > + const struct sbrec_datapath_binding *, > + const char *name); > + > +#endif /* ovn/lport.h */ > diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c > index 02ecb3e..f5dbecc 100644 > --- a/ovn/controller/ovn-controller.c > +++ b/ovn/controller/ovn-controller.c > @@ -23,32 +23,32 @@ > #include <stdlib.h> > #include <string.h> > > +#include "binding.h" > +#include "chassis.h" > #include "command-line.h" > #include "compiler.h" > #include "daemon.h" > #include "dirs.h" > #include "dynamic-string.h" > +#include "encaps.h" > +#include "fatal-signal.h" > +#include "lflow.h" > +#include "lib/vswitch-idl.h" > +#include "lport.h" > +#include "ofctrl.h" > #include "openvswitch/vconn.h" > #include "openvswitch/vlog.h" > #include "ovn/lib/ovn-sb-idl.h" > +#include "patch.h" > +#include "physical.h" > +#include "pinctrl.h" > #include "poll-loop.h" > -#include "fatal-signal.h" > -#include "lib/vswitch-idl.h" > #include "smap.h" > -#include "stream.h" > #include "stream-ssl.h" > +#include "stream.h" > #include "unixctl.h" > #include "util.h" > > -#include "ofctrl.h" > -#include "pinctrl.h" > -#include "binding.h" > -#include "chassis.h" > -#include "encaps.h" > -#include "patch.h" > -#include "physical.h" > -#include "lflow.h" > - > VLOG_DEFINE_THIS_MODULE(main); > > static unixctl_cb_func ovn_controller_exit; > @@ -292,18 +292,25 @@ main(int argc, char *argv[]) > } > > if (br_int) { > + struct lport_index lports; > + struct mcgroup_index mcgroups; > + lport_index_init(&lports, ctx.ovnsb_idl); > + mcgroup_index_init(&mcgroups, ctx.ovnsb_idl); > + > enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int); > > pinctrl_run(&ctx, br_int); > > struct hmap flow_table = HMAP_INITIALIZER(&flow_table); > - lflow_run(&ctx, &flow_table, &ct_zones); > + lflow_run(&ctx, &lports, &mcgroups, &ct_zones, &flow_table); > 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); > + mcgroup_index_destroy(&mcgroups); > + lport_index_destroy(&lports); > } > > unixctl_server_run(unixctl); _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev