" dump-flows SWITCH FLOW print matching FLOWs\n"
" dump-aggregate SWITCH print aggregate flow statistics\n"
" dump-aggregate SWITCH FLOW print aggregate stats for FLOWs\n"
+ " queue-stats SWITCH [PORT [QUEUE]] dump queue stats\n"
" add-flow SWITCH FLOW add flow described by FLOW\n"
" add-flows SWITCH FILE add flows from FILE\n"
" mod-flows SWITCH FLOW modify actions of matching FLOWs\n"
dump_stats_transaction(argv[1], request);
}
+static void
+do_queue_stats(int argc, char *argv[])
+{
+ struct ofp_queue_stats_request *req;
+ struct ofpbuf *request;
+
+ req = alloc_stats_request(sizeof *req, OFPST_QUEUE, &request);
+
+ if (argc > 2 && argv[2][0] && strcasecmp(argv[2], "all")) {
+ req->port_no = htons(str_to_port_no(argv[1], argv[2]));
+ } else {
+ req->port_no = htons(OFPP_ALL);
+ }
+ if (argc > 3 && argv[3][0] && strcasecmp(argv[3], "all")) {
+ req->queue_id = htonl(atoi(argv[3]));
+ } else {
+ req->queue_id = htonl(OFPQ_ALL);
+ }
+
+ memset(req->pad, 0, sizeof req->pad);
+
+ dump_stats_transaction(argv[1], request);
+}
+
static void
do_add_flow(int argc OVS_UNUSED, char *argv[])
{
do_add_flows(int argc OVS_UNUSED, char *argv[])
{
struct vconn *vconn;
+ struct ofpbuf *b;
FILE *file;
- char line[1024];
file = fopen(argv[2], "r");
if (file == NULL) {
}
open_vconn(argv[1], &vconn);
- while (fgets(line, sizeof line, file)) {
- struct ofpbuf *buffer;
- struct ofp_flow_mod *ofm;
- uint16_t priority, idle_timeout, hard_timeout;
- uint64_t cookie;
- struct ofp_match match;
-
- char *comment;
-
- /* Delete comments. */
- comment = strchr(line, '#');
- if (comment) {
- *comment = '\0';
- }
-
- /* Drop empty lines. */
- if (line[strspn(line, " \t\n")] == '\0') {
- continue;
- }
-
- /* Parse and send. parse_ofp_str() will expand and reallocate
- * the data in 'buffer', so we can't keep pointers to across the
- * parse_ofp_str() call. */
- make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
- parse_ofp_str(line, &match, buffer,
- NULL, NULL, &priority, &idle_timeout, &hard_timeout,
- &cookie);
- ofm = buffer->data;
- ofm->match = match;
- ofm->command = htons(OFPFC_ADD);
- ofm->cookie = htonll(cookie);
- ofm->idle_timeout = htons(idle_timeout);
- ofm->hard_timeout = htons(hard_timeout);
- ofm->buffer_id = htonl(UINT32_MAX);
- ofm->priority = htons(priority);
-
- send_openflow_buffer(vconn, buffer);
+ while ((b = parse_ofp_add_flow_file(file)) != NULL) {
+ send_openflow_buffer(vconn, b);
}
vconn_close(vconn);
fclose(file);
count * message_size / (duration / 1000.0));
}
+/* This command is really only useful for testing the flow parser (ofp_parse),
+ * so it is undocumented. */
+static void
+do_parse_flows(int argc OVS_UNUSED, char *argv[])
+{
+ struct ofpbuf *b;
+ FILE *file;
+
+ file = fopen(argv[1], "r");
+ if (file == NULL) {
+ ovs_fatal(errno, "%s: open", argv[2]);
+ }
+
+ while ((b = parse_ofp_add_flow_file(file)) != NULL) {
+ ofp_print(stdout, b->data, b->size, 0);
+ ofpbuf_delete(b);
+ }
+ fclose(file);
+}
+
static void
do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
{ "dump-tables", 1, 1, do_dump_tables },
{ "dump-flows", 1, 2, do_dump_flows },
{ "dump-aggregate", 1, 2, do_dump_aggregate },
+ { "queue-stats", 1, 3, do_queue_stats },
{ "add-flow", 2, 2, do_add_flow },
{ "add-flows", 2, 2, do_add_flows },
{ "mod-flows", 2, 2, do_mod_flows },
{ "probe", 1, 1, do_probe },
{ "ping", 1, 2, do_ping },
{ "benchmark", 3, 3, do_benchmark },
+ { "parse-flows", 1, 1, do_parse_flows },
{ "help", 0, INT_MAX, do_help },
{ NULL, 0, 0, NULL },
};