FreeBSD/sys/netgraph/ng_pipe.c
/*
 * Receive data on a hook - both in upstream and downstream direction.
 * We put the frame on the inbound queue, and try to initiate dequeuing
 * sequence immediately. If inbound queue is full, discard one frame
 * depending on dropping policy (from the head or from the tail of the
 * queue).
 */
Receive data on a hook - both in upstream and downstream direction.
We put the frame on the inbound queue, and try to initiate dequeuing
sequence immediately. If inbound queue is full, discard one frame
depending on dropping policy (from the head or from the tail of the
queue).
Receive data on a hook - both in upstream and downstream direction . We put the frame on the inbound queue and try to initiate dequeuing sequence immediately . If inbound queue is full discard one frame depending on dropping policy ( from the head or from the tail of the queue ) .
static int
ngp_rcvdata(hook_p hook, item_p item)
{
	struct hookinfo *const hinfo = NG_HOOK_PRIVATE(hook);
	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
	struct timeval uuptime;
	struct timeval *now = &uuptime;
	struct ngp_fifo *ngp_f = NULL, *ngp_f1;
	struct ngp_hdr *ngp_h = NULL;
	struct mbuf *m;
	int hash, plen;
	int error = 0;
	if (hinfo->run.qin_frames == 0 && hinfo->run.qout_frames == 0 &&
	    hinfo->noqueue) {
		struct hookinfo *dest;
		if (hinfo == &priv->lower)
			dest = &priv->upper;
		else
			dest = &priv->lower;
		plen = NGI_M(item)->m_pkthdr.len;
		NG_FWD_ITEM_HOOK(error, item, dest->hook);
		if (error) {
			hinfo->stats.out_disc_frames++;
			hinfo->stats.out_disc_octets += plen;
		} else {
			hinfo->stats.fwd_frames++;
			hinfo->stats.fwd_octets += plen;
		}
		return (error);
	}
	microuptime(now);
	if (hinfo->run.qin_frames == 0) {
		struct timeval *when = &hinfo->qin_utime;
		if (when->tv_sec < now->tv_sec || (when->tv_sec == now->tv_sec
		    && when->tv_usec < now->tv_usec)) {
			when->tv_sec = now->tv_sec;
			when->tv_usec = now->tv_usec;
		}
	}
	ngp_h = uma_zalloc(ngp_zone, M_NOWAIT);
	KASSERT((ngp_h != NULL), ("ngp_h zalloc failed (1)"));
	NGI_GET_M(item, m);
	KASSERT(m != NULL, ("NGI_GET_M failed"));
	ngp_h->m = m;
	NG_FREE_ITEM(item);
	if (hinfo->cfg.fifo)
		hash = 0;	
	else
		hash = ip_hash(m, priv->header_offset);
	TAILQ_FOREACH(ngp_f, &hinfo->fifo_head, fifo_le)
		if (hash == ngp_f->hash)
			break;
	if (ngp_f == NULL) {
		ngp_f = uma_zalloc(ngp_zone, M_NOWAIT);
		KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (2)"));
		TAILQ_INIT(&ngp_f->packet_head);
		ngp_f->hash = hash;
		ngp_f->packets = 1;
		ngp_f->rr_deficit = hinfo->cfg.drr;	
		hinfo->run.fifo_queues++;
		TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link);
		FIFO_VTIME_SORT(m->m_pkthdr.len);
	} else {
		TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link);
		ngp_f->packets++;
	}
	hinfo->run.qin_frames++;
	hinfo->run.qin_octets += m->m_pkthdr.len;
	if (hinfo->run.qin_frames > hinfo->cfg.qin_size_limit) {
		struct mbuf *m1;
		int longest = 0;
		TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le)
			if (ngp_f1->packets > longest) {
				longest = ngp_f1->packets;
				ngp_f = ngp_f1;
			}
		if (hinfo->cfg.drophead) 
			ngp_h = TAILQ_FIRST(&ngp_f->packet_head);
		else 
			ngp_h = TAILQ_LAST(&ngp_f->packet_head, p_head);
		TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link);
		m1 = ngp_h->m;
		uma_zfree(ngp_zone, ngp_h);
		hinfo->run.qin_octets -= m1->m_pkthdr.len;
		hinfo->stats.in_disc_octets += m1->m_pkthdr.len;
		m_freem(m1);
		if (--(ngp_f->packets) == 0) {
			TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le);
			uma_zfree(ngp_zone, ngp_f);
			hinfo->run.fifo_queues--;
		}
		hinfo->run.qin_frames--;
		hinfo->stats.in_disc_frames++;
	}
	pipe_dequeue(hinfo, now);
	return (0);
}
static int ngp_rcvdata ( hook_p hook , item_p item ) { struct hookinfo * const hinfo = NG_HOOK_PRIVATE ( hook ) ; const priv_p priv = NG_NODE_PRIVATE ( NG_HOOK_NODE ( hook ) ) ; struct timeval uuptime ; struct timeval * now = & uuptime ; struct ngp_fifo * ngp_f = NULL , * ngp_f1 ; struct ngp_hdr * ngp_h = NULL ; struct mbuf * m ; int hash , plen ; int error = 0 ; if ( hinfo -> run . qin_frames == 0 && hinfo -> run . qout_frames == 0 && hinfo -> noqueue ) { struct hookinfo * dest ; if ( hinfo == & priv -> lower ) dest = & priv -> upper ; else dest = & priv -> lower ; plen = NGI_M ( item ) -> m_pkthdr . len ; NG_FWD_ITEM_HOOK ( error , item , dest -> hook ) ; if ( error ) { hinfo -> stats . out_disc_frames ++ ; hinfo -> stats . out_disc_octets += plen ; } else { hinfo -> stats . fwd_frames ++ ; hinfo -> stats . fwd_octets += plen ; } return ( error ) ; } microuptime ( now ) ; if ( hinfo -> run . qin_frames == 0 ) { struct timeval * when = & hinfo -> qin_utime ; if ( when -> tv_sec < now -> tv_sec || ( when -> tv_sec == now -> tv_sec && when -> tv_usec < now -> tv_usec ) ) { when -> tv_sec = now -> tv_sec ; when -> tv_usec = now -> tv_usec ; } } ngp_h = uma_zalloc ( ngp_zone , M_NOWAIT ) ; KASSERT ( ( ngp_h != NULL ) , ( " " ) ) ; NGI_GET_M ( item , m ) ; KASSERT ( m != NULL , ( " " ) ) ; ngp_h -> m = m ; NG_FREE_ITEM ( item ) ; if ( hinfo -> cfg . fifo ) hash = 0 ; else hash = ip_hash ( m , priv -> header_offset ) ; TAILQ_FOREACH ( ngp_f , & hinfo -> fifo_head , fifo_le ) if ( hash == ngp_f -> hash ) break ; if ( ngp_f == NULL ) { ngp_f = uma_zalloc ( ngp_zone , M_NOWAIT ) ; KASSERT ( ngp_h != NULL , ( " " ) ) ; TAILQ_INIT ( & ngp_f -> packet_head ) ; ngp_f -> hash = hash ; ngp_f -> packets = 1 ; ngp_f -> rr_deficit = hinfo -> cfg . drr ; hinfo -> run . fifo_queues ++ ; TAILQ_INSERT_TAIL ( & ngp_f -> packet_head , ngp_h , ngp_link ) ; FIFO_VTIME_SORT ( m -> m_pkthdr . len ) ; } else { TAILQ_INSERT_TAIL ( & ngp_f -> packet_head , ngp_h , ngp_link ) ; ngp_f -> packets ++ ; } hinfo -> run . qin_frames ++ ; hinfo -> run . qin_octets += m -> m_pkthdr . len ; if ( hinfo -> run . qin_frames > hinfo -> cfg . qin_size_limit ) { struct mbuf * m1 ; int longest = 0 ; TAILQ_FOREACH ( ngp_f1 , & hinfo -> fifo_head , fifo_le ) if ( ngp_f1 -> packets > longest ) { longest = ngp_f1 -> packets ; ngp_f = ngp_f1 ; } if ( hinfo -> cfg . drophead ) ngp_h = TAILQ_FIRST ( & ngp_f -> packet_head ) ; else ngp_h = TAILQ_LAST ( & ngp_f -> packet_head , p_head ) ; TAILQ_REMOVE ( & ngp_f -> packet_head , ngp_h , ngp_link ) ; m1 = ngp_h -> m ; uma_zfree ( ngp_zone , ngp_h ) ; hinfo -> run . qin_octets -= m1 -> m_pkthdr . len ; hinfo -> stats . in_disc_octets += m1 -> m_pkthdr . len ; m_freem ( m1 ) ; if ( -- ( ngp_f -> packets ) == 0 ) { TAILQ_REMOVE ( & hinfo -> fifo_head , ngp_f , fifo_le ) ; uma_zfree ( ngp_zone , ngp_f ) ; hinfo -> run . fifo_queues -- ; } hinfo -> run . qin_frames -- ; hinfo -> stats . in_disc_frames ++ ; } pipe_dequeue ( hinfo , now ) ; return ( 0 ) ; }
Receive data on a hook - both in upstream and downstream direction.
Receive data on a hook - both in upstream and downstream direction .
/*
	 * Shortcut from inbound to outbound hook when neither of
	 * bandwidth, delay, BER or duplication probability is
	 * configured, nor we have queued frames to drain.
	 */ /* Send the frame. */ /* Update stats. */ /*
	 * If this was an empty queue, update service deadline time.
	 */ /* Populate the packet header */ /* all packets go into a single FIFO queue */ /* Find the appropriate FIFO queue for the packet and enqueue it*/ /* DRR quantum */ /* Discard a frame if inbound queue limit has been reached */ /* Find the longest queue */ /* Drop a frame from the queue head/tail, depending on cfg */ /*
	 * Try to start the dequeuing process immediately.
	 */