FreeBSD/sys/dev/netmap/netmap_vale.c
/*
 * Lookup function for a learning bridge.
 * Update the hash table with the source address,
 * and then returns the destination port index, and the
 * ring in *dst_ring (at the moment, always use ring 0)
 */
Lookup function for a learning bridge.
Update the hash table with the source address,
and then returns the destination port index, and the
ring in *dst_ring (at the moment, always use ring 0)
Lookup function for a learning bridge . Update the hash table with the source address and then returns the destination port index and the ring in * dst_ring ( at the moment always use ring 0 )
u_int
netmap_bdg_learning(struct nm_bdg_fwd *ft, uint8_t *dst_ring,
		struct netmap_vp_adapter *na)
{
	uint8_t *buf = ft->ft_buf;
	u_int buf_len = ft->ft_len;
	struct nm_hash_ent *ht = na->na_bdg->ht;
	uint32_t sh, dh;
	u_int dst, mysrc = na->bdg_port;
	uint64_t smac, dmac;
	if (buf_len >= 14 + na->virt_hdr_len) {
		buf += na->virt_hdr_len;
		buf_len -= na->virt_hdr_len;
	} else if (buf_len == na->virt_hdr_len && ft->ft_flags & NS_MOREFRAG) {
		ft++;
		buf = ft->ft_buf;
		buf_len = ft->ft_len;
	} else {
		RD(5, "invalid buf format, length %d", buf_len);
		return NM_BDG_NOPORT;
	}
	dmac = le64toh(*(uint64_t *)(buf)) & 0xffffffffffff;
	smac = le64toh(*(uint64_t *)(buf + 4));
	smac >>= 16;
	if (((buf[6] & 1) == 0) && (na->last_smac != smac)) { 
		uint8_t *s = buf+6;
		sh = nm_bridge_rthash(s); 
		na->last_smac = ht[sh].mac = smac;	
		ht[sh].ports = mysrc;
		if (netmap_verbose)
		    D("src %02x:%02x:%02x:%02x:%02x:%02x on port %d",
			s[0], s[1], s[2], s[3], s[4], s[5], mysrc);
	}
	dst = NM_BDG_BROADCAST;
	if ((buf[0] & 1) == 0) { 
		dh = nm_bridge_rthash(buf); 
		if (ht[dh].mac == dmac) {	
			dst = ht[dh].ports;
		}
	}
	return dst;
}
u_int netmap_bdg_learning ( struct nm_bdg_fwd * ft , uint8_t * dst_ring , struct netmap_vp_adapter * na ) { uint8_t * buf = ft -> ft_buf ; u_int buf_len = ft -> ft_len ; struct nm_hash_ent * ht = na -> na_bdg -> ht ; uint32_t sh , dh ; u_int dst , mysrc = na -> bdg_port ; uint64_t smac , dmac ; if ( buf_len >= 14 + na -> virt_hdr_len ) { buf += na -> virt_hdr_len ; buf_len -= na -> virt_hdr_len ; } else if ( buf_len == na -> virt_hdr_len && ft -> ft_flags & NS_MOREFRAG ) { ft ++ ; buf = ft -> ft_buf ; buf_len = ft -> ft_len ; } else { RD ( 5 , " " , buf_len ) ; return NM_BDG_NOPORT ; } dmac = le64toh ( * ( uint64_t * ) ( buf ) ) & 0xffffffffffff ; smac = le64toh ( * ( uint64_t * ) ( buf + 4 ) ) ; smac >>= 16 ; if ( ( ( buf [ 6 ] & 1 ) == 0 ) && ( na -> last_smac != smac ) ) { uint8_t * s = buf + 6 ; sh = nm_bridge_rthash ( s ) ; na -> last_smac = ht [ sh ] . mac = smac ; ht [ sh ] . ports = mysrc ; if ( netmap_verbose ) D ( " " , s [ 0 ] , s [ 1 ] , s [ 2 ] , s [ 3 ] , s [ 4 ] , s [ 5 ] , mysrc ) ; } dst = NM_BDG_BROADCAST ; if ( ( buf [ 0 ] & 1 ) == 0 ) { dh = nm_bridge_rthash ( buf ) ; if ( ht [ dh ] . mac == dmac ) { dst = ht [ dh ] . ports ; } } return dst ; }
Lookup function for a learning bridge.
Lookup function for a learning bridge .
/* safety check, unfortunately we have many cases */ /* virthdr + mac_hdr in the same slot */ /* only header in first fragment */ /*
	 * The hash is somewhat expensive, there might be some
	 * worthwhile optimizations here.
	 */ /* valid src */ // XXX hash of source /* update source port forwarding entry */ /* XXX expire ? */ /* unicast */ // XXX hash of dst /* found dst */ /* XXX otherwise return NM_BDG_UNKNOWN ? */