#include <config.h>
-
-#include "rstp.h"
+#undef NDEBUG
+#include "rstp-common.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include "ofpbuf.h"
#include "ovstest.h"
+#include "dp-packet.h"
#include "packets.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
#define MAX_PORTS 10
new_test_case(void)
{
struct test_case *tc = xmalloc(sizeof *tc);
+
tc->n_bridges = 0;
tc->n_lans = 0;
return tc;
}
+/* This callback is called with rstp_mutex held. */
static void
-send_bpdu(struct ofpbuf *pkt, int port_no, void *b_)
+send_bpdu(struct dp_packet *pkt, void *port_, void *b_)
+ OVS_REQUIRES(rstp_mutex)
{
struct bridge *b = b_;
struct lan *lan;
+ const struct rstp_port *port = port_;
+ uint16_t port_no = port->port_number;
assert(port_no < b->n_ports);
lan = b->ports[port_no];
if (lan) {
- const void *data = ofpbuf_l3(pkt);
- size_t size = (char *) ofpbuf_tail(pkt) - (char *) data;
+ const void *data = dp_packet_l3(pkt);
+ size_t size = (char *) dp_packet_tail(pkt) - (char *) data;
int i;
for (i = 0; i < lan->n_conns; i++) {
struct lan_conn *conn = &lan->conns[i];
+
if (conn->bridge != b || conn->port_no != port_no) {
struct bridge *dst = conn->bridge;
struct bpdu *bpdu = &dst->rxq[dst->rxq_head++ % RXQ_SIZE];
+
assert(dst->rxq_head - dst->rxq_tail <= RXQ_SIZE);
bpdu->data = xmemdup(data, size);
bpdu->size = size;
}
}
}
- ofpbuf_delete(pkt);
+ dp_packet_delete(pkt);
}
static struct bridge *
b->rstp = rstp_create(name, id, send_bpdu, b);
for (i = 1; i < MAX_PORTS; i++) {
p = rstp_add_port(b->rstp);
- rstp_port_set_aux(p, b);
+ rstp_port_set_aux(p, p);
rstp_port_set_state(p, RSTP_DISABLED);
rstp_port_set_mac_operational(p, true);
}
if (old_lan) {
for (j = 0; j < old_lan->n_conns; j++) {
struct lan_conn *c = &old_lan->conns[j];
+
if (c->bridge == b && c->port_no == port_no) {
memmove(c, c + 1, sizeof *c * (old_lan->n_conns - j - 1));
old_lan->n_conns--;
b->ports[port_no] = new_lan;
if (new_lan) {
int conn_no = new_lan->n_conns++;
+
assert(conn_no < ARRAY_SIZE(new_lan->conns));
new_lan->conns[conn_no].bridge = b;
new_lan->conns[conn_no].port_no = port_no;
for (i = 0; i < b->n_ports; i++) {
struct lan *lan = b->ports[i];
struct rstp_port *p = rstp_get_port(b->rstp, i);
+
if (rstp_port_get_state(p) == RSTP_FORWARDING && lan) {
dump_lan_tree(tc, lan, level + 1);
}
printf("%s\n", lan->name);
for (i = 0; i < lan->n_conns; i++) {
struct bridge *b = lan->conns[i].bridge;
+
dump_bridge_tree(tc, b, level + 1);
}
}
for (i = 0; i < tc->n_bridges; i++) {
struct bridge *b = tc->bridges[i];
+
b->reached = false;
}
for (i = 0; i < tc->n_lans; i++) {
struct lan *lan = tc->lans[i];
+
lan->reached = false;
}
for (i = 0; i < tc->n_bridges; i++) {
struct bridge *b = tc->bridges[i];
struct rstp *rstp = b->rstp;
+
if (rstp_is_root_bridge(rstp)) {
dump_bridge_tree(tc, b, 0);
}
simulate(struct test_case *tc, int granularity)
{
int time, i, round_trips;
+
for (time = 0; time < 1000 * 180; time += granularity) {
for (i = 0; i < tc->n_bridges; i++) {
}
for (round_trips = 0; round_trips < granularity; round_trips++) {
bool any = false;
+
for (i = 0; i < tc->n_bridges; i++) {
struct bridge *b = tc->bridges[i];
+
for (; b->rxq_tail != b->rxq_head; b->rxq_tail++) {
struct bpdu *bpdu = &b->rxq[b->rxq_tail % RXQ_SIZE];
- rstp_received_bpdu(rstp_get_port(b->rstp, bpdu->port_no),
- bpdu->data, bpdu->size);
+
+ rstp_port_received_bpdu(rstp_get_port(b->rstp,
+ bpdu->port_no),
+ bpdu->data, bpdu->size);
free(bpdu->data);
any = true;
}
}
}
-static void
+OVS_NO_RETURN static void
err(const char *message, ...)
- PRINTF_FORMAT(1, 2)
- NO_RETURN;
+ OVS_PRINTF_FORMAT(1, 2);
static void
err(const char *message, ...)
static void
warn(const char *message, ...)
- PRINTF_FORMAT(1, 2);
+ OVS_PRINTF_FORMAT(1, 2);
static void
warn(const char *message, ...)
get_int(int *intp)
{
char *save_pos = pos;
+
if (token && isdigit((unsigned char) *token)) {
*intp = strtol(token, NULL, 0);
get_token();
must_get_int(void)
{
int x;
+
if (!get_int(&x)) {
err("expected integer");
}
tc = new_test_case();
for (i = 0; i < 26; i++) {
char name[2];
+
name[0] = 'a' + i;
name[1] = '\0';
new_lan(tc, name);
if (match("=")) {
for (port_no = 1; port_no < MAX_PORTS; port_no++) {
struct rstp_port *p = rstp_get_port(bridge->rstp, port_no);
+
if (!token || match("X")) {
/* Disable port. */
reinitialize_port(p);
if (match("rootid")) {
uint64_t rootid;
+
must_match(":");
rootid = must_get_int();
if (match("^")) {
for (port_no = 1; port_no < b->n_active_ports; port_no++) {
struct rstp_port *p = rstp_get_port(rstp, port_no);
enum rstp_state state = rstp_port_get_state(p);
+
if (state != RSTP_DISABLED && state != RSTP_FORWARDING) {
warn("%s: root port %d in state %s",
rstp_get_name(b->rstp), port_no,
for (port_no = 1; port_no < b->n_active_ports; port_no++) {
struct rstp_port *p = rstp_get_port(rstp, port_no);
enum rstp_state state;
+
if (token == NULL || match("D")) {
state = RSTP_DISABLED;
} else if (match("Di")) {
}
if (state == RSTP_FORWARDING) {
struct rstp_port *root_port = rstp_get_root_port(rstp);
+
if (match(":")) {
int root_path_cost = must_get_int();
+
if (p != root_port) {
warn("%s: port %d is not the root port",
rstp_get_name(rstp), port_no);
} else {
warn("%s: (port %d is the root port)",
rstp_get_name(rstp),
- rstp_port_number(root_port));
+ rstp_port_get_number(root_port));
}
} else if (cost_value != root_path_cost) {
warn("%s: root path cost is %d, should be %d",
for (i = 0; i < tc->n_lans; i++) {
struct lan *lan = tc->lans[i];
+
free(CONST_CAST(char *, lan->name));
free(lan);
}
for (i = 0; i < tc->n_bridges; i++) {
struct bridge *bridge = tc->bridges[i];
int j;
+
for (j = 1; j < MAX_PORTS; j++) {
- rstp_delete_port(rstp_get_port(bridge->rstp, j));
+ rstp_port_unref(rstp_get_port(bridge->rstp, j));
}
rstp_unref(bridge->rstp);
free(bridge);