X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fstp.c;h=dbe48e82374e5a113670b3633e01bcf0014019ac;hb=e379e4d167e31d1cd5f7b86fff091a2e09ff6e45;hp=ed3a08de08aa8a14e6f5124437f2fd0421962b8a;hpb=bd3950ddfa5cf54d79feb332782d66d27c86090f;p=sliver-openvswitch.git diff --git a/lib/stp.c b/lib/stp.c index ed3a08de0..dbe48e823 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, 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. @@ -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" @@ -141,12 +143,12 @@ struct stp { void (*send_bpdu)(struct ofpbuf *bpdu, int port_no, void *aux); void *aux; - atomic_int ref_cnt; + struct ovs_refcount ref_cnt; }; 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); \ @@ -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); } @@ -304,7 +306,7 @@ stp_create(const char *name, stp_identifier bridge_id, p->path_cost = 19; /* Recommended default for 100 Mb/s link. */ stp_initialize_port(p, STP_DISABLED); } - atomic_init(&stp->ref_cnt, 1); + ovs_refcount_init(&stp->ref_cnt); list_push_back(all_stps, &stp->node); ovs_mutex_unlock(&mutex); @@ -316,9 +318,7 @@ stp_ref(const struct stp *stp_) { struct stp *stp = CONST_CAST(struct stp *, stp_); if (stp) { - int orig; - atomic_add(&stp->ref_cnt, 1, &orig); - ovs_assert(orig > 0); + ovs_refcount_ref(&stp->ref_cnt); } return stp; } @@ -327,15 +327,7 @@ stp_ref(const struct stp *stp_) void stp_unref(struct stp *stp) { - int orig; - - if (!stp) { - return; - } - - atomic_sub(&stp->ref_cnt, 1, &orig); - ovs_assert(orig > 0); - if (orig == 1) { + if (stp && ovs_refcount_unref(&stp->ref_cnt) == 1) { ovs_mutex_lock(&mutex); list_remove(&stp->node); ovs_mutex_unlock(&mutex); @@ -666,7 +658,7 @@ stp_state_name(enum stp_state state) case STP_BLOCKING: return "blocking"; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -692,6 +684,15 @@ stp_learn_in_state(enum stp_state state) return (state & (STP_DISABLED | STP_LEARNING | STP_FORWARDING)) != 0; } +/* Returns true if 'state' is one in which rx&tx bpdu should be done on + * on a port, false otherwise. */ +bool +stp_listen_in_state(enum stp_state state) +{ + return (state & + (STP_LISTENING | STP_LEARNING | STP_FORWARDING)) != 0; +} + /* Returns the name for the given 'role' (for use in debugging and log * messages). */ const char * @@ -707,7 +708,7 @@ stp_role_name(enum stp_role role) case STP_ROLE_DISABLED: return "disabled"; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -727,7 +728,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 +748,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 +758,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; @@ -1127,6 +1128,7 @@ 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 @@ -1257,6 +1259,7 @@ stp_set_port_state(struct stp_port *p, enum stp_state state) if (p < p->stp->first_changed_port) { p->stp->first_changed_port = p; } + seq_change(connectivity_seq_get()); } p->state = state; } @@ -1275,6 +1278,7 @@ stp_topology_change_detection(struct stp *stp) OVS_REQUIRES(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); } @@ -1531,14 +1535,15 @@ stp_send_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) /* Skeleton. */ pkt = ofpbuf_new(ETH_HEADER_LEN + LLC_HEADER_LEN + bpdu_size); - pkt->l2 = eth = ofpbuf_put_zeros(pkt, sizeof *eth); + eth = ofpbuf_put_zeros(pkt, sizeof *eth); llc = ofpbuf_put_zeros(pkt, sizeof *llc); - pkt->l3 = ofpbuf_put(pkt, bpdu, bpdu_size); + ofpbuf_set_frame(pkt, eth); + ofpbuf_set_l3(pkt, ofpbuf_put(pkt, bpdu, bpdu_size)); /* 802.2 header. */ memcpy(eth->eth_dst, eth_addr_stp, ETH_ADDR_LEN); /* p->stp->send_bpdu() must fill in source address. */ - eth->eth_type = htons(pkt->size - ETH_HEADER_LEN); + eth->eth_type = htons(ofpbuf_size(pkt) - ETH_HEADER_LEN); /* LLC header. */ llc->llc_dsap = STP_LLC_DSAP;