2009-08-17 Till Straumann <strauman@slac.stanford.edu>

* network/tsec.c, network/if_tsec_pub.h:
	Fixed bugs in multicast support; added reference-count
	for hash-table entries which allows for the implementation
	of a 'deletion' routine.
	NOTE: mcast support largely untested.
This commit is contained in:
Till Straumann
2009-08-17 14:27:55 +00:00
parent 8131a3d808
commit e8ac5d470e
3 changed files with 68 additions and 15 deletions

View File

@@ -1,3 +1,11 @@
2009-08-17 Till Straumann <strauman@slac.stanford.edu>
* network/tsec.c, network/if_tsec_pub.h:
Fixed bugs in multicast support; added reference-count
for hash-table entries which allows for the implementation
of a 'deletion' routine.
NOTE: mcast support largely untested.
2009-06-05 Till Straumann <strauman@slac.stanford.edu> 2009-06-05 Till Straumann <strauman@slac.stanford.edu>
* irq/irq_init.c: silenced compiler warning. * irq/irq_init.c: silenced compiler warning.

View File

@@ -182,35 +182,51 @@ BSP_tsec_init_hw(struct tsec_private *mp, int promisc, unsigned char *enaddr);
* Clear multicast hash filter. No multicast frames are accepted * Clear multicast hash filter. No multicast frames are accepted
* after executing this routine (unless the hardware was initialized * after executing this routine (unless the hardware was initialized
* in 'promiscuous' mode). * in 'promiscuous' mode).
*
* Reset reference count for all hash-table entries
* to zero (see BSP_tsec_mcast_filter_accept_del()).
*/ */
void void
BSP_tsec_mcast_filter_clear(struct tsec_private *mp); BSP_tsec_mcast_filter_clear(struct tsec_private *mp);
/* /*
* Program multicast filter to accept all multicast frames. * Program multicast filter to accept all multicast frames.
*
* Increment reference count for all hash-table entries
* by one (see BSP_tsec_mcast_filter_accept_del()).
*/ */
void void
BSP_tsec_mcast_filter_accept_all(struct tsec_private *mp); BSP_tsec_mcast_filter_accept_all(struct tsec_private *mp);
/* /*
* Add a MAC address to the multicast filter. * Add a MAC address to the multicast filter and increment
* the reference count for the matching hash-table entry
* (see BSP_tsec_mcast_filter_accept_del()).
*
* Existing entries are not changed but note that * Existing entries are not changed but note that
* the filter is imperfect, i.e., multiple MAC addresses * the filter is imperfect, i.e., multiple MAC addresses
* may alias to a single filter entry. Hence software * may alias to a single filter entry. Hence software
* filtering must still be performed. * filtering must still be performed.
* *
* NOTE: Deletion of an address is not possible. This is
* usually accomplished by a higher-level driver
* maintaining a list/database of multicast addresses
* and going through a sequence:
*
* BSP_tsec_mcast_filter_clear()
* forall mcast addresses do
* BSP_tsec_mcast_filter_accept_add()
*/ */
void void
BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, unsigned char *enaddr); BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, unsigned char *enaddr);
/*
* Remove a MAC address from the (imperfec) multicast
* filter.
* Note that the driver maintains an internal reference
* counter for each multicast hash. The hash-table
* entry is only cleared when the reference count
* reaches zero ('del' has been called the same
* amount of times as 'add' for an address (or
* any alias) that matches a given table entry.
* BSP_tsec_mcast_filter_clear() resets all reference
* counters to zero.
*/
void
BSP_tsec_mcast_filter_accept_del(struct tsec_private *mp, unsigned char *enaddr);
/* /*
* Dump statistics to FILE 'f'. If NULL, stdout is used. * Dump statistics to FILE 'f'. If NULL, stdout is used.
*/ */

View File

