X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=utilities%2Fovs-ofctl.c;h=13f583e7e3a1bbb064cb4bac1e03d37115370642;hb=c424adb3ac3460818256181a073b09e92cdc562a;hp=b13cf96bac9486f7a0d528f203441db5bcce758a;hpb=f22716dcca299b863dd72eb193fb1283c5f686da;p=openvswitch diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index b13cf96b..13f583e7 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -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 }, };