X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fmac-learning.c;h=b924e496d78cebef20fed0de1a82a43aabb01557;hb=ca2e44b48d767d6c7c96df42b1a36d0dcf3309dc;hp=5311ccf64b006de113f3bb3f8e6aec5318966397;hpb=711c48de9dc8047b6780299584526d17d4b8b906;p=sliver-openvswitch.git diff --git a/lib/mac-learning.c b/lib/mac-learning.c index 5311ccf64..b924e496d 100644 --- a/lib/mac-learning.c +++ b/lib/mac-learning.c @@ -31,6 +31,7 @@ * derivatives without specific, written prior permission. */ +#include #include "mac-learning.h" #include @@ -39,7 +40,8 @@ #include "hash.h" #include "list.h" -#include "openflow.h" +#include "openflow/openflow.h" +#include "timeval.h" #include "util.h" #define THIS_MODULE VLM_mac_learning @@ -55,8 +57,9 @@ struct mac_entry { struct list hash_node; /* Element in a mac_learning 'table' list. */ struct list lru_node; /* Element in mac_learning 'lrus' list. */ + time_t used; /* Last used time. */ uint8_t mac[ETH_ADDR_LEN]; /* Known MAC address. */ - uint16_t port; /* Port on which MAC was most recently seen. */ + int port; /* Port on which MAC was most recently seen. */ }; /* MAC learning table. */ @@ -125,38 +128,36 @@ mac_learning_learn(struct mac_learning *ml, struct mac_entry *e; struct list *bucket; - assert(src_port != OFPP_FLOOD); if (eth_addr_is_multicast(src_mac)) { - VLOG_DBG("multicast packet source "ETH_ADDR_FMT, - ETH_ADDR_ARGS(src_mac)); + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 30); + VLOG_DBG_RL(&rl, "multicast packet source "ETH_ADDR_FMT, + ETH_ADDR_ARGS(src_mac)); return false; } bucket = mac_table_bucket(ml, src_mac); e = search_bucket(bucket, src_mac); - if (e) { - /* Make 'e' most-recently-used. */ - list_remove(&e->lru_node); - list_push_back(&ml->lrus, &e->lru_node); - if (e->port == src_port) { - return false; - } - } else { - /* Learn a new address. - * First drop the least recently used mac source. */ + if (!e) { e = CONTAINER_OF(ml->lrus.next, struct mac_entry, lru_node); + memcpy(e->mac, src_mac, ETH_ADDR_LEN); if (e->hash_node.next) { list_remove(&e->hash_node); } - list_remove(&e->lru_node); - - /* Create new mac source. */ - memcpy(e->mac, src_mac, ETH_ADDR_LEN); list_push_front(bucket, &e->hash_node); - list_push_back(&ml->lrus, &e->lru_node); + e->port = -1; + } + + /* Make the entry most-recently-used. */ + list_remove(&e->lru_node); + list_push_back(&ml->lrus, &e->lru_node); + e->used = time_now(); + + /* Did we learn something? */ + if (e->port != src_port) { + e->port = src_port; + return true; } - e->port = src_port; - return true; + return false; } /* Looks up address 'dst' in 'ml'. Returns the port on which a frame destined @@ -167,7 +168,7 @@ mac_learning_lookup(const struct mac_learning *ml, { if (!eth_addr_is_multicast(dst)) { struct mac_entry *e = search_bucket(mac_table_bucket(ml, dst), dst); - if (e) { + if (e && time_now() - e->used < 60) { return e->port; } }