-/* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
+/* Copyright (c) 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
const struct lacp_pdu *pdu;
- pdu = ofpbuf_at(b, (uint8_t *)b->l3 - (uint8_t *)b->data, LACP_PDU_LEN);
+ pdu = ofpbuf_at(b, (uint8_t *)ofpbuf_l3(b) - (uint8_t *)ofpbuf_data(b),
+ LACP_PDU_LEN);
if (pdu && pdu->subtype == 1
&& pdu->actor_type == 1 && pdu->actor_len == 20
lacp_unixctl_show, NULL);
}
-/* Creates a LACP object. */
-struct lacp *
-lacp_create(void) OVS_EXCLUDED(mutex)
+static void
+lacp_lock(void) OVS_ACQUIRES(mutex)
{
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
- struct lacp *lacp;
if (ovsthread_once_start(&once)) {
ovs_mutex_init_recursive(&mutex);
ovsthread_once_done(&once);
}
+ ovs_mutex_lock(&mutex);
+}
+
+static void
+lacp_unlock(void) OVS_RELEASES(mutex)
+{
+ ovs_mutex_unlock(&mutex);
+}
+
+/* Creates a LACP object. */
+struct lacp *
+lacp_create(void) OVS_EXCLUDED(mutex)
+{
+ struct lacp *lacp;
lacp = xzalloc(sizeof *lacp);
hmap_init(&lacp->slaves);
ovs_refcount_init(&lacp->ref_cnt);
- ovs_mutex_lock(&mutex);
+ lacp_lock();
list_push_back(all_lacps, &lacp->node);
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
return lacp;
}
void
lacp_unref(struct lacp *lacp) OVS_EXCLUDED(mutex)
{
- if (lacp && ovs_refcount_unref(&lacp->ref_cnt) == 1) {
+ if (lacp && ovs_refcount_unref_relaxed(&lacp->ref_cnt) == 1) {
struct slave *slave, *next;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
HMAP_FOR_EACH_SAFE (slave, next, node, &lacp->slaves) {
slave_destroy(slave);
}
hmap_destroy(&lacp->slaves);
list_remove(&lacp->node);
free(lacp->name);
- ovs_refcount_destroy(&lacp->ref_cnt);
free(lacp);
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}
}
{
ovs_assert(!eth_addr_is_zero(s->id));
- ovs_mutex_lock(&mutex);
+ lacp_lock();
if (!lacp->name || strcmp(s->name, lacp->name)) {
free(lacp->name);
lacp->name = xstrdup(s->name);
lacp->update = true;
}
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}
/* Returns true if 'lacp' is configured in active mode, false if 'lacp' is
lacp_is_active(const struct lacp *lacp) OVS_EXCLUDED(mutex)
{
bool ret;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
ret = lacp->active;
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
return ret;
}
long long int tx_rate;
struct slave *slave;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
slave = slave_lookup(lacp, slave_);
if (!slave) {
goto out;
}
out:
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}
/* Returns the lacp_status of the given 'lacp' object (which may be NULL). */
enum lacp_status
lacp_status(const struct lacp *lacp) OVS_EXCLUDED(mutex)
{
- enum lacp_status ret;
+ if (lacp) {
+ enum lacp_status ret;
- ovs_mutex_lock(&mutex);
- if (!lacp) {
- ret = LACP_DISABLED;
- } else if (lacp->negotiated) {
- ret = LACP_NEGOTIATED;
+ lacp_lock();
+ ret = lacp->negotiated ? LACP_NEGOTIATED : LACP_CONFIGURED;
+ lacp_unlock();
+ return ret;
} else {
- ret = LACP_CONFIGURED;
+ /* Don't take 'mutex'. It might not even be initialized, since we
+ * don't know that any lacp object has been created. */
+ return LACP_DISABLED;
}
- ovs_mutex_unlock(&mutex);
- return ret;
}
/* Registers 'slave_' as subordinate to 'lacp'. This should be called at least
{
struct slave *slave;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
slave = slave_lookup(lacp, slave_);
if (!slave) {
slave = xzalloc(sizeof *slave);
slave_set_expired(slave);
}
}
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}
/* Unregisters 'slave_' with 'lacp'. */
{
struct slave *slave;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
slave = slave_lookup(lacp, slave_);
if (slave) {
slave_destroy(slave);
lacp->update = true;
}
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}
/* This function should be called whenever the carrier status of 'slave_' has
return;
}
- ovs_mutex_lock(&mutex);
+ lacp_lock();
slave = slave_lookup(lacp, slave_);
if (!slave) {
goto out;
}
out:
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}
static bool
struct slave *slave;
bool ret;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
slave = slave_lookup(lacp, slave_);
ret = slave ? slave_may_enable__(slave) : false;
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
return ret;
} else {
return true;
struct slave *slave;
bool ret;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
slave = slave_lookup(lacp, slave_);
ret = slave ? slave->status != LACP_DEFAULTED : false;
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
return ret;
}
{
struct slave *slave;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
if (timer_expired(&slave->rx)) {
enum slave_status old_status = slave->status;
seq_change(connectivity_seq_get());
}
}
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}
/* Causes poll_block() to wake up when lacp_run() needs to be called again. */
{
struct slave *slave;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
if (slave_may_tx(slave)) {
timer_wait(&slave->tx);
timer_wait(&slave->rx);
}
}
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}
\f
/* Static Helpers. */
struct ds ds = DS_EMPTY_INITIALIZER;
struct lacp *lacp;
- ovs_mutex_lock(&mutex);
+ lacp_lock();
if (argc > 1) {
lacp = lacp_find(argv[1]);
if (!lacp) {
ds_destroy(&ds);
out:
- ovs_mutex_unlock(&mutex);
+ lacp_unlock();
}