X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Flacp.c;h=5d9085023a604c65cf435f5f7a6c81157d63b363;hb=bbb8dee92d639331e8bd81823638267dcc895396;hp=374d915a94549e27c6b513d3b7d4b1da30d26ef1;hpb=29985e75480f5133a16b8921cbce6e5a4002f5f1;p=sliver-openvswitch.git diff --git a/lib/lacp.c b/lib/lacp.c index 374d915a9..5d9085023 100644 --- a/lib/lacp.c +++ b/lib/lacp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 Nicira, Inc. +/* Copyright (c) 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ #include #include "lacp.h" -#include #include #include "dynamic-string.h" @@ -48,6 +47,7 @@ VLOG_DEFINE_THIS_MODULE(lacp); #define LACP_RX_MULTIPLIER 3 /* Multiply by TX rate to get RX rate. */ #define LACP_INFO_LEN 15 +OVS_PACKED( struct lacp_info { ovs_be16 sys_priority; /* System priority. */ uint8_t sys_id[ETH_ADDR_LEN]; /* System ID. */ @@ -55,10 +55,11 @@ struct lacp_info { ovs_be16 port_priority; /* Port priority. */ ovs_be16 port_id; /* Port ID. */ uint8_t state; /* State mask. See LACP_STATE macros. */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(LACP_INFO_LEN == sizeof(struct lacp_info)); #define LACP_PDU_LEN 110 +OVS_PACKED( struct lacp_pdu { uint8_t subtype; /* Always 1. */ uint8_t version; /* Always 1. */ @@ -77,7 +78,7 @@ struct lacp_pdu { uint8_t collector_len; /* Always 16. */ ovs_be16 collector_delay; /* Maximum collector delay. Set to UINT16_MAX. */ uint8_t z3[64]; /* Combination of several fields. Always 0. */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(LACP_PDU_LEN == sizeof(struct lacp_pdu)); /* Implementation. */ @@ -101,6 +102,8 @@ 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. */ + + int ref_cnt; }; struct slave { @@ -198,14 +201,31 @@ lacp_create(void) lacp = xzalloc(sizeof *lacp); hmap_init(&lacp->slaves); list_push_back(&all_lacps, &lacp->node); + lacp->ref_cnt = 1; + return lacp; +} + +struct lacp * +lacp_ref(const struct lacp *lacp_) +{ + struct lacp *lacp = CONST_CAST(struct lacp *, lacp_); + if (lacp) { + ovs_assert(lacp->ref_cnt > 0); + lacp->ref_cnt++; + } return lacp; } /* Destroys 'lacp' and its slaves. Does nothing if 'lacp' is NULL. */ void -lacp_destroy(struct lacp *lacp) +lacp_unref(struct lacp *lacp) { - if (lacp) { + if (!lacp) { + return; + } + + ovs_assert(lacp->ref_cnt > 0); + if (!--lacp->ref_cnt) { struct slave *slave, *next; HMAP_FOR_EACH_SAFE (slave, next, node, &lacp->slaves) { @@ -223,7 +243,7 @@ lacp_destroy(struct lacp *lacp) void lacp_configure(struct lacp *lacp, const struct lacp_settings *s) { - assert(!eth_addr_is_zero(s->id)); + ovs_assert(!eth_addr_is_zero(s->id)); if (!lacp->name || strcmp(s->name, lacp->name)) { free(lacp->name); @@ -261,6 +281,10 @@ lacp_process_packet(struct lacp *lacp, const void *slave_, const struct lacp_pdu *pdu; long long int tx_rate; + if (!slave) { + return; + } + pdu = parse_lacp_packet(packet); if (!pdu) { VLOG_WARN_RL(&rl, "%s: received an unparsable LACP PDU.", lacp->name); @@ -356,6 +380,10 @@ lacp_slave_carrier_changed(const struct lacp *lacp, const void *slave_) if (lacp) { struct slave *slave = slave_lookup(lacp, slave_); + if (!slave) { + return; + } + if (slave->status == LACP_CURRENT || slave->lacp->active) { slave_set_expired(slave); } @@ -377,27 +405,21 @@ bool lacp_slave_may_enable(const struct lacp *lacp, const void *slave_) { if (lacp) { - return slave_may_enable__(slave_lookup(lacp, slave_)); + struct slave *slave = slave_lookup(lacp, slave_); + return slave ? slave_may_enable__(slave) : false; } else { return true; } } -/* Returns the port ID used for 'slave_' in LACP communications. */ -uint16_t -lacp_slave_get_port_id(const struct lacp *lacp, const void *slave_) -{ - struct slave *slave = slave_lookup(lacp, slave_); - return slave->port_id; -} - /* Returns true if partner information on 'slave_' is up to date. 'slave_' * not being current, generally indicates a connectivity problem, or a * misconfigured (or broken) partner. */ bool lacp_slave_is_current(const struct lacp *lacp, const void *slave_) { - return slave_lookup(lacp, slave_)->status != LACP_DEFAULTED; + struct slave *slave = slave_lookup(lacp, slave_); + return slave ? slave->status != LACP_DEFAULTED : false; } /* This function should be called periodically to update 'lacp'. */ @@ -750,7 +772,9 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) ds_put_format(ds, "\tsys_priority: %u\n", lacp->sys_priority); ds_put_cstr(ds, "\taggregation key: "); if (lacp->key_slave) { - ds_put_format(ds, "%u", lacp->key_slave->port_id); + ds_put_format(ds, "%u", lacp->key_slave->key + ? lacp->key_slave->key + : lacp->key_slave->port_id); } else { ds_put_cstr(ds, "none"); }