@@ -150,4 +150,52 @@ struct ofp15_group_desc_stats {
};
OFP_ASSERT(sizeof(struct ofp15_group_desc_stats) == 16);
+struct ofp_oxs_stat {
+ ovs_be16 reserved; /* One of OFPST_* */
+ ovs_be16 length; /* Stats Length */
+};
+OFP_ASSERT(sizeof(struct ofp_oxs_stat) == 4);
+
+/*Body for ofp_multipart_request of type
+ OFPMP_FLOW_DESC & OFPMP_FLOW_STATS.*/
+struct ofp15_oxs_flow_stats_request {
+ uint8_t table_id; /* ID of table to read
+ (from ofp_table_desc),
+ OFPTT_ALL for all tables. */
+ uint8_t pad[3]; /* Align to 32 bits. */
+ ovs_be32 out_port; /* Require matching entries to include
+ this as an output port. A value of
+ OFP_ANY indicates no restriction. */
+ ovs_be32 out_group; /* Require matching entries to include
+ this as an output group. A value of
+ OFPG_ANY indicates no restriction. */
+ uint8_t pad2[4]; /* Align to 64 bits. */
+ ovs_be64 cookie; /* Require matching entries to contain
+ this cookie value */
+ ovs_be64 cookie_mask; /* Mask used to restrict the cookie bits
+ that must match. A value of 0
+ indicates no restriction. */
+};
+OFP_ASSERT(sizeof(struct ofp15_oxs_flow_stats_request) == 32);
+
+/* Body of reply to OFPMP_FLOW_STATS request
+* and body for OFPIT_STAT_TRIGGER generated status. */
+struct ofp15_oxs_flow_stats_reply {
+ ovs_be16 length; /* Length of this entry. */
+ uint8_t pad2[2]; /* Align to 64-bits. */
+ uint8_t table_id; /* ID of table flow came from. */
+ uint8_t reason; /* One of OFPFSR_*. */
+ ovs_be16 priority; /* Priority of the entry. */
+};
+OFP_ASSERT(sizeof(struct ofp15_oxs_flow_stats_reply) == 8);
+
+/* OXS flow stat field types for OpenFlow basic class. */
+enum oxs_ofb_stat_fields {
+ OFPXST_OFB_DURATION = 0, /* Time flow entry has been alive. */
+ OFPXST_OFB_IDLE_TIME = 1, /* Time flow entry has been idle. */
+ OFPXST_OFB_FLOW_COUNT = 2, /* Number of aggregated flow entries. */
+ OFPXST_OFB_PACKET_COUNT = 3, /* Number of packets in flow entry. */
+ OFPXST_OFB_BYTE_COUNT = 4, /* Number of bytes in flow entry. */
+};
+
#endif /* openflow/openflow-1.5.h */
@@ -287,6 +287,8 @@ enum ofpraw {
OFPRAW_OFPST10_FLOW_REQUEST,
/* OFPST 1.1+ (1): struct ofp11_flow_stats_request, uint8_t[8][]. */
OFPRAW_OFPST11_FLOW_REQUEST,
+ /* OFPST 1.5+ (17): struct ofp15_oxs_flow_stats_request, uint8_t[8][]. */
+ OFPRAW_OFPST15_OXS_FLOW_REQUEST,
/* NXST 1.0 (0): struct nx_flow_stats_request, uint8_t[8][]. */
OFPRAW_NXST_FLOW_REQUEST,
@@ -296,6 +298,8 @@ enum ofpraw {
OFPRAW_OFPST11_FLOW_REPLY,
/* OFPST 1.3+ (1): uint8_t[]. */
OFPRAW_OFPST13_FLOW_REPLY,
+ /* OFPST 1.5+ (17): uint8_t[]. */
+ OFPRAW_OFPST15_OXS_FLOW_REPLY,
/* NXST 1.0 (0): uint8_t[]. */
OFPRAW_NXST_FLOW_REPLY,
@@ -628,10 +632,12 @@ enum ofptype {
OFPTYPE_FLOW_STATS_REQUEST, /* OFPRAW_OFPST10_FLOW_REQUEST.
* OFPRAW_OFPST11_FLOW_REQUEST.
* OFPRAW_NXST_FLOW_REQUEST. */
+ OFPTYPE_OXS_FLOW_STATS_REQUEST, /* OFPRAW_OFPST15_OXS_FLOW_REQUEST. */
OFPTYPE_FLOW_STATS_REPLY, /* OFPRAW_OFPST10_FLOW_REPLY.
* OFPRAW_OFPST11_FLOW_REPLY.
* OFPRAW_OFPST13_FLOW_REPLY.
* OFPRAW_NXST_FLOW_REPLY. */
+ OFPTYPE_OXS_FLOW_STATS_REPLY, /* OFPRAW_OFPST15_OXS_FLOW_REPLY. */
OFPTYPE_AGGREGATE_STATS_REQUEST, /* OFPRAW_OFPST10_AGGREGATE_REQUEST.
* OFPRAW_OFPST11_AGGREGATE_REQUEST.
* OFPRAW_NXST_AGGREGATE_REQUEST. */
@@ -197,6 +197,8 @@ lib_libopenvswitch_la_SOURCES = \
lib/ovsdb-parser.h \
lib/ovsdb-types.c \
lib/ovsdb-types.h \
+ lib/ox-stat.c \
+ lib/ox-stat.h \
lib/packets.c \
lib/packets.h \
lib/pcap-file.c \
@@ -41,6 +41,8 @@
#include "socket-util.h"
#include "util.h"
+extern uint8_t oxs_field_set;
+
/* Parses 'str' as an 8-bit unsigned integer into '*valuep'.
*
* 'name' describes the value parsed in an error message, if any.
@@ -188,6 +190,34 @@ str_to_connhelper(const char *str, uint16_t *alg)
return xasprintf("invalid conntrack helper \"%s\"", str);
}
+struct ox_fields {
+ const char *name;
+ uint16_t fl_type;
+};
+
+static bool
+parse_oxs_field(const char *name, const struct ox_fields **f_out)
+{
+ static const struct ox_fields fields[] = {
+ { "oxs-duration", OFPXST_OFB_DURATION },
+ { "oxs-idle_time", OFPXST_OFB_IDLE_TIME },
+ { "oxs-flow_count", OFPXST_OFB_FLOW_COUNT },
+ { "oxs-packet_count", OFPXST_OFB_PACKET_COUNT },
+ { "oxs-byte_count", OFPXST_OFB_BYTE_COUNT },
+ };
+
+ const struct ox_fields *f;
+
+ for (f = fields; f < &fields[ARRAY_SIZE(fields)]; f++) {
+ if (!strcmp(f->name, name)) {
+ *f_out = f;
+ return true;
+ }
+ }
+ *f_out = NULL;
+ return false;
+}
+
struct protocol {
const char *name;
uint16_t dl_type;
@@ -406,10 +436,23 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
while (ofputil_parse_key_value(&string, &name, &value)) {
const struct protocol *p;
+ const struct ox_fields *f;
const struct mf_field *mf;
char *error = NULL;
- if (parse_protocol(name, &p)) {
+ if (parse_oxs_field(name, &f)) {
+ if(f->fl_type == OFPXST_OFB_DURATION) {
+ oxs_field_set |= 1<<0;
+ } else if(f->fl_type == OFPXST_OFB_IDLE_TIME) {
+ oxs_field_set |= 1<<1;
+ } else if(f->fl_type == OFPXST_OFB_FLOW_COUNT) {
+ oxs_field_set |= 1<<2;
+ } else if(f->fl_type == OFPXST_OFB_PACKET_COUNT) {
+ oxs_field_set |= 1<<3;
+ } else if(f->fl_type == OFPXST_OFB_BYTE_COUNT) {
+ oxs_field_set |= 1<<4;
+ }
+ } else if (parse_protocol(name, &p)) {
match_set_dl_type(&fm->match, htons(p->dl_type));
if (p->nw_proto) {
match_set_nw_proto(&fm->match, p->nw_proto);
@@ -3523,6 +3523,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
ofp_print_flow_stats_request(string, oh);
break;
+ case OFPTYPE_OXS_FLOW_STATS_REQUEST:
+ ofp_print_stats(string, oh);
+ ofp_print_flow_stats_request(string, oh);
+ break;
+
case OFPTYPE_TABLE_STATS_REQUEST:
ofp_print_stats(string, oh);
break;
@@ -3547,6 +3552,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
ofp_print_flow_stats_reply(string, oh);
break;
+ case OFPTYPE_OXS_FLOW_STATS_REPLY:
+ ofp_print_stats(string, oh);
+ ofp_print_flow_stats_reply(string, oh);
+ break;
+
case OFPTYPE_QUEUE_STATS_REPLY:
ofp_print_stats(string, oh);
ofp_print_ofpst_queue_reply(string, oh, verbosity);
@@ -1392,6 +1392,8 @@ is_admitted_msg(const struct ofpbuf *b)
case OFPTYPE_DESC_STATS_REPLY:
case OFPTYPE_FLOW_STATS_REQUEST:
case OFPTYPE_FLOW_STATS_REPLY:
+ case OFPTYPE_OXS_FLOW_STATS_REQUEST:
+ case OFPTYPE_OXS_FLOW_STATS_REPLY:
case OFPTYPE_AGGREGATE_STATS_REQUEST:
case OFPTYPE_AGGREGATE_STATS_REPLY:
case OFPTYPE_TABLE_STATS_REQUEST:
@@ -7987,6 +7987,9 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
case OFPTYPE_FLOW_STATS_REQUEST:
return handle_flow_stats_request(ofconn, oh);
+ case OFPTYPE_OXS_FLOW_STATS_REQUEST:
+ return handle_flow_stats_request(ofconn, oh);
+
case OFPTYPE_AGGREGATE_STATS_REQUEST:
return handle_aggregate_stats_request(ofconn, oh);
@@ -8062,6 +8065,7 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
case OFPTYPE_DESC_STATS_REPLY:
case OFPTYPE_FLOW_STATS_REPLY:
+ case OFPTYPE_OXS_FLOW_STATS_REPLY:
case OFPTYPE_QUEUE_STATS_REPLY:
case OFPTYPE_PORT_STATS_REPLY:
case OFPTYPE_TABLE_STATS_REPLY: