Esempio n. 1
0
/* Reserves 'size' bytes of headroom so that they can be later allocated with
 * ofpbuf_push_uninit() without reallocating the ofpbuf. */
void
ofpbuf_reserve(struct ofpbuf *b, size_t size)
{
    ovs_assert(!ofpbuf_size(b));
    ofpbuf_prealloc_tailroom(b, size);
    ofpbuf_set_data(b, (char*)ofpbuf_data(b) + size);
}
Esempio n. 2
0
static int
parse_actions(void)
{
    struct ds in;

    ds_init(&in);
    vlog_set_levels_from_string_assert("odp_util:console:dbg");
    while (!ds_get_test_line(&in, stdin)) {
        struct ofpbuf odp_actions;
        struct ds out;
        int error;

        /* Convert string to OVS DP actions. */
        ofpbuf_init(&odp_actions, 0);
        error = odp_actions_from_string(ds_cstr(&in), NULL, &odp_actions);
        if (error) {
            printf("odp_actions_from_string: error\n");
            goto next;
        }

        /* Convert odp_actions back to string. */
        ds_init(&out);
        format_odp_actions(&out, ofpbuf_data(&odp_actions), ofpbuf_size(&odp_actions));
        puts(ds_cstr(&out));
        ds_destroy(&out);

    next:
        ofpbuf_uninit(&odp_actions);
    }
    ds_destroy(&in);

    return 0;
}
Esempio n. 3
0
/* Reserves 'headroom' bytes at the head and 'tailroom' at the end so that
 * they can be later allocated with ofpbuf_push_uninit() or
 * ofpbuf_put_uninit() without reallocating the ofpbuf. */
void
ofpbuf_reserve_with_tailroom(struct ofpbuf *b, size_t headroom,
                             size_t tailroom)
{
    ovs_assert(!ofpbuf_size(b));
    ofpbuf_prealloc_tailroom(b, headroom + tailroom);
    ofpbuf_set_data(b, (char*)ofpbuf_data(b) + headroom);
}
Esempio n. 4
0
/* Prefixes 'size' bytes to the head end of 'b', reallocating and copying its
 * data if necessary.  Returns a pointer to the first byte of the data's
 * location in the ofpbuf.  The new data is left uninitialized. */
void *
ofpbuf_push_uninit(struct ofpbuf *b, size_t size)
{
    ofpbuf_prealloc_headroom(b, size);
    ofpbuf_set_data(b, (char*)ofpbuf_data(b) - size);
    ofpbuf_set_size(b, ofpbuf_size(b) + size);
    return ofpbuf_data(b);
}
Esempio n. 5
0
File: learn.c Progetto: Milstein/ovs
/* Converts 'learn' into a "struct nx_action_learn" and appends that action to
 * 'ofpacts'. */
void
learn_to_nxast(const struct ofpact_learn *learn, struct ofpbuf *openflow)
{
    const struct ofpact_learn_spec *spec;
    struct nx_action_learn *nal;
    size_t start_ofs;

    start_ofs = ofpbuf_size(openflow);
    nal = ofputil_put_NXAST_LEARN(openflow);
    nal->idle_timeout = htons(learn->idle_timeout);
    nal->hard_timeout = htons(learn->hard_timeout);
    nal->fin_idle_timeout = htons(learn->fin_idle_timeout);
    nal->fin_hard_timeout = htons(learn->fin_hard_timeout);
    nal->priority = htons(learn->priority);
    nal->cookie = htonll(learn->cookie);
    nal->flags = htons(learn->flags);
    nal->table_id = learn->table_id;

    for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec++) {
        put_u16(openflow, spec->n_bits | spec->dst_type | spec->src_type);

        if (spec->src_type == NX_LEARN_SRC_FIELD) {
            put_u32(openflow, spec->src.field->nxm_header);
            put_u16(openflow, spec->src.ofs);
        } else {
            size_t n_dst_bytes = 2 * DIV_ROUND_UP(spec->n_bits, 16);
            uint8_t *bits = ofpbuf_put_zeros(openflow, n_dst_bytes);
            bitwise_copy(&spec->src_imm, sizeof spec->src_imm, 0,
                         bits, n_dst_bytes, 0,
                         spec->n_bits);
        }

        if (spec->dst_type == NX_LEARN_DST_MATCH ||
            spec->dst_type == NX_LEARN_DST_LOAD) {
            put_u32(openflow, spec->dst.field->nxm_header);
            put_u16(openflow, spec->dst.ofs);
        }
    }

    if ((ofpbuf_size(openflow) - start_ofs) % 8) {
        ofpbuf_put_zeros(openflow, 8 - (ofpbuf_size(openflow) - start_ofs) % 8);
    }

    nal = ofpbuf_at_assert(openflow, start_ofs, sizeof *nal);
    nal->len = htons(ofpbuf_size(openflow) - start_ofs);
}
Esempio n. 6
0
/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
 * copying its data if necessary.  Returns a pointer to the first byte of the
 * new data, which is left uninitialized. */
void *
ofpbuf_put_uninit(struct ofpbuf *b, size_t size)
{
    void *p;
    ofpbuf_prealloc_tailroom(b, size);
    p = ofpbuf_tail(b);
    ofpbuf_set_size(b, ofpbuf_size(b) + size);
    return p;
}
Esempio n. 7
0
/* Try connecting and sending a normal hello, which should succeed. */
static void
test_send_plain_hello(int argc OVS_UNUSED, char *argv[])
{
    const char *type = argv[1];
    struct ofpbuf *hello;

    hello = ofpraw_alloc_xid(OFPRAW_OFPT_HELLO, OFP13_VERSION,
                             htonl(0x12345678), 0);
    test_send_hello(type, ofpbuf_data(hello), ofpbuf_size(hello), 0);
    ofpbuf_delete(hello);
}
Esempio n. 8
0
/* Try connecting and sending an echo request instead of a hello, which should
 * fail with EPROTO. */
static void
test_send_echo_hello(int argc OVS_UNUSED, char *argv[])
{
    const char *type = argv[1];
    struct ofpbuf *echo;

    echo = ofpraw_alloc_xid(OFPRAW_OFPT_ECHO_REQUEST, OFP13_VERSION,
                             htonl(0x12345678), 0);
    test_send_hello(type, ofpbuf_data(echo), ofpbuf_size(echo), EPROTO);
    ofpbuf_delete(echo);
}
Esempio n. 9
0
/* Parses as many pairs of hex digits as possible (possibly separated by
 * spaces) from the beginning of 's', appending bytes for their values to 'b'.
 * Returns the first character of 's' that is not the first of a pair of hex
 * digits.  If 'n' is nonnull, stores the number of bytes added to 'b' in
 * '*n'. */
char *
ofpbuf_put_hex(struct ofpbuf *b, const char *s, size_t *n)
{
    size_t initial_size = ofpbuf_size(b);
    for (;;) {
        uint8_t byte;
        bool ok;

        s += strspn(s, " \t\r\n");
        byte = hexits_value(s, 2, &ok);
        if (!ok) {
            if (n) {
                *n = ofpbuf_size(b) - initial_size;
            }
            return CONST_CAST(char *, s);
        }

        ofpbuf_put(b, &byte, 1);
        s += 2;
    }
}
Esempio n. 10
0
/* Try connecting and sending a hello packet that has a bad version, which
 * should fail with EPROTO. */
static void
test_send_invalid_version_hello(int argc OVS_UNUSED, char *argv[])
{
    const char *type = argv[1];
    struct ofpbuf *hello;

    hello = ofpraw_alloc_xid(OFPRAW_OFPT_HELLO, OFP13_VERSION,
                             htonl(0x12345678), 0);
    ((struct ofp_header *) ofpbuf_data(hello))->version = 0;
    test_send_hello(type, ofpbuf_data(hello), ofpbuf_size(hello), EPROTO);
    ofpbuf_delete(hello);
}
Esempio n. 11
0
static void
send_bogus_packet_ins(struct fail_open *fo)
{
    struct ofproto_packet_in pin;
    uint8_t mac[ETH_ADDR_LEN];
    struct ofpbuf b;

    ofpbuf_init(&b, 128);
    eth_addr_nicira_random(mac);
    compose_rarp(&b, mac);

    memset(&pin, 0, sizeof pin);
    pin.up.packet = ofpbuf_data(&b);
    pin.up.packet_len = ofpbuf_size(&b);
    pin.up.reason = OFPR_NO_MATCH;
    pin.up.fmd.in_port = OFPP_LOCAL;
    pin.send_len = ofpbuf_size(&b);
    pin.miss_type = OFPROTO_PACKET_IN_NO_MISS;
    connmgr_send_packet_in(fo->connmgr, &pin);

    ofpbuf_uninit(&b);
}
Esempio n. 12
0
/* Shifts all of the data within the allocated space in 'b' by 'delta' bytes.
 * For example, a 'delta' of 1 would cause each byte of data to move one byte
 * forward (from address 'p' to 'p+1'), and a 'delta' of -1 would cause each
 * byte to move one byte backward (from 'p' to 'p-1'). */
