Skip to content
Permalink
Browse files
ovn: Introduce ovn-controller.
Add new ovn-controller daemon that runs locally on transport nodes.
This initial version registers itself in the Chassis table and registers
logical ports to the appropriate rows in the Bindings table.

Signed-off-by: Justin Pettit <jpettit@nicira.com>
Acked-by: Russell Bryant <rbryant@redhat.com>
  • Loading branch information
justinpettit committed Apr 12, 2015
1 parent a0149f4 commit 717c7fc508044d08210c686c1e8576c29a108f86
@@ -371,3 +371,4 @@ include vtep/automake.mk
include datapath-windows/automake.mk
include datapath-windows/include/automake.mk
include ovn/automake.mk
include ovn/controller/automake.mk
@@ -1,5 +1,4 @@
/ovn-architecture.7
/ovn-controller.8
/ovn-nb.5
/ovn-nb.gv
/ovn-nb.pic
@@ -129,17 +129,6 @@

** Interaction with Open_vSwitch and OVN databases:

*** Monitor VIFs attached to the integration bridge in Open_vSwitch.

In response to changes, add or remove corresponding rows in
Bindings table in OVN.

*** Populate Chassis row in OVN at startup. Maintain Chassis row over time.

(Warn if any other Chassis claims the same IP address.)

*** Remove Chassis and Bindings rows from OVN on exit.

*** Monitor Chassis table in OVN.

Populate Port records for tunnels to other chassis into
@@ -155,14 +144,6 @@

Default: VXLAN? Geneve?

*** Location of Open_vSwitch database.

We can probably use the same default as ovs-vsctl.

*** Location of OVN Southbound database.

Probably no useful default.

*** SSL configuration.

Can probably get this from Open_vSwitch database.
@@ -66,8 +66,8 @@ ovn/ovn-nb.5: \
$(srcdir)/ovn/ovn-nb.xml > $@.tmp && \
mv $@.tmp $@

man_MANS += ovn/ovn-controller.8 ovn/ovn-architecture.7 ovn/ovn-nbctl.8
EXTRA_DIST += ovn/ovn-controller.8.in ovn/ovn-architecture.7.xml ovn/ovn-nbctl.8.xml
man_MANS += ovn/ovn-architecture.7 ovn/ovn-nbctl.8
EXTRA_DIST += ovn/ovn-architecture.7.xml ovn/ovn-nbctl.8.xml

SUFFIXES += .xml
%: %.xml
@@ -0,0 +1,2 @@
/ovn-controller
/ovn-controller.8
@@ -0,0 +1,11 @@
bin_PROGRAMS += ovn/controller/ovn-controller
ovn_controller_ovn_controller_SOURCES = \
ovn/controller/bindings.c \
ovn/controller/bindings.h \
ovn/controller/chassis.c \
ovn/controller/chassis.h \
ovn/controller/ovn-controller.c \
ovn/controller/ovn-controller.h
ovn_controller_ovn_controller_LDADD = ovn/libovn.la lib/libopenvswitch.la
man_MANS += ovn/controller/ovn-controller.8
EXTRA_DIST += ovn/controller/ovn-controller.8.xml
@@ -0,0 +1,179 @@
/* Copyright (c) 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <config.h>
#include "bindings.h"

#include "lib/sset.h"
#include "lib/util.h"
#include "lib/vswitch-idl.h"
#include "openvswitch/vlog.h"
#include "ovn/ovn-sb-idl.h"
#include "ovn-controller.h"

VLOG_DEFINE_THIS_MODULE(bindings);

#define DEFAULT_BRIDGE_NAME "br-int"

void
bindings_init(struct controller_ctx *ctx)
{
ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_open_vswitch);
ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_open_vswitch_col_bridges);

ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_bridge);
ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_bridge_col_name);
ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_bridge_col_ports);

ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_port);
ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_port_col_name);
ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_port_col_interfaces);

ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_interface);
ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_name);
ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_external_ids);
}

static void
get_local_iface_ids(struct controller_ctx *ctx, struct sset *lports)
{
const struct ovsrec_open_vswitch *cfg;
const struct ovsrec_bridge *bridge_rec;
const char *bridge_name;
int i;

cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
if (!cfg) {
VLOG_INFO("No Open_vSwitch row defined.");
return;
}

bridge_name = smap_get(&cfg->external_ids, "ovn-bridge");
if (!bridge_name) {
bridge_name = DEFAULT_BRIDGE_NAME;
}

OVSREC_BRIDGE_FOR_EACH(bridge_rec, ctx->ovs_idl) {
if (!strcmp(bridge_rec->name, bridge_name)) {
break;
}
}

if (!bridge_rec) {
VLOG_INFO("Could not find bridge '%s'", bridge_name);
return;
}

for (i = 0; i < bridge_rec->n_ports; i++) {
const struct ovsrec_port *port_rec = bridge_rec->ports[i];
const char *iface_id;
int j;

if (!strcmp(port_rec->name, bridge_rec->name)) {
continue;
}

for (j = 0; j < port_rec->n_interfaces; j++) {
const struct ovsrec_interface *iface_rec;

iface_rec = port_rec->interfaces[j];
iface_id = smap_get(&iface_rec->external_ids, "iface-id");
if (!iface_id) {
VLOG_DBG("Could not find iface-id for '%s'", iface_rec->name);
continue;
}
sset_add(lports, iface_id);
}
}
}

void
bindings_run(struct controller_ctx *ctx)
{
const struct sbrec_bindings *bindings_rec;
struct ovsdb_idl_txn *txn;
struct sset lports;
const char *name;
int retval;

sset_init(&lports);
get_local_iface_ids(ctx, &lports);

txn = ovsdb_idl_txn_create(ctx->ovnsb_idl);
ovsdb_idl_txn_add_comment(txn,
"ovn-controller: updating bindings for '%s'",
ctx->chassis_name);

SBREC_BINDINGS_FOR_EACH(bindings_rec, ctx->ovnsb_idl) {
if (sset_find_and_delete(&lports, bindings_rec->logical_port)) {
if (!strcmp(bindings_rec->chassis, ctx->chassis_name)) {
continue;
}
if (bindings_rec->chassis[0]) {
VLOG_INFO("Changing chassis for lport %s from %s to %s",
bindings_rec->logical_port, bindings_rec->chassis,
ctx->chassis_name);
}
sbrec_bindings_set_chassis(bindings_rec, ctx->chassis_name);
} else if (!strcmp(bindings_rec->chassis, ctx->chassis_name)) {
sbrec_bindings_set_chassis(bindings_rec, "");
}
}

retval = ovsdb_idl_txn_commit_block(txn);
if (retval == TXN_ERROR) {
VLOG_INFO("Problem committing bindings information: %s",
ovsdb_idl_txn_status_to_string(retval));
}

ovsdb_idl_txn_destroy(txn);

SSET_FOR_EACH (name, &lports) {
VLOG_DBG("No binding record for lport %s", name);
}
sset_destroy(&lports);
}

void
bindings_destroy(struct controller_ctx *ctx)
{
int retval = TXN_TRY_AGAIN;

ovs_assert(ctx->ovnsb_idl);

while (retval != TXN_SUCCESS && retval != TXN_UNCHANGED) {
const struct sbrec_bindings *bindings_rec;
struct ovsdb_idl_txn *txn;

txn = ovsdb_idl_txn_create(ctx->ovnsb_idl);
ovsdb_idl_txn_add_comment(txn,
"ovn-controller: removing all bindings for '%s'",
ctx->chassis_name);

SBREC_BINDINGS_FOR_EACH(bindings_rec, ctx->ovnsb_idl) {
if (!strcmp(bindings_rec->chassis, ctx->chassis_name)) {
sbrec_bindings_set_chassis(bindings_rec, "");
}
}

retval = ovsdb_idl_txn_commit_block(txn);
if (retval == TXN_ERROR) {
VLOG_INFO("Problem removing bindings: %s",
ovsdb_idl_txn_status_to_string(retval));
}

ovsdb_idl_txn_destroy(txn);
}
}
@@ -0,0 +1,26 @@
/* 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_BINDINGS_H
#define OVN_BINDINGS_H 1

struct controller_ctx;

void bindings_init(struct controller_ctx *);
void bindings_run(struct controller_ctx *);
void bindings_destroy(struct controller_ctx *);

#endif /* ovn/bindings.h */

0 comments on commit 717c7fc

Please sign in to comment.