X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fovs-ofctl.c;h=54e4b0c329c216bae9f8546f33d6af3081a1b31d;hb=d12513f7075373d07565f66ab4c781b73b00867d;hp=d39e187b57ffbbf3629352f775cd5d190f978ca9;hpb=f48667811c04d848dc345aa0bbda29d889b5f960;p=openvswitch diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index d39e187b..54e4b0c3 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -337,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[]) { @@ -386,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 ntohs(osf->ports[port_idx].port_no); + 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 @@ -488,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); } @@ -511,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); @@ -527,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); } @@ -541,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); } @@ -585,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); } @@ -632,60 +655,20 @@ 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 (!strcasecmp(argv[3], "up")) { opm->mask |= htonl(OFPPC_PORT_DOWN); } else if (!strcasecmp(argv[3], "down")) { @@ -700,9 +683,8 @@ do_mod_port(int argc OVS_UNUSED, char *argv[]) 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); } @@ -890,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 },