With this patch, the LACP module may be manually configured to use
an arbitrary transmission rate set in the database.
---
lib/lacp.c | 64 ++++++++++++++++++++++++++++++++++++++++++--------
lib/lacp.h | 9 ++++++-
vswitchd/bridge.c | 16 +++++++++++-
vswitchd/vswitch.xml | 16 ++++++++----
4 files changed, 87 insertions(+), 18 deletions(-)
diff --git a/lib/lacp.c b/lib/lacp.c
index 82d07c1..e0ad639 100644
--- a/lib/lacp.c
+++ b/lib/lacp.c
@@ -48,7 +48,8 @@ struct lacp {
struct hmap slaves; /* Slaves this LACP object controls. */
struct slave *key_slave; /* Slave whose ID will be the aggregation key. */
- bool fast; /* Fast or Slow LACP time. */
+ enum lacp_time lacp_time; /* Fast, Slow or Custom LACP time. */
+ long long int custom_time; /* LACP_CUSTOM_TIME transmission rate. */
bool negotiated; /* True if LACP negotiations were successful. */
bool update; /* True if lacp_update() needs to be called. */
};
@@ -180,7 +181,8 @@ lacp_configure(struct lacp *lacp, const struct
lacp_settings *s)
memcpy(lacp->sys_id, s->id, ETH_ADDR_LEN);
lacp->sys_priority = s->priority;
lacp->active = s->active;
- lacp->fast = s->fast;
+ lacp->lacp_time = s->lacp_time;
+ lacp->custom_time = s->custom_time;
}
/* Returns true if 'lacp' is configured in active mode, false if 'lacp' is
@@ -199,10 +201,23 @@ lacp_process_pdu(struct lacp *lacp, const void *slave_,
const struct lacp_pdu *pdu)
{
struct slave *slave = slave_lookup(lacp, slave_);
+ long long int tx_rate;
+
+ switch (lacp->lacp_time) {
+ case LACP_TIME_FAST:
+ tx_rate = LACP_FAST_TIME_TX;
+ break;
+ case LACP_TIME_SLOW:
+ tx_rate = LACP_SLOW_TIME_TX;
+ break;
+ case LACP_TIME_CUSTOM:
+ tx_rate = lacp->custom_time;
+ break;
+ default: NOT_REACHED();
+ }
slave->status = LACP_CURRENT;
- timer_set_duration(&slave->rx, LACP_RX_MULTIPLIER *
- (lacp->fast ? LACP_FAST_TIME_TX : LACP_SLOW_TIME_TX));
+ timer_set_duration(&slave->rx, LACP_RX_MULTIPLIER * tx_rate);
slave->ntt_actor = pdu->partner;
@@ -354,15 +369,21 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu)
if (timer_expired(&slave->tx)
|| !info_tx_equal(&actor, &slave->ntt_actor)) {
+ long long int duration;
slave->ntt_actor = actor;
compose_lacp_pdu(&actor, &slave->partner, &pdu);
send_pdu(slave->aux, &pdu);
- timer_set_duration(&slave->tx,
- (slave->partner.state & LACP_STATE_TIME
- ? LACP_FAST_TIME_TX
- : LACP_SLOW_TIME_TX));
+ if (lacp->lacp_time == LACP_TIME_CUSTOM) {
+ duration = lacp->custom_time;
+ } else {
+ duration = (slave->partner.state & LACP_STATE_TIME
+ ? LACP_FAST_TIME_TX
+ : LACP_SLOW_TIME_TX);
+ }
+
+ timer_set_duration(&slave->tx, duration);
}
}
}
@@ -474,10 +495,18 @@ slave_set_defaulted(struct slave *slave)
static void
slave_set_expired(struct slave *slave)
{
+ struct lacp *lacp = slave->lacp;
+
slave->status = LACP_EXPIRED;
slave->partner.state |= LACP_STATE_TIME;
slave->partner.state &= ~LACP_STATE_SYNC;
- timer_set_duration(&slave->rx, LACP_RX_MULTIPLIER * LACP_FAST_TIME_TX);
+
+ /* The spec says we should wait LACP_RX_MULTIPLIER * LACP_FAST_TIME_TX.
+ * This doesn't make sense when using custom times which can be much
+ * smaller than LACP_FAST_TIME. */
+ timer_set_duration(&slave->rx, (lacp->lacp_time == LACP_TIME_CUSTOM
+ ? lacp->custom_time
+ : LACP_RX_MULTIPLIER * LACP_FAST_TIME_TX));
}
static void
@@ -489,7 +518,7 @@ slave_get_actor(struct slave *slave, struct lacp_info
*actor)
state |= LACP_STATE_ACT;
}
- if (slave->lacp->fast) {
+ if (slave->lacp->lacp_time != LACP_TIME_SLOW) {
state |= LACP_STATE_TIME;
}
@@ -671,6 +700,21 @@ lacp_unixctl_show(struct unixctl_conn *conn,
}
ds_put_cstr(&ds, "\n");
+ ds_put_cstr(&ds, "\tlacp_time: ");
+ switch (lacp->lacp_time) {
+ case LACP_TIME_FAST:
+ ds_put_cstr(&ds, "fast\n");
+ break;
+ case LACP_TIME_SLOW:
+ ds_put_cstr(&ds, "slow\n");
+ break;
+ case LACP_TIME_CUSTOM:
+ ds_put_format(&ds, "custom (%lld)\n", lacp->custom_time);
+ break;
+ default:
+ ds_put_cstr(&ds, "unknown\n");
+ }
+
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
char *status;
struct lacp_info actor;
diff --git a/lib/lacp.h b/lib/lacp.h
index f2c9469..927dfe6 100644
--- a/lib/lacp.h
+++ b/lib/lacp.h
@@ -75,12 +75,19 @@ const struct lacp_pdu *parse_lacp_packet(const struct
ofpbuf *);
/* LACP Protocol Implementation. */
+enum lacp_time {
+ LACP_TIME_FAST,
+ LACP_TIME_SLOW,
+ LACP_TIME_CUSTOM
+};
+
struct lacp_settings {
char *name;
uint8_t id[ETH_ADDR_LEN];
uint16_t priority;
bool active;
- bool fast;
+ enum lacp_time lacp_time;
+ long long int custom_time;
};
void lacp_init(void);
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index a0762fe..d7d7214 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -3117,6 +3117,8 @@ port_reconfigure_lacp(struct port *port)
{
static struct lacp_settings s;
struct iface *iface;
+ const char *lacp_time;
+ long long int custom_time;
int priority;
if (!enable_lacp(port, &s.active)) {
@@ -3135,8 +3137,18 @@ port_reconfigure_lacp(struct port *port)
? priority
: UINT16_MAX - !list_is_short(&port->ifaces));
- s.fast = !strcmp(get_port_other_config(port->cfg, "lacp-time", "slow"),
- "fast");
+ lacp_time = get_port_other_config(port->cfg, "lacp-time", "slow");
+ custom_time = atoi(lacp_time);
+ if (!strcmp(lacp_time, "fast")) {
+ s.lacp_time = LACP_TIME_FAST;
+ } else if (!strcmp(lacp_time, "slow")) {
+ s.lacp_time = LACP_TIME_SLOW;
+ } else if (custom_time > 0) {
+ s.lacp_time = LACP_TIME_CUSTOM;
+ s.custom_time = custom_time;
+ } else {
+ s.lacp_time = LACP_TIME_SLOW;
+ }
if (!port->lacp) {
port->lacp = lacp_create();
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 566e6cf..bf452b3 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -654,11 +654,17 @@
and 65535.</dd>
<dt><code>lacp-time</code></dt>
<dd> The LACP timing which should be used on this
- <ref table="Port"/>. Possible values are <code>fast</code> and
- <code>slow</code>. By default <code>slow</code> is used. When
- configured to be <code>fast</code> more frequent LACP heartbeats
- will be requested causing connectivity problems to be detected more
- quickly.</dd>
+ <ref table="Port"/>. Possible values are <code>fast</code>,
+ <code>slow</code> and a positive number of milliseconds. By
+ default <code>slow</code> is used. When configured to be
+ <code>fast</code> more frequent LACP heartbeats will be requested
+ causing connectivity problems to be detected more quickly. Users
+ may manually set a heartbeat transmission rate to increase the
+ fault detection speed further. When manually set, OVS expects the
+ transmission rate to be configured the same on the partner
+ switch. Manually setting <code>lacp-time</code> to something other
+ than <code>fast</code> or <code>slow</code> is not supported in the
+ LACP specification.</dd>
</dl>
</column>
</group>
--
1.7.4.2
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev