- struct mac_entry *e;
- LIST_FOR_EACH (e, struct mac_entry, hash_node, bucket) {
- if (eth_addr_equals(e->mac, mac) && e->vlan == vlan) {
- return e;
+ if (mac_entry_get_port(ml, e) != port) {
+ ml->need_revalidate = true;
+
+ if (e->mlport) {
+ struct mac_learning_port *mlport = e->mlport;
+ list_remove(&e->port_lru_node);
+
+ if (list_is_empty(&mlport->port_lrus)) {
+ ovs_assert(mlport->heap_node.priority == 1);
+ hmap_remove(&ml->ports_by_ptr, &mlport->hmap_node);
+ heap_remove(&ml->ports_by_usage, &mlport->heap_node);
+ free(mlport);
+ } else {
+ ovs_assert(mlport->heap_node.priority > 1);
+ heap_change(&ml->ports_by_usage, &mlport->heap_node,
+ mlport->heap_node.priority - 1);
+ }
+ e->mlport = NULL;
+ }
+
+ if (port) {
+ struct mac_learning_port *mlport;
+
+ mlport = mac_learning_port_lookup(ml, port);
+ if (!mlport) {
+ mlport = xzalloc(sizeof *mlport);
+ hmap_insert(&ml->ports_by_ptr, &mlport->hmap_node,
+ hash_pointer(port, ml->secret));
+ heap_insert(&ml->ports_by_usage, &mlport->heap_node, 1);
+ mlport->port = port;
+ list_init(&mlport->port_lrus);
+ } else {
+ heap_change(&ml->ports_by_usage, &mlport->heap_node,
+ mlport->heap_node.priority + 1);
+ }
+ list_push_back(&mlport->port_lrus, &e->port_lru_node);
+ e->mlport = mlport;