netdev: Fix carrier status for down interfaces.
[sliver-openvswitch.git] / utilities / ovs-ofctl.c
index b13cf96..13f583e 100644 (file)
@@ -150,6 +150,7 @@ usage(void)
            "  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"
@@ -399,7 +400,7 @@ str_to_port_no(const char *vconn_name, const char *str)
     int n_ports;
     int port_idx;
     unsigned int port_no;
-    
+
 
     /* Check if the argument is a port index.  Otherwise, treat it as
      * the port name. */
@@ -464,6 +465,30 @@ do_dump_aggregate(int argc, char *argv[])
     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[])
 {
@@ -499,8 +524,8 @@ static void
 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) {
@@ -508,43 +533,8 @@ do_add_flows(int argc OVS_UNUSED, char *argv[])
     }
 
     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);
@@ -595,7 +585,7 @@ static void do_del_flows(int argc, char *argv[])
 
     /* Parse and send. */
     ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
-    parse_ofp_str(argc > 2 ? argv[2] : "", &ofm->match, NULL, NULL, 
+    parse_ofp_str(argc > 2 ? argv[2] : "", &ofm->match, NULL, NULL,
                   &out_port, &priority, NULL, NULL, NULL);
     if (strict) {
         ofm->command = htons(OFPFC_DELETE_STRICT);
@@ -710,7 +700,7 @@ do_mod_port(int argc OVS_UNUSED, char *argv[])
     int n_ports;
     int port_idx;
     int port_no;
-    
+
 
     /* Check if the argument is a port index.  Otherwise, treat it as
      * the port name. */
@@ -719,7 +709,7 @@ do_mod_port(int argc OVS_UNUSED, char *argv[])
         port_no = -1;
     }
 
-    /* Send a "Features Request" to get the information we need in order 
+    /* Send a "Features Request" to get the information we need in order
      * to modify the port. */
     make_openflow(sizeof(struct ofp_header), OFPT_FEATURES_REQUEST, &request);
     open_vconn(argv[1], &vconn);
@@ -736,7 +726,7 @@ do_mod_port(int argc OVS_UNUSED, char *argv[])
             }
         } else {
             /* Check argument as an interface name */
-            if (!strncmp((char *)osf->ports[port_idx].name, argv[2], 
+            if (!strncmp((char *)osf->ports[port_idx].name, argv[2],
                         sizeof osf->ports[0].name)) {
                 break;
             }
@@ -758,14 +748,14 @@ do_mod_port(int argc OVS_UNUSED, char *argv[])
 
     if (!strncasecmp(argv[3], MOD_PORT_CMD_UP, sizeof MOD_PORT_CMD_UP)) {
         opm->mask |= htonl(OFPPC_PORT_DOWN);
-    } else if (!strncasecmp(argv[3], MOD_PORT_CMD_DOWN, 
+    } else if (!strncasecmp(argv[3], MOD_PORT_CMD_DOWN,
                 sizeof MOD_PORT_CMD_DOWN)) {
         opm->mask |= htonl(OFPPC_PORT_DOWN);
         opm->config |= htonl(OFPPC_PORT_DOWN);
-    } else if (!strncasecmp(argv[3], MOD_PORT_CMD_FLOOD, 
+    } else if (!strncasecmp(argv[3], MOD_PORT_CMD_FLOOD,
                 sizeof MOD_PORT_CMD_FLOOD)) {
         opm->mask |= htonl(OFPPC_NO_FLOOD);
-    } else if (!strncasecmp(argv[3], MOD_PORT_CMD_NOFLOOD, 
+    } else if (!strncasecmp(argv[3], MOD_PORT_CMD_NOFLOOD,
                 sizeof MOD_PORT_CMD_NOFLOOD)) {
         opm->mask |= htonl(OFPPC_NO_FLOOD);
         opm->config |= htonl(OFPPC_NO_FLOOD);
@@ -869,6 +859,26 @@ do_benchmark(int argc OVS_UNUSED, char *argv[])
            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)
 {
@@ -884,6 +894,7 @@ static const struct command all_commands[] = {
     { "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 },
@@ -894,6 +905,7 @@ static const struct command all_commands[] = {
     { "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 },
 };