-/* Copyright (c) 2011, 2012 Nicira, Inc.
+/* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
bool fast; /* True if using fast probe interval. */
bool negotiated; /* True if LACP negotiations were successful. */
bool update; /* True if lacp_update() needs to be called. */
+ bool fallback_ab; /* True if fallback to active-backup on LACP failure. */
atomic_int ref_cnt;
};
static struct list all_lacps__ = LIST_INITIALIZER(&all_lacps__);
static struct list *const all_lacps OVS_GUARDED_BY(mutex) = &all_lacps__;
-static void lacp_update_attached(struct lacp *) OVS_REQ_WRLOCK(mutex);
+static void lacp_update_attached(struct lacp *) OVS_REQUIRES(mutex);
-static void slave_destroy(struct slave *) OVS_REQ_WRLOCK(mutex);
-static void slave_set_defaulted(struct slave *) OVS_REQ_WRLOCK(mutex);
-static void slave_set_expired(struct slave *) OVS_REQ_WRLOCK(mutex);
+static void slave_destroy(struct slave *) OVS_REQUIRES(mutex);
+static void slave_set_defaulted(struct slave *) OVS_REQUIRES(mutex);
+static void slave_set_expired(struct slave *) OVS_REQUIRES(mutex);
static void slave_get_actor(struct slave *, struct lacp_info *actor)
- OVS_REQ_WRLOCK(mutex);
+ OVS_REQUIRES(mutex);
static void slave_get_priority(struct slave *, struct lacp_info *priority)
- OVS_REQ_WRLOCK(mutex);
+ OVS_REQUIRES(mutex);
static bool slave_may_tx(const struct slave *)
- OVS_REQ_WRLOCK(mutex);
+ OVS_REQUIRES(mutex);
static struct slave *slave_lookup(const struct lacp *, const void *slave)
- OVS_REQ_WRLOCK(mutex);
+ OVS_REQUIRES(mutex);
static bool info_tx_equal(struct lacp_info *, struct lacp_info *)
- OVS_REQ_WRLOCK(mutex);
+ OVS_REQUIRES(mutex);
static unixctl_cb_func lacp_unixctl_show;
struct lacp *lacp;
if (ovsthread_once_start(&once)) {
- ovs_mutex_init(&mutex, PTHREAD_MUTEX_RECURSIVE);
+ ovs_mutex_init_recursive(&mutex);
ovsthread_once_done(&once);
}
lacp->active = s->active;
lacp->fast = s->fast;
+
+ if (lacp->fallback_ab != s->fallback_ab_cfg) {
+ lacp->fallback_ab = s->fallback_ab_cfg;
+ lacp->update = true;
+ }
+
ovs_mutex_unlock(&mutex);
}
}
static bool
-slave_may_enable__(struct slave *slave) OVS_REQ_WRLOCK(mutex)
+slave_may_enable__(struct slave *slave) OVS_REQUIRES(mutex)
{
/* The slave may be enabled if it's attached to an aggregator and its
* partner is synchronized.*/
- return slave->attached && (slave->partner.state & LACP_STATE_SYNC);
+ return slave->attached && (slave->partner.state & LACP_STATE_SYNC
+ || (slave->lacp && slave->lacp->fallback_ab
+ && slave->status == LACP_DEFAULTED));
}
/* This function should be called before enabling 'slave_' to send or receive
/* Updates the attached status of all slaves controlled by 'lacp' and sets its
* negotiated parameter to true if any slaves are attachable. */
static void
-lacp_update_attached(struct lacp *lacp) OVS_REQ_WRLOCK(mutex)
+lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
{
struct slave *lead, *slave;
struct lacp_info lead_pri;
}
if (slave->status == LACP_DEFAULTED) {
+ if (lacp->fallback_ab) {
+ slave->attached = true;
+ }
continue;
}
if (lead) {
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
- if (lead->partner.key != slave->partner.key
+ if ((lacp->fallback_ab && slave->status == LACP_DEFAULTED)
+ || lead->partner.key != slave->partner.key
|| !eth_addr_equals(lead->partner.sys_id,
slave->partner.sys_id)) {
slave->attached = false;
}
static void
-slave_destroy(struct slave *slave) OVS_REQ_WRLOCK(mutex)
+slave_destroy(struct slave *slave) OVS_REQUIRES(mutex)
{
if (slave) {
struct lacp *lacp = slave->lacp;
}
static void
-slave_set_defaulted(struct slave *slave) OVS_REQ_WRLOCK(mutex)
+slave_set_defaulted(struct slave *slave) OVS_REQUIRES(mutex)
{
memset(&slave->partner, 0, sizeof slave->partner);
}
static void
-slave_set_expired(struct slave *slave) OVS_REQ_WRLOCK(mutex)
+slave_set_expired(struct slave *slave) OVS_REQUIRES(mutex)
{
slave->status = LACP_EXPIRED;
slave->partner.state |= LACP_STATE_TIME;
static void
slave_get_actor(struct slave *slave, struct lacp_info *actor)
- OVS_REQ_WRLOCK(mutex)
+ OVS_REQUIRES(mutex)
{
struct lacp *lacp = slave->lacp;
uint16_t key;
* link. */
static void
slave_get_priority(struct slave *slave, struct lacp_info *priority)
- OVS_REQ_WRLOCK(mutex)
+ OVS_REQUIRES(mutex)
{
uint16_t partner_priority, actor_priority;
}
static bool
-slave_may_tx(const struct slave *slave) OVS_REQ_WRLOCK(mutex)
+slave_may_tx(const struct slave *slave) OVS_REQUIRES(mutex)
{
return slave->lacp->active || slave->status != LACP_DEFAULTED;
}
static struct slave *
-slave_lookup(const struct lacp *lacp, const void *slave_) OVS_REQ_WRLOCK(mutex)
+slave_lookup(const struct lacp *lacp, const void *slave_) OVS_REQUIRES(mutex)
{
struct slave *slave;
}
\f
static struct lacp *
-lacp_find(const char *name) OVS_REQ_WRLOCK(&mutex)
+lacp_find(const char *name) OVS_REQUIRES(mutex)
{
struct lacp *lacp;
}
static void
-lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQ_WRLOCK(&mutex)
+lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
{
struct shash slave_shash = SHASH_INITIALIZER(&slave_shash);
const struct shash_node **sorted_slaves = NULL;