/* Insertion sort of the packet in the buffer using its seqnum */ void insert_descending_order(struct tcp_buf *tcp_buffer, struct ofpbuf *pkt){ int i, index; uint32_t seq_buf, seq_new; index = 0; if(tcp_buffer->inserted_items == 0){ tcp_buffer->buffer[0] = pkt; } else{ seq_buf = get_tcp_seq(tcp_buffer->buffer[index]); seq_new = get_tcp_seq(pkt); // Find the correct position for the item while((seq_new <= seq_buf) && (index<tcp_buffer->inserted_items)){ index++; if(seq_new == seq_buf){ tcp_buffer->expected_seqnum = get_next_seqnum(tcp_buffer, seq_new, pkt, false); } if(tcp_buffer->buffer[index]){ seq_buf = get_tcp_seq(tcp_buffer->buffer[index]); } } // Shift the elements to the right for(i=tcp_buffer->inserted_items;i>index;i--){ tcp_buffer->buffer[i] = tcp_buffer->buffer[i-1]; } tcp_buffer->buffer[index] = pkt; } tcp_buffer->inserted_items++; tcp_buffer->consecutive_buffering_events++; }
void Packet::print() { uint32_t tsval, tsecr; char sip_str[INET_ADDRSTRLEN]; char dip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ip_hdr->ip_src.s_addr, sip_str, INET_ADDRSTRLEN); inet_ntop(AF_INET, &ip_hdr->ip_dst.s_addr, dip_str, INET_ADDRSTRLEN); get_tcp_ts(&tsval,&tsecr); switch(get_ip_protocol()) { case IPPROTO_TCP: std::cout << "TCP packet: " << "[" << get_ts().tv_sec << "." << std::setw(9) << std::setfill('0') << get_ts().tv_nsec << "] [" << sip_str << ":" << get_tcp_sport() << "->" << dip_str << ":" << get_tcp_dport() << "] " << "[S:" << get_tcp_seq() << "] " << "[A:" << get_tcp_ack() << "] " << "[L:" << get_tcp_payload_len() << "] " << "[M:" << get_tcp_mss() << "] " << "[TV:" << tsval << "] " << "[TE:" << tsecr << "]" << std::endl << std::flush; break; case IPPROTO_ICMP: std::cout << "ICMP packet: [" << sip_str << "->" << dip_str << "] " << "[TTL:" << get_ip_ttl() << "]" << std::endl << std::flush; break; default: std::cout << "Unknown packet!" << std::endl << std::flush; break; } }
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; }