Exemple #1
0
/* 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);
    }
}
Exemple #2
0
/* 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");
    }
}
Exemple #3
0
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;
}
Exemple #4
0
static void
unblock_sigalrm(const sigset_t *oldsigs)
{
    if (sigprocmask(SIG_SETMASK, oldsigs, NULL)) {
        ofp_fatal(errno, "sigprocmask");
    }
}
Exemple #5
0
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");
    }
}
Exemple #6
0
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);
    }
}
Exemple #7
0
/* 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);
        }
    }
}
Exemple #11
0
/* 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);
        }
    }
}
Exemple #13
0
/* 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;
}
Exemple #14
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,
        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);
}
Exemple #15
0
/* 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);
}
Exemple #16
0
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;

}
Exemple #20
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);
}
Exemple #21
0
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);
}
Exemple #22
0
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);
}