Exemplo n.º 1
0
/**
 * first fragment for given address is detected - setup
 */
ip_frag_desc_t *ip_frag_manager::new_frag_desc(ip_frag_key_t &key)
{
	ip_frag_desc_t *desc = NULL;
	struct ip_frag_hole_desc *hole = NULL;

	hole = alloc_hole_desc();
	if (!hole){
		frag_dbg("NULL hole");
		return NULL;
	}
	hole->first = IP_FRAG_NINF;
	hole->last  = IP_FRAG_INF;

	desc = alloc_frag_desc();
	if (!desc) {
		frag_dbg("NULL desc");
		free_hole_desc(hole);
		return NULL;
	}
	desc->ttl = IP_FRAG_TTL;
	desc->frag_list = 0;
	desc->hole_list = hole;
	desc->frag_counter = m_frag_counter;

	m_frags[key]  = desc;
	return desc;
}
Exemplo n.º 2
0
ip_frag_manager::ip_frag_manager() : lock_spin("ip_frag_manager")
{
	frag_dbg("");
	m_frag_counter = 0;
	int i;

	
	frag_dbg("NOTE: ip frag periodic timer is disabled until HW supports ip frag offload");
	// g_p_event_handler_manager->register_timer_event(IP_FRAG_CLEANUP_INT, this, PERIODIC_TIMER, 0);

	frag_dbg("Created new IPFRAG MANAGER instance");
	/* allocate hole list */
	desc_base = new ip_frag_desc_t [IP_FRAG_MAX_DESC];
	BULLSEYE_EXCLUDE_BLOCK_START
	if (!desc_base) {
		frag_dbg("Failed to allocate descriptor");
		free_frag_resources();
		throw_vma_exception("Failed to allocate descriptor");
	}
	hole_base = new ip_frag_hole_desc [IP_FRAG_MAX_HOLES];
	if (!hole_base) {
		frag_dbg("Failed to allocate hole descriptor");
		free_frag_resources();
		throw_vma_exception("Failed to allocate hole descriptor");
	}
	BULLSEYE_EXCLUDE_BLOCK_END
	for (i = 0; i < IP_FRAG_MAX_DESC; i++) {
		free_frag_desc(&desc_base[i]);
	}
	for (i = 0; i < IP_FRAG_MAX_HOLES; i++) {
		free_hole_desc(&hole_base[i]);
	}
}
Exemplo n.º 3
0
void ip_frag_manager::free_frag_resources(void)
{

        ip_frags_list_t::iterator i;
	ip_frag_desc_t *desc;

	frag_dbg("NOTE: ip frag periodic timer is disabled until HW supports ip frag offload");
	// g_p_event_handler_manager->unregister_timer_event(this, NULL);

	lock();

	while (m_frags.size() > 0) {
		i = m_frags.begin();
		desc = i->second;
		destroy_frag_desc(desc);
		free_frag_desc(desc);
		m_frags.erase(i);
	}

	owner_desc_map_t temp_buff_map = m_return_descs;
	m_return_descs.clear();

	unlock();

	// Must call cq_mgr outside the lock to avoid ABBA deadlock
	return_buffers_to_owners(temp_buff_map);

	delete [] desc_base;
	delete [] hole_base;
	frag_dbg("Deleted IPFRAG MANAGER instance");
}
static void pico_ipv6_frag_timer_on(void)
{
    ipv6_fragments_timer = pico_timer_add(PICO_IPV6_FRAG_TIMEOUT, pico_frag_expire, &ipv6_fragments);
    if (!ipv6_fragments_timer) {
        frag_dbg("FRAG: Failed to start IPv6 expiration timer\n");
        pico_fragments_empty_tree(&ipv6_fragments);
    }
}
Exemplo n.º 5
0
void ip_frag_manager::handle_timer_expired(void* user_data)
{
	NOT_IN_USE(user_data);
	ip_frags_list_t::iterator iter, iter_temp;
	ip_frag_desc_t *desc;
	uint64_t delta =0;

	lock();
	if (m_frag_counter > IP_FRAG_SPACE) {
		delta = m_frag_counter - IP_FRAG_SPACE;
		m_frag_counter -= delta;
	}

	frag_dbg("calling handle_timer_expired, m_frag_counter=%ld, delta=%ld", m_frag_counter, delta);
	PRINT_STATISTICS();

	iter = m_frags.begin();
	while (iter != m_frags.end()) {
		desc = iter->second;
		desc->frag_counter -= delta;
		if (desc->frag_counter<0 || (desc->ttl <= 0)) {	//discard this packet
			frag_dbg("expiring packet fragments desc=%p (frag_counter=%d, ttl=%d)", desc, desc->frag_counter, desc->ttl);
			destroy_frag_desc(desc);
			free_frag_desc(desc);
			iter_temp = iter++;
			m_frags.erase(iter_temp);
		}
		else {
			iter++;
		}

		--desc->ttl;
	}

	owner_desc_map_t temp_buff_map = m_return_descs;
	m_return_descs.clear();

	PRINT_STATISTICS();
	unlock();

	// Must call cq_mgr outside the lock to avoid ABBA deadlock
	return_buffers_to_owners(temp_buff_map);
}
Exemplo n.º 6
0
/**
 * Complexity of the algorithm:
 * O(1) if packets are coming in order or reverse order
 * O(n^2) for random fragments, where n is number of fragments
 * returns: 0 if finished OK (if the packet is complete - put it in ret)
 * 		   -1 if finished not OK and this packet needs to be droped
 */
