In my opinion, this makes the code more obviously correct in many places,
because there are generally fewer variables. One must generally keep two
variables in sync for iterating through an array: the array index and the
contents of the array at that index. For iterating through an hmap, only
the map element is necessary.
A linked list would also be a reasonable choice for the bridge's collection
of ports. I chose to use an hmap because we already had an index by name
and it seemed OK to use only one index. I decided not to keep the shash
because they are less convenient for iteration than an hmap.
---
vswitchd/bridge.c | 167 +++++++++++++++++++++++------------------------------
1 files changed, 73 insertions(+), 94 deletions(-)
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 52b4c95..2d0df9b 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -155,12 +155,13 @@ struct mirror {
#define FLOOD_PORT ((struct port *) 1) /* The 'flood' output port. */
struct port {
struct bridge *bridge;
- size_t port_idx;
+ struct hmap_node hmap_node; /* Element in struct bridge's "ports" hmap. */
+ char *name;
+
int vlan; /* -1=trunk port, else a 12-bit VLAN ID. */
unsigned long *trunks; /* Bitmap of trunked VLANs, if 'vlan' == -1.
* NULL if all VLANs are trunked. */
const struct ovsrec_port *cfg;
- char *name;
/* Monitoring. */
struct netdev_monitor *monitor; /* Tracks carrier. NULL if miimon. */
@@ -213,10 +214,8 @@ struct bridge {
struct hmap ifaces; /* Contains "struct iface"s. */
/* Bridge ports. */
- struct port **ports;
- size_t n_ports, allocated_ports;
+ struct hmap ports; /* "struct port"s indexed by name. */
struct shash iface_by_name; /* "struct iface"s indexed by name. */
- struct shash port_by_name; /* "struct port"s indexed by name. */
/* Bonding. */
bool has_bonded_ports;
@@ -464,22 +463,19 @@ iterate_and_prune_ifaces(struct bridge *br,
void *aux),
void *aux)
{
- size_t i;
+ struct port *port, *next_port;
- for (i = 0; i < br->n_ports; ) {
- struct port *port = br->ports[i];
- struct iface *iface, *next;
+ HMAP_FOR_EACH_SAFE (port, next_port, hmap_node, &br->ports) {
+ struct iface *iface, *next_iface;
- LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) {
+ LIST_FOR_EACH_SAFE (iface, next_iface, port_elem, &port->ifaces) {
if (!cb(br, iface, aux)) {
iface_set_ofport(iface->cfg, -1);
iface_destroy(iface);
}
}
- if (port->n_ifaces) {
- i++;
- } else {
+ if (!port->n_ifaces) {
VLOG_WARN("%s port has no interfaces, dropping", port->name);
port_destroy(port);
}
@@ -810,7 +806,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch
*ovs_cfg)
"with another vswitch, choose an engine id less "
"than 128", br->name);
}
- if (br->n_ports > 508) {
+ if (hmap_count(&br->ports) > 508) {
VLOG_WARN("bridge %s: netflow port mangling will conflict "
"with another port when more than 508 ports are "
"used", br->name);
@@ -884,8 +880,9 @@ bridge_reconfigure(const struct ovsrec_open_vswitch
*ovs_cfg)
bridge_reconfigure_remotes(br, managers, n_managers);
}
LIST_FOR_EACH (br, node, &all_bridges) {
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ struct port *port;
+
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
struct iface *iface;
if (port->monitor) {
@@ -949,7 +946,7 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t
ea[ETH_ADDR_LEN],
struct iface **hw_addr_iface)
{
const char *hwaddr;
- size_t i;
+ struct port *port;
int error;
*hw_addr_iface = NULL;
@@ -970,8 +967,7 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t
ea[ETH_ADDR_LEN],
/* Otherwise choose the minimum non-local MAC address among all of the
* interfaces. */
memset(ea, 0xff, ETH_ADDR_LEN);
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
uint8_t iface_ea[ETH_ADDR_LEN];
struct iface *candidate;
struct iface *iface;
@@ -1444,10 +1440,9 @@ bridge_run(void)
txn = ovsdb_idl_txn_create(idl);
LIST_FOR_EACH (br, node, &all_bridges) {
- size_t i;
+ struct port *port;
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
struct iface *iface;
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
@@ -1473,7 +1468,7 @@ bridge_wait(void)
struct bridge *br;
LIST_FOR_EACH (br, node, &all_bridges) {
- size_t i;
+ struct port *port;
ofproto_wait(br->ofproto);
if (ofproto_has_primary_controller(br->ofproto)) {
@@ -1482,8 +1477,8 @@ bridge_wait(void)
mac_learning_wait(br->ml);
- for (i = 0; i < br->n_ports; i++) {
- port_wait(br->ports[i]);
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
+ port_wait(port);
}
}
ovsdb_idl_wait(idl);
@@ -1652,9 +1647,8 @@ bridge_create(const struct ovsrec_bridge *br_cfg)
br->ml = mac_learning_create();
eth_addr_nicira_random(br->default_ea);
+ hmap_init(&br->ports);
hmap_init(&br->ifaces);
-
- shash_init(&br->port_by_name);
shash_init(&br->iface_by_name);
br->flush = false;
@@ -1670,10 +1664,11 @@ static void
bridge_destroy(struct bridge *br)
{
if (br) {
+ struct port *port, *next;
int error;
- while (br->n_ports > 0) {
- port_destroy(br->ports[br->n_ports - 1]);
+ HMAP_FOR_EACH_SAFE (port, next, hmap_node, &br->ports) {
+ port_destroy(port);
}
list_remove(&br->node);
error = dpif_delete(br->dpif);
@@ -1685,9 +1680,8 @@ bridge_destroy(struct bridge *br)
ofproto_destroy(br->ofproto);
mac_learning_destroy(br->ml);
hmap_destroy(&br->ifaces);
- shash_destroy(&br->port_by_name);
+ hmap_destroy(&br->ports);
shash_destroy(&br->iface_by_name);
- free(br->ports);
free(br->name);
free(br);
}
@@ -1754,7 +1748,7 @@ bridge_unixctl_reconnect(struct unixctl_conn *conn,
static int
bridge_run_one(struct bridge *br)
{
- size_t i;
+ struct port *port;
int error;
error = ofproto_run1(br->ofproto);
@@ -1764,8 +1758,8 @@ bridge_run_one(struct bridge *br)
mac_learning_run(br->ml, ofproto_get_revalidate_set(br->ofproto));
- for (i = 0; i < br->n_ports; i++) {
- port_run(br->ports[i]);
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
+ port_run(port);
}
error = ofproto_run2(br->ofproto, br->flush);
@@ -1798,18 +1792,13 @@ bridge_get_controllers(const struct bridge *br,
static void
bridge_reconfigure_one(struct bridge *br)
{
- struct shash old_ports, new_ports;
+ enum ofproto_fail_mode fail_mode;
struct svec snoops, old_snoops;
+ struct port *port, *next;
struct shash_node *node;
- enum ofproto_fail_mode fail_mode;
+ struct shash new_ports;
size_t i;
- /* Collect old ports. */
- shash_init(&old_ports);
- for (i = 0; i < br->n_ports; i++) {
- shash_add(&old_ports, br->ports[i]->name, br->ports[i]);
- }
-
/* Collect new ports. */
shash_init(&new_ports);
for (i = 0; i < br->cfg->n_ports; i++) {
@@ -1839,11 +1828,10 @@ bridge_reconfigure_one(struct bridge *br)
/* Get rid of deleted ports.
* Get rid of deleted interfaces on ports that still exist. */
- SHASH_FOR_EACH (node, &old_ports) {
- struct port *port = node->data;
+ HMAP_FOR_EACH_SAFE (port, next, hmap_node, &br->ports) {
const struct ovsrec_port *port_cfg;
- port_cfg = shash_find_data(&new_ports, node->name);
+ port_cfg = shash_find_data(&new_ports, port->name);
if (!port_cfg) {
port_destroy(port);
} else {
@@ -1855,7 +1843,7 @@ bridge_reconfigure_one(struct bridge *br)
* Add new interfaces to existing ports.
* Reconfigure existing ports. */
SHASH_FOR_EACH (node, &new_ports) {
- struct port *port = shash_find_data(&old_ports, node->name);
+ struct port *port = port_lookup(br, node->name);
if (!port) {
port = port_create(br, node->name);
}
@@ -1867,7 +1855,6 @@ bridge_reconfigure_one(struct bridge *br)
port_destroy(port);
}
}
- shash_destroy(&old_ports);
shash_destroy(&new_ports);
/* Set the fail-mode */
@@ -2069,11 +2056,10 @@ bridge_reconfigure_remotes(struct bridge *br,
static void
bridge_get_all_ifaces(const struct bridge *br, struct shash *ifaces)
{
- size_t i;
+ struct port *port;
shash_init(ifaces);
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
struct iface *iface;
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
@@ -2098,11 +2084,10 @@ bridge_fetch_dp_ifaces(struct bridge *br)
{
struct dpif_port_dump dump;
struct dpif_port dpif_port;
- size_t i;
+ struct port *port;
/* Reset all interface numbers. */
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
struct iface *iface;
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
@@ -2592,7 +2577,6 @@ compose_dsts(const struct bridge *br, const struct flow
*flow, uint16_t vlan,
mirror_mask_t mirrors = in_port->src_mirrors;
struct dst dst;
int flow_vlan;
- size_t i;
flow_vlan = vlan_tci_to_vid(flow->vlan_tci);
if (flow_vlan == 0) {
@@ -2600,8 +2584,9 @@ compose_dsts(const struct bridge *br, const struct flow
*flow, uint16_t vlan,
}
if (out_port == FLOOD_PORT) {
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ struct port *port;
+
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
if (port != in_port
&& port_is_floodable(port)
&& port_includes_vlan(port, vlan)
@@ -2627,8 +2612,9 @@ compose_dsts(const struct bridge *br, const struct flow
*flow, uint16_t vlan,
dst_set_add(set, &dst);
}
} else {
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ struct port *port;
+
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
if (port_includes_vlan(port, m->out_vlan)
&& set_dst(&dst, flow, in_port, port, tags))
{
@@ -3043,16 +3029,15 @@ static void
bridge_account_checkpoint_ofhook_cb(void *br_)
{
struct bridge *br = br_;
+ struct port *port;
long long int now;
- size_t i;
if (!br->has_bonded_ports) {
return;
}
now = time_msec();
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
if (port->n_ifaces > 1 && port->bond_mode != BM_AB
&& now >= port->bond_next_rebalance) {
port->bond_next_rebalance = now + port->bond_rebalance_interval;
@@ -3466,10 +3451,9 @@ bond_unixctl_list(struct unixctl_conn *conn,
ds_put_cstr(&ds, "bridge\tbond\ttype\tslaves\n");
LIST_FOR_EACH (br, node, &all_bridges) {
- size_t i;
+ struct port *port;
- for (i = 0; i < br->n_ports; i++) {
- const struct port *port = br->ports[i];
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
if (port->n_ifaces > 1) {
struct iface *iface;
@@ -3495,10 +3479,9 @@ bond_find(const char *name)
const struct bridge *br;
LIST_FOR_EACH (br, node, &all_bridges) {
- size_t i;
+ struct port *port;
- for (i = 0; i < br->n_ports; i++) {
- struct port *port = br->ports[i];
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
if (!strcmp(port->name, name) && port->n_ifaces > 1) {
return port;
}
@@ -3901,19 +3884,13 @@ port_create(struct bridge *br, const char *name)
port = xzalloc(sizeof *port);
port->bridge = br;
- port->port_idx = br->n_ports;
port->vlan = -1;
port->trunks = NULL;
port->name = xstrdup(name);
port->active_iface = NULL;
list_init(&port->ifaces);
- if (br->n_ports >= br->allocated_ports) {
- br->ports = x2nrealloc(br->ports, &br->allocated_ports,
- sizeof *br->ports);
- }
- br->ports[br->n_ports++] = port;
- shash_add_assert(&br->port_by_name, port->name, port);
+ hmap_insert(&br->ports, &port->hmap_node, hash_string(port->name, 0));
VLOG_INFO("created port %s on bridge %s", port->name, br->name);
bridge_flush(br);
@@ -4208,7 +4185,6 @@ port_destroy(struct port *port)
if (port) {
struct bridge *br = port->bridge;
struct iface *iface, *next;
- struct port *del;
int i;
for (i = 0; i < MAX_MIRRORS; i++) {
@@ -4222,10 +4198,7 @@ port_destroy(struct port *port)
iface_destroy(iface);
}
- shash_find_and_delete_assert(&br->port_by_name, port->name);
-
- del = br->ports[port->port_idx] = br->ports[--br->n_ports];
- del->port_idx = port->port_idx;
+ hmap_remove(&br->ports, &port->hmap_node);
VLOG_INFO("destroyed port %s on bridge %s", port->name, br->name);
@@ -4248,7 +4221,15 @@ port_from_dp_ifidx(const struct bridge *br, uint16_t
dp_ifidx)
static struct port *
port_lookup(const struct bridge *br, const char *name)
{
- return shash_find_data(&br->port_by_name, name);
+ struct port *port;
+
+ HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_string(name, 0),
+ &br->ports) {
+ if (!strcmp(port->name, name)) {
+ return port;
+ }
+ }
+ return NULL;
}
static struct iface *
@@ -4666,6 +4647,7 @@ static void
mirror_reconfigure(struct bridge *br)
{
unsigned long *rspan_vlans;
+ struct port *port;
int i;
/* Get rid of deleted mirrors. */
@@ -4695,8 +4677,8 @@ mirror_reconfigure(struct bridge *br)
}
/* Update port reserved status. */
- for (i = 0; i < br->n_ports; i++) {
- br->ports[i]->is_mirror_output_port = false;
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
+ port->is_mirror_output_port = false;
}
for (i = 0; i < MAX_MIRRORS; i++) {
struct mirror *m = br->mirrors[i];
@@ -4768,11 +4750,11 @@ mirror_destroy(struct mirror *m)
{
if (m) {
struct bridge *br = m->bridge;
- size_t i;
+ struct port *port;
- for (i = 0; i < br->n_ports; i++) {
- br->ports[i]->src_mirrors &= ~(MIRROR_MASK_C(1) << m->idx);
- br->ports[i]->dst_mirrors &= ~(MIRROR_MASK_C(1) << m->idx);
+ HMAP_FOR_EACH (port, hmap_node, &br->ports) {
+ port->src_mirrors &= ~(MIRROR_MASK_C(1) << m->idx);
+ port->dst_mirrors &= ~(MIRROR_MASK_C(1) << m->idx);
}
shash_destroy(&m->src_ports);
@@ -4858,10 +4840,10 @@ mirror_reconfigure_one(struct mirror *m, struct
ovsrec_mirror *cfg)
struct shash src_ports, dst_ports;
mirror_mask_t mirror_bit;
struct port *out_port;
+ struct port *port;
int out_vlan;
size_t n_vlans;
int *vlans;
- size_t i;
/* Set name. */
if (strcmp(cfg->name, m->name)) {
@@ -4898,10 +4880,9 @@ mirror_reconfigure_one(struct mirror *m, struct
ovsrec_mirror *cfg)
shash_init(&src_ports);
shash_init(&dst_ports);
if (cfg->select_all) {
- for (i = 0; i < m->bridge->n_ports; i++) {
- const char *name = m->bridge->ports[i]->name;
- shash_add_once(&src_ports, name, NULL);
- shash_add_once(&dst_ports, name, NULL);
+ HMAP_FOR_EACH (port, hmap_node, &m->bridge->ports) {
+ shash_add_once(&src_ports, port->name, NULL);
+ shash_add_once(&dst_ports, port->name, NULL);
}
vlans = NULL;
n_vlans = 0;
@@ -4936,9 +4917,7 @@ mirror_reconfigure_one(struct mirror *m, struct
ovsrec_mirror *cfg)
/* Update ports. */
mirror_bit = MIRROR_MASK_C(1) << m->idx;
- for (i = 0; i < m->bridge->n_ports; i++) {
- struct port *port = m->bridge->ports[i];
-
+ HMAP_FOR_EACH (port, hmap_node, &m->bridge->ports) {
if (shash_find(&m->src_ports, port->name)
|| (m->n_vlans
&& (!port->vlan
--
1.7.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev