X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Flacp.c;h=c51fac69da3b792af2566097809c5b5869793298;hb=d0040604727e1582abbc28fa62903a822453c99f;hp=22cba9429bb9a13cc804be21a5bec870f65a9d1e;hpb=5dab8eced8eeb7faf193e2a96d75b9ee30b4c3eb;p=openvswitch diff --git a/lib/lacp.c b/lib/lacp.c index 22cba942..c51fac69 100644 --- a/lib/lacp.c +++ b/lib/lacp.c @@ -25,6 +25,7 @@ #include "ofpbuf.h" #include "packets.h" #include "poll-loop.h" +#include "shash.h" #include "timer.h" #include "timeval.h" #include "unixctl.h" @@ -135,8 +136,7 @@ static bool slave_may_tx(const struct slave *); static struct slave *slave_lookup(const struct lacp *, const void *slave); static bool info_tx_equal(struct lacp_info *, struct lacp_info *); -static void lacp_unixctl_show(struct unixctl_conn *, const char *args, - void *aux); +static unixctl_cb_func lacp_unixctl_show; /* Populates 'pdu' with a LACP PDU comprised of 'actor' and 'partner'. */ static void @@ -187,7 +187,8 @@ parse_lacp_packet(const struct ofpbuf *b) void lacp_init(void) { - unixctl_command_register("lacp/show", "[port]", lacp_unixctl_show, NULL); + unixctl_command_register("lacp/show", "[port]", 0, 1, + lacp_unixctl_show, NULL); } /* Creates a LACP object. */ @@ -224,6 +225,8 @@ lacp_destroy(struct lacp *lacp) void lacp_configure(struct lacp *lacp, const struct lacp_settings *s) { + assert(!eth_addr_is_zero(s->id)); + if (!lacp->name || strcmp(s->name, lacp->name)) { free(lacp->name); lacp->name = xstrdup(s->name); @@ -240,7 +243,9 @@ lacp_configure(struct lacp *lacp, const struct lacp_settings *s) lacp->active = s->active; lacp->lacp_time = s->lacp_time; - lacp->custom_time = MAX(TIME_UPDATE_INTERVAL, s->custom_time); + lacp->custom_time = (s->lacp_time == LACP_TIME_CUSTOM + ? MAX(TIME_UPDATE_INTERVAL, s->custom_time) + : 0); } /* Returns true if 'lacp' is configured in active mode, false if 'lacp' is @@ -296,12 +301,17 @@ lacp_process_packet(struct lacp *lacp, const void *slave_, } } -/* Returns true if 'lacp' has successfully negotiated with its partner. False - * if 'lacp' is NULL. */ -bool -lacp_negotiated(const struct lacp *lacp) +/* Returns the lacp_status of the given 'lacp' object (which may be NULL). */ +enum lacp_status +lacp_status(const struct lacp *lacp) { - return lacp ? lacp->negotiated : false; + if (!lacp) { + return LACP_DISABLED; + } else if (lacp->negotiated) { + return LACP_NEGOTIATED; + } else { + return LACP_CONFIGURED; + } } /* Registers 'slave_' as subordinate to 'lacp'. This should be called at least @@ -379,12 +389,8 @@ lacp_slave_may_enable(const struct lacp *lacp, const void *slave_) struct slave *slave = slave_lookup(lacp, slave_); /* The slave may be enabled if it's attached to an aggregator and its - * partner is synchronized. The only exception is defaulted slaves. - * They are not required to have synchronized partners because they - * have no partners at all. They will only be attached if negotiations - * failed on all slaves in the bond. */ - return slave->attached && (slave->partner.state & LACP_STATE_SYNC - || slave->status == LACP_DEFAULTED); + * partner is synchronized.*/ + return slave->attached && (slave->partner.state & LACP_STATE_SYNC); } else { return true; } @@ -499,14 +505,13 @@ lacp_update_attached(struct lacp *lacp) HMAP_FOR_EACH (slave, node, &lacp->slaves) { struct lacp_info pri; - slave->attached = true; + slave->attached = false; /* XXX: In the future allow users to configure the expected system ID. * For now just special case loopback. */ if (eth_addr_equals(slave->partner.sys_id, slave->lacp->sys_id)) { VLOG_WARN_RL(&rl, "slave %s: Loopback detected. Slave is " "connected to its own bond", slave->name); - slave->attached = false; continue; } @@ -514,6 +519,7 @@ lacp_update_attached(struct lacp *lacp) continue; } + slave->attached = true; slave_get_priority(slave, &pri); if (!lead || memcmp(&pri, &lead_pri, sizeof pri) < 0) { @@ -526,8 +532,7 @@ lacp_update_attached(struct lacp *lacp) if (lead) { HMAP_FOR_EACH (slave, node, &lacp->slaves) { - if (slave->status == LACP_DEFAULTED - || lead->partner.key != slave->partner.key + if (lead->partner.key != slave->partner.key || !eth_addr_equals(lead->partner.sys_id, slave->partner.sys_id)) { slave->attached = false; @@ -724,42 +729,46 @@ static void ds_put_lacp_state(struct ds *ds, uint8_t state) { if (state & LACP_STATE_ACT) { - ds_put_cstr(ds, "activity "); + ds_put_cstr(ds, " activity"); } if (state & LACP_STATE_TIME) { - ds_put_cstr(ds, "timeout "); + ds_put_cstr(ds, " timeout"); } if (state & LACP_STATE_AGG) { - ds_put_cstr(ds, "aggregation "); + ds_put_cstr(ds, " aggregation"); } if (state & LACP_STATE_SYNC) { - ds_put_cstr(ds, "synchronized "); + ds_put_cstr(ds, " synchronized"); } if (state & LACP_STATE_COL) { - ds_put_cstr(ds, "collecting "); + ds_put_cstr(ds, " collecting"); } if (state & LACP_STATE_DIST) { - ds_put_cstr(ds, "distributing "); + ds_put_cstr(ds, " distributing"); } if (state & LACP_STATE_DEF) { - ds_put_cstr(ds, "defaulted "); + ds_put_cstr(ds, " defaulted"); } if (state & LACP_STATE_EXP) { - ds_put_cstr(ds, "expired "); + ds_put_cstr(ds, " expired"); } } static void lacp_print_details(struct ds *ds, struct lacp *lacp) { + struct shash slave_shash = SHASH_INITIALIZER(&slave_shash); + const struct shash_node **sorted_slaves = NULL; + struct slave *slave; + int i; ds_put_format(ds, "---- %s ----\n", lacp->name); ds_put_format(ds, "\tstatus: %s", lacp->active ? "active" : "passive"); @@ -797,9 +806,15 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) } HMAP_FOR_EACH (slave, node, &lacp->slaves) { + shash_add(&slave_shash, slave->name, slave); + } + sorted_slaves = shash_sort(&slave_shash); + + for (i = 0; i < shash_count(&slave_shash); i++) { char *status; struct lacp_info actor; + slave = sorted_slaves[i]->data; slave_get_actor(slave, &actor); switch (slave->status) { case LACP_CURRENT: @@ -830,7 +845,7 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) ntohs(actor.port_priority)); ds_put_format(ds, "\tactor key: %u\n", ntohs(actor.key)); - ds_put_cstr(ds, "\tactor state: "); + ds_put_cstr(ds, "\tactor state:"); ds_put_lacp_state(ds, actor.state); ds_put_cstr(ds, "\n\n"); @@ -844,21 +859,24 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) ntohs(slave->partner.port_priority)); ds_put_format(ds, "\tpartner key: %u\n", ntohs(slave->partner.key)); - ds_put_cstr(ds, "\tpartner state: "); + ds_put_cstr(ds, "\tpartner state:"); ds_put_lacp_state(ds, slave->partner.state); ds_put_cstr(ds, "\n"); } + + shash_destroy(&slave_shash); + free(sorted_slaves); } static void -lacp_unixctl_show(struct unixctl_conn *conn, - const char *args, void *aux OVS_UNUSED) +lacp_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[], + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; struct lacp *lacp; - if (strlen(args)) { - lacp = lacp_find(args); + if (argc > 1) { + lacp = lacp_find(argv[1]); if (!lacp) { unixctl_command_reply(conn, 501, "no such lacp object"); return;