dpif: Change dpif_port_group_get() semantics.
authorBen Pfaff <blp@nicira.com>
Wed, 17 Jun 2009 21:22:57 +0000 (14:22 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 6 Jul 2009 16:07:24 +0000 (09:07 -0700)
This function is easier for callers to use if they do not have to guess
how many ports are in the group.  Since it's not performance critical at
all, introduce these easier semantics.

lib/dpif.c
lib/dpif.h
utilities/ovs-dpctl.c

index 877cfc8..b538c4c 100644 (file)
@@ -391,21 +391,39 @@ dpif_port_group_set(struct dpif *dpif, uint16_t group,
     return do_ioctl(dpif, ODP_PORT_GROUP_SET, "ODP_PORT_GROUP_SET", &pg);
 }
 
-/* Careful: '*n_out' can be greater than 'n_ports' on return, if 'n_ports' is
- * less than the number of ports in 'group'. */
 int
 dpif_port_group_get(const struct dpif *dpif, uint16_t group,
-                    uint16_t ports[], size_t n_ports, size_t *n_out)
+                    uint16_t **ports, size_t *n_ports)
 {
-    struct odp_port_group pg;
     int error;
 
-    assert(n_ports <= UINT16_MAX);
-    pg.group = group;
-    pg.ports = ports;
-    pg.n_ports = n_ports;
-    error = do_ioctl(dpif, ODP_PORT_GROUP_GET, "ODP_PORT_GROUP_GET", &pg);
-    *n_out = error ? 0 : pg.n_ports;
+    *ports = NULL;
+    *n_ports = 0;
+    for (;;) {
+        struct odp_port_group pg;
+        pg.group = group;
+        pg.ports = *ports;
+        pg.n_ports = *n_ports;
+
+        error = do_ioctl(dpif, ODP_PORT_GROUP_GET, "ODP_PORT_GROUP_GET", &pg);
+        if (error) {
+            /* Hard error. */
+            free(*ports);
+            *ports = NULL;
+            *n_ports = 0;
+            break;
+        } else if (pg.n_ports <= *n_ports) {
+            /* Success. */
+            *n_ports = pg.n_ports;
+            break;
+        } else {
+            /* Soft error: there were more ports than we expected in the
+             * group.  Try again. */
+            free(*ports);
+            *ports = xcalloc(pg.n_ports, sizeof **ports);
+            *n_ports = pg.n_ports;
+        }
+    }
     return error;
 }
 
index 164bb2b..a767788 100644 (file)
@@ -60,7 +60,7 @@ int dpif_port_list(const struct dpif *, struct odp_port **, size_t *n_ports);
 int dpif_port_group_set(struct dpif *, uint16_t group,
                         const uint16_t ports[], size_t n_ports);
 int dpif_port_group_get(const struct dpif *, uint16_t group,
-                        uint16_t ports[], size_t n_ports, size_t *n_out);
+                        uint16_t **ports, size_t *n_ports);
 
 int dpif_flow_flush(struct dpif *);
 int dpif_flow_put(struct dpif *, struct odp_flow_put *);
index 92d1d2d..9f45b3a 100644 (file)
@@ -515,11 +515,10 @@ do_dump_groups(int argc UNUSED, char *argv[])
     run(dpif_open(argv[1], &dpif), "opening datapath");
     run(dpif_get_dp_stats(dpif, &stats), "get datapath stats");
     for (i = 0; i < stats.max_groups; i++) {
-        uint16_t ports[UINT16_MAX];
+        uint16_t *ports;
         size_t n_ports;
 
-        if (!dpif_port_group_get(dpif, i, ports,
-                                 ARRAY_SIZE(ports), &n_ports) && n_ports) {
+        if (!dpif_port_group_get(dpif, i, &ports, &n_ports) && n_ports) {
             size_t j;
 
             printf("group %u:", i);
@@ -528,6 +527,7 @@ do_dump_groups(int argc UNUSED, char *argv[])
             }
             printf("\n");
         }
+        free(ports);
     }
     dpif_close(dpif);
 }