Signed-off-by: Simon Horman <ho...@verge.net.au> ---
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 Fix dump-tables --- include/openflow/openflow-1.1.h | 4 ++ include/openflow/openflow-1.2.h | 29 +++++++++ lib/ofp-util.c | 4 ++ ofproto/ofproto-dpif.c | 32 ++++++++-- ofproto/ofproto-provider.h | 71 ++++++++++++++++++++-- ofproto/ofproto.c | 131 +++++++++++++++++++++++++++++++++++----- 6 files changed, 245 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/lib/ofp-util.c b/lib/ofp-util.c index c373eae..fdded88 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -954,6 +954,8 @@ static const struct ofputil_msg_type ofputil_msg_types[] = { sizeof(struct ofp_desc_stats), 0), OFPST11_REPLY(OFPST11_AGGREGATE, OFPST_AGGREGATE, sizeof(struct ofp11_aggregate_stats_reply), 0), + OFPST11_REPLY(OFPST_TABLE, OFPST_TABLE, + 0, sizeof(struct ofp11_table_stats)), OFPST11_REPLY(OFPST_PORT_DESC, OFPST_PORT_DESC, 0, sizeof(struct ofp11_port)), #undef OFPST11_REPLY @@ -971,6 +973,8 @@ static const struct ofputil_msg_type ofputil_msg_types[] = { OFPST12_REPLY(OFPST11_FLOW, OFPST_FLOW, 0, 1), OFPST12_REPLY(OFPST11_AGGREGATE, OFPST_AGGREGATE, sizeof(struct ofp11_aggregate_stats_reply), 0), + OFPST12_REPLY(OFPST_TABLE, OFPST_TABLE, + 0, sizeof(struct ofp12_table_stats)), OFPST12_REPLY(OFPST_PORT_DESC, OFPST_PORT_DESC, 0, sizeof(struct ofp11_port)), #undef OFPST12_REPLY 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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev