blob: 6c272169d21521a812e4311600c9152264f570d1 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
2* Copyright 2011, Big Switch Networks, Inc.
3* Originally created by David Erickson, Stanford University
4*
5* Licensed under the Apache License, Version 2.0 (the "License"); you may
6* not use this file except in compliance with the License. You may obtain
7* a copy of the License at
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14* License for the specific language governing permissions and limitations
15* under the License.
16**/
17
18package net.floodlightcontroller.packet;
19
20import java.nio.ByteBuffer;
21
22/**
23 * This class is a Rapid Spanning Tree Protocol
24 * Bridge Protocol Data Unit
25 * @author alexreimers
26 */
27public class BPDU extends BasePacket {
28 public enum BPDUType {
29 CONFIG,
30 TOPOLOGY_CHANGE;
31 }
32
33 private final long destMac = 0x0180c2000000L; // 01-80-c2-00-00-00
34
35 // TODO - check this for RSTP
36 private LLC llcHeader;
37 private short protocolId = 0;
38 private byte version = 0;
39 private byte type;
40 private byte flags;
41 private byte[] rootBridgeId;
42 private int rootPathCost;
43 private byte[] senderBridgeId; // switch cluster MAC
44 private short portId; // port it was transmitted from
45 private short messageAge; // 256ths of a second
46 private short maxAge; // 256ths of a second
47 private short helloTime; // 256ths of a second
48 private short forwardDelay; // 256ths of a second
49
50 public BPDU(BPDUType type) {
51 rootBridgeId = new byte[8];
52 senderBridgeId = new byte[8];
53
54 llcHeader = new LLC();
55 llcHeader.setDsap((byte) 0x42);
56 llcHeader.setSsap((byte) 0x42);
57 llcHeader.setCtrl((byte) 0x03);
58
59 switch(type) {
60 case CONFIG:
61 this.type = 0x0;
62 break;
63 case TOPOLOGY_CHANGE:
64 this.type = (byte) 0x80; // 1000 0000
65 break;
66 default:
67 this.type = 0;
68 break;
69 }
70 }
71
72 @Override
73 public byte[] serialize() {
74 byte[] data;
75 // TODO check these
76 if (type == 0x0) {
77 // config
78 data = new byte[38];
79 } else {
80 // topology change
81 data = new byte[7]; // LLC + TC notification
82 }
83
84 ByteBuffer bb = ByteBuffer.wrap(data);
85 // Serialize the LLC header
86 byte[] llc = llcHeader.serialize();
87 bb.put(llc, 0, llc.length);
88 bb.putShort(protocolId);
89 bb.put(version);
90 bb.put(type);
91
92 if (type == 0x0) {
93 bb.put(flags);
94 bb.put(rootBridgeId, 0, rootBridgeId.length);
95 bb.putInt(rootPathCost);
96 bb.put(senderBridgeId, 0, senderBridgeId.length);
97 bb.putShort(portId);
98 bb.putShort(messageAge);
99 bb.putShort(maxAge);
100 bb.putShort(helloTime);
101 bb.putShort(forwardDelay);
102 }
103
104 return data;
105 }
106
107 @Override
108 public IPacket deserialize(byte[] data, int offset, int length) {
109 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
110
111 // LLC header
112 llcHeader.deserialize(data, offset, 3);
113
114 this.protocolId = bb.getShort();
115 this.version = bb.get();
116 this.type = bb.get();
117
118 // These fields only exist if it's a configuration BPDU
119 if (this.type == 0x0) {
120 this.flags = bb.get();
121 bb.get(rootBridgeId, 0, 6);
122 this.rootPathCost = bb.getInt();
123 bb.get(this.senderBridgeId, 0, 6);
124 this.portId = bb.getShort();
125 this.messageAge = bb.getShort();
126 this.maxAge = bb.getShort();
127 this.helloTime = bb.getShort();
128 this.forwardDelay = bb.getShort();
129 }
130 // TODO should we set other fields to 0?
131
132 return this;
133 }
134
135 public long getDestMac() {
136 return destMac;
137 }
138}