X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fovs-ofctl.c;h=54e4b0c329c216bae9f8546f33d6af3081a1b31d;hb=d12513f7075373d07565f66ab4c781b73b00867d;hp=1901e242a2369c47fb4c59744a99d7487c50159b;hpb=8050b31d635005a11e5f4ef5517af8672af7cf55;p=openvswitch diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 1901e242..54e4b0c3 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -51,12 +51,6 @@ VLOG_DEFINE_THIS_MODULE(ofctl); - -#define MOD_PORT_CMD_UP "up" -#define MOD_PORT_CMD_DOWN "down" -#define MOD_PORT_CMD_FLOOD "flood" -#define MOD_PORT_CMD_NOFLOOD "noflood" - /* Use strict matching for flow mod commands? */ static bool strict; @@ -217,7 +211,7 @@ open_vconn__(const char *name, const char *default_suffix, struct stat s; char *bridge_path, *datapath_name, *datapath_type; - bridge_path = xasprintf("%s/%s.%s", ovs_rundir, name, default_suffix); + bridge_path = xasprintf("%s/%s.%s", ovs_rundir(), name, default_suffix); dp_parse_name(name, &datapath_name, &datapath_type); if (strstr(name, ":")) { @@ -239,7 +233,7 @@ open_vconn__(const char *name, const char *default_suffix, } socket_name = xasprintf("%s/%s.%s", - ovs_rundir, dpif_name, default_suffix); + ovs_rundir(), dpif_name, default_suffix); if (stat(socket_name, &s)) { ovs_fatal(errno, "cannot connect to %s: stat failed on %s", name, socket_name); @@ -307,7 +301,7 @@ dump_trivial_transaction(const char *vconn_name, uint8_t request_type) static void dump_stats_transaction(const char *vconn_name, struct ofpbuf *request) { - uint32_t send_xid = ((struct ofp_header *) request->data)->xid; + ovs_be32 send_xid = ((struct ofp_header *) request->data)->xid; struct vconn *vconn; bool done = false; @@ -343,6 +337,24 @@ dump_trivial_stats_transaction(const char *vconn_name, uint8_t stats_type) dump_stats_transaction(vconn_name, request); } +/* Sends 'request', which should be a request that only has a reply if an error + * occurs, and waits for it to succeed or fail. If an error does occur, prints + * it and exits with an error. */ +static void +dump_noreply_transaction(struct vconn *vconn, struct ofpbuf *request) +{ + struct ofpbuf *reply; + + update_openflow_length(request); + run(vconn_transact_noreply(vconn, request, &reply), + "talking to %s", vconn_get_name(vconn)); + if (reply) { + ofp_print(stderr, reply->data, reply->size, 2); + exit(1); + } + ofpbuf_delete(reply); +} + static void do_show(int argc OVS_UNUSED, char *argv[]) { @@ -392,46 +404,67 @@ do_dump_tables(int argc OVS_UNUSED, char *argv[]) dump_trivial_stats_transaction(argv[1], OFPST_TABLE); } -static uint16_t -str_to_port_no(const char *vconn_name, const char *str) +/* Opens a connection to 'vconn_name', fetches the ofp_phy_port structure for + * 'port_name' (which may be a port name or number), and copies it into + * '*oppp'. */ +static void +fetch_ofp_phy_port(const char *vconn_name, const char *port_name, + struct ofp_phy_port *oppp) { struct ofpbuf *request, *reply; struct ofp_switch_features *osf; + unsigned int port_no; struct vconn *vconn; 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. */ - if (str_to_uint(str, 10, &port_no)) { - return port_no; + /* Try to interpret the argument as a port number. */ + if (!str_to_uint(port_name, 10, &port_no)) { + port_no = UINT_MAX; } - /* Send a "Features Request" to resolve the name into a number. */ + /* Fetch the switch's ofp_switch_features. */ make_openflow(sizeof(struct ofp_header), OFPT_FEATURES_REQUEST, &request); open_vconn(vconn_name, &vconn); run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_name); osf = reply->data; + if (reply->size < sizeof *osf) { + ovs_fatal(0, "%s: received too-short features reply (only %zu bytes)", + vconn_name, reply->size); + } n_ports = (reply->size - sizeof *osf) / sizeof *osf->ports; for (port_idx = 0; port_idx < n_ports; port_idx++) { - /* Check argument as an interface name */ - if (!strncmp((char *)osf->ports[port_idx].name, str, - sizeof osf->ports[0].name)) { - break; + const struct ofp_phy_port *opp = &osf->ports[port_idx]; + + if (port_no != UINT_MAX + ? htons(port_no) == opp->port_no + : !strncmp((char *) opp->name, port_name, sizeof opp->name)) { + *oppp = *opp; + ofpbuf_delete(reply); + vconn_close(vconn); + return; } } - if (port_idx == n_ports) { - ovs_fatal(0, "couldn't find monitored port: %s", str); - } + ovs_fatal(0, "%s: couldn't find port `%s'", vconn_name, port_name); +} - ofpbuf_delete(reply); - vconn_close(vconn); +/* Returns the port number corresponding to 'port_name' (which may be a port + * name or number) within the switch 'vconn_name'. */ +static uint16_t +str_to_port_no(const char *vconn_name, const char *port_name) +{ + unsigned int port_no; - return port_idx; + if (str_to_uint(port_name, 10, &port_no)) { + return port_no; + } else { + struct ofp_phy_port opp; + + fetch_ofp_phy_port(vconn_name, port_name, &opp); + return ntohs(opp.port_no); + } } static void @@ -443,8 +476,7 @@ do_dump_flows(int argc, char *argv[]) req = alloc_stats_request(sizeof *req, OFPST_FLOW, &request); parse_ofp_str(&pf, NULL, argc > 2 ? argv[2] : ""); - flow_to_match(&pf.rule.flow, pf.rule.wc.wildcards, NXFF_OPENFLOW10, - &req->match); + ofputil_cls_rule_to_match(&pf.rule, NXFF_OPENFLOW10, &req->match); memset(&req->pad, 0, sizeof req->pad); req->out_port = htons(pf.out_port); @@ -460,8 +492,7 @@ do_dump_aggregate(int argc, char *argv[]) req = alloc_stats_request(sizeof *req, OFPST_AGGREGATE, &request); parse_ofp_str(&pf, NULL, argc > 2 ? argv[2] : ""); - flow_to_match(&pf.rule.flow, pf.rule.wc.wildcards, NXFF_OPENFLOW10, - &req->match); + ofputil_cls_rule_to_match(&pf.rule, NXFF_OPENFLOW10, &req->match); memset(&req->pad, 0, sizeof req->pad); req->out_port = htons(pf.out_port); @@ -496,12 +527,12 @@ static void do_add_flow(int argc OVS_UNUSED, char *argv[]) { struct vconn *vconn; - struct ofpbuf *buffer; + struct ofpbuf *request; - buffer = parse_ofp_flow_mod_str(argv[2], OFPFC_ADD); + request = parse_ofp_flow_mod_str(argv[2], OFPFC_ADD); open_vconn(argv[1], &vconn); - send_openflow_buffer(vconn, buffer); + dump_noreply_transaction(vconn, request); vconn_close(vconn); } @@ -519,7 +550,7 @@ do_add_flows(int argc OVS_UNUSED, char *argv[]) open_vconn(argv[1], &vconn); while ((b = parse_ofp_add_flow_file(file)) != NULL) { - send_openflow_buffer(vconn, b); + dump_noreply_transaction(vconn, b); } vconn_close(vconn); fclose(file); @@ -535,7 +566,7 @@ do_mod_flows(int argc OVS_UNUSED, char *argv[]) command = strict ? OFPFC_MODIFY_STRICT : OFPFC_MODIFY; buffer = parse_ofp_flow_mod_str(argv[2], command); open_vconn(argv[1], &vconn); - send_openflow_buffer(vconn, buffer); + dump_noreply_transaction(vconn, buffer); vconn_close(vconn); } @@ -549,23 +580,7 @@ static void do_del_flows(int argc, char *argv[]) buffer = parse_ofp_flow_mod_str(argc > 2 ? argv[2] : "", command); open_vconn(argv[1], &vconn); - send_openflow_buffer(vconn, buffer); - vconn_close(vconn); -} - -static void -do_tun_cookie(int argc OVS_UNUSED, char *argv[]) -{ - struct nxt_tun_id_cookie *tun_id_cookie; - struct ofpbuf *buffer; - struct vconn *vconn; - - tun_id_cookie = make_nxmsg(sizeof *tun_id_cookie, NXT_TUN_ID_FROM_COOKIE, - &buffer); - tun_id_cookie->set = !strcmp(argv[2], "true"); - - open_vconn(argv[1], &vconn); - send_openflow_buffer(vconn, buffer); + dump_noreply_transaction(vconn, buffer); vconn_close(vconn); } @@ -593,7 +608,7 @@ do_monitor(int argc, char *argv[]) osc = make_openflow(sizeof *osc, OFPT_SET_CONFIG, &buf); osc->miss_send_len = htons(miss_send_len); - send_openflow_buffer(vconn, buf); + dump_noreply_transaction(vconn, buf); } monitor_vconn(vconn); } @@ -640,80 +655,36 @@ do_probe(int argc OVS_UNUSED, char *argv[]) static void do_mod_port(int argc OVS_UNUSED, char *argv[]) { - struct ofpbuf *request, *reply; - struct ofp_switch_features *osf; struct ofp_port_mod *opm; + struct ofp_phy_port opp; + struct ofpbuf *request; struct vconn *vconn; - char *endptr; - int n_ports; - int port_idx; - int port_no; - - /* Check if the argument is a port index. Otherwise, treat it as - * the port name. */ - port_no = strtol(argv[2], &endptr, 10); - if (port_no == 0 && endptr == argv[2]) { - port_no = -1; - } - - /* 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); - run(vconn_transact(vconn, request, &reply), "talking to %s", argv[1]); - - osf = reply->data; - n_ports = (reply->size - sizeof *osf) / sizeof *osf->ports; - - for (port_idx = 0; port_idx < n_ports; port_idx++) { - if (port_no != -1) { - /* Check argument as a port index */ - if (osf->ports[port_idx].port_no == htons(port_no)) { - break; - } - } else { - /* Check argument as an interface name */ - if (!strncmp((char *)osf->ports[port_idx].name, argv[2], - sizeof osf->ports[0].name)) { - break; - } - - } - } - if (port_idx == n_ports) { - ovs_fatal(0, "couldn't find monitored port: %s", argv[2]); - } + fetch_ofp_phy_port(argv[1], argv[2], &opp); opm = make_openflow(sizeof(struct ofp_port_mod), OFPT_PORT_MOD, &request); - opm->port_no = osf->ports[port_idx].port_no; - memcpy(opm->hw_addr, osf->ports[port_idx].hw_addr, sizeof opm->hw_addr); + opm->port_no = opp.port_no; + memcpy(opm->hw_addr, opp.hw_addr, sizeof opm->hw_addr); opm->config = htonl(0); opm->mask = htonl(0); opm->advertise = htonl(0); - printf("modifying port: %s\n", osf->ports[port_idx].name); - - if (!strncasecmp(argv[3], MOD_PORT_CMD_UP, sizeof MOD_PORT_CMD_UP)) { + if (!strcasecmp(argv[3], "up")) { opm->mask |= htonl(OFPPC_PORT_DOWN); - } else if (!strncasecmp(argv[3], MOD_PORT_CMD_DOWN, - sizeof MOD_PORT_CMD_DOWN)) { + } else if (!strcasecmp(argv[3], "down")) { opm->mask |= htonl(OFPPC_PORT_DOWN); opm->config |= htonl(OFPPC_PORT_DOWN); - } else if (!strncasecmp(argv[3], MOD_PORT_CMD_FLOOD, - sizeof MOD_PORT_CMD_FLOOD)) { + } else if (!strcasecmp(argv[3], "flood")) { opm->mask |= htonl(OFPPC_NO_FLOOD); - } else if (!strncasecmp(argv[3], MOD_PORT_CMD_NOFLOOD, - sizeof MOD_PORT_CMD_NOFLOOD)) { + } else if (!strcasecmp(argv[3], "noflood")) { opm->mask |= htonl(OFPPC_NO_FLOOD); opm->config |= htonl(OFPPC_NO_FLOOD); } else { ovs_fatal(0, "unknown mod-port command '%s'", argv[3]); } - send_openflow_buffer(vconn, request); - - ofpbuf_delete(reply); + open_vconn(argv[1], &vconn); + dump_noreply_transaction(vconn, request); vconn_close(vconn); } @@ -755,7 +726,7 @@ do_ping(int argc, char *argv[]) ofp_print(stdout, reply, reply->size, 2); } printf("%zu bytes from %s: xid=%08"PRIx32" time=%.1f ms\n", - reply->size - sizeof *rpy_hdr, argv[1], rpy_hdr->xid, + reply->size - sizeof *rpy_hdr, argv[1], ntohl(rpy_hdr->xid), (1000*(double)(end.tv_sec - start.tv_sec)) + (.001*(end.tv_usec - start.tv_usec))); ofpbuf_delete(request); @@ -901,7 +872,6 @@ static const struct command all_commands[] = { { "add-flows", 2, 2, do_add_flows }, { "mod-flows", 2, 2, do_mod_flows }, { "del-flows", 1, 2, do_del_flows }, - { "tun-cookie", 2, 2, do_tun_cookie }, { "dump-ports", 1, 2, do_dump_ports }, { "mod-port", 3, 3, do_mod_port }, { "probe", 1, 1, do_probe },