mirror of
https://github.com/openvswitch/ovs
synced 2025-09-03 15:55:19 +00:00
bridge: Tolerate missing Port and Interface records for local port.
Until now, ovs-vswitchd has been unable to configure IP addresses and routes for bridges whose Bridge records lack a Port and an Interface record for the bridge's local port (e.g. OFPP_LOCAL, the port with the same name as the bridge itself). When such a bridge was reconfigured, ovs-vswitchd would output a log message that worried people. This commit fixes the internal limitation that led to the message being printed. Bug #5385.
This commit is contained in:
@@ -1108,6 +1108,15 @@ ovsdb_idl_get(const struct ovsdb_idl_row *row,
|
||||
|
||||
return ovsdb_idl_read(row, column);
|
||||
}
|
||||
|
||||
/* Returns false if 'row' was obtained from the IDL, true if it was initialized
|
||||
* to all-zero-bits by some other entity. If 'row' was set up some other way
|
||||
* then the return value is indeterminate. */
|
||||
bool
|
||||
ovsdb_idl_row_is_synthetic(const struct ovsdb_idl_row *row)
|
||||
{
|
||||
return row->table == NULL;
|
||||
}
|
||||
|
||||
/* Transactions. */
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2009, 2010 Nicira Networks.
|
||||
/* Copyright (c) 2009, 2010, 2011 Nicira Networks.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -105,6 +105,8 @@ const struct ovsdb_datum *ovsdb_idl_get(const struct ovsdb_idl_row *,
|
||||
const struct ovsdb_idl_column *,
|
||||
enum ovsdb_atomic_type key_type,
|
||||
enum ovsdb_atomic_type value_type);
|
||||
|
||||
bool ovsdb_idl_row_is_synthetic(const struct ovsdb_idl_row *);
|
||||
|
||||
/* Transactions. */
|
||||
|
||||
|
@@ -185,6 +185,11 @@ struct bridge {
|
||||
|
||||
/* Port mirroring. */
|
||||
struct mirror *mirrors[MAX_MIRRORS];
|
||||
|
||||
/* Synthetic local port if necessary. */
|
||||
struct ovsrec_port synth_local_port;
|
||||
struct ovsrec_interface synth_local_iface;
|
||||
struct ovsrec_interface *synth_local_ifacep;
|
||||
};
|
||||
|
||||
/* List of all bridges. */
|
||||
@@ -264,6 +269,7 @@ static void iface_update_qos(struct iface *, const struct ovsrec_qos *);
|
||||
static void iface_update_cfm(struct iface *);
|
||||
static bool iface_refresh_cfm_stats(struct iface *iface);
|
||||
static bool iface_get_carrier(const struct iface *);
|
||||
static bool iface_is_synthetic(const struct iface *);
|
||||
|
||||
static void shash_from_ovs_idl_map(char **keys, char **values, size_t n,
|
||||
struct shash *);
|
||||
@@ -1140,6 +1146,10 @@ iface_refresh_status(struct iface *iface)
|
||||
int64_t mtu_64;
|
||||
int error;
|
||||
|
||||
if (iface_is_synthetic(iface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
shash_init(&sh);
|
||||
|
||||
if (!netdev_get_status(iface->netdev, &sh)) {
|
||||
@@ -1282,6 +1292,10 @@ iface_refresh_stats(struct iface *iface)
|
||||
|
||||
struct netdev_stats stats;
|
||||
|
||||
if (iface_is_synthetic(iface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Intentionally ignore return value, since errors will set 'stats' to
|
||||
* all-1s, and we will deal with that correctly below. */
|
||||
netdev_get_stats(iface->netdev, &stats);
|
||||
@@ -1716,6 +1730,7 @@ bridge_destroy(struct bridge *br)
|
||||
hmap_destroy(&br->ifaces);
|
||||
hmap_destroy(&br->ports);
|
||||
shash_destroy(&br->iface_by_name);
|
||||
free(br->synth_local_iface.type);
|
||||
free(br->name);
|
||||
free(br);
|
||||
}
|
||||
@@ -1841,22 +1856,28 @@ bridge_reconfigure_one(struct bridge *br)
|
||||
br->name, name);
|
||||
}
|
||||
}
|
||||
if (!shash_find(&new_ports, br->name)) {
|
||||
struct dpif_port dpif_port;
|
||||
char *type;
|
||||
|
||||
/* If we have a controller, then we need a local port. Complain if the
|
||||
* user didn't specify one.
|
||||
*
|
||||
* XXX perhaps we should synthesize a port ourselves in this case. */
|
||||
if (bridge_get_controllers(br, NULL)) {
|
||||
char local_name[IF_NAMESIZE];
|
||||
int error;
|
||||
VLOG_WARN("bridge %s: no port named %s, synthesizing one",
|
||||
br->name, br->name);
|
||||
|
||||
error = dpif_port_get_name(br->dpif, ODPP_LOCAL,
|
||||
local_name, sizeof local_name);
|
||||
if (!error && !shash_find(&new_ports, local_name)) {
|
||||
VLOG_WARN("bridge %s: controller specified but no local port "
|
||||
"(port named %s) defined",
|
||||
br->name, local_name);
|
||||
}
|
||||
dpif_port_query_by_number(br->dpif, ODPP_LOCAL, &dpif_port);
|
||||
type = xstrdup(dpif_port.type ? dpif_port.type : "internal");
|
||||
dpif_port_destroy(&dpif_port);
|
||||
|
||||
br->synth_local_port.interfaces = &br->synth_local_ifacep;
|
||||
br->synth_local_port.n_interfaces = 1;
|
||||
br->synth_local_port.name = br->name;
|
||||
|
||||
br->synth_local_iface.name = br->name;
|
||||
free(br->synth_local_iface.type);
|
||||
br->synth_local_iface.type = type;
|
||||
|
||||
br->synth_local_ifacep = &br->synth_local_iface;
|
||||
|
||||
shash_add(&new_ports, br->name, &br->synth_local_port);
|
||||
}
|
||||
|
||||
/* Get rid of deleted ports.
|
||||
@@ -3405,7 +3426,7 @@ iface_set_mac(struct iface *iface)
|
||||
static void
|
||||
iface_set_ofport(const struct ovsrec_interface *if_cfg, int64_t ofport)
|
||||
{
|
||||
if (if_cfg) {
|
||||
if (if_cfg && !ovsdb_idl_row_is_synthetic(&if_cfg->header_)) {
|
||||
ovsrec_interface_set_ofport(if_cfg, &ofport, 1);
|
||||
}
|
||||
}
|
||||
@@ -3565,6 +3586,14 @@ iface_get_carrier(const struct iface *iface)
|
||||
/* XXX */
|
||||
return netdev_get_carrier(iface->netdev);
|
||||
}
|
||||
|
||||
/* Returns true if 'iface' is synthetic, that is, if we constructed it locally
|
||||
* instead of obtaining it from the database. */
|
||||
static bool
|
||||
iface_is_synthetic(const struct iface *iface)
|
||||
{
|
||||
return ovsdb_idl_row_is_synthetic(&iface->cfg->header_);
|
||||
}
|
||||
|
||||
/* Port mirroring. */
|
||||
|
||||
|
Reference in New Issue
Block a user