Beispiel #1
0
static int
lookup_brc_multicast_group(int *multicast_group)
{
    struct nl_sock *sock;
    struct ofpbuf request, *reply;
    struct nlattr *attrs[ARRAY_SIZE(brc_multicast_policy)];
    int retval;

    retval = nl_sock_create(NETLINK_GENERIC, &sock);
    if (retval) {
        return retval;
    }
    ofpbuf_init(&request, 0);
    nl_msg_put_genlmsghdr(&request, 0, brc_family,
                          NLM_F_REQUEST, BRC_GENL_C_QUERY_MC, 1);
    retval = nl_sock_transact(sock, &request, &reply);
    ofpbuf_uninit(&request);
    if (retval) {
        nl_sock_destroy(sock);
        return retval;
    }
    if (!nl_policy_parse(reply, NLMSG_HDRLEN + GENL_HDRLEN,
                         brc_multicast_policy, attrs,
                         ARRAY_SIZE(brc_multicast_policy))) {
        nl_sock_destroy(sock);
        ofpbuf_delete(reply);
        return EPROTO;
    }
    *multicast_group = nl_attr_get_u32(attrs[BRC_GENL_A_MC_GROUP]);
    nl_sock_destroy(sock);
    ofpbuf_delete(reply);

    return 0;
}
Beispiel #2
0
/* Drop a packet from the longest queue in 'rl'. */
static void
drop_packet(struct rate_limiter *rl)
{
    struct ofp_queue *longest;  /* Queue currently selected as longest. */
    int n_longest;              /* # of queues of same length as 'longest'. */
    struct ofp_queue *q;

    longest = &rl->queues[0];
    n_longest = 1;
    for (q = &rl->queues[0]; q < &rl->queues[OFPP_MAX]; q++) {
        if (longest->n < q->n) {
            longest = q;
            n_longest = 1;
        } else if (longest->n == q->n) {
            n_longest++;

            /* Randomly select one of the longest queues, with a uniform
             * distribution (Knuth algorithm 3.4.2R). */
            if (!random_range(n_longest)) {
                longest = q;
            }
        }
    }

    /* FIXME: do we want to pop the tail instead? */
    ofpbuf_delete(queue_pop_head(longest));
    rl->n_queued--;
}
Beispiel #3
0
static void
send_bpdu(struct ofpbuf *pkt, int port_no, void *b_)
{
    struct bridge *b = b_;
    struct lan *lan;

    assert(port_no < b->n_ports);
    lan = b->ports[port_no];
    if (lan) {
        const void *data = pkt->l3;
        size_t size = (char *) ofpbuf_tail(pkt) - (char *) data;
        int i;

        for (i = 0; i < lan->n_conns; i++) {
            struct lan_conn *conn = &lan->conns[i];
            if (conn->bridge != b || conn->port_no != port_no) {
                struct bridge *dst = conn->bridge;
                struct bpdu *bpdu = &dst->rxq[dst->rxq_head++ % RXQ_SIZE];
                assert(dst->rxq_head - dst->rxq_tail <= RXQ_SIZE);
                bpdu->data = xmemdup(data, size);
                bpdu->size = size;
                bpdu->port_no = conn->port_no;
            }
        }
    }
    ofpbuf_delete(pkt);
}
/* Sends the given 'command' to datapath 'dp', related to the local datapath
 * numbered 'dp_idx'.  If 'arg' is nonnull, adds it to the command as the
 * datapath or port name attribute depending on the requested operation.  
 * Returns 0 if successful, otherwise a positive errno value. */
static int
send_mgmt_command(struct dpif *dp, int dp_idx, int command, const char *arg)
{
    struct ofpbuf request, *reply;
    int retval;

    ofpbuf_init(&request, 0);
    nl_msg_put_genlmsghdr(&request, dp->sock, 32, openflow_family,
                          NLM_F_REQUEST | NLM_F_ACK, command, 1);
    if (dp_idx != -1) {
        nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp_idx);
    }
    if (arg) {
        if ((command == DP_GENL_C_ADD_DP) || (command == DP_GENL_C_DEL_DP)) {
            nl_msg_put_string(&request, DP_GENL_A_DP_NAME, arg);
        } else {
            nl_msg_put_string(&request, DP_GENL_A_PORTNAME, arg);
        }
    }
    retval = nl_sock_transact(dp->sock, &request, &reply);
    ofpbuf_uninit(&request);
    ofpbuf_delete(reply);

    return retval;
}
Beispiel #5
0
static int
netdev_windows_system_construct(struct netdev *netdev_)
{
    struct netdev_windows *netdev = netdev_windows_cast(netdev_);
    struct netdev_windows_netdev_info info;
    struct ofpbuf *buf;
    int ret;

    /* Query the attributes and runtime status of the netdev. */
    ret = query_netdev(netdev_get_name(&netdev->up), &info, &buf);
    if (ret) {
        return ret;
    }
    ofpbuf_delete(buf);

    netdev->change_seq = 1;
    netdev->dev_type = info.ovs_type;
    netdev->port_no = info.port_no;

    netdev->mac = info.mac_address;
    netdev->cache_valid = VALID_ETHERADDR;
    netdev->ifindex = -EOPNOTSUPP;

    netdev->mtu = info.mtu;
    netdev->cache_valid |= VALID_MTU;

    netdev->ifi_flags = dp_to_netdev_ifi_flags(info.ifi_flags);
    netdev->cache_valid |= VALID_IFFLAG;

    VLOG_DBG("construct device %s, ovs_type: %u.",
             netdev_get_name(&netdev->up), info.ovs_type);
    return 0;
}
Beispiel #6
0
int
main(int argc OVS_UNUSED, char *argv[])
{
    struct ofp_match expected_match;
    FILE *flows, *pcap;
    int retval;
    int n = 0, errors = 0;

    set_program_name(argv[0]);

    flows = stdin;
    pcap = fdopen(3, "rb");
    if (!pcap) {
        ovs_fatal(errno, "failed to open fd 3 for reading");
    }

    retval = pcap_read_header(pcap);
    if (retval) {
        ovs_fatal(retval > 0 ? retval : 0, "reading pcap header failed");
    }

    while (fread(&expected_match, sizeof expected_match, 1, flows)) {
        struct ofpbuf *packet;
        struct ofp_match extracted_match;
        struct cls_rule rule;
        struct flow flow;

        n++;

        retval = pcap_read(pcap, &packet);
        if (retval == EOF) {
            ovs_fatal(0, "unexpected end of file reading pcap file");
        } else if (retval) {
            ovs_fatal(retval, "error reading pcap file");
        }

        flow_extract(packet, 0, 1, &flow);
        cls_rule_init_exact(&flow, 0, &rule);
        ofputil_cls_rule_to_match(&rule, &extracted_match);

        if (memcmp(&expected_match, &extracted_match, sizeof expected_match)) {
            char *exp_s = ofp_match_to_string(&expected_match, 2);
            char *got_s = ofp_match_to_string(&extracted_match, 2);
            errors++;
            printf("mismatch on packet #%d (1-based).\n", n);
            printf("Packet:\n");
            ofp_print_packet(stdout, packet->data, packet->size, packet->size);
            ovs_hex_dump(stdout, packet->data, packet->size, 0, true);
            printf("Expected flow:\n%s\n", exp_s);
            printf("Actually extracted flow:\n%s\n", got_s);
            printf("\n");
            free(exp_s);
            free(got_s);
        }

        ofpbuf_delete(packet);
    }
    printf("checked %d packets, %d errors\n", n, errors);
    return errors != 0;
}
Beispiel #7
0
/* Takes care of necessary 'sw' activity, except for receiving packets (which
 * the caller must do). */
void
lswitch_run(struct lswitch *sw)
{
    int i;

    rconn_run(sw->rconn);

    if (sw->state == S_CONNECTING) {
        if (rconn_get_version(sw->rconn) != -1) {
            lswitch_handshake(sw);
            sw->state = S_FEATURES_REPLY;
        }
        return;
    }

    for (i = 0; i < 50; i++) {
        struct ofpbuf *msg;

        msg = rconn_recv(sw->rconn);
        if (!msg) {
            break;
        }

        lswitch_process_packet(sw, msg);
        ofpbuf_delete(msg);
    }
}
Beispiel #8
0
static void
stream_clear_txbuf(struct stream_vconn *s)
{
    ofpbuf_delete(s->txbuf);
    s->txbuf = NULL;
    s->tx_waiter = NULL;
}
static void
ssl_clear_txbuf(struct ssl_vconn *sslv)
{
    ofpbuf_delete(sslv->txbuf);
    sslv->txbuf = NULL;
    sslv->tx_waiter = NULL;
}
Beispiel #10
0
static int
stream_send(struct vconn *vconn, struct ofpbuf *buffer)
{
    struct stream_vconn *s = stream_vconn_cast(vconn);
    ssize_t retval;

    if (s->txbuf) {
        return EAGAIN;
    }

    retval = write(s->fd, buffer->data, buffer->size);
    if (retval == buffer->size) {
        ofpbuf_delete(buffer);
        return 0;
    } else if (retval >= 0 || errno == EAGAIN) {
        leak_checker_claim(buffer);
        s->txbuf = buffer;
        if (retval > 0) {
            ofpbuf_pull(buffer, retval);
        }
        s->tx_waiter = poll_fd_callback(s->fd, POLLOUT, stream_do_tx, vconn);
        return 0;
    } else {
        return errno;
    }
}
Beispiel #11
0
/* Performs periodic maintenance on 'rpc', such as flushing output buffers. */
void
jsonrpc_run(struct jsonrpc *rpc)
{
    if (rpc->status) {
        return;
    }

    stream_run(rpc->stream);
    while (!list_is_empty(&rpc->output)) {
        struct ofpbuf *buf = ofpbuf_from_list(rpc->output.next);
        int retval;

        retval = stream_send(rpc->stream, buf->data, buf->size);
        if (retval >= 0) {
            rpc->backlog -= retval;
            ofpbuf_pull(buf, retval);
            if (!buf->size) {
                list_remove(&buf->list_node);
                rpc->output_count--;
                ofpbuf_delete(buf);
            }
        } else {
            if (retval != -EAGAIN) {
                VLOG_WARN_RL(&rl, "%s: send error: %s",
                             rpc->name, ovs_strerror(-retval));
                jsonrpc_error(rpc, -retval);
            }
            break;
        }
    }
}
Beispiel #12
0
size_t
ofl_structs_match_pack(struct ofl_match_header *src, struct ofp_match *dst, uint8_t* oxm_fields, enum byte_order order, struct ofl_exp *exp) {
    switch (src->type) {
        case (OFPMT_OXM): {
            struct ofl_match *m = (struct ofl_match *)src;
            struct ofpbuf *b = ofpbuf_new(0);
            int oxm_len;
            dst->type = htons(m->header.type);
            oxm_fields = (uint8_t*) &dst->oxm_fields;
            dst->length = htons(sizeof(struct ofp_match));
            if (src->length){
                if (order == HOST_ORDER)
                    oxm_len = oxm_put_match(b, m);
                else oxm_len = oxm_put_packet_match(b,m);
                memcpy(oxm_fields, (uint8_t*) ofpbuf_pull(b,oxm_len), oxm_len);
                dst->length = htons(oxm_len + ((sizeof(struct ofp_match )-4)));
                ofpbuf_delete(b);
                return ntohs(dst->length);
            }
            else return 0;
        }
        default: {
            if (exp == NULL || exp->match == NULL || exp->match->pack == NULL) {
                OFL_LOG_WARN(LOG_MODULE, "Trying to pack experimenter match, but no callback was given.");
                return -1;
            }
            return exp->match->pack(src, dst);
        }
    }
}
Beispiel #13
0
/* Removes each of the "struct ofpbuf"s on 'list' from the list and frees
 * them.  */
void
ofpbuf_list_delete(struct ovs_list *list)
{
    struct ofpbuf *b;

    LIST_FOR_EACH_POP (b, list_node, list) {
        ofpbuf_delete(b);
    }
Beispiel #14
0
/* Removes each of the "struct ofpbuf"s on 'list' from the list and frees
 * them.  */
void
ofpbuf_list_delete(struct list *list)
{
    struct ofpbuf *b, *next;

    LIST_FOR_EACH_SAFE (b, next, list_node, list) {
        list_remove(&b->list_node);
        ofpbuf_delete(b);
    }
Beispiel #15
0
static void
stream_close(struct vconn *vconn)
{
    struct stream_vconn *s = stream_vconn_cast(vconn);
    poll_cancel(s->tx_waiter);
    stream_clear_txbuf(s);
    ofpbuf_delete(s->rxbuf);
    close(s->fd);
    free(s);
}
static void
ssl_close(struct vconn *vconn)
{
    struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
    poll_cancel(sslv->tx_waiter);
    ssl_clear_txbuf(sslv);
    ofpbuf_delete(sslv->rxbuf);
    SSL_free(sslv->ssl);
    close(sslv->fd);
    free(sslv);
}
Beispiel #17
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);
}
Beispiel #18
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);
}
Beispiel #19
0
/* Try connecting and sending an echo request instead of a hello, which should
 * fail with EPROTO. */
static void
test_send_echo_hello(struct ovs_cmdl_context *ctx)
{
    const char *type = ctx->argv[1];
    struct ofpbuf *echo;

    echo = ofpraw_alloc_xid(OFPRAW_OFPT_ECHO_REQUEST, OFP13_VERSION,
                             htonl(0x12345678), 0);
    test_send_hello(type, echo->data, echo->size, EPROTO);
    ofpbuf_delete(echo);
}
Beispiel #20
0
/* Try connecting and sending a normal hello, which should succeed. */
static void
test_send_plain_hello(struct ovs_cmdl_context *ctx)
{
    const char *type = ctx->argv[1];
    struct ofpbuf *hello;

    hello = ofpraw_alloc_xid(OFPRAW_OFPT_HELLO, OFP13_VERSION,
                             htonl(0x12345678), 0);
    test_send_hello(type, hello->data, hello->size, 0);
    ofpbuf_delete(hello);
}
/* Looks up the Netlink multicast group and datapath index of a datapath
 * by either the datapath index or name.  If 'dp_idx' points to a value 
 * of '-1', then 'dp_name' is used to lookup the datapath.  If successful, 
 * stores the multicast group in '*multicast_group' and the index in
 * '*dp_idx' and returns 0. Otherwise, returns a positive errno value. */
static int
query_datapath(int *dp_idx, int *multicast_group, const char *dp_name)
{
    struct nl_sock *sock;
    struct ofpbuf request, *reply;
    struct nlattr *attrs[ARRAY_SIZE(openflow_multicast_policy)];
    int retval;

    retval = nl_sock_create(NETLINK_GENERIC, 0, 0, 0, &sock);
    if (retval) {
        return retval;
    }
    ofpbuf_init(&request, 0);
    nl_msg_put_genlmsghdr(&request, sock, 0, openflow_family, NLM_F_REQUEST,
                          DP_GENL_C_QUERY_DP, 1);
    if (*dp_idx != -1) {
        nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, *dp_idx);
    }
    if (dp_name) {
        nl_msg_put_string(&request, DP_GENL_A_DP_NAME, dp_name);
    }
    retval = nl_sock_transact(sock, &request, &reply);
    ofpbuf_uninit(&request);
    if (retval) {
        nl_sock_destroy(sock);
        return retval;
    }
    if (!nl_policy_parse(reply, NLMSG_HDRLEN + GENL_HDRLEN,
                         openflow_multicast_policy, attrs,
                         ARRAY_SIZE(openflow_multicast_policy))) {
        nl_sock_destroy(sock);
        ofpbuf_delete(reply);
        return EPROTO;
    }
    *dp_idx = nl_attr_get_u32(attrs[DP_GENL_A_DP_IDX]);
    *multicast_group = nl_attr_get_u32(attrs[DP_GENL_A_MC_GROUP]);
    nl_sock_destroy(sock);
    ofpbuf_delete(reply);

    return 0;
}
Beispiel #22
0
/* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'.  The
 * caller must free '*packetp'.  On success, returns NULL.  On failure, returns
 * an error message and stores NULL in '*packetp'. */
