X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=utilities%2Fovs-ofctl.c;h=95bf1bfbbe4c3d6dbae878391fdde7d89e7f59dd;hb=03f976b173e2e670eb2fa77eae8eacd2abf4bf84;hp=899ce4e669a5e47adc5369bad001ffb9e0aa8500;hpb=0b4f207828c9354761efc60bd9ab90898d9cc623;p=sliver-openvswitch.git diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 899ce4e66..95bf1bfbb 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -281,6 +281,7 @@ 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" + " mod-table SWITCH MOD modify flow table 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" @@ -301,6 +302,13 @@ usage(void) " monitor SWITCH [MISSLEN] [invalid_ttl] [watch:[...]]\n" " print packets received from SWITCH\n" " snoop SWITCH snoop on SWITCH and its controller\n" + " add-group SWITCH GROUP add group described by GROUP\n" + " add-group SWITCH FILE add group from FILE\n" + " mod-group SWITCH GROUP modify specific group\n" + " del-groups SWITCH [GROUP] delete matching GROUPs\n" + " dump-group-features SWITCH print group features\n" + " dump-groups SWITCH print group description\n" + " dump-group-stats SWITCH [GROUP] print group statistics\n" "\nFor OpenFlow switches and controllers:\n" " probe TARGET probe whether TARGET is up\n" " ping TARGET [N] latency of N-byte echos\n" @@ -871,13 +879,12 @@ prepare_dump_flows(int argc, char *argv[], bool aggregate, char *error; error = parse_ofp_flow_stats_request_str(&fsr, aggregate, - argc > 2 ? argv[2] : ""); + argc > 2 ? argv[2] : "", + &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } - usable_protocols = ofputil_flow_stats_request_usable_protocols(&fsr); - protocol = open_vconn(argv[1], &vconn); protocol = set_protocol_for_flow_dump(vconn, protocol, usable_protocols); *requestp = ofputil_encode_flow_stats_request(&fsr, protocol); @@ -1031,17 +1038,13 @@ ofctl_queue_stats(int argc, char *argv[]) } static enum ofputil_protocol -open_vconn_for_flow_mod(const char *remote, - const struct ofputil_flow_mod *fms, size_t n_fms, - struct vconn **vconnp) +open_vconn_for_flow_mod(const char *remote, struct vconn **vconnp, + enum ofputil_protocol usable_protocols) { - enum ofputil_protocol usable_protocols; enum ofputil_protocol cur_protocol; char *usable_s; int i; - /* Figure out what flow formats will work. */ - usable_protocols = ofputil_flow_mod_usable_protocols(fms, n_fms); if (!(usable_protocols & allowed_protocols)) { char *allowed_s = ofputil_protocols_to_string(allowed_protocols); usable_s = ofputil_protocols_to_string(usable_protocols); @@ -1073,13 +1076,13 @@ open_vconn_for_flow_mod(const char *remote, static void ofctl_flow_mod__(const char *remote, struct ofputil_flow_mod *fms, - size_t n_fms) + size_t n_fms, enum ofputil_protocol usable_protocols) { enum ofputil_protocol protocol; struct vconn *vconn; size_t i; - protocol = open_vconn_for_flow_mod(remote, fms, n_fms, &vconn); + protocol = open_vconn_for_flow_mod(remote, &vconn, usable_protocols); for (i = 0; i < n_fms; i++) { struct ofputil_flow_mod *fm = &fms[i]; @@ -1093,32 +1096,37 @@ ofctl_flow_mod__(const char *remote, struct ofputil_flow_mod *fms, static void ofctl_flow_mod_file(int argc OVS_UNUSED, char *argv[], uint16_t command) { + enum ofputil_protocol usable_protocols; struct ofputil_flow_mod *fms = NULL; size_t n_fms = 0; char *error; - error = parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms); + error = parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms, + &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } - ofctl_flow_mod__(argv[1], fms, n_fms); + ofctl_flow_mod__(argv[1], fms, n_fms, usable_protocols); free(fms); } static void ofctl_flow_mod(int argc, char *argv[], uint16_t command) { + enum ofputil_protocol usable_protocols; + if (argc > 2 && !strcmp(argv[2], "-")) { ofctl_flow_mod_file(argc, argv, command); } else { struct ofputil_flow_mod fm; char *error; - error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command); + error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command, + &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } - ofctl_flow_mod__(argv[1], &fm, 1); + ofctl_flow_mod__(argv[1], &fm, 1, usable_protocols); } } @@ -1440,6 +1448,7 @@ ofctl_monitor(int argc, char *argv[]) { struct vconn *vconn; int i; + enum ofputil_protocol usable_protocols; open_vconn(argv[1], &vconn); for (i = 2; i < argc; i++) { @@ -1458,7 +1467,8 @@ ofctl_monitor(int argc, char *argv[]) struct ofpbuf *msg; char *error; - error = parse_flow_monitor_request(&fmr, arg + 6); + error = parse_flow_monitor_request(&fmr, arg + 6, + &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } @@ -1561,9 +1571,10 @@ ofctl_packet_out(int argc, char *argv[]) struct vconn *vconn; char *error; int i; + enum ofputil_protocol usable_protocols; /* TODO: Use in proto selection */ ofpbuf_init(&ofpacts, 64); - error = parse_ofpacts(argv[3], &ofpacts); + error = parse_ofpacts(argv[3], &ofpacts, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } @@ -1653,6 +1664,42 @@ found: vconn_close(vconn); } +static void +ofctl_mod_table(int argc OVS_UNUSED, char *argv[]) +{ + enum ofputil_protocol protocol, usable_protocols; + struct ofputil_table_mod tm; + struct vconn *vconn; + char *error; + int i; + + error = parse_ofp_table_mod(&tm, argv[2], argv[3], &usable_protocols); + if (error) { + ovs_fatal(0, "%s", error); + } + + protocol = open_vconn(argv[1], &vconn); + if (!(protocol & usable_protocols)) { + for (i = 0; i < sizeof(enum ofputil_protocol) * CHAR_BIT; i++) { + enum ofputil_protocol f = 1 << i; + if (f != protocol + && f & usable_protocols + && try_set_protocol(vconn, f, &protocol)) { + protocol = f; + break; + } + } + } + + if (!(protocol & usable_protocols)) { + char *usable_s = ofputil_protocols_to_string(usable_protocols); + ovs_fatal(0, "Switch does not support table mod message(%s)", usable_s); + } + + transact_noreply(vconn, ofputil_encode_table_mod(&tm, protocol)); + vconn_close(vconn); +} + static void ofctl_get_frags(int argc OVS_UNUSED, char *argv[]) { @@ -1839,6 +1886,153 @@ ofctl_benchmark(int argc OVS_UNUSED, char *argv[]) count * message_size / (duration / 1000.0)); } +static void +ofctl_group_mod__(const char *remote, struct ofputil_group_mod *gms, + size_t n_gms) +{ + struct ofputil_group_mod *gm; + struct ofpbuf *request; + + struct vconn *vconn; + size_t i; + + open_vconn(remote, &vconn); + + for (i = 0; i < n_gms; i++) { + gm = &gms[i]; + request = ofputil_encode_group_mod(vconn_get_version(vconn), gm); + if (request) { + transact_noreply(vconn, request); + } + } + + vconn_close(vconn); + +} + + +static void +ofctl_group_mod_file(int argc OVS_UNUSED, char *argv[], uint16_t command) +{ + struct ofputil_group_mod *gms = NULL; + enum ofputil_protocol usable_protocols; + size_t n_gms = 0; + char *error; + + error = parse_ofp_group_mod_file(argv[2], command, &gms, &n_gms, + &usable_protocols); + if (error) { + ovs_fatal(0, "%s", error); + } + ofctl_group_mod__(argv[1], gms, n_gms); + free(gms); +} + +static void +ofctl_group_mod(int argc, char *argv[], uint16_t command) +{ + if (argc > 2 && !strcmp(argv[2], "-")) { + ofctl_group_mod_file(argc, argv, command); + } else { + enum ofputil_protocol usable_protocols; + struct ofputil_group_mod gm; + char *error; + + error = parse_ofp_group_mod_str(&gm, command, argc > 2 ? argv[2] : "", + &usable_protocols); + if (error) { + ovs_fatal(0, "%s", error); + } + ofctl_group_mod__(argv[1], &gm, 1); + } +} + +static void +ofctl_add_group(int argc, char *argv[]) +{ + ofctl_group_mod(argc, argv, OFPGC11_ADD); +} + +static void +ofctl_add_groups(int argc, char *argv[]) +{ + ofctl_group_mod_file(argc, argv, OFPGC11_ADD); +} + +static void +ofctl_mod_group(int argc, char *argv[]) +{ + ofctl_group_mod(argc, argv, OFPGC11_MODIFY); +} + +static void +ofctl_del_groups(int argc, char *argv[]) +{ + ofctl_group_mod(argc, argv, OFPGC11_DELETE); +} + +static void +ofctl_dump_group_stats(int argc, char *argv[]) +{ + enum ofputil_protocol usable_protocols; + struct ofputil_group_mod gm; + struct ofpbuf *request; + struct vconn *vconn; + uint32_t group_id; + char *error; + + memset(&gm, 0, sizeof gm); + + error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE, + argc > 2 ? argv[2] : "", + &usable_protocols); + if (error) { + ovs_fatal(0, "%s", error); + } + + group_id = gm.group_id; + + open_vconn(argv[1], &vconn); + request = ofputil_encode_group_stats_request(vconn_get_version(vconn), + group_id); + if (request) { + dump_stats_transaction(vconn, request); + } + + vconn_close(vconn); +} + +static void +ofctl_dump_group_desc(int argc OVS_UNUSED, char *argv[]) +{ + struct ofpbuf *request; + struct vconn *vconn; + + open_vconn(argv[1], &vconn); + + request = ofputil_encode_group_desc_request(vconn_get_version(vconn)); + if (request) { + dump_stats_transaction(vconn, request); + } + + vconn_close(vconn); +} + +static void +ofctl_dump_group_features(int argc OVS_UNUSED, char *argv[]) +{ + struct ofpbuf *request; + struct vconn *vconn; + + open_vconn(argv[1], &vconn); + request = ofputil_encode_group_features_request(vconn_get_version(vconn)); + if (request) { + dump_stats_transaction(vconn, request); + } + + vconn_close(vconn); +} + static void ofctl_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) { @@ -2000,22 +2194,23 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index) struct fte_version *version; struct ofputil_flow_mod fm; char *error; + enum ofputil_protocol usable; - error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s)); + error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), &usable); if (error) { ovs_fatal(0, "%s:%d: %s", filename, line_number, error); } + usable_protocols &= usable; version = xmalloc(sizeof *version); version->cookie = fm.new_cookie; version->idle_timeout = fm.idle_timeout; version->hard_timeout = fm.hard_timeout; - version->flags = fm.flags & (OFPFF_SEND_FLOW_REM | OFPFF10_EMERG); + version->flags = fm.flags & (OFPUTIL_FF_SEND_FLOW_REM + | OFPUTIL_FF_EMERG); version->ofpacts = fm.ofpacts; version->ofpacts_len = fm.ofpacts_len; - usable_protocols &= ofputil_usable_protocols(&fm.match); - fte_insert(cls, &fm.match, fm.priority, version, index); } ds_destroy(&s); @@ -2279,14 +2474,13 @@ ofctl_diff_flows(int argc OVS_UNUSED, char *argv[]) /* Undocumented commands for unit testing. */ static void -ofctl_parse_flows__(struct ofputil_flow_mod *fms, size_t n_fms) +ofctl_parse_flows__(struct ofputil_flow_mod *fms, size_t n_fms, + enum ofputil_protocol usable_protocols) { - enum ofputil_protocol usable_protocols; enum ofputil_protocol protocol = 0; char *usable_s; size_t i; - usable_protocols = ofputil_flow_mod_usable_protocols(fms, n_fms); usable_s = ofputil_protocols_to_string(usable_protocols); printf("usable protocols: %s\n", usable_s); free(usable_s); @@ -2321,14 +2515,15 @@ ofctl_parse_flows__(struct ofputil_flow_mod *fms, size_t n_fms) static void ofctl_parse_flow(int argc OVS_UNUSED, char *argv[]) { + enum ofputil_protocol usable_protocols; struct ofputil_flow_mod fm; char *error; - error = parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD); + error = parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } - ofctl_parse_flows__(&fm, 1); + ofctl_parse_flows__(&fm, 1, usable_protocols); } /* "parse-flows FILENAME": reads the named file as a sequence of flows (like @@ -2336,15 +2531,17 @@ ofctl_parse_flow(int argc OVS_UNUSED, char *argv[]) static void ofctl_parse_flows(int argc OVS_UNUSED, char *argv[]) { + enum ofputil_protocol usable_protocols; struct ofputil_flow_mod *fms = NULL; size_t n_fms = 0; char *error; - error = parse_ofp_flow_mod_file(argv[1], OFPFC_ADD, &fms, &n_fms); + error = parse_ofp_flow_mod_file(argv[1], OFPFC_ADD, &fms, &n_fms, + &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } - ofctl_parse_flows__(fms, n_fms); + ofctl_parse_flows__(fms, n_fms, usable_protocols); free(fms); } @@ -2799,6 +2996,8 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[]) enum ofperr error; char *error_s; + enum ofputil_protocol usable_protocols; /* Unused for now. */ + match_init_catchall(&match); match.flow.vlan_tci = htons(strtoul(argv[1], NULL, 16)); match.wc.masks.vlan_tci = htons(strtoul(argv[2], NULL, 16)); @@ -2807,7 +3006,7 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[]) string_s = match_to_string(&match, OFP_DEFAULT_PRIORITY); printf("%s -> ", string_s); fflush(stdout); - error_s = parse_ofp_str(&fm, -1, string_s); + error_s = parse_ofp_str(&fm, -1, string_s, &usable_protocols); if (error_s) { ovs_fatal(0, "%s", error_s); } @@ -2990,12 +3189,21 @@ static const struct command all_commands[] = { { "dump-ports", 1, 2, ofctl_dump_ports }, { "dump-ports-desc", 1, 1, ofctl_dump_ports_desc }, { "mod-port", 3, 3, ofctl_mod_port }, + { "mod-table", 3, 3, ofctl_mod_table }, { "get-frags", 1, 1, ofctl_get_frags }, { "set-frags", 2, 2, ofctl_set_frags }, { "ofp-parse", 1, 1, ofctl_ofp_parse }, { "probe", 1, 1, ofctl_probe }, { "ping", 1, 2, ofctl_ping }, { "benchmark", 3, 3, ofctl_benchmark }, + + { "add-group", 1, 2, ofctl_add_group }, + { "add-groups", 1, 2, ofctl_add_groups }, + { "mod-group", 1, 2, ofctl_mod_group }, + { "del-groups", 1, 2, ofctl_del_groups }, + { "dump-groups", 1, 1, ofctl_dump_group_desc }, + { "dump-group-stats", 1, 2, ofctl_dump_group_stats }, + { "dump-group-features", 1, 1, ofctl_dump_group_features }, { "help", 0, INT_MAX, ofctl_help }, /* Undocumented commands for testing. */