/*
- * Copyright (c) 2011-2014 M3S, Srl - Italy
+ * Copyright (c) 2011-2015 M3S, Srl - Italy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* Authors:
* Martino Fornasa <mf@fornasa.it>
* Daniele Venturino <daniele.venturino@m3s.it>
+ * Carlo Andreotti <c.andreotti@m3s.it>
*
* References to IEEE 802.1D-2004 standard are enclosed in square brackets.
* E.g. [17.3], [Table 17-1], etc.
#include "byte-order.h"
#include "connectivity.h"
#include "ofpbuf.h"
+#include "dp-packet.h"
#include "packets.h"
#include "seq.h"
#include "unixctl.h"
#include "util.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
VLOG_DEFINE_THIS_MODULE(rstp_sm);
{
struct eth_header *eth;
struct llc_header *llc;
- struct ofpbuf *pkt;
+ struct dp_packet *pkt;
/* Skeleton. */
- pkt = ofpbuf_new(ETH_HEADER_LEN + LLC_HEADER_LEN + bpdu_size);
- eth = ofpbuf_put_zeros(pkt, sizeof *eth);
- llc = ofpbuf_put_zeros(pkt, sizeof *llc);
- ofpbuf_set_frame(pkt, eth);
- ofpbuf_set_l3(pkt, ofpbuf_put(pkt, bpdu, bpdu_size));
+ pkt = dp_packet_new(ETH_HEADER_LEN + LLC_HEADER_LEN + bpdu_size);
+ eth = dp_packet_put_zeros(pkt, sizeof *eth);
+ llc = dp_packet_put_zeros(pkt, sizeof *llc);
+ dp_packet_reset_offsets(pkt);
+ dp_packet_set_l3(pkt, dp_packet_put(pkt, bpdu, bpdu_size));
/* 802.2 header. */
- memcpy(eth->eth_dst, eth_addr_stp, ETH_ADDR_LEN);
+ eth->eth_dst = eth_addr_stp;
/* p->rstp->send_bpdu() must fill in source address. */
- eth->eth_type = htons(ofpbuf_size(pkt) - ETH_HEADER_LEN);
+ eth->eth_type = htons(dp_packet_size(pkt) - ETH_HEADER_LEN);
/* LLC header. */
llc->llc_dsap = STP_LLC_DSAP;
OVS_REQUIRES(rstp_mutex)
{
if ((p->received_bpdu_buffer.flags & BPDU_FLAG_LEARNING) != 0) {
- p->agreed = true;
- p->proposing = false;
+ /* 802.1D-2004 says to set the agreed flag and to clear the proposing
+ * flag. 802.1q-2008 instead says to set the disputed variable and to
+ * clear the agreed variable. */
+ p->disputed = true;
+ p->agreed = false;
}
}
{
enum port_information_state_machine old_state;
struct rstp *r;
+ struct rstp_port *p1;
old_state = p->port_information_sm_state;
r = p->rstp;
} else {
switch (p->rcvd_info) {
case SUPERIOR_DESIGNATED_INFO:
+ /* 802.1q-2008 has a checkBPDUConsistency() function, called on
+ * a BPDU reception. checkBPDUConsistency() clears the agreed
+ * variable if the received message priority vector is superior
+ * to the port priority vector, the BPDU is an ST BPDU or an
+ * RST BPDU, its port role is Designated and its Learning flag
+ * is set. */
+ if (p->received_bpdu_buffer.flags & BPDU_FLAG_LEARNING) {
+ HMAP_FOR_EACH (p1, node, &r->ports) {
+ if (p1->port_number != p->port_number) {
+ p1->agreed = false;
+ }
+ }
+ }
p->port_information_sm_state =
PORT_INFORMATION_SM_SUPERIOR_DESIGNATED_EXEC;
break;
case PORT_INFORMATION_SM_REPEATED_DESIGNATED_EXEC:
record_proposal(p);
set_tc_flags(p);
+ /* This record_agreement() is missing in 802.1D-2004, but it's present
+ * in 802.1q-2008. */
+ record_agreement(p);
updt_rcvd_info_while(p);
p->rcvd_msg = false;
p->port_information_sm_state = PORT_INFORMATION_SM_REPEATED_DESIGNATED;
set_tc_flags(p);
/* RECEIVED is not specified in Standard 802.1D-2004. */
p->agree = p->agree && better_or_same_info(p, RECEIVED);
+ /* This record_agreement() and the synced assignment are missing in
+ * 802.1D-2004, but they're present in 802.1q-2008. */
+ record_agreement(p);
+ p->synced = p->synced && p->agreed;
record_priority(p);
record_times(p);
updt_rcvd_info_while(p);
p->port_role_transition_sm_state);
}
if (last_role != p->role) {
- last_role = p->role;
VLOG_DBG("%s, port %u, port role ["RSTP_PORT_ID_FMT"] = %s",
p->rstp->name, p->port_number, p->port_id,
rstp_port_role_name(p->role));