@@ -19,7 +19,9 @@ ovn_controller_ovn_controller_SOURCES = \
ovn/controller/ovn-controller.c \
ovn/controller/ovn-controller.h \
ovn/controller/physical.c \
- ovn/controller/physical.h
+ ovn/controller/physical.h \
+ ovn/controller/filter.c \
+ ovn/controller/filter.h
ovn_controller_ovn_controller_LDADD = ovn/lib/libovn.la lib/libopenvswitch.la
man_MANS += ovn/controller/ovn-controller.8
EXTRA_DIST += ovn/controller/ovn-controller.8.xml
@@ -24,6 +24,10 @@
#include "openvswitch/vlog.h"
#include "ovn/lib/ovn-sb-idl.h"
#include "ovn-controller.h"
+#include "lport.h"
+#include "filter.h"
+#include "poll-loop.h"
+#include "timeval.h"
VLOG_DEFINE_THIS_MODULE(binding);
@@ -50,7 +54,9 @@ binding_register_ovs_idl(struct ovsdb_idl *ovs_idl)
}
static void
-get_local_iface_ids(const struct ovsrec_bridge *br_int, struct shash *lports)
+get_local_iface_ids(const struct ovsrec_bridge *br_int, struct shash *lports,
+ struct lport_index *lports_index,
+ struct controller_ctx *ctx)
{
int i;
@@ -72,13 +78,17 @@ get_local_iface_ids(const struct ovsrec_bridge *br_int, struct shash *lports)
continue;
}
shash_add(lports, iface_id, iface_rec);
+ if (!lport_lookup_by_name(lports_index, iface_id)) {
+ filter_lport(ctx, iface_id);
+ }
}
}
}
static void
add_local_datapath(struct hmap *local_datapaths,
- const struct sbrec_port_binding *binding_rec)
+ const struct sbrec_port_binding *binding_rec,
+ struct controller_ctx *ctx)
{
if (get_local_datapath(local_datapaths,
binding_rec->datapath->tunnel_key)) {
@@ -88,6 +98,7 @@ add_local_datapath(struct hmap *local_datapaths,
struct local_datapath *ld = xzalloc(sizeof *ld);
hmap_insert(local_datapaths, &ld->hmap_node,
binding_rec->datapath->tunnel_key);
+ filter_datapath(ctx, binding_rec);
}
static void
@@ -104,7 +115,7 @@ update_qos(const struct ovsrec_interface *iface_rec,
void
binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
const char *chassis_id, struct sset *all_lports,
- struct hmap *local_datapaths)
+ struct lport_index *lports_index, struct hmap *local_datapaths)
{
const struct sbrec_chassis *chassis_rec;
const struct sbrec_port_binding *binding_rec;
@@ -113,7 +124,7 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
struct shash lports = SHASH_INITIALIZER(&lports);
if (br_int) {
- get_local_iface_ids(br_int, &lports);
+ get_local_iface_ids(br_int, &lports, lports_index, ctx);
} else {
/* We have no integration bridge, therefore no local logical ports.
* We'll remove our chassis from all port binding records below. */
@@ -137,7 +148,7 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
/* Add child logical port to the set of all local ports. */
sset_add(all_lports, binding_rec->logical_port);
}
- add_local_datapath(local_datapaths, binding_rec);
+ add_local_datapath(local_datapaths, binding_rec, ctx);
if (iface_rec && ctx->ovs_idl_txn) {
update_qos(iface_rec, binding_rec);
}
@@ -169,6 +180,12 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
* a patch port for each one. */
sset_add(all_lports, binding_rec->logical_port);
}
+ const char *peer = smap_get(&binding_rec->options, "peer");
+ if (peer) {
+ if (!lport_lookup_by_name(lports_index, peer)) {
+ filter_lport(ctx, peer);
+ }
+ }
}
SHASH_FOR_EACH (node, &lports) {
@@ -25,10 +25,12 @@ struct ovsdb_idl;
struct ovsrec_bridge;
struct simap;
struct sset;
+struct lport_index;
void binding_register_ovs_idl(struct ovsdb_idl *);
void binding_run(struct controller_ctx *, const struct ovsrec_bridge *br_int,
const char *chassis_id, struct sset *all_lports,
+ struct lport_index *lports_index,
struct hmap *local_datapaths);
bool binding_cleanup(struct controller_ctx *, const char *chassis_id);
new file mode 100644
@@ -0,0 +1,165 @@
+/* Copyright (c) 2015, 2016 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 "filter.h"
+
+#include "openvswitch/vlog.h"
+#include "ovn/lib/ovn-sb-idl.h"
+#include "ovn-controller.h"
+
+VLOG_DEFINE_THIS_MODULE(filter);
+
+static struct hmap filtered_dps = HMAP_INITIALIZER(&filtered_dps);
+static struct hmap filtered_lps = HMAP_INITIALIZER(&filtered_lps);
+
+struct filtered_dp {
+ struct hmap_node hmap_node;
+ int64_t tunnel_key;
+ struct sbrec_datapath_binding *datapath;
+ bool used;
+};
+
+struct filtered_lp {
+ struct hmap_node hmap_node;
+ const char *lport_name;
+ bool used;
+};
+
+void
+filter_init(struct ovsdb_idl *idl)
+{
+ sbrec_port_binding_add_clause_false(idl);
+ sbrec_mac_binding_add_clause_false(idl);
+ sbrec_logical_flow_add_clause_false(idl);
+ sbrec_multicast_group_add_clause_false(idl);
+
+}
+
+void
+filter_mark_unused(void)
+{
+ struct filtered_lp *lp;
+ struct filtered_lp *dp;
+
+ HMAP_FOR_EACH(lp, hmap_node, &filtered_lps) {
+ lp->used = false;
+ }
+ HMAP_FOR_EACH(dp, hmap_node, &filtered_dps) {
+ dp->used = false;
+ }
+}
+
+void
+filter_remove_unused(struct controller_ctx *ctx)
+{
+ struct filtered_lp *lp, *next;
+ struct filtered_dp *dp, *next_dp;
+
+ HMAP_FOR_EACH_SAFE(lp, next, hmap_node, &filtered_lps) {
+ if (!lp->used) {
+ VLOG_INFO("Unfilter Port %s", lp->lport_name);
+ sbrec_port_binding_remove_clause_logical_port(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ lp->lport_name);
+ hmap_remove(&filtered_lps, &lp->hmap_node);
+ free(lp);
+ }
+ }
+ HMAP_FOR_EACH_SAFE(dp, next_dp, hmap_node, &filtered_dps) {
+ if (!dp->used) {
+ VLOG_INFO("Unfilter DP "UUID_FMT,
+ UUID_ARGS(&dp->datapath->header_.uuid));
+ sbrec_port_binding_remove_clause_datapath(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ dp->datapath);
+ sbrec_mac_binding_remove_clause_datapath(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ dp->datapath);
+ sbrec_logical_flow_remove_clause_logical_datapath(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ dp->datapath);
+ sbrec_multicast_group_remove_clause_datapath(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ dp->datapath);
+ hmap_remove(&filtered_lps, &lp->hmap_node);
+ free(lp);
+ }
+ }
+}
+
+void
+filter_lport(struct controller_ctx *ctx, const char *lport_name)
+{
+ struct filtered_lp *lp;
+ size_t hash = hash_bytes(lport_name, strlen(lport_name), 0);
+
+ HMAP_FOR_EACH_WITH_HASH(lp, hmap_node, hash, &filtered_lps) {
+ if (!strcmp(lp->lport_name, lport_name)) {
+ lp->used = true;
+ return;
+ }
+ }
+
+ VLOG_INFO("Filter Port %s", lport_name);
+
+ sbrec_port_binding_add_clause_logical_port(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ lport_name);
+
+ char *name = xmalloc(strlen(lport_name));
+ lp = xmalloc(sizeof *lp);
+
+ strcpy(name, lport_name);
+ lp->lport_name = name;
+ lp->used = true;
+ hmap_insert(&filtered_lps, &lp->hmap_node,
+ hash);
+}
+
+void
+filter_datapath(struct controller_ctx *ctx,
+ const struct sbrec_port_binding *pb)
+{
+ struct filtered_dp *dp;
+
+ HMAP_FOR_EACH_WITH_HASH(dp, hmap_node, pb->datapath->tunnel_key,
+ &filtered_dps) {
+ if (dp->tunnel_key == pb->datapath->tunnel_key) {
+ dp->used = true;
+ return;
+ }
+ }
+
+ VLOG_INFO("Filter DP "UUID_FMT, UUID_ARGS(&pb->datapath->header_.uuid));
+ sbrec_port_binding_add_clause_datapath(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ pb->datapath);
+ sbrec_mac_binding_add_clause_datapath(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ pb->datapath);
+ sbrec_logical_flow_add_clause_logical_datapath(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ pb->datapath);
+ sbrec_multicast_group_add_clause_datapath(ctx->ovnsb_idl,
+ OVSDB_F_EQ,
+ pb->datapath);
+
+ dp = xmalloc(sizeof *dp);
+ dp->tunnel_key = pb->datapath->tunnel_key;
+ dp->datapath = pb->datapath;
+ dp->used = true;
+ hmap_insert(&filtered_dps, &dp->hmap_node, pb->datapath->tunnel_key);
+}
new file mode 100644
@@ -0,0 +1,30 @@
+/* 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_FILTER_H
+#define OVN_FILTER_H 1
+
+struct controller_ctx;
+struct ovsdb_idl;
+struct sbrec_port_binding;
+
+void filter_init(struct ovsdb_idl *idl);
+void filter_mark_unused(void);
+void filter_remove_unused(struct controller_ctx *ctx);
+void filter_lport(struct controller_ctx *ctx, const char *lport_name);
+void filter_datapath(struct controller_ctx *ctx,
+ const struct sbrec_port_binding *pb);
+
+#endif /* ovn/controller/filter.h */
@@ -53,6 +53,7 @@
#include "stream.h"
#include "unixctl.h"
#include "util.h"
+#include "filter.h"
VLOG_DEFINE_THIS_MODULE(main);
@@ -383,6 +384,9 @@ main(int argc, char *argv[])
char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);
struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
+
+ filter_init(ovnsb_idl_loop.idl);
+
ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
int probe_interval = 0;
@@ -416,6 +420,7 @@ main(int argc, char *argv[])
.ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop),
.ovnsb_idl = ovnsb_idl_loop.idl,
.ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
+ .ovnsb_remote = ovnsb_remote,
};
/* Contains "struct local_datpath" nodes whose hash values are the
@@ -427,11 +432,16 @@ main(int argc, char *argv[])
const struct ovsrec_bridge *br_int = get_br_int(&ctx);
const char *chassis_id = get_chassis_id(ctx.ovs_idl);
+ struct lport_index lports;
+ struct mcgroup_index mcgroups;
+ lport_index_init(&lports, ctx.ovnsb_idl);
+ mcgroup_index_init(&mcgroups, ctx.ovnsb_idl);
+ filter_mark_unused();
if (chassis_id) {
chassis_run(&ctx, chassis_id);
encaps_run(&ctx, br_int, chassis_id);
- binding_run(&ctx, br_int, chassis_id, &all_lports,
+ binding_run(&ctx, br_int, chassis_id, &all_lports, &lports,
&local_datapaths);
}
@@ -439,11 +449,6 @@ main(int argc, char *argv[])
patch_run(&ctx, br_int, chassis_id, &local_datapaths,
&patched_datapaths);
- 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, &lports, br_int, chassis_id, &local_datapaths);
@@ -460,10 +465,12 @@ main(int argc, char *argv[])
}
ofctrl_put(&flow_table);
hmap_destroy(&flow_table);
- mcgroup_index_destroy(&mcgroups);
- lport_index_destroy(&lports);
}
+ filter_remove_unused(&ctx);
+ mcgroup_index_destroy(&mcgroups);
+ lport_index_destroy(&lports);
+
sset_destroy(&all_lports);
struct local_datapath *cur_node, *next_node;
@@ -26,6 +26,7 @@
struct controller_ctx {
struct ovsdb_idl *ovnsb_idl;
struct ovsdb_idl_txn *ovnsb_idl_txn;
+ char *ovnsb_remote;
struct ovsdb_idl *ovs_idl;
struct ovsdb_idl_txn *ovs_idl_txn;
@@ -22,6 +22,7 @@
#include "lib/vswitch-idl.h"
#include "openvswitch/vlog.h"
#include "ovn-controller.h"
+#include "filter.h"
VLOG_DEFINE_THIS_MODULE(patch);
@@ -230,7 +231,8 @@ add_bridge_mappings(struct controller_ctx *ctx,
static void
add_patched_datapath(struct hmap *patched_datapaths,
- const struct sbrec_port_binding *binding_rec, bool local)
+ const struct sbrec_port_binding *binding_rec, bool local,
+ struct controller_ctx *ctx)
{
if (get_patched_datapath(patched_datapaths,
binding_rec->datapath->tunnel_key)) {
@@ -242,6 +244,7 @@ add_patched_datapath(struct hmap *patched_datapaths,
pd->port_binding = binding_rec;
hmap_insert(patched_datapaths, &pd->hmap_node,
binding_rec->datapath->tunnel_key);
+ filter_datapath(ctx, binding_rec);
}
/* Add one OVS patch port for each OVN logical patch port.
@@ -304,7 +307,7 @@ add_logical_patch_ports(struct controller_ctx *ctx,
existing_ports);
free(dst_name);
free(src_name);
- add_patched_datapath(patched_datapaths, binding, local_port);
+ add_patched_datapath(patched_datapaths, binding, local_port, ctx);
if (local_port) {
if (binding->chassis != chassis_rec && ctx->ovnsb_idl_txn) {
sbrec_port_binding_set_chassis(binding, chassis_rec);
@@ -92,11 +92,14 @@ AT_CHECK([ovn-sbctl \
-- --id=@dp2 create Datapath_Binding tunnel_key=2 \
-- create Port_Binding datapath=@dp1 logical_port=foo tunnel_key=1 type=patch options:peer=bar \
-- create Port_Binding datapath=@dp2 logical_port=bar tunnel_key=2 type=patch options:peer=foo \
+ -- create Port_Binding datapath=@dp1 logical_port=localvif3 tunnel_key=3 \
| ${PERL} $srcdir/uuidfilt.pl], [0], [<0>
<1>
<2>
<3>
+<4>
])
+ovs-vsctl add-port br-int localvif3 -- set Interface localvif3 external_ids:iface-id=localvif3
check_patches \
'br-int patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2' \