FreeBSD/sys/dev/netmap/netmap_vale.c
/*
 * main dispatch routine for the bridge.
 * Grab packets from a kring, move them into the ft structure
 * associated to the tx (input) port. Max one instance per port,
 * filtered on input (ioctl, poll or XXX).
 * Returns the next position in the ring.
 */
main dispatch routine for the bridge.
Grab packets from a kring, move them into the ft structure
associated to the tx (input) port. Max one instance per port,
filtered on input (ioctl, poll or XXX).
Returns the next position in the ring.
main dispatch routine for the bridge . Grab packets from a kring move them into the ft structure associated to the tx ( input ) port . Max one instance per port filtered on input ( ioctl poll or XXX ) . Returns the next position in the ring .
static int
nm_bdg_preflush(struct netmap_kring *kring, u_int end)
{
	struct netmap_vp_adapter *na =
		(struct netmap_vp_adapter*)kring->na;
	struct netmap_ring *ring = kring->ring;
	struct nm_bdg_fwd *ft;
	u_int ring_nr = kring->ring_id;
	u_int j = kring->nr_hwcur, lim = kring->nkr_num_slots - 1;
	u_int ft_i = 0;	
	u_int frags = 1; 
	struct nm_bridge *b = na->na_bdg;
	ND("wait rlock for %d packets", ((j > end ? lim+1 : 0) + end) - j);
	if (na->up.na_flags & NAF_BDG_MAYSLEEP)
		BDG_RLOCK(b);
	else if (!BDG_RTRYLOCK(b))
		return 0;
	ND(5, "rlock acquired for %d packets", ((j > end ? lim+1 : 0) + end) - j);
	ft = kring->nkr_ft;
	for (; likely(j != end); j = nm_next(j, lim)) {
		struct netmap_slot *slot = &ring->slot[j];
		char *buf;
		ft[ft_i].ft_len = slot->len;
		ft[ft_i].ft_flags = slot->flags;
		ND("flags is 0x%x", slot->flags);
		slot->flags &= ~NS_BUF_CHANGED;
		ft[ft_i].ft_next = NM_FT_NULL;
		buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ?
			(void *)(uintptr_t)slot->ptr : NMB(&na->up, slot);
		if (unlikely(buf == NULL)) {
			RD(5, "NULL %s buffer pointer from %s slot %d len %d",
				(slot->flags & NS_INDIRECT) ? "INDIRECT" : "DIRECT",
				kring->name, j, ft[ft_i].ft_len);
			buf = ft[ft_i].ft_buf = NETMAP_BUF_BASE(&na->up);
			ft[ft_i].ft_len = 0;
			ft[ft_i].ft_flags = 0;
		}
		__builtin_prefetch(buf);
		++ft_i;
		if (slot->flags & NS_MOREFRAG) {
			frags++;
			continue;
		}
		if (unlikely(netmap_verbose && frags > 1))
			RD(5, "%d frags at %d", frags, ft_i - frags);
		ft[ft_i - frags].ft_frags = frags;
		frags = 1;
		if (unlikely((int)ft_i >= bridge_batch))
			ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr);
	}
	if (frags > 1) {
		D("truncate incomplete fragment at %d (%d frags)", ft_i, frags);
		ft[ft_i - 1].ft_frags &= ~NS_MOREFRAG;
		ft[ft_i - frags].ft_frags = frags - 1;
	}
	if (ft_i)
		ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr);
	BDG_RUNLOCK(b);
	return j;
}
static int nm_bdg_preflush ( struct netmap_kring * kring , u_int end ) { struct netmap_vp_adapter * na = ( struct netmap_vp_adapter * ) kring -> na ; struct netmap_ring * ring = kring -> ring ; struct nm_bdg_fwd * ft ; u_int ring_nr = kring -> ring_id ; u_int j = kring -> nr_hwcur , lim = kring -> nkr_num_slots - 1 ; u_int ft_i = 0 ; u_int frags = 1 ; struct nm_bridge * b = na -> na_bdg ; ND ( " " , ( ( j > end ? lim + 1 : 0 ) + end ) - j ) ; if ( na -> up . na_flags & NAF_BDG_MAYSLEEP ) BDG_RLOCK ( b ) ; else if ( ! BDG_RTRYLOCK ( b ) ) return 0 ; ND ( 5 , " " , ( ( j > end ? lim + 1 : 0 ) + end ) - j ) ; ft = kring -> nkr_ft ; for ( ; likely ( j != end ) ; j = nm_next ( j , lim ) ) { struct netmap_slot * slot = & ring -> slot [ j ] ; char * buf ; ft [ ft_i ] . ft_len = slot -> len ; ft [ ft_i ] . ft_flags = slot -> flags ; ND ( " " , slot -> flags ) ; slot -> flags &= ~ NS_BUF_CHANGED ; ft [ ft_i ] . ft_next = NM_FT_NULL ; buf = ft [ ft_i ] . ft_buf = ( slot -> flags & NS_INDIRECT ) ? ( void * ) ( uintptr_t ) slot -> ptr : NMB ( & na -> up , slot ) ; if ( unlikely ( buf == NULL ) ) { RD ( 5 , " " , ( slot -> flags & NS_INDIRECT ) ? " " : " " , kring -> name , j , ft [ ft_i ] . ft_len ) ; buf = ft [ ft_i ] . ft_buf = NETMAP_BUF_BASE ( & na -> up ) ; ft [ ft_i ] . ft_len = 0 ; ft [ ft_i ] . ft_flags = 0 ; } __builtin_prefetch ( buf ) ; ++ ft_i ; if ( slot -> flags & NS_MOREFRAG ) { frags ++ ; continue ; } if ( unlikely ( netmap_verbose && frags > 1 ) ) RD ( 5 , " " , frags , ft_i - frags ) ; ft [ ft_i - frags ] . ft_frags = frags ; frags = 1 ; if ( unlikely ( ( int ) ft_i >= bridge_batch ) ) ft_i = nm_bdg_flush ( ft , ft_i , na , ring_nr ) ; } if ( frags > 1 ) { D ( " " , ft_i , frags ) ; ft [ ft_i - 1 ] . ft_frags &= ~ NS_MOREFRAG ; ft [ ft_i - frags ] . ft_frags = frags - 1 ; } if ( ft_i ) ft_i = nm_bdg_flush ( ft , ft_i , na , ring_nr ) ; BDG_RUNLOCK ( b ) ; return j ; }
main dispatch routine for the bridge.
main dispatch routine for the bridge .
/* start from 0 */ /* how many frags ? */ /* To protect against modifications to the bridge we acquire a
	 * shared lock, waiting if we can sleep (if the source port is
	 * attached to a user process) or with a trylock otherwise (NICs).
	 */ /* we do not use the buf changed flag, but we still need to reset it */ /* this slot goes into a list so initialize the link field */ // ft_i > 0, ft[ft_i-1].flags has NS_MOREFRAG