[ovs-dev] [PATCH 04/27] ofp-util: Allow decoding of Open Flow 1.1 & 1.2 Table Statistics Request Messages

Simon Horman horms at verge.net.au
Tue Aug 21 04:55:36 UTC 2012


Signed-off-by: Simon Horman <horms at verge.net.au>

---

v12
* No change

v11
* No change

v10
* No change

v9
* Set wildcards, match, write_setfields and apply_setfields based
  on a bitmap of (1 << OFPXMT_*)

v8
* Manual rebase
* Make use of enum ofp_version
* Add ofp-tests

v7
* Omitted

v6
* No change

v5
* Manual rebase
* Add OFPST_TABLE entry for Open Flow 1.1 and 1.2 to ofputil_msg_types,
  this wires-up decoding of table statistics messages.

v4
* Initial post

table test
---
 include/openflow/openflow-1.1.h |   4 ++
 include/openflow/openflow-1.2.h |   5 ++
 ofproto/ofproto-dpif.c          |  32 ++++++++--
 ofproto/ofproto-provider.h      |  71 +++++++++++++++++++--
 ofproto/ofproto.c               | 133 ++++++++++++++++++++++++++++++++++++----
 tests/ofp-print.at              |  16 ++++-
 6 files changed, 237 insertions(+), 24 deletions(-)

diff --git a/include/openflow/openflow-1.1.h b/include/openflow/openflow-1.1.h
index 696c3ec..5592520 100644
--- a/include/openflow/openflow-1.1.h
+++ b/include/openflow/openflow-1.1.h
@@ -281,6 +281,10 @@ enum ofp11_instruction_type {
     OFPIT11_EXPERIMENTER = 0xFFFF  /* Experimenter instruction */
 };
 
+#define OFPIT11_ALL OFPIT11_GOTO_TABLE | OFPIT11_WRITE_METADATA |       \
+                    OFPIT11_WRITE_ACTIONS | OFPIT11_APPLY_ACTIONS |     \
+                    OFPIT11_CLEAR_ACTIONS
+
 #define OFP11_INSTRUCTION_ALIGN 8
 
 /* Generic ofp_instruction structure. */
diff --git a/include/openflow/openflow-1.2.h b/include/openflow/openflow-1.2.h
index 0a73ed1..64bc993 100644
--- a/include/openflow/openflow-1.2.h
+++ b/include/openflow/openflow-1.2.h
@@ -106,8 +106,13 @@ enum oxm12_ofb_match_fields {
     OFPXMT12_OFB_IPV6_ND_TLL,    /* Target link-layer for ND. */
     OFPXMT12_OFB_MPLS_LABEL,     /* MPLS label. */
     OFPXMT12_OFB_MPLS_TC,        /* MPLS TC. */
+
+    /* End Marker */
+    OFPXMT12_OFB_MAX,
 };
 
+#define OFPXMT12_MASK ((1ULL << OFPXMT12_OFB_MAX) - 1)
+
 /* OXM implementation makes use of NXM as they are the same format
  * with different field definitions
  */
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 10d450e..36ab8d7 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1153,17 +1153,37 @@ get_features(struct ofproto *ofproto_ OVS_UNUSED,
 }
 
 static void
-get_tables(struct ofproto *ofproto_, struct ofp10_table_stats *ots)
+get_tables(struct ofproto *ofproto_, struct ofproto_table_stats *ots)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct dpif_dp_stats s;
 
-    strcpy(ots->name, "classifier");
-
     dpif_get_dp_stats(ofproto->dpif, &s);
