X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=utilities%2Fovs-ofctl.c;h=c2cc1f6d4edda0d8d490aba7cd2602e0fcd806e8;hb=a34779bcbe9a4fd568bdcd414ee0416c208dbf22;hp=6453167218528fd364af22ee7514c6a63a228a78;hpb=bdda5aca7b376bcc8c88072d00011a9da04af65c;p=sliver-openvswitch.git diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 645316721..c2cc1f6d4 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -98,7 +98,7 @@ struct sort_criterion { static struct sort_criterion *criteria; static size_t n_criteria, allocated_criteria; -static const struct command all_commands[]; +static const struct command *get_all_commands(void); static void usage(void) NO_RETURN; static void parse_options(int argc, char *argv[]); @@ -113,7 +113,7 @@ main(int argc, char *argv[]) set_program_name(argv[0]); parse_options(argc, argv); signal(SIGPIPE, SIG_IGN); - run_command(argc - optind, argv + optind, all_commands); + run_command(argc - optind, argv + optind, get_all_commands()); return 0; } @@ -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,11 +302,28 @@ 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" + " add-meter SWITCH METER add meter described by METER\n" + " mod-meter SWITCH METER modify specific METER\n" + " del-meter SWITCH METER delete METER\n" + " del-meters SWITCH delete all meters\n" + " dump-meter SWITCH METER print METER configuration\n" + " dump-meters SWITCH print all meter configuration\n" + " meter-stats SWITCH [METER] print meter statistics\n" + " meter-features SWITCH print meter features\n" "\nFor OpenFlow switches and controllers:\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", + "SWITCH or TARGET is an active OpenFlow connection method.\n" + "\nOther commands:\n" + " ofp-parse FILE print messages read from FILE\n", program_name, program_name); vconn_usage(true, false, false); daemon_usage(); @@ -869,13 +887,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); @@ -1029,17 +1046,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); @@ -1071,13 +1084,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]; @@ -1091,15 +1104,17 @@ 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); } @@ -1111,12 +1126,14 @@ ofctl_flow_mod(int argc, char *argv[], uint16_t command) } else { struct ofputil_flow_mod fm; char *error; + enum ofputil_protocol usable_protocols; - 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); } } @@ -1386,7 +1403,8 @@ monitor_vconn(struct vconn *vconn, bool reply_to_echo_requests) run(retval, "vconn_recv"); if (timestamp) { - char *s = xastrftime("%Y-%m-%d %H:%M:%S: ", time_wall(), true); + char *s = xastrftime_msec("%Y-%m-%d %H:%M:%S.###: ", + time_wall_msec(), true); fputs(s, stderr); free(s); } @@ -1438,6 +1456,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++) { @@ -1456,7 +1475,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); } @@ -1559,9 +1579,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); } @@ -1651,6 +1672,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[]) { @@ -1696,6 +1753,56 @@ ofctl_set_frags(int argc OVS_UNUSED, char *argv[]) vconn_close(vconn); } +static void +ofctl_ofp_parse(int argc OVS_UNUSED, char *argv[]) +{ + const char *filename = argv[1]; + struct ofpbuf b; + FILE *file; + + file = !strcmp(filename, "-") ? stdin : fopen(filename, "r"); + if (file == NULL) { + ovs_fatal(errno, "%s: open", filename); + } + + ofpbuf_init(&b, 65536); + for (;;) { + struct ofp_header *oh; + size_t length, tail_len; + void *tail; + size_t n; + + ofpbuf_clear(&b); + oh = ofpbuf_put_uninit(&b, sizeof *oh); + n = fread(oh, 1, sizeof *oh, file); + if (n == 0) { + break; + } else if (n < sizeof *oh) { + ovs_fatal(0, "%s: unexpected end of file mid-message", filename); + } + + length = ntohs(oh->length); + if (length < sizeof *oh) { + ovs_fatal(0, "%s: %zu-byte message is too short for OpenFlow", + filename, length); + } + + tail_len = length - sizeof *oh; + tail = ofpbuf_put_uninit(&b, tail_len); + n = fread(tail, 1, tail_len, file); + if (n < tail_len) { + ovs_fatal(0, "%s: unexpected end of file mid-message", filename); + } + + ofp_print(stdout, b.data, b.size, verbosity + 2); + } + ofpbuf_uninit(&b); + + if (file != stdin) { + fclose(file); + } +} + static void ofctl_ping(int argc, char *argv[]) { @@ -1787,6 +1894,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) { @@ -1889,11 +2143,13 @@ fte_free_all(struct classifier *cls) struct cls_cursor cursor; struct fte *fte, *next; + ovs_rwlock_wrlock(&cls->rwlock); cls_cursor_init(&cursor, cls, NULL); CLS_CURSOR_FOR_EACH_SAFE (fte, next, rule, &cursor) { classifier_remove(cls, &fte->rule); fte_free(fte); } + ovs_rwlock_unlock(&cls->rwlock); classifier_destroy(cls); } @@ -1912,7 +2168,9 @@ fte_insert(struct classifier *cls, const struct match *match, cls_rule_init(&fte->rule, match, priority); fte->versions[index] = version; + ovs_rwlock_wrlock(&cls->rwlock); old = fte_from_cls_rule(classifier_replace(cls, &fte->rule)); + ovs_rwlock_unlock(&cls->rwlock); if (old) { fte_version_free(old->versions[index]); fte->versions[!index] = old->versions[!index]; @@ -1944,22 +2202,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); @@ -2079,6 +2338,7 @@ fte_make_flow_mod(const struct fte *fte, int index, uint16_t command, fm.cookie = htonll(0); fm.cookie_mask = htonll(0); fm.new_cookie = version->cookie; + fm.modify_cookie = true; fm.table_id = 0xff; fm.command = command; fm.idle_timeout = version->idle_timeout; @@ -2121,6 +2381,7 @@ ofctl_replace_flows(int argc OVS_UNUSED, char *argv[]) list_init(&requests); /* Delete flows that exist on the switch but not in the file. */ + ovs_rwlock_rdlock(&cls.rwlock); cls_cursor_init(&cursor, &cls, NULL); CLS_CURSOR_FOR_EACH (fte, rule, &cursor) { struct fte_version *file_ver = fte->versions[FILE_IDX]; @@ -2144,6 +2405,7 @@ ofctl_replace_flows(int argc OVS_UNUSED, char *argv[]) fte_make_flow_mod(fte, FILE_IDX, OFPFC_ADD, protocol, &requests); } } + ovs_rwlock_unlock(&cls.rwlock); transact_multiple_noreply(vconn, &requests); vconn_close(vconn); @@ -2185,6 +2447,7 @@ ofctl_diff_flows(int argc OVS_UNUSED, char *argv[]) ds_init(&a_s); ds_init(&b_s); + ovs_rwlock_rdlock(&cls.rwlock); cls_cursor_init(&cursor, &cls, NULL); CLS_CURSOR_FOR_EACH (fte, rule, &cursor) { struct fte_version *a = fte->versions[0]; @@ -2204,6 +2467,7 @@ ofctl_diff_flows(int argc OVS_UNUSED, char *argv[]) } } } + ovs_rwlock_unlock(&cls.rwlock); ds_destroy(&a_s); ds_destroy(&b_s); @@ -2214,18 +2478,113 @@ ofctl_diff_flows(int argc OVS_UNUSED, char *argv[]) exit(2); } } + +static void +ofctl_meter_mod__(const char *bridge, const char *str, int command) +{ + struct ofputil_meter_mod mm; + struct vconn *vconn; + enum ofputil_protocol protocol; + enum ofputil_protocol usable_protocols; + enum ofp_version version; + + if (str) { + char *error; + error = parse_ofp_meter_mod_str(&mm, str, command, &usable_protocols); + if (error) { + ovs_fatal(0, "%s", error); + } + } else { + usable_protocols = OFPUTIL_P_OF13_UP; + mm.command = command; + mm.meter.meter_id = OFPM13_ALL; + } + + protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols); + version = ofputil_protocol_to_ofp_version(protocol); + transact_noreply(vconn, ofputil_encode_meter_mod(version, &mm)); + vconn_close(vconn); +} + +static void +ofctl_meter_request__(const char *bridge, const char *str, + enum ofputil_meter_request_type type) +{ + struct ofputil_meter_mod mm; + struct vconn *vconn; + enum ofputil_protocol usable_protocols; + enum ofputil_protocol protocol; + enum ofp_version version; + + if (str) { + char *error; + error = parse_ofp_meter_mod_str(&mm, str, -1, &usable_protocols); + if (error) { + ovs_fatal(0, "%s", error); + } + } else { + usable_protocols = OFPUTIL_P_OF13_UP; + mm.meter.meter_id = OFPM13_ALL; + } + + protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols); + version = ofputil_protocol_to_ofp_version(protocol); + transact_noreply(vconn, ofputil_encode_meter_request(version, + type, + mm.meter.meter_id)); + vconn_close(vconn); +} + + +static void +ofctl_add_meter(int argc OVS_UNUSED, char *argv[]) +{ + ofctl_meter_mod__(argv[1], argv[2], OFPMC13_ADD); +} + +static void +ofctl_mod_meter(int argc OVS_UNUSED, char *argv[]) +{ + ofctl_meter_mod__(argv[1], argv[2], OFPMC13_MODIFY); +} + +static void +ofctl_del_meters(int argc, char *argv[]) +{ + ofctl_meter_mod__(argv[1], argc > 2 ? argv[2] : NULL, OFPMC13_DELETE); +} + +static void +ofctl_dump_meters(int argc, char *argv[]) +{ + ofctl_meter_request__(argv[1], argc > 2 ? argv[2] : NULL, + OFPUTIL_METER_CONFIG); +} + +static void +ofctl_meter_stats(int argc, char *argv[]) +{ + ofctl_meter_request__(argv[1], argc > 2 ? argv[2] : NULL, + OFPUTIL_METER_STATS); +} + +static void +ofctl_meter_features(int argc OVS_UNUSED, char *argv[]) +{ + ofctl_meter_request__(argv[1], NULL, OFPUTIL_METER_FEATURES); +} + /* 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); @@ -2260,14 +2619,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 @@ -2275,15 +2635,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); } @@ -2334,7 +2696,7 @@ ofctl_parse_nxm__(bool oxm) ofpbuf_init(&nx_match, 0); if (oxm) { match_len = oxm_put_match(&nx_match, &match); - out = oxm_match_to_string(nx_match.data, match_len); + out = oxm_match_to_string(&nx_match, match_len); } else { match_len = nx_put_match(&nx_match, &match, cookie, cookie_mask); @@ -2738,6 +3100,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)); @@ -2746,7 +3110,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); } @@ -2774,7 +3138,7 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[]) /* Convert to and from OXM. */ ofpbuf_init(&nxm, 0); nxm_match_len = oxm_put_match(&nxm, &match); - nxm_s = oxm_match_to_string(nxm.data, nxm_match_len); + nxm_s = oxm_match_to_string(&nxm, nxm_match_len); error = oxm_pull_match(&nxm, &nxm_match); printf("OXM: %s -> ", nxm_s); if (error) { @@ -2925,15 +3289,33 @@ static const struct command all_commands[] = { { "del-flows", 1, 2, ofctl_del_flows }, { "replace-flows", 2, 2, ofctl_replace_flows }, { "diff-flows", 2, 2, ofctl_diff_flows }, + { "add-meter", 2, 2, ofctl_add_meter }, + { "mod-meter", 2, 2, ofctl_mod_meter }, + { "del-meter", 2, 2, ofctl_del_meters }, + { "del-meters", 1, 1, ofctl_del_meters }, + { "dump-meter", 2, 2, ofctl_dump_meters }, + { "dump-meters", 1, 1, ofctl_dump_meters }, + { "meter-stats", 1, 2, ofctl_meter_stats }, + { "meter-features", 1, 1, ofctl_meter_features }, { "packet-out", 4, INT_MAX, ofctl_packet_out }, { "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. */ @@ -2955,3 +3337,8 @@ static const struct command all_commands[] = { { NULL, 0, 0, NULL }, }; + +static const struct command *get_all_commands(void) +{ + return all_commands; +}