Message ID | 20210716114504.1895739-1-numans@ovn.org |
---|---|
State | Changes Requested |
Delegated to: | Han Zhou |
Headers | show |
Series | pflow_output and ct_zone engine improvements. | expand |
Context | Check | Description |
---|---|---|
ovsrobot/apply-robot | success | apply and check: success |
On Fri, Jul 16, 2021 at 4:45 AM <numans@ovn.org> wrote: > > From: Numan Siddique <numans@ovn.org> > > This would uncomplicate the binding.c code a bit. The tracking > data and the related functions are also moved to the file - ldata.h. > This would help in an upcoming patch. > > Signed-off-by: Numan Siddique <numans@ovn.org> > --- > controller/automake.mk | 4 +- > controller/binding.c | 363 ++++++----------------------------- > controller/binding.h | 13 -- > controller/ldata.c | 368 ++++++++++++++++++++++++++++++++++++ > controller/ldata.h | 120 ++++++++++++ > controller/lflow.c | 1 + > controller/lport.c | 40 ++++ > controller/lport.h | 7 +- > controller/ovn-controller.c | 50 ++--- > controller/ovn-controller.h | 34 ---- > controller/patch.c | 1 + > controller/physical.c | 1 + > controller/pinctrl.c | 1 + > 13 files changed, 618 insertions(+), 385 deletions(-) > create mode 100644 controller/ldata.c > create mode 100644 controller/ldata.h > > diff --git a/controller/automake.mk b/controller/automake.mk > index 2f6c50890..a3c5c6af5 100644 > --- a/controller/automake.mk > +++ b/controller/automake.mk > @@ -33,7 +33,9 @@ controller_ovn_controller_SOURCES = \ > controller/physical.c \ > controller/physical.h \ > controller/mac-learn.c \ > - controller/mac-learn.h > + controller/mac-learn.h \ > + controller/ldata.c \ > + controller/ldata.h > > controller_ovn_controller_LDADD = lib/libovn.la $(OVS_LIBDIR)/ libopenvswitch.la > man_MANS += controller/ovn-controller.8 > diff --git a/controller/binding.c b/controller/binding.c > index d50f3affa..e68546ca9 100644 > --- a/controller/binding.c > +++ b/controller/binding.c > @@ -14,13 +14,8 @@ > */ > > #include <config.h> > -#include "binding.h" > -#include "ha-chassis.h" > -#include "if-status.h" > -#include "lflow.h" > -#include "lport.h" > -#include "patch.h" > > +/* OVS includes. */ > #include "lib/bitmap.h" > #include "openvswitch/poll-loop.h" > #include "lib/sset.h" > @@ -29,9 +24,18 @@ > #include "lib/vswitch-idl.h" > #include "openvswitch/hmap.h" > #include "openvswitch/vlog.h" > + > +/* OVN includes. */ > +#include "binding.h" > +#include "ha-chassis.h" > +#include "if-status.h" > +#include "ldata.h" > +#include "lflow.h" > #include "lib/chassis-index.h" > #include "lib/ovn-sb-idl.h" > +#include "lport.h" > #include "ovn-controller.h" > +#include "patch.h" > > VLOG_DEFINE_THIS_MODULE(binding); > > @@ -76,106 +80,27 @@ binding_register_ovs_idl(struct ovsdb_idl *ovs_idl) > ovsdb_idl_add_column(ovs_idl, &ovsrec_qos_col_type); > } > > -static struct tracked_binding_datapath *tracked_binding_datapath_create( > - const struct sbrec_datapath_binding *, > - bool is_new, struct hmap *tracked_dps); > -static struct tracked_binding_datapath *tracked_binding_datapath_find( > - struct hmap *, const struct sbrec_datapath_binding *); > -static void tracked_binding_datapath_lport_add( > - const struct sbrec_port_binding *, struct hmap *tracked_datapaths); > static void update_lport_tracking(const struct sbrec_port_binding *pb, > - struct hmap *tracked_dp_bindings); > - > -static void > -add_local_datapath__(struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > - struct ovsdb_idl_index *sbrec_port_binding_by_datapath, > - struct ovsdb_idl_index *sbrec_port_binding_by_name, > - const struct sbrec_datapath_binding *datapath, > - bool has_local_l3gateway, int depth, > - struct hmap *local_datapaths, > - struct hmap *tracked_datapaths) > -{ > - uint32_t dp_key = datapath->tunnel_key; > - struct local_datapath *ld = get_local_datapath(local_datapaths, dp_key); > - if (ld) { > - if (has_local_l3gateway) { > - ld->has_local_l3gateway = true; > - } > - return; > - } > + struct hmap *tracked_dp_bindings, > + bool claimed); > > - ld = xzalloc(sizeof *ld); > - hmap_insert(local_datapaths, &ld->hmap_node, dp_key); > - ld->datapath = datapath; > - ld->localnet_port = NULL; > - shash_init(&ld->external_ports); > - ld->has_local_l3gateway = has_local_l3gateway; > - > - if (tracked_datapaths) { > - struct tracked_binding_datapath *tdp = > - tracked_binding_datapath_find(tracked_datapaths, datapath); > - if (!tdp) { > - tracked_binding_datapath_create(datapath, true, tracked_datapaths); > - } else { > - /* Its possible that there is already an entry in tracked datapaths > - * for this 'datapath'. tracked_binding_datapath_lport_add() may > - * have created it. Since the 'datapath' is added to the > - * local datapaths, set 'tdp->is_new' to true so that the flows > - * for this datapath are programmed properly. > - * */ > - tdp->is_new = true; > - } > - } > +struct local_datpath_added_aux { > + bool has_local_l3gateway; > + struct hmap *tracked_datapaths; > +}; > > - if (depth >= 100) { > - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); > - VLOG_WARN_RL(&rl, "datapaths nested too deep"); > - return; > +/* This function is called by local_datapath_add() if a new local_datapath > + * is created. */ > +static void > +local_datapath_added(struct local_datapath *ld, void *aux) > +{ > + struct local_datpath_added_aux *aux_ = aux; > + if (aux_->tracked_datapaths) { > + tracked_datapath_add(ld->datapath, TRACKED_RESOURCE_NEW, > + aux_->tracked_datapaths); > } > > - struct sbrec_port_binding *target = > - sbrec_port_binding_index_init_row(sbrec_port_binding_by_datapath); > - sbrec_port_binding_index_set_datapath(target, datapath); > - > - const struct sbrec_port_binding *pb; > - SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target, > - sbrec_port_binding_by_datapath) { > - if (!strcmp(pb->type, "patch") || !strcmp(pb->type, "l3gateway")) { > - const char *peer_name = smap_get(&pb->options, "peer"); > - if (peer_name) { > - const struct sbrec_port_binding *peer; > - > - peer = lport_lookup_by_name(sbrec_port_binding_by_name, > - peer_name); > - > - if (peer && peer->datapath) { > - if (!strcmp(pb->type, "patch")) { > - /* Add the datapath to local datapath only for patch > - * ports. For l3gateway ports, since gateway router > - * resides on one chassis, we don't need to add. > - * Otherwise, all other chassis might create patch > - * ports between br-int and the provider bridge. */ > - add_local_datapath__(sbrec_datapath_binding_by_key, > - sbrec_port_binding_by_datapath, > - sbrec_port_binding_by_name, > - peer->datapath, false, > - depth + 1, local_datapaths, > - tracked_datapaths); > - } > - ld->n_peer_ports++; > - if (ld->n_peer_ports > ld->n_allocated_peer_ports) { > - ld->peer_ports = > - x2nrealloc(ld->peer_ports, > - &ld->n_allocated_peer_ports, > - sizeof *ld->peer_ports); > - } > - ld->peer_ports[ld->n_peer_ports - 1].local = pb; > - ld->peer_ports[ld->n_peer_ports - 1].remote = peer; > - } > - } > - } > - } > - sbrec_port_binding_index_destroy_row(target); > + ld->has_local_l3gateway = aux_->has_local_l3gateway; > } > > static void > @@ -186,11 +111,17 @@ add_local_datapath(struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > bool has_local_l3gateway, struct hmap *local_datapaths, > struct hmap *tracked_datapaths) > { > - add_local_datapath__(sbrec_datapath_binding_by_key, > - sbrec_port_binding_by_datapath, > - sbrec_port_binding_by_name, > - datapath, has_local_l3gateway, 0, local_datapaths, > - tracked_datapaths); > + struct local_datpath_added_aux aux = { > + .has_local_l3gateway = has_local_l3gateway, > + .tracked_datapaths = tracked_datapaths, > + }; > + > + local_datapath_add(local_datapaths, datapath, > + sbrec_datapath_binding_by_key, > + sbrec_port_binding_by_datapath, > + sbrec_port_binding_by_name, > + local_datapath_added, > + &aux); > } > > static void > @@ -559,7 +490,8 @@ update_related_lport(const struct sbrec_port_binding *pb, > > if (b_ctx->tracked_dp_bindings) { > /* Add the 'pb' to the tracked_datapaths. */ > - tracked_binding_datapath_lport_add(pb, b_ctx->tracked_dp_bindings); > + tracked_datapath_lport_add(pb, TRACKED_RESOURCE_NEW, > + b_ctx->tracked_dp_bindings); > } > } > sset_add(&b_ctx->related_lports->lport_names, pb->logical_port); > @@ -582,7 +514,8 @@ remove_related_lport(const struct sbrec_port_binding *pb, > > if (b_ctx->tracked_dp_bindings) { > /* Add the 'pb' to the tracked_datapaths. */ > - tracked_binding_datapath_lport_add(pb, b_ctx->tracked_dp_bindings); > + tracked_datapath_lport_add(pb, TRACKED_RESOURCE_REMOVED, > + b_ctx->tracked_dp_bindings); > } > } > } > @@ -927,74 +860,6 @@ is_lport_vif(const struct sbrec_port_binding *pb) > return !pb->type[0]; > } > > -static struct tracked_binding_datapath * > -tracked_binding_datapath_create(const struct sbrec_datapath_binding *dp, > - bool is_new, > - struct hmap *tracked_datapaths) > -{ > - struct tracked_binding_datapath *t_dp = xzalloc(sizeof *t_dp); > - t_dp->dp = dp; > - t_dp->is_new = is_new; > - shash_init(&t_dp->lports); > - hmap_insert(tracked_datapaths, &t_dp->node, uuid_hash(&dp->header_.uuid)); > - return t_dp; > -} > - > -static struct tracked_binding_datapath * > -tracked_binding_datapath_find(struct hmap *tracked_datapaths, > - const struct sbrec_datapath_binding *dp) > -{ > - struct tracked_binding_datapath *t_dp; > - size_t hash = uuid_hash(&dp->header_.uuid); > - HMAP_FOR_EACH_WITH_HASH (t_dp, node, hash, tracked_datapaths) { > - if (uuid_equals(&t_dp->dp->header_.uuid, &dp->header_.uuid)) { > - return t_dp; > - } > - } > - > - return NULL; > -} > - > -static void > -tracked_binding_datapath_lport_add(const struct sbrec_port_binding *pb, > - struct hmap *tracked_datapaths) > -{ > - if (!tracked_datapaths) { > - return; > - } > - > - struct tracked_binding_datapath *tracked_dp = > - tracked_binding_datapath_find(tracked_datapaths, pb->datapath); > - if (!tracked_dp) { > - tracked_dp = tracked_binding_datapath_create(pb->datapath, false, > - tracked_datapaths); > - } > - > - /* Check if the lport is already present or not. > - * If it is already present, then just update the 'pb' field. */ > - struct tracked_binding_lport *lport = > - shash_find_data(&tracked_dp->lports, pb->logical_port); > - > - if (!lport) { > - lport = xmalloc(sizeof *lport); > - shash_add(&tracked_dp->lports, pb->logical_port, lport); > - } > - > - lport->pb = pb; > -} > - > -void > -binding_tracked_dp_destroy(struct hmap *tracked_datapaths) > -{ > - struct tracked_binding_datapath *t_dp; > - HMAP_FOR_EACH_POP (t_dp, node, tracked_datapaths) { > - shash_destroy_free_data(&t_dp->lports); > - free(t_dp); > - } > - > - hmap_destroy(tracked_datapaths); > -} > - > static enum en_lport_type > get_lport_type(const struct sbrec_port_binding *pb) > { > @@ -1129,7 +994,7 @@ claim_lport(const struct sbrec_port_binding *pb, > sbrec_port_binding_set_chassis(pb, chassis_rec); > > if (tracked_datapaths) { > - update_lport_tracking(pb, tracked_datapaths); > + update_lport_tracking(pb, tracked_datapaths, true); > } > } > > @@ -1178,7 +1043,7 @@ release_lport(const struct sbrec_port_binding *pb, bool sb_readonly, > sbrec_port_binding_set_virtual_parent(pb, NULL); > } > > - update_lport_tracking(pb, tracked_datapaths); > + update_lport_tracking(pb, tracked_datapaths, false); > if_status_mgr_release_iface(if_mgr, pb->logical_port); > VLOG_INFO("Releasing lport %s from this chassis.", pb->logical_port); > return true; > @@ -1828,42 +1693,6 @@ binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, > return !any_changes; > } > > -static const struct sbrec_port_binding * > -get_peer_lport__(const struct sbrec_port_binding *pb, > - struct binding_ctx_in *b_ctx_in) > -{ > - const char *peer_name = smap_get(&pb->options, "peer"); > - > - if (!peer_name) { > - return NULL; > - } > - > - const struct sbrec_port_binding *peer; > - peer = lport_lookup_by_name(b_ctx_in->sbrec_port_binding_by_name, > - peer_name); > - return (peer && peer->datapath) ? peer : NULL; > -} > - > -static const struct sbrec_port_binding * > -get_l3gw_peer_lport(const struct sbrec_port_binding *pb, > - struct binding_ctx_in *b_ctx_in) > -{ > - if (strcmp(pb->type, "l3gateway")) { > - return NULL; > - } > - return get_peer_lport__(pb, b_ctx_in); > -} > - > -static const struct sbrec_port_binding * > -get_peer_lport(const struct sbrec_port_binding *pb, > - struct binding_ctx_in *b_ctx_in) > -{ > - if (strcmp(pb->type, "patch")) { > - return NULL; > - } > - return get_peer_lport__(pb, b_ctx_in); > -} > - > /* This function adds the local datapath of the 'peer' of > * lport 'pb' to the local datapaths if it is not yet added. > */ > @@ -1873,61 +1702,16 @@ add_local_datapath_peer_port(const struct sbrec_port_binding *pb, > struct binding_ctx_out *b_ctx_out, > struct local_datapath *ld) > { > - const struct sbrec_port_binding *peer; > - peer = get_peer_lport(pb, b_ctx_in); > - > - if (!peer) { > - return; > - } > - > - bool present = false; > - for (size_t i = 0; i < ld->n_peer_ports; i++) { > - if (ld->peer_ports[i].local == pb) { > - present = true; > - break; > - } > - } > - > - if (!present) { > - ld->n_peer_ports++; > - if (ld->n_peer_ports > ld->n_allocated_peer_ports) { > - ld->peer_ports = > - x2nrealloc(ld->peer_ports, > - &ld->n_allocated_peer_ports, > - sizeof *ld->peer_ports); > - } > - ld->peer_ports[ld->n_peer_ports - 1].local = pb; > - ld->peer_ports[ld->n_peer_ports - 1].remote = peer; > - } > - > - struct local_datapath *peer_ld = > - get_local_datapath(b_ctx_out->local_datapaths, > - peer->datapath->tunnel_key); > - if (!peer_ld) { > - add_local_datapath__(b_ctx_in->sbrec_datapath_binding_by_key, > - b_ctx_in->sbrec_port_binding_by_datapath, > - b_ctx_in->sbrec_port_binding_by_name, > - peer->datapath, false, > - 1, b_ctx_out->local_datapaths, > - b_ctx_out->tracked_dp_bindings); > - return; > - } > - > - for (size_t i = 0; i < peer_ld->n_peer_ports; i++) { > - if (peer_ld->peer_ports[i].local == peer) { > - return; > - } > - } > + struct local_datpath_added_aux aux = { > + .has_local_l3gateway = false, > + .tracked_datapaths = b_ctx_out->tracked_dp_bindings, > + }; > > - peer_ld->n_peer_ports++; > - if (peer_ld->n_peer_ports > peer_ld->n_allocated_peer_ports) { > - peer_ld->peer_ports = > - x2nrealloc(peer_ld->peer_ports, > - &peer_ld->n_allocated_peer_ports, > - sizeof *peer_ld->peer_ports); > - } > - peer_ld->peer_ports[peer_ld->n_peer_ports - 1].local = peer; > - peer_ld->peer_ports[peer_ld->n_peer_ports - 1].remote = pb; > + local_datapath_add_peer_port(pb, b_ctx_in->sbrec_datapath_binding_by_key, > + b_ctx_in->sbrec_port_binding_by_datapath, > + b_ctx_in->sbrec_port_binding_by_name, > + ld, b_ctx_out->local_datapaths, > + local_datapath_added, &aux); > } > > static void > @@ -1935,34 +1719,7 @@ remove_local_datapath_peer_port(const struct sbrec_port_binding *pb, > struct local_datapath *ld, > struct hmap *local_datapaths) > { > - size_t i = 0; > - for (i = 0; i < ld->n_peer_ports; i++) { > - if (ld->peer_ports[i].local == pb) { > - break; > - } > - } > - > - if (i == ld->n_peer_ports) { > - return; > - } > - > - const struct sbrec_port_binding *peer = ld->peer_ports[i].remote; > - > - /* Possible improvement: We can shrink the allocated peer ports > - * if (ld->n_peer_ports < ld->n_allocated_peer_ports / 2). > - */ > - ld->peer_ports[i].local = ld->peer_ports[ld->n_peer_ports - 1].local; > - ld->peer_ports[i].remote = ld->peer_ports[ld->n_peer_ports - 1].remote; > - ld->n_peer_ports--; > - > - struct local_datapath *peer_ld = > - get_local_datapath(local_datapaths, peer->datapath->tunnel_key); > - if (peer_ld) { > - /* Remove the peer port from the peer datapath. The peer > - * datapath also tries to remove its peer lport, but that would > - * be no-op. */ > - remove_local_datapath_peer_port(peer, peer_ld, local_datapaths); > - } > + local_datapath_remove_peer_port(pb, ld, local_datapaths); > } > > static void > @@ -1995,13 +1752,16 @@ remove_pb_from_local_datapath(const struct sbrec_port_binding *pb, > > static void > update_lport_tracking(const struct sbrec_port_binding *pb, > - struct hmap *tracked_dp_bindings) > + struct hmap *tracked_dp_bindings, > + bool claimed) > { > if (!tracked_dp_bindings) { > return; > } > > - tracked_binding_datapath_lport_add(pb, tracked_dp_bindings); > + tracked_datapath_lport_add( > + pb, claimed ? TRACKED_RESOURCE_NEW : TRACKED_RESOURCE_REMOVED, > + tracked_dp_bindings); > } > > /* Considers the ovs iface 'iface_rec' for claiming. > @@ -2315,7 +2075,7 @@ handle_deleted_lport(const struct sbrec_port_binding *pb, > /* If the binding is not local, if 'pb' is a L3 gateway port, we should > * remove its peer, if that one is local. > */ > - pb = get_l3gw_peer_lport(pb, b_ctx_in); > + pb = lport_get_l3gw_peer(pb, b_ctx_in->sbrec_port_binding_by_name); > if (pb) { > ld = get_local_datapath(b_ctx_out->local_datapaths, > pb->datapath->tunnel_key); > @@ -2598,7 +2358,10 @@ delete_done: > * */ > const struct sbrec_port_binding *peer; > struct local_datapath *peer_ld = NULL; > - peer = get_peer_lport(pb, b_ctx_in); > + peer = > + lport_get_peer(pb, > + b_ctx_in->sbrec_port_binding_by_name); > + > if (peer) { > peer_ld = > get_local_datapath(b_ctx_out->local_datapaths, > diff --git a/controller/binding.h b/controller/binding.h > index 77197e742..b1717bd2b 100644 > --- a/controller/binding.h > +++ b/controller/binding.h > @@ -121,19 +121,6 @@ void local_binding_set_up(struct shash *local_bindings, const char *pb_name, > void local_binding_set_down(struct shash *local_bindings, const char *pb_name, > bool sb_readonly, bool ovs_readonly); > > -/* Represents a tracked binding logical port. */ > -struct tracked_binding_lport { > - const struct sbrec_port_binding *pb; > -}; > - > -/* Represent a tracked binding datapath. */ > -struct tracked_binding_datapath { > - struct hmap_node node; > - const struct sbrec_datapath_binding *dp; > - bool is_new; > - struct shash lports; /* shash of struct tracked_binding_lport. */ > -}; > - > void binding_register_ovs_idl(struct ovsdb_idl *); > void binding_run(struct binding_ctx_in *, struct binding_ctx_out *); > bool binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, > diff --git a/controller/ldata.c b/controller/ldata.c > new file mode 100644 > index 000000000..a6df9b1da > --- /dev/null > +++ b/controller/ldata.c > @@ -0,0 +1,368 @@ > +/* Copyright (c) 2021, Red Hat, 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> > + > +/* OVS includes. */ > +#include "include/openvswitch/json.h" > +#include "lib/hmapx.h" > +#include "lib/util.h" > +#include "openvswitch/vlog.h" > + > +/* OVN includes. */ > +#include "ldata.h" > +#include "lport.h" > +#include "lib/ovn-util.h" > +#include "lib/ovn-sb-idl.h" > + > +VLOG_DEFINE_THIS_MODULE(ldata); > + > +static struct local_datapath *local_datapath_add__( > + struct hmap *local_datapaths, > + const struct sbrec_datapath_binding *, > + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, > + struct ovsdb_idl_index *sbrec_port_binding_by_name, > + int depth, > + void (*datapath_added)(struct local_datapath *, > + void *aux), > + void *aux); > + > +static struct tracked_datapath *tracked_datapath_create( > + const struct sbrec_datapath_binding *dp, > + enum en_tracked_resource_type tracked_type, > + struct hmap *tracked_datapaths); > + > +struct local_datapath * > +get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key) > +{ > + struct hmap_node *node = hmap_first_with_hash(local_datapaths, tunnel_key); > + return (node > + ? CONTAINER_OF(node, struct local_datapath, hmap_node) > + : NULL); > +} > + > +struct local_datapath * > +local_datapath_alloc(const struct sbrec_datapath_binding *dp) > +{ > + struct local_datapath *ld = xzalloc(sizeof *ld); > + ld->datapath = dp; > + ld->is_switch = datapath_is_switch(dp); > + shash_init(&ld->external_ports); > + return ld; > +} > + > +void > +local_datapaths_destroy(struct hmap *local_datapaths) > +{ > + struct local_datapath *ld; > + HMAP_FOR_EACH_POP (ld, hmap_node, local_datapaths) { > + local_datapath_destroy(ld); > + } > + > + hmap_destroy(local_datapaths); > +} > + > +void > +local_datapath_destroy(struct local_datapath *ld) > +{ > + free(ld->peer_ports); > + shash_destroy(&ld->external_ports); > + free(ld); > +} > + > +void > +local_datapath_add(struct hmap *local_datapaths, > + const struct sbrec_datapath_binding *dp, > + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, > + struct ovsdb_idl_index *sbrec_port_binding_by_name, > + void (*datapath_added_cb)( > + struct local_datapath *ld, > + void *aux), > + void *aux) > +{ > + local_datapath_add__(local_datapaths, dp, sbrec_datapath_binding_by_key, > + sbrec_port_binding_by_datapath, > + sbrec_port_binding_by_name, 0, > + datapath_added_cb, aux); > +} > + > +void > +local_datapath_add_peer_port( > + const struct sbrec_port_binding *pb, > + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, > + struct ovsdb_idl_index *sbrec_port_binding_by_name, > + struct local_datapath *ld, > + struct hmap *local_datapaths, > + void (*datapath_added_cb)( > + struct local_datapath *ld, > + void *aux), > + void *aux) > +{ > + const struct sbrec_port_binding *peer; > + peer = lport_get_peer(pb, sbrec_port_binding_by_name); > + > + if (!peer) { > + return; > + } > + > + bool present = false; > + for (size_t i = 0; i < ld->n_peer_ports; i++) { > + if (ld->peer_ports[i].local == pb) { > + present = true; > + break; > + } > + } > + > + if (!present) { > + ld->n_peer_ports++; > + if (ld->n_peer_ports > ld->n_allocated_peer_ports) { > + ld->peer_ports = > + x2nrealloc(ld->peer_ports, > + &ld->n_allocated_peer_ports, > + sizeof *ld->peer_ports); > + } > + ld->peer_ports[ld->n_peer_ports - 1].local = pb; > + ld->peer_ports[ld->n_peer_ports - 1].remote = peer; > + } > + > + struct local_datapath *peer_ld = > + get_local_datapath(local_datapaths, > + peer->datapath->tunnel_key); > + if (!peer_ld) { > + local_datapath_add__(local_datapaths, peer->datapath, > + sbrec_datapath_binding_by_key, > + sbrec_port_binding_by_datapath, > + sbrec_port_binding_by_name, 1, > + datapath_added_cb, aux); > + return; > + } > + > + for (size_t i = 0; i < peer_ld->n_peer_ports; i++) { > + if (peer_ld->peer_ports[i].local == peer) { > + return; > + } > + } > + > + peer_ld->n_peer_ports++; > + if (peer_ld->n_peer_ports > peer_ld->n_allocated_peer_ports) { > + peer_ld->peer_ports = > + x2nrealloc(peer_ld->peer_ports, > + &peer_ld->n_allocated_peer_ports, > + sizeof *peer_ld->peer_ports); > + } > + peer_ld->peer_ports[peer_ld->n_peer_ports - 1].local = peer; > + peer_ld->peer_ports[peer_ld->n_peer_ports - 1].remote = pb; > +} > + > +void > +local_datapath_remove_peer_port(const struct sbrec_port_binding *pb, > + struct local_datapath *ld, > + struct hmap *local_datapaths) > +{ > + size_t i = 0; > + for (i = 0; i < ld->n_peer_ports; i++) { > + if (ld->peer_ports[i].local == pb) { > + break; > + } > + } > + > + if (i == ld->n_peer_ports) { > + return; > + } > + > + const struct sbrec_port_binding *peer = ld->peer_ports[i].remote; > + > + /* Possible improvement: We can shrink the allocated peer ports > + * if (ld->n_peer_ports < ld->n_allocated_peer_ports / 2). > + */ > + ld->peer_ports[i].local = ld->peer_ports[ld->n_peer_ports - 1].local; > + ld->peer_ports[i].remote = ld->peer_ports[ld->n_peer_ports - 1].remote; > + ld->n_peer_ports--; > + > + struct local_datapath *peer_ld = > + get_local_datapath(local_datapaths, peer->datapath->tunnel_key); > + if (peer_ld) { > + /* Remove the peer port from the peer datapath. The peer > + * datapath also tries to remove its peer lport, but that would > + * be no-op. */ > + local_datapath_remove_peer_port(peer, peer_ld, local_datapaths); > + } > +} > + > +/* track datapath functions. */ > +struct tracked_datapath * > +tracked_datapath_add(const struct sbrec_datapath_binding *dp, > + enum en_tracked_resource_type tracked_type, > + struct hmap *tracked_datapaths) > +{ > + struct tracked_datapath *t_dp = > + tracked_datapath_find(tracked_datapaths, dp); > + if (!t_dp) { > + t_dp = tracked_datapath_create(dp, tracked_type, tracked_datapaths); > + } else { > + t_dp->tracked_type = tracked_type; > + } > + > + return t_dp; > +} > + > +struct tracked_datapath * > +tracked_datapath_find(struct hmap *tracked_datapaths, > + const struct sbrec_datapath_binding *dp) > +{ > + struct tracked_datapath *t_dp; > + size_t hash = uuid_hash(&dp->header_.uuid); > + HMAP_FOR_EACH_WITH_HASH (t_dp, node, hash, tracked_datapaths) { > + if (uuid_equals(&t_dp->dp->header_.uuid, &dp->header_.uuid)) { > + return t_dp; > + } > + } > + > + return NULL; > +} > + > +void > +tracked_datapath_lport_add(const struct sbrec_port_binding *pb, > + enum en_tracked_resource_type tracked_type, > + struct hmap *tracked_datapaths) > +{ > + struct tracked_datapath *tracked_dp = > + tracked_datapath_find(tracked_datapaths, pb->datapath); > + if (!tracked_dp) { > + tracked_dp = tracked_datapath_create(pb->datapath, > + TRACKED_RESOURCE_UPDATED, > + tracked_datapaths); > + } > + > + /* Check if the lport is already present or not. > + * If it is already present, then just update the 'pb' field. */ > + struct tracked_lport *lport = > + shash_find_data(&tracked_dp->lports, pb->logical_port); > + > + if (!lport) { > + lport = xmalloc(sizeof *lport); > + shash_add(&tracked_dp->lports, pb->logical_port, lport); > + } > + > + lport->pb = pb; > + lport->tracked_type = tracked_type; > +} > + > +void > +tracked_datapaths_destroy(struct hmap *tracked_datapaths) > +{ > + struct tracked_datapath *t_dp; > + HMAP_FOR_EACH_POP (t_dp, node, tracked_datapaths) { > + shash_destroy_free_data(&t_dp->lports); > + free(t_dp); > + } > + > + hmap_destroy(tracked_datapaths); > +} > + > +/* static functions. */ > +static struct local_datapath * > +local_datapath_add__(struct hmap *local_datapaths, > + const struct sbrec_datapath_binding *dp, > + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, > + struct ovsdb_idl_index *sbrec_port_binding_by_name, > + int depth, > + void (*datapath_added_cb)( > + struct local_datapath *ld, > + void *aux), > + void *aux) > +{ > + uint32_t dp_key = dp->tunnel_key; > + struct local_datapath *ld = get_local_datapath(local_datapaths, dp_key); > + if (ld) { > + return ld; This changes the original behavior that when the ld is found it updates the has_local_l3gateway before returning. Would this cause a problem? > + } > + > + ld = local_datapath_alloc(dp); > + hmap_insert(local_datapaths, &ld->hmap_node, dp_key); > + ld->datapath = dp; > + > + if (datapath_added_cb) { > + datapath_added_cb(ld, aux); > + } > + > + if (depth >= 100) { > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); > + VLOG_WARN_RL(&rl, "datapaths nested too deep"); > + return ld; > + } > + > + struct sbrec_port_binding *target = > + sbrec_port_binding_index_init_row(sbrec_port_binding_by_datapath); > + sbrec_port_binding_index_set_datapath(target, dp); > + > + const struct sbrec_port_binding *pb; > + SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target, > + sbrec_port_binding_by_datapath) { > + if (!strcmp(pb->type, "patch") || !strcmp(pb->type, "l3gateway")) { > + const char *peer_name = smap_get(&pb->options, "peer"); > + if (peer_name) { > + const struct sbrec_port_binding *peer; > + > + peer = lport_lookup_by_name(sbrec_port_binding_by_name, > + peer_name); > + > + if (peer && peer->datapath) { > + if (!strcmp(pb->type, "patch")) { > + /* Add the datapath to local datapath only for patch > + * ports. For l3gateway ports, since gateway router > + * resides on one chassis, we don't need to add. > + * Otherwise, all other chassis might create patch > + * ports between br-int and the provider bridge. */ > + local_datapath_add__(local_datapaths, peer->datapath, > + sbrec_datapath_binding_by_key, > + sbrec_port_binding_by_datapath, > + sbrec_port_binding_by_name, > + depth + 1, datapath_added_cb, > + aux); > + } > + ld->n_peer_ports++; > + if (ld->n_peer_ports > ld->n_allocated_peer_ports) { > + ld->peer_ports = > + x2nrealloc(ld->peer_ports, > + &ld->n_allocated_peer_ports, > + sizeof *ld->peer_ports); > + } > + ld->peer_ports[ld->n_peer_ports - 1].local = pb; > + ld->peer_ports[ld->n_peer_ports - 1].remote = peer; > + } > + } > + } > + } > + sbrec_port_binding_index_destroy_row(target); > + return ld; > +} > + > +static struct tracked_datapath * > +tracked_datapath_create(const struct sbrec_datapath_binding *dp, > + enum en_tracked_resource_type tracked_type, > + struct hmap *tracked_datapaths) > +{ > + struct tracked_datapath *t_dp = xzalloc(sizeof *t_dp); > + t_dp->dp = dp; > + t_dp->tracked_type = tracked_type; > + shash_init(&t_dp->lports); > + hmap_insert(tracked_datapaths, &t_dp->node, uuid_hash(&dp->header_.uuid)); > + return t_dp; > +} > diff --git a/controller/ldata.h b/controller/ldata.h > new file mode 100644 > index 000000000..16ad43c8f > --- /dev/null > +++ b/controller/ldata.h > @@ -0,0 +1,120 @@ > +/* Copyright (c) 2021, Red Hat, 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 LDATA_H > +#define LDATA_H 1 > + > +/* OVS includes. */ > +#include "include/openvswitch/shash.h" > +#include "lib/smap.h" > + > +struct sbrec_datapath_binding; > +struct sbrec_port_binding; > +struct ovsdb_idl_index; > + > +/* A logical datapath that has some relevance to this hypervisor. A logical > + * datapath D is relevant to hypervisor H if: > + * > + * - Some VIF or l2gateway or l3gateway port in D is located on H. > + * > + * - D is reachable over a series of hops across patch ports, starting from > + * a datapath relevant to H. > + * > + * The 'hmap_node''s hash value is 'datapath->tunnel_key'. */ > +struct local_datapath { > + struct hmap_node hmap_node; > + const struct sbrec_datapath_binding *datapath; > + bool is_switch; > + > + /* The localnet port in this datapath, if any (at most one is allowed). */ > + const struct sbrec_port_binding *localnet_port; > + > + /* True if this datapath contains an l3gateway port located on this > + * hypervisor. */ > + bool has_local_l3gateway; > + > + struct { > + const struct sbrec_port_binding *local; > + const struct sbrec_port_binding *remote; > + } *peer_ports; > + > + size_t n_peer_ports; > + size_t n_allocated_peer_ports; > + > + struct shash external_ports; > +}; > + > +struct local_datapath *local_datapath_alloc( > + const struct sbrec_datapath_binding *); > +struct local_datapath *get_local_datapath(const struct hmap *, > + uint32_t tunnel_key); > +void local_datapath_add(struct hmap *local_datapaths, > + const struct sbrec_datapath_binding *, > + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, > + struct ovsdb_idl_index *sbrec_port_binding_by_name, > + void (*datapath_added)(struct local_datapath *, > + void *aux), > + void *aux); > + > +void local_datapaths_destroy(struct hmap *local_datapaths); > +void local_datapath_destroy(struct local_datapath *ld); > +void local_datapath_add_peer_port( > + const struct sbrec_port_binding *pb, > + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, > + struct ovsdb_idl_index *sbrec_port_binding_by_name, > + struct local_datapath *ld, > + struct hmap *local_datapaths, > + void (*datapath_added_cb)( > + struct local_datapath *ld, > + void *aux), > + void *aux); > + > +void local_datapath_remove_peer_port(const struct sbrec_port_binding *pb, > + struct local_datapath *ld, > + struct hmap *local_datapaths); > + > +enum en_tracked_resource_type { > + TRACKED_RESOURCE_NEW, > + TRACKED_RESOURCE_REMOVED, > + TRACKED_RESOURCE_UPDATED > +}; > + > +/* Represents a tracked logical port. */ > +struct tracked_lport { > + const struct sbrec_port_binding *pb; > + enum en_tracked_resource_type tracked_type; > +}; > + > +/* Represent a tracked datapath. */ > +struct tracked_datapath { > + struct hmap_node node; > + const struct sbrec_datapath_binding *dp; > + enum en_tracked_resource_type tracked_type; > + struct shash lports; /* shash of struct tracked_binding_lport. */ > +}; > + > +struct tracked_datapath * tracked_datapath_add( > + const struct sbrec_datapath_binding *, enum en_tracked_resource_type, > + struct hmap *tracked_datapaths); > +struct tracked_datapath *tracked_datapath_find( > + struct hmap *tracked_datapaths, const struct sbrec_datapath_binding *); > +void tracked_datapath_lport_add(const struct sbrec_port_binding *, > + enum en_tracked_resource_type, > + struct hmap *tracked_datapaths); > +void tracked_datapaths_destroy(struct hmap *tracked_datapaths); > + > +#endif /* controller/ldata.h */ > diff --git a/controller/lflow.c b/controller/lflow.c > index c58c4f25c..d1f32077b 100644 > --- a/controller/lflow.c > +++ b/controller/lflow.c > @@ -17,6 +17,7 @@ > #include "lflow.h" > #include "coverage.h" > #include "ha-chassis.h" > +#include "ldata.h" > #include "lflow-cache.h" > #include "lport.h" > #include "ofctrl.h" > diff --git a/controller/lport.c b/controller/lport.c > index 478fcfd82..25b4ef200 100644 > --- a/controller/lport.c > +++ b/controller/lport.c > @@ -23,6 +23,10 @@ > #include "lib/ovn-sb-idl.h" > VLOG_DEFINE_THIS_MODULE(lport); > > +static const struct sbrec_port_binding *get_peer_lport( > + const struct sbrec_port_binding *pb, > + struct ovsdb_idl_index *sbrec_port_binding_by_name); > + > const struct sbrec_port_binding * > lport_lookup_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, > const char *name) > @@ -84,6 +88,26 @@ lport_is_chassis_resident(struct ovsdb_idl_index *sbrec_port_binding_by_name, > } > } > > +const struct sbrec_port_binding * > +lport_get_peer(const struct sbrec_port_binding *pb, > + struct ovsdb_idl_index *sbrec_port_binding_by_name) > +{ > + if (strcmp(pb->type, "patch")) { > + return NULL; > + } > + return get_peer_lport(pb, sbrec_port_binding_by_name); > +} > + > +const struct sbrec_port_binding * > +lport_get_l3gw_peer(const struct sbrec_port_binding *pb, > + struct ovsdb_idl_index *sbrec_port_binding_by_name) > +{ > + if (strcmp(pb->type, "l3gateway")) { > + return NULL; > + } > + return get_peer_lport(pb, sbrec_port_binding_by_name); > +} > + > const struct sbrec_datapath_binding * > datapath_lookup_by_key(struct ovsdb_idl_index *sbrec_datapath_binding_by_key, > uint64_t dp_key) > @@ -120,3 +144,19 @@ mcgroup_lookup_by_dp_name( > > return retval; > } > + > +static const struct sbrec_port_binding * > +get_peer_lport(const struct sbrec_port_binding *pb, > + struct ovsdb_idl_index *sbrec_port_binding_by_name) > +{ > + const char *peer_name = smap_get(&pb->options, "peer"); > + > + if (!peer_name) { > + return NULL; > + } > + > + const struct sbrec_port_binding *peer; > + peer = lport_lookup_by_name(sbrec_port_binding_by_name, > + peer_name); > + return (peer && peer->datapath) ? peer : NULL; > +} > diff --git a/controller/lport.h b/controller/lport.h > index 345efc184..43b3d714d 100644 > --- a/controller/lport.h > +++ b/controller/lport.h > @@ -54,5 +54,10 @@ lport_is_chassis_resident(struct ovsdb_idl_index *sbrec_port_binding_by_name, > const struct sbrec_chassis *chassis, > const struct sset *active_tunnels, > const char *port_name); > - > +const struct sbrec_port_binding *lport_get_peer( > + const struct sbrec_port_binding *, > + struct ovsdb_idl_index *sbrec_port_binding_by_name); > +const struct sbrec_port_binding *lport_get_l3gw_peer( > + const struct sbrec_port_binding *, > + struct ovsdb_idl_index *sbrec_port_binding_by_name); > #endif /* controller/lport.h */ > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > index 2418c301b..8f620e4ad 100644 > --- a/controller/ovn-controller.c > +++ b/controller/ovn-controller.c > @@ -39,6 +39,7 @@ > #include "lflow.h" > #include "lflow-cache.h" > #include "lib/vswitch-idl.h" > +#include "ldata.h" > #include "lport.h" > #include "memory.h" > #include "ofctrl.h" > @@ -131,15 +132,6 @@ struct pending_pkt { > /* Registered ofctrl seqno type for nb_cfg propagation. */ > static size_t ofctrl_seq_type_nb_cfg; > > -struct local_datapath * > -get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key) > -{ > - struct hmap_node *node = hmap_first_with_hash(local_datapaths, tunnel_key); > - return (node > - ? CONTAINER_OF(node, struct local_datapath, hmap_node) > - : NULL); > -} > - > uint32_t > get_tunnel_type(const char *name) > { > @@ -1067,8 +1059,8 @@ struct ed_type_runtime_data { > * > * ------------------------------------------------------------------------ > * | | This is a hmap of | > - * | | 'struct tracked_binding_datapath' defined in | > - * | | binding.h. Runtime data handlers for OVS | > + * | | 'struct tracked_datapath' defined in | > + * | | ldata.h. Runtime data handlers for OVS | > * | | Interface and Port Binding changes store the | > * | @tracked_dp_bindings | changed datapaths (datapaths added/removed from | > * | | local_datapaths) and changed port bindings | nit: Some alignment problem of the right side border of the above table. Thanks, Han > @@ -1126,7 +1118,7 @@ en_runtime_data_clear_tracked_data(void *data_) > { > struct ed_type_runtime_data *data = data_; > > - binding_tracked_dp_destroy(&data->tracked_dp_bindings); > + tracked_datapaths_destroy(&data->tracked_dp_bindings); > hmap_init(&data->tracked_dp_bindings); > data->local_lports_changed = false; > data->tracked = false; > @@ -1164,15 +1156,7 @@ en_runtime_data_cleanup(void *data) > sset_destroy(&rt_data->active_tunnels); > sset_destroy(&rt_data->egress_ifaces); > smap_destroy(&rt_data->local_iface_ids); > - struct local_datapath *cur_node, *next_node; > - HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, > - &rt_data->local_datapaths) { > - free(cur_node->peer_ports); > - shash_destroy(&cur_node->external_ports); > - hmap_remove(&rt_data->local_datapaths, &cur_node->hmap_node); > - free(cur_node); > - } > - hmap_destroy(&rt_data->local_datapaths); > + local_datapaths_destroy(&rt_data->local_datapaths); > shash_destroy_free_data(&rt_data->local_active_ports_ipv6_pd); > shash_destroy_free_data(&rt_data->local_active_ports_ras); > local_binding_data_destroy(&rt_data->lbinding_data); > @@ -1284,14 +1268,7 @@ en_runtime_data_run(struct engine_node *node, void *data) > /* don't cleanup since there is no data yet */ > first_run = false; > } else { > - struct local_datapath *cur_node, *next_node; > - HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, local_datapaths) { > - free(cur_node->peer_ports); > - shash_destroy(&cur_node->external_ports); > - hmap_remove(local_datapaths, &cur_node->hmap_node); > - free(cur_node); > - } > - hmap_clear(local_datapaths); > + local_datapaths_destroy(local_datapaths); > shash_clear_free_data(local_active_ipv6_pd); > shash_clear_free_data(local_active_ras); > local_binding_data_destroy(&rt_data->lbinding_data); > @@ -1300,6 +1277,7 @@ en_runtime_data_run(struct engine_node *node, void *data) > sset_destroy(active_tunnels); > sset_destroy(&rt_data->egress_ifaces); > smap_destroy(&rt_data->local_iface_ids); > + hmap_init(local_datapaths); > sset_init(local_lports); > related_lports_init(&rt_data->related_lports); > sset_init(active_tunnels); > @@ -1741,12 +1719,12 @@ port_groups_runtime_data_handler(struct engine_node *node, void *data) > pg_sb->name); > ovs_assert(pg_lports); > > - struct tracked_binding_datapath *tdp; > + struct tracked_datapath *tdp; > bool need_update = false; > HMAP_FOR_EACH (tdp, node, &rt_data->tracked_dp_bindings) { > struct shash_node *shash_node; > SHASH_FOR_EACH (shash_node, &tdp->lports) { > - struct tracked_binding_lport *lport = shash_node->data; > + struct tracked_lport *lport = shash_node->data; > if (sset_contains(pg_lports, lport->pb->logical_port)) { > /* At least one local port-binding change is related to the > * port_group, so the port_group_cs_local needs update. */ > @@ -1899,9 +1877,9 @@ ct_zones_runtime_data_handler(struct engine_node *node, void *data OVS_UNUSED) > } > > struct hmap *tracked_dp_bindings = &rt_data->tracked_dp_bindings; > - struct tracked_binding_datapath *tdp; > + struct tracked_datapath *tdp; > HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) { > - if (tdp->is_new) { > + if (tdp->tracked_type == TRACKED_RESOURCE_NEW) { > /* A new datapath has been added. Fall back to full recompute. */ > return false; > } > @@ -2423,9 +2401,9 @@ lflow_output_runtime_data_handler(struct engine_node *node, > struct ed_type_lflow_output *fo = data; > init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out); > > - struct tracked_binding_datapath *tdp; > + struct tracked_datapath *tdp; > HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) { > - if (tdp->is_new) { > + if (tdp->tracked_type == TRACKED_RESOURCE_NEW) { > if (!lflow_add_flows_for_datapath(tdp->dp, &l_ctx_in, > &l_ctx_out)) { > return false; > @@ -2433,7 +2411,7 @@ lflow_output_runtime_data_handler(struct engine_node *node, > } else { > struct shash_node *shash_node; > SHASH_FOR_EACH (shash_node, &tdp->lports) { > - struct tracked_binding_lport *lport = shash_node->data; > + struct tracked_lport *lport = shash_node->data; > if (!lflow_handle_flows_for_lport(lport->pb, &l_ctx_in, > &l_ctx_out)) { > return false; > diff --git a/controller/ovn-controller.h b/controller/ovn-controller.h > index b864ed0fa..578588305 100644 > --- a/controller/ovn-controller.h > +++ b/controller/ovn-controller.h > @@ -40,40 +40,6 @@ struct ct_zone_pending_entry { > enum ct_zone_pending_state state; > }; > > -/* A logical datapath that has some relevance to this hypervisor. A logical > - * datapath D is relevant to hypervisor H if: > - * > - * - Some VIF or l2gateway or l3gateway port in D is located on H. > - * > - * - D is reachable over a series of hops across patch ports, starting from > - * a datapath relevant to H. > - * > - * The 'hmap_node''s hash value is 'datapath->tunnel_key'. */ > -struct local_datapath { > - struct hmap_node hmap_node; > - const struct sbrec_datapath_binding *datapath; > - > - /* The localnet port in this datapath, if any (at most one is allowed). */ > - const struct sbrec_port_binding *localnet_port; > - > - /* True if this datapath contains an l3gateway port located on this > - * hypervisor. */ > - bool has_local_l3gateway; > - > - struct { > - const struct sbrec_port_binding *local; > - const struct sbrec_port_binding *remote; > - } *peer_ports; > - > - size_t n_peer_ports; > - size_t n_allocated_peer_ports; > - > - struct shash external_ports; > -}; > - > -struct local_datapath *get_local_datapath(const struct hmap *, > - uint32_t tunnel_key); > - > const struct ovsrec_bridge *get_bridge(const struct ovsrec_bridge_table *, > const char *br_name); > > diff --git a/controller/patch.c b/controller/patch.c > index e54b56354..99a095c57 100644 > --- a/controller/patch.c > +++ b/controller/patch.c > @@ -18,6 +18,7 @@ > #include "patch.h" > > #include "hash.h" > +#include "ldata.h" > #include "lflow.h" > #include "lib/vswitch-idl.h" > #include "lport.h" > diff --git a/controller/physical.c b/controller/physical.c > index 483a5a49b..b244ff1c2 100644 > --- a/controller/physical.c > +++ b/controller/physical.c > @@ -20,6 +20,7 @@ > #include "encaps.h" > #include "flow.h" > #include "ha-chassis.h" > +#include "ldata.h" > #include "lflow.h" > #include "lport.h" > #include "chassis.h" > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > index 8e4c4d18c..e2d892aab 100644 > --- a/controller/pinctrl.c > +++ b/controller/pinctrl.c > @@ -25,6 +25,7 @@ > #include "encaps.h" > #include "flow.h" > #include "ha-chassis.h" > +#include "ldata.h" > #include "lport.h" > #include "mac-learn.h" > #include "nx-match.h" > -- > 2.31.1 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
On Mon, Jul 26, 2021 at 6:47 PM Han Zhou <zhouhan@gmail.com> wrote: > > > > On Fri, Jul 16, 2021 at 4:45 AM <numans@ovn.org> wrote: > > > > From: Numan Siddique <numans@ovn.org> > > > > This would uncomplicate the binding.c code a bit. The tracking > > data and the related functions are also moved to the file - ldata.h. > > This would help in an upcoming patch. > > Hi Numan, Sorry that one more comment regarding the new module "ldata" naming. It is a little confusing to me. Maybe it is supposed to take care of local bindings? Would local_binding be better? "l" can mean logical, local or something else. Thanks, Han
On Mon, Jul 26, 2021 at 10:04 PM Han Zhou <zhouhan@gmail.com> wrote: > > On Mon, Jul 26, 2021 at 6:47 PM Han Zhou <zhouhan@gmail.com> wrote: > > > > > > > > On Fri, Jul 16, 2021 at 4:45 AM <numans@ovn.org> wrote: > > > > > > From: Numan Siddique <numans@ovn.org> > > > > > > This would uncomplicate the binding.c code a bit. The tracking > > > data and the related functions are also moved to the file - ldata.h. > > > This would help in an upcoming patch. > > > > > Hi Numan, > > Sorry that one more comment regarding the new module "ldata" naming. It is > a little confusing to me. Maybe it is supposed to take care of local > bindings? Would local_binding be better? "l" can mean logical, local or > something else. Hi Han, I supposed to mean "local data". I thought naming "local_binding.c" or "lbinding.c" would be confusing since we already have binding.c My idea was for this file to be used for maintaining local data and not just binding. Does "local_data.c" seem fine to you ? Regarding your comment on "has_local_l3gateway" in the previous reply, you're right. I'll handle that in v2. Thanks for the reviews. Numan > > Thanks, > Han > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
On Mon, Jul 26, 2021 at 7:39 PM Numan Siddique <numans@ovn.org> wrote: > > On Mon, Jul 26, 2021 at 10:04 PM Han Zhou <zhouhan@gmail.com> wrote: > > > > On Mon, Jul 26, 2021 at 6:47 PM Han Zhou <zhouhan@gmail.com> wrote: > > > > > > > > > > > > On Fri, Jul 16, 2021 at 4:45 AM <numans@ovn.org> wrote: > > > > > > > > From: Numan Siddique <numans@ovn.org> > > > > > > > > This would uncomplicate the binding.c code a bit. The tracking > > > > data and the related functions are also moved to the file - ldata.h. > > > > This would help in an upcoming patch. > > > > > > > > Hi Numan, > > > > Sorry that one more comment regarding the new module "ldata" naming. It is > > a little confusing to me. Maybe it is supposed to take care of local > > bindings? Would local_binding be better? "l" can mean logical, local or > > something else. > > Hi Han, > > I supposed to mean "local data". I thought naming "local_binding.c" > or "lbinding.c" would > be confusing since we already have binding.c > > My idea was for this file to be used for maintaining local data and > not just binding. > > Does "local_data.c" seem fine to you ? > To my understanding local data includes local port-bindings and local datapath-bindings, which is local data of the original binding.c module, so I thought local_binding.c should be clear. I am also fine with local_data.c. Thanks, Han > > Regarding your comment on "has_local_l3gateway" in the previous reply, > you're right. > I'll handle that in v2. > > Thanks for the reviews. > > Numan > > > > > > Thanks, > > Han > > _______________________________________________ > > dev mailing list > > dev@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > >
diff --git a/controller/automake.mk b/controller/automake.mk index 2f6c50890..a3c5c6af5 100644 --- a/controller/automake.mk +++ b/controller/automake.mk @@ -33,7 +33,9 @@ controller_ovn_controller_SOURCES = \ controller/physical.c \ controller/physical.h \ controller/mac-learn.c \ - controller/mac-learn.h + controller/mac-learn.h \ + controller/ldata.c \ + controller/ldata.h controller_ovn_controller_LDADD = lib/libovn.la $(OVS_LIBDIR)/libopenvswitch.la man_MANS += controller/ovn-controller.8 diff --git a/controller/binding.c b/controller/binding.c index d50f3affa..e68546ca9 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -14,13 +14,8 @@ */ #include <config.h> -#include "binding.h" -#include "ha-chassis.h" -#include "if-status.h" -#include "lflow.h" -#include "lport.h" -#include "patch.h" +/* OVS includes. */ #include "lib/bitmap.h" #include "openvswitch/poll-loop.h" #include "lib/sset.h" @@ -29,9 +24,18 @@ #include "lib/vswitch-idl.h" #include "openvswitch/hmap.h" #include "openvswitch/vlog.h" + +/* OVN includes. */ +#include "binding.h" +#include "ha-chassis.h" +#include "if-status.h" +#include "ldata.h" +#include "lflow.h" #include "lib/chassis-index.h" #include "lib/ovn-sb-idl.h" +#include "lport.h" #include "ovn-controller.h" +#include "patch.h" VLOG_DEFINE_THIS_MODULE(binding); @@ -76,106 +80,27 @@ binding_register_ovs_idl(struct ovsdb_idl *ovs_idl) ovsdb_idl_add_column(ovs_idl, &ovsrec_qos_col_type); } -static struct tracked_binding_datapath *tracked_binding_datapath_create( - const struct sbrec_datapath_binding *, - bool is_new, struct hmap *tracked_dps); -static struct tracked_binding_datapath *tracked_binding_datapath_find( - struct hmap *, const struct sbrec_datapath_binding *); -static void tracked_binding_datapath_lport_add( - const struct sbrec_port_binding *, struct hmap *tracked_datapaths); static void update_lport_tracking(const struct sbrec_port_binding *pb, - struct hmap *tracked_dp_bindings); - -static void -add_local_datapath__(struct ovsdb_idl_index *sbrec_datapath_binding_by_key, - struct ovsdb_idl_index *sbrec_port_binding_by_datapath, - struct ovsdb_idl_index *sbrec_port_binding_by_name, - const struct sbrec_datapath_binding *datapath, - bool has_local_l3gateway, int depth, - struct hmap *local_datapaths, - struct hmap *tracked_datapaths) -{ - uint32_t dp_key = datapath->tunnel_key; - struct local_datapath *ld = get_local_datapath(local_datapaths, dp_key); - if (ld) { - if (has_local_l3gateway) { - ld->has_local_l3gateway = true; - } - return; - } + struct hmap *tracked_dp_bindings, + bool claimed); - ld = xzalloc(sizeof *ld); - hmap_insert(local_datapaths, &ld->hmap_node, dp_key); - ld->datapath = datapath; - ld->localnet_port = NULL; - shash_init(&ld->external_ports); - ld->has_local_l3gateway = has_local_l3gateway; - - if (tracked_datapaths) { - struct tracked_binding_datapath *tdp = - tracked_binding_datapath_find(tracked_datapaths, datapath); - if (!tdp) { - tracked_binding_datapath_create(datapath, true, tracked_datapaths); - } else { - /* Its possible that there is already an entry in tracked datapaths - * for this 'datapath'. tracked_binding_datapath_lport_add() may - * have created it. Since the 'datapath' is added to the - * local datapaths, set 'tdp->is_new' to true so that the flows - * for this datapath are programmed properly. - * */ - tdp->is_new = true; - } - } +struct local_datpath_added_aux { + bool has_local_l3gateway; + struct hmap *tracked_datapaths; +}; - if (depth >= 100) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_WARN_RL(&rl, "datapaths nested too deep"); - return; +/* This function is called by local_datapath_add() if a new local_datapath + * is created. */ +static void +local_datapath_added(struct local_datapath *ld, void *aux) +{ + struct local_datpath_added_aux *aux_ = aux; + if (aux_->tracked_datapaths) { + tracked_datapath_add(ld->datapath, TRACKED_RESOURCE_NEW, + aux_->tracked_datapaths); } - struct sbrec_port_binding *target = - sbrec_port_binding_index_init_row(sbrec_port_binding_by_datapath); - sbrec_port_binding_index_set_datapath(target, datapath); - - const struct sbrec_port_binding *pb; - SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target, - sbrec_port_binding_by_datapath) { - if (!strcmp(pb->type, "patch") || !strcmp(pb->type, "l3gateway")) { - const char *peer_name = smap_get(&pb->options, "peer"); - if (peer_name) { - const struct sbrec_port_binding *peer; - - peer = lport_lookup_by_name(sbrec_port_binding_by_name, - peer_name); - - if (peer && peer->datapath) { - if (!strcmp(pb->type, "patch")) { - /* Add the datapath to local datapath only for patch - * ports. For l3gateway ports, since gateway router - * resides on one chassis, we don't need to add. - * Otherwise, all other chassis might create patch - * ports between br-int and the provider bridge. */ - add_local_datapath__(sbrec_datapath_binding_by_key, - sbrec_port_binding_by_datapath, - sbrec_port_binding_by_name, - peer->datapath, false, - depth + 1, local_datapaths, - tracked_datapaths); - } - ld->n_peer_ports++; - if (ld->n_peer_ports > ld->n_allocated_peer_ports) { - ld->peer_ports = - x2nrealloc(ld->peer_ports, - &ld->n_allocated_peer_ports, - sizeof *ld->peer_ports); - } - ld->peer_ports[ld->n_peer_ports - 1].local = pb; - ld->peer_ports[ld->n_peer_ports - 1].remote = peer; - } - } - } - } - sbrec_port_binding_index_destroy_row(target); + ld->has_local_l3gateway = aux_->has_local_l3gateway; } static void @@ -186,11 +111,17 @@ add_local_datapath(struct ovsdb_idl_index *sbrec_datapath_binding_by_key, bool has_local_l3gateway, struct hmap *local_datapaths, struct hmap *tracked_datapaths) { - add_local_datapath__(sbrec_datapath_binding_by_key, - sbrec_port_binding_by_datapath, - sbrec_port_binding_by_name, - datapath, has_local_l3gateway, 0, local_datapaths, - tracked_datapaths); + struct local_datpath_added_aux aux = { + .has_local_l3gateway = has_local_l3gateway, + .tracked_datapaths = tracked_datapaths, + }; + + local_datapath_add(local_datapaths, datapath, + sbrec_datapath_binding_by_key, + sbrec_port_binding_by_datapath, + sbrec_port_binding_by_name, + local_datapath_added, + &aux); } static void @@ -559,7 +490,8 @@ update_related_lport(const struct sbrec_port_binding *pb, if (b_ctx->tracked_dp_bindings) { /* Add the 'pb' to the tracked_datapaths. */ - tracked_binding_datapath_lport_add(pb, b_ctx->tracked_dp_bindings); + tracked_datapath_lport_add(pb, TRACKED_RESOURCE_NEW, + b_ctx->tracked_dp_bindings); } } sset_add(&b_ctx->related_lports->lport_names, pb->logical_port); @@ -582,7 +514,8 @@ remove_related_lport(const struct sbrec_port_binding *pb, if (b_ctx->tracked_dp_bindings) { /* Add the 'pb' to the tracked_datapaths. */ - tracked_binding_datapath_lport_add(pb, b_ctx->tracked_dp_bindings); + tracked_datapath_lport_add(pb, TRACKED_RESOURCE_REMOVED, + b_ctx->tracked_dp_bindings); } } } @@ -927,74 +860,6 @@ is_lport_vif(const struct sbrec_port_binding *pb) return !pb->type[0]; } -static struct tracked_binding_datapath * -tracked_binding_datapath_create(const struct sbrec_datapath_binding *dp, - bool is_new, - struct hmap *tracked_datapaths) -{ - struct tracked_binding_datapath *t_dp = xzalloc(sizeof *t_dp); - t_dp->dp = dp; - t_dp->is_new = is_new; - shash_init(&t_dp->lports); - hmap_insert(tracked_datapaths, &t_dp->node, uuid_hash(&dp->header_.uuid)); - return t_dp; -} - -static struct tracked_binding_datapath * -tracked_binding_datapath_find(struct hmap *tracked_datapaths, - const struct sbrec_datapath_binding *dp) -{ - struct tracked_binding_datapath *t_dp; - size_t hash = uuid_hash(&dp->header_.uuid); - HMAP_FOR_EACH_WITH_HASH (t_dp, node, hash, tracked_datapaths) { - if (uuid_equals(&t_dp->dp->header_.uuid, &dp->header_.uuid)) { - return t_dp; - } - } - - return NULL; -} - -static void -tracked_binding_datapath_lport_add(const struct sbrec_port_binding *pb, - struct hmap *tracked_datapaths) -{ - if (!tracked_datapaths) { - return; - } - - struct tracked_binding_datapath *tracked_dp = - tracked_binding_datapath_find(tracked_datapaths, pb->datapath); - if (!tracked_dp) { - tracked_dp = tracked_binding_datapath_create(pb->datapath, false, - tracked_datapaths); - } - - /* Check if the lport is already present or not. - * If it is already present, then just update the 'pb' field. */ - struct tracked_binding_lport *lport = - shash_find_data(&tracked_dp->lports, pb->logical_port); - - if (!lport) { - lport = xmalloc(sizeof *lport); - shash_add(&tracked_dp->lports, pb->logical_port, lport); - } - - lport->pb = pb; -} - -void -binding_tracked_dp_destroy(struct hmap *tracked_datapaths) -{ - struct tracked_binding_datapath *t_dp; - HMAP_FOR_EACH_POP (t_dp, node, tracked_datapaths) { - shash_destroy_free_data(&t_dp->lports); - free(t_dp); - } - - hmap_destroy(tracked_datapaths); -} - static enum en_lport_type get_lport_type(const struct sbrec_port_binding *pb) { @@ -1129,7 +994,7 @@ claim_lport(const struct sbrec_port_binding *pb, sbrec_port_binding_set_chassis(pb, chassis_rec); if (tracked_datapaths) { - update_lport_tracking(pb, tracked_datapaths); + update_lport_tracking(pb, tracked_datapaths, true); } } @@ -1178,7 +1043,7 @@ release_lport(const struct sbrec_port_binding *pb, bool sb_readonly, sbrec_port_binding_set_virtual_parent(pb, NULL); } - update_lport_tracking(pb, tracked_datapaths); + update_lport_tracking(pb, tracked_datapaths, false); if_status_mgr_release_iface(if_mgr, pb->logical_port); VLOG_INFO("Releasing lport %s from this chassis.", pb->logical_port); return true; @@ -1828,42 +1693,6 @@ binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, return !any_changes; } -static const struct sbrec_port_binding * -get_peer_lport__(const struct sbrec_port_binding *pb, - struct binding_ctx_in *b_ctx_in) -{ - const char *peer_name = smap_get(&pb->options, "peer"); - - if (!peer_name) { - return NULL; - } - - const struct sbrec_port_binding *peer; - peer = lport_lookup_by_name(b_ctx_in->sbrec_port_binding_by_name, - peer_name); - return (peer && peer->datapath) ? peer : NULL; -} - -static const struct sbrec_port_binding * -get_l3gw_peer_lport(const struct sbrec_port_binding *pb, - struct binding_ctx_in *b_ctx_in) -{ - if (strcmp(pb->type, "l3gateway")) { - return NULL; - } - return get_peer_lport__(pb, b_ctx_in); -} - -static const struct sbrec_port_binding * -get_peer_lport(const struct sbrec_port_binding *pb, - struct binding_ctx_in *b_ctx_in) -{ - if (strcmp(pb->type, "patch")) { - return NULL; - } - return get_peer_lport__(pb, b_ctx_in); -} - /* This function adds the local datapath of the 'peer' of * lport 'pb' to the local datapaths if it is not yet added. */ @@ -1873,61 +1702,16 @@ add_local_datapath_peer_port(const struct sbrec_port_binding *pb, struct binding_ctx_out *b_ctx_out, struct local_datapath *ld) { - const struct sbrec_port_binding *peer; - peer = get_peer_lport(pb, b_ctx_in); - - if (!peer) { - return; - } - - bool present = false; - for (size_t i = 0; i < ld->n_peer_ports; i++) { - if (ld->peer_ports[i].local == pb) { - present = true; - break; - } - } - - if (!present) { - ld->n_peer_ports++; - if (ld->n_peer_ports > ld->n_allocated_peer_ports) { - ld->peer_ports = - x2nrealloc(ld->peer_ports, - &ld->n_allocated_peer_ports, - sizeof *ld->peer_ports); - } - ld->peer_ports[ld->n_peer_ports - 1].local = pb; - ld->peer_ports[ld->n_peer_ports - 1].remote = peer; - } - - struct local_datapath *peer_ld = - get_local_datapath(b_ctx_out->local_datapaths, - peer->datapath->tunnel_key); - if (!peer_ld) { - add_local_datapath__(b_ctx_in->sbrec_datapath_binding_by_key, - b_ctx_in->sbrec_port_binding_by_datapath, - b_ctx_in->sbrec_port_binding_by_name, - peer->datapath, false, - 1, b_ctx_out->local_datapaths, - b_ctx_out->tracked_dp_bindings); - return; - } - - for (size_t i = 0; i < peer_ld->n_peer_ports; i++) { - if (peer_ld->peer_ports[i].local == peer) { - return; - } - } + struct local_datpath_added_aux aux = { + .has_local_l3gateway = false, + .tracked_datapaths = b_ctx_out->tracked_dp_bindings, + }; - peer_ld->n_peer_ports++; - if (peer_ld->n_peer_ports > peer_ld->n_allocated_peer_ports) { - peer_ld->peer_ports = - x2nrealloc(peer_ld->peer_ports, - &peer_ld->n_allocated_peer_ports, - sizeof *peer_ld->peer_ports); - } - peer_ld->peer_ports[peer_ld->n_peer_ports - 1].local = peer; - peer_ld->peer_ports[peer_ld->n_peer_ports - 1].remote = pb; + local_datapath_add_peer_port(pb, b_ctx_in->sbrec_datapath_binding_by_key, + b_ctx_in->sbrec_port_binding_by_datapath, + b_ctx_in->sbrec_port_binding_by_name, + ld, b_ctx_out->local_datapaths, + local_datapath_added, &aux); } static void @@ -1935,34 +1719,7 @@ remove_local_datapath_peer_port(const struct sbrec_port_binding *pb, struct local_datapath *ld, struct hmap *local_datapaths) { - size_t i = 0; - for (i = 0; i < ld->n_peer_ports; i++) { - if (ld->peer_ports[i].local == pb) { - break; - } - } - - if (i == ld->n_peer_ports) { - return; - } - - const struct sbrec_port_binding *peer = ld->peer_ports[i].remote; - - /* Possible improvement: We can shrink the allocated peer ports - * if (ld->n_peer_ports < ld->n_allocated_peer_ports / 2). - */ - ld->peer_ports[i].local = ld->peer_ports[ld->n_peer_ports - 1].local; - ld->peer_ports[i].remote = ld->peer_ports[ld->n_peer_ports - 1].remote; - ld->n_peer_ports--; - - struct local_datapath *peer_ld = - get_local_datapath(local_datapaths, peer->datapath->tunnel_key); - if (peer_ld) { - /* Remove the peer port from the peer datapath. The peer - * datapath also tries to remove its peer lport, but that would - * be no-op. */ - remove_local_datapath_peer_port(peer, peer_ld, local_datapaths); - } + local_datapath_remove_peer_port(pb, ld, local_datapaths); } static void @@ -1995,13 +1752,16 @@ remove_pb_from_local_datapath(const struct sbrec_port_binding *pb, static void update_lport_tracking(const struct sbrec_port_binding *pb, - struct hmap *tracked_dp_bindings) + struct hmap *tracked_dp_bindings, + bool claimed) { if (!tracked_dp_bindings) { return; } - tracked_binding_datapath_lport_add(pb, tracked_dp_bindings); + tracked_datapath_lport_add( + pb, claimed ? TRACKED_RESOURCE_NEW : TRACKED_RESOURCE_REMOVED, + tracked_dp_bindings); } /* Considers the ovs iface 'iface_rec' for claiming. @@ -2315,7 +2075,7 @@ handle_deleted_lport(const struct sbrec_port_binding *pb, /* If the binding is not local, if 'pb' is a L3 gateway port, we should * remove its peer, if that one is local. */ - pb = get_l3gw_peer_lport(pb, b_ctx_in); + pb = lport_get_l3gw_peer(pb, b_ctx_in->sbrec_port_binding_by_name); if (pb) { ld = get_local_datapath(b_ctx_out->local_datapaths, pb->datapath->tunnel_key); @@ -2598,7 +2358,10 @@ delete_done: * */ const struct sbrec_port_binding *peer; struct local_datapath *peer_ld = NULL; - peer = get_peer_lport(pb, b_ctx_in); + peer = + lport_get_peer(pb, + b_ctx_in->sbrec_port_binding_by_name); + if (peer) { peer_ld = get_local_datapath(b_ctx_out->local_datapaths, diff --git a/controller/binding.h b/controller/binding.h index 77197e742..b1717bd2b 100644 --- a/controller/binding.h +++ b/controller/binding.h @@ -121,19 +121,6 @@ void local_binding_set_up(struct shash *local_bindings, const char *pb_name, void local_binding_set_down(struct shash *local_bindings, const char *pb_name, bool sb_readonly, bool ovs_readonly); -/* Represents a tracked binding logical port. */ -struct tracked_binding_lport { - const struct sbrec_port_binding *pb; -}; - -/* Represent a tracked binding datapath. */ -struct tracked_binding_datapath { - struct hmap_node node; - const struct sbrec_datapath_binding *dp; - bool is_new; - struct shash lports; /* shash of struct tracked_binding_lport. */ -}; - void binding_register_ovs_idl(struct ovsdb_idl *); void binding_run(struct binding_ctx_in *, struct binding_ctx_out *); bool binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, diff --git a/controller/ldata.c b/controller/ldata.c new file mode 100644 index 000000000..a6df9b1da --- /dev/null +++ b/controller/ldata.c @@ -0,0 +1,368 @@ +/* Copyright (c) 2021, Red Hat, 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> + +/* OVS includes. */ +#include "include/openvswitch/json.h" +#include "lib/hmapx.h" +#include "lib/util.h" +#include "openvswitch/vlog.h" + +/* OVN includes. */ +#include "ldata.h" +#include "lport.h" +#include "lib/ovn-util.h" +#include "lib/ovn-sb-idl.h" + +VLOG_DEFINE_THIS_MODULE(ldata); + +static struct local_datapath *local_datapath_add__( + struct hmap *local_datapaths, + const struct sbrec_datapath_binding *, + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + int depth, + void (*datapath_added)(struct local_datapath *, + void *aux), + void *aux); + +static struct tracked_datapath *tracked_datapath_create( + const struct sbrec_datapath_binding *dp, + enum en_tracked_resource_type tracked_type, + struct hmap *tracked_datapaths); + +struct local_datapath * +get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key) +{ + struct hmap_node *node = hmap_first_with_hash(local_datapaths, tunnel_key); + return (node + ? CONTAINER_OF(node, struct local_datapath, hmap_node) + : NULL); +} + +struct local_datapath * +local_datapath_alloc(const struct sbrec_datapath_binding *dp) +{ + struct local_datapath *ld = xzalloc(sizeof *ld); + ld->datapath = dp; + ld->is_switch = datapath_is_switch(dp); + shash_init(&ld->external_ports); + return ld; +} + +void +local_datapaths_destroy(struct hmap *local_datapaths) +{ + struct local_datapath *ld; + HMAP_FOR_EACH_POP (ld, hmap_node, local_datapaths) { + local_datapath_destroy(ld); + } + + hmap_destroy(local_datapaths); +} + +void +local_datapath_destroy(struct local_datapath *ld) +{ + free(ld->peer_ports); + shash_destroy(&ld->external_ports); + free(ld); +} + +void +local_datapath_add(struct hmap *local_datapaths, + const struct sbrec_datapath_binding *dp, + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + void (*datapath_added_cb)( + struct local_datapath *ld, + void *aux), + void *aux) +{ + local_datapath_add__(local_datapaths, dp, sbrec_datapath_binding_by_key, + sbrec_port_binding_by_datapath, + sbrec_port_binding_by_name, 0, + datapath_added_cb, aux); +} + +void +local_datapath_add_peer_port( + const struct sbrec_port_binding *pb, + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + struct local_datapath *ld, + struct hmap *local_datapaths, + void (*datapath_added_cb)( + struct local_datapath *ld, + void *aux), + void *aux) +{ + const struct sbrec_port_binding *peer; + peer = lport_get_peer(pb, sbrec_port_binding_by_name); + + if (!peer) { + return; + } + + bool present = false; + for (size_t i = 0; i < ld->n_peer_ports; i++) { + if (ld->peer_ports[i].local == pb) { + present = true; + break; + } + } + + if (!present) { + ld->n_peer_ports++; + if (ld->n_peer_ports > ld->n_allocated_peer_ports) { + ld->peer_ports = + x2nrealloc(ld->peer_ports, + &ld->n_allocated_peer_ports, + sizeof *ld->peer_ports); + } + ld->peer_ports[ld->n_peer_ports - 1].local = pb; + ld->peer_ports[ld->n_peer_ports - 1].remote = peer; + } + + struct local_datapath *peer_ld = + get_local_datapath(local_datapaths, + peer->datapath->tunnel_key); + if (!peer_ld) { + local_datapath_add__(local_datapaths, peer->datapath, + sbrec_datapath_binding_by_key, + sbrec_port_binding_by_datapath, + sbrec_port_binding_by_name, 1, + datapath_added_cb, aux); + return; + } + + for (size_t i = 0; i < peer_ld->n_peer_ports; i++) { + if (peer_ld->peer_ports[i].local == peer) { + return; + } + } + + peer_ld->n_peer_ports++; + if (peer_ld->n_peer_ports > peer_ld->n_allocated_peer_ports) { + peer_ld->peer_ports = + x2nrealloc(peer_ld->peer_ports, + &peer_ld->n_allocated_peer_ports, + sizeof *peer_ld->peer_ports); + } + peer_ld->peer_ports[peer_ld->n_peer_ports - 1].local = peer; + peer_ld->peer_ports[peer_ld->n_peer_ports - 1].remote = pb; +} + +void +local_datapath_remove_peer_port(const struct sbrec_port_binding *pb, + struct local_datapath *ld, + struct hmap *local_datapaths) +{ + size_t i = 0; + for (i = 0; i < ld->n_peer_ports; i++) { + if (ld->peer_ports[i].local == pb) { + break; + } + } + + if (i == ld->n_peer_ports) { + return; + } + + const struct sbrec_port_binding *peer = ld->peer_ports[i].remote; + + /* Possible improvement: We can shrink the allocated peer ports + * if (ld->n_peer_ports < ld->n_allocated_peer_ports / 2). + */ + ld->peer_ports[i].local = ld->peer_ports[ld->n_peer_ports - 1].local; + ld->peer_ports[i].remote = ld->peer_ports[ld->n_peer_ports - 1].remote; + ld->n_peer_ports--; + + struct local_datapath *peer_ld = + get_local_datapath(local_datapaths, peer->datapath->tunnel_key); + if (peer_ld) { + /* Remove the peer port from the peer datapath. The peer + * datapath also tries to remove its peer lport, but that would + * be no-op. */ + local_datapath_remove_peer_port(peer, peer_ld, local_datapaths); + } +} + +/* track datapath functions. */ +struct tracked_datapath * +tracked_datapath_add(const struct sbrec_datapath_binding *dp, + enum en_tracked_resource_type tracked_type, + struct hmap *tracked_datapaths) +{ + struct tracked_datapath *t_dp = + tracked_datapath_find(tracked_datapaths, dp); + if (!t_dp) { + t_dp = tracked_datapath_create(dp, tracked_type, tracked_datapaths); + } else { + t_dp->tracked_type = tracked_type; + } + + return t_dp; +} + +struct tracked_datapath * +tracked_datapath_find(struct hmap *tracked_datapaths, + const struct sbrec_datapath_binding *dp) +{ + struct tracked_datapath *t_dp; + size_t hash = uuid_hash(&dp->header_.uuid); + HMAP_FOR_EACH_WITH_HASH (t_dp, node, hash, tracked_datapaths) { + if (uuid_equals(&t_dp->dp->header_.uuid, &dp->header_.uuid)) { + return t_dp; + } + } + + return NULL; +} + +void +tracked_datapath_lport_add(const struct sbrec_port_binding *pb, + enum en_tracked_resource_type tracked_type, + struct hmap *tracked_datapaths) +{ + struct tracked_datapath *tracked_dp = + tracked_datapath_find(tracked_datapaths, pb->datapath); + if (!tracked_dp) { + tracked_dp = tracked_datapath_create(pb->datapath, + TRACKED_RESOURCE_UPDATED, + tracked_datapaths); + } + + /* Check if the lport is already present or not. + * If it is already present, then just update the 'pb' field. */ + struct tracked_lport *lport = + shash_find_data(&tracked_dp->lports, pb->logical_port); + + if (!lport) { + lport = xmalloc(sizeof *lport); + shash_add(&tracked_dp->lports, pb->logical_port, lport); + } + + lport->pb = pb; + lport->tracked_type = tracked_type; +} + +void +tracked_datapaths_destroy(struct hmap *tracked_datapaths) +{ + struct tracked_datapath *t_dp; + HMAP_FOR_EACH_POP (t_dp, node, tracked_datapaths) { + shash_destroy_free_data(&t_dp->lports); + free(t_dp); + } + + hmap_destroy(tracked_datapaths); +} + +/* static functions. */ +static struct local_datapath * +local_datapath_add__(struct hmap *local_datapaths, + const struct sbrec_datapath_binding *dp, + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + int depth, + void (*datapath_added_cb)( + struct local_datapath *ld, + void *aux), + void *aux) +{ + uint32_t dp_key = dp->tunnel_key; + struct local_datapath *ld = get_local_datapath(local_datapaths, dp_key); + if (ld) { + return ld; + } + + ld = local_datapath_alloc(dp); + hmap_insert(local_datapaths, &ld->hmap_node, dp_key); + ld->datapath = dp; + + if (datapath_added_cb) { + datapath_added_cb(ld, aux); + } + + if (depth >= 100) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "datapaths nested too deep"); + return ld; + } + + struct sbrec_port_binding *target = + sbrec_port_binding_index_init_row(sbrec_port_binding_by_datapath); + sbrec_port_binding_index_set_datapath(target, dp); + + const struct sbrec_port_binding *pb; + SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target, + sbrec_port_binding_by_datapath) { + if (!strcmp(pb->type, "patch") || !strcmp(pb->type, "l3gateway")) { + const char *peer_name = smap_get(&pb->options, "peer"); + if (peer_name) { + const struct sbrec_port_binding *peer; + + peer = lport_lookup_by_name(sbrec_port_binding_by_name, + peer_name); + + if (peer && peer->datapath) { + if (!strcmp(pb->type, "patch")) { + /* Add the datapath to local datapath only for patch + * ports. For l3gateway ports, since gateway router + * resides on one chassis, we don't need to add. + * Otherwise, all other chassis might create patch + * ports between br-int and the provider bridge. */ + local_datapath_add__(local_datapaths, peer->datapath, + sbrec_datapath_binding_by_key, + sbrec_port_binding_by_datapath, + sbrec_port_binding_by_name, + depth + 1, datapath_added_cb, + aux); + } + ld->n_peer_ports++; + if (ld->n_peer_ports > ld->n_allocated_peer_ports) { + ld->peer_ports = + x2nrealloc(ld->peer_ports, + &ld->n_allocated_peer_ports, + sizeof *ld->peer_ports); + } + ld->peer_ports[ld->n_peer_ports - 1].local = pb; + ld->peer_ports[ld->n_peer_ports - 1].remote = peer; + } + } + } + } + sbrec_port_binding_index_destroy_row(target); + return ld; +} + +static struct tracked_datapath * +tracked_datapath_create(const struct sbrec_datapath_binding *dp, + enum en_tracked_resource_type tracked_type, + struct hmap *tracked_datapaths) +{ + struct tracked_datapath *t_dp = xzalloc(sizeof *t_dp); + t_dp->dp = dp; + t_dp->tracked_type = tracked_type; + shash_init(&t_dp->lports); + hmap_insert(tracked_datapaths, &t_dp->node, uuid_hash(&dp->header_.uuid)); + return t_dp; +} diff --git a/controller/ldata.h b/controller/ldata.h new file mode 100644 index 000000000..16ad43c8f --- /dev/null +++ b/controller/ldata.h @@ -0,0 +1,120 @@ +/* Copyright (c) 2021, Red Hat, 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 LDATA_H +#define LDATA_H 1 + +/* OVS includes. */ +#include "include/openvswitch/shash.h" +#include "lib/smap.h" + +struct sbrec_datapath_binding; +struct sbrec_port_binding; +struct ovsdb_idl_index; + +/* A logical datapath that has some relevance to this hypervisor. A logical + * datapath D is relevant to hypervisor H if: + * + * - Some VIF or l2gateway or l3gateway port in D is located on H. + * + * - D is reachable over a series of hops across patch ports, starting from + * a datapath relevant to H. + * + * The 'hmap_node''s hash value is 'datapath->tunnel_key'. */ +struct local_datapath { + struct hmap_node hmap_node; + const struct sbrec_datapath_binding *datapath; + bool is_switch; + + /* The localnet port in this datapath, if any (at most one is allowed). */ + const struct sbrec_port_binding *localnet_port; + + /* True if this datapath contains an l3gateway port located on this + * hypervisor. */ + bool has_local_l3gateway; + + struct { + const struct sbrec_port_binding *local; + const struct sbrec_port_binding *remote; + } *peer_ports; + + size_t n_peer_ports; + size_t n_allocated_peer_ports; + + struct shash external_ports; +}; + +struct local_datapath *local_datapath_alloc( + const struct sbrec_datapath_binding *); +struct local_datapath *get_local_datapath(const struct hmap *, + uint32_t tunnel_key); +void local_datapath_add(struct hmap *local_datapaths, + const struct sbrec_datapath_binding *, + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + void (*datapath_added)(struct local_datapath *, + void *aux), + void *aux); + +void local_datapaths_destroy(struct hmap *local_datapaths); +void local_datapath_destroy(struct local_datapath *ld); +void local_datapath_add_peer_port( + const struct sbrec_port_binding *pb, + struct ovsdb_idl_index *sbrec_datapath_binding_by_key, + struct ovsdb_idl_index *sbrec_port_binding_by_datapath, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + struct local_datapath *ld, + struct hmap *local_datapaths, + void (*datapath_added_cb)( + struct local_datapath *ld, + void *aux), + void *aux); + +void local_datapath_remove_peer_port(const struct sbrec_port_binding *pb, + struct local_datapath *ld, + struct hmap *local_datapaths); + +enum en_tracked_resource_type { + TRACKED_RESOURCE_NEW, + TRACKED_RESOURCE_REMOVED, + TRACKED_RESOURCE_UPDATED +}; + +/* Represents a tracked logical port. */ +struct tracked_lport { + const struct sbrec_port_binding *pb; + enum en_tracked_resource_type tracked_type; +}; + +/* Represent a tracked datapath. */ +struct tracked_datapath { + struct hmap_node node; + const struct sbrec_datapath_binding *dp; + enum en_tracked_resource_type tracked_type; + struct shash lports; /* shash of struct tracked_binding_lport. */ +}; + +struct tracked_datapath * tracked_datapath_add( + const struct sbrec_datapath_binding *, enum en_tracked_resource_type, + struct hmap *tracked_datapaths); +struct tracked_datapath *tracked_datapath_find( + struct hmap *tracked_datapaths, const struct sbrec_datapath_binding *); +void tracked_datapath_lport_add(const struct sbrec_port_binding *, + enum en_tracked_resource_type, + struct hmap *tracked_datapaths); +void tracked_datapaths_destroy(struct hmap *tracked_datapaths); + +#endif /* controller/ldata.h */ diff --git a/controller/lflow.c b/controller/lflow.c index c58c4f25c..d1f32077b 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -17,6 +17,7 @@ #include "lflow.h" #include "coverage.h" #include "ha-chassis.h" +#include "ldata.h" #include "lflow-cache.h" #include "lport.h" #include "ofctrl.h" diff --git a/controller/lport.c b/controller/lport.c index 478fcfd82..25b4ef200 100644 --- a/controller/lport.c +++ b/controller/lport.c @@ -23,6 +23,10 @@ #include "lib/ovn-sb-idl.h" VLOG_DEFINE_THIS_MODULE(lport); +static const struct sbrec_port_binding *get_peer_lport( + const struct sbrec_port_binding *pb, + struct ovsdb_idl_index *sbrec_port_binding_by_name); + const struct sbrec_port_binding * lport_lookup_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, const char *name) @@ -84,6 +88,26 @@ lport_is_chassis_resident(struct ovsdb_idl_index *sbrec_port_binding_by_name, } } +const struct sbrec_port_binding * +lport_get_peer(const struct sbrec_port_binding *pb, + struct ovsdb_idl_index *sbrec_port_binding_by_name) +{ + if (strcmp(pb->type, "patch")) { + return NULL; + } + return get_peer_lport(pb, sbrec_port_binding_by_name); +} + +const struct sbrec_port_binding * +lport_get_l3gw_peer(const struct sbrec_port_binding *pb, + struct ovsdb_idl_index *sbrec_port_binding_by_name) +{ + if (strcmp(pb->type, "l3gateway")) { + return NULL; + } + return get_peer_lport(pb, sbrec_port_binding_by_name); +} + const struct sbrec_datapath_binding * datapath_lookup_by_key(struct ovsdb_idl_index *sbrec_datapath_binding_by_key, uint64_t dp_key) @@ -120,3 +144,19 @@ mcgroup_lookup_by_dp_name( return retval; } + +static const struct sbrec_port_binding * +get_peer_lport(const struct sbrec_port_binding *pb, + struct ovsdb_idl_index *sbrec_port_binding_by_name) +{ + const char *peer_name = smap_get(&pb->options, "peer"); + + if (!peer_name) { + return NULL; + } + + const struct sbrec_port_binding *peer; + peer = lport_lookup_by_name(sbrec_port_binding_by_name, + peer_name); + return (peer && peer->datapath) ? peer : NULL; +} diff --git a/controller/lport.h b/controller/lport.h index 345efc184..43b3d714d 100644 --- a/controller/lport.h +++ b/controller/lport.h @@ -54,5 +54,10 @@ lport_is_chassis_resident(struct ovsdb_idl_index *sbrec_port_binding_by_name, const struct sbrec_chassis *chassis, const struct sset *active_tunnels, const char *port_name); - +const struct sbrec_port_binding *lport_get_peer( + const struct sbrec_port_binding *, + struct ovsdb_idl_index *sbrec_port_binding_by_name); +const struct sbrec_port_binding *lport_get_l3gw_peer( + const struct sbrec_port_binding *, + struct ovsdb_idl_index *sbrec_port_binding_by_name); #endif /* controller/lport.h */ diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 2418c301b..8f620e4ad 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -39,6 +39,7 @@ #include "lflow.h" #include "lflow-cache.h" #include "lib/vswitch-idl.h" +#include "ldata.h" #include "lport.h" #include "memory.h" #include "ofctrl.h" @@ -131,15 +132,6 @@ struct pending_pkt { /* Registered ofctrl seqno type for nb_cfg propagation. */ static size_t ofctrl_seq_type_nb_cfg; -struct local_datapath * -get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key) -{ - struct hmap_node *node = hmap_first_with_hash(local_datapaths, tunnel_key); - return (node - ? CONTAINER_OF(node, struct local_datapath, hmap_node) - : NULL); -} - uint32_t get_tunnel_type(const char *name) { @@ -1067,8 +1059,8 @@ struct ed_type_runtime_data { * * ------------------------------------------------------------------------ * | | This is a hmap of | - * | | 'struct tracked_binding_datapath' defined in | - * | | binding.h. Runtime data handlers for OVS | + * | | 'struct tracked_datapath' defined in | + * | | ldata.h. Runtime data handlers for OVS | * | | Interface and Port Binding changes store the | * | @tracked_dp_bindings | changed datapaths (datapaths added/removed from | * | | local_datapaths) and changed port bindings | @@ -1126,7 +1118,7 @@ en_runtime_data_clear_tracked_data(void *data_) { struct ed_type_runtime_data *data = data_; - binding_tracked_dp_destroy(&data->tracked_dp_bindings); + tracked_datapaths_destroy(&data->tracked_dp_bindings); hmap_init(&data->tracked_dp_bindings); data->local_lports_changed = false; data->tracked = false; @@ -1164,15 +1156,7 @@ en_runtime_data_cleanup(void *data) sset_destroy(&rt_data->active_tunnels); sset_destroy(&rt_data->egress_ifaces); smap_destroy(&rt_data->local_iface_ids); - struct local_datapath *cur_node, *next_node; - HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, - &rt_data->local_datapaths) { - free(cur_node->peer_ports); - shash_destroy(&cur_node->external_ports); - hmap_remove(&rt_data->local_datapaths, &cur_node->hmap_node); - free(cur_node); - } - hmap_destroy(&rt_data->local_datapaths); + local_datapaths_destroy(&rt_data->local_datapaths); shash_destroy_free_data(&rt_data->local_active_ports_ipv6_pd); shash_destroy_free_data(&rt_data->local_active_ports_ras); local_binding_data_destroy(&rt_data->lbinding_data); @@ -1284,14 +1268,7 @@ en_runtime_data_run(struct engine_node *node, void *data) /* don't cleanup since there is no data yet */ first_run = false; } else { - struct local_datapath *cur_node, *next_node; - HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, local_datapaths) { - free(cur_node->peer_ports); - shash_destroy(&cur_node->external_ports); - hmap_remove(local_datapaths, &cur_node->hmap_node); - free(cur_node); - } - hmap_clear(local_datapaths); + local_datapaths_destroy(local_datapaths); shash_clear_free_data(local_active_ipv6_pd); shash_clear_free_data(local_active_ras); local_binding_data_destroy(&rt_data->lbinding_data); @@ -1300,6 +1277,7 @@ en_runtime_data_run(struct engine_node *node, void *data) sset_destroy(active_tunnels); sset_destroy(&rt_data->egress_ifaces); smap_destroy(&rt_data->local_iface_ids); + hmap_init(local_datapaths); sset_init(local_lports); related_lports_init(&rt_data->related_lports); sset_init(active_tunnels); @@ -1741,12 +1719,12 @@ port_groups_runtime_data_handler(struct engine_node *node, void *data) pg_sb->name); ovs_assert(pg_lports); - struct tracked_binding_datapath *tdp; + struct tracked_datapath *tdp; bool need_update = false; HMAP_FOR_EACH (tdp, node, &rt_data->tracked_dp_bindings) { struct shash_node *shash_node; SHASH_FOR_EACH (shash_node, &tdp->lports) { - struct tracked_binding_lport *lport = shash_node->data; + struct tracked_lport *lport = shash_node->data; if (sset_contains(pg_lports, lport->pb->logical_port)) { /* At least one local port-binding change is related to the * port_group, so the port_group_cs_local needs update. */ @@ -1899,9 +1877,9 @@ ct_zones_runtime_data_handler(struct engine_node *node, void *data OVS_UNUSED) } struct hmap *tracked_dp_bindings = &rt_data->tracked_dp_bindings; - struct tracked_binding_datapath *tdp; + struct tracked_datapath *tdp; HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) { - if (tdp->is_new) { + if (tdp->tracked_type == TRACKED_RESOURCE_NEW) { /* A new datapath has been added. Fall back to full recompute. */ return false; } @@ -2423,9 +2401,9 @@ lflow_output_runtime_data_handler(struct engine_node *node, struct ed_type_lflow_output *fo = data; init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out); - struct tracked_binding_datapath *tdp; + struct tracked_datapath *tdp; HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) { - if (tdp->is_new) { + if (tdp->tracked_type == TRACKED_RESOURCE_NEW) { if (!lflow_add_flows_for_datapath(tdp->dp, &l_ctx_in, &l_ctx_out)) { return false; @@ -2433,7 +2411,7 @@ lflow_output_runtime_data_handler(struct engine_node *node, } else { struct shash_node *shash_node; SHASH_FOR_EACH (shash_node, &tdp->lports) { - struct tracked_binding_lport *lport = shash_node->data; + struct tracked_lport *lport = shash_node->data; if (!lflow_handle_flows_for_lport(lport->pb, &l_ctx_in, &l_ctx_out)) { return false; diff --git a/controller/ovn-controller.h b/controller/ovn-controller.h index b864ed0fa..578588305 100644 --- a/controller/ovn-controller.h +++ b/controller/ovn-controller.h @@ -40,40 +40,6 @@ struct ct_zone_pending_entry { enum ct_zone_pending_state state; }; -/* A logical datapath that has some relevance to this hypervisor. A logical - * datapath D is relevant to hypervisor H if: - * - * - Some VIF or l2gateway or l3gateway port in D is located on H. - * - * - D is reachable over a series of hops across patch ports, starting from - * a datapath relevant to H. - * - * The 'hmap_node''s hash value is 'datapath->tunnel_key'. */ -struct local_datapath { - struct hmap_node hmap_node; - const struct sbrec_datapath_binding *datapath; - - /* The localnet port in this datapath, if any (at most one is allowed). */ - const struct sbrec_port_binding *localnet_port; - - /* True if this datapath contains an l3gateway port located on this - * hypervisor. */ - bool has_local_l3gateway; - - struct { - const struct sbrec_port_binding *local; - const struct sbrec_port_binding *remote; - } *peer_ports; - - size_t n_peer_ports; - size_t n_allocated_peer_ports; - - struct shash external_ports; -}; - -struct local_datapath *get_local_datapath(const struct hmap *, - uint32_t tunnel_key); - const struct ovsrec_bridge *get_bridge(const struct ovsrec_bridge_table *, const char *br_name); diff --git a/controller/patch.c b/controller/patch.c index e54b56354..99a095c57 100644 --- a/controller/patch.c +++ b/controller/patch.c @@ -18,6 +18,7 @@ #include "patch.h" #include "hash.h" +#include "ldata.h" #include "lflow.h" #include "lib/vswitch-idl.h" #include "lport.h" diff --git a/controller/physical.c b/controller/physical.c index 483a5a49b..b244ff1c2 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -20,6 +20,7 @@ #include "encaps.h" #include "flow.h" #include "ha-chassis.h" +#include "ldata.h" #include "lflow.h" #include "lport.h" #include "chassis.h" diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 8e4c4d18c..e2d892aab 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -25,6 +25,7 @@ #include "encaps.h" #include "flow.h" #include "ha-chassis.h" +#include "ldata.h" #include "lport.h" #include "mac-learn.h" #include "nx-match.h"