-    put_32aligned_be64(&ots->lookup_count, htonll(s.n_hit + s.n_missed));
-    put_32aligned_be64(&ots->matched_count,
-                       htonll(s.n_hit + ofproto->n_matches));
+
+    switch ((enum ofp_version)ots->ofp_version) {
+    case OFP12_VERSION:
+        strcpy(ots->o12ts->name, "classifier");
+        ots->o12ts->lookup_count = htonll(s.n_hit + s.n_missed);
+        ots->o12ts->matched_count = htonll(s.n_hit + ofproto->n_matches);
+        break;
+
+    case OFP11_VERSION:
+        strcpy(ots->o11ts->name, "classifier");
+        ots->o11ts->lookup_count = htonll(s.n_hit + s.n_missed);
+        ots->o11ts->matched_count = htonll(s.n_hit + ofproto->n_matches);
+        break;
+
+    case OFP10_VERSION:
+        strcpy(ots->o10ts->name, "classifier");
+        put_32aligned_be64(&ots->o10ts->lookup_count,
+                           htonll(s.n_hit + s.n_missed));
+        put_32aligned_be64(&ots->o10ts->matched_count,
+                           htonll(s.n_hit + ofproto->n_matches));
+        break;
+
+    default:
+        NOT_REACHED();
+    }
 }
 
 static struct ofport *
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 15dc347..c1757a4 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -194,6 +194,15 @@ struct rule {
     uint64_t modify_seqno;      /* Sequence number when changed. */
 };
 