int ip_frag_manager::add_frag(iphdr *hdr, mem_buf_desc_t *frag, mem_buf_desc_t **ret)
{
	ip_frag_key_t key;
	ip_frags_list_t::iterator i;
	ip_frag_desc_t *desc;
	struct ip_frag_hole_desc *phole, *phole_prev;
	struct ip_frag_hole_desc *new_hole;
	uint16_t frag_off, frag_first, frag_last;
	bool more_frags;

	assert(hdr);
	assert(frag);

	key.ip_id       = hdr->id;  //id is in network order!
	key.src_ip      = hdr->saddr;
	key.dst_ip      = hdr->daddr;
	key.ipproto     = hdr->protocol;

	frag_dbg("Fragment: %d.%d.%d.%d->%d.%d.%d.%d id=%x size=%d",
		 NIPQUAD(key.src_ip),
		 NIPQUAD(key.dst_ip),
		 (int)key.ip_id, (int)ntohs(hdr->tot_len));

#ifdef IP_FRAG_DEBUG
	if (debug_drop_every_n_pkt && ((++debug_drop_index) % debug_drop_every_n_pkt == 0)) {
		frag_dbg("XXX debug force dropped XXX");
		return -1;
	}
#endif

	lock();

	MEMBUF_DEBUG_REF_INC(frag);
	PRINT_STATISTICS();

	frag_off = ntohs(hdr->frag_off);
	more_frags = frag_off & MORE_FRAGMENTS_FLAG;
	frag_first = (frag_off & FRAGMENT_OFFSET) * 8;
	frag_last = frag_first + ntohs(hdr->tot_len) - (hdr->ihl<<2) - 1; // frag starts from 0!!!
	frag_dbg("> fragment: %d-%d, %s more frags", frag_first, frag_last, more_frags?"pending":"no");

	m_frag_counter++;

	i = m_frags.find(key);

	if (i == m_frags.end()) {
		/* new fragment */
		frag_dbg("> new fragmented packet");
		desc = new_frag_desc(key);
	}
	else {
		desc = i->second;
		if ((m_frag_counter - desc->frag_counter) > IP_FRAG_SPACE) {
			// discard this packet
			frag_dbg("expiring packet fragments id=%x", i->first);
			destroy_frag_desc(desc);
			free_frag_desc(desc);
			m_frags.erase(i);
			i = m_frags.end();
			// Add new fregment
			frag_dbg("> new fragmented packet");
			desc = new_frag_desc(key);
		}
		else {
			frag_dbg("> old fragmented packet");
	}
	}
	if (desc==NULL) {
		MEMBUF_DEBUG_REF_DEC(frag);
		PRINT_STATISTICS();
		unlock();
		return -1;
	}

	//desc->last_frag_counter = m_frag_counter;

	/* 8 step reassembly algorithm as described in RFC 815 */
	//step 1
	phole_prev = 0; phole = desc->hole_list;
	while (phole) {
		//step 2 and step 3
		if (frag_first >= phole->first && frag_last <= phole->last) {
			break;
		}
		phole_prev = phole;
		phole = phole->next;
	}
	if (!phole) {   // the right hole wasn't found
		MEMBUF_DEBUG_REF_DEC(frag);
		PRINT_STATISTICS();
		unlock();
		return -1;
	}

	frag_dbg("> found hole: %d-%d", phole->first, phole->last);

	// step 4 - remove hole from list
	if (phole_prev)
		phole_prev->next = phole->next;
	else
		desc->hole_list	= phole->next;

	// step 5
	if (frag_first > phole->first) {
		new_hole                = alloc_hole_desc();
		if (!new_hole) {
			free_hole_desc(phole); // phole was removed from the list in step 4!
			MEMBUF_DEBUG_REF_DEC(frag);
			PRINT_STATISTICS();
			unlock();
			return -1;
		}
		new_hole->first         = phole->first;
		new_hole->last          = frag_first-1;
		new_hole->data_first    = phole->data_first;
		new_hole->data_last     = frag;

		new_hole->next = phole->next;
		if (phole_prev)
			phole_prev->next = new_hole;
		else
			desc->hole_list	= new_hole;

		phole_prev = new_hole;
	}

	//step 6
	if (frag_last < phole->last && more_frags) {
		new_hole                = alloc_hole_desc();
		if (!new_hole) {
			free_hole_desc(phole);  // phole was removed from the list in step 4!
			MEMBUF_DEBUG_REF_DEC(frag);
			PRINT_STATISTICS();
			unlock();
			return -1;
		}

		new_hole->first         = frag_last + 1;
		new_hole->last          = phole->last;
		new_hole->data_first    = frag;
		new_hole->data_last     = phole->data_last;

		new_hole->next = phole->next;
		if (phole_prev)
			phole_prev->next = new_hole;
		else
			desc->hole_list	= new_hole;
	}

	// link frag
	if (phole->data_first)
		phole->data_first->p_next_desc = frag;
	else
		desc->frag_list	= frag;
	frag->p_next_desc = phole->data_last;

	free_hole_desc(phole);

	if (!desc->hole_list) {
		//step 8 - datagram assembly completed
		if (i == m_frags.end())
			i = m_frags.find(key);
		if (i == m_frags.end()){
			MEMBUF_DEBUG_REF_DEC(frag);
			frag_panic("frag desc lost from map???");
			//coverity unreachable
			/*unlock();
			return -1;*/
		}
		MEMBUF_DEBUG_REF_DEC(desc->frag_list);
		m_frags.erase(i);
		*ret = desc->frag_list;
		free_frag_desc(desc);
		frag_dbg("> PACKET ASSEMBLED");
		PRINT_STATISTICS();
		unlock();
		return 0;
	}
	frag_dbg("> need more packets");

	*ret = NULL;
	PRINT_STATISTICS();
	unlock();
	return 0;
}
Exemplo n.º 7
0
void ip_frag_manager::print_statistics()
{
	frag_dbg("free desc=%d, free holes=%d, map size=%d, frags=%d", desc_free_list_count, hole_free_list_count, m_frags.size(), g_ip_frag_count_check);
}