summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
8e8d596)
The mac-learning implementation used a free list to keep track of
statically allocated table entries. This made the code slightly
more difficult to understand than the more straightforward heap
based strategy implemented by this patch.
mac_learning_create(void)
{
struct mac_learning *ml;
mac_learning_create(void)
{
struct mac_learning *ml;
ml = xmalloc(sizeof *ml);
list_init(&ml->lrus);
ml = xmalloc(sizeof *ml);
list_init(&ml->lrus);
- for (i = 0; i < MAC_MAX; i++) {
- struct mac_entry *s = &ml->entries[i];
- list_push_front(&ml->free, &s->lru_node);
- }
ml->secret = random_uint32();
ml->flood_vlans = NULL;
return ml;
ml->secret = random_uint32();
ml->flood_vlans = NULL;
return ml;
mac_learning_destroy(struct mac_learning *ml)
{
if (ml) {
mac_learning_destroy(struct mac_learning *ml)
{
if (ml) {
+ struct mac_entry *e, *next;
+
+ HMAP_FOR_EACH_SAFE (e, next, hmap_node, &ml->table) {
+ hmap_remove(&ml->table, &e->hmap_node);
+ free(e);
+ }
hmap_destroy(&ml->table);
hmap_destroy(&ml->table);
bitmap_free(ml->flood_vlans);
free(ml);
}
bitmap_free(ml->flood_vlans);
free(ml);
}
if (!e) {
uint32_t hash = mac_table_hash(ml, src_mac, vlan);
if (!e) {
uint32_t hash = mac_table_hash(ml, src_mac, vlan);
- if (!list_is_empty(&ml->free)) {
- e = mac_entry_from_lru_node(ml->free.next);
- } else {
- e = mac_entry_from_lru_node(ml->lrus.next);
- hmap_remove(&ml->table, &e->hmap_node);
+ if (hmap_count(&ml->table) >= MAC_MAX) {
+ get_lru(ml, &e);
+ mac_learning_expire(ml, e);
+ e = xmalloc(sizeof *e);
hmap_insert(&ml->table, &e->hmap_node, hash);
memcpy(e->mac, src_mac, ETH_ADDR_LEN);
e->vlan = vlan;
e->tag = 0;
e->grat_arp_lock = TIME_MIN;
hmap_insert(&ml->table, &e->hmap_node, hash);
memcpy(e->mac, src_mac, ETH_ADDR_LEN);
e->vlan = vlan;
e->tag = 0;
e->grat_arp_lock = TIME_MIN;
+ } else {
+ list_remove(&e->lru_node);
}
/* Mark 'e' as recently used. */
}
/* Mark 'e' as recently used. */
- list_remove(&e->lru_node);
list_push_back(&ml->lrus, &e->lru_node);
e->expires = time_now() + MAC_ENTRY_IDLE_TIME;
list_push_back(&ml->lrus, &e->lru_node);
e->expires = time_now() + MAC_ENTRY_IDLE_TIME;
-/* Expires 'e' from the 'ml' hash table. 'e' must not already be on the free
- * list. */
+/* Expires 'e' from the 'ml' hash table. */
void
mac_learning_expire(struct mac_learning *ml, struct mac_entry *e)
{
hmap_remove(&ml->table, &e->hmap_node);
list_remove(&e->lru_node);
void
mac_learning_expire(struct mac_learning *ml, struct mac_entry *e)
{
hmap_remove(&ml->table, &e->hmap_node);
list_remove(&e->lru_node);
- list_push_front(&ml->free, &e->lru_node);
}
/* Expires all the mac-learning entries in 'ml'. The tags in 'ml' are
}
/* Expires all the mac-learning entries in 'ml'. The tags in 'ml' are
while (get_lru(ml, &e)){
mac_learning_expire(ml, e);
}
while (get_lru(ml, &e)){
mac_learning_expire(ml, e);
}
+ hmap_shrink(&ml->table);
/* A MAC learning table entry. */
struct mac_entry {
struct hmap_node hmap_node; /* Node in a mac_learning hmap. */
/* A MAC learning table entry. */
struct mac_entry {
struct hmap_node hmap_node; /* Node in a mac_learning hmap. */
- struct list lru_node; /* Element in 'lrus' or 'free' list. */
+ struct list lru_node; /* Element in 'lrus' list. */
time_t expires; /* Expiration time. */
time_t grat_arp_lock; /* Gratuitous ARP lock expiration time. */
uint8_t mac[ETH_ADDR_LEN]; /* Known MAC address. */
time_t expires; /* Expiration time. */
time_t grat_arp_lock; /* Gratuitous ARP lock expiration time. */
uint8_t mac[ETH_ADDR_LEN]; /* Known MAC address. */
/* MAC learning table. */
struct mac_learning {
struct hmap table; /* Learning table. */
/* MAC learning table. */
struct mac_learning {
struct hmap table; /* Learning table. */
- struct list free; /* Not-in-use entries. */
struct list lrus; /* In-use entries, least recently used at the
front, most recently used at the back. */
struct list lrus; /* In-use entries, least recently used at the
front, most recently used at the back. */
- struct mac_entry entries[MAC_MAX]; /* All entries. */
uint32_t secret; /* Secret for randomizing hash table. */
unsigned long *flood_vlans; /* Bitmap of learning disabled VLANs. */
};
uint32_t secret; /* Secret for randomizing hash table. */
unsigned long *flood_vlans; /* Bitmap of learning disabled VLANs. */
};