@@ -640,6 +640,8 @@ static inline void bd_wrbuf(TSEC_BD *bd, uint32_t addr)
/* Driver 'private' data */ /* Driver 'private' data */
#define NUM_MC_HASHES 256
struct tsec_private { struct tsec_private {
FEC_Enet_Base base; /* Controller base address */ FEC_Enet_Base base; /* Controller base address */
FEC_Enet_Base phy_base; /* Phy base address (not necessarily identical FEC_Enet_Base phy_base; /* Phy base address (not necessarily identical
@@ -684,6 +686,7 @@ struct tsec_private {
unsigned odrops; unsigned odrops;
unsigned repack; unsigned repack;
} stats; } stats;
uint16_t mc_refcnt[NUM_MC_HASHES];
}; };
#define NEXT_TXI(mp, i) (((i)+1) < (mp)->tx_ring_size ? (i)+1 : 0 ) #define NEXT_TXI(mp, i) (((i)+1) < (mp)->tx_ring_size ? (i)+1 : 0 )
@@ -1402,9 +1405,10 @@ rtems_interrupt_level l;
} }
static uint8_t static uint8_t
hash_accept(struct tsec_private *mp, uint32_t tble, const uint8_t *enaddr) hash_prog(struct tsec_private *mp, uint32_t tble, const uint8_t *enaddr, int accept)
{ {
uint8_t s; uint8_t s;
uint32_t reg, bit;
s = ether_crc32_le(enaddr, ETHER_ADDR_LEN); s = ether_crc32_le(enaddr, ETHER_ADDR_LEN);
@@ -1413,7 +1417,16 @@ uint8_t s;
s = ((s&0x33) << 2) | ((s&0xcc) >> 2); s = ((s&0x33) << 2) | ((s&0xcc) >> 2);
s = ((s&0x55) << 1) | ((s&0xaa) >> 1); s = ((s&0x55) << 1) | ((s&0xaa) >> 1);
fec_wr( mp->base, tble + (s >> (5-2)), (1 << (31 - (s & 31))) ); reg = tble + ((s >> (5-2)) & ~3);
bit = 1 << (31 - (s & 31));
if ( accept ) {
if ( 0 == mp->mc_refcnt[s]++ )
fec_set( mp->base, reg, bit );
} else {
if ( mp->mc_refcnt[s] > 0 && 0 == --mp->mc_refcnt[s] )
fec_clr( mp->base, reg, bit );
}
} }
void void
@@ -1423,6 +1436,8 @@ int i;
for ( i=0; i<8*4; i+=4 ) { for ( i=0; i<8*4; i+=4 ) {
fec_wr( mp->base, TSEC_GADDR0 + i, 0 ); fec_wr( mp->base, TSEC_GADDR0 + i, 0 );
} }
for ( i=0; i<NUM_MC_HASHES; i++ )
mp->mc_refcnt[i] = 0;
} }
void void
@@ -1432,10 +1447,12 @@ int i;
for ( i=0; i<8*4; i+=4 ) { for ( i=0; i<8*4; i+=4 ) {
fec_wr( mp->base, TSEC_GADDR0 + i, 0xffffffff ); fec_wr( mp->base, TSEC_GADDR0 + i, 0xffffffff );
} }
for ( i=0; i<NUM_MC_HASHES; i++ )
mp->mc_refcnt[i]++;
} }
void static void
BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, uint8_t *enaddr) mcast_filter_prog(struct tsec_private *mp, uint8_t *enaddr, int accept)
{ {
static const uint8_t bcst={0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static const uint8_t bcst={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if ( ! (enaddr[0] & 0x01) ) { if ( ! (enaddr[0] & 0x01) ) {
@@ -1446,7 +1463,19 @@ static const uint8_t bcst={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
/* broadcast; ignore */ /* broadcast; ignore */
return; return;
} }
hash_accept(mp, TSEC_GADDR0, enaddr); hash_prog(mp, TSEC_GADDR0, enaddr, accept);
}
void
BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, uint8_t *enaddr)
{
mcast_filter_prog(mp, enaddr, 1 /* accept */);
}
void
BSP_tsec_mcast_filter_accept_del(struct tsec_private *mp, uint8_t *enaddr)
{
mcast_filter_prog(mp, enaddr, 0 /* delete */);
} }
void void