dpif-sflow: Remove unused parameter from dpif_sflow_create().
[openvswitch] / ofproto / ofproto-dpif.c
index e5767169c7988ab08360c46d93a70313bc840279..9f5bb9652bae08796fedf2e8c9cc4689f6c05693 100644 (file)
@@ -49,6 +49,7 @@
 #include "ofproto-dpif-sflow.h"
 #include "poll-loop.h"
 #include "simap.h"
+#include "smap.h"
 #include "timer.h"
 #include "unaligned.h"
 #include "unixctl.h"
@@ -367,6 +368,8 @@ struct subfacet {
     ovs_be16 initial_tci;       /* Initial VLAN TCI value. */
 };
 
+#define SUBFACET_DESTROY_MAX_BATCH 50
+
 static struct subfacet *subfacet_create(struct facet *, enum odp_key_fitness,
                                         const struct nlattr *key,
                                         size_t key_len, ovs_be16 initial_tci,
@@ -375,6 +378,8 @@ static struct subfacet *subfacet_find(struct ofproto_dpif *,
                                       const struct nlattr *key, size_t key_len);
 static void subfacet_destroy(struct subfacet *);
 static void subfacet_destroy__(struct subfacet *);
+static void subfacet_destroy_batch(struct ofproto_dpif *,
+                                   struct subfacet **, int n);
 static void subfacet_get_key(struct subfacet *, struct odputil_keybuf *,
                              struct ofpbuf *key);
 static void subfacet_reset_dp_stats(struct subfacet *,
@@ -1306,7 +1311,7 @@ set_sflow(struct ofproto *ofproto_,
         if (!ds) {
             struct ofport_dpif *ofport;
 
-            ds = ofproto->sflow = dpif_sflow_create(ofproto->dpif);
+            ds = ofproto->sflow = dpif_sflow_create();
             HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
                 dpif_sflow_add_port(ds, &ofport->up, ofport->odp_port);
             }
@@ -3563,35 +3568,6 @@ subfacet_max_idle(const struct ofproto_dpif *ofproto)
     return bucket * BUCKET_WIDTH;
 }
 
-enum { EXPIRE_MAX_BATCH = 50 };
-
-static void
-expire_batch(struct ofproto_dpif *ofproto, struct subfacet **subfacets, int n)
-{
-    struct odputil_keybuf keybufs[EXPIRE_MAX_BATCH];
-    struct dpif_op ops[EXPIRE_MAX_BATCH];
-    struct dpif_op *opsp[EXPIRE_MAX_BATCH];
-    struct ofpbuf keys[EXPIRE_MAX_BATCH];
-    struct dpif_flow_stats stats[EXPIRE_MAX_BATCH];
-    int i;
-
-    for (i = 0; i < n; i++) {
-        ops[i].type = DPIF_OP_FLOW_DEL;
-        subfacet_get_key(subfacets[i], &keybufs[i], &keys[i]);
-        ops[i].u.flow_del.key = keys[i].data;
-        ops[i].u.flow_del.key_len = keys[i].size;
-        ops[i].u.flow_del.stats = &stats[i];
-        opsp[i] = &ops[i];
-    }
-
-    dpif_operate(ofproto->dpif, opsp, n);
-    for (i = 0; i < n; i++) {
-        subfacet_reset_dp_stats(subfacets[i], &stats[i]);
-        subfacets[i]->path = SF_NOT_INSTALLED;
-        subfacet_destroy(subfacets[i]);
-    }
-}
-
 static void
 expire_subfacets(struct ofproto_dpif *ofproto, int dp_max_idle)
 {
@@ -3603,7 +3579,7 @@ expire_subfacets(struct ofproto_dpif *ofproto, int dp_max_idle)
     long long int special_cutoff = time_msec() - 10000;
 
     struct subfacet *subfacet, *next_subfacet;
-    struct subfacet *batch[EXPIRE_MAX_BATCH];
+    struct subfacet *batch[SUBFACET_DESTROY_MAX_BATCH];
     int n_batch;
 
     n_batch = 0;
@@ -3617,8 +3593,8 @@ expire_subfacets(struct ofproto_dpif *ofproto, int dp_max_idle)
         if (subfacet->used < cutoff) {
             if (subfacet->path != SF_NOT_INSTALLED) {
                 batch[n_batch++] = subfacet;
-                if (n_batch >= EXPIRE_MAX_BATCH) {
-                    expire_batch(ofproto, batch, n_batch);
+                if (n_batch >= SUBFACET_DESTROY_MAX_BATCH) {
+                    subfacet_destroy_batch(ofproto, batch, n_batch);
                     n_batch = 0;
                 }
             } else {
@@ -3628,7 +3604,7 @@ expire_subfacets(struct ofproto_dpif *ofproto, int dp_max_idle)
     }
 
     if (n_batch > 0) {
-        expire_batch(ofproto, batch, n_batch);
+        subfacet_destroy_batch(ofproto, batch, n_batch);
     }
 }
 
@@ -4412,6 +4388,34 @@ subfacet_destroy(struct subfacet *subfacet)
     }
 }
 
+static void
+subfacet_destroy_batch(struct ofproto_dpif *ofproto,
+                       struct subfacet **subfacets, int n)
+{
+    struct odputil_keybuf keybufs[SUBFACET_DESTROY_MAX_BATCH];
+    struct dpif_op ops[SUBFACET_DESTROY_MAX_BATCH];
+    struct dpif_op *opsp[SUBFACET_DESTROY_MAX_BATCH];
+    struct ofpbuf keys[SUBFACET_DESTROY_MAX_BATCH];
+    struct dpif_flow_stats stats[SUBFACET_DESTROY_MAX_BATCH];
+    int i;
+
+    for (i = 0; i < n; i++) {
+        ops[i].type = DPIF_OP_FLOW_DEL;
+        subfacet_get_key(subfacets[i], &keybufs[i], &keys[i]);
+        ops[i].u.flow_del.key = keys[i].data;
+        ops[i].u.flow_del.key_len = keys[i].size;
+        ops[i].u.flow_del.stats = &stats[i];
+        opsp[i] = &ops[i];
+    }
+
+    dpif_operate(ofproto->dpif, opsp, n);
+    for (i = 0; i < n; i++) {
+        subfacet_reset_dp_stats(subfacets[i], &stats[i]);
+        subfacets[i]->path = SF_NOT_INSTALLED;
+        subfacet_destroy(subfacets[i]);
+    }
+}
+
 /* Initializes 'key' with the sequence of OVS_KEY_ATTR_* Netlink attributes
  * that can be used to refer to 'subfacet'.  The caller must provide 'keybuf'
  * for use as temporary storage. */
@@ -7043,6 +7047,208 @@ ofproto_dpif_self_check(struct unixctl_conn *conn,
     ds_destroy(&reply);
 }
 
+/* Store the current ofprotos in 'ofproto_shash'.  Returns a sorted list
+ * of the 'ofproto_shash' nodes.  It is the responsibility of the caller
+ * to destroy 'ofproto_shash' and free the returned value. */
+static const struct shash_node **
+get_ofprotos(struct shash *ofproto_shash)
+{
+    const struct ofproto_dpif *ofproto;
+
+    HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+        char *name = xasprintf("%s@%s", ofproto->up.type, ofproto->up.name);
+        shash_add_nocopy(ofproto_shash, name, ofproto);
+    }
+
+    return shash_sort(ofproto_shash);
+}
+
+static void
+ofproto_unixctl_dpif_dump_dps(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                              const char *argv[] OVS_UNUSED,
+                              void *aux OVS_UNUSED)
+{
+    struct ds ds = DS_EMPTY_INITIALIZER;
+    struct shash ofproto_shash;
+    const struct shash_node **sorted_ofprotos;
+    int i;
+
+    shash_init(&ofproto_shash);
+    sorted_ofprotos = get_ofprotos(&ofproto_shash);
+    for (i = 0; i < shash_count(&ofproto_shash); i++) {
+        const struct shash_node *node = sorted_ofprotos[i];
+        ds_put_format(&ds, "%s\n", node->name);
+    }
+
+    shash_destroy(&ofproto_shash);
+    free(sorted_ofprotos);
+
+    unixctl_command_reply(conn, ds_cstr(&ds));
+    ds_destroy(&ds);
+}
+
+static void
+show_dp_format(const struct ofproto_dpif *ofproto, struct ds *ds)
+{
+    struct dpif_dp_stats s;
+    const struct shash_node **ports;
+    int i;
+
+    dpif_get_dp_stats(ofproto->dpif, &s);
+
+    ds_put_format(ds, "%s@%s:\n", ofproto->up.type, ofproto->up.name);
+    ds_put_format(ds,
+                  "\tlookups: hit:%"PRIu64" missed:%"PRIu64" lost:%"PRIu64"\n",
+                  s.n_hit, s.n_missed, s.n_lost);
+    ds_put_format(ds, "\tflows: %"PRIu64"\n", s.n_flows);
+
+    ports = shash_sort(&ofproto->up.port_by_name);
+    for (i = 0; i < shash_count(&ofproto->up.port_by_name); i++) {
+        const struct shash_node *node = ports[i];
+        struct ofport *ofport = node->data;
+        const char *name = netdev_get_name(ofport->netdev);
+        const char *type = netdev_get_type(ofport->netdev);
+
+        ds_put_format(ds, "\t%s %u/%u:", name, ofport->ofp_port,
+                      ofp_port_to_odp_port(ofproto, ofport->ofp_port));
+        if (strcmp(type, "system")) {
+            struct netdev *netdev;
+            int error;
+
+            ds_put_format(ds, " (%s", type);
+
+            error = netdev_open(name, type, &netdev);
+            if (!error) {
+                struct smap config;
+
+                smap_init(&config);
+                error = netdev_get_config(netdev, &config);
+                if (!error) {
+                    const struct smap_node **nodes;
+                    size_t i;
+
+                    nodes = smap_sort(&config);
+                    for (i = 0; i < smap_count(&config); i++) {
+                        const struct smap_node *node = nodes[i];
+                        ds_put_format(ds, "%c %s=%s", i ? ',' : ':',
+                                      node->key, node->value);
+                    }
+                    free(nodes);
+                }
+                smap_destroy(&config);
+
+                netdev_close(netdev);
+            }
+            ds_put_char(ds, ')');
+        }
+        ds_put_char(ds, '\n');
+    }
+    free(ports);
+}
+
+static void
+ofproto_unixctl_dpif_show(struct unixctl_conn *conn, int argc,
+                          const char *argv[], void *aux OVS_UNUSED)
+{
+    struct ds ds = DS_EMPTY_INITIALIZER;
+    const struct ofproto_dpif *ofproto;
+
+    if (argc > 1) {
+        int i;
+        for (i = 1; i < argc; i++) {
+            ofproto = ofproto_dpif_lookup(argv[i]);
+            if (!ofproto) {
+                ds_put_format(&ds, "Unknown bridge %s (use dpif/dump-dps "
+                                   "for help)", argv[i]);
+                unixctl_command_reply_error(conn, ds_cstr(&ds));
+                return;
+            }
+            show_dp_format(ofproto, &ds);
+        }
+    } else {
+        struct shash ofproto_shash;
+        const struct shash_node **sorted_ofprotos;
+        int i;
+
+        shash_init(&ofproto_shash);
+        sorted_ofprotos = get_ofprotos(&ofproto_shash);
+        for (i = 0; i < shash_count(&ofproto_shash); i++) {
+            const struct shash_node *node = sorted_ofprotos[i];
+            show_dp_format(node->data, &ds);
+        }
+
+        shash_destroy(&ofproto_shash);
+        free(sorted_ofprotos);
+    }
+
+    unixctl_command_reply(conn, ds_cstr(&ds));
+    ds_destroy(&ds);
+}
+
+static void
+ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn,
+                                int argc OVS_UNUSED, const char *argv[],
+                                void *aux OVS_UNUSED)
+{
+    struct ds ds = DS_EMPTY_INITIALIZER;
+    const struct ofproto_dpif *ofproto;
+    struct subfacet *subfacet;
+
+    ofproto = ofproto_dpif_lookup(argv[1]);
+    if (!ofproto) {
+        unixctl_command_reply_error(conn, "no such bridge");
+        return;
+    }
+
+    HMAP_FOR_EACH (subfacet, hmap_node, &ofproto->subfacets) {
+        struct odputil_keybuf keybuf;
+        struct ofpbuf key;
+
+        subfacet_get_key(subfacet, &keybuf, &key);
+        odp_flow_key_format(key.data, key.size, &ds);
+
+        ds_put_format(&ds, ", packets:%"PRIu64", bytes:%"PRIu64", used:",
+                      subfacet->dp_packet_count, subfacet->dp_byte_count);
+        if (subfacet->used) {
+            ds_put_format(&ds, "%.3fs",
+                          (time_msec() - subfacet->used) / 1000.0);
+        } else {
+            ds_put_format(&ds, "never");
+        }
+        if (subfacet->facet->tcp_flags) {
+            ds_put_cstr(&ds, ", flags:");
+            packet_format_tcp_flags(&ds, subfacet->facet->tcp_flags);
+        }
+
+        ds_put_cstr(&ds, ", actions:");
+        format_odp_actions(&ds, subfacet->actions, subfacet->actions_len);
+        ds_put_char(&ds, '\n');
+    }
+
+    unixctl_command_reply(conn, ds_cstr(&ds));
+    ds_destroy(&ds);
+}
+
+static void
+ofproto_unixctl_dpif_del_flows(struct unixctl_conn *conn,
+                               int argc OVS_UNUSED, const char *argv[],
+                               void *aux OVS_UNUSED)
+{
+    struct ds ds = DS_EMPTY_INITIALIZER;
+    struct ofproto_dpif *ofproto;
+
+    ofproto = ofproto_dpif_lookup(argv[1]);
+    if (!ofproto) {
+        unixctl_command_reply_error(conn, "no such bridge");
+        return;
+    }
+
+    flush(&ofproto->up);
+
+    unixctl_command_reply(conn, ds_cstr(&ds));
+    ds_destroy(&ds);
+}
+
 static void
 ofproto_dpif_unixctl_init(void)
 {
@@ -7066,6 +7272,14 @@ ofproto_dpif_unixctl_init(void)
                              ofproto_dpif_unclog, NULL);
     unixctl_command_register("ofproto/self-check", "[bridge]", 0, 1,
                              ofproto_dpif_self_check, NULL);
+    unixctl_command_register("dpif/dump-dps", "", 0, 0,
+                             ofproto_unixctl_dpif_dump_dps, NULL);
+    unixctl_command_register("dpif/show", "[bridge]", 0, INT_MAX,
+                             ofproto_unixctl_dpif_show, NULL);
+    unixctl_command_register("dpif/dump-flows", "bridge", 1, 1,
+                             ofproto_unixctl_dpif_dump_flows, NULL);
+    unixctl_command_register("dpif/del-flows", "bridge", 1, 1,
+                             ofproto_unixctl_dpif_del_flows, NULL);
 }
 \f
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
@@ -7279,6 +7493,9 @@ const struct ofproto_class ofproto_dpif_class = {
     enumerate_types,
     enumerate_names,
     del,
+    NULL,                       /* type_run */
+    NULL,                       /* type_run_fast */
+    NULL,                       /* type_wait */
     alloc,
     construct,
     destruct,