X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Flacp.c;h=49ae5e5a2d41933ef161e49e16eaae48a5c20590;hb=HEAD;hp=82698746dec359eeff1f9d4dc9a8b576377bffcd;hpb=bd3ad2c3508aaf7283f3ee041ecd3e5108471b21;p=sliver-openvswitch.git diff --git a/lib/lacp.c b/lib/lacp.c index 82698746d..49ae5e5a2 100644 --- a/lib/lacp.c +++ b/lib/lacp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2012 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. @@ -18,12 +18,14 @@ #include +#include "connectivity.h" #include "dynamic-string.h" #include "hash.h" #include "hmap.h" #include "ofpbuf.h" #include "packets.h" #include "poll-loop.h" +#include "seq.h" #include "shash.h" #include "timer.h" #include "timeval.h" @@ -102,8 +104,9 @@ struct lacp { 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; + struct ovs_refcount ref_cnt; }; struct slave { @@ -178,7 +181,8 @@ parse_lacp_packet(const struct ofpbuf *b) { 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 @@ -207,13 +211,13 @@ lacp_create(void) OVS_EXCLUDED(mutex) 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 = xzalloc(sizeof *lacp); hmap_init(&lacp->slaves); - atomic_init(&lacp->ref_cnt, 1); + ovs_refcount_init(&lacp->ref_cnt); ovs_mutex_lock(&mutex); list_push_back(all_lacps, &lacp->node); @@ -226,9 +230,7 @@ lacp_ref(const struct lacp *lacp_) { struct lacp *lacp = CONST_CAST(struct lacp *, lacp_); if (lacp) { - int orig; - atomic_add(&lacp->ref_cnt, 1, &orig); - ovs_assert(orig > 0); + ovs_refcount_ref(&lacp->ref_cnt); } return lacp; } @@ -237,15 +239,7 @@ lacp_ref(const struct lacp *lacp_) void lacp_unref(struct lacp *lacp) OVS_EXCLUDED(mutex) { - int orig; - - if (!lacp) { - return; - } - - atomic_sub(&lacp->ref_cnt, 1, &orig); - ovs_assert(orig > 0); - if (orig == 1) { + if (lacp && ovs_refcount_unref(&lacp->ref_cnt) == 1) { struct slave *slave, *next; ovs_mutex_lock(&mutex); @@ -283,6 +277,12 @@ lacp_configure(struct lacp *lacp, const struct lacp_settings *s) 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); } @@ -345,18 +345,18 @@ out: 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; + ovs_mutex_lock(&mutex); + ret = lacp->negotiated ? LACP_NEGOTIATED : LACP_CONFIGURED; + ovs_mutex_unlock(&mutex); + 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 @@ -450,7 +450,9 @@ 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 @@ -500,11 +502,16 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex) ovs_mutex_lock(&mutex); HMAP_FOR_EACH (slave, node, &lacp->slaves) { if (timer_expired(&slave->rx)) { + enum slave_status old_status = slave->status; + if (slave->status == LACP_CURRENT) { slave_set_expired(slave); } else if (slave->status == LACP_EXPIRED) { slave_set_defaulted(slave); } + if (slave->status != old_status) { + seq_change(connectivity_seq_get()); + } } } @@ -535,6 +542,7 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex) : LACP_SLOW_TIME_TX); timer_set_duration(&slave->tx, duration); + seq_change(connectivity_seq_get()); } } ovs_mutex_unlock(&mutex); @@ -587,6 +595,9 @@ lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex) } if (slave->status == LACP_DEFAULTED) { + if (lacp->fallback_ab) { + slave->attached = true; + } continue; } @@ -603,7 +614,8 @@ lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex) 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; @@ -884,7 +896,7 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex) status = "defaulted"; break; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } ds_put_format(ds, "\nslave: %s: %s %s\n", slave->name, status,