void
ofpbuf_shift(struct ofpbuf *b, int delta)
{
    ovs_assert(delta > 0 ? delta <= ofpbuf_tailroom(b)
               : delta < 0 ? -delta <= ofpbuf_headroom(b)
               : true);

    if (delta != 0) {
        char *dst = (char *) ofpbuf_data(b) + delta;
        memmove(dst, ofpbuf_data(b), ofpbuf_size(b));
        ofpbuf_set_data(b, dst);
    }
}
Esempio n. 13
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);
}
Esempio n. 14
0
/* Try connecting and sending an extra-long hello, which should succeed (since
 * the specification says that implementations must accept and ignore extra
 * data). */
static void
test_send_long_hello(int argc OVS_UNUSED, char *argv[])
{
    const char *type = argv[1];
    struct ofpbuf *hello;
    enum { EXTRA_BYTES = 8 };

    hello = ofpraw_alloc_xid(OFPRAW_OFPT_HELLO, OFP13_VERSION,
                             htonl(0x12345678), EXTRA_BYTES);
    ofpbuf_put_zeros(hello, EXTRA_BYTES);
    ofpmsg_update_length(hello);
    test_send_hello(type, ofpbuf_data(hello), ofpbuf_size(hello), 0);
    ofpbuf_delete(hello);
}
Esempio n. 15
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);
    }
}
Esempio n. 16
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;
}
Esempio n. 17
0
static enum ofperr
nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
                struct match *match,
                ovs_be64 *cookie, ovs_be64 *cookie_mask)
{
    uint8_t *p = NULL;

    if (match_len) {
        p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
        if (!p) {
            VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a "
                        "multiple of 8, is longer than space in message (max "
                        "length %"PRIu32")", match_len, ofpbuf_size(b));
            return OFPERR_OFPBMC_BAD_LEN;
        }
    }

    return nx_pull_raw(p, match_len, strict, match, cookie, cookie_mask);
}
Esempio n. 18
0
/* Creates and returns a new ofpbuf whose data are copied from 'buffer'.   The
 * returned ofpbuf will additionally have 'headroom' bytes of headroom. */
struct ofpbuf *
ofpbuf_clone_with_headroom(const struct ofpbuf *buffer, size_t headroom)
{
    struct ofpbuf *new_buffer;

    new_buffer = ofpbuf_clone_data_with_headroom(ofpbuf_data(buffer),
                                                 ofpbuf_size(buffer),
                                                 headroom);
    if (buffer->frame) {
        uintptr_t data_delta
            = (char *)ofpbuf_data(new_buffer) - (char *)ofpbuf_data(buffer);

        new_buffer->frame = (char *) buffer->frame + data_delta;
    }
    new_buffer->l2_5_ofs = buffer->l2_5_ofs;
    new_buffer->l3_ofs = buffer->l3_ofs;
    new_buffer->l4_ofs = buffer->l4_ofs;

    return new_buffer;
}
Esempio n. 19
0
/* Composes 'fm' so that executing it will implement 'learn' given that the
 * packet being processed has 'flow' as its flow.
 *
 * Uses 'ofpacts' to store the flow mod's actions.  The caller must initialize
 * 'ofpacts' and retains ownership of it.  'fm->ofpacts' will point into the
 * 'ofpacts' buffer.
 *
 * The caller has to actually execute 'fm'. */
void
learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
              struct ofputil_flow_mod *fm, struct ofpbuf *ofpacts)
{
    const struct ofpact_learn_spec *spec;

