int main(int argc, char *argv[]) { char *unixctl_path = NULL; char *run_command = NULL; struct unixctl_server *unixctl; struct ovsdb_jsonrpc_server *jsonrpc; struct shash remotes; struct ovsdb_error *error; struct ovsdb_file *file; struct ovsdb *db; struct process *run_process; char *file_name; bool exiting; int retval; proctitle_init(argc, argv); set_program_name(argv[0]); signal(SIGPIPE, SIG_IGN); process_init(); parse_options(argc, argv, &file_name, &remotes, &unixctl_path, &run_command); die_if_already_running(); daemonize_start(); error = ovsdb_file_open(file_name, false, &db, &file); if (error) { ovs_fatal(0, "%s", ovsdb_error_to_string(error)); } jsonrpc = ovsdb_jsonrpc_server_create(db); reconfigure_from_db(jsonrpc, db, &remotes); retval = unixctl_server_create(unixctl_path, &unixctl); if (retval) { exit(EXIT_FAILURE); } if (run_command) { char *run_argv[4]; run_argv[0] = "/bin/sh"; run_argv[1] = "-c"; run_argv[2] = run_command; run_argv[3] = NULL; retval = process_start(run_argv, NULL, 0, NULL, 0, &run_process); if (retval) { ovs_fatal(retval, "%s: process failed to start", run_command); } } else { run_process = NULL; } daemonize_complete(); unixctl_command_register("exit", ovsdb_server_exit, &exiting); unixctl_command_register("ovsdb-server/compact", ovsdb_server_compact, file); unixctl_command_register("ovsdb-server/reconnect", ovsdb_server_reconnect, jsonrpc); exiting = false; while (!exiting) { reconfigure_from_db(jsonrpc, db, &remotes); ovsdb_jsonrpc_server_run(jsonrpc); unixctl_server_run(unixctl); ovsdb_trigger_run(db, time_msec()); if (run_process && process_exited(run_process)) { exiting = true; } ovsdb_jsonrpc_server_wait(jsonrpc); unixctl_server_wait(unixctl); ovsdb_trigger_wait(db, time_msec()); if (run_process) { process_wait(run_process); } poll_block(); } ovsdb_jsonrpc_server_destroy(jsonrpc); ovsdb_destroy(db); shash_destroy(&remotes); unixctl_server_destroy(unixctl); if (run_process && process_exited(run_process)) { int status = process_status(run_process); if (status) { ovs_fatal(0, "%s: child exited, %s", run_command, process_status_msg(status)); } } return 0; }
int main(int argc, char *argv[]) { struct unixctl_server *server; enum { MAX_RECV = 1500 }; const char *target; struct ofpbuf buf; bool exiting = false; int error; int sock; int n; proctitle_init(argc, argv); set_program_name(argv[0]); parse_options(argc, argv); if (argc - optind != 1) { ovs_fatal(0, "exactly one non-option argument required " "(use --help for help)"); } target = argv[optind]; sock = inet_open_passive(SOCK_DGRAM, target, 0, NULL, 0); if (sock < 0) { ovs_fatal(0, "%s: failed to open (%s)", argv[1], strerror(-sock)); } daemon_save_fd(STDOUT_FILENO); daemonize_start(); error = unixctl_server_create(NULL, &server); if (error) { ovs_fatal(error, "failed to create unixctl server"); } unixctl_command_register("exit", "", 0, 0, test_netflow_exit, &exiting); daemonize_complete(); ofpbuf_init(&buf, MAX_RECV); n = 0; for (;;) { int retval; unixctl_server_run(server); ofpbuf_clear(&buf); do { retval = read(sock, buf.data, buf.allocated); } while (retval < 0 && errno == EINTR); if (retval > 0) { ofpbuf_put_uninit(&buf, retval); if (n++ > 0) { putchar('\n'); } print_netflow(&buf); fflush(stdout); } if (exiting) { break; } poll_fd_wait(sock, POLLIN); unixctl_server_wait(server); poll_block(); } return 0; }
/* Helper for bundle_parse and bundle_parse_load. */ static void bundle_parse__(struct ofpbuf *b, const char *s, char **save_ptr, const char *fields, const char *basis, const char *algorithm, const char *slave_type, const char *dst, const char *slave_delim) { enum ofputil_action_code code; struct nx_action_bundle *nab; uint16_t n_slaves; if (!slave_delim) { ovs_fatal(0, "%s: not enough arguments to bundle action", s); } if (strcasecmp(slave_delim, "slaves")) { ovs_fatal(0, "%s: missing slave delimiter, expected `slaves' got `%s'", s, slave_delim); } code = dst ? OFPUTIL_NXAST_BUNDLE_LOAD : OFPUTIL_NXAST_BUNDLE; b->l2 = ofputil_put_action(code, b); n_slaves = 0; for (;;) { ovs_be16 slave_be; char *slave; slave = strtok_r(NULL, ", ", save_ptr); if (!slave || n_slaves >= BUNDLE_MAX_SLAVES) { break; } slave_be = htons(atoi(slave)); ofpbuf_put(b, &slave_be, sizeof slave_be); n_slaves++; } /* Slaves array must be multiple of 8 bytes long. */ if (b->size % 8) { ofpbuf_put_zeros(b, 8 - (b->size % 8)); } nab = b->l2; nab->len = htons(b->size - ((char *) b->l2 - (char *) b->data)); nab->n_slaves = htons(n_slaves); nab->basis = htons(atoi(basis)); if (!strcasecmp(fields, "eth_src")) { nab->fields = htons(NX_HASH_FIELDS_ETH_SRC); } else if (!strcasecmp(fields, "symmetric_l4")) { nab->fields = htons(NX_HASH_FIELDS_SYMMETRIC_L4); } else { ovs_fatal(0, "%s: unknown fields `%s'", s, fields); } if (!strcasecmp(algorithm, "active_backup")) { nab->algorithm = htons(NX_BD_ALG_ACTIVE_BACKUP); } else if (!strcasecmp(algorithm, "hrw")) { nab->algorithm = htons(NX_BD_ALG_HRW); } else { ovs_fatal(0, "%s: unknown algorithm `%s'", s, algorithm); } if (!strcasecmp(slave_type, "ofport")) { nab->slave_type = htonl(NXM_OF_IN_PORT); } else { ovs_fatal(0, "%s: unknown slave_type `%s'", s, slave_type); } if (dst) { uint32_t reg; int ofs, n_bits; nxm_parse_field_bits(dst, ®, &ofs, &n_bits); nab->dst = htonl(reg); nab->ofs_nbits = nxm_encode_ofs_nbits(ofs, n_bits); } b->l2 = NULL; }
int main(int argc, char *argv[]) { const struct ovsdb_client_command *command; char *database; struct jsonrpc *rpc; ovs_cmdl_proctitle_init(argc, argv); set_program_name(argv[0]); parse_options(argc, argv); fatal_ignore_sigpipe(); daemon_become_new_user(false); if (optind >= argc) { ovs_fatal(0, "missing command name; use --help for help"); } for (command = get_all_commands(); ; command++) { if (!command->name) { VLOG_FATAL("unknown command '%s'; use --help for help", argv[optind]); } else if (!strcmp(command->name, argv[optind])) { break; } } optind++; if (command->need != NEED_NONE) { if (argc - optind > command->min_args && (isalpha((unsigned char) argv[optind][0]) && strchr(argv[optind], ':'))) { rpc = open_jsonrpc(argv[optind++]); } else { char *sock = xasprintf("unix:%s/db.sock", ovs_rundir()); rpc = open_jsonrpc(sock); free(sock); } } else { rpc = NULL; } if (command->need == NEED_DATABASE) { struct svec dbs; svec_init(&dbs); fetch_dbs(rpc, &dbs); if (argc - optind > command->min_args && svec_contains(&dbs, argv[optind])) { database = xstrdup(argv[optind++]); } else if (dbs.n == 1) { database = xstrdup(dbs.names[0]); } else if (svec_contains(&dbs, "Open_vSwitch")) { database = xstrdup("Open_vSwitch"); } else { jsonrpc_close(rpc); ovs_fatal(0, "no default database for `%s' command, please " "specify a database name", command->name); } svec_destroy(&dbs); } else { database = NULL; } if (argc - optind < command->min_args || argc - optind > command->max_args) { free(database); VLOG_FATAL("invalid syntax for '%s' (use --help for help)", command->name); } command->handler(rpc, database, argc - optind, argv + optind); free(database); jsonrpc_close(rpc); if (ferror(stdout)) { VLOG_FATAL("write to stdout failed"); } if (ferror(stderr)) { VLOG_FATAL("write to stderr failed"); } return 0; }
/* Parses 'arg' as a set of arguments to the "learn" action and appends a * matching NXAST_LEARN action to 'b'. The format parsed is described in * ovs-ofctl(8). * * Prints an error on stderr and aborts the program if 'arg' syntax is invalid. * * If 'flow' is nonnull, then it should be the flow from a cls_rule that is * the matching rule for the learning action. This helps to better validate * the action's arguments. * * Modifies 'arg'. */ void learn_parse(struct ofpbuf *b, char *arg, const struct flow *flow) { char *orig = xstrdup(arg); char *name, *value; enum ofperr error; size_t learn_ofs; size_t len; struct nx_action_learn *learn; struct cls_rule rule; learn_ofs = b->size; learn = ofputil_put_NXAST_LEARN(b); learn->idle_timeout = htons(OFP_FLOW_PERMANENT); learn->hard_timeout = htons(OFP_FLOW_PERMANENT); learn->priority = htons(OFP_DEFAULT_PRIORITY); learn->cookie = htonll(0); learn->flags = htons(0); learn->table_id = 1; cls_rule_init_catchall(&rule, 0); while (ofputil_parse_key_value(&arg, &name, &value)) { learn = ofpbuf_at_assert(b, learn_ofs, sizeof *learn); if (!strcmp(name, "table")) { learn->table_id = atoi(value); if (learn->table_id == 255) { ovs_fatal(0, "%s: table id 255 not valid for `learn' action", orig); } } else if (!strcmp(name, "priority")) { learn->priority = htons(atoi(value)); } else if (!strcmp(name, "idle_timeout")) { learn->idle_timeout = htons(atoi(value)); } else if (!strcmp(name, "hard_timeout")) { learn->hard_timeout = htons(atoi(value)); } else if (!strcmp(name, "fin_idle_timeout")) { learn->fin_idle_timeout = htons(atoi(value)); } else if (!strcmp(name, "fin_hard_timeout")) { learn->fin_hard_timeout = htons(atoi(value)); } else if (!strcmp(name, "cookie")) { learn->cookie = htonll(strtoull(value, NULL, 0)); } else { struct learn_spec spec; learn_parse_spec(orig, name, value, &spec); /* Check prerequisites. */ if (spec.src_type == NX_LEARN_SRC_FIELD && flow && !mf_are_prereqs_ok(spec.src.field, flow)) { ovs_fatal(0, "%s: cannot specify source field %s because " "prerequisites are not satisfied", orig, spec.src.field->name); } if ((spec.dst_type == NX_LEARN_DST_MATCH || spec.dst_type == NX_LEARN_DST_LOAD) && !mf_are_prereqs_ok(spec.dst.field, &rule.flow)) { ovs_fatal(0, "%s: cannot specify destination field %s because " "prerequisites are not satisfied", orig, spec.dst.field->name); } /* Update 'rule' to allow for satisfying destination * prerequisites. */ if (spec.src_type == NX_LEARN_SRC_IMMEDIATE && spec.dst_type == NX_LEARN_DST_MATCH) { mf_write_subfield(&spec.dst, &spec.src_imm, &rule); } /* Output the flow_mod_spec. */ put_u16(b, spec.n_bits | spec.src_type | spec.dst_type); if (spec.src_type == NX_LEARN_SRC_IMMEDIATE) { int n_bytes = DIV_ROUND_UP(spec.n_bits, 16) * 2; int ofs = sizeof spec.src_imm - n_bytes; ofpbuf_put(b, &spec.src_imm.u8[ofs], n_bytes); } else { put_u32(b, spec.src.field->nxm_header); put_u16(b, spec.src.ofs); } if (spec.dst_type == NX_LEARN_DST_MATCH || spec.dst_type == NX_LEARN_DST_LOAD) { put_u32(b, spec.dst.field->nxm_header); put_u16(b, spec.dst.ofs); } else { assert(spec.dst_type == NX_LEARN_DST_OUTPUT); } } } put_u16(b, 0); len = b->size - learn_ofs; if (len % 8) { ofpbuf_put_zeros(b, 8 - len % 8); } learn = ofpbuf_at_assert(b, learn_ofs, sizeof *learn); learn->len = htons(b->size - learn_ofs); /* In theory the above should have caught any errors, but... */ if (flow) { error = learn_check(learn, flow); if (error) { ovs_fatal(0, "%s: %s", orig, ofperr_to_string(error)); } } free(orig); }
static char * parse_options(int argc, char *argv[], char **unixctl_pathp) { enum { OPT_PEER_CA_CERT = UCHAR_MAX + 1, OPT_MLOCKALL, OPT_UNIXCTL, VLOG_OPTION_ENUMS, OPT_BOOTSTRAP_CA_CERT, OPT_ENABLE_DUMMY, OPT_DISABLE_SYSTEM, DAEMON_OPTION_ENUMS, OPT_DPDK, }; static const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {"mlockall", no_argument, NULL, OPT_MLOCKALL}, {"unixctl", required_argument, NULL, OPT_UNIXCTL}, DAEMON_LONG_OPTIONS, VLOG_LONG_OPTIONS, STREAM_SSL_LONG_OPTIONS, {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT}, {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT}, {"enable-dummy", optional_argument, NULL, OPT_ENABLE_DUMMY}, {"disable-system", no_argument, NULL, OPT_DISABLE_SYSTEM}, {"dpdk", optional_argument, NULL, OPT_DPDK}, {NULL, 0, NULL, 0}, }; char *short_options = ovs_cmdl_long_options_to_short_options(long_options); for (;;) { int c; c = getopt_long(argc, argv, short_options, long_options, NULL); if (c == -1) { break; } switch (c) { case 'h': usage(); case 'V': ovs_print_version(0, 0); exit(EXIT_SUCCESS); case OPT_MLOCKALL: want_mlockall = true; break; case OPT_UNIXCTL: *unixctl_pathp = optarg; break; VLOG_OPTION_HANDLERS DAEMON_OPTION_HANDLERS STREAM_SSL_OPTION_HANDLERS case OPT_PEER_CA_CERT: stream_ssl_set_peer_ca_cert_file(optarg); break; case OPT_BOOTSTRAP_CA_CERT: stream_ssl_set_ca_cert_file(optarg, true); break; case OPT_ENABLE_DUMMY: dummy_enable(optarg); break; case OPT_DISABLE_SYSTEM: dp_blacklist_provider("system"); break; case '?': exit(EXIT_FAILURE); case OPT_DPDK: ovs_fatal(0, "Using --dpdk to configure DPDK is not supported."); break; default: abort(); } } free(short_options); argc -= optind; argv += optind; switch (argc) { case 0: return xasprintf("unix:%s/db.sock", ovs_rundir()); case 1: return xstrdup(argv[0]); default: VLOG_FATAL("at most one non-option argument accepted; " "use --help for usage"); } }
static int parse_filter(char *filter_parse) { struct ds in; struct flow flow_filter; struct flow_wildcards wc_filter; char *error, *filter = NULL; vlog_set_levels_from_string_assert("odp_util:console:dbg"); if (filter_parse && !strncmp(filter_parse, "filter=", 7)) { filter = strdup(filter_parse+7); memset(&flow_filter, 0, sizeof(flow_filter)); memset(&wc_filter, 0, sizeof(wc_filter)); error = parse_ofp_exact_flow(&flow_filter, &wc_filter.masks, filter, NULL); if (error) { ovs_fatal(0, "Failed to parse filter (%s)", error); } } else { ovs_fatal(0, "No filter to parse."); } ds_init(&in); while (!ds_get_test_line(&in, stdin)) { struct ofpbuf odp_key; struct ofpbuf odp_mask; struct ds out; int error; /* Convert string to OVS DP key. */ ofpbuf_init(&odp_key, 0); ofpbuf_init(&odp_mask, 0); error = odp_flow_from_string(ds_cstr(&in), NULL, &odp_key, &odp_mask); if (error) { printf("odp_flow_from_string: error\n"); goto next; } if (filter) { struct flow flow; struct flow_wildcards wc; struct match match, match_filter; struct minimatch minimatch; odp_flow_key_to_flow(ofpbuf_data(&odp_key), ofpbuf_size(&odp_key), &flow); odp_flow_key_to_mask(ofpbuf_data(&odp_mask), ofpbuf_size(&odp_mask), &wc.masks, &flow); match_init(&match, &flow, &wc); match_init(&match_filter, &flow_filter, &wc); match_init(&match_filter, &match_filter.flow, &wc_filter); minimatch_init(&minimatch, &match_filter); if (!minimatch_matches_flow(&minimatch, &match.flow)) { minimatch_destroy(&minimatch); goto next; } minimatch_destroy(&minimatch); } /* Convert odp_key to string. */ ds_init(&out); odp_flow_format(ofpbuf_data(&odp_key), ofpbuf_size(&odp_key), ofpbuf_data(&odp_mask), ofpbuf_size(&odp_mask), NULL, &out, false); puts(ds_cstr(&out)); ds_destroy(&out); next: ofpbuf_uninit(&odp_key); ofpbuf_uninit(&odp_mask); } ds_destroy(&in); free(filter); return 0; }
/* Connects to a fake_pvconn with vconn_open(), accepts that connection and * sends the 'out' bytes in 'out_size' to it (presumably an OFPT_HELLO * message), then verifies that vconn_connect() reports * 'expect_connect_error'. */ static void test_send_hello(const char *type, const void *out, size_t out_size, int expect_connect_error) { struct fake_pvconn fpv; struct vconn *vconn; bool read_hello, connected; struct ofpbuf *msg; struct stream *stream; size_t n_sent; fpv_create(type, &fpv); CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); vconn_run(vconn); stream = fpv_accept(&fpv); fpv_destroy(&fpv); n_sent = 0; while (n_sent < out_size) { int retval; retval = stream_send(stream, (char *) out + n_sent, out_size - n_sent); if (retval > 0) { n_sent += retval; } else if (retval == -EAGAIN) { stream_run(stream); vconn_run(vconn); stream_recv_wait(stream); vconn_connect_wait(vconn); vconn_run_wait(vconn); poll_block(); } else { ovs_fatal(0, "stream_send returned unexpected value %d", retval); } } read_hello = connected = false; for (;;) { if (!read_hello) { struct ofp_header hello; int retval = stream_recv(stream, &hello, sizeof hello); if (retval == sizeof hello) { enum ofpraw raw; CHECK(hello.version, OFP13_VERSION); CHECK(ofpraw_decode_partial(&raw, &hello, sizeof hello), 0); CHECK(raw, OFPRAW_OFPT_HELLO); CHECK(ntohs(hello.length), sizeof hello); read_hello = true; } else { CHECK_ERRNO(retval, -EAGAIN); } } vconn_run(vconn); if (!connected) { int error = vconn_connect(vconn); if (error == expect_connect_error) { if (!error) { connected = true; } else { stream_close(stream); vconn_close(vconn); return; } } else { CHECK_ERRNO(error, EAGAIN); } } if (read_hello && connected) { break; } vconn_run_wait(vconn); if (!connected) { vconn_connect_wait(vconn); } if (!read_hello) { stream_recv_wait(stream); } poll_block(); } stream_close(stream); CHECK_ERRNO(vconn_recv_block(vconn, &msg), EOF); vconn_close(vconn); }
static void test_stp_main(int argc, char *argv[]) { struct test_case *tc; FILE *input_file; int i; vlog_set_pattern(VLF_CONSOLE, "%c|%p|%m"); vlog_set_levels(NULL, VLF_SYSLOG, VLL_OFF); if (argc != 2) { ovs_fatal(0, "usage: test-stp INPUT.STP\n"); } file_name = argv[1]; input_file = fopen(file_name, "r"); if (!input_file) { ovs_fatal(errno, "error opening \"%s\"", file_name); } tc = new_test_case(); for (i = 0; i < 26; i++) { char name[2]; name[0] = 'a' + i; name[1] = '\0'; new_lan(tc, name); } for (line_number = 1; fgets(line, sizeof line, input_file); line_number++) { char *newline, *hash; newline = strchr(line, '\n'); if (newline) { *newline = '\0'; } hash = strchr(line, '#'); if (hash) { *hash = '\0'; } pos = line; if (!get_token()) { continue; } if (match("bridge")) { struct bridge *bridge; int bridge_no, port_no; bridge_no = must_get_int(); if (bridge_no < tc->n_bridges) { bridge = tc->bridges[bridge_no]; } else if (bridge_no == tc->n_bridges) { bridge = new_bridge(tc, must_get_int()); } else { err("bridges must be numbered consecutively from 0"); } if (match("^")) { stp_set_bridge_priority(bridge->stp, must_get_int()); } if (match("=")) { for (port_no = 0; port_no < STP_MAX_PORTS; port_no++) { struct stp_port *p = stp_get_port(bridge->stp, port_no); if (!token || match("X")) { stp_port_disable(p); } else if (match("_")) { /* Nothing to do. */ } else { struct lan *lan; int path_cost; if (!strcmp(token, "0")) { lan = NULL; } else if (strlen(token) == 1 && islower((unsigned char)*token)) { lan = tc->lans[*token - 'a']; } else { err("%s is not a valid LAN name " "(0 or a lowercase letter)", token); } get_token(); path_cost = match(":") ? must_get_int() : 10; if (port_no < bridge->n_ports) { stp_port_set_path_cost(p, path_cost); stp_port_enable(p); reconnect_port(bridge, port_no, lan); } else if (port_no == bridge->n_ports) { new_port(bridge, lan, path_cost); } else { err("ports must be numbered consecutively"); } if (match("^")) { stp_port_set_priority(p, must_get_int()); } } } } } else if (match("run")) { simulate(tc, must_get_int()); } else if (match("dump")) { dump(tc); } else if (match("tree")) { tree(tc); } else if (match("check")) { struct bridge *b; struct stp *stp; int bridge_no, port_no; bridge_no = must_get_int(); if (bridge_no >= tc->n_bridges) { err("no bridge numbered %d", bridge_no); } b = tc->bridges[bridge_no]; stp = b->stp; must_match("="); if (match("rootid")) { uint64_t rootid; must_match(":"); rootid = must_get_int(); if (match("^")) { rootid |= (uint64_t) must_get_int() << 48; } else { rootid |= UINT64_C(0x8000) << 48; } if (stp_get_designated_root(stp) != rootid) { warn("%s: root %"PRIx64", not %"PRIx64, stp_get_name(stp), stp_get_designated_root(stp), rootid); } } if (match("root")) { if (stp_get_root_path_cost(stp)) { warn("%s: root path cost of root is %u but should be 0", stp_get_name(stp), stp_get_root_path_cost(stp)); } if (!stp_is_root_bridge(stp)) { warn("%s: root is %"PRIx64", not %"PRIx64, stp_get_name(stp), stp_get_designated_root(stp), stp_get_bridge_id(stp)); } for (port_no = 0; port_no < b->n_ports; port_no++) { struct stp_port *p = stp_get_port(stp, port_no); enum stp_state state = stp_port_get_state(p); if (!(state & (STP_DISABLED | STP_FORWARDING))) { warn("%s: root port %d in state %s", stp_get_name(b->stp), port_no, stp_state_name(state)); } } } else { for (port_no = 0; port_no < STP_MAX_PORTS; port_no++) { struct stp_port *p = stp_get_port(stp, port_no); enum stp_state state; if (token == NULL || match("D")) { state = STP_DISABLED; } else if (match("B")) { state = STP_BLOCKING; } else if (match("Li")) { state = STP_LISTENING; } else if (match("Le")) { state = STP_LEARNING; } else if (match("F")) { state = STP_FORWARDING; } else if (match("_")) { continue; } else { err("unknown port state %s", token); } if (stp_port_get_state(p) != state) { warn("%s port %d: state is %s but should be %s", stp_get_name(stp), port_no, stp_state_name(stp_port_get_state(p)), stp_state_name(state)); } if (state == STP_FORWARDING) { struct stp_port *root_port = stp_get_root_port(stp); if (match(":")) { int root_path_cost = must_get_int(); if (p != root_port) { warn("%s: port %d is not the root port", stp_get_name(stp), port_no); if (!root_port) { warn("%s: (there is no root port)", stp_get_name(stp)); } else { warn("%s: (port %d is the root port)", stp_get_name(stp), stp_port_no(root_port)); } } else if (root_path_cost != stp_get_root_path_cost(stp)) { warn("%s: root path cost is %u, should be %d", stp_get_name(stp), stp_get_root_path_cost(stp), root_path_cost); } } else if (p == root_port) { warn("%s: port %d is the root port but " "not expected to be", stp_get_name(stp), port_no); } } } } if (n_warnings) { exit(EXIT_FAILURE); } } if (get_token()) { err("trailing garbage on line"); } } free(token); for (i = 0; i < tc->n_lans; i++) { struct lan *lan = tc->lans[i]; free(CONST_CAST(char *, lan->name)); free(lan); } for (i = 0; i < tc->n_bridges; i++) { struct bridge *bridge = tc->bridges[i]; stp_unref(bridge->stp); free(bridge); } free(tc); fclose(input_file); }
static void parse_options(int argc, char *argv[]) { static const struct option long_options[] = { {"local", required_argument, NULL, 'l'}, {"remote", required_argument, NULL, 'r'}, {"batches", required_argument, NULL, 'b'}, {"sockets", required_argument, NULL, 's'}, {"max-rate", required_argument, NULL, 'c'}, {"timeout", required_argument, NULL, 'T'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0}, }; char *short_options = ovs_cmdl_long_options_to_short_options(long_options); local_addr.s_addr = htonl(INADDR_ANY); local_min_port = local_max_port = 0; remote_addr.s_addr = htonl(0); remote_min_port = remote_max_port = 0; for (;;) { int c; c = getopt_long(argc, argv, short_options, long_options, NULL); if (c == -1) { break; } switch (c) { case 'l': parse_target(optarg, &local_addr, &local_min_port, &local_max_port); break; case 'r': parse_target(optarg, &remote_addr, &remote_min_port, &remote_max_port); if (remote_addr.s_addr == htonl(INADDR_ANY)) { ovs_fatal(0, "remote IP address is required"); } break; case 'b': n_batches = atoi(optarg); if (n_batches < 0) { ovs_fatal(0, "--batches or -b argument must be at least 1"); } break; case 's': n_sockets = atoi(optarg); if (n_sockets < 1 || n_sockets > MAX_SOCKETS) { ovs_fatal(0, "--sockets or -s argument must be between 1 " "and %d (inclusive)", MAX_SOCKETS); } break; case 'c': max_rate = atof(optarg); if (max_rate <= 0.0) { ovs_fatal(0, "--max-rate or -c argument must be positive"); } break; case 'T': timeout = atoi(optarg); if (!timeout) { ovs_fatal(0, "-T or --timeout argument must be positive"); } break; case 'h': usage(); case 'V': ovs_print_version(0, 0); exit(EXIT_SUCCESS); case '?': exit(EXIT_FAILURE); default: abort(); } } free(short_options); }
int main(int argc, char *argv[]) { enum { MP_MAX_LINKS = 63 }; struct ofpact_multipath mp; bool ok = true; char *error; int n; set_program_name(argv[0]); if (argc != 2) { ovs_fatal(0, "usage: %s multipath_action", program_name); } error = multipath_parse(&mp, argv[1]); if (error) { ovs_fatal(0, "%s", error); } for (n = 1; n <= MP_MAX_LINKS; n++) { enum { N_FLOWS = 65536 }; double disruption, perfect, distribution; int histogram[MP_MAX_LINKS]; double sum_dev2, stddev; int changed; int i; changed = 0; memset(histogram, 0, sizeof histogram); for (i = 0; i < N_FLOWS; i++) { int old_link, new_link; struct flow_wildcards wc; struct flow flow; flow_random_hash_fields(&flow); mp.max_link = n - 1; multipath_execute(&mp, &flow, &wc); old_link = flow.regs[0]; mp.max_link = n; multipath_execute(&mp, &flow, &wc); new_link = flow.regs[0]; assert(old_link >= 0 && old_link < n); assert(new_link >= 0 && new_link < n + 1); histogram[old_link]++; changed += old_link != new_link; } sum_dev2 = 0.0; for (i = 0; i < n; i++) { double mean = (double) N_FLOWS / n; double deviation = histogram[i] - mean; sum_dev2 += deviation * deviation; } stddev = sqrt(sum_dev2 / n); disruption = (double) changed / N_FLOWS; perfect = 1.0 / (n + 1); distribution = stddev / ((double) N_FLOWS / n); printf("%2d -> %2d: disruption=%.2f (perfect=%.2f); " "stddev/expected=%.4f\n", n, n + 1, disruption, perfect, distribution); switch (mp.algorithm) { case NX_MP_ALG_MODULO_N: if (disruption < (n < 2 ? .25 : .5)) { fprintf(stderr, "%d -> %d: disruption=%.2f < .5\n", n, n + 1, disruption); ok = false; } break; case NX_MP_ALG_HASH_THRESHOLD: if (disruption < .48 || disruption > .52) { fprintf(stderr, "%d -> %d: disruption=%.2f not approximately " ".5\n", n, n + 1, disruption); ok = false; } break; case NX_MP_ALG_ITER_HASH: if (!(n & (n - 1))) { break; } /* Fall through. */ case NX_MP_ALG_HRW: if (fabs(disruption - perfect) >= .01) { fprintf(stderr, "%d -> %d: disruption=%.5f differs from " "perfect=%.5f by more than .01\n", n, n + 1, disruption, perfect); ok = false; } break; default: OVS_NOT_REACHED(); } } return ok ? 0 : 1; }
int main(int argc OVS_UNUSED, char *argv[]) { struct ofp10_match expected_match; FILE *flows, *pcap; int retval; int n = 0, errors = 0; set_program_name(argv[0]); flows = stdin; pcap = fdopen(3, "rb"); if (!pcap) { ovs_fatal(errno, "failed to open fd 3 for reading"); } retval = pcap_read_header(pcap); if (retval) { ovs_fatal(retval > 0 ? retval : 0, "reading pcap header failed"); } while (fread(&expected_match, sizeof expected_match, 1, flows)) { struct ofpbuf *packet; struct ofp10_match extracted_match; struct match match; struct flow flow; n++; retval = pcap_read(pcap, &packet); if (retval == EOF) { ovs_fatal(0, "unexpected end of file reading pcap file"); } else if (retval) { ovs_fatal(retval, "error reading pcap file"); } flow_extract(packet, 0, NULL, 1, &flow); match_init_exact(&match, &flow); ofputil_match_to_ofp10_match(&match, &extracted_match); if (memcmp(&expected_match, &extracted_match, sizeof expected_match)) { char *exp_s = ofp10_match_to_string(&expected_match, 2); char *got_s = ofp10_match_to_string(&extracted_match, 2); errors++; printf("mismatch on packet #%d (1-based).\n", n); printf("Packet:\n"); ofp_print_packet(stdout, packet->data, packet->size); ovs_hex_dump(stdout, packet->data, packet->size, 0, true); match_print(&match); printf("Expected flow:\n%s\n", exp_s); printf("Actually extracted flow:\n%s\n", got_s); ovs_hex_dump(stdout, &expected_match, sizeof expected_match, 0, false); ovs_hex_dump(stdout, &extracted_match, sizeof extracted_match, 0, false); printf("\n"); free(exp_s); free(got_s); } ofpbuf_delete(packet); } printf("checked %d packets, %d errors\n", n, errors); return errors != 0; }
int main(int argc OVS_UNUSED, char *argv[]) { uint64_t buf_stub[4096 / 64]; struct nl_sock *sock; struct ofpbuf buf; int error; set_program_name(argv[0]); vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG); error = nl_sock_create(NETLINK_ROUTE, &sock); if (error) { ovs_fatal(error, "could not create rtnetlink socket"); } error = nl_sock_join_mcgroup(sock, RTNLGRP_LINK); if (error) { ovs_fatal(error, "could not join RTNLGRP_LINK multicast group"); } ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); for (;;) { error = nl_sock_recv(sock, &buf, false); if (error == EAGAIN) { /* Nothing to do. */ } else if (error == ENOBUFS) { ovs_error(0, "network monitor socket overflowed"); } else if (error) { ovs_fatal(error, "error on network monitor socket"); } else { struct iff_flag { unsigned int flag; const char *name; }; static const struct iff_flag flags[] = { { IFF_UP, "UP", }, { IFF_BROADCAST, "BROADCAST", }, #ifndef _WIN32 { IFF_DEBUG, "DEBUG", }, #endif { IFF_LOOPBACK, "LOOPBACK", }, #ifndef _WIN32 { IFF_POINTOPOINT, "POINTOPOINT", }, { IFF_NOTRAILERS, "NOTRAILERS", }, #endif { IFF_RUNNING, "RUNNING", }, #ifndef _WIN32 { IFF_NOARP, "NOARP", }, #endif { IFF_PROMISC, "PROMISC", }, #ifndef _WIN32 { IFF_ALLMULTI, "ALLMULTI", }, { IFF_MASTER, "MASTER", }, { IFF_SLAVE, "SLAVE", }, #endif { IFF_MULTICAST, "MULTICAST", }, #ifndef _WIN32 { IFF_PORTSEL, "PORTSEL", }, { IFF_AUTOMEDIA, "AUTOMEDIA", }, { IFF_DYNAMIC, "DYNAMIC", }, #endif }; struct nlattr *attrs[ARRAY_SIZE(rtnlgrp_link_policy)]; struct nlmsghdr *nlh; struct ifinfomsg *iim; int i; nlh = ofpbuf_at(&buf, 0, NLMSG_HDRLEN); iim = ofpbuf_at(&buf, NLMSG_HDRLEN, sizeof *iim); if (!iim) { ovs_error(0, "received bad rtnl message (no ifinfomsg)"); continue; } if (!nl_policy_parse(&buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg), rtnlgrp_link_policy, attrs, ARRAY_SIZE(rtnlgrp_link_policy))) { ovs_error(0, "received bad rtnl message (policy)"); continue; } printf("netdev %s changed (%s):\n", nl_attr_get_string(attrs[IFLA_IFNAME]), (nlh->nlmsg_type == RTM_NEWLINK ? "RTM_NEWLINK" #ifndef _WIN32 : nlh->nlmsg_type == RTM_DELLINK ? "RTM_DELLINK" #endif : nlh->nlmsg_type == RTM_GETLINK ? "RTM_GETLINK" #ifndef _WIN32 : nlh->nlmsg_type == RTM_SETLINK ? "RTM_SETLINK" #endif : "other")); printf("\tflags:"); for (i = 0; i < ARRAY_SIZE(flags); i++) { if (iim->ifi_flags & flags[i].flag) { printf(" %s", flags[i].name); } } printf("\n"); if (attrs[IFLA_MASTER]) { uint32_t idx = nl_attr_get_u32(attrs[IFLA_MASTER]); char ifname[IFNAMSIZ]; #ifndef _WIN32 if (!if_indextoname(idx, ifname)) { strcpy(ifname, "unknown"); } #endif printf("\tmaster=%"PRIu32" (%s)\n", idx, ifname); } } nl_sock_wait(sock, POLLIN); poll_block(); } }
static void parse_named_action(enum ofputil_action_code code, const struct flow *flow, char *arg, struct ofpbuf *ofpacts) { struct ofpact_tunnel *tunnel; uint16_t vid; uint16_t ethertype; ovs_be32 ip; uint8_t pcp; uint8_t tos; switch (code) { case OFPUTIL_ACTION_INVALID: NOT_REACHED(); case OFPUTIL_OFPAT10_OUTPUT: case OFPUTIL_OFPAT11_OUTPUT: parse_output(arg, ofpacts); break; case OFPUTIL_OFPAT10_SET_VLAN_VID: case OFPUTIL_OFPAT11_SET_VLAN_VID: vid = str_to_u32(arg); if (vid & ~VLAN_VID_MASK) { ovs_fatal(0, "%s: not a valid VLAN VID", arg); } ofpact_put_SET_VLAN_VID(ofpacts)->vlan_vid = vid; break; case OFPUTIL_OFPAT10_SET_VLAN_PCP: case OFPUTIL_OFPAT11_SET_VLAN_PCP: pcp = str_to_u32(arg); if (pcp & ~7) { ovs_fatal(0, "%s: not a valid VLAN PCP", arg); } ofpact_put_SET_VLAN_PCP(ofpacts)->vlan_pcp = pcp; break; case OFPUTIL_OFPAT12_SET_FIELD: set_field_parse(arg, ofpacts); break; case OFPUTIL_OFPAT10_STRIP_VLAN: case OFPUTIL_OFPAT11_POP_VLAN: ofpact_put_STRIP_VLAN(ofpacts); break; case OFPUTIL_OFPAT11_PUSH_VLAN: ethertype = str_to_u16(arg, "ethertype"); if (ethertype != ETH_TYPE_VLAN_8021Q) { /* XXX ETH_TYPE_VLAN_8021AD case isn't supported */ ovs_fatal(0, "%s: not a valid VLAN ethertype", arg); } ofpact_put_PUSH_VLAN(ofpacts); break; case OFPUTIL_OFPAT11_SET_QUEUE: ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg); break; case OFPUTIL_OFPAT10_SET_DL_SRC: case OFPUTIL_OFPAT11_SET_DL_SRC: str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac); break; case OFPUTIL_OFPAT10_SET_DL_DST: case OFPUTIL_OFPAT11_SET_DL_DST: str_to_mac(arg, ofpact_put_SET_ETH_DST(ofpacts)->mac); break; case OFPUTIL_OFPAT10_SET_NW_SRC: case OFPUTIL_OFPAT11_SET_NW_SRC: str_to_ip(arg, &ip); ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4 = ip; break; case OFPUTIL_OFPAT10_SET_NW_DST: case OFPUTIL_OFPAT11_SET_NW_DST: str_to_ip(arg, &ip); ofpact_put_SET_IPV4_DST(ofpacts)->ipv4 = ip; break; case OFPUTIL_OFPAT10_SET_NW_TOS: case OFPUTIL_OFPAT11_SET_NW_TOS: tos = str_to_u32(arg); if (tos & ~IP_DSCP_MASK) { ovs_fatal(0, "%s: not a valid TOS", arg); } ofpact_put_SET_IPV4_DSCP(ofpacts)->dscp = tos; break; case OFPUTIL_OFPAT11_DEC_NW_TTL: NOT_REACHED(); case OFPUTIL_OFPAT10_SET_TP_SRC: case OFPUTIL_OFPAT11_SET_TP_SRC: ofpact_put_SET_L4_SRC_PORT(ofpacts)->port = str_to_u32(arg); break; case OFPUTIL_OFPAT10_SET_TP_DST: case OFPUTIL_OFPAT11_SET_TP_DST: ofpact_put_SET_L4_DST_PORT(ofpacts)->port = str_to_u32(arg); break; case OFPUTIL_OFPAT10_ENQUEUE: parse_enqueue(arg, ofpacts); break; case OFPUTIL_NXAST_RESUBMIT: parse_resubmit(arg, ofpacts); break; case OFPUTIL_NXAST_SET_TUNNEL: case OFPUTIL_NXAST_SET_TUNNEL64: tunnel = ofpact_put_SET_TUNNEL(ofpacts); tunnel->ofpact.compat = code; tunnel->tun_id = str_to_u64(arg); break; case OFPUTIL_NXAST_WRITE_METADATA: parse_metadata(ofpacts, arg); break; case OFPUTIL_NXAST_SET_QUEUE: ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg); break; case OFPUTIL_NXAST_POP_QUEUE: ofpact_put_POP_QUEUE(ofpacts); break; case OFPUTIL_NXAST_REG_MOVE: nxm_parse_reg_move(ofpact_put_REG_MOVE(ofpacts), arg); break; case OFPUTIL_NXAST_REG_LOAD: nxm_parse_reg_load(ofpact_put_REG_LOAD(ofpacts), arg); break; case OFPUTIL_NXAST_NOTE: parse_note(arg, ofpacts); break; case OFPUTIL_NXAST_MULTIPATH: multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg); break; case OFPUTIL_NXAST_AUTOPATH__DEPRECATED: autopath_parse(ofpact_put_AUTOPATH(ofpacts), arg); break; case OFPUTIL_NXAST_BUNDLE: bundle_parse(arg, ofpacts); break; case OFPUTIL_NXAST_BUNDLE_LOAD: bundle_parse_load(arg, ofpacts); break; case OFPUTIL_NXAST_RESUBMIT_TABLE: case OFPUTIL_NXAST_OUTPUT_REG: case OFPUTIL_NXAST_DEC_TTL_CNT_IDS: NOT_REACHED(); case OFPUTIL_NXAST_LEARN: learn_parse(arg, flow, ofpacts); break; case OFPUTIL_NXAST_EXIT: ofpact_put_EXIT(ofpacts); break; case OFPUTIL_NXAST_DEC_TTL: parse_dec_ttl(ofpacts, arg); break; case OFPUTIL_NXAST_FIN_TIMEOUT: parse_fin_timeout(ofpacts, arg); break; case OFPUTIL_NXAST_CONTROLLER: parse_controller(ofpacts, arg); break; } }
/* Helper for bundle_parse and bundle_parse_load. */ static void bundle_parse__(const char *s, char **save_ptr, const char *fields, const char *basis, const char *algorithm, const char *slave_type, const char *dst, const char *slave_delim, struct ofpbuf *ofpacts) { struct ofpact_bundle *bundle; if (!slave_delim) { ovs_fatal(0, "%s: not enough arguments to bundle action", s); } if (strcasecmp(slave_delim, "slaves")) { ovs_fatal(0, "%s: missing slave delimiter, expected `slaves' got `%s'", s, slave_delim); } bundle = ofpact_put_BUNDLE(ofpacts); for (;;) { uint16_t slave_port; char *slave; slave = strtok_r(NULL, ", []", save_ptr); if (!slave || bundle->n_slaves >= BUNDLE_MAX_SLAVES) { break; } if (!ofputil_port_from_string(slave, &slave_port)) { ovs_fatal(0, "%s: bad port number", slave); } ofpbuf_put(ofpacts, &slave_port, sizeof slave_port); bundle = ofpacts->l2; bundle->n_slaves++; } ofpact_update_len(ofpacts, &bundle->ofpact); bundle->basis = atoi(basis); if (!strcasecmp(fields, "eth_src")) { bundle->fields = NX_HASH_FIELDS_ETH_SRC; } else if (!strcasecmp(fields, "symmetric_l4")) { bundle->fields = NX_HASH_FIELDS_SYMMETRIC_L4; } else { ovs_fatal(0, "%s: unknown fields `%s'", s, fields); } if (!strcasecmp(algorithm, "active_backup")) { bundle->algorithm = NX_BD_ALG_ACTIVE_BACKUP; } else if (!strcasecmp(algorithm, "hrw")) { bundle->algorithm = NX_BD_ALG_HRW; } else { ovs_fatal(0, "%s: unknown algorithm `%s'", s, algorithm); } if (strcasecmp(slave_type, "ofport")) { ovs_fatal(0, "%s: unknown slave_type `%s'", s, slave_type); } if (dst) { mf_parse_subfield(&bundle->dst, dst); } }
static void test_rstp_main(int argc, char *argv[]) { struct test_case *tc; FILE *input_file; int i; vlog_set_pattern(VLF_CONSOLE, "%c|%p|%m"); vlog_set_levels(NULL, VLF_SYSLOG, VLL_OFF); if (argc != 2) { ovs_fatal(0, "usage: test-rstp INPUT.RSTP\n"); } file_name = argv[1]; input_file = fopen(file_name, "r"); if (!input_file) { ovs_fatal(errno, "error opening \"%s\"", file_name); } tc = new_test_case(); for (i = 0; i < 26; i++) { char name[2]; name[0] = 'a' + i; name[1] = '\0'; new_lan(tc, name); } for (line_number = 1; fgets(line, sizeof line, input_file); line_number++) { char *newline, *hash; newline = strchr(line, '\n'); if (newline) { *newline = '\0'; } hash = strchr(line, '#'); if (hash) { *hash = '\0'; } pos = line; if (!get_token()) { continue; } if (match("bridge")) { struct bridge *bridge; int bridge_no, port_no; bridge_no = must_get_int(); if (bridge_no < tc->n_bridges) { bridge = tc->bridges[bridge_no]; } else if (bridge_no == tc->n_bridges) { bridge = new_bridge(tc, must_get_int()); } else { err("bridges must be numbered consecutively from 0"); } if (match("^")) { rstp_set_bridge_priority(bridge->rstp, must_get_int()); } if (match("=")) { for (port_no = 1; port_no < MAX_PORTS; port_no++) { struct rstp_port *p = rstp_get_port(bridge->rstp, port_no); if (!token || match("X")) { /* Disable port. */ reinitialize_port(p); rstp_port_set_state(p, RSTP_DISABLED); rstp_port_set_mac_operational(p, false); } else if (match("_")) { /* Nothing to do. */ } else { struct lan *lan; uint32_t path_cost; if (!strcmp(token, "0")) { lan = NULL; } else if (strlen(token) == 1 && islower((unsigned char)*token)) { lan = tc->lans[*token - 'a']; } else { err("%s is not a valid LAN name " "(0 or a lowercase letter)", token); } get_token(); path_cost = match(":") ? must_get_int() : RSTP_DEFAULT_PORT_PATH_COST; if (port_no < bridge->n_ports) { /* Enable port. */ reinitialize_port(p); rstp_port_set_path_cost(p, path_cost); rstp_port_set_state(p, RSTP_DISCARDING); rstp_port_set_mac_operational(p, true); reconnect_port(bridge, port_no, lan); } else if (port_no == bridge->n_ports) { new_port(bridge, lan, path_cost); bridge->n_active_ports++; } else { err("ports must be numbered consecutively"); } if (match("^")) { rstp_port_set_priority(p, must_get_int()); } } } } } else if (match("run")) { simulate(tc, must_get_int()); } else if (match("dump")) { dump(tc); } else if (match("tree")) { tree(tc); } else if (match("check")) { struct bridge *b; struct rstp *rstp; int bridge_no, port_no; uint32_t cost_value; bridge_no = must_get_int(); if (bridge_no >= tc->n_bridges) { err("no bridge numbered %d", bridge_no); } b = tc->bridges[bridge_no]; rstp = b->rstp; must_match("="); if (match("rootid")) { uint64_t rootid; must_match(":"); rootid = must_get_int(); if (match("^")) { rootid |= (uint64_t) must_get_int() << 48; } else { rootid |= UINT64_C(0x8000) << 48; } if (rstp_get_designated_root(rstp) != rootid) { warn("%s: root "RSTP_ID_FMT", not %"PRIx64, rstp_get_name(rstp), RSTP_ID_ARGS(rstp_get_designated_root(rstp)), rootid); } } cost_value = rstp_get_root_path_cost(rstp); if (match("root")) { if (cost_value != 0) { warn("%s: root path cost of root is %d instead of 0 \n", rstp_get_name(rstp), cost_value); } if (!rstp_is_root_bridge(rstp)) { warn("%s: root is "RSTP_ID_FMT", not "RSTP_ID_FMT"", rstp_get_name(rstp), RSTP_ID_ARGS(rstp_get_designated_root(rstp)), RSTP_ID_ARGS(rstp_get_bridge_id(rstp))); } for (port_no = 1; port_no < b->n_active_ports; port_no++) { struct rstp_port *p = rstp_get_port(rstp, port_no); enum rstp_state state = rstp_port_get_state(p); if (state != RSTP_DISABLED && state != RSTP_FORWARDING) { warn("%s: root port %d in state %s", rstp_get_name(b->rstp), port_no, rstp_state_name(state)); } } } else { for (port_no = 1; port_no < b->n_active_ports; port_no++) { struct rstp_port *p = rstp_get_port(rstp, port_no); enum rstp_state state; if (token == NULL || match("D")) { state = RSTP_DISABLED; } else if (match("Di")) { state = RSTP_DISCARDING; } else if (match("Le")) { state = RSTP_LEARNING; } else if (match("F")) { state = RSTP_FORWARDING; } else if (match("_")) { continue; } else { err("unknown port state %s", token); } if (rstp_port_get_state(p) != state) { warn("%s port %d: state is %s but should be %s", rstp_get_name(rstp), port_no, rstp_state_name(rstp_port_get_state(p)), rstp_state_name(state)); } if (state == RSTP_FORWARDING) { struct rstp_port *root_port = rstp_get_root_port(rstp); if (match(":")) { int root_path_cost = must_get_int(); if (p != root_port) { warn("%s: port %d is not the root port", rstp_get_name(rstp), port_no); if (!root_port) { warn("%s: (there is no root port)", rstp_get_name(rstp)); } else { warn("%s: (port %d is the root port)", rstp_get_name(rstp), rstp_port_get_number(root_port)); } } else if (cost_value != root_path_cost) { warn("%s: root path cost is %d, should be %d", rstp_get_name(rstp), cost_value, root_path_cost); } } else if (p == root_port) { warn("%s: port %d is the root port but " "not expected to be", rstp_get_name(rstp), port_no); } } } } if (n_warnings) { printf("failing because of %d warnings\n", n_warnings); exit(EXIT_FAILURE); } } if (get_token()) { printf("failing because of errors\n"); err("trailing garbage on line"); } } free(token); for (i = 0; i < tc->n_lans; i++) { struct lan *lan = tc->lans[i]; free(CONST_CAST(char *, lan->name)); free(lan); } for (i = 0; i < tc->n_bridges; i++) { struct bridge *bridge = tc->bridges[i]; int j; for (j = 1; j < MAX_PORTS; j++) { rstp_port_unref(rstp_get_port(bridge->rstp, j)); } rstp_unref(bridge->rstp); free(bridge); } free(tc); }
/* Convert 'string' (as described in the Flow Syntax section of the ovs-ofctl * man page) into 'pf'. If 'actions' is specified, an action must be in * 'string' and may be expanded or reallocated. */ void parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx, struct ofpbuf *actions, char *string) { char *save_ptr = NULL; char *name; if (table_idx) { *table_idx = 0xff; } cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY); fm->cookie = htonll(0); fm->command = UINT16_MAX; fm->idle_timeout = OFP_FLOW_PERMANENT; fm->hard_timeout = OFP_FLOW_PERMANENT; fm->buffer_id = UINT32_MAX; fm->out_port = OFPP_NONE; fm->flags = 0; if (actions) { char *act_str = strstr(string, "action"); if (!act_str) { ovs_fatal(0, "must specify an action"); } *act_str = '\0'; act_str = strchr(act_str + 1, '='); if (!act_str) { ovs_fatal(0, "must specify an action"); } act_str++; str_to_action(act_str, actions); fm->actions = actions->data; fm->n_actions = actions->size / sizeof(union ofp_action); } else { fm->actions = NULL; fm->n_actions = 0; } for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name; name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) { const struct protocol *p; if (parse_protocol(name, &p)) { cls_rule_set_dl_type(&fm->cr, htons(p->dl_type)); if (p->nw_proto) { cls_rule_set_nw_proto(&fm->cr, p->nw_proto); } } else { const struct field *f; char *value; value = strtok_r(NULL, ", \t\r\n", &save_ptr); if (!value) { ovs_fatal(0, "field %s missing value", name); } if (table_idx && !strcmp(name, "table")) { *table_idx = atoi(value); } else if (!strcmp(name, "out_port")) { fm->out_port = atoi(value); } else if (!strcmp(name, "priority")) { fm->cr.priority = atoi(value); } else if (!strcmp(name, "idle_timeout")) { fm->idle_timeout = atoi(value); } else if (!strcmp(name, "hard_timeout")) { fm->hard_timeout = atoi(value); } else if (!strcmp(name, "cookie")) { fm->cookie = htonll(str_to_u64(value)); } else if (parse_field_name(name, &f)) { if (!strcmp(value, "*") || !strcmp(value, "ANY")) { if (f->wildcard) { fm->cr.wc.wildcards |= f->wildcard; cls_rule_zero_wildcarded_fields(&fm->cr); } else if (f->index == F_NW_SRC) { cls_rule_set_nw_src_masked(&fm->cr, 0, 0); } else if (f->index == F_NW_DST) { cls_rule_set_nw_dst_masked(&fm->cr, 0, 0); } else if (f->index == F_IPV6_SRC) { cls_rule_set_ipv6_src_masked(&fm->cr, &in6addr_any, &in6addr_any); } else if (f->index == F_IPV6_DST) { cls_rule_set_ipv6_dst_masked(&fm->cr, &in6addr_any, &in6addr_any); } else if (f->index == F_DL_VLAN) { cls_rule_set_any_vid(&fm->cr); } else if (f->index == F_DL_VLAN_PCP) { cls_rule_set_any_pcp(&fm->cr); } else { NOT_REACHED(); } } else { parse_field_value(&fm->cr, f->index, value); } } else if (!strncmp(name, "reg", 3) && isdigit((unsigned char) name[3])) { unsigned int reg_idx = atoi(name + 3); if (reg_idx >= FLOW_N_REGS) { ovs_fatal(0, "only %d registers supported", FLOW_N_REGS); } parse_reg_value(&fm->cr, reg_idx, value); } else { ovs_fatal(0, "unknown keyword %s", name); } } } }
static void do_listen(int argc OVS_UNUSED, char *argv[]) { struct pstream *pstream; struct jsonrpc **rpcs; size_t n_rpcs, allocated_rpcs; bool done; int error; error = jsonrpc_pstream_open(argv[1], &pstream, DSCP_DEFAULT); if (error) { ovs_fatal(error, "could not listen on \"%s\"", argv[1]); } daemonize(); rpcs = NULL; n_rpcs = allocated_rpcs = 0; done = false; for (;;) { struct stream *stream; size_t i; /* Accept new connections. */ error = pstream_accept(pstream, &stream); if (!error) { if (n_rpcs >= allocated_rpcs) { rpcs = x2nrealloc(rpcs, &allocated_rpcs, sizeof *rpcs); } rpcs[n_rpcs++] = jsonrpc_open(stream); } else if (error != EAGAIN) { ovs_fatal(error, "pstream_accept failed"); } /* Service existing connections. */ for (i = 0; i < n_rpcs; ) { struct jsonrpc *rpc = rpcs[i]; struct jsonrpc_msg *msg; jsonrpc_run(rpc); if (!jsonrpc_get_backlog(rpc)) { error = jsonrpc_recv(rpc, &msg); if (!error) { error = handle_rpc(rpc, msg, &done); jsonrpc_msg_destroy(msg); } else if (error == EAGAIN) { error = 0; } } if (!error) { error = jsonrpc_get_status(rpc); } if (error) { jsonrpc_close(rpc); ovs_error(error, "connection closed"); memmove(&rpcs[i], &rpcs[i + 1], (n_rpcs - i - 1) * sizeof *rpcs); n_rpcs--; } else { i++; } } /* Wait for something to do. */ if (done && !n_rpcs) { break; } pstream_wait(pstream); for (i = 0; i < n_rpcs; i++) { struct jsonrpc *rpc = rpcs[i]; jsonrpc_wait(rpc); if (!jsonrpc_get_backlog(rpc)) { jsonrpc_recv_wait(rpc); } } poll_block(); } free(rpcs); pstream_close(pstream); }
static void learn_parse_spec(const char *orig, char *name, char *value, struct learn_spec *spec) { memset(spec, 0, sizeof *spec); if (mf_from_name(name)) { const struct mf_field *dst = mf_from_name(name); union mf_value imm; char *error; error = mf_parse_value(dst, value, &imm); if (error) { ovs_fatal(0, "%s", error); } spec->n_bits = dst->n_bits; spec->src_type = NX_LEARN_SRC_IMMEDIATE; memset(&spec->src_imm, 0, sizeof spec->src_imm); memcpy(&spec->src_imm.u8[sizeof spec->src_imm - dst->n_bytes], &imm, dst->n_bytes); spec->dst_type = NX_LEARN_DST_MATCH; spec->dst.field = dst; spec->dst.ofs = 0; spec->dst.n_bits = dst->n_bits; } else if (strchr(name, '[')) { /* Parse destination and check prerequisites. */ if (mf_parse_subfield(&spec->dst, name)[0] != '\0') { ovs_fatal(0, "%s: syntax error after NXM field name `%s'", orig, name); } /* Parse source and check prerequisites. */ if (value[0] != '\0') { if (mf_parse_subfield(&spec->src, value)[0] != '\0') { ovs_fatal(0, "%s: syntax error after NXM field name `%s'", orig, value); } if (spec->src.n_bits != spec->dst.n_bits) { ovs_fatal(0, "%s: bit widths of %s (%u) and %s (%u) differ", orig, name, spec->src.n_bits, value, spec->dst.n_bits); } } else { spec->src = spec->dst; } spec->n_bits = spec->src.n_bits; spec->src_type = NX_LEARN_SRC_FIELD; spec->dst_type = NX_LEARN_DST_MATCH; } else if (!strcmp(name, "load")) { if (value[strcspn(value, "[-")] == '-') { learn_parse_load_immediate(value, spec); } else { struct nx_action_reg_move move; nxm_parse_reg_move(&move, value); spec->n_bits = ntohs(move.n_bits); spec->src_type = NX_LEARN_SRC_FIELD; nxm_decode_discrete(&spec->src, move.src, move.src_ofs, move.n_bits); spec->dst_type = NX_LEARN_DST_LOAD; nxm_decode_discrete(&spec->dst, move.dst, move.dst_ofs, move.n_bits); } } else if (!strcmp(name, "output")) { if (mf_parse_subfield(&spec->src, value)[0] != '\0') { ovs_fatal(0, "%s: syntax error after NXM field name `%s'", orig, name); } spec->n_bits = spec->src.n_bits; spec->src_type = NX_LEARN_SRC_FIELD; spec->dst_type = NX_LEARN_DST_OUTPUT; } else { ovs_fatal(0, "%s: unknown keyword %s", orig, name); } }