const char *
eth_from_hex(const char *hex, struct ofpbuf **packetp)
{
    struct ofpbuf *packet;

    packet = *packetp = ofpbuf_new(strlen(hex) / 2);

    if (ofpbuf_put_hex(packet, hex, NULL)[0] != '\0') {
        ofpbuf_delete(packet);
        *packetp = NULL;
        return "Trailing garbage in packet data";
    }

    if (packet->size < ETH_HEADER_LEN) {
        ofpbuf_delete(packet);
        *packetp = NULL;
        return "Packet data too short for Ethernet";
    }

    return NULL;
}
Beispiel #23
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);
}
Beispiel #24
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(struct ovs_cmdl_context *ctx)
{
    const char *type = ctx->argv[1];
    struct ofpbuf *hello;

    hello = ofpraw_alloc_xid(OFPRAW_OFPT_HELLO, OFP13_VERSION,
                             htonl(0x12345678), 0);
    ((struct ofp_header *) hello->data)->version = 0;
    test_send_hello(type, hello->data, hello->size, EPROTO);
    ofpbuf_delete(hello);
}
Beispiel #25
0
static void
remote_rconn_run(struct datapath *dp, struct remote *r, uint8_t conn_id) {
    struct rconn *rconn;
    ofl_err error;
    size_t i;

    if (conn_id == MAIN_CONNECTION)
        rconn = r->rconn;
    else if (conn_id == PTIN_CONNECTION)
        rconn = r->rconn_aux;

    rconn_run(rconn);
    /* Do some remote processing, but cap it at a reasonable amount so that
     * other processing doesn't starve. */
    for (i = 0; i < 50; i++) {
        if (!r->cb_dump) {
            struct ofpbuf *buffer;

            buffer = rconn_recv(rconn);
            if (buffer == NULL) {
                break;
            } else {
                struct ofl_msg_header *msg;

                struct sender sender = {.remote = r, .conn_id = conn_id};

                error = ofl_msg_unpack(buffer->data, buffer->size, &msg, &(sender.xid), dp->exp);

                if (!error) {
                    error = handle_control_msg(dp, msg, &sender);

                    if (error) {
                        ofl_msg_free(msg, dp->exp);
                    }
                }

                if (error) {
                    struct ofl_msg_error err =
                            {{.type = OFPT_ERROR},
                             .type = ofl_error_type(error),
                             .code = ofl_error_code(error),
                             .data_length = buffer->size,
                             .data        = buffer->data};
                    dp_send_message(dp, (struct ofl_msg_header *)&err, &sender);
                }

                ofpbuf_delete(buffer);
            }
        } else {
            if (r->n_txq < TXQ_LIMIT) {
Beispiel #26
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);
}
Beispiel #27
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(struct ovs_cmdl_context *ctx)
{
    const char *type = ctx->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, hello->data, hello->size, 0);
    ofpbuf_delete(hello);
}
Beispiel #28
0
void
packet_destroy(struct packet *pkt) {
    /* If packet is saved in a buffer, do not destroy it,
     * if buffer is still valid */
    if (pkt->buffer_id != NO_BUFFER) {
        if (dp_buffers_is_alive(pkt->dp->buffers, pkt->buffer_id)) {
            return;
        } else {
            dp_buffers_discard(pkt->dp->buffers, pkt->buffer_id, false);
        }
    }

    action_set_destroy(pkt->action_set);
    ofpbuf_delete(pkt->buffer);
    packet_handle_std_destroy(pkt->handle_std);
    free(pkt);
}
Beispiel #29
0
static ofl_err
ofl_structs_oxm_match_unpack(struct ofp_match* src, uint8_t* buf, size_t *len, struct ofl_match **dst){

     int error = 0;
     struct ofpbuf *b = ofpbuf_new(0);
     struct ofl_match *m = (struct ofl_match *) malloc(sizeof(struct ofl_match));
     m->header.type = ntohs(src->type);
    *len -= ROUND_UP(ntohs(src->length),8);
     if(ntohs(src->length) > sizeof(struct ofp_match)){
         ofpbuf_put(b, buf, ntohs(src->length) - (sizeof(struct ofp_match) -4)); 
         error = oxm_pull_match(b, m, ntohs(src->length) - (sizeof(struct ofp_match) -4));
         m->header.length = ntohs(src->length) - 4;
     }
    else m->header.length = 0;
    ofpbuf_delete(b);    
    *dst = m;
    return error;
}
Beispiel #30
0
struct ofpbuf *
bundle_add(enum ofputil_protocol proto)
{
    struct ofputil_bundle_add_msg msg;
    struct ofpbuf *fm;
    struct ofpbuf *add;

    memset(&msg, 0, sizeof(msg));
    msg.bundle_id = 99999999;
    msg.flags = OFPBF_ATOMIC;
    fm = flow_mod(proto);
    clear_xid(fm);
    msg.msg = fm->data;
    add = ofputil_encode_bundle_add(
        ofputil_protocol_to_ofp_version(proto), &msg);
    ofpbuf_delete(fm);
    return add;
}