[ovs-dev] [PATCH 46/48] ofp-util: Allow decoding of Open Flow 1.1 & 1.2 Table Statistics Request Messages
Simon Horman
horms at verge.net.au
Mon Jun 25 06:44:49 UTC 2012
Signed-off-by: Simon Horman <horms at verge.net.au>
---
v4
* Initial post
---
include/openflow/openflow-1.1.h | 4 ++
include/openflow/openflow-1.2.h | 29 +++++++++
ofproto/ofproto-dpif.c | 32 ++++++++--
ofproto/ofproto-provider.h | 71 ++++++++++++++++++++--
ofproto/ofproto.c | 131 +++++++++++++++++++++++++++++++++++-----
5 files changed, 241 insertions(+), 26 deletions(-)
diff --git a/include/openflow/openflow-1.1.h b/include/openflow/openflow-1.1.h
index 4cf2d74..37ca661 100644
--- a/include/openflow/openflow-1.1.h
+++ b/include/openflow/openflow-1.1.h
@@ -307,6 +307,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 daa8d34..bd86bf9 100644
--- a/include/openflow/openflow-1.2.h
+++ b/include/openflow/openflow-1.2.h
@@ -116,6 +116,35 @@ enum oxm12_ofb_match_fields {
OFPXMT12_OFB_MPLS_TC, /* MPLS TC. */
};
+#define OFPXMT12_SUPPORTED OFPXMT12_OFB_IN_PORT | \
+ OFPXMT12_OFB_ETH_DST | \
+ OFPXMT12_OFB_ETH_SRC | \
+ OFPXMT12_OFB_ETH_TYPE | \
+ OFPXMT12_OFB_IP_DSCP | \
+ OFPXMT12_OFB_IP_ECN | \
+ OFPXMT12_OFB_IP_PROTO | \
+ OFPXMT12_OFB_IPV4_SRC | \
+ OFPXMT12_OFB_IPV4_DST | \
+ OFPXMT12_OFB_TCP_SRC | \
+ OFPXMT12_OFB_TCP_DST | \
+ OFPXMT12_OFB_UDP_SRC | \
+ OFPXMT12_OFB_UDP_DST | \
+ OFPXMT12_OFB_ICMPV4_TYPE | \
+ OFPXMT12_OFB_ICMPV4_CODE | \
+ OFPXMT12_OFB_ARP_OP | \
+ OFPXMT12_OFB_ARP_SPA | \
+ OFPXMT12_OFB_ARP_TPA | \
+ OFPXMT12_OFB_ARP_SHA | \
+ OFPXMT12_OFB_ARP_THA | \
+ OFPXMT12_OFB_IPV6_SRC | \
+ OFPXMT12_OFB_IPV6_DST | \
+ OFPXMT12_OFB_IPV6_FLABEL | \
+ OFPXMT12_OFB_ICMPV6_TYPE | \
+ OFPXMT12_OFB_ICMPV6_CODE | \
+ OFPXMT12_OFB_IPV6_ND_TARGET | \
+ OFPXMT12_OFB_IPV6_ND_SLL | \
+ OFPXMT12_OFB_IPV6_ND_TLL
+
/* 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 65355ca..a327951 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1112,17 +1112,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 (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 d68c9d4..18b4c44 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -183,6 +183,15 @@ struct rule {
unsigned int ofpacts_len; /* Size of 'ofpacts', in bytes. */
};
+struct ofproto_table_stats {
+ uint8_t 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)
{
@@ -429,14 +438,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.
*
@@ -452,6 +495,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.
*
@@ -461,10 +519,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 5baa826..d70208d 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2120,17 +2120,25 @@ 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, struct ofpbuf *msg)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
struct ofp10_table_stats *ots;
- struct ofpbuf *msg;
size_t i;
- ofputil_make_stats_reply(0, request, &msg);
-
ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables);
for (i = 0; i < p->n_tables; i++) {
ots[i].table_id = i;
@@ -2140,18 +2148,113 @@ 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);
- }
+static void
+handle_table_stats_request11(struct ofconn *ofconn, struct ofpbuf *msg)
+{
+ struct ofproto *p = ofconn_get_ofproto(ofconn);
+ struct ofp11_stats_msg *osm;
+ struct ofp11_table_stats *ots;
+ size_t i;
- if (table->max_flows < ntohl(ots[i].max_entries)) {
- ots[i].max_entries = htonl(table->max_flows);
- }
+ 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);
+ }
+}
+
+static void
+handle_table_stats_request12(struct ofconn *ofconn, struct ofpbuf *msg)
+{
+ struct ofproto *p = ofconn_get_ofproto(ofconn);
+ struct ofp11_stats_msg *osm;
+ struct ofp12_table_stats *ots;
+ size_t i;
+
+ 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].write_actions = ots[i].apply_actions = htonl(OFPAT12_OUTPUT);
+ ots[i].write_setfields = ots[i].apply_setfields =
+ htonl(OFPXMT12_SUPPORTED);
+ 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);
+ }
+}
+
+static enum ofperr
+handle_table_stats_request(struct ofconn *ofconn,
+ const struct ofp_header *request)
+{
+ struct ofpbuf *msg;
+
+ ofputil_make_stats_reply(0, request, &msg);
+
+ switch (request->version) {
+ case OFP12_VERSION:
+ handle_table_stats_request12(ofconn, msg);
+ break;
+
+ case OFP11_VERSION:
+ handle_table_stats_request11(ofconn, msg);
+ break;
+
+ case OFP10_VERSION:
+ handle_table_stats_request10(ofconn, msg);
+ break;
+
+ default:
+ NOT_REACHED();
}
ofconn_send_reply(ofconn, msg);
--
1.7.10.2.484.gcd07cc5
More information about the dev
mailing list