[ovs-dev] [vlan-maint 2/2] vswitchd: Make the MAC entry aging time configurable.
Ben Pfaff
blp at nicira.com
Mon Jan 23 22:43:53 UTC 2012
NICS-11.
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
lib/learning-switch.c | 6 ++++--
lib/mac-learning.c | 41 ++++++++++++++++++++++++++++++++++-------
lib/mac-learning.h | 10 +++++++---
ofproto/ofproto.c | 4 ++--
vswitchd/bridge.c | 14 ++++++++++++--
vswitchd/vswitch.xml | 6 ++++++
6 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index ca97054..5b1996c 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -96,7 +96,9 @@ lswitch_create(struct rconn *rconn, const struct lswitch_config *cfg)
sw->max_idle = cfg->max_idle;
sw->datapath_id = 0;
sw->last_features_request = time_now() - 1;
- sw->ml = cfg->mode == LSW_LEARN ? mac_learning_create() : NULL;
+ sw->ml = (cfg->mode == LSW_LEARN
+ ? mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME)
+ : NULL);
sw->action_normal = cfg->mode == LSW_NORMAL;
flow_wildcards_init_exact(&sw->wc);
diff --git a/lib/mac-learning.c b/lib/mac-learning.c
index b7320e8..5efa44d 100644
--- a/lib/mac-learning.c
+++ b/lib/mac-learning.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,12 +36,12 @@ VLOG_DEFINE_THIS_MODULE(mac_learning);
COVERAGE_DEFINE(mac_learning_learned);
COVERAGE_DEFINE(mac_learning_expired);
-/* Returns the number of seconds since 'e' was last learned. */
+/* Returns the number of seconds since 'e' (within 'ml') was last learned. */
int
-mac_entry_age(const struct mac_entry *e)
+mac_entry_age(const struct mac_learning *ml, const struct mac_entry *e)
{
time_t remaining = e->expires - time_now();
- return MAC_ENTRY_IDLE_TIME - remaining;
+ return ml->idle_time - remaining;
}
static uint32_t
@@ -115,9 +115,18 @@ free_mac_entry(struct mac_learning *ml, struct mac_entry *e)
list_push_front(&ml->free, &e->lru_node);
}
-/* Creates and returns a new MAC learning table. */
+static unsigned int
+normalize_idle_time(unsigned int idle_time)
+{
+ return (idle_time < 15 ? 15
+ : idle_time > 3600 ? 3600
+ : idle_time);
+}
+
+/* Creates and returns a new MAC learning table with an initial MAC aging
+ * timeout of 'idle_time' seconds. */
struct mac_learning *
-mac_learning_create(void)
+mac_learning_create(unsigned int idle_time)
{
struct mac_learning *ml;
int i;
@@ -134,6 +143,7 @@ mac_learning_create(void)
}
ml->secret = random_uint32();
ml->flood_vlans = NULL;
+ ml->idle_time = normalize_idle_time(idle_time);
return ml;
}
@@ -164,6 +174,23 @@ mac_learning_set_flood_vlans(struct mac_learning *ml, unsigned long *bitmap)
return ret;
}
+/* Changes the MAC agin timeout of 'ml' to 'idle_time' seconds. */
+void
+mac_learning_set_idle_time(struct mac_learning *ml, unsigned int idle_time)
+{
+ idle_time = normalize_idle_time(idle_time);
+ if (idle_time != ml->idle_time) {
+ struct mac_entry *e;
+ int delta;
+
+ delta = (int) idle_time - (int) ml->idle_time;
+ LIST_FOR_EACH (e, lru_node, &ml->lrus) {
+ e->expires += delta;
+ }
+ ml->idle_time = idle_time;
+ }
+}
+
static bool
is_learning_vlan(const struct mac_learning *ml, uint16_t vlan)
{
@@ -222,7 +249,7 @@ mac_learning_learn(struct mac_learning *ml,
/* Make the entry most-recently-used. */
list_remove(&e->lru_node);
list_push_back(&ml->lrus, &e->lru_node);
- e->expires = time_now() + MAC_ENTRY_IDLE_TIME;
+ e->expires = time_now() + ml->idle_time;
if (lock_type == GRAT_ARP_LOCK_SET) {
e->grat_arp_lock = time_now() + MAC_GRAT_ARP_LOCK_TIME;
}
diff --git a/lib/mac-learning.h b/lib/mac-learning.h
index 9c59fa0..9a5a52e 100644
--- a/lib/mac-learning.h
+++ b/lib/mac-learning.h
@@ -22,6 +22,8 @@
#include "packets.h"
#include "tag.h"
+struct mac_learning;
+
#define MAC_HASH_BITS 10
#define MAC_HASH_MASK (MAC_HASH_SIZE - 1)
#define MAC_HASH_SIZE (1u << MAC_HASH_BITS)
@@ -29,7 +31,7 @@
#define MAC_MAX 2048
/* Time, in seconds, before expiring a mac_entry due to inactivity. */
-#define MAC_ENTRY_IDLE_TIME 300
+#define MAC_ENTRY_DEFAULT_IDLE_TIME 300
/* Time, in seconds, to lock an entry updated by a gratuitous ARP to avoid
* relearning based on a reflection from a bond slave. */
@@ -53,7 +55,7 @@ struct mac_entry {
tag_type tag; /* Tag for this learning entry. */
};
-int mac_entry_age(const struct mac_entry *);
+int mac_entry_age(const struct mac_learning *, const struct mac_entry *);
/* MAC learning table. */
struct mac_learning {
@@ -64,12 +66,14 @@ struct mac_learning {
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. */
+ unsigned int idle_time; /* Max age before deleting an entry. */
};
-struct mac_learning *mac_learning_create(void);
+struct mac_learning *mac_learning_create(unsigned int idle_time);
void mac_learning_destroy(struct mac_learning *);
bool mac_learning_set_flood_vlans(struct mac_learning *,
unsigned long *bitmap);
+void mac_learning_set_idle_time(struct mac_learning *, unsigned int idle_time);
tag_type mac_learning_learn(struct mac_learning *,
const uint8_t src[ETH_ADDR_LEN], uint16_t vlan,
uint16_t src_port, enum grat_arp_lock_type
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 9bcef2c..37e2ad9 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
* Copyright (c) 2010 Jean Tourrilhes - HP-Labs.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -515,7 +515,7 @@ ofproto_create(const char *datapath, const char *datapath_type,
} else {
p->ofhooks = &default_ofhooks;
p->aux = p;
- p->ml = mac_learning_create();
+ p->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
}
/* Pick final datapath ID. */
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index fb2ad83..b2303d0 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -1584,7 +1584,8 @@ bridge_unixctl_fdb_show(struct unixctl_conn *conn,
}
ds_put_format(&ds, "%5d %4d "ETH_ADDR_FMT" %3d\n",
br->ports[e->port]->ifaces[0]->dp_ifidx,
- e->vlan, ETH_ADDR_ARGS(e->mac), mac_entry_age(e));
+ e->vlan, ETH_ADDR_ARGS(e->mac),
+ mac_entry_age(br->ml, e));
}
unixctl_command_reply(conn, 200, ds_cstr(&ds));
ds_destroy(&ds);
@@ -1714,7 +1715,7 @@ bridge_create(const struct ovsrec_bridge *br_cfg)
br->name = xstrdup(br_cfg->name);
br->cfg = br_cfg;
- br->ml = mac_learning_create();
+ br->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
eth_addr_nicira_random(br->default_ea);
hmap_init(&br->ifaces);
@@ -1867,6 +1868,8 @@ bridge_reconfigure_one(struct bridge *br)
struct svec snoops, old_snoops;
struct shash_node *node;
enum ofproto_fail_mode fail_mode;
+ const char *idle_time_str;
+ int idle_time;
size_t i;
/* Collect old ports. */
@@ -1946,6 +1949,13 @@ bridge_reconfigure_one(struct bridge *br)
}
ofproto_set_fail_mode(br->ofproto, fail_mode);
+ /* Set the MAC learning aging timeout. */
+ idle_time_str = bridge_get_other_config(br->cfg, "mac-aging-time");
+ idle_time = (idle_time_str && atoi(idle_time_str)
+ ? atoi(idle_time_str)
+ : MAC_ENTRY_DEFAULT_IDLE_TIME);
+ mac_learning_set_idle_time(br->ml, idle_time);
+
/* Delete all flows if we're switching from connected to standalone or vice
* versa. (XXX Should we delete all flows if we are switching from one
* controller to another?) */
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 2f77669..c574434 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -437,6 +437,12 @@
does not have QoS configured, or if the port does not have a queue
with the specified ID, the default queue is used instead.
</dd>
+ <dt><code>mac-aging-time</code></dt>
+ <dd>
+ A positive integer specifying the maximum number of seconds to
+ retain a MAC learning entry for which no packets have been seen.
+ The default is currently 300 seconds (5 minutes).
+ </dd>
</dl>
</column>
</group>
--
1.7.2.5
More information about the dev
mailing list