X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fstp.c;h=814026306fc0cebb9e5284f92168a26244650c35;hb=5d386c0613024993566fb3bef13a1e33fa93e91c;hp=2ff9df7c56cf24eb76a515d7f944b88f851d6a44;hpb=bd54dbcdd77cfd85f4ea2a589b07f1da5c3119d5;p=sliver-openvswitch.git diff --git a/lib/stp.c b/lib/stp.c index 2ff9df7c5..814026306 100644 --- a/lib/stp.c +++ b/lib/stp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 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. @@ -26,8 +26,10 @@ #include #include #include "byte-order.h" +#include "connectivity.h" #include "ofpbuf.h" #include "packets.h" +#include "seq.h" #include "unixctl.h" #include "util.h" #include "vlog.h" @@ -146,7 +148,7 @@ struct stp { static struct ovs_mutex mutex; static struct list all_stps__ = LIST_INITIALIZER(&all_stps__); -static struct list *const all_stps OVS_GUARDED_BY(&mutex) = &all_stps__; +static struct list *const all_stps OVS_GUARDED_BY(mutex) = &all_stps__; #define FOR_EACH_ENABLED_PORT(PORT, STP) \ for ((PORT) = stp_next_enabled_port((STP), (STP)->ports); \ @@ -154,7 +156,7 @@ static struct list *const all_stps OVS_GUARDED_BY(&mutex) = &all_stps__; (PORT) = stp_next_enabled_port((STP), (PORT) + 1)) static struct stp_port * stp_next_enabled_port(const struct stp *stp, const struct stp_port *port) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { for (; port < &stp->ports[ARRAY_SIZE(stp->ports)]; port++) { if (port->state != STP_DISABLED) { @@ -166,57 +168,57 @@ stp_next_enabled_port(const struct stp *stp, const struct stp_port *port) #define MESSAGE_AGE_INCREMENT 1 -static void stp_transmit_config(struct stp_port *) OVS_REQ_WRLOCK(mutex); +static void stp_transmit_config(struct stp_port *) OVS_REQUIRES(mutex); static bool stp_supersedes_port_info(const struct stp_port *, const struct stp_config_bpdu *) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static void stp_record_config_information(struct stp_port *, const struct stp_config_bpdu *) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static void stp_record_config_timeout_values(struct stp *, const struct stp_config_bpdu *) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static bool stp_is_designated_port(const struct stp_port *) - OVS_REQ_WRLOCK(mutex); -static void stp_config_bpdu_generation(struct stp *) OVS_REQ_WRLOCK(mutex); -static void stp_transmit_tcn(struct stp *) OVS_REQ_WRLOCK(mutex); -static void stp_configuration_update(struct stp *) OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); +static void stp_config_bpdu_generation(struct stp *) OVS_REQUIRES(mutex); +static void stp_transmit_tcn(struct stp *) OVS_REQUIRES(mutex); +static void stp_configuration_update(struct stp *) OVS_REQUIRES(mutex); static bool stp_supersedes_root(const struct stp_port *root, - const struct stp_port *) OVS_REQ_WRLOCK(mutex); -static void stp_root_selection(struct stp *) OVS_REQ_WRLOCK(mutex); -static void stp_designated_port_selection(struct stp *) OVS_REQ_WRLOCK(mutex); + const struct stp_port *) OVS_REQUIRES(mutex); +static void stp_root_selection(struct stp *) OVS_REQUIRES(mutex); +static void stp_designated_port_selection(struct stp *) OVS_REQUIRES(mutex); static void stp_become_designated_port(struct stp_port *) - OVS_REQ_WRLOCK(mutex); -static void stp_port_state_selection(struct stp *) OVS_REQ_WRLOCK(mutex); -static void stp_make_forwarding(struct stp_port *) OVS_REQ_WRLOCK(mutex); -static void stp_make_blocking(struct stp_port *) OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); +static void stp_port_state_selection(struct stp *) OVS_REQUIRES(mutex); +static void stp_make_forwarding(struct stp_port *) OVS_REQUIRES(mutex); +static void stp_make_blocking(struct stp_port *) OVS_REQUIRES(mutex); static void stp_set_port_state(struct stp_port *, enum stp_state) - OVS_REQ_WRLOCK(mutex); -static void stp_topology_change_detection(struct stp *) OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); +static void stp_topology_change_detection(struct stp *) OVS_REQUIRES(mutex); static void stp_topology_change_acknowledged(struct stp *) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static void stp_acknowledge_topology_change(struct stp_port *) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static void stp_received_config_bpdu(struct stp *, struct stp_port *, const struct stp_config_bpdu *) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static void stp_received_tcn_bpdu(struct stp *, struct stp_port *) - OVS_REQ_WRLOCK(mutex); -static void stp_hello_timer_expiry(struct stp *) OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); +static void stp_hello_timer_expiry(struct stp *) OVS_REQUIRES(mutex); static void stp_message_age_timer_expiry(struct stp_port *) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static bool stp_is_designated_for_some_port(const struct stp *) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static void stp_forward_delay_timer_expiry(struct stp_port *) - OVS_REQ_WRLOCK(mutex); -static void stp_tcn_timer_expiry(struct stp *) OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); +static void stp_tcn_timer_expiry(struct stp *) OVS_REQUIRES(mutex); static void stp_topology_change_timer_expiry(struct stp *) - OVS_REQ_WRLOCK(mutex); -static void stp_hold_timer_expiry(struct stp_port *) OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); +static void stp_hold_timer_expiry(struct stp_port *) OVS_REQUIRES(mutex); static void stp_initialize_port(struct stp_port *, enum stp_state) - OVS_REQ_WRLOCK(mutex); -static void stp_become_root_bridge(struct stp *) OVS_REQ_WRLOCK(mutex); -static void stp_update_bridge_timers(struct stp *) OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); +static void stp_become_root_bridge(struct stp *) OVS_REQUIRES(mutex); +static void stp_update_bridge_timers(struct stp *) OVS_REQUIRES(mutex); static int clamp(int x, int min, int max); static int ms_to_timer(int ms); @@ -226,7 +228,7 @@ static void stp_stop_timer(struct stp_timer *); static bool stp_timer_expired(struct stp_timer *, int elapsed, int timeout); static void stp_send_bpdu(struct stp_port *, const void *, size_t) - OVS_REQ_WRLOCK(mutex); + OVS_REQUIRES(mutex); static void stp_unixctl_tcn(struct unixctl_conn *, int argc, const char *argv[], void *aux); @@ -264,7 +266,7 @@ stp_create(const char *name, stp_identifier bridge_id, * into the stp module through a patch port. This happens * intentionally as part of the unit tests. Ideally we'd ditch * the call back function, but for now this is what we have. */ - ovs_mutex_init(&mutex, PTHREAD_MUTEX_RECURSIVE); + ovs_mutex_init_recursive(&mutex); ovsthread_once_done(&once); } @@ -393,7 +395,7 @@ out: static void set_bridge_id(struct stp *stp, stp_identifier new_bridge_id) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { if (new_bridge_id != stp->bridge_id) { bool root; @@ -666,7 +668,7 @@ stp_state_name(enum stp_state state) case STP_BLOCKING: return "blocking"; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -707,7 +709,7 @@ stp_role_name(enum stp_role role) case STP_ROLE_DISABLED: return "disabled"; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -727,7 +729,7 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) } if (bpdu_size < sizeof(struct stp_bpdu_header)) { - VLOG_WARN("%s: received runt %zu-byte BPDU", stp->name, bpdu_size); + VLOG_WARN("%s: received runt %"PRIuSIZE"-byte BPDU", stp->name, bpdu_size); p->error_count++; goto out; } @@ -747,7 +749,7 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) switch (header->bpdu_type) { case STP_TYPE_CONFIG: if (bpdu_size < sizeof(struct stp_config_bpdu)) { - VLOG_WARN("%s: received config BPDU with invalid size %zu", + VLOG_WARN("%s: received config BPDU with invalid size %"PRIuSIZE, stp->name, bpdu_size); p->error_count++; goto out; @@ -757,7 +759,7 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) case STP_TYPE_TCN: if (bpdu_size != sizeof(struct stp_tcn_bpdu)) { - VLOG_WARN("%s: received TCN BPDU with invalid size %zu", + VLOG_WARN("%s: received TCN BPDU with invalid size %"PRIuSIZE, stp->name, bpdu_size); p->error_count++; goto out; @@ -1005,7 +1007,7 @@ stp_port_disable_change_detection(struct stp_port *p) } static void -stp_transmit_config(struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_transmit_config(struct stp_port *p) OVS_REQUIRES(mutex) { struct stp *stp = p->stp; bool root = stp_is_root_bridge(stp); @@ -1052,7 +1054,7 @@ stp_transmit_config(struct stp_port *p) OVS_REQ_WRLOCK(mutex) static bool stp_supersedes_port_info(const struct stp_port *p, const struct stp_config_bpdu *config) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { if (ntohll(config->root_id) != p->designated_root) { return ntohll(config->root_id) < p->designated_root; @@ -1069,7 +1071,7 @@ stp_supersedes_port_info(const struct stp_port *p, static void stp_record_config_information(struct stp_port *p, const struct stp_config_bpdu *config) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { p->designated_root = ntohll(config->root_id); p->designated_cost = ntohl(config->root_path_cost); @@ -1081,7 +1083,7 @@ stp_record_config_information(struct stp_port *p, static void stp_record_config_timeout_values(struct stp *stp, const struct stp_config_bpdu *config) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { stp->max_age = ntohs(config->max_age); stp->hello_time = ntohs(config->hello_time); @@ -1090,14 +1092,14 @@ stp_record_config_timeout_values(struct stp *stp, } static bool -stp_is_designated_port(const struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_is_designated_port(const struct stp_port *p) OVS_REQUIRES(mutex) { return (p->designated_bridge == p->stp->bridge_id && p->designated_port == p->port_id); } static void -stp_config_bpdu_generation(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_config_bpdu_generation(struct stp *stp) OVS_REQUIRES(mutex) { struct stp_port *p; @@ -1109,7 +1111,7 @@ stp_config_bpdu_generation(struct stp *stp) OVS_REQ_WRLOCK(mutex) } static void -stp_transmit_tcn(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_transmit_tcn(struct stp *stp) OVS_REQUIRES(mutex) { struct stp_port *p = stp->root_port; struct stp_tcn_bpdu tcn_bpdu; @@ -1123,15 +1125,16 @@ stp_transmit_tcn(struct stp *stp) OVS_REQ_WRLOCK(mutex) } static void -stp_configuration_update(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_configuration_update(struct stp *stp) OVS_REQUIRES(mutex) { stp_root_selection(stp); stp_designated_port_selection(stp); + seq_change(connectivity_seq_get()); } static bool stp_supersedes_root(const struct stp_port *root, const struct stp_port *p) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { int p_cost = p->designated_cost + p->path_cost; int root_cost = root->designated_cost + root->path_cost; @@ -1150,7 +1153,7 @@ stp_supersedes_root(const struct stp_port *root, const struct stp_port *p) } static void -stp_root_selection(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_root_selection(struct stp *stp) OVS_REQUIRES(mutex) { struct stp_port *p, *root; @@ -1176,7 +1179,7 @@ stp_root_selection(struct stp *stp) OVS_REQ_WRLOCK(mutex) } static void -stp_designated_port_selection(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_designated_port_selection(struct stp *stp) OVS_REQUIRES(mutex) { struct stp_port *p; @@ -1195,7 +1198,7 @@ stp_designated_port_selection(struct stp *stp) OVS_REQ_WRLOCK(mutex) } static void -stp_become_designated_port(struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_become_designated_port(struct stp_port *p) OVS_REQUIRES(mutex) { struct stp *stp = p->stp; p->designated_root = stp->designated_root; @@ -1205,7 +1208,7 @@ stp_become_designated_port(struct stp_port *p) OVS_REQ_WRLOCK(mutex) } static void -stp_port_state_selection(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_port_state_selection(struct stp *stp) OVS_REQUIRES(mutex) { struct stp_port *p; @@ -1226,7 +1229,7 @@ stp_port_state_selection(struct stp *stp) OVS_REQ_WRLOCK(mutex) } static void -stp_make_forwarding(struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_make_forwarding(struct stp_port *p) OVS_REQUIRES(mutex) { if (p->state == STP_BLOCKING) { stp_set_port_state(p, STP_LISTENING); @@ -1235,7 +1238,7 @@ stp_make_forwarding(struct stp_port *p) OVS_REQ_WRLOCK(mutex) } static void -stp_make_blocking(struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_make_blocking(struct stp_port *p) OVS_REQUIRES(mutex) { if (!(p->state & (STP_DISABLED | STP_BLOCKING))) { if (p->state & (STP_FORWARDING | STP_LEARNING)) { @@ -1250,19 +1253,20 @@ stp_make_blocking(struct stp_port *p) OVS_REQ_WRLOCK(mutex) static void stp_set_port_state(struct stp_port *p, enum stp_state state) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { if (state != p->state && !p->state_changed) { p->state_changed = true; if (p < p->stp->first_changed_port) { p->stp->first_changed_port = p; } + seq_change(connectivity_seq_get()); } p->state = state; } static void -stp_topology_change_detection(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_topology_change_detection(struct stp *stp) OVS_REQUIRES(mutex) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -1275,18 +1279,19 @@ stp_topology_change_detection(struct stp *stp) OVS_REQ_WRLOCK(mutex) } stp->fdb_needs_flush = true; stp->topology_change_detected = true; + seq_change(connectivity_seq_get()); VLOG_INFO_RL(&rl, "%s: detected topology change.", stp->name); } static void -stp_topology_change_acknowledged(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_topology_change_acknowledged(struct stp *stp) OVS_REQUIRES(mutex) { stp->topology_change_detected = false; stp_stop_timer(&stp->tcn_timer); } static void -stp_acknowledge_topology_change(struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_acknowledge_topology_change(struct stp_port *p) OVS_REQUIRES(mutex) { p->topology_change_ack = true; stp_transmit_config(p); @@ -1295,7 +1300,7 @@ stp_acknowledge_topology_change(struct stp_port *p) OVS_REQ_WRLOCK(mutex) static void stp_received_config_bpdu(struct stp *stp, struct stp_port *p, const struct stp_config_bpdu *config) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { if (ntohs(config->message_age) >= ntohs(config->max_age)) { VLOG_WARN("%s: received config BPDU with message age (%u) greater " @@ -1336,7 +1341,7 @@ stp_received_config_bpdu(struct stp *stp, struct stp_port *p, static void stp_received_tcn_bpdu(struct stp *stp, struct stp_port *p) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { if (p->state != STP_DISABLED) { if (stp_is_designated_port(p)) { @@ -1347,14 +1352,14 @@ stp_received_tcn_bpdu(struct stp *stp, struct stp_port *p) } static void -stp_hello_timer_expiry(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_hello_timer_expiry(struct stp *stp) OVS_REQUIRES(mutex) { stp_config_bpdu_generation(stp); stp_start_timer(&stp->hello_timer, 0); } static void -stp_message_age_timer_expiry(struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_message_age_timer_expiry(struct stp_port *p) OVS_REQUIRES(mutex) { struct stp *stp = p->stp; bool root = stp_is_root_bridge(stp); @@ -1373,7 +1378,7 @@ stp_message_age_timer_expiry(struct stp_port *p) OVS_REQ_WRLOCK(mutex) } static bool -stp_is_designated_for_some_port(const struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_is_designated_for_some_port(const struct stp *stp) OVS_REQUIRES(mutex) { const struct stp_port *p; @@ -1386,7 +1391,7 @@ stp_is_designated_for_some_port(const struct stp *stp) OVS_REQ_WRLOCK(mutex) } static void -stp_forward_delay_timer_expiry(struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_forward_delay_timer_expiry(struct stp_port *p) OVS_REQUIRES(mutex) { if (p->state == STP_LISTENING) { stp_set_port_state(p, STP_LEARNING); @@ -1402,21 +1407,21 @@ stp_forward_delay_timer_expiry(struct stp_port *p) OVS_REQ_WRLOCK(mutex) } static void -stp_tcn_timer_expiry(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_tcn_timer_expiry(struct stp *stp) OVS_REQUIRES(mutex) { stp_transmit_tcn(stp); stp_start_timer(&stp->tcn_timer, 0); } static void -stp_topology_change_timer_expiry(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_topology_change_timer_expiry(struct stp *stp) OVS_REQUIRES(mutex) { stp->topology_change_detected = false; stp->topology_change = false; } static void -stp_hold_timer_expiry(struct stp_port *p) OVS_REQ_WRLOCK(mutex) +stp_hold_timer_expiry(struct stp_port *p) OVS_REQUIRES(mutex) { if (p->config_pending) { stp_transmit_config(p); @@ -1425,7 +1430,7 @@ stp_hold_timer_expiry(struct stp_port *p) OVS_REQ_WRLOCK(mutex) static void stp_initialize_port(struct stp_port *p, enum stp_state state) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { ovs_assert(state & (STP_DISABLED | STP_BLOCKING)); stp_become_designated_port(p); @@ -1441,7 +1446,7 @@ stp_initialize_port(struct stp_port *p, enum stp_state state) } static void -stp_become_root_bridge(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_become_root_bridge(struct stp *stp) OVS_REQUIRES(mutex) { stp->max_age = stp->bridge_max_age; stp->hello_time = stp->bridge_hello_time; @@ -1453,21 +1458,21 @@ stp_become_root_bridge(struct stp *stp) OVS_REQ_WRLOCK(mutex) } static void -stp_start_timer(struct stp_timer *timer, int value) OVS_REQ_WRLOCK(mutex) +stp_start_timer(struct stp_timer *timer, int value) OVS_REQUIRES(mutex) { timer->value = value; timer->active = true; } static void -stp_stop_timer(struct stp_timer *timer) OVS_REQ_WRLOCK(mutex) +stp_stop_timer(struct stp_timer *timer) OVS_REQUIRES(mutex) { timer->active = false; } static bool stp_timer_expired(struct stp_timer *timer, int elapsed, int timeout) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { if (timer->active) { timer->value += elapsed; @@ -1502,7 +1507,7 @@ clamp(int x, int min, int max) } static void -stp_update_bridge_timers(struct stp *stp) OVS_REQ_WRLOCK(mutex) +stp_update_bridge_timers(struct stp *stp) OVS_REQUIRES(mutex) { int ht, ma, fd; @@ -1523,7 +1528,7 @@ stp_update_bridge_timers(struct stp *stp) OVS_REQ_WRLOCK(mutex) static void stp_send_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) - OVS_REQ_WRLOCK(mutex) + OVS_REQUIRES(mutex) { struct eth_header *eth; struct llc_header *llc; @@ -1552,7 +1557,7 @@ stp_send_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) /* Unixctl. */ static struct stp * -stp_find(const char *name) OVS_REQ_WRLOCK(mutex) +stp_find(const char *name) OVS_REQUIRES(mutex) { struct stp *stp;