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 877cfc823d1577e710b8b2d45025563d5a3f97ad..b538c4cae1ac7b463c08242dc01b1ac847037388 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 164bb2bf984a380aff393ee1fbad1f1a391b814e..a767788313cfd00dcd70e73b6ab2fda773840d42 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 92d1d2d6a8fd939bb2663f59450a0991ec6389be..9f45b3add47b35274556f5c1c3e1341fd97d2882 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);
 }