+struct ofproto_table_stats {
+    enum ofp_version ofp_version;
+    union {
+        struct ofp10_table_stats *o10ts;
+        struct ofp11_table_stats *o11ts;
+        struct ofp12_table_stats *o12ts;
+    };
+};
+
 static inline struct rule *
 rule_from_cls_rule(const struct cls_rule *cls_rule)
 {
@@ -449,14 +458,48 @@ struct ofproto_class {
 
     /* Helper for the OpenFlow OFPST_TABLE statistics request.
      *
-     * The 'ots' array contains 'ofproto->n_tables' elements.  Each element is
-     * initialized as:
+     * The 'ots' structure contains two elements
+     *
+     *  - 'ofp_version' the OpenFLow version in use, set to one of:
+     *                  OFP10_VERSION, OFP11_VERSION, OFP12_VERSION.
+     *                  These values denote OpenFLow 1.0, 1.1 and 1.2
+     *                  respectively.
+     *
+     *  - A union of 'o10ts', 'o11ts' and 'o12ts'.
+     *
+     *    This is an array of OpenFLow version-specific table statistics
+     *    elements.
+     *
+     *    'o10ts' should be used for OpenFLow 1.0.
+     *    'o11ts' should be used for OpenFLow 1.1.
+     *    'o12ts' should be used for OpenFLow 1.2.
+     *
+     * The 'o1Xts' array contains 'ofproto->n_tables' elements.
+     * Each element is initialized as:
      *
      *   - 'table_id' to the array index.
      *
      *   - 'name' to "table#" where # is the table ID.
      *
-     *   - 'wildcards' to OFPFW10_ALL.
+     *   - 'wildcards' to OFPFW10_ALL (OpenFLow 1.0) or
+     *                    OFPFW11_ALL (OpenFLow 1.1 and 1.2).
+     *
+     *   - 'instructions' to OFPIT11_ALL (OpenFLow 1.1 and 1.2).
+     *                    Not present in OpenFLow 1.0.
+     *
+     *   - 'write_actions' to OFPAT11_OUTPUT (OpenFLow 1.1) or
+     *                        OFPAT12_OUTPUT (OpenFLow 1.2).
+     *                     Not present in OpenFLow 1.0.
+     *
+     *   - 'apply_actions' to OFPAT11_OUTPUT (OpenFLow 1.1) or
+     *                        OFPAT12_OUTPUT (OpenFLow 1.2).
+     *                     Not present in OpenFLow 1.0.
+     *
+     *   - 'write_setfields' to OFPXMT12_SUPPORTED (OpenFLow 1.2).
+     *                       Not present in OpenFLow 1.0 or 1.1.
+     *
+     *   - 'apply_setfields' to OFPXMT12_SUPPORTED (OpenFLow 1.2).
+     *                       Not present in OpenFLow 1.0 or 1.1.
      *
      *   - 'max_entries' to 1,000,000.
      *
@@ -472,6 +515,21 @@ struct ofproto_class {
      *   - 'wildcards' to the set of wildcards actually supported by the table
      *     (if it doesn't support all OpenFlow wildcards).
      *
+     *   - 'instructions' to set the instructions actually supported by
+     *     the table.
+     *
+     *   - 'write_actions' to set the write actions actually supported by
+     *     the table (if it doesn't support all OpenFlow actions).
+     *
+     *   - 'apply_actions' to set the apply actions actually supported by
+     *     the table (if it doesn't support all OpenFlow actions).
+     *
+     *   - 'write_setfields' to set the write setfields actually supported by
+     *     the table.
+     *
+     *   - 'apply_setfields' to set the apply setfields actually supported by
+     *     the table.
+     *
      *   - 'max_entries' to the maximum number of flows actually supported by
      *     the hardware.
      *
@@ -481,10 +539,11 @@ struct ofproto_class {
      *   - 'matched_count' to the number of packets looked up in this flow
      *     table so far that matched one of the flow entries.
      *
-     * Keep in mind that all of the members of struct ofp10_table_stats are in
-     * network byte order.
+     * Keep in mind that all of the members of elements of the oXts array
+     * are in network byte order.
      */
-    void (*get_tables)(struct ofproto *ofproto, struct ofp10_table_stats *ots);
+    void (*get_tables)(struct ofproto *ofproto,
+                       struct ofproto_table_stats *ots);
 
 /* ## ---------------- ## */
 /* ## ofport Functions ## */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 5c9ab9d..3a39cca 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2203,9 +2203,21 @@ handle_desc_stats_request(struct ofconn *ofconn,
     return 0;
 }
 
-static enum ofperr
-handle_table_stats_request(struct ofconn *ofconn,
-                           const struct ofp_header *request)
+static void
+stats_request_finish(const struct oftable *table,
+                     char *name, size_t namelen, ovs_be32 *max_entries) {
+    if (table->name) {
+        ovs_strzcpy(name, table->name, namelen);
+    }
+
+    if (table->max_flows < ntohl(*max_entries)) {
+        *max_entries = htonl(table->max_flows);
+    }
+}
+
+static void
+handle_table_stats_request10(struct ofconn *ofconn,
+                             const struct ofp_header *request)
 {
     struct ofproto *p = ofconn_get_ofproto(ofconn);
     struct ofp10_table_stats *ots;
@@ -2222,21 +2234,120 @@ handle_table_stats_request(struct ofconn *ofconn,
         ots[i].active_count = htonl(classifier_count(&p->tables[i].cls));
     }
 
-    p->ofproto_class->get_tables(p, ots);
+    {
+        struct ofproto_table_stats ts = {
+            .ofp_version = OFP10_VERSION,
+            .o10ts = ots
+        };
+        p->ofproto_class->get_tables(p, &ts);
+    }
 
     for (i = 0; i < p->n_tables; i++) {
-        const struct oftable *table = &p->tables[i];
+        stats_request_finish(p->tables + i, ots[i].name, sizeof ots[i].name,
+                             &ots[i].max_entries);
+    }
 
-        if (table->name) {
-            ovs_strzcpy(ots[i].name, table->name, sizeof ots[i].name);
-        }
+    ofconn_send_reply(ofconn, msg);
+}
 
-        if (table->max_flows < ntohl(ots[i].max_entries)) {
-            ots[i].max_entries = htonl(table->max_flows);
-        }
+static void
+handle_table_stats_request11(struct ofconn *ofconn,
+                             const struct ofp_header *request)
+{
+    struct ofproto *p = ofconn_get_ofproto(ofconn);
+    struct ofp11_table_stats *ots;
+    struct ofpbuf *msg;
+    size_t i;
+
+    msg = ofpraw_alloc_stats_reply(request, sizeof *ots * p->n_tables);
+    ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables);
+    for (i = 0; i < p->n_tables; i++) {
+        ots[i].table_id = i;
+        sprintf(ots[i].name, "table%zu", i);
+        ots[i].wildcards = ots[i].match = htonl(OFPFW11_ALL);
+        ots[i].instructions = htonl(OFPIT11_ALL);
+        ots[i].write_actions = ots[i].apply_actions = htonl(OFPAT11_OUTPUT);
+        ots[i].config = ots[i].apply_actions = htonl(0);
+        ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */
+        ots[i].active_count = htonl(classifier_count(&p->tables[i].cls));
+    }
+
+    {
+        struct ofproto_table_stats ts = {
+            .ofp_version = OFP11_VERSION,
+            .o11ts = ots
+        };
+        p->ofproto_class->get_tables(p, &ts);
+    }
+
+    for (i = 0; i < p->n_tables; i++) {
+        stats_request_finish(p->tables + i, ots[i].name, sizeof ots[i].name,
+                             &ots[i].max_entries);
+    }
+
+    ofconn_send_reply(ofconn, msg);
+}
+
+static void
+handle_table_stats_request12(struct ofconn *ofconn,
+                             const struct ofp_header *request)
+{
+    struct ofproto *p = ofconn_get_ofproto(ofconn);
+    struct ofp12_table_stats *ots;
+    struct ofpbuf *msg;
+    size_t i;
+
+    msg = ofpraw_alloc_stats_reply(request, sizeof *ots * p->n_tables);
+    ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables);
+    for (i = 0; i < p->n_tables; i++) {
+        ots[i].table_id = i;
+        sprintf(ots[i].name, "table%zu", i);
+        ots[i].wildcards = ots[i].match = ots[i].write_setfields =
+            ots[i].apply_setfields = htonll(OFPXMT12_MASK);
+        ots[i].write_actions = ots[i].apply_actions = htonl(OFPAT12_OUTPUT);
+        ots[i].instructions = htonl(OFPIT11_ALL);
+        ots[i].config = ots[i].apply_actions = htonl(0);
+        ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */
+        ots[i].active_count = htonl(classifier_count(&p->tables[i].cls));
+    }
+
+    {
+        struct ofproto_table_stats ts = {
+            .ofp_version = OFP12_VERSION,
+            .o12ts = ots
+        };
+        p->ofproto_class->get_tables(p, &ts);
+    }
+
+    for (i = 0; i < p->n_tables; i++) {
+        stats_request_finish(p->tables + i, ots[i].name, sizeof ots[i].name,
+                             &ots[i].max_entries);
     }
 
     ofconn_send_reply(ofconn, msg);
+}
+
+static enum ofperr
+handle_table_stats_request(struct ofconn *ofconn,
+                           const struct ofp_header *request)
+{
+    switch (request->version) {
+    case OFP12_VERSION:
+        handle_table_stats_request12(ofconn, request);
+        break;
+
+    case OFP11_VERSION:
+        handle_table_stats_request11(ofconn, request);
+        break;
+
+    case OFP10_VERSION:
+        handle_table_stats_request10(ofconn, request);
+        break;
+
+    default:
+        NOT_REACHED();
+    }
+
     return 0;
 }
 
