159
167
#define MESSAGE_AGE_INCREMENT 1
161
static void stp_transmit_config(struct stp_port *);
169
static void stp_transmit_config(struct stp_port *) OVS_REQ_WRLOCK(mutex);
162
170
static bool stp_supersedes_port_info(const struct stp_port *,
163
const struct stp_config_bpdu *);
171
const struct stp_config_bpdu *)
172
OVS_REQ_WRLOCK(mutex);
164
173
static void stp_record_config_information(struct stp_port *,
165
const struct stp_config_bpdu *);
174
const struct stp_config_bpdu *)
175
OVS_REQ_WRLOCK(mutex);
166
176
static void stp_record_config_timeout_values(struct stp *,
167
const struct stp_config_bpdu *);
168
static bool stp_is_designated_port(const struct stp_port *);
169
static void stp_config_bpdu_generation(struct stp *);
170
static void stp_transmit_tcn(struct stp *);
171
static void stp_configuration_update(struct stp *);
177
const struct stp_config_bpdu *)
178
OVS_REQ_WRLOCK(mutex);
179
static bool stp_is_designated_port(const struct stp_port *)
180
OVS_REQ_WRLOCK(mutex);
181
static void stp_config_bpdu_generation(struct stp *) OVS_REQ_WRLOCK(mutex);
182
static void stp_transmit_tcn(struct stp *) OVS_REQ_WRLOCK(mutex);
183
static void stp_configuration_update(struct stp *) OVS_REQ_WRLOCK(mutex);
172
184
static bool stp_supersedes_root(const struct stp_port *root,
173
const struct stp_port *);
174
static void stp_root_selection(struct stp *);
175
static void stp_designated_port_selection(struct stp *);
176
static void stp_become_designated_port(struct stp_port *);
177
static void stp_port_state_selection(struct stp *);
178
static void stp_make_forwarding(struct stp_port *);
179
static void stp_make_blocking(struct stp_port *);
180
static void stp_set_port_state(struct stp_port *, enum stp_state);
181
static void stp_topology_change_detection(struct stp *);
182
static void stp_topology_change_acknowledged(struct stp *);
183
static void stp_acknowledge_topology_change(struct stp_port *);
185
const struct stp_port *) OVS_REQ_WRLOCK(mutex);
186
static void stp_root_selection(struct stp *) OVS_REQ_WRLOCK(mutex);
187
static void stp_designated_port_selection(struct stp *) OVS_REQ_WRLOCK(mutex);
188
static void stp_become_designated_port(struct stp_port *)
189
OVS_REQ_WRLOCK(mutex);
190
static void stp_port_state_selection(struct stp *) OVS_REQ_WRLOCK(mutex);
191
static void stp_make_forwarding(struct stp_port *) OVS_REQ_WRLOCK(mutex);
192
static void stp_make_blocking(struct stp_port *) OVS_REQ_WRLOCK(mutex);
193
static void stp_set_port_state(struct stp_port *, enum stp_state)
194
OVS_REQ_WRLOCK(mutex);
195
static void stp_topology_change_detection(struct stp *) OVS_REQ_WRLOCK(mutex);
196
static void stp_topology_change_acknowledged(struct stp *)
197
OVS_REQ_WRLOCK(mutex);
198
static void stp_acknowledge_topology_change(struct stp_port *)
199
OVS_REQ_WRLOCK(mutex);
184
200
static void stp_received_config_bpdu(struct stp *, struct stp_port *,
185
const struct stp_config_bpdu *);
186
static void stp_received_tcn_bpdu(struct stp *, struct stp_port *);
187
static void stp_hello_timer_expiry(struct stp *);
188
static void stp_message_age_timer_expiry(struct stp_port *);
189
static bool stp_is_designated_for_some_port(const struct stp *);
190
static void stp_forward_delay_timer_expiry(struct stp_port *);
191
static void stp_tcn_timer_expiry(struct stp *);
192
static void stp_topology_change_timer_expiry(struct stp *);
193
static void stp_hold_timer_expiry(struct stp_port *);
194
static void stp_initialize_port(struct stp_port *, enum stp_state);
195
static void stp_become_root_bridge(struct stp *);
196
static void stp_update_bridge_timers(struct stp *);
201
const struct stp_config_bpdu *)
202
OVS_REQ_WRLOCK(mutex);
203
static void stp_received_tcn_bpdu(struct stp *, struct stp_port *)
204
OVS_REQ_WRLOCK(mutex);
205
static void stp_hello_timer_expiry(struct stp *) OVS_REQ_WRLOCK(mutex);
206
static void stp_message_age_timer_expiry(struct stp_port *)
207
OVS_REQ_WRLOCK(mutex);
208
static bool stp_is_designated_for_some_port(const struct stp *)
209
OVS_REQ_WRLOCK(mutex);
210
static void stp_forward_delay_timer_expiry(struct stp_port *)
211
OVS_REQ_WRLOCK(mutex);
212
static void stp_tcn_timer_expiry(struct stp *) OVS_REQ_WRLOCK(mutex);
213
static void stp_topology_change_timer_expiry(struct stp *)
214
OVS_REQ_WRLOCK(mutex);
215
static void stp_hold_timer_expiry(struct stp_port *) OVS_REQ_WRLOCK(mutex);
216
static void stp_initialize_port(struct stp_port *, enum stp_state)
217
OVS_REQ_WRLOCK(mutex);
218
static void stp_become_root_bridge(struct stp *) OVS_REQ_WRLOCK(mutex);
219
static void stp_update_bridge_timers(struct stp *) OVS_REQ_WRLOCK(mutex);
198
221
static int clamp(int x, int min, int max);
199
222
static int ms_to_timer(int ms);
231
255
void (*send_bpdu)(struct ofpbuf *bpdu, int port_no, void *aux),
258
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
235
260
struct stp_port *p;
262
if (ovsthread_once_start(&once)) {
263
/* We need a recursive mutex because stp_send_bpdu() could loop back
264
* into the stp module through a patch port. This happens
265
* intentionally as part of the unit tests. Ideally we'd ditch
266
* the call back function, but for now this is what we have. */
267
ovs_mutex_init(&mutex, PTHREAD_MUTEX_RECURSIVE);
268
ovsthread_once_done(&once);
271
ovs_mutex_lock(&mutex);
237
272
stp = xzalloc(sizeof *stp);
238
273
stp->name = xstrdup(name);
239
274
stp->bridge_id = bridge_id;
269
304
p->path_cost = 19; /* Recommended default for 100 Mb/s link. */
270
305
stp_initialize_port(p, STP_DISABLED);
272
list_push_back(&all_stps, &stp->node);
307
atomic_init(&stp->ref_cnt, 1);
309
list_push_back(all_stps, &stp->node);
310
ovs_mutex_unlock(&mutex);
315
stp_ref(const struct stp *stp_)
317
struct stp *stp = CONST_CAST(struct stp *, stp_);
320
atomic_add(&stp->ref_cnt, 1, &orig);
321
ovs_assert(orig > 0);
276
326
/* Destroys 'stp'. */
278
stp_destroy(struct stp *stp)
328
stp_unref(struct stp *stp)
336
atomic_sub(&stp->ref_cnt, 1, &orig);
337
ovs_assert(orig > 0);
339
ovs_mutex_lock(&mutex);
281
340
list_remove(&stp->node);
341
ovs_mutex_unlock(&mutex);
396
469
stp_set_forward_delay(struct stp *stp, int ms)
471
ovs_mutex_lock(&mutex);
398
472
stp->rq_forward_delay = ms;
399
473
stp_update_bridge_timers(stp);
474
ovs_mutex_unlock(&mutex);
402
477
/* Returns the name given to 'stp' in the call to stp_create(). */
404
479
stp_get_name(const struct stp *stp)
483
ovs_mutex_lock(&mutex);
485
ovs_mutex_unlock(&mutex);
409
489
/* Returns the bridge ID for 'stp'. */
411
491
stp_get_bridge_id(const struct stp *stp)
413
return stp->bridge_id;
493
stp_identifier bridge_id;
495
ovs_mutex_lock(&mutex);
496
bridge_id = stp->bridge_id;
497
ovs_mutex_unlock(&mutex);
416
501
/* Returns the bridge ID of the bridge currently believed to be the root. */
418
503
stp_get_designated_root(const struct stp *stp)
420
return stp->designated_root;
505
stp_identifier designated_root;
507
ovs_mutex_lock(&mutex);
508
designated_root = stp->designated_root;
509
ovs_mutex_unlock(&mutex);
510
return designated_root;
423
513
/* Returns true if 'stp' believes itself to the be root of the spanning tree,
654
798
stp_port_set_aux(struct stp_port *p, void *aux)
800
ovs_mutex_lock(&mutex);
802
ovs_mutex_unlock(&mutex);
659
805
/* Returns the 'aux' member of 'p'. */
661
807
stp_port_get_aux(struct stp_port *p)
811
ovs_mutex_lock(&mutex);
813
ovs_mutex_unlock(&mutex);
666
817
/* Returns the index of port 'p' within its bridge. */
668
819
stp_port_no(const struct stp_port *p)
670
struct stp *stp = p->stp;
824
ovs_mutex_lock(&mutex);
671
826
ovs_assert(p >= stp->ports && p < &stp->ports[ARRAY_SIZE(stp->ports)]);
672
return p - stp->ports;
827
index = p - p->stp->ports;
828
ovs_mutex_unlock(&mutex);
675
832
/* Returns the port ID for 'p'. */
677
834
stp_port_get_id(const struct stp_port *p)
838
ovs_mutex_lock(&mutex);
839
port_id = p->port_id;
840
ovs_mutex_unlock(&mutex);
682
844
/* Returns the state of port 'p'. */
684
846
stp_port_get_state(const struct stp_port *p)
848
enum stp_state state;
850
ovs_mutex_lock(&mutex);
852
ovs_mutex_unlock(&mutex);
689
856
/* Returns the role of port 'p'. */
691
858
stp_port_get_role(const struct stp_port *p)
693
struct stp_port *root_port = stp_get_root_port(p->stp);
860
struct stp_port *root_port;
863
ovs_mutex_lock(&mutex);
864
root_port = p->stp->root_port;
695
865
if (root_port && root_port->port_id == p->port_id) {
696
return STP_ROLE_ROOT;
866
role = STP_ROLE_ROOT;
697
867
} else if (stp_is_designated_port(p)) {
698
return STP_ROLE_DESIGNATED;
868
role = STP_ROLE_DESIGNATED;
699
869
} else if (p->state == STP_DISABLED) {
700
return STP_ROLE_DISABLED;
870
role = STP_ROLE_DISABLED;
702
return STP_ROLE_ALTERNATE;
872
role = STP_ROLE_ALTERNATE;
874
ovs_mutex_unlock(&mutex);
706
878
/* Retrieves BPDU transmit and receive counts for 'p'. */
707
void stp_port_get_counts(const struct stp_port *p,
708
int *tx_count, int *rx_count, int *error_count)
880
stp_port_get_counts(const struct stp_port *p,
881
int *tx_count, int *rx_count, int *error_count)
883
ovs_mutex_lock(&mutex);
710
884
*tx_count = p->tx_count;
711
885
*rx_count = p->rx_count;
712
886
*error_count = p->error_count;
887
ovs_mutex_unlock(&mutex);
715
890
/* Disables STP on port 'p'. */
717
892
stp_port_disable(struct stp_port *p)
719
struct stp *stp = p->stp;
896
ovs_mutex_lock(&mutex);
720
898
if (p->state != STP_DISABLED) {
721
899
bool root = stp_is_root_bridge(stp);
722
900
stp_become_designated_port(p);
762
946
stp_port_state_selection(stp);
949
ovs_mutex_unlock(&mutex);
767
952
/* Convert 'speed' (measured in Mb/s) into the path cost. */
769
954
stp_convert_speed_to_cost(unsigned int speed)
771
return speed >= 10000 ? 2 /* 10 Gb/s. */
772
: speed >= 1000 ? 4 /* 1 Gb/s. */
773
: speed >= 100 ? 19 /* 100 Mb/s. */
774
: speed >= 16 ? 62 /* 16 Mb/s. */
775
: speed >= 10 ? 100 /* 10 Mb/s. */
776
: speed >= 4 ? 250 /* 4 Mb/s. */
777
: 19; /* 100 Mb/s (guess). */
958
ovs_mutex_lock(&mutex);
959
ret = speed >= 10000 ? 2 /* 10 Gb/s. */
960
: speed >= 1000 ? 4 /* 1 Gb/s. */
961
: speed >= 100 ? 19 /* 100 Mb/s. */
962
: speed >= 16 ? 62 /* 16 Mb/s. */
963
: speed >= 10 ? 100 /* 10 Mb/s. */
964
: speed >= 4 ? 250 /* 4 Mb/s. */
965
: 19; /* 100 Mb/s (guess). */
966
ovs_mutex_unlock(&mutex);
780
970
/* Sets the path cost of port 'p' to 'path_cost'. Lower values are generally
1366
1568
stp_unixctl_tcn(struct unixctl_conn *conn, int argc,
1367
1569
const char *argv[], void *aux OVS_UNUSED)
1571
ovs_mutex_lock(&mutex);
1369
1572
if (argc > 1) {
1370
1573
struct stp *stp = stp_find(argv[1]);
1373
1576
unixctl_command_reply_error(conn, "no such stp object");
1376
1579
stp_topology_change_detection(stp);
1378
1581
struct stp *stp;
1380
LIST_FOR_EACH (stp, node, &all_stps) {
1583
LIST_FOR_EACH (stp, node, all_stps) {
1381
1584
stp_topology_change_detection(stp);
1385
1588
unixctl_command_reply(conn, "OK");
1591
ovs_mutex_unlock(&mutex);