X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fovs-ofctl.c;h=7b20ba097ab957775a43672110b2a61a02619ac0;hb=2bcf7df6f7a87d8940deff6fbbc359b0a310a74a;hp=d7c88b682c63cc83acfc47106f9369a14b037cb4;hpb=e89993f33c2ccd0373a47941df82bdd797c525ea;p=openvswitch diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index d7c88b68..7b20ba09 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -172,6 +172,8 @@ usage(void) " dump-desc SWITCH print switch description\n" " dump-tables SWITCH print table stats\n" " mod-port SWITCH IFACE ACT modify port behavior\n" + " get-frags SWITCH print fragment handling behavior\n" + " set-frags SWITCH FRAG_MODE set fragment handling behavior\n" " dump-ports SWITCH [PORT] print port statistics\n" " dump-flows SWITCH print all flow entries\n" " dump-flows SWITCH FLOW print matching FLOWs\n" @@ -185,10 +187,10 @@ usage(void) " replace-flows SWITCH FILE replace flows with those in FILE\n" " monitor SWITCH [MISSLEN] print packets received from SWITCH\n" "\nFor OpenFlow switches and controllers:\n" - " probe VCONN probe whether VCONN is up\n" - " ping VCONN [N] latency of N-byte echos\n" - " benchmark VCONN N COUNT bandwidth of COUNT N-byte echos\n" - "where each SWITCH is an active OpenFlow connection method.\n", + " probe TARGET probe whether TARGET is up\n" + " ping TARGET [N] latency of N-byte echos\n" + " benchmark TARGET N COUNT bandwidth of COUNT N-byte echos\n" + "where SWITCH or TARGET is an active OpenFlow connection method.\n", program_name, program_name); vconn_usage(true, false, false); vlog_usage(); @@ -351,7 +353,9 @@ dump_trivial_stats_transaction(const char *vconn_name, uint8_t stats_type) /* 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. */ + * it and exits with an error. + * + * Destroys all of the 'requests'. */ static void transact_multiple_noreply(struct vconn *vconn, struct list *requests) { @@ -372,7 +376,9 @@ transact_multiple_noreply(struct vconn *vconn, struct list *requests) /* 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. */ + * it and exits with an error. + * + * Destroys 'request'. */ static void transact_noreply(struct vconn *vconn, struct ofpbuf *request) { @@ -383,6 +389,44 @@ transact_noreply(struct vconn *vconn, struct ofpbuf *request) transact_multiple_noreply(vconn, &requests); } +static void +fetch_switch_config(struct vconn *vconn, struct ofp_switch_config *config_) +{ + struct ofp_switch_config *config; + struct ofp_header *header; + struct ofpbuf *request; + struct ofpbuf *reply; + + make_openflow(sizeof(struct ofp_header), OFPT_GET_CONFIG_REQUEST, + &request); + run(vconn_transact(vconn, request, &reply), + "talking to %s", vconn_get_name(vconn)); + + header = reply->data; + if (header->type != OFPT_GET_CONFIG_REPLY || + header->length != htons(sizeof *config)) { + ovs_fatal(0, "%s: bad reply to config request", vconn_get_name(vconn)); + } + + config = reply->data; + *config_ = *config; +} + +static void +set_switch_config(struct vconn *vconn, struct ofp_switch_config *config_) +{ + struct ofp_switch_config *config; + struct ofp_header save_header; + struct ofpbuf *request; + + config = make_openflow(sizeof *config, OFPT_SET_CONFIG, &request); + save_header = config->header; + *config = *config_; + config->header = save_header; + + transact_noreply(vconn, request); +} + static void do_show(int argc OVS_UNUSED, char *argv[]) { @@ -534,7 +578,7 @@ static void do_dump_flows__(int argc, char *argv[], bool aggregate) { enum nx_flow_format min_flow_format, flow_format; - struct flow_stats_request fsr; + struct ofputil_flow_stats_request fsr; struct ofpbuf *request; struct vconn *vconn; @@ -542,6 +586,9 @@ do_dump_flows__(int argc, char *argv[], bool aggregate) open_vconn(argv[1], &vconn); min_flow_format = ofputil_min_flow_format(&fsr.match); + if (fsr.cookie_mask != htonll(0)) { + min_flow_format = NXFF_NXM; + } flow_format = negotiate_highest_flow_format(vconn, min_flow_format); request = ofputil_encode_flow_stats_request(&fsr, flow_format); dump_stats_transaction(argv[1], request); @@ -720,13 +767,11 @@ do_monitor(int argc, char *argv[]) open_vconn(argv[1], &vconn); if (argc > 2) { - int miss_send_len = atoi(argv[2]); - struct ofp_switch_config *osc; - struct ofpbuf *buf; + struct ofp_switch_config config; - osc = make_openflow(sizeof *osc, OFPT_SET_CONFIG, &buf); - osc->miss_send_len = htons(miss_send_len); - transact_noreply(vconn, buf); + fetch_switch_config(vconn, &config); + config.miss_send_len = htons(atoi(argv[2])); + set_switch_config(vconn, &config); } monitor_vconn(vconn); } @@ -797,6 +842,11 @@ do_mod_port(int argc OVS_UNUSED, char *argv[]) } else if (!strcasecmp(argv[3], "noflood")) { opm->mask |= htonl(OFPPC_NO_FLOOD); opm->config |= htonl(OFPPC_NO_FLOOD); + } else if (!strcasecmp(argv[3], "forward")) { + opm->mask |= htonl(OFPPC_NO_FWD); + } else if (!strcasecmp(argv[3], "noforward")) { + opm->mask |= htonl(OFPPC_NO_FWD); + opm->config |= htonl(OFPPC_NO_FWD); } else { ovs_fatal(0, "unknown mod-port command '%s'", argv[3]); } @@ -806,6 +856,51 @@ do_mod_port(int argc OVS_UNUSED, char *argv[]) vconn_close(vconn); } +static void +do_get_frags(int argc OVS_UNUSED, char *argv[]) +{ + struct ofp_switch_config config; + struct vconn *vconn; + + open_vconn(argv[1], &vconn); + fetch_switch_config(vconn, &config); + puts(ofputil_frag_handling_to_string(ntohs(config.flags))); + vconn_close(vconn); +} + +static void +do_set_frags(int argc OVS_UNUSED, char *argv[]) +{ + struct ofp_switch_config config; + enum ofp_config_flags mode; + struct vconn *vconn; + ovs_be16 flags; + + if (!ofputil_frag_handling_from_string(argv[2], &mode)) { + ovs_fatal(0, "%s: unknown fragment handling mode", argv[2]); + } + + open_vconn(argv[1], &vconn); + fetch_switch_config(vconn, &config); + flags = htons(mode) | (config.flags & htons(~OFPC_FRAG_MASK)); + if (flags != config.flags) { + /* Set the configuration. */ + config.flags = flags; + set_switch_config(vconn, &config); + + /* Then retrieve the configuration to see if it really took. OpenFlow + * doesn't define error reporting for bad modes, so this is all we can + * do. */ + fetch_switch_config(vconn, &config); + if (flags != config.flags) { + ovs_fatal(0, "%s: setting fragment handling mode failed (this " + "switch probably doesn't support mode \"%s\")", + argv[1], ofputil_frag_handling_to_string(mode)); + } + } + vconn_close(vconn); +} + static void do_ping(int argc, char *argv[]) { @@ -1041,8 +1136,8 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index) min_flow_format = NXFF_OPENFLOW10; while (!ds_get_preprocessed_line(&s, file)) { struct fte_version *version; + struct ofputil_flow_mod fm; enum nx_flow_format min_ff; - struct flow_mod fm; parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), true); @@ -1076,7 +1171,7 @@ static void read_flows_from_switch(struct vconn *vconn, enum nx_flow_format flow_format, struct classifier *cls, int index) { - struct flow_stats_request fsr; + struct ofputil_flow_stats_request fsr; struct ofpbuf *request; ovs_be32 send_xid; bool done; @@ -1085,6 +1180,7 @@ read_flows_from_switch(struct vconn *vconn, enum nx_flow_format flow_format, cls_rule_init_catchall(&fsr.match, 0); fsr.out_port = OFPP_NONE; fsr.table_id = 0xff; + fsr.cookie = fsr.cookie_mask = htonll(0); request = ofputil_encode_flow_stats_request(&fsr, flow_format); send_xid = ((struct ofp_header *) request->data)->xid; send_openflow_buffer(vconn, request); @@ -1152,7 +1248,7 @@ fte_make_flow_mod(const struct fte *fte, int index, uint16_t command, enum nx_flow_format flow_format, struct list *packets) { const struct fte_version *version = fte->versions[index]; - struct flow_mod fm; + struct ofputil_flow_mod fm; struct ofpbuf *ofm; fm.cr = fte->rule; @@ -1334,7 +1430,7 @@ do_parse_flows(int argc OVS_UNUSED, char *argv[]) file = fopen(argv[1], "r"); if (file == NULL) { - ovs_fatal(errno, "%s: open", argv[2]); + ovs_fatal(errno, "%s: open", argv[1]); } flow_format = NXFF_OPENFLOW10; @@ -1363,6 +1459,7 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) while (!ds_get_line(&in, stdin)) { struct ofpbuf nx_match; struct cls_rule rule; + ovs_be64 cookie, cookie_mask; int match_len; int error; char *s; @@ -1386,14 +1483,15 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) match_len = nx_match_from_string(ds_cstr(&in), &nx_match); /* Convert nx_match to cls_rule. */ - error = nx_pull_match(&nx_match, match_len, 0, &rule); + error = nx_pull_match(&nx_match, match_len, 0, &rule, + &cookie, &cookie_mask); if (!error) { char *out; /* Convert cls_rule back to nx_match. */ ofpbuf_uninit(&nx_match); ofpbuf_init(&nx_match, 0); - match_len = nx_put_match(&nx_match, &rule); + match_len = nx_put_match(&nx_match, &rule, cookie, cookie_mask); /* Convert nx_match to string. */ out = nx_match_to_string(nx_match.data, match_len); @@ -1442,6 +1540,8 @@ static const struct command all_commands[] = { { "diff-flows", 2, 2, do_diff_flows }, { "dump-ports", 1, 2, do_dump_ports }, { "mod-port", 3, 3, do_mod_port }, + { "get-frags", 1, 1, do_get_frags }, + { "set-frags", 2, 2, do_set_frags }, { "probe", 1, 1, do_probe }, { "ping", 1, 2, do_ping }, { "benchmark", 3, 3, do_benchmark },