Пример #1
0
static bool
rate_limit_local_packet_cb(struct relay *r, void *rl_)
{
    struct rate_limiter *rl = rl_;
    const struct settings *s = rl->s;
    struct ofp_packet_in *opi;

    opi = get_ofp_packet_in(r);
    if (!opi) {
        return false;
    }

    if (opi->reason == OFPR_ACTION) {
        /* Don't rate-limit 'ofp-packet_in's generated by flows that the
         * controller set up.  XXX we should really just rate-limit them
         * *separately* so that no one can flood the controller this way. */
        return false;
    }

    if (!rl->n_queued && get_token(rl)) {
        /* In the common case where we are not constrained by the rate limit,
         * let the packet take the normal path. */
        rl->n_normal++;
        return false;
    } else {
        /* Otherwise queue it up for the periodic callback to drain out. */
        struct ofpbuf *msg = r->halves[HALF_LOCAL].rxbuf;
        int port = ntohs(opi->in_port) % OFPP_MAX;
        if (rl->n_queued >= s->burst_limit) {
            drop_packet(rl);
        }
        queue_push_tail(&rl->queues[port], ofpbuf_clone(msg));
        rl->n_queued++;
        rl->n_limited++;
        return true;
    }
}
Пример #2
0
struct packet *
packet_clone(struct packet *pkt) {
    struct packet *clone;

    clone = xmalloc(sizeof(struct packet));
    clone->dp         = pkt->dp;
    clone->buffer     = ofpbuf_clone(pkt->buffer);
    clone->in_port    = pkt->in_port;
    clone->action_set = action_set_clone(pkt->action_set);

    clone->packet_out       = pkt->packet_out;
    clone->out_group        = OFPG_ANY;
    clone->out_port         = OFPP_ANY;
    clone->out_port_max_len = 0;
    clone->out_queue        = 0;
    clone->buffer_id        = NO_BUFFER; // the original is saved in buffer,
                                         // but this buffer is a copy of that,
                                         // and might be altered later
    clone->table_id         = pkt->table_id;

    clone->handle_std = packet_handle_std_clone(clone, pkt->handle_std);

    return clone;
}
Пример #3
0
int get_packet_list(struct ofpbuf *out_packets[], struct ofpbuf * packet, uint32_t flow_id, uint32_t in_port){

    struct tcp_buf * tcp_buf;    
    uint8_t tcp_flags;
    struct tcp_header *tcp;
    uint32_t seq;
    int i, out_packets_count;
    uint32_t seq_work;
    struct ofpbuf * buf_pkt;
    int removed_items;


    // Getting the buffer for the flow, or creating a new one if 
    // not existing
    tcp_buf = get_tcp_buf(flow_id);

    tcp = ofpbuf_l4(packet);
    tcp_flags = TCP_FLAGS(tcp->tcp_ctl);    
    seq = get_tcp_seq(packet);

    out_packets_count = 0;


    if (tcp_flags & TCP_SYN){
        tcp_buf->expected_seqnum = seq+1;
        VLOG_INFO("[SYN packet] sequence: %" PRIu32 " expected: %" PRIu32 " in_port: %"PRIu32 "  size: %d",
            seq, tcp_buf->expected_seqnum, in_port, tcp_buf->inserted_items);
        out_packets[out_packets_count] = packet;
        out_packets_count++;
    }
    else if(tcp_buf->fin_state){
        delete_tcp_buf(tcp_buf);
        out_packets[out_packets_count] = packet;
        out_packets_count++;
    }
    // Retransmission or packets which come without a SYN or after a FIN
    // Just send out
    else if(tcp_buf->expected_seqnum == -1){
        out_packets[out_packets_count] = packet;
        out_packets_count++;
    }
    // Sending out and checking if the the gap in the reordering buffer has been filled
    else if(seq <= tcp_buf->expected_seqnum){
        VLOG_INFO("[sending in order packet] seq: %"PRIu32 " expected: %" PRIu32 " in_port: %"PRIu32 " size: %d",
            seq, tcp_buf->expected_seqnum, in_port, tcp_buf->inserted_items);

        out_packets[out_packets_count] = packet;
        out_packets_count++;
        tcp_buf->consecutive_buffering_events = 0;

        // Increasing sequence only if it matches
        if(seq == tcp_buf->expected_seqnum){
            tcp_buf->expected_seqnum = get_next_seqnum(tcp_buf, tcp_buf->expected_seqnum, packet, false);
        }

        // Check if there are packets waiting to be sent
        removed_items = 0;
        for(i=tcp_buf->inserted_items-1;i>= 0;i--){
            seq_work = get_tcp_seq(tcp_buf->buffer[i]);

            if(seq_work <= tcp_buf->expected_seqnum){
                VLOG_INFO("[sending out from buffer] sequence: %" PRIu32 " expected: %" PRIu32 " size: %d",
                    seq_work, tcp_buf->expected_seqnum, tcp_buf->inserted_items - removed_items);
                removed_items++;            
                out_packets[out_packets_count] = tcp_buf->buffer[i];
                out_packets_count++;
                if(seq_work == tcp_buf->expected_seqnum){
                    tcp_buf->expected_seqnum = get_next_seqnum(tcp_buf, tcp_buf->expected_seqnum, tcp_buf->buffer[i], false);
                }
            }
        }
        tcp_buf->inserted_items = tcp_buf->inserted_items - removed_items;
    }
    // Buffer not full yet, buffering the packet
    else if(tcp_buf->inserted_items<TCP_BUF_SIZE && tcp_buf->consecutive_buffering_events < CONSECUTIVE_BUFFERING_TREESHOLD){
        VLOG_INFO("[buffering] sequence: %"PRIu32 " expected: %" PRIu32 " in_port: %"PRIu32 " size: %d",
            seq, tcp_buf->expected_seqnum, in_port, tcp_buf->inserted_items);
        buf_pkt = ofpbuf_clone(packet);
        insert_descending_order(tcp_buf, buf_pkt);
    }
    // Buffer full or loss event detecte
    else{
        VLOG_WARN("!! -- Empty Buffer Event -- !!");
        if(tcp_buf->consecutive_buffering_events >= CONSECUTIVE_BUFFERING_TREESHOLD)
            syslog(LOG_INFO, "!! -- Because of an apparent loss -- !!");

        seq_work = get_tcp_seq(tcp_buf->buffer[tcp_buf->inserted_items-1]);

        // If incoming packet has the smallest sequence
        if(seq<seq_work){
            VLOG_INFO("[resetting buffer] sequence: %" PRIu32, seq);
            out_packets[out_packets_count] = packet;
            out_packets_count++;
        }
        // If a packet in the buffer has the smallest sequence
        else{
            VLOG_INFO("[resetting] sequence: %" PRIu32, get_tcp_seq(tcp_buf->buffer[tcp_buf->inserted_items-1]));
            out_packets[out_packets_count] = tcp_buf->buffer[tcp_buf->inserted_items-1];
            out_packets_count++;
            tcp_buf->inserted_items--;
            buf_pkt = ofpbuf_clone(packet);
            insert_descending_order(tcp_buf, buf_pkt);
        }

        // Completely empty the buffer
        for(i=tcp_buf->inserted_items-1;i>= 0;i--){
            seq_work = get_tcp_seq(tcp_buf->buffer[i]);
            VLOG_INFO("resetting %" PRIu32, seq_work);
            get_next_seqnum(tcp_buf, seq_work, tcp_buf->buffer[i], false);
            out_packets[out_packets_count] = tcp_buf->buffer[i];
            out_packets_count++;

            // Adjusting seqnum
            if(i==0){
                tcp_buf->expected_seqnum = get_next_seqnum(tcp_buf, seq_work, tcp_buf->buffer[i], false);
            }
        }

        tcp_buf->inserted_items=0;

        if(tcp_buf->consecutive_buffering_events >= CONSECUTIVE_BUFFERING_TREESHOLD){
            tcp_buf->expected_seqnum = get_next_seqnum(tcp_buf, tcp_buf->expected_seqnum, packet, true);
        }
    }

    return out_packets_count;
}