mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
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:
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user