    match_init_catchall(&fm->match);
    fm->priority = learn->priority;
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    fm->new_cookie = learn->cookie;
    fm->modify_cookie = fm->new_cookie != OVS_BE64_MAX;
    fm->table_id = learn->table_id;
    fm->command = OFPFC_MODIFY_STRICT;
    fm->idle_timeout = learn->idle_timeout;
    fm->hard_timeout = learn->hard_timeout;
    fm->importance = 0;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = 0;
    if (learn->flags & NX_LEARN_F_SEND_FLOW_REM) {
        fm->flags |= OFPUTIL_FF_SEND_FLOW_REM;
    }
    fm->ofpacts = NULL;
    fm->ofpacts_len = 0;
    fm->delete_reason = OFPRR_DELETE;

    if (learn->fin_idle_timeout || learn->fin_hard_timeout) {
        struct ofpact_fin_timeout *oft;

        oft = ofpact_put_FIN_TIMEOUT(ofpacts);
        oft->fin_idle_timeout = learn->fin_idle_timeout;
        oft->fin_hard_timeout = learn->fin_hard_timeout;
    }

    for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec++) {
        struct ofpact_set_field *sf;
        union mf_subvalue value;

        if (spec->src_type == NX_LEARN_SRC_FIELD) {
            mf_read_subfield(&spec->src, flow, &value);
        } else {
            value = spec->src_imm;
        }

        switch (spec->dst_type) {
        case NX_LEARN_DST_MATCH:
            mf_write_subfield(&spec->dst, &value, &fm->match);
            break;

        case NX_LEARN_DST_LOAD:
            sf = ofpact_put_reg_load(ofpacts);
            sf->field = spec->dst.field;
            bitwise_copy(&value, sizeof value, 0,
                         &sf->value, spec->dst.field->n_bytes, spec->dst.ofs,
                         spec->n_bits);
            bitwise_one(&sf->mask, spec->dst.field->n_bytes, spec->dst.ofs,
                        spec->n_bits);
            break;

        case NX_LEARN_DST_OUTPUT:
            if (spec->n_bits <= 16
                || is_all_zeros(value.u8, sizeof value - 2)) {
                ovs_be16 *last_be16 = &value.be16[ARRAY_SIZE(value.be16) - 1];
                ofp_port_t port = u16_to_ofp(ntohs(*last_be16));

                if (ofp_to_u16(port) < ofp_to_u16(OFPP_MAX)
                    || port == OFPP_IN_PORT
                    || port == OFPP_FLOOD
                    || port == OFPP_LOCAL
                    || port == OFPP_ALL) {
                    ofpact_put_OUTPUT(ofpacts)->port = port;
                }
            }
            break;
        }
    }
    ofpact_pad(ofpacts);

    fm->ofpacts = ofpbuf_data(ofpacts);
    fm->ofpacts_len = ofpbuf_size(ofpacts);
}
Esempio n. 20
0
static void
print_netflow(struct ofpbuf *buf)
{
    const struct netflow_v5_header *hdr;
    int i;

    hdr = ofpbuf_try_pull(buf, sizeof *hdr);
    if (!hdr) {
        printf("truncated NetFlow packet header\n");
        return;
    }
    printf("header: v%"PRIu16", "
           "uptime %"PRIu32", "
           "now %"PRIu32".%09"PRIu32", "
           "seq %"PRIu32", "
           "engine %"PRIu8",%"PRIu8,
           ntohs(hdr->version),
           ntohl(hdr->sysuptime),
           ntohl(hdr->unix_secs), ntohl(hdr->unix_nsecs),
           ntohl(hdr->flow_seq),
           hdr->engine_type, hdr->engine_id);
    if (hdr->sampling_interval != htons(0)) {
        printf(", interval %"PRIu16, ntohs(hdr->sampling_interval));
    }
    putchar('\n');

    for (i = 0; i < ntohs(hdr->count); i++) {
        struct netflow_v5_record *rec;

        rec = ofpbuf_try_pull(buf, sizeof *rec);
        if (!rec) {
            printf("truncated NetFlow records\n");
            return;
        }

        printf("seq %"PRIu32": "IP_FMT" > "IP_FMT, ntohl(hdr->flow_seq),
               IP_ARGS(rec->src_addr), IP_ARGS(rec->dst_addr));

        printf(", if %"PRIu16" > %"PRIu16,
               ntohs(rec->input), ntohs(rec->output));

        printf(", %"PRIu32" pkts, %"PRIu32" bytes",
               ntohl(rec->packet_count), ntohl(rec->byte_count));

        switch (rec->ip_proto) {
        case IPPROTO_TCP:
            printf(", TCP %"PRIu16" > %"PRIu16,
                   ntohs(rec->src_port), ntohs(rec->dst_port));
            if (rec->tcp_flags) {
                struct ds s = DS_EMPTY_INITIALIZER;
                packet_format_tcp_flags(&s, rec->tcp_flags);
                printf(" %s", ds_cstr(&s));
                ds_destroy(&s);
            }
            break;

        case IPPROTO_UDP:
            printf(", UDP %"PRIu16" > %"PRIu16,
                   ntohs(rec->src_port), ntohs(rec->dst_port));
            break;

        case IPPROTO_SCTP:
            printf(", SCTP %"PRIu16" > %"PRIu16,
                   ntohs(rec->src_port), ntohs(rec->dst_port));
            break;

        case IPPROTO_ICMP:
            printf(", ICMP %"PRIu16":%"PRIu16,
                   ntohs(rec->dst_port) >> 8,
                   ntohs(rec->dst_port) & 0xff);
            if (rec->src_port != htons(0)) {
                printf(", src_port=%"PRIu16, ntohs(rec->src_port));
            }
            break;

        default:
            printf(", proto %"PRIu8, rec->ip_proto);
            break;
        }

        if (rec->ip_proto != IPPROTO_TCP && rec->tcp_flags != 0) {
            printf(", flags %"PRIx8, rec->tcp_flags);
        }

        if (rec->ip_proto != IPPROTO_TCP &&
            rec->ip_proto != IPPROTO_UDP &&
            rec->ip_proto != IPPROTO_SCTP &&
            rec->ip_proto != IPPROTO_ICMP) {
            if (rec->src_port != htons(0)) {
                printf(", src_port %"PRIu16, ntohs(rec->src_port));
            }
            if (rec->dst_port != htons(0)) {
                printf(", dst_port %"PRIu16, ntohs(rec->dst_port));
            }
        }

        if (rec->ip_tos) {
            printf(", TOS %"PRIx8, rec->ip_tos);
        }

        printf(", time %"PRIu32"...%"PRIu32,
               ntohl(rec->init_time), ntohl(rec->used_time));

        if (rec->nexthop != htonl(0)) {
            printf(", nexthop "IP_FMT, IP_ARGS(rec->nexthop));
        }
        if (rec->src_as != htons(0) || rec->dst_as != htons(0)) {
            printf(", AS %"PRIu16" > %"PRIu16,
                   ntohs(rec->src_as), ntohs(rec->dst_as));
        }
        if (rec->src_mask != 0 || rec->dst_mask != 0) {
            printf(", mask %"PRIu8" > %"PRIu8, rec->src_mask, rec->dst_mask);
        }
        if (rec->pad1) {
            printf(", pad1 %"PRIu8, rec->pad1);
        }
        if (rec->pad[0] || rec->pad[1]) {
            printf(", pad %"PRIu8", %"PRIu8, rec->pad[0], rec->pad[1]);
        }
        putchar('\n');
    }

    if (ofpbuf_size(buf)) {
        printf("%"PRIu32" extra bytes after last record\n", ofpbuf_size(buf));
    }
}
Esempio n. 21
0
static int
parse_filter(char *filter_parse)
{
    struct ds in;
    struct flow flow_filter;
    struct flow_wildcards wc_filter;
    char *error, *filter = NULL;

    vlog_set_levels_from_string_assert("odp_util:console:dbg");
    if (filter_parse && !strncmp(filter_parse, "filter=", 7)) {
        filter = strdup(filter_parse+7);
        memset(&flow_filter, 0, sizeof(flow_filter));
        memset(&wc_filter, 0, sizeof(wc_filter));

        error = parse_ofp_exact_flow(&flow_filter, &wc_filter.masks, filter,
                                     NULL);
        if (error) {
            ovs_fatal(0, "Failed to parse filter (%s)", error);
        }
    } else {
        ovs_fatal(0, "No filter to parse.");
    }

    ds_init(&in);
    while (!ds_get_test_line(&in, stdin)) {
        struct ofpbuf odp_key;
        struct ofpbuf odp_mask;
        struct ds out;
        int error;

        /* Convert string to OVS DP key. */
        ofpbuf_init(&odp_key, 0);
        ofpbuf_init(&odp_mask, 0);
        error = odp_flow_from_string(ds_cstr(&in), NULL,
                                     &odp_key, &odp_mask);
        if (error) {
            printf("odp_flow_from_string: error\n");
            goto next;
        }

        if (filter) {
            struct flow flow;
            struct flow_wildcards wc;
            struct match match, match_filter;
            struct minimatch minimatch;

            odp_flow_key_to_flow(ofpbuf_data(&odp_key), ofpbuf_size(&odp_key), &flow);
            odp_flow_key_to_mask(ofpbuf_data(&odp_mask), ofpbuf_size(&odp_mask), &wc.masks,
                                 &flow);
            match_init(&match, &flow, &wc);

            match_init(&match_filter, &flow_filter, &wc);
            match_init(&match_filter, &match_filter.flow, &wc_filter);
            minimatch_init(&minimatch, &match_filter);

            if (!minimatch_matches_flow(&minimatch, &match.flow)) {
                minimatch_destroy(&minimatch);
                goto next;
            }
            minimatch_destroy(&minimatch);
        }
        /* Convert odp_key to string. */
        ds_init(&out);
        odp_flow_format(ofpbuf_data(&odp_key), ofpbuf_size(&odp_key),
                        ofpbuf_data(&odp_mask), ofpbuf_size(&odp_mask), NULL, &out, false);
        puts(ds_cstr(&out));
        ds_destroy(&out);

    next:
        ofpbuf_uninit(&odp_key);
        ofpbuf_uninit(&odp_mask);
    }
    ds_destroy(&in);

    free(filter);
    return 0;
}
Esempio n. 22
0
static int
parse_keys(bool wc_keys)
{
    int exit_code = 0;
    struct ds in;

    ds_init(&in);
    vlog_set_levels_from_string_assert("odp_util:console:dbg");
    while (!ds_get_test_line(&in, stdin)) {
        enum odp_key_fitness fitness;
        struct ofpbuf odp_key;
        struct ofpbuf odp_mask;
        struct flow flow;
        struct ds out;
        int error;

        /* Convert string to OVS DP key. */
        ofpbuf_init(&odp_key, 0);
        ofpbuf_init(&odp_mask, 0);
        error = odp_flow_from_string(ds_cstr(&in), NULL,
                                     &odp_key, &odp_mask);
        if (error) {
            printf("odp_flow_from_string: error\n");
            goto next;
        }

        if (!wc_keys) {
            /* Convert odp_key to flow. */
            fitness = odp_flow_key_to_flow(ofpbuf_data(&odp_key), ofpbuf_size(&odp_key), &flow);
            switch (fitness) {
                case ODP_FIT_PERFECT:
                    break;

                case ODP_FIT_TOO_LITTLE:
                    printf("ODP_FIT_TOO_LITTLE: ");
                    break;

                case ODP_FIT_TOO_MUCH:
                    printf("ODP_FIT_TOO_MUCH: ");
                    break;

                case ODP_FIT_ERROR:
                    printf("odp_flow_key_to_flow: error\n");
                    goto next;
            }
            /* Convert cls_rule back to odp_key. */
            ofpbuf_uninit(&odp_key);
            ofpbuf_init(&odp_key, 0);
            odp_flow_key_from_flow(&odp_key, &flow, NULL,
                                   flow.in_port.odp_port);

            if (ofpbuf_size(&odp_key) > ODPUTIL_FLOW_KEY_BYTES) {
                printf ("too long: %"PRIu32" > %d\n",
                        ofpbuf_size(&odp_key), ODPUTIL_FLOW_KEY_BYTES);
                exit_code = 1;
            }
        }

        /* Convert odp_key to string. */
        ds_init(&out);
        if (wc_keys) {
            odp_flow_format(ofpbuf_data(&odp_key), ofpbuf_size(&odp_key),
                            ofpbuf_data(&odp_mask), ofpbuf_size(&odp_mask), NULL, &out, false);
        } else {
            odp_flow_key_format(ofpbuf_data(&odp_key), ofpbuf_size(&odp_key), &out);
        }
        puts(ds_cstr(&out));
        ds_destroy(&out);

    next:
        ofpbuf_uninit(&odp_key);
    }
    ds_destroy(&in);

    return exit_code;
}
Esempio n. 23
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;
}
Esempio n. 24
0
static int
nl_sock_transact_multiple__(struct nl_sock *sock,
                            struct nl_transaction **transactions, size_t n,
                            size_t *done)
{
    uint64_t tmp_reply_stub[1024 / 8];
    struct nl_transaction tmp_txn;
    struct ofpbuf tmp_reply;

    uint32_t base_seq;
    struct iovec iovs[MAX_IOVS];
    struct msghdr msg;
    int error;
    int i;

    base_seq = nl_sock_allocate_seq(sock, n);
    *done = 0;
    for (i = 0; i < n; i++) {
        struct nl_transaction *txn = transactions[i];
        struct nlmsghdr *nlmsg = nl_msg_nlmsghdr(txn->request);

        nlmsg->nlmsg_len = ofpbuf_size(txn->request);
        nlmsg->nlmsg_seq = base_seq + i;
        nlmsg->nlmsg_pid = sock->pid;

        iovs[i].iov_base = ofpbuf_data(txn->request);
        iovs[i].iov_len = ofpbuf_size(txn->request);
    }

    memset(&msg, 0, sizeof msg);
    msg.msg_iov = iovs;
    msg.msg_iovlen = n;
    do {
#ifdef _WIN32
    DWORD last_error = 0;
    bool result = FALSE;
    for (i = 0; i < n; i++) {
        result = WriteFile((HANDLE)sock->handle, iovs[i].iov_base, iovs[i].iov_len,
                           &error, NULL);
        last_error = GetLastError();
        if (last_error != ERROR_SUCCESS && !result) {
            error = EAGAIN;
            errno = EAGAIN;
        } else {
            error = 0;
        }
    }
#else
        error = sendmsg(sock->fd, &msg, 0) < 0 ? errno : 0;
#endif
    } while (error == EINTR);

    for (i = 0; i < n; i++) {
        struct nl_transaction *txn = transactions[i];

        log_nlmsg(__func__, error, ofpbuf_data(txn->request), ofpbuf_size(txn->request),
                  sock->protocol);
    }
    if (!error) {
        COVERAGE_ADD(netlink_sent, n);
    }

    if (error) {
        return error;
    }

    ofpbuf_use_stub(&tmp_reply, tmp_reply_stub, sizeof tmp_reply_stub);
    tmp_txn.request = NULL;
    tmp_txn.reply = &tmp_reply;
    tmp_txn.error = 0;
    while (n > 0) {
        struct nl_transaction *buf_txn, *txn;
        uint32_t seq;

        /* Find a transaction whose buffer we can use for receiving a reply.
         * If no such transaction is left, use tmp_txn. */
        buf_txn = &tmp_txn;
        for (i = 0; i < n; i++) {
            if (transactions[i]->reply) {
                buf_txn = transactions[i];
                break;
            }
        }

        /* Receive a reply. */
        error = nl_sock_recv__(sock, buf_txn->reply, false);
        if (error) {
            if (error == EAGAIN) {
                nl_sock_record_errors__(transactions, n, 0);
                *done += n;
                error = 0;
            }
            break;
        }

        /* Match the reply up with a transaction. */
        seq = nl_msg_nlmsghdr(buf_txn->reply)->nlmsg_seq;
        if (seq < base_seq || seq >= base_seq + n) {
            VLOG_DBG_RL(&rl, "ignoring unexpected seq %#"PRIx32, seq);
            continue;
        }
        i = seq - base_seq;
        txn = transactions[i];

        /* Fill in the results for 'txn'. */
        if (nl_msg_nlmsgerr(buf_txn->reply, &txn->error)) {
            if (txn->reply) {
                ofpbuf_clear(txn->reply);
            }
            if (txn->error) {
                VLOG_DBG_RL(&rl, "received NAK error=%d (%s)",
                            error, ovs_strerror(txn->error));
            }
        } else {
            txn->error = 0;
            if (txn->reply && txn != buf_txn) {
                /* Swap buffers. */
                struct ofpbuf *reply = buf_txn->reply;
                buf_txn->reply = txn->reply;
                txn->reply = reply;
            }
        }

        /* Fill in the results for transactions before 'txn'.  (We have to do
         * this after the results for 'txn' itself because of the buffer swap
         * above.) */
        nl_sock_record_errors__(transactions, i, 0);

        /* Advance. */
        *done += i + 1;
        transactions += i + 1;
        n -= i + 1;
        base_seq += i + 1;
    }
    ofpbuf_uninit(&tmp_reply);

    return error;
}
Esempio n. 25
0
File: learn.c Progetto: Milstein/ovs
/* Composes 'fm' so that executing it will implement 'learn' given that the
 * packet being processed has 'flow' as its flow.
 *
 * Uses 'ofpacts' to store the flow mod's actions.  The caller must initialize
 * 'ofpacts' and retains ownership of it.  'fm->ofpacts' will point into the
 * 'ofpacts' buffer.
 *
 * The caller has to actually execute 'fm'. */
