X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=utilities%2Fovs-ofctl.c;h=899ce4e669a5e47adc5369bad001ffb9e0aa8500;hb=4b570f12766f3c4eeb527de69d8eedfd59c34b86;hp=6453167218528fd364af22ee7514c6a63a228a78;hpb=bdda5aca7b376bcc8c88072d00011a9da04af65c;p=sliver-openvswitch.git diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 645316721..899ce4e66 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; } @@ -305,7 +305,9 @@ usage(void) " 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(); @@ -1696,6 +1698,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[]) { @@ -1889,11 +1941,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 +1966,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]; @@ -2079,6 +2135,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 +2178,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 +2202,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 +2244,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 +2264,7 @@ ofctl_diff_flows(int argc OVS_UNUSED, char *argv[]) } } } + ovs_rwlock_unlock(&cls.rwlock); ds_destroy(&a_s); ds_destroy(&b_s); @@ -2334,7 +2395,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); @@ -2774,7 +2835,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) { @@ -2931,6 +2992,7 @@ static const struct command all_commands[] = { { "mod-port", 3, 3, ofctl_mod_port }, { "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 }, @@ -2955,3 +3017,8 @@ static const struct command all_commands[] = { { NULL, 0, 0, NULL }, }; + +static const struct command *get_all_commands(void) +{ + return all_commands; +}