diff --git a/tests/ofp-print.at b/tests/ofp-print.at
index aca502a..093c69b 100644
--- a/tests/ofp-print.at
+++ b/tests/ofp-print.at
@@ -794,13 +794,27 @@ OFPST_AGGREGATE reply (OF1.2) (xid=0x2): packet_count=121 byte_count=19279 flow_
 ])
 AT_CLEANUP
 
-AT_SETUP([OFPST_TABLE request])
+AT_SETUP([OFPST_TABLE request - OF1.0])
 AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
 AT_CHECK([ovs-ofctl ofp-print "0110000c0000000100030000"], [0], [dnl
 OFPST_TABLE request (xid=0x1):
 ])
 AT_CLEANUP
 
+AT_SETUP([OFPST_TABLE request - OF1.1])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "02120010000000020003000000000000"], [0], [dnl
+OFPST_TABLE request (OF1.1) (xid=0x2):
+])
+AT_CLEANUP
+
+AT_SETUP([OFPST_TABLE request - OF1.2])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "03120010000000020003000000000000"], [0], [dnl
+OFPST_TABLE request (OF1.2) (xid=0x2):
+])
+AT_CLEANUP
+
 AT_SETUP([OFPST_TABLE reply - OF1.0])
 AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
 AT_CHECK([ovs-ofctl ofp-print "\
-- 
1.7.10.2.484.gcd07cc5




More information about the dev mailing list