int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
{
	struct rte_mbuf *m_last;
        utl_rte_pktmbuf_check(m);

	m_last = rte_pktmbuf_lastseg(m);
	if (len > m_last->data_len)
		return -1;

	m_last->data_len = (uint16_t)(m_last->data_len - len);
	m->pkt_len  = (m->pkt_len - len);
	return 0;
}
char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
{
	void *tail;
	struct rte_mbuf *m_last;
	utl_rte_pktmbuf_check(m);


	m_last = rte_pktmbuf_lastseg(m);
	if (len > rte_pktmbuf_tailroom(m_last))
		return NULL;

	tail = (char*) m_last->buf_addr + m_last->data_len;
	m_last->data_len = (uint16_t)(m_last->data_len + len);
	m->pkt_len  = (m->pkt_len + len);
	return (char*) tail;
}
/* TCP */
int ipaugenblick_receive(int sock,void **pbuffer,int *total_len,int *first_segment_len,void **pdesc)
{ 
    struct rte_mbuf *mbuf;

    ipaugenblick_stats_receive_called++;
    /* first try to look shadow. shadow pointer saved when last mbuf delievered partially */
    mbuf = ipaugenblick_get_from_shadow(sock);
    if((mbuf)&&(*total_len > 0)) { /* total_len > 0 means user restricts total read count */
//	printf("%s %d %d\n",__FILE__,__LINE__,*total_len);
	int total_len2 = *total_len;
	/* now find mbuf (if any) to be delievered partially and save it to shadown */
	ipaugenblick_try_read_exact_amount(mbuf,sock,&total_len2,first_segment_len);
	*pbuffer = rte_pktmbuf_mtod(mbuf,void *);
    	*pdesc = mbuf;
	if((total_len2 > 0)&&(total_len2 < *total_len)) { /* read less than user requested, try ring */
//		printf("%s %d %d\n",__FILE__,__LINE__,total_len2);
		struct rte_mbuf *mbuf2 = ipaugenblick_dequeue_rx_buf(sock);
		if(!mbuf2) { /* ring is empty */
			*total_len = total_len2;
//			printf("%s %d\n",__FILE__,__LINE__);
		}
		else { /* now try to find an mbuf to be delievered partially in the chain */
			int total_len3 = *total_len - total_len2;
			int first_segment_len_dummy;
			ipaugenblick_try_read_exact_amount(mbuf2,sock,&total_len3,&first_segment_len_dummy);
			struct rte_mbuf *last_mbuf = rte_pktmbuf_lastseg(mbuf);
			last_mbuf->next = mbuf2;
			*total_len = total_len2 + total_len3;
//			printf("%s %d %d\n",__FILE__,__LINE__,total_len3);
		}
	}
	else {
//		printf("%s %d %d\n",__FILE__,__LINE__,*total_len);
		//goto read_from_ring;
	}
	if(local_socket_descriptors[sock].shadow) {
		uint32_t ringidx_ready_mask = sock|(SOCKET_READABLE_BIT << SOCKET_READY_SHIFT);
		if(local_socket_descriptors[sock].select != -1)
			rte_ring_enqueue(selectors[local_socket_descriptors[sock].select].ready_connections,(void *)ringidx_ready_mask);	
	}
	return 0;
    }