From: Ethan Jackson Date: Fri, 22 Jul 2011 00:41:58 +0000 (-0700) Subject: mac-learning: Convert to hmap. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8ea45fdc0f5100487d40e501a0946b7dc3cac38a;p=openvswitch mac-learning: Convert to hmap. The mac-learning code predates the hmap data structure in OVS. For this reason, it rolled it's own hmap-like bucket concept. This patch converts it to use an hmap which makes the code slightly simpler and easier to understand. --- diff --git a/lib/mac-learning.c b/lib/mac-learning.c index ff240e97..4bb9f2a2 100644 --- a/lib/mac-learning.c +++ b/lib/mac-learning.c @@ -68,23 +68,15 @@ make_unknown_mac_tag(const struct mac_learning *ml, return tag_create_deterministic(h); } -static struct list * -mac_table_bucket(const struct mac_learning *ml, - const uint8_t mac[ETH_ADDR_LEN], - uint16_t vlan) -{ - uint32_t hash = mac_table_hash(mac, vlan); - const struct list *list = &ml->table[hash & MAC_HASH_MASK]; - return (struct list *) list; -} - static struct mac_entry * -search_bucket(struct list *bucket, const uint8_t mac[ETH_ADDR_LEN], - uint16_t vlan) +mac_entry_lookup(const struct mac_learning *ml, + const uint8_t mac[ETH_ADDR_LEN], uint16_t vlan) { struct mac_entry *e; - LIST_FOR_EACH (e, hash_node, bucket) { - if (eth_addr_equals(e->mac, mac) && e->vlan == vlan) { + + HMAP_FOR_EACH_WITH_HASH (e, hmap_node, mac_table_hash(mac, vlan), + &ml->table) { + if (e->vlan == vlan && eth_addr_equals(e->mac, mac)) { return e; } } @@ -116,9 +108,7 @@ mac_learning_create(void) ml = xmalloc(sizeof *ml); list_init(&ml->lrus); list_init(&ml->free); - for (i = 0; i < MAC_HASH_SIZE; i++) { - list_init(&ml->table[i]); - } + hmap_init(&ml->table); for (i = 0; i < MAC_MAX; i++) { struct mac_entry *s = &ml->entries[i]; list_push_front(&ml->free, &s->lru_node); @@ -133,6 +123,7 @@ void mac_learning_destroy(struct mac_learning *ml) { if (ml) { + hmap_destroy(&ml->table); bitmap_free(ml->flood_vlans); free(ml); } @@ -185,18 +176,16 @@ mac_learning_insert(struct mac_learning *ml, const uint8_t src_mac[ETH_ADDR_LEN], uint16_t vlan) { struct mac_entry *e; - struct list *bucket; - bucket = mac_table_bucket(ml, src_mac, vlan); - e = search_bucket(bucket, src_mac, vlan); + e = mac_entry_lookup(ml, src_mac, vlan); if (!e) { 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); - list_remove(&e->hash_node); + hmap_remove(&ml->table, &e->hmap_node); } - list_push_front(bucket, &e->hash_node); + hmap_insert(&ml->table, &e->hmap_node, mac_table_hash(src_mac, vlan)); memcpy(e->mac, src_mac, ETH_ADDR_LEN); e->vlan = vlan; e->tag = 0; @@ -247,8 +236,8 @@ mac_learning_lookup(const struct mac_learning *ml, * rarely that we revalidate every flow when it changes. */ return NULL; } else { - struct mac_entry *e = search_bucket(mac_table_bucket(ml, dst, vlan), - dst, vlan); + struct mac_entry *e = mac_entry_lookup(ml, dst, vlan); + assert(e == NULL || e->tag != 0); if (tag) { /* Tag either the learned port or the lack thereof. */ @@ -263,7 +252,7 @@ mac_learning_lookup(const struct mac_learning *ml, void mac_learning_expire(struct mac_learning *ml, struct mac_entry *e) { - list_remove(&e->hash_node); + hmap_remove(&ml->table, &e->hmap_node); list_remove(&e->lru_node); list_push_front(&ml->free, &e->lru_node); } diff --git a/lib/mac-learning.h b/lib/mac-learning.h index d9fa433c..d2f28744 100644 --- a/lib/mac-learning.h +++ b/lib/mac-learning.h @@ -18,15 +18,12 @@ #define MAC_LEARNING_H 1 #include +#include "hmap.h" #include "list.h" #include "packets.h" #include "tag.h" #include "timeval.h" -#define MAC_HASH_BITS 10 -#define MAC_HASH_MASK (MAC_HASH_SIZE - 1) -#define MAC_HASH_SIZE (1u << MAC_HASH_BITS) - #define MAC_MAX 2048 /* Time, in seconds, before expiring a mac_entry due to inactivity. */ @@ -38,7 +35,7 @@ /* A MAC learning table entry. */ struct mac_entry { - struct list hash_node; /* Element in a mac_learning 'table' list. */ + struct hmap_node hmap_node; /* Node in a mac_learning hmap. */ struct list lru_node; /* Element in 'lrus' or 'free' list. */ time_t expires; /* Expiration time. */ time_t grat_arp_lock; /* Gratuitous ARP lock expiration time. */ @@ -78,10 +75,10 @@ static inline bool mac_entry_is_grat_arp_locked(const struct mac_entry *mac) /* 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 table[MAC_HASH_SIZE]; /* Hash table. */ 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. */