[ovs-dev] [bridge 09/15] bridge: Change port's 'ifaces' member from array to list.

Ben Pfaff blp at nicira.com
Mon Mar 21 17:59:50 UTC 2011


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 a list, only
the list element is necessary.
---
 vswitchd/bridge.c |  169 +++++++++++++++++++++++++---------------------------
 1 files changed, 81 insertions(+), 88 deletions(-)

diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 4e843cb..6a4ead1 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -98,6 +98,7 @@ static void dst_set_free(struct dst_set *);
 
 struct iface {
     /* These members are always valid. */
+    struct list port_elem;      /* Element in struct port's "ifaces" list. */
     struct port *port;          /* Containing port. */
     char *name;                 /* Host network device name. */
     tag_type tag;               /* Tag associated with this interface. */
@@ -168,8 +169,8 @@ struct port {
 
     /* An ordinary bridge port has 1 interface.
      * A bridge port for bonding has at least 2 interfaces. */
-    struct iface **ifaces;
-    size_t n_ifaces, allocated_ifaces;
+    struct list ifaces;         /* List of "struct iface"s. */
+    size_t n_ifaces;            /* list_size(ifaces). */
 
     /* Bonding info. */
     enum bond_mode bond_mode;   /* Type of the bond. BM_SLB is the default. */
@@ -279,6 +280,7 @@ static void port_del_ifaces(struct port *, const struct ovsrec_port *);
 static void port_destroy(struct port *);
 static struct port *port_lookup(const struct bridge *, const char *name);
 static struct iface *port_lookup_iface(const struct port *, const char *name);
+static struct iface *port_get_an_iface(const struct port *);
 static struct port *port_from_dp_ifidx(const struct bridge *,
                                        uint16_t dp_ifidx);
 static void port_update_bonding(struct port *);
@@ -462,15 +464,14 @@ iterate_and_prune_ifaces(struct bridge *br,
                                     void *aux),
                          void *aux)
 {
-    size_t i, j;
+    size_t i;
 
     for (i = 0; i < br->n_ports; ) {
         struct port *port = br->ports[i];
-        for (j = 0; j < port->n_ifaces; ) {
-            struct iface *iface = port->ifaces[j];
-            if (cb(br, iface, aux)) {
-                j++;
-            } else {
+        struct iface *iface, *next;
+
+        LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) {
+            if (!cb(br, iface, aux)) {
                 iface_set_ofport(iface->cfg, -1);
                 iface_destroy(iface);
             }
@@ -885,11 +886,11 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
     LIST_FOR_EACH (br, node, &all_bridges) {
         for (i = 0; i < br->n_ports; i++) {
             struct port *port = br->ports[i];
-            int j;
+            struct iface *iface;
 
             if (port->monitor) {
-                for (j = 0; j < port->n_ifaces; j++) {
-                    netdev_monitor_add(port->monitor, port->ifaces[j]->netdev);
+                LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+                    netdev_monitor_add(port->monitor, iface->netdev);
                 }
             } else {
                 port->miimon_next_update = 0;
@@ -898,8 +899,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
             port_update_lacp(port);
             port_update_bonding(port);
 
-            for (j = 0; j < port->n_ifaces; j++) {
-                iface_update_qos(port->ifaces[j], port->cfg->qos);
+            LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+                iface_update_qos(iface, port->cfg->qos);
             }
         }
     }
@@ -948,7 +949,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, j;
+    size_t i;
     int error;
 
     *hw_addr_iface = NULL;
@@ -972,6 +973,7 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
     for (i = 0; i < br->n_ports; i++) {
         struct port *port = br->ports[i];
         uint8_t iface_ea[ETH_ADDR_LEN];
+        struct iface *candidate;
         struct iface *iface;
 
         /* Mirror output ports don't participate. */
@@ -980,12 +982,11 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
         }
 
         /* Choose the MAC address to represent the port. */
+        iface = NULL;
         if (port->cfg->mac && eth_addr_from_string(port->cfg->mac, iface_ea)) {
             /* Find the interface with this Ethernet address (if any) so that
              * we can provide the correct devname to the caller. */
-            iface = NULL;
-            for (j = 0; j < port->n_ifaces; j++) {
-                struct iface *candidate = port->ifaces[j];
+            LIST_FOR_EACH (candidate, port_elem, &port->ifaces) {
                 uint8_t candidate_ea[ETH_ADDR_LEN];
                 if (!netdev_get_etheraddr(candidate->netdev, candidate_ea)
                     && eth_addr_equals(iface_ea, candidate_ea)) {
@@ -999,10 +1000,8 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
              * scripts always add slaves to a bond in alphabetical order, so
              * for compatibility we choose the interface with the name that is
              * first in alphabetical order. */
-            iface = port->ifaces[0];
-            for (j = 1; j < port->n_ifaces; j++) {
-                struct iface *candidate = port->ifaces[j];
-                if (strcmp(candidate->name, iface->name) < 0) {
+            LIST_FOR_EACH (candidate, port_elem, &port->ifaces) {
+                if (!iface || strcmp(candidate->name, iface->name) < 0) {
                     iface = candidate;
                 }
             }
@@ -1449,10 +1448,9 @@ bridge_run(void)
 
                 for (i = 0; i < br->n_ports; i++) {
                     struct port *port = br->ports[i];
-                    size_t j;
+                    struct iface *iface;
 
-                    for (j = 0; j < port->n_ifaces; j++) {
-                        struct iface *iface = port->ifaces[j];
+                    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
                         iface_refresh_stats(iface);
                         iface_refresh_cfm_stats(iface);
                         iface_refresh_status(iface);
@@ -1523,7 +1521,7 @@ bridge_unixctl_fdb_show(struct unixctl_conn *conn,
             continue;
         }
         ds_put_format(&ds, "%5d  %4d  "ETH_ADDR_FMT"  %3d\n",
-                      br->ports[e->port]->ifaces[0]->dp_ifidx,
+                      port_get_an_iface(br->ports[e->port])->dp_ifidx,
                       e->vlan, ETH_ADDR_ARGS(e->mac), mac_entry_age(e));
     }
     unixctl_command_reply(conn, 200, ds_cstr(&ds));
@@ -2074,13 +2072,14 @@ bridge_reconfigure_remotes(struct bridge *br,
 static void
 bridge_get_all_ifaces(const struct bridge *br, struct shash *ifaces)
 {
-    size_t i, j;
+    size_t i;
 
     shash_init(ifaces);
     for (i = 0; i < br->n_ports; i++) {
         struct port *port = br->ports[i];
-        for (j = 0; j < port->n_ifaces; j++) {
-            struct iface *iface = port->ifaces[j];
+        struct iface *iface;
+
+        LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
             shash_add_once(ifaces, iface->name, iface);
         }
         if (port->n_ifaces > 1 && port->cfg->bond_fake_iface) {
@@ -2102,13 +2101,14 @@ bridge_fetch_dp_ifaces(struct bridge *br)
 {
     struct dpif_port_dump dump;
     struct dpif_port dpif_port;
-    size_t i, j;
+    size_t i;
 
     /* Reset all interface numbers. */
     for (i = 0; i < br->n_ports; i++) {
         struct port *port = br->ports[i];
-        for (j = 0; j < port->n_ifaces; j++) {
-            struct iface *iface = port->ifaces[j];
+        struct iface *iface;
+
+        LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
             iface->dp_ifidx = -1;
         }
     }
@@ -2182,12 +2182,10 @@ bond_choose_iface(const struct port *port)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
     struct iface *best_down_slave;
-    size_t i;
+    struct iface *iface;
 
     best_down_slave = NULL;
-    for (i = 0; i < port->n_ifaces; i++) {
-        struct iface *iface = port->ifaces[i];
-
+    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
         if (iface->enabled) {
             return iface;
         } else if ((!best_down_slave
@@ -2216,7 +2214,7 @@ choose_output_iface(const struct port *port, const struct flow *flow,
 
     assert(port->n_ifaces);
     if (port->n_ifaces == 1) {
-        iface = port->ifaces[0];
+        iface = port_get_an_iface(port);
     } else if (port->bond_mode == BM_AB) {
         iface = port->active_iface;
         if (!iface) {
@@ -2356,14 +2354,14 @@ bond_update_fake_iface_stats(struct port *port)
 {
     struct netdev_stats bond_stats;
     struct netdev *bond_dev;
-    size_t i;
+    struct iface *iface;
 
     memset(&bond_stats, 0, sizeof bond_stats);
 
-    for (i = 0; i < port->n_ifaces; i++) {
+    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
         struct netdev_stats slave_stats;
 
-        if (!netdev_get_stats(port->ifaces[i]->netdev, &slave_stats)) {
+        if (!netdev_get_stats(iface->netdev, &slave_stats)) {
             /* XXX: We swap the stats here because they are swapped back when
              * reported by the internal device.  The reason for this is
              * internal devices normally represent packets going into the system
@@ -2389,18 +2387,17 @@ bond_update_fake_iface_stats(struct port *port)
 static void
 bond_run(struct port *port)
 {
-    size_t i;
+    struct iface *iface;
 
     if (port->n_ifaces < 2) {
         return;
     }
 
-    for (i = 0; i < port->n_ifaces; i++) {
-        bond_link_status_update(port->ifaces[i]);
+    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+        bond_link_status_update(iface);
     }
 
-    for (i = 0; i < port->n_ifaces; i++) {
-        struct iface *iface = port->ifaces[i];
+    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
         if (time_msec() >= iface->delay_expires) {
             bond_enable_slave(iface, !iface->enabled);
         }
@@ -2416,14 +2413,13 @@ bond_run(struct port *port)
 static void
 bond_wait(struct port *port)
 {
-    size_t i;
+    struct iface *iface;
 
     if (port->n_ifaces < 2) {
         return;
     }
 
-    for (i = 0; i < port->n_ifaces; i++) {
-        struct iface *iface = port->ifaces[i];
+    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
         if (iface->delay_expires != LLONG_MAX) {
             poll_timer_wait_until(iface->delay_expires);
         }
@@ -2563,11 +2559,11 @@ port_includes_vlan(const struct port *port, uint16_t vlan)
 static bool
 port_is_floodable(const struct port *port)
 {
-    int i;
+    struct iface *iface;
 
-    for (i = 0; i < port->n_ifaces; i++) {
+    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
         if (!ofproto_port_is_floodable(port->bridge->ofproto,
-                                       port->ifaces[i]->dp_ifidx)) {
+                                       iface->dp_ifidx)) {
             return false;
         }
     }
@@ -2584,6 +2580,13 @@ port_get_active_iface_tag(const struct port *port)
             : port->no_ifaces_tag);
 }
 
+/* Returns an arbitrary interface within 'port'. */
+static struct iface *
+port_get_an_iface(const struct port *port)
+{
+    return CONTAINER_OF(port->ifaces.next, struct iface, port_elem);
+}
+
 static void
 compose_dsts(const struct bridge *br, const struct flow *flow, uint16_t vlan,
              const struct port *in_port, const struct port *out_port,
@@ -3243,6 +3246,7 @@ bond_rebalance_port(struct port *port)
     struct bond_entry *hashes[BOND_MASK + 1];
     struct slave_balance *b, *from, *to;
     struct bond_entry *e;
+    struct iface *iface;
     size_t i;
 
     assert(port->bond_mode != BM_AB);
@@ -3258,13 +3262,15 @@ bond_rebalance_port(struct port *port)
      * become contiguous in memory, and then we point each 'hashes' members of
      * a slave_balance structure to the start of a contiguous group. */
     n_bals = port->n_ifaces;
-    bals = xmalloc(n_bals * sizeof *bals);
-    for (b = bals; b < &bals[n_bals]; b++) {
-        b->iface = port->ifaces[b - bals];
+    b = bals = xmalloc(n_bals * sizeof *bals);
+    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+        b->iface = iface;
         b->tx_bytes = 0;
         b->hashes = NULL;
         b->n_hashes = 0;
+        b++;
     }
+    assert(b == &bals[n_bals]);
     for (i = 0; i <= BOND_MASK; i++) {
         hashes[i] = &port->bond_hash[i];
     }
@@ -3463,13 +3469,12 @@ bond_unixctl_list(struct unixctl_conn *conn,
         for (i = 0; i < br->n_ports; i++) {
             const struct port *port = br->ports[i];
             if (port->n_ifaces > 1) {
-                size_t j;
+                struct iface *iface;
 
                 ds_put_format(&ds, "%s\t%s\t%s\t", br->name, port->name,
                               bond_mode_to_string(port->bond_mode));
-                for (j = 0; j < port->n_ifaces; j++) {
-                    const struct iface *iface = port->ifaces[j];
-                    if (j) {
+                LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+                    if (&iface->port_elem != port->ifaces.next) {
                         ds_put_cstr(&ds, ", ");
                     }
                     ds_put_cstr(&ds, iface->name);
@@ -3506,7 +3511,7 @@ bond_unixctl_show(struct unixctl_conn *conn,
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
     const struct port *port;
-    size_t j;
+    struct iface *iface;
 
     port = bond_find(args);
     if (!port) {
@@ -3546,8 +3551,7 @@ bond_unixctl_show(struct unixctl_conn *conn,
                       port->bond_next_rebalance - time_msec());
     }
 
-    for (j = 0; j < port->n_ifaces; j++) {
-        const struct iface *iface = port->ifaces[j];
+    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
         struct bond_entry *be;
         struct flow flow;
 
@@ -3851,20 +3855,18 @@ port_run(struct port *port)
             free(devname);
         }
     } else if (time_msec() >= port->miimon_next_update) {
-        size_t i;
+        struct iface *iface;
 
-        for (i = 0; i < port->n_ifaces; i++) {
-            struct iface *iface = port->ifaces[i];
+        LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
             iface_update_carrier(iface);
         }
         port->miimon_next_update = time_msec() + port->miimon_interval;
     }
 
     if (port->lacp) {
-        size_t i;
+        struct iface *iface;
 
-        for (i = 0; i < port->n_ifaces; i++) {
-            struct iface *iface = port->ifaces[i];
+        LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
             lacp_slave_enable(port->lacp, iface, iface->enabled);
         }
 
@@ -3902,6 +3904,7 @@ port_create(struct bridge *br, const char *name)
     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,
@@ -3941,6 +3944,7 @@ get_interface_other_config(const struct ovsrec_interface *iface,
 static void
 port_del_ifaces(struct port *port, const struct ovsrec_port *cfg)
 {
+    struct iface *iface, *next;
     struct shash new_ifaces;
     size_t i;
 
@@ -3952,12 +3956,9 @@ port_del_ifaces(struct port *port, const struct ovsrec_port *cfg)
     }
 
     /* Get rid of deleted interfaces. */
-    for (i = 0; i < port->n_ifaces; ) {
-        struct iface *iface = port->ifaces[i];
+    LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) {
         if (!shash_find(&new_ifaces, iface->name)) {
             iface_destroy(iface);
-        } else {
-            i++;
         }
     }
 
@@ -4182,6 +4183,7 @@ port_destroy(struct port *port)
 {
     if (port) {
         struct bridge *br = port->bridge;
+        struct iface *iface, *next;
         struct port *del;
         int i;
 
@@ -4192,8 +4194,8 @@ port_destroy(struct port *port)
             }
         }
 
-        while (port->n_ifaces > 0) {
-            iface_destroy(port->ifaces[port->n_ifaces - 1]);
+        LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) {
+            iface_destroy(iface);
         }
 
         shash_find_and_delete_assert(&br->port_by_name, port->name);
@@ -4204,7 +4206,6 @@ port_destroy(struct port *port)
         VLOG_INFO("destroyed port %s on bridge %s", port->name, br->name);
 
         netdev_monitor_destroy(port->monitor);
-        free(port->ifaces);
         bitmap_free(port->trunks);
         free(port->name);
         free(port);
@@ -4236,14 +4237,13 @@ static void
 port_update_lacp(struct port *port)
 {
     if (port->lacp) {
-        size_t i;
+        struct iface *iface;
 
         lacp_configure(port->lacp, port->name,
                        port->bridge->ea, port->lacp_priority,
                        port->lacp_active, port->lacp_fast);
 
-        for (i = 0; i < port->n_ifaces; i++) {
-            struct iface *iface = port->ifaces[i];
+        LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
             lacp_slave_register(port->lacp, iface, iface->name,
                                 iface->dp_ifidx, iface->lacp_priority);
         }
@@ -4313,11 +4313,9 @@ iface_create(struct port *port, const struct ovsrec_interface *if_cfg)
 
     shash_add_assert(&br->iface_by_name, iface->name, iface);
 
-    if (port->n_ifaces >= port->allocated_ifaces) {
-        port->ifaces = x2nrealloc(port->ifaces, &port->allocated_ifaces,
-                                  sizeof *port->ifaces);
-    }
-    port->ifaces[port->n_ifaces++] = iface;
+    list_push_back(&port->ifaces, &iface->port_elem);
+    port->n_ifaces++;
+
     if (port->n_ifaces > 1) {
         br->has_bonded_ports = true;
     }
@@ -4336,7 +4334,6 @@ iface_destroy(struct iface *iface)
         struct port *port = iface->port;
         struct bridge *br = port->bridge;
         bool del_active = port->active_iface == iface;
-        size_t i;
 
         if (port->bond_hash) {
             struct bond_entry *e;
@@ -4361,12 +4358,8 @@ iface_destroy(struct iface *iface)
             hmap_remove(&br->ifaces, &iface->dp_ifidx_node);
         }
 
-        for (i = 0; i < port->n_ifaces; i++) {
-            if (iface == port->ifaces[i]) {
-                port->ifaces[i] = port->ifaces[--port->n_ifaces];
-                break;
-            }
-        }
+        list_remove(&iface->port_elem);
+        port->n_ifaces--;
 
         netdev_close(iface->netdev);
 
-- 
1.7.1




More information about the dev mailing list