blob: d3707117aaa4eaa660a82ea7e1e19df28c0e5dc6 [file] [log] [blame]
Yotam Harcholf3f11152013-09-05 16:47:16 -07001package org.projectfloodlight.openflow.types;
2
3import org.jboss.netty.buffer.ChannelBuffer;
4import org.projectfloodlight.openflow.exceptions.OFParseError;
5
Andreas Wundsam22ba3af2013-10-04 16:00:30 -07006import com.google.common.hash.PrimitiveSink;
Andreas Wundsam85c961f2013-09-29 21:22:12 -07007import com.google.common.primitives.Shorts;
8
Andreas Wundsam55b71ce2013-10-01 19:26:46 -07009/** Represents an OpenFlow Vlan VID, as specified by the OpenFlow 1.3 spec.
10 *
11 * <b> Note: this is not just the 12-bit vlan tag. OpenFlow defines
12 * the additional mask bits 0x1000 to represent the presence of a vlan
13 * tag. This additional bit will be stripped when writing a OF1.0 value
14 * tag.
15 * </b>
16 *
17 *
18 * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
19 *
20 */
Yotam Harcholf3f11152013-09-05 16:47:16 -070021public class VlanVid implements OFValueType<VlanVid> {
22
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070023 private static final short VALIDATION_MASK = 0x1FFF;
24 private static final short PRESENT_VAL = 0x1000;
25 private static final short VLAN_MASK = 0x0FFF;
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070026 private static final short NONE_VAL = 0x0000;
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070027 private static final short UNTAGGED_VAL_OF13 = (short) 0x0000;
28 private static final short UNTAGGED_VAL_OF10 = (short) 0xFFFF;
Yotam Harcholf3f11152013-09-05 16:47:16 -070029 final static int LENGTH = 2;
30
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070031 /** presence of a VLAN tag is idicated by the presence of bit 0x1000 */
32 public static final VlanVid PRESENT = new VlanVid(PRESENT_VAL);
33
34 /** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070035 public static final VlanVid NONE = new VlanVid(NONE_VAL);
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070036
37 /** for use with masking operations */
Yotam Harchol329f2b02013-09-11 15:05:26 -070038 public static final VlanVid NO_MASK = new VlanVid((short)0xFFFF);
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070039 public static final VlanVid FULL_MASK = NONE;
40
41 /** an untagged packet is specified as 0000 in OF 1.0, but 0xFFFF in OF1.0. Special case that. */
42 public static final VlanVid UNTAGGED = new VlanVid(NONE_VAL) {
43 @Override
44 public void write2BytesOF10(ChannelBuffer c) {
45 c.writeShort(UNTAGGED_VAL_OF10);
46 }
47 };
Yotam Harcholf3f11152013-09-05 16:47:16 -070048
49 private final short vid;
50
51 private VlanVid(short vid) {
52 this.vid = vid;
53 }
54
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070055 public static VlanVid ofRawVid(short vid) {
56 if(vid == UNTAGGED_VAL_OF13)
57 return UNTAGGED;
58 else if(vid == PRESENT_VAL)
59 return PRESENT;
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070060 else if ((vid & VALIDATION_MASK) != vid)
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070061 throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
Yotam Harcholf3f11152013-09-05 16:47:16 -070062 return new VlanVid(vid);
63 }
64
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070065 public static VlanVid ofVlan(int vlan) {
66 if( (vlan & VLAN_MASK) != vlan)
67 throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vlan));
68 return ofRawVid( (short) (vlan | PRESENT_VAL));
69 }
70
71 public static VlanVid ofVlanOF10(short of10vlan) {
72 if(of10vlan == NONE_VAL) {
73 return NONE;
74 } else if(of10vlan == UNTAGGED_VAL_OF10) {
75 return UNTAGGED;
76 } else {
77 return ofVlan(of10vlan);
78 }
79 }
80
81 /** @return whether or not this VlanId has the present (0x1000) bit set */
82 public boolean isPresentBitSet() {
83 return (vid & PRESENT_VAL) != 0;
84 }
85
86 /** @return the actual VLAN tag this vid identifies */
87 public short getVlan() {
88 return (short) (vid & VLAN_MASK);
89 }
90
Yotam Harcholf3f11152013-09-05 16:47:16 -070091 @Override
92 public boolean equals(Object obj) {
93 if (!(obj instanceof VlanVid))
94 return false;
95 VlanVid other = (VlanVid)obj;
96 if (other.vid != this.vid)
97 return false;
98 return true;
99 }
100
101 @Override
102 public int hashCode() {
103 int prime = 13873;
104 return this.vid * prime;
105 }
106
107 @Override
108 public String toString() {
109 return "0x" + Integer.toHexString(vid);
110 }
111
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700112 public short getRawVid() {
Yotam Harcholf3f11152013-09-05 16:47:16 -0700113 return vid;
114 }
115
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700116
Yotam Harcholf3f11152013-09-05 16:47:16 -0700117 @Override
118 public int getLength() {
119 return LENGTH;
120 }
121
122
123 volatile byte[] bytesCache = null;
124
125 public byte[] getBytes() {
126 if (bytesCache == null) {
127 synchronized (this) {
128 if (bytesCache == null) {
129 bytesCache =
130 new byte[] { (byte) ((vid >>> 8) & 0xFF),
131 (byte) ((vid >>> 0) & 0xFF) };
132 }
133 }
134 }
135 return bytesCache;
136 }
137
138 public void write2Bytes(ChannelBuffer c) {
139 c.writeShort(this.vid);
140 }
141
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700142 public void write2BytesOF10(ChannelBuffer c) {
143 c.writeShort(this.getVlan());
144 }
145
Yotam Harcholf3f11152013-09-05 16:47:16 -0700146 public static VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700147 return VlanVid.ofRawVid(c.readShort());
148 }
149
150 public static VlanVid read2BytesOF10(ChannelBuffer c) throws OFParseError {
151 return VlanVid.ofVlanOF10(c.readShort());
Yotam Harcholf3f11152013-09-05 16:47:16 -0700152 }
153
154 @Override
155 public VlanVid applyMask(VlanVid mask) {
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700156 return VlanVid.ofRawVid((short)(this.vid & mask.vid));
Yotam Harcholf3f11152013-09-05 16:47:16 -0700157 }
158
Andreas Wundsam85c961f2013-09-29 21:22:12 -0700159 @Override
160 public int compareTo(VlanVid o) {
161 return Shorts.compare(vid, o.vid);
162 }
Andreas Wundsam22ba3af2013-10-04 16:00:30 -0700163 @Override
164 public void putTo(PrimitiveSink sink) {
165 sink.putShort(vid);
166 }
Yotam Harcholf3f11152013-09-05 16:47:16 -0700167}