Esempio n. 1
0
/* Execute a group entry of type FAILFAST. */
static void
execute_ff(struct group_entry *entry, struct packet *pkt) {
    size_t b  = select_from_ff_group(entry);

    if (b != -1) {
        struct ofl_bucket *bucket = entry->desc->buckets[b];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[b]->byte_count += p->buffer->size;
        entry->stats->counters[b]->packet_count++;
        /* Cookie field is set 0xffffffffffffffff
           because we cannot associate to any
           particular flow */
        action_set_execute(p->action_set, p, 0xffffffffffffffff);
        packet_destroy(p);
    } else {
        VLOG_DBG_RL(LOG_MODULE, &rl, "No bucket in group.");
    }
}
Esempio n. 2
0
static void
jsonrpc_log_msg(const struct jsonrpc *rpc, const char *title,
                const struct jsonrpc_msg *msg)
{
    if (VLOG_IS_DBG_ENABLED()) {
        struct ds s = DS_EMPTY_INITIALIZER;
        if (msg->method) {
            ds_put_format(&s, ", method=\"%s\"", msg->method);
        }
        if (msg->params) {
            ds_put_cstr(&s, ", params=");
            json_to_ds(msg->params, 0, &s);
        }
        if (msg->result) {
            ds_put_cstr(&s, ", result=");
            json_to_ds(msg->result, 0, &s);
        }
        if (msg->error) {
            ds_put_cstr(&s, ", error=");
            json_to_ds(msg->error, 0, &s);
        }
        if (msg->id) {
            ds_put_cstr(&s, ", id=");
            json_to_ds(msg->id, 0, &s);
        }
        VLOG_DBG("%s: %s %s%s", rpc->name, title,
                 jsonrpc_msg_type_to_string(msg->type), ds_cstr(&s));
        ds_destroy(&s);
    }
}
Esempio n. 3
0
/* Executes a group entry of type ALL. */
static void
execute_all(struct group_entry *entry, struct packet *pkt) {
    size_t i;

    /* TODO Zoltan: Currently packets are always cloned. However it should
     * be possible to see if cloning is necessary, or not, based on bucket actions. */
    for (i=0; i<entry->desc->buckets_num; i++) {
        struct ofl_bucket *bucket = entry->desc->buckets[i];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[i]->byte_count += p->buffer->size;
        entry->stats->counters[i]->packet_count++;

        /* Cookie field is set 0xffffffffffffffff
           because we cannot associate to any
           particular flow */
        action_set_execute(p->action_set, p, 0xffffffffffffffff);

        packet_destroy(p);
    }
}
Esempio n. 4
0
/* Execute a group entry of type INDIRECT. */
static void
execute_indirect(struct group_entry *entry, struct packet *pkt) {

    if (entry->desc->buckets_num > 0) {
        struct ofl_bucket *bucket = entry->desc->buckets[0];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[0]->byte_count += p->buffer->size;
        entry->stats->counters[0]->packet_count++;

        action_set_execute(p->action_set, p);
        packet_destroy(p);
    } else {
        VLOG_DBG_RL(LOG_MODULE, &rl, "No bucket in group.");
    }
}
Esempio n. 5
0
/* Prepare to start a process whose command-line arguments are given by the
 * null-terminated 'argv' array.  Returns 0 if successful, otherwise a
 * positive errno value. */
static int
process_prestart(char **argv)
{
    char *binary;

    process_init();

    /* Log the process to be started. */
    if (VLOG_IS_DBG_ENABLED()) {
        char *args = process_escape_args(argv);
        VLOG_DBG("starting subprocess: %s", args);
        free(args);
    }

    /* execvp() will search PATH too, but the error in that case is more
     * obscure, since it is only reported post-fork. */
    binary = process_search_path(argv[0]);
    if (!binary) {
        VLOG_ERR("%s not found in PATH", argv[0]);
        return ENOENT;
    }
    free(binary);

    return 0;
}
/* Causes the following call to poll_block() to block for no more than 'msec'
 * milliseconds.  If 'msec' is nonpositive, the following call to poll_block()
 * will not block at all.
 *
 * The timer registration is one-shot: only the following call to poll_block()
 * is affected.  The timer will need to be re-registered after poll_block() is
 * called if it is to persist. */