void
learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
              struct ofputil_flow_mod *fm, struct ofpbuf *ofpacts)
{
    const struct ofpact_learn_spec *spec;

    match_init_catchall(&fm->match);
    fm->priority = learn->priority;
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    fm->new_cookie = htonll(learn->cookie);
    fm->modify_cookie = fm->new_cookie != OVS_BE64_MAX;
    fm->table_id = learn->table_id;
    fm->command = OFPFC_MODIFY_STRICT;
    fm->idle_timeout = learn->idle_timeout;
    fm->hard_timeout = learn->hard_timeout;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = learn->flags;
    fm->ofpacts = NULL;
    fm->ofpacts_len = 0;

    if (learn->fin_idle_timeout || learn->fin_hard_timeout) {
        struct ofpact_fin_timeout *oft;

        oft = ofpact_put_FIN_TIMEOUT(ofpacts);
        oft->fin_idle_timeout = learn->fin_idle_timeout;
        oft->fin_hard_timeout = learn->fin_hard_timeout;
    }

    for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec++) {
        union mf_subvalue value;
        int chunk, ofs;

        if (spec->src_type == NX_LEARN_SRC_FIELD) {
            mf_read_subfield(&spec->src, flow, &value);
        } else {
            value = spec->src_imm;
        }

        switch (spec->dst_type) {
        case NX_LEARN_DST_MATCH:
            mf_write_subfield(&spec->dst, &value, &fm->match);
            break;

        case NX_LEARN_DST_LOAD:
            for (ofs = 0; ofs < spec->n_bits; ofs += chunk) {
                struct ofpact_reg_load *load;

                chunk = MIN(spec->n_bits - ofs, 64);

                load = ofpact_put_REG_LOAD(ofpacts);
                load->dst.field = spec->dst.field;
                load->dst.ofs = spec->dst.ofs + ofs;
                load->dst.n_bits = chunk;
                bitwise_copy(&value, sizeof value, ofs,
                             &load->subvalue, sizeof load->subvalue, 0,
                             chunk);
            }
            break;

        case NX_LEARN_DST_OUTPUT:
            if (spec->n_bits <= 16
                || is_all_zeros(value.u8, sizeof value - 2)) {
                ofp_port_t port = u16_to_ofp(ntohs(value.be16[7]));

                if (ofp_to_u16(port) < ofp_to_u16(OFPP_MAX)
                    || port == OFPP_IN_PORT
                    || port == OFPP_FLOOD
                    || port == OFPP_LOCAL
                    || port == OFPP_ALL) {
                    ofpact_put_OUTPUT(ofpacts)->port = port;
                }
            }
            break;
        }
    }
    ofpact_pad(ofpacts);

    fm->ofpacts = ofpbuf_data(ofpacts);
    fm->ofpacts_len = ofpbuf_size(ofpacts);
}