Пример #1
0
static void *
search_ccmap(void *aux_)
{
    struct ccmap_aux *aux = aux_;
    size_t i;

    if (mutation_frac) {
        for (i = 0; i < n_elems; i++) {
            uint32_t hash = hash_int(i, 0);

            if (random_uint32() < mutation_frac) {
                ovs_mutex_lock(&aux->mutex);
                uint32_t count = ccmap_find(aux->ccmap, hash);
                if (count) {
                    ccmap_dec(aux->ccmap, hash);
                }
                ovs_mutex_unlock(&aux->mutex);
            } else {
                ignore(ccmap_find(aux->ccmap, hash));
            }
        }
    } else {
        for (i = 0; i < n_elems; i++) {
            ignore(ccmap_find(aux->ccmap, hash_int(i, 0)));
        }
    }
    return NULL;
}
Пример #2
0
static void
time_timespec__(struct clock *c, struct timespec *ts)
{
    bool slow_path;

    time_init();

    atomic_read_relaxed(&c->slow_path, &slow_path);
    if (!slow_path) {
        xclock_gettime(c->id, ts);
    } else {
        struct timespec warp;
        struct timespec cache;
        bool stopped;

        ovs_mutex_lock(&c->mutex);
        stopped = c->stopped;
        warp = c->warp;
        cache = c->cache;
        ovs_mutex_unlock(&c->mutex);

        if (!stopped) {
            xclock_gettime(c->id, &cache);
        }
        timespec_add(ts, &cache, &warp);
    }
}
Пример #3
0
/* Check whether a fatal signal has occurred and, if so, call the fatal signal
 * hooks and exit.
 *
 * This function is called automatically by poll_block(), but specialized
 * programs that may not always call poll_block() on a regular basis should
 * also call it periodically.  (Therefore, any function with "block" in its
 * name should call fatal_signal_run() each time it is called, either directly
 * or through poll_block(), because such functions can only used by specialized
 * programs that can afford to block outside their main loop around
 * poll_block().)
 */
void
fatal_signal_run(void)
{
    sig_atomic_t sig_nr;

    fatal_signal_init();

    sig_nr = stored_sig_nr;
    if (sig_nr != SIG_ATOMIC_MAX) {
        char namebuf[SIGNAL_NAME_BUFSIZE];

        ovs_mutex_lock(&mutex);

        VLOG_WARN("terminating with signal %d (%s)",
                  (int)sig_nr, signal_name(sig_nr, namebuf, sizeof namebuf));
        call_hooks(sig_nr);

        /* Re-raise the signal with the default handling so that the program
         * termination status reflects that we were killed by this signal */
        signal(sig_nr, SIG_DFL);
        raise(sig_nr);

        ovs_mutex_unlock(&mutex);
        OVS_NOT_REACHED();
    }
}
Пример #4
0
/* Unregisters 'file' from being unlinked when the program terminates via
 * exit() or a fatal signal. */
void
fatal_signal_remove_file_to_unlink(const char *file)
{
    fatal_signal_init();

    ovs_mutex_lock(&mutex);
    sset_find_and_delete(&files, file);
    ovs_mutex_unlock(&mutex);
}
Пример #5
0
static bool
is_warped(const struct clock *c)
{
    bool warped;

    ovs_mutex_lock(&c->mutex);
    warped = monotonic_clock.warp.tv_sec || monotonic_clock.warp.tv_nsec;
    ovs_mutex_unlock(&c->mutex);

    return warped;
}
Пример #6
0
/* Registers 'file' to be unlinked when the program terminates via exit() or a
 * fatal signal. */
void
fatal_signal_add_file_to_unlink(const char *file)
{
    fatal_signal_init();

    ovs_mutex_lock(&mutex);
    if (!added_hook) {
        added_hook = true;
        fatal_signal_add_hook(unlink_files, cancel_files, NULL, true);
    }

    sset_add(&files, file);
    ovs_mutex_unlock(&mutex);
}
Пример #7
0
/* Registers 'hook_cb' to be called from inside poll_block() following a fatal
 * signal.  'hook_cb' does not need to be async-signal-safe.  In a
 * multithreaded program 'hook_cb' might be called from any thread, with
 * threads other than the one running 'hook_cb' in unknown states.
 *
 * If 'run_at_exit' is true, 'hook_cb' is also called during normal process
 * termination, e.g. when exit() is called or when main() returns.
 *
 * If the current process forks, fatal_signal_fork() may be called to clear the
 * parent process's fatal signal hooks, so that 'hook_cb' is only called when
 * the child terminates, not when the parent does.  When fatal_signal_fork() is
 * called, it calls the 'cancel_cb' function if it is nonnull, passing 'aux',
 * to notify that the hook has been canceled.  This allows the hook to free
 * memory, etc. */
void
fatal_signal_add_hook(void (*hook_cb)(void *aux), void (*cancel_cb)(void *aux),
                      void *aux, bool run_at_exit)
{
    fatal_signal_init();

    ovs_mutex_lock(&mutex);
    ovs_assert(n_hooks < MAX_HOOKS);
    hooks[n_hooks].hook_cb = hook_cb;
    hooks[n_hooks].cancel_cb = cancel_cb;
    hooks[n_hooks].aux = aux;
    hooks[n_hooks].run_at_exit = run_at_exit;
    n_hooks++;
    ovs_mutex_unlock(&mutex);
}
Пример #8
0
/* Starts a Netlink "dump" operation, by sending 'request' to the kernel on a
 * Netlink socket created with the given 'protocol', and initializes 'dump' to
 * reflect the state of the operation.
 *
 * 'request' must contain a Netlink message.  Before sending the message,
 * nlmsg_len will be finalized to match request->size, and nlmsg_pid will be
 * set to the Netlink socket's pid.  NLM_F_DUMP and NLM_F_ACK will be set in
 * nlmsg_flags.
 *
 * The design of this Netlink socket library ensures that the dump is reliable.
 *
 * This function provides no status indication.  nl_dump_done() provides an
 * error status for the entire dump operation.
 *
 * The caller must eventually destroy 'request'.
 */
void
nl_dump_start(struct nl_dump *dump, int protocol, const struct ofpbuf *request)
{
    nl_msg_nlmsghdr(request)->nlmsg_flags |= NLM_F_DUMP | NLM_F_ACK;

    ovs_mutex_init(&dump->mutex);
    ovs_mutex_lock(&dump->mutex);
    dump->status = nl_pool_alloc(protocol, &dump->sock);
    if (!dump->status) {
        dump->status = nl_sock_send__(dump->sock, request,
                                      nl_sock_allocate_seq(dump->sock, 1),
                                      true);
    }
    dump->nl_seq = nl_msg_nlmsghdr(request)->nlmsg_seq;
    ovs_mutex_unlock(&dump->mutex);
}
Пример #9
0
/* Like fatal_signal_remove_file_to_unlink(), but also unlinks 'file'.
 * Returns 0 if successful, otherwise a positive errno value. */
int
fatal_signal_unlink_file_now(const char *file)
{
    int error;

    fatal_signal_init();

    ovs_mutex_lock(&mutex);

    error = unlink(file) ? errno : 0;
    if (error) {
        VLOG_WARN("could not unlink \"%s\" (%s)", file, ovs_strerror(error));
    }

    fatal_signal_remove_file_to_unlink(file);

    ovs_mutex_unlock(&mutex);

    return error;
}
Пример #10
0
Файл: uuid.c Проект: shettyg/ovs
/* Generates a new random UUID in 'uuid'.
 *
 * We go to some trouble to ensure as best we can that the generated UUID has
 * these properties:
 *
 *      - Uniqueness.  The random number generator is seeded using both the
 *        system clock and the system random number generator, plus a few
 *        other identifiers, which is about as good as we can get in any kind
 *        of simple way.
 *
 *      - Unpredictability.  In some situations it could be bad for an
 *        adversary to be able to guess the next UUID to be generated with some
 *        probability of success.  This property may or may not be important
 *        for our purposes, but it is better if we can get it.
 *
 * To ensure both of these, we start by taking our seed data and passing it
 * through SHA-1.  We use the result as an AES-128 key.  We also generate a
 * random 16-byte value[*] which we then use as the counter for CTR mode.  To
 * generate a UUID in a manner compliant with the above goals, we merely
 * increment the counter and encrypt it.
 *
 * [*] It is not actually important that the initial value of the counter be
 *     random.  AES-128 in counter mode is secure either way.
 */
