예제 #1
0
/* Reallocates 'b' so that it has exactly 'new_headroom' and 'new_tailroom'
 * bytes of headroom and tailroom, respectively. */
static void
ofpbuf_resize__(struct ofpbuf *b, size_t new_headroom, size_t new_tailroom)
{
    void *new_base, *new_data;
    size_t new_allocated;

    new_allocated = new_headroom + ofpbuf_size(b) + new_tailroom;

    switch (b->source) {
    case OFPBUF_DPDK:
        OVS_NOT_REACHED();

    case OFPBUF_MALLOC:
        if (new_headroom == ofpbuf_headroom(b)) {
            new_base = xrealloc(ofpbuf_base(b), new_allocated);
        } else {
            new_base = xmalloc(new_allocated);
            ofpbuf_copy__(b, new_base, new_headroom, new_tailroom);
            free(ofpbuf_base(b));
        }
        break;

    case OFPBUF_STACK:
        OVS_NOT_REACHED();

    case OFPBUF_STUB:
        b->source = OFPBUF_MALLOC;
        new_base = xmalloc(new_allocated);
        ofpbuf_copy__(b, new_base, new_headroom, new_tailroom);
        break;

    default:
        OVS_NOT_REACHED();
    }

    b->allocated = new_allocated;
    ofpbuf_set_base(b, new_base);

    new_data = (char *) new_base + new_headroom;
    if (ofpbuf_data(b) != new_data) {
        if (b->frame) {
            uintptr_t data_delta = (char *) new_data - (char *) ofpbuf_data(b);

            b->frame = (char *) b->frame + data_delta;
        }
        ofpbuf_set_data(b, new_data);
    }
}
예제 #2
0
/* Returns the data in 'b' as a block of malloc()'d memory and frees the buffer
 * within 'b'.  (If 'b' itself was dynamically allocated, e.g. with
 * ofpbuf_new(), then it should still be freed with, e.g., ofpbuf_delete().) */
void *
ofpbuf_steal_data(struct ofpbuf *b)
{
    void *p;
    ovs_assert(b->source != OFPBUF_DPDK);

    if (b->source == OFPBUF_MALLOC && ofpbuf_data(b) == ofpbuf_base(b)) {
        p = ofpbuf_data(b);
    } else {
        p = xmemdup(ofpbuf_data(b), ofpbuf_size(b));
        if (b->source == OFPBUF_MALLOC) {
            free(ofpbuf_base(b));
        }
    }
    ofpbuf_set_base(b, NULL);
    ofpbuf_set_data(b, NULL);
    return p;
}
예제 #3
0
static void
ofpbuf_copy__(struct ofpbuf *b, uint8_t *new_base,
              size_t new_headroom, size_t new_tailroom)
{
    const uint8_t *old_base = ofpbuf_base(b);
    size_t old_headroom = ofpbuf_headroom(b);
    size_t old_tailroom = ofpbuf_tailroom(b);
    size_t copy_headroom = MIN(old_headroom, new_headroom);
    size_t copy_tailroom = MIN(old_tailroom, new_tailroom);

    memcpy(&new_base[new_headroom - copy_headroom],
           &old_base[old_headroom - copy_headroom],
           copy_headroom + ofpbuf_size(b) + copy_tailroom);
}
예제 #4
0
/* Frees memory that 'b' points to. */
void
ofpbuf_uninit(struct ofpbuf *b)
{
    if (b) {
        if (b->source == OFPBUF_MALLOC) {
            free(ofpbuf_base(b));
        } else if (b->source == OFPBUF_DPDK) {
#ifdef DPDK_NETDEV
            /* If this ofpbuf was allocated by DPDK it must have been
             * created as a dpif_packet */
            free_dpdk_buf((struct dpif_packet*) b);
#else
            ovs_assert(b->source != OFPBUF_DPDK);
#endif
        }
    }
}
예제 #5
0
static int
nl_sock_recv__(struct nl_sock *sock, struct ofpbuf *buf, bool wait)
{
    /* We can't accurately predict the size of the data to be received.  The
     * caller is supposed to have allocated enough space in 'buf' to handle the
     * "typical" case.  To handle exceptions, we make available enough space in
     * 'tail' to allow Netlink messages to be up to 64 kB long (a reasonable
     * figure since that's the maximum length of a Netlink attribute). */
    struct nlmsghdr *nlmsghdr;
#ifdef _WIN32
#define MAX_STACK_LENGTH 81920
    uint8_t tail[MAX_STACK_LENGTH];
#else
    uint8_t tail[65536];
#endif
    struct iovec iov[2];
    struct msghdr msg;
    ssize_t retval;
    int error;

    ovs_assert(buf->allocated >= sizeof *nlmsghdr);
    ofpbuf_clear(buf);

    iov[0].iov_base = ofpbuf_base(buf);
    iov[0].iov_len = buf->allocated;
    iov[1].iov_base = tail;
    iov[1].iov_len = sizeof tail;

    memset(&msg, 0, sizeof msg);
    msg.msg_iov = iov;
    msg.msg_iovlen = 2;

    /* Receive a Netlink message from the kernel.
     *
     * This works around a kernel bug in which the kernel returns an error code
     * as if it were the number of bytes read.  It doesn't actually modify
     * anything in the receive buffer in that case, so we can initialize the
     * Netlink header with an impossible message length and then, upon success,
     * check whether it changed. */
    nlmsghdr = ofpbuf_base(buf);
    do {
        nlmsghdr->nlmsg_len = UINT32_MAX;
#ifdef _WIN32
        boolean result = false;
        DWORD last_error = 0;
        result = ReadFile(sock->handle, tail, MAX_STACK_LENGTH, &retval, NULL);
        last_error = GetLastError();
        if (last_error != ERROR_SUCCESS && !result) {
            retval = -1;
            errno = EAGAIN;
        } else {
            ofpbuf_put(buf, tail, retval);
        }
#else
        retval = recvmsg(sock->fd, &msg, wait ? 0 : MSG_DONTWAIT);
#endif
        error = (retval < 0 ? errno
                 : retval == 0 ? ECONNRESET /* not possible? */
                 : nlmsghdr->nlmsg_len != UINT32_MAX ? 0
                 : retval);
    } while (error == EINTR);
    if (error) {
        if (error == ENOBUFS) {
            /* Socket receive buffer overflow dropped one or more messages that
             * the kernel tried to send to us. */
            COVERAGE_INC(netlink_overflow);
        }
        return error;
    }

    if (msg.msg_flags & MSG_TRUNC) {
        VLOG_ERR_RL(&rl, "truncated message (longer than %"PRIuSIZE" bytes)",
                    sizeof tail);
        return E2BIG;
    }

    if (retval < sizeof *nlmsghdr
        || nlmsghdr->nlmsg_len < sizeof *nlmsghdr
        || nlmsghdr->nlmsg_len > retval) {
        VLOG_ERR_RL(&rl, "received invalid nlmsg (%"PRIuSIZE" bytes < %"PRIuSIZE")",
                    retval, sizeof *nlmsghdr);
        return EPROTO;
    }
#ifndef _WIN32
    ofpbuf_set_size(buf, MIN(retval, buf->allocated));
    if (retval > buf->allocated) {
        COVERAGE_INC(netlink_recv_jumbo);
        ofpbuf_put(buf, tail, retval - buf->allocated);
    }
#endif

    log_nlmsg(__func__, 0, ofpbuf_data(buf), ofpbuf_size(buf), sock->protocol);
    COVERAGE_INC(netlink_received);

    return 0;
}