/* Blocks program termination signals until fatal_signal_unblock() is called. * May be called multiple times with nesting; if so, fatal_signal_unblock() * must be called the same number of times to unblock signals. * * This is needed while adjusting a data structure that will be accessed by a * fatal signal hook, so that the hook is not invoked while the data structure * is in an inconsistent state. */ void fatal_signal_block(void) { static bool inited = false; if (!inited) { size_t i; inited = true; sigemptyset(&fatal_signal_set); for (i = 0; i < ARRAY_SIZE(fatal_signals); i++) { int sig_nr = fatal_signals[i]; struct sigaction old_sa; sigaddset(&fatal_signal_set, sig_nr); if (sigaction(sig_nr, NULL, &old_sa)) { ofp_fatal(errno, "sigaction"); } if (old_sa.sa_handler == SIG_DFL && signal(sig_nr, fatal_signal_handler) == SIG_ERR) { ofp_fatal(errno, "signal"); } } atexit(atexit_handler); } if (++block_level == 1) { call_sigprocmask(SIG_BLOCK, &fatal_signal_set, &saved_signal_mask); } }
/* Initializes the timetracking module. */ void time_init(void) { struct sigaction sa; struct itimerval itimer; if (inited) { return; } inited = true; gettimeofday(&now, NULL); tick = false; /* Set up signal handler. */ memset(&sa, 0, sizeof sa); sa.sa_handler = sigalrm_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGALRM, &sa, NULL)) { ofp_fatal(errno, "sigaction(SIGALRM) failed"); } /* Set up periodic timer. */ itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = TIME_UPDATE_INTERVAL * 1000; itimer.it_value = itimer.it_interval; if (setitimer(ITIMER_REAL, &itimer, NULL)) { ofp_fatal(errno, "setitimer failed"); } }
int main(int argc, char *argv[]) { struct rconn *rconn; int error; set_program_name(argv[0]); register_fault_handlers(); time_init(); vlog_init(); parse_options(argc, argv); signal(SIGPIPE, SIG_IGN); if (argc - optind != 1) { ofp_fatal(0, "missing controller argument; use --help for usage"); } rconn = rconn_create(60, max_backoff); error = rconn_connect(rconn, argv[optind]); if (error == EAFNOSUPPORT) { ofp_fatal(0, "no support for %s vconn", argv[optind]); } error = dp_new(&dp, dpid, rconn); if (listen_pvconn_name) { struct pvconn *listen_pvconn; int retval; retval = pvconn_open(listen_pvconn_name, &listen_pvconn); if (retval && retval != EAGAIN) { ofp_fatal(retval, "opening %s", listen_pvconn_name); } dp_add_listen_pvconn(dp, listen_pvconn); } if (error) { ofp_fatal(error, "could not create datapath"); } if (port_list) { add_ports(dp, port_list); } die_if_already_running(); daemonize(); error = vlog_server_listen(NULL, NULL); if (error) { ofp_fatal(error, "could not listen for vlog connections"); } for (;;) { dp_run(dp); dp_wait(dp); poll_block(); } return 0; }
static void unblock_sigalrm(const sigset_t *oldsigs) { if (sigprocmask(SIG_SETMASK, oldsigs, NULL)) { ofp_fatal(errno, "sigprocmask"); } }
static void block_sigalrm(sigset_t *oldsigs) { sigset_t sigalrm; sigemptyset(&sigalrm); sigaddset(&sigalrm, SIGALRM); if (sigprocmask(SIG_BLOCK, &sigalrm, oldsigs)) { ofp_fatal(errno, "sigprocmask"); } }
void random_init(void) { static bool inited = false; if (!inited) { struct timeval tv; inited = true; if (gettimeofday(&tv, NULL) < 0) { ofp_fatal(errno, "gettimeofday"); } srand(tv.tv_sec ^ tv.tv_usec); } }
/* Initializes the signals subsystem (if it is not already initialized). Calls * exit() if initialization fails. * * Calling this function is optional; it will be called automatically by * signal_start() if necessary. Calling it explicitly allows the client to * prevent the process from exiting at an unexpected time. */ void signal_init(void) { static bool inited; if (!inited) { inited = true; if (pipe(fds)) { ofp_fatal(errno, "could not create pipe"); } set_nonblocking(fds[0]); set_nonblocking(fds[1]); } }
int main(int argc, char *argv[]) { struct dhclient *cli; int error; set_program_name(argv[0]); register_fault_handlers(); vlog_init(); parse_options(argc, argv); argc -= optind; argv += optind; if (argc != 1) { ofp_fatal(0, "exactly one non-option argument required; " "use --help for help"); } error = dhclient_create(argv[0], modify_dhcp_request, NULL, NULL, &cli); if (error) { ofp_fatal(error, "dhclient_create failed"); } dhclient_init(cli, request_ip.s_addr); fatal_signal_add_hook(release, cli, true); for (;;) { fatal_signal_block(); dhclient_run(cli); if (dhclient_changed(cli)) { dhclient_configure_netdev(cli); if (update_resolv_conf) { dhclient_update_resolv_conf(cli); } } dhclient_wait(cli); fatal_signal_unblock(); poll_block(); } }
/* If configured with set_pidfile() or set_detach(), creates the pid file and * detaches from the foreground session. */ void daemonize(void) { if (detach) { char c = 0; int fds[2]; if (pipe(fds) < 0) { ofp_fatal(errno, "pipe failed"); } switch (fork()) { default: /* Parent process: wait for child to create pidfile, then exit. */ close(fds[1]); fatal_signal_fork(); if (read(fds[0], &c, 1) != 1) { ofp_fatal(errno, "daemon child failed to signal startup"); } exit(0); case 0: /* Child process. */ close(fds[0]); make_pidfile(); write(fds[1], &c, 1); close(fds[1]); setsid(); chdir("/"); break; case -1: /* Error. */ ofp_fatal(errno, "could not fork"); break; } } else { make_pidfile(); } }
/* If a locked pidfile exists, issue a warning message and, unless * ignore_existing_pidfile() has been called, terminate the program. */ void die_if_already_running(void) { pid_t pid = already_running(); if (pid) { if (!force) { ofp_fatal(0, "%s: already running as pid %ld", get_pidfile(), (long int) pid); } else { VLOG_WARN("%s: %s already running as pid %ld", get_pidfile(), program_name, (long int) pid); } } }
/* Add a range of numeric ports from min to max, inclusive */ static void add_ports_range(struct datapath *dp, int min_port, int max_port) { char port_name[16]; int port; int error; for (port = min_port; port <= max_port; port++) { sprintf(port_name, "%d", port); error = dp_add_port(dp, port_name, num_queues); if (error) { ofp_fatal(error, "failed to add port %s", port_name); } } }
static void add_ports(struct datapath *dp, char *port_list) { char *port, *save_ptr; /* Glibc 2.7 has a bug in strtok_r when compiling with optimization that * can cause segfaults here: * http://sources.redhat.com/bugzilla/show_bug.cgi?id=5614. * Using ",," instead of the obvious "," works around it. */ for (port = strtok_r(port_list, ",,", &save_ptr); port; port = strtok_r(NULL, ",,", &save_ptr)) { int error = dp_ports_add(dp, port); if (error) { ofp_fatal(error, "failed to add port %s", port); } } }
/* Sets up a handler for 'signr' and returns a structure that represents it. * * Only one handler for a given signal may be registered at a time. */ struct signal * signal_register(int signr) { struct sigaction sa; struct signal *s; signal_init(); /* Set up signal handler. */ assert(signr >= 1 && signr < N_SIGNALS); memset(&sa, 0, sizeof sa); sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(signr, &sa, NULL)) { ofp_fatal(errno, "sigaction(%d) failed", signr); } /* Return structure. */ s = xmalloc(sizeof *s); s->signr = signr; return s; }
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man * page) into 'fm' for sending the specified flow_mod 'command' to a switch. * If 'actions' is specified, an action must be in 'string' and may be expanded * or reallocated. * * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_* * constant for 'command'. To parse syntax for an OFPST_FLOW or * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'. */ void parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, bool verbose) { enum { F_OUT_PORT = 1 << 0, F_ACTIONS = 1 << 1, F_TIMEOUT = 1 << 3, F_PRIORITY = 1 << 4, F_FLAGS = 1 << 5, } fields; char *string = xstrdup(str_); char *save_ptr = NULL; char *act_str = NULL; char *name; switch (command) { case -1: fields = F_OUT_PORT; break; case OFPFC_ADD: fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS; break; case OFPFC_DELETE: fields = F_OUT_PORT; break; case OFPFC_DELETE_STRICT: fields = F_OUT_PORT | F_PRIORITY; break; case OFPFC_MODIFY: fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS; break; case OFPFC_MODIFY_STRICT: fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS; break; default: NOT_REACHED(); } match_init_catchall(&fm->match); fm->priority = OFP_DEFAULT_PRIORITY; fm->cookie = htonll(0); fm->cookie_mask = htonll(0); if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) { /* For modify, by default, don't update the cookie. */ fm->new_cookie = htonll(UINT64_MAX); } else{ fm->new_cookie = htonll(0); } fm->table_id = 0xff; fm->command = command; fm->idle_timeout = OFP_FLOW_PERMANENT; fm->hard_timeout = OFP_FLOW_PERMANENT; fm->buffer_id = UINT32_MAX; fm->out_port = OFPP_ANY; fm->flags = 0; if (fields & F_ACTIONS) { act_str = strstr(string, "action"); if (!act_str) { ofp_fatal(str_, verbose, "must specify an action"); } *act_str = '\0'; act_str = strchr(act_str + 1, '='); if (!act_str) { ofp_fatal(str_, verbose, "must specify an action"); } act_str++; } 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)) { match_set_dl_type(&fm->match, htons(p->dl_type)); if (p->nw_proto) { match_set_nw_proto(&fm->match, p->nw_proto); } } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) { fm->flags |= OFPFF_SEND_FLOW_REM; } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) { fm->flags |= OFPFF_CHECK_OVERLAP; } else if (fields & F_FLAGS && !strcmp(name, "reset_counts")) { fm->flags |= OFPFF12_RESET_COUNTS; } else if (fields & F_FLAGS && !strcmp(name, "no_packet_counts")) { fm->flags |= OFPFF13_NO_PKT_COUNTS; } else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) { fm->flags |= OFPFF13_NO_BYT_COUNTS; } else { char *value; value = strtok_r(NULL, ", \t\r\n", &save_ptr); if (!value) { ofp_fatal(str_, verbose, "field %s missing value", name); } if (!strcmp(name, "table")) { fm->table_id = str_to_u8(value, name); } else if (!strcmp(name, "out_port")) { if (!ofputil_port_from_string(value, &fm->out_port)) { ofp_fatal(str_, verbose, "%s is not a valid OpenFlow port", name); } } else if (fields & F_PRIORITY && !strcmp(name, "priority")) { fm->priority = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) { fm->idle_timeout = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) { fm->hard_timeout = str_to_u16(value, name); } else if (!strcmp(name, "cookie")) { char *mask = strchr(value, '/'); if (mask) { /* A mask means we're searching for a cookie. */ if (command == OFPFC_ADD) { ofp_fatal(str_, verbose, "flow additions cannot use " "a cookie mask"); } *mask = '\0'; fm->cookie = htonll(str_to_u64(value)); fm->cookie_mask = htonll(str_to_u64(mask+1)); } else { /* No mask means that the cookie is being set. */ if (command != OFPFC_ADD && command != OFPFC_MODIFY && command != OFPFC_MODIFY_STRICT) { ofp_fatal(str_, verbose, "cannot set cookie"); } fm->new_cookie = htonll(str_to_u64(value)); } } else if (mf_from_name(name)) { parse_field(mf_from_name(name), value, &fm->match); } else if (!strcmp(name, "duration") || !strcmp(name, "n_packets") || !strcmp(name, "n_bytes") || !strcmp(name, "idle_age") || !strcmp(name, "hard_age")) { /* Ignore these, so that users can feed the output of * "ovs-ofctl dump-flows" back into commands that parse * flows. */ } else { ofp_fatal(str_, verbose, "unknown keyword %s", name); } } } if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX) && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) { /* On modifies without a mask, we are supposed to add a flow if * one does not exist. If a cookie wasn't been specified, use a * default of zero. */ fm->new_cookie = htonll(0); } if (fields & F_ACTIONS) { struct ofpbuf ofpacts; enum ofperr err; ofpbuf_init(&ofpacts, 32); str_to_inst_ofpacts(act_str, &ofpacts); fm->ofpacts_len = ofpacts.size; fm->ofpacts = ofpbuf_steal_data(&ofpacts); err = ofpacts_check(fm->ofpacts, fm->ofpacts_len, &fm->match.flow, OFPP_MAX, 0); if (err) { exit(EXIT_FAILURE); } } else { fm->ofpacts_len = 0; fm->ofpacts = NULL; } free(string); }
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man * page) into 'mm' for sending the specified meter_mod 'command' to a switch. */ void parse_ofp_meter_mod_str(struct ofputil_meter_mod *mm, const char *str_, int command, bool verbose) { enum { F_METER = 1 << 0, F_FLAGS = 1 << 1, F_BANDS = 1 << 2, } fields; char *string = xstrdup(str_); char *save_ptr = NULL; char *band_str = NULL; char *name; switch (command) { case -1: fields = F_METER; break; case OFPMC13_ADD: fields = F_METER | F_FLAGS | F_BANDS; break; case OFPMC13_DELETE: fields = F_METER; break; case OFPMC13_MODIFY: fields = F_METER | F_FLAGS | F_BANDS; break; default: NOT_REACHED(); } mm->command = command; mm->meter.meter_id = 0; mm->meter.flags = 0; if (fields & F_BANDS) { band_str = strstr(string, "band"); if (!band_str) { ofp_fatal(str_, verbose, "must specify bands"); } *band_str = '\0'; band_str = strchr(band_str + 1, '='); if (!band_str) { ofp_fatal(str_, verbose, "must specify bands"); } band_str++; } for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name; name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) { if (fields & F_FLAGS && !strcmp(name, "kbps")) { mm->meter.flags |= OFPMF13_KBPS; } else if (fields & F_FLAGS && !strcmp(name, "pktps")) { mm->meter.flags |= OFPMF13_PKTPS; } else if (fields & F_FLAGS && !strcmp(name, "burst")) { mm->meter.flags |= OFPMF13_BURST; } else if (fields & F_FLAGS && !strcmp(name, "stats")) { mm->meter.flags |= OFPMF13_STATS; } else { char *value; value = strtok_r(NULL, ", \t\r\n", &save_ptr); if (!value) { ofp_fatal(str_, verbose, "field %s missing value", name); } if (!strcmp(name, "meter")) { if (!strcmp(value, "all")) { mm->meter.meter_id = OFPM13_ALL; } else if (!strcmp(value, "controller")) { mm->meter.meter_id = OFPM13_CONTROLLER; } else if (!strcmp(value, "slowpath")) { mm->meter.meter_id = OFPM13_SLOWPATH; } else { mm->meter.meter_id = str_to_u32(value); if (mm->meter.meter_id > OFPM13_MAX) { ofp_fatal(str_, verbose, "invalid value for %s", name); } } } else { ofp_fatal(str_, verbose, "unknown keyword %s", name); } } } if (fields & F_METER && !mm->meter.meter_id) { ofp_fatal(str_, verbose, "must specify 'meter'"); } if (fields & F_FLAGS && !mm->meter.flags) { ofp_fatal(str_, verbose, "meter must specify either 'kbps' or 'pktps'"); } if (fields & F_BANDS) { struct ofpbuf bands; uint16_t n_bands = 0; struct ofputil_meter_band *band = NULL; int i; ofpbuf_init(&bands, 64); for (name = strtok_r(band_str, "=, \t\r\n", &save_ptr); name; name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) { char *value; value = strtok_r(NULL, ", \t\r\n", &save_ptr); if (!value) { ofp_fatal(str_, verbose, "field %s missing value", name); } if (!strcmp(name, "type")) { /* Start a new band */ band = ofpbuf_put_zeros(&bands, sizeof *band); n_bands++; if (!strcmp(value, "drop")) { band->type = OFPMBT13_DROP; } else if (!strcmp(value, "dscp_remark")) { band->type = OFPMBT13_DSCP_REMARK; } else { ofp_fatal(str_, verbose, "field %s unknown value %s", name, value); } } else if (!band || !band->type) { ofp_fatal(str_, verbose, "band must start with the 'type' keyword"); } else if (!strcmp(name, "rate")) { band->rate = str_to_u32(value); } else if (!strcmp(name, "burst_size")) { band->burst_size = str_to_u32(value); } else if (!strcmp(name, "prec_level")) { band->prec_level = str_to_u8(value, name); } else { ofp_fatal(str_, verbose, "unknown keyword %s", name); } } /* validate bands */ if (!n_bands) { ofp_fatal(str_, verbose, "meter must have bands"); } mm->meter.n_bands = n_bands; mm->meter.bands = ofpbuf_steal_data(&bands); for (i = 0; i < n_bands; ++i) { band = &mm->meter.bands[i]; if (!band->type) { ofp_fatal(str_, verbose, "band must have 'type'"); } if (band->type == OFPMBT13_DSCP_REMARK) { if (!band->prec_level) { ofp_fatal(str_, verbose, "'dscp_remark' band must have" " 'prec_level'"); } } else { if (band->prec_level) { ofp_fatal(str_, verbose, "Only 'dscp_remark' band may have" " 'prec_level'"); } } if (!band->rate) { ofp_fatal(str_, verbose, "band must have 'rate'"); } if (mm->meter.flags & OFPMF13_BURST) { if (!band->burst_size) { ofp_fatal(str_, verbose, "band must have 'burst_size' " "when 'burst' flag is set"); } } else { if (band->burst_size) { ofp_fatal(str_, verbose, "band may have 'burst_size' only " "when 'burst' flag is set"); } } } } else { mm->meter.n_bands = 0; mm->meter.bands = NULL; } free(string); }
int main(int argc, char *argv[]) { struct test_case *tc; FILE *input_file; int i; if (argc != 2) { ofp_fatal(0, "usage: test-stp INPUT.STP\n"); } file_name = argv[1]; input_file = fopen(file_name, "r"); if (!input_file) { ofp_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(*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"); } } return 0; }
static void parse_options(struct datapath *dp, int argc, char *argv[]) { enum { OPT_MFR_DESC = UCHAR_MAX + 1, OPT_HW_DESC, OPT_SW_DESC, OPT_DP_DESC, OPT_SERIAL_NUM, OPT_BOOTSTRAP_CA_CERT, OPT_NO_LOCAL_PORT, OPT_NO_SLICING }; static struct option long_options[] = { {"interfaces", required_argument, 0, 'i'}, {"local-port", required_argument, 0, 'L'}, {"no-local-port", no_argument, 0, OPT_NO_LOCAL_PORT}, {"datapath-id", required_argument, 0, 'd'}, {"multiconn", no_argument, 0, 'm'}, {"verbose", optional_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"no-slicing", no_argument, 0, OPT_NO_SLICING}, {"mfr-desc", required_argument, 0, OPT_MFR_DESC}, {"hw-desc", required_argument, 0, OPT_HW_DESC}, {"sw-desc", required_argument, 0, OPT_SW_DESC}, {"dp_desc", required_argument, 0, OPT_DP_DESC}, {"serial_num", required_argument, 0, OPT_SERIAL_NUM}, DAEMON_LONG_OPTIONS, #ifdef HAVE_OPENSSL VCONN_SSL_LONG_OPTIONS {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT}, #endif {0, 0, 0, 0}, }; char *short_options = long_options_to_short_options(long_options); for (;;) { int indexptr; int c; c = getopt_long(argc, argv, short_options, long_options, &indexptr); if (c == -1) { break; } switch (c) { case 'd': { uint64_t dpid; if (strlen(optarg) != 12 || strspn(optarg, "0123456789abcdefABCDEF") != 12) { ofp_fatal(0, "argument to -d or --datapath-id must be " "exactly 12 hex digits"); } dpid = strtoll(optarg, NULL, 16); if (!dpid) { ofp_fatal(0, "argument to -d or --datapath-id must " "be nonzero"); } dp_set_dpid(dp, dpid); break; } case 'm': { use_multiple_connections = true; break; } case 'h': usage(); case 'V': printf("%s %s compiled "__DATE__" "__TIME__"\n", program_name, VERSION BUILDNR); exit(EXIT_SUCCESS); case 'v': vlog_set_verbosity(optarg); break; case 'i': if (!port_list) { port_list = optarg; } else { port_list = xasprintf("%s,%s", port_list, optarg); } break; case 'L': local_port = optarg; break; case OPT_NO_LOCAL_PORT: local_port = NULL; break; case OPT_MFR_DESC: dp_set_mfr_desc(dp, optarg); break; case OPT_HW_DESC: dp_set_hw_desc(dp, optarg); break; case OPT_SW_DESC: dp_set_sw_desc(dp, optarg); break; case OPT_DP_DESC: dp_set_dp_desc(dp, optarg); break; case OPT_SERIAL_NUM: dp_set_serial_num(dp, optarg); break; case OPT_NO_SLICING: dp_set_max_queues(dp, 0); break; DAEMON_OPTION_HANDLERS #ifdef HAVE_OPENSSL VCONN_SSL_OPTION_HANDLERS case OPT_BOOTSTRAP_CA_CERT: vconn_ssl_set_ca_cert_file(optarg, true); break; #endif case '?': exit(EXIT_FAILURE); default: abort(); } } free(short_options); }
void out_of_memory(void) { ofp_fatal(0, "virtual memory exhausted"); }
extern "C" int nblink_initialize(void) { char ErrBuf[ERRBUF_SIZE + 1]; int NetPDLProtoDBFlags = nbPROTODB_MINIMAL; int NetPDLDecoderFlags = nbDECODER_GENERATEPDML; int ShowNetworkNames = 0; char* NetPDLFileName = (char*) NETPDLDIR"/"NETPDLFILE; struct stat netpdlstat; struct sigaction sa; /* Set up signal handler. */ memset(&sa, 0, sizeof sa); sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGINT, &sa, NULL)) { ofp_fatal(errno, "sigterm(SIGINT) failed"); } pkhdr = new struct pcap_pkthdr; if (nbIsInitialized() == nbFAILURE) { if (stat(NETPDLFILE, &netpdlstat) > 0 || errno != ENOENT) { NetPDLFileName += sizeof(NETPDLDIR) + 1 - 1; /* null char and '/' cancel out */ } if (nbInitialize(NetPDLFileName, NetPDLProtoDBFlags, ErrBuf, sizeof(ErrBuf)) == nbFAILURE) { printf("Error initializing the NetBee Library; %s\n", ErrBuf); return nbFAILURE; } } Decoder= nbAllocatePacketDecoder(NetPDLDecoderFlags, ErrBuf, sizeof(ErrBuf)); if (Decoder == NULL) { printf("Error creating the NetPDLParser: %s.\n", ErrBuf); return nbFAILURE; } // Get the PacketDecoderVars; let's do the check, although it is not really needed if ((PacketDecoderVars= Decoder->GetPacketDecoderVars()) == NULL) { printf("Error: cannot get an instance of the nbPacketDecoderVars class.\n"); return nbFAILURE; } // Set the appropriate NetPDL configuration variables // PacketDecoderVars->SetVariableNumber((char*) NETPDL_VARIABLE_SHOWNETWORKNAMES, ShowNetworkNames); if (PacketDecoderVars->SetVariableNumber((char*) NETPDL_VARIABLE_SHOWNETWORKNAMES, ShowNetworkNames)==nbFAILURE) { printf("Error: cannot set variables of the decoder properly.\n"); return nbFAILURE; } PDMLReader = Decoder->GetPDMLReader(); return 0; }
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man * page) into 'fm' for sending the specified flow_mod 'command' to a switch. * If 'actions' is specified, an action must be in 'string' and may be expanded * or reallocated. * * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_* * constant for 'command'. To parse syntax for an OFPST_FLOW or * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'. */ void parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, bool verbose) { enum { F_OUT_PORT = 1 << 0, F_ACTIONS = 1 << 1, F_TIMEOUT = 1 << 3, F_PRIORITY = 1 << 4 } fields; char *string = xstrdup(str_); char *save_ptr = NULL; char *act_str = NULL; char *name; switch (command) { case -1: fields = F_OUT_PORT; break; case OFPFC_ADD: fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY; break; case OFPFC_DELETE: fields = F_OUT_PORT; break; case OFPFC_DELETE_STRICT: fields = F_OUT_PORT | F_PRIORITY; break; case OFPFC_MODIFY: fields = F_ACTIONS; break; case OFPFC_MODIFY_STRICT: fields = F_ACTIONS | F_PRIORITY; break; default: NOT_REACHED(); } cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY); fm->cookie = htonll(0); fm->cookie_mask = htonll(0); if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) { /* For modify, by default, don't update the cookie. */ fm->new_cookie = htonll(UINT64_MAX); } else{ fm->new_cookie = htonll(0); } fm->table_id = 0xff; fm->command = command; 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 (fields & F_ACTIONS) { act_str = strstr(string, "action"); if (!act_str) { ofp_fatal(str_, verbose, "must specify an action"); } *act_str = '\0'; act_str = strchr(act_str + 1, '='); if (!act_str) { ofp_fatal(str_, verbose, "must specify an action"); } act_str++; } 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 { char *value; value = strtok_r(NULL, ", \t\r\n", &save_ptr); if (!value) { ofp_fatal(str_, verbose, "field %s missing value", name); } if (!strcmp(name, "table")) { fm->table_id = str_to_table_id(value); } else if (!strcmp(name, "out_port")) { fm->out_port = atoi(value); } else if (fields & F_PRIORITY && !strcmp(name, "priority")) { fm->cr.priority = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) { fm->idle_timeout = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) { fm->hard_timeout = str_to_u16(value, name); } else if (!strcmp(name, "cookie")) { char *mask = strchr(value, '/'); if (mask) { /* A mask means we're searching for a cookie. */ if (command == OFPFC_ADD) { ofp_fatal(str_, verbose, "flow additions cannot use " "a cookie mask"); } *mask = '\0'; fm->cookie = htonll(str_to_u64(value)); fm->cookie_mask = htonll(str_to_u64(mask+1)); } else { /* No mask means that the cookie is being set. */ if (command != OFPFC_ADD && command != OFPFC_MODIFY && command != OFPFC_MODIFY_STRICT) { ofp_fatal(str_, verbose, "cannot set cookie"); } fm->new_cookie = htonll(str_to_u64(value)); } } else if (mf_from_name(name)) { parse_field(mf_from_name(name), value, &fm->cr); } else if (!strcmp(name, "duration") || !strcmp(name, "n_packets") || !strcmp(name, "n_bytes")) { /* Ignore these, so that users can feed the output of * "ovs-ofctl dump-flows" back into commands that parse * flows. */ } else { ofp_fatal(str_, verbose, "unknown keyword %s", name); } } } if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX) && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) { /* On modifies without a mask, we are supposed to add a flow if * one does not exist. If a cookie wasn't been specified, use a * default of zero. */ fm->new_cookie = htonll(0); } if (fields & F_ACTIONS) { struct ofpbuf actions; ofpbuf_init(&actions, sizeof(union ofp_action)); str_to_action(&fm->cr.flow, act_str, &actions); fm->actions = ofpbuf_steal_data(&actions); fm->n_actions = actions.size / sizeof(union ofp_action); } else { fm->actions = NULL; fm->n_actions = 0; } free(string); }
int main(int argc, char *argv[]) { static const struct option long_options[] = { /* Target options must come first. */ {"all", no_argument, NULL, 'a'}, {"target", required_argument, NULL, 't'}, {"help", no_argument, NULL, 'h'}, /* Action options come afterward. */ {"list", no_argument, NULL, 'l'}, {"set", required_argument, NULL, 's'}, {"reopen", no_argument, NULL, 'r'}, {0, 0, 0, 0}, }; char *short_options; /* Determine targets. */ bool ok = true; int n_actions = 0; struct vlog_client **clients = NULL; size_t n_clients = 0; set_program_name(argv[0]); time_init(); short_options = long_options_to_short_options(long_options); for (;;) { int option; size_t i; option = getopt_long(argc, argv, short_options, long_options, NULL); if (option == -1) { break; } if (!strchr("ath", option) && n_clients == 0) { ofp_fatal(0, "no targets specified (use --help for help)"); } else { ++n_actions; } switch (option) { case 'a': add_all_targets(&clients, &n_clients, &ok); break; case 't': add_target(&clients, &n_clients, optarg, &ok); break; case 'l': for (i = 0; i < n_clients; i++) { struct vlog_client *client = clients[i]; char *reply; printf("%s:\n", vlog_client_target(client)); reply = transact(client, "list", &ok); fputs(reply, stdout); free(reply); } break; case 's': for (i = 0; i < n_clients; i++) { struct vlog_client *client = clients[i]; char *request = xasprintf("set %s", optarg); transact_ack(client, request, &ok); free(request); } break; case 'r': for (i = 0; i < n_clients; i++) { struct vlog_client *client = clients[i]; char *request = xstrdup("reopen"); transact_ack(client, request, &ok); free(request); } break; case 'h': usage(argv[0], EXIT_SUCCESS); break; case '?': exit(EXIT_FAILURE); default: NOT_REACHED(); } } if (!n_actions) { fprintf(stderr, "warning: no actions specified (use --help for help)\n"); } exit(ok ? 0 : 1); }
static void parse_options(int argc, char *argv[]) { enum { OPT_MAX_BACKOFF = UCHAR_MAX + 1, OPT_MFR_DESC, OPT_HW_DESC, OPT_SW_DESC, OPT_SERIAL_NUM, OPT_BOOTSTRAP_CA_CERT }; static struct option long_options[] = { {"interfaces", required_argument, 0, 'i'}, {"datapath-id", required_argument, 0, 'd'}, {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF}, {"listen", required_argument, 0, 'l'}, {"verbose", optional_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"mfr-desc", required_argument, 0, OPT_MFR_DESC}, {"hw-desc", required_argument, 0, OPT_HW_DESC}, {"sw-desc", required_argument, 0, OPT_SW_DESC}, {"serial_num", required_argument, 0, OPT_SERIAL_NUM}, DAEMON_LONG_OPTIONS, #ifdef HAVE_OPENSSL VCONN_SSL_LONG_OPTIONS {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT}, #endif {0, 0, 0, 0}, }; char *short_options = long_options_to_short_options(long_options); for (;;) { int indexptr; int c; c = getopt_long(argc, argv, short_options, long_options, &indexptr); if (c == -1) { break; } switch (c) { case 'd': if (strlen(optarg) != 12 || strspn(optarg, "0123456789abcdefABCDEF") != 12) { ofp_fatal(0, "argument to -d or --datapath-id must be " "exactly 12 hex digits"); } dpid = strtoll(optarg, NULL, 16); if (!dpid) { ofp_fatal(0, "argument to -d or --datapath-id must " "be nonzero"); } break; case 'h': usage(); case 'V': printf("%s %s compiled "__DATE__" "__TIME__"\n", program_name, VERSION BUILDNR); exit(EXIT_SUCCESS); case 'v': vlog_set_verbosity(optarg); break; case 'i': if (!port_list) { port_list = optarg; } else { port_list = xasprintf("%s,%s", port_list, optarg); } break; case OPT_MAX_BACKOFF: max_backoff = atoi(optarg); if (max_backoff < 1) { ofp_fatal(0, "--max-backoff argument must be at least 1"); } else if (max_backoff > 3600) { max_backoff = 3600; } break; case OPT_MFR_DESC: strncpy(mfr_desc, optarg, sizeof mfr_desc); break; case OPT_HW_DESC: strncpy(hw_desc, optarg, sizeof hw_desc); break; case OPT_SW_DESC: strncpy(sw_desc, optarg, sizeof sw_desc); break; case OPT_SERIAL_NUM: strncpy(serial_num, optarg, sizeof serial_num); break; case 'l': if (listen_pvconn_name) { ofp_fatal(0, "-l or --listen may be only specified once"); } listen_pvconn_name = optarg; break; DAEMON_OPTION_HANDLERS #ifdef HAVE_OPENSSL VCONN_SSL_OPTION_HANDLERS case OPT_BOOTSTRAP_CA_CERT: vconn_ssl_set_ca_cert_file(optarg, true); break; #endif case '?': exit(EXIT_FAILURE); default: abort(); } } free(short_options); }