void
poll_timer_wait(int msec)
{
    if (timeout < 0 || msec < timeout) {
        timeout = MAX(0, msec);
        if (VLOG_IS_DBG_ENABLED()) {
            backtrace_capture(&timeout_backtrace);
        }
    }
}
/* Creates and returns a new poll_waiter for 'fd' and 'events'. */
static struct poll_waiter *
new_waiter(int fd, short int events)
{
    struct poll_waiter *waiter = xcalloc(1, sizeof *waiter);
    assert(fd >= 0);
    waiter->fd = fd;
    waiter->events = events;
    if (VLOG_IS_DBG_ENABLED()) {
        waiter->backtrace = xmalloc(sizeof *waiter->backtrace);
        backtrace_capture(waiter->backtrace);
    }
    list_push_back(&waiters, &waiter->node);
    n_waiters++;
    return waiter;
}
Esempio n. 8
0
/* Processes 'msg', which should be an OpenFlow received on 'rconn', according
 * to the learning switch state in 'sw'.  The most likely result of processing
 * is that flow-setup and packet-out OpenFlow messages will be sent out on
 * 'rconn'.  */
static void
lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg)
{
    enum ofptype type;
    struct ofpbuf b;

    b = *msg;
    if (ofptype_pull(&type, &b)) {
        return;
    }

    if (sw->state == S_FEATURES_REPLY
        && type != OFPTYPE_ECHO_REQUEST
        && type != OFPTYPE_FEATURES_REPLY) {
        return;
    }

    if (type == OFPTYPE_ECHO_REQUEST) {
        process_echo_request(sw, msg->data);
    } else if (type == OFPTYPE_FEATURES_REPLY) {
        if (sw->state == S_FEATURES_REPLY) {
            if (!process_switch_features(sw, msg->data)) {
                sw->state = S_SWITCHING;
            } else {
                rconn_disconnect(sw->rconn);
            }
        }
    } else if (type == OFPTYPE_PACKET_IN) {
        process_packet_in(sw, msg->data);
    } else if (type == OFPTYPE_FLOW_REMOVED) {
        /* Nothing to do. */
    } else if (VLOG_IS_DBG_ENABLED()) {
        char *s = ofp_to_string(msg->data, msg->size, 2);
        VLOG_DBG_RL(&rl, "%016llx: OpenFlow packet ignored: %s",
                    sw->datapath_id, s);
        free(s);
    }
}
Esempio n. 9
0
void
pipeline_process_packet(struct pipeline *pl, struct packet *pkt) {
    struct flow_table *table, *next_table;

    if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
        char *pkt_str = packet_to_string(pkt);
        VLOG_DBG_RL(LOG_MODULE, &rl, "processing packet: %s", pkt_str);
        free(pkt_str);
    }
 
    if (!packet_handle_std_is_ttl_valid(pkt->handle_std)) {
        if ((pl->dp->config.flags & OFPC_INVALID_TTL_TO_CONTROLLER) != 0) {
            VLOG_DBG_RL(LOG_MODULE, &rl, "Packet has invalid TTL, sending to controller.");
            
            send_packet_to_controller(pl, pkt, 0/*table_id*/, OFPR_INVALID_TTL);
        } else {
            VLOG_DBG_RL(LOG_MODULE, &rl, "Packet has invalid TTL, dropping.");
        }
        packet_destroy(pkt);
        return;
    }

    next_table = pl->tables[0];
    while (next_table != NULL) {
        struct flow_entry *entry;

        VLOG_DBG_RL(LOG_MODULE, &rl, "trying table %u.", next_table->stats->table_id);

        pkt->table_id = next_table->stats->table_id;
        table         = next_table;
        next_table    = NULL;
         
        entry = flow_table_lookup(table, pkt);
        if (entry != NULL) {
	        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
                char *m = ofl_structs_flow_stats_to_string(entry->stats, pkt->dp->exp);
                VLOG_DBG_RL(LOG_MODULE, &rl, "found matching entry: %s.", m);
                free(m);
            }

            execute_entry(pl, entry, &next_table, &pkt);
            /* Packet could be destroyed by a meter instruction */
            if (!pkt)
                return;
            
            if (next_table == NULL) {
               /* Cookie field is set 0xffffffffffffffff
                because we cannot associate it to any
                particular flow */
                action_set_execute(pkt->action_set, pkt, 0xffffffffffffffff);
                packet_destroy(pkt);
                return;
            }

        } else {
			/* OpenFlow 1.3 default behavior on a table miss */
			VLOG_DBG_RL(LOG_MODULE, &rl, "No matching entry found. Dropping packet.");
			packet_destroy(pkt);
			return;
        }
    }
    VLOG_WARN_RL(LOG_MODULE, &rl, "Reached outside of pipeline processing cycle.");
}
Esempio n. 10
0
static int
new_ssl_stream(const char *name, int fd, enum session_type type,
               enum ssl_state state, struct stream **streamp)
{
    struct ssl_stream *sslv;
    SSL *ssl = NULL;
    int retval;

    /* Check for all the needful configuration. */
    retval = 0;
    if (!private_key.read) {
        VLOG_ERR("Private key must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!certificate.read) {
        VLOG_ERR("Certificate must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!ca_cert.read && verify_peer_cert && !bootstrap_ca_cert) {
        VLOG_ERR("CA certificate must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!retval && !SSL_CTX_check_private_key(ctx)) {
        VLOG_ERR("Private key does not match certificate public key: %s",
                 ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
    }
    if (retval) {
        goto error;
    }

    /* Disable Nagle.
     * On windows platforms, this can only be called upon TCP connected.
     */
    if (state == STATE_SSL_CONNECTING) {
        setsockopt_tcp_nodelay(fd);
    }

    /* Create and configure OpenSSL stream. */
    ssl = SSL_new(ctx);
    if (ssl == NULL) {
        VLOG_ERR("SSL_new: %s", ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
        goto error;
    }
    if (SSL_set_fd(ssl, fd) == 0) {
        VLOG_ERR("SSL_set_fd: %s", ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
        goto error;
    }
    if (!verify_peer_cert || (bootstrap_ca_cert && type == CLIENT)) {
        SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
    }

    /* Create and return the ssl_stream. */
    sslv = xmalloc(sizeof *sslv);
    stream_init(&sslv->stream, &ssl_stream_class, EAGAIN, name);
    sslv->state = state;
    sslv->type = type;
    sslv->fd = fd;
    sslv->ssl = ssl;
    sslv->txbuf = NULL;
    sslv->rx_want = sslv->tx_want = SSL_NOTHING;
    sslv->session_nr = next_session_nr++;
    sslv->n_head = 0;

    if (VLOG_IS_DBG_ENABLED()) {
        SSL_set_msg_callback(ssl, ssl_protocol_cb);
        SSL_set_msg_callback_arg(ssl, sslv);
    }

    *streamp = &sslv->stream;
    return 0;

error:
    if (ssl) {
        SSL_free(ssl);
    }
    closesocket(fd);
    return retval;
}
/* Blocks until one or more of the events registered with poll_fd_wait()
 * occurs, or until the minimum duration registered with poll_timer_wait()
 * elapses, or not at all if poll_immediate_wake() has been called.
 *
 * Also executes any autonomous subroutines registered with poll_fd_callback(),
 * if their file descriptors have become ready. */
void
poll_block(void)
{
    static struct pollfd *pollfds;
    static size_t max_pollfds;

    struct poll_waiter *pw;
    struct list *node;
    int n_pollfds;
    int retval;

    assert(!running_cb);
    if (max_pollfds < n_waiters) {
        max_pollfds = n_waiters;
        pollfds = xrealloc(pollfds, max_pollfds * sizeof *pollfds);
    }

    n_pollfds = 0;
    LIST_FOR_EACH (pw, struct poll_waiter, node, &waiters) {
        pw->pollfd = &pollfds[n_pollfds];
        pollfds[n_pollfds].fd = pw->fd;
        pollfds[n_pollfds].events = pw->events;
        pollfds[n_pollfds].revents = 0;
        n_pollfds++;
    }

    retval = time_poll(pollfds, n_pollfds, timeout);
    if (retval < 0) {
        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
        VLOG_ERR_RL(&rl, "poll: %s", strerror(-retval));
    } else if (!retval && VLOG_IS_DBG_ENABLED()) {
        log_wakeup(&timeout_backtrace, "%d-ms timeout", timeout);
    }

    for (node = waiters.next; node != &waiters; ) {
        pw = CONTAINER_OF(node, struct poll_waiter, node);
        if (!pw->pollfd || !pw->pollfd->revents) {
            if (pw->function) {
                node = node->next;
                continue;
            }
        } else {
            if (VLOG_IS_DBG_ENABLED()) {
                log_wakeup(pw->backtrace, "%s%s%s%s%s on fd %d",
                           pw->pollfd->revents & POLLIN ? "[POLLIN]" : "",
                           pw->pollfd->revents & POLLOUT ? "[POLLOUT]" : "",
                           pw->pollfd->revents & POLLERR ? "[POLLERR]" : "",
                           pw->pollfd->revents & POLLHUP ? "[POLLHUP]" : "",
                           pw->pollfd->revents & POLLNVAL ? "[POLLNVAL]" : "",
                           pw->fd);
            }

            if (pw->function) {
#ifndef NDEBUG
                running_cb = pw;
#endif
                pw->function(pw->fd, pw->pollfd->revents, pw->aux);
#ifndef NDEBUG
                running_cb = NULL;
#endif
            }
        }
        node = node->next;
        poll_cancel(pw);
    }

    timeout = -1;
    timeout_backtrace.n_frames = 0;
}
Esempio n. 12
0
static int
new_ssl_stream(const char *name, int fd, enum session_type type,
               enum ssl_state state, const struct sockaddr_in *remote,
               struct stream **streamp)
{
    struct sockaddr_in local;
    socklen_t local_len = sizeof local;
    struct ssl_stream *sslv;
    SSL *ssl = NULL;
    int on = 1;
    int retval;

    /* Check for all the needful configuration. */
    retval = 0;
    if (!private_key.read) {
        VLOG_ERR("Private key must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!certificate.read) {
        VLOG_ERR("Certificate must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!ca_cert.read && verify_peer_cert && !bootstrap_ca_cert) {
        VLOG_ERR("CA certificate must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!retval && !SSL_CTX_check_private_key(ctx)) {
        VLOG_ERR("Private key does not match certificate public key: %s",
                 ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
    }
    if (retval) {
        goto error;
    }

    /* Get the local IP and port information */
    retval = getsockname(fd, (struct sockaddr *) &local, &local_len);
    if (retval) {
        memset(&local, 0, sizeof local);
    }

    /* Disable Nagle. */
    retval = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof on);
    if (retval) {
        VLOG_ERR("%s: setsockopt(TCP_NODELAY): %s", name, strerror(errno));
        retval = errno;
        goto error;
    }

    /* Create and configure OpenSSL stream. */
    ssl = SSL_new(ctx);
    if (ssl == NULL) {
        VLOG_ERR("SSL_new: %s", ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
        goto error;
    }
    if (SSL_set_fd(ssl, fd) == 0) {
        VLOG_ERR("SSL_set_fd: %s", ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
        goto error;
    }
    if (!verify_peer_cert || (bootstrap_ca_cert && type == CLIENT)) {
        SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
    }

    /* Create and return the ssl_stream. */
    sslv = xmalloc(sizeof *sslv);
    stream_init(&sslv->stream, &ssl_stream_class, EAGAIN, name);
    stream_set_remote_ip(&sslv->stream, remote->sin_addr.s_addr);
    stream_set_remote_port(&sslv->stream, remote->sin_port);
    stream_set_local_ip(&sslv->stream, local.sin_addr.s_addr);
    stream_set_local_port(&sslv->stream, local.sin_port);
    sslv->state = state;
    sslv->type = type;
    sslv->fd = fd;
    sslv->ssl = ssl;
    sslv->txbuf = NULL;
    sslv->rx_want = sslv->tx_want = SSL_NOTHING;
    sslv->session_nr = next_session_nr++;
    sslv->n_head = 0;

    if (VLOG_IS_DBG_ENABLED()) {
        SSL_set_msg_callback(ssl, ssl_protocol_cb);
        SSL_set_msg_callback_arg(ssl, sslv);
    }

    *streamp = &sslv->stream;
    return 0;

error:
    if (ssl) {
        SSL_free(ssl);
    }
    close(fd);
    return retval;
}