void
uuid_generate(struct uuid *uuid)
{
    static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
    uint64_t copy[2];

    uuid_init();

    /* Copy out the counter's current value, then increment it. */
    ovs_mutex_lock(&mutex);
    copy[0] = counter[0];
    copy[1] = counter[1];
    if (++counter[1] == 0) {
        counter[0]++;
    }
    ovs_mutex_unlock(&mutex);

    /* AES output is exactly 16 bytes, so we encrypt directly into 'uuid'. */
    aes128_encrypt(&key, copy, uuid);

    uuid_set_bits_v4(uuid);
}
Пример #11
0
/* Creates a new netlink socket for the given netlink 'protocol'
 * (NETLINK_ROUTE, NETLINK_GENERIC, ...).  Returns 0 and sets '*sockp' to the
 * new socket if successful, otherwise returns a positive errno value. */
int
nl_sock_create(int protocol, struct nl_sock **sockp)
{
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
    struct nl_sock *sock;
#ifndef _WIN32
    struct sockaddr_nl local, remote;
#endif
    socklen_t local_size;
    int rcvbuf;
    int retval = 0;

    if (ovsthread_once_start(&once)) {
        int save_errno = errno;
        errno = 0;

        max_iovs = sysconf(_SC_UIO_MAXIOV);
        if (max_iovs < _XOPEN_IOV_MAX) {
            if (max_iovs == -1 && errno) {
                VLOG_WARN("sysconf(_SC_UIO_MAXIOV): %s", ovs_strerror(errno));
            }
            max_iovs = _XOPEN_IOV_MAX;
        } else if (max_iovs > MAX_IOVS) {
            max_iovs = MAX_IOVS;
        }

        errno = save_errno;
        ovsthread_once_done(&once);
    }

    *sockp = NULL;
    sock = xmalloc(sizeof *sock);

#ifdef _WIN32
    sock->handle = CreateFileA("\\\\.\\OpenVSwitchDevice",
                               GENERIC_READ | GENERIC_WRITE,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL, OPEN_EXISTING,
                               FILE_ATTRIBUTE_NORMAL, NULL);

    int last_error = GetLastError();

    if (sock->handle == INVALID_HANDLE_VALUE) {
        VLOG_ERR("fcntl: %s", ovs_strerror(last_error));
        goto error;
    }
#else
    sock->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
    if (sock->fd < 0) {
        VLOG_ERR("fcntl: %s", ovs_strerror(errno));
        goto error;
    }
#endif

    sock->protocol = protocol;
    sock->next_seq = 1;

    rcvbuf = 1024 * 1024;
#ifdef _WIN32
    sock->rcvbuf = rcvbuf;
    ovs_mutex_lock(&portid_mutex);
    sock->pid = portid_next();
    set_sock_pid_in_kernel(sock->handle, sock->pid);
    ovs_mutex_unlock(&portid_mutex);
#else
    if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUFFORCE,
                   &rcvbuf, sizeof rcvbuf)) {
        /* Only root can use SO_RCVBUFFORCE.  Everyone else gets EPERM.
         * Warn only if the failure is therefore unexpected. */
        if (errno != EPERM) {
            VLOG_WARN_RL(&rl, "setting %d-byte socket receive buffer failed "
                         "(%s)", rcvbuf, ovs_strerror(errno));
        }
    }

    retval = get_socket_rcvbuf(sock->fd);
    if (retval < 0) {
        retval = -retval;
        goto error;
    }
    sock->rcvbuf = retval;

    /* Connect to kernel (pid 0) as remote address. */
    memset(&remote, 0, sizeof remote);
    remote.nl_family = AF_NETLINK;
    remote.nl_pid = 0;
    if (connect(sock->fd, (struct sockaddr *) &remote, sizeof remote) < 0) {
        VLOG_ERR("connect(0): %s", ovs_strerror(errno));
        goto error;
    }

    /* Obtain pid assigned by kernel. */
    local_size = sizeof local;
    if (getsockname(sock->fd, (struct sockaddr *) &local, &local_size) < 0) {
        VLOG_ERR("getsockname: %s", ovs_strerror(errno));
        goto error;
    }
    if (local_size < sizeof local || local.nl_family != AF_NETLINK) {
        VLOG_ERR("getsockname returned bad Netlink name");
        retval = EINVAL;
        goto error;
    }
    sock->pid = local.nl_pid;
#endif

    *sockp = sock;
    return 0;

error:
    if (retval == 0) {
        retval = errno;
        if (retval == 0) {
            retval = EINVAL;
        }
    }
#ifdef _WIN32
    if (sock->handle != INVALID_HANDLE_VALUE) {
        CloseHandle(sock->handle);
    }
#else
    if (sock->fd >= 0) {
        close(sock->fd);
    }
#endif
    free(sock);
    return retval;
}