blob: 6bd758117dbef2484bdba733e708e92470ab157a [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 Wundsam85c961f2013-09-29 21:22:12 -07006import com.google.common.primitives.Shorts;
7
Andreas Wundsam55b71ce2013-10-01 19:26:46 -07008/** Represents an OpenFlow Vlan VID, as specified by the OpenFlow 1.3 spec.
9 *
10 * <b> Note: this is not just the 12-bit vlan tag. OpenFlow defines
11 * the additional mask bits 0x1000 to represent the presence of a vlan
12 * tag. This additional bit will be stripped when writing a OF1.0 value
13 * tag.
14 * </b>
15 *
16 *
17 * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
18 *
19 */
Yotam Harcholf3f11152013-09-05 16:47:16 -070020public class VlanVid implements OFValueType<VlanVid> {
21
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070022 private static final short VALIDATION_MASK = 0x1FFF;
23 private static final short PRESENT_VAL = 0x1000;
24 private static final short VLAN_MASK = 0x0FFF;
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070025 private static final short NONE_VAL = 0x0000;
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070026 private static final short UNTAGGED_VAL_OF13 = (short) 0x0000;
27 private static final short UNTAGGED_VAL_OF10 = (short) 0xFFFF;
Yotam Harcholf3f11152013-09-05 16:47:16 -070028 final static int LENGTH = 2;
29
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070030 /** presence of a VLAN tag is idicated by the presence of bit 0x1000 */
31 public static final VlanVid PRESENT = new VlanVid(PRESENT_VAL);
32
33 /** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070034 public static final VlanVid NONE = new VlanVid(NONE_VAL);
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070035
36 /** for use with masking operations */
Yotam Harchol329f2b02013-09-11 15:05:26 -070037 public static final VlanVid NO_MASK = new VlanVid((short)0xFFFF);
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070038 public static final VlanVid FULL_MASK = NONE;
39
40 /** an untagged packet is specified as 0000 in OF 1.0, but 0xFFFF in OF1.0. Special case that. */
41 public static final VlanVid UNTAGGED = new VlanVid(NONE_VAL) {
42 @Override
43 public void write2BytesOF10(ChannelBuffer c) {
44 c.writeShort(UNTAGGED_VAL_OF10);
45 }
46 };
Yotam Harcholf3f11152013-09-05 16:47:16 -070047
48 private final short vid;
49
50 private VlanVid(short vid) {
51 this.vid = vid;
52 }
53
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070054 public static VlanVid ofRawVid(short vid) {
55 if(vid == UNTAGGED_VAL_OF13)
56 return UNTAGGED;
57 else if(vid == PRESENT_VAL)
58 return PRESENT;
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070059 else if ((vid & VALIDATION_MASK) != vid)
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070060 throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
Yotam Harcholf3f11152013-09-05 16:47:16 -070061 return new VlanVid(vid);
62 }
63
Andreas Wundsam55b71ce2013-10-01 19:26:46 -070064 public static VlanVid ofVlan(int vlan) {
65 if( (vlan & VLAN_MASK) != vlan)
66 throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vlan));
67 return ofRawVid( (short) (vlan | PRESENT_VAL));
68 }
69
70 public static VlanVid ofVlanOF10(short of10vlan) {
71 if(of10vlan == NONE_VAL) {
72 return NONE;
73 } else if(of10vlan == UNTAGGED_VAL_OF10) {
74 return UNTAGGED;
75 } else {
76 return ofVlan(of10vlan);
77 }
78 }
79
80 /** @return whether or not this VlanId has the present (0x1000) bit set */
81 public boolean isPresentBitSet() {
82 return (vid & PRESENT_VAL) != 0;
83 }
84
85 /** @return the actual VLAN tag this vid identifies */
86 public short getVlan() {
87 return (short) (vid & VLAN_MASK);
88 }
89
Yotam Harcholf3f11152013-09-05 16:47:16 -070090 @Override
91 public boolean equals(Object obj) {
92 if (!(obj instanceof VlanVid))
93 return false;
94 VlanVid other = (VlanVid)obj;
95 if (other.vid != this.vid)
96 return false;
97 return true;
98 }
99
100 @Override
101 public int hashCode() {
102 int prime = 13873;
103 return this.vid * prime;
104 }
105
106 @Override
107 public String toString() {
108 return "0x" + Integer.toHexString(vid);
109 }
110
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700111 public short getRawVid() {
Yotam Harcholf3f11152013-09-05 16:47:16 -0700112 return vid;
113 }
114
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700115
Yotam Harcholf3f11152013-09-05 16:47:16 -0700116 @Override
117 public int getLength() {
118 return LENGTH;
119 }
120
121
122 volatile byte[] bytesCache = null;
123
124 public byte[] getBytes() {
125 if (bytesCache == null) {
126 synchronized (this) {
127 if (bytesCache == null) {
128 bytesCache =
129 new byte[] { (byte) ((vid >>> 8) & 0xFF),
130 (byte) ((vid >>> 0) & 0xFF) };
131 }
132 }
133 }
134 return bytesCache;
135 }
136
137 public void write2Bytes(ChannelBuffer c) {
138 c.writeShort(this.vid);
139 }
140
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700141 public void write2BytesOF10(ChannelBuffer c) {
142 c.writeShort(this.getVlan());
143 }
144
Yotam Harcholf3f11152013-09-05 16:47:16 -0700145 public static VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700146 return VlanVid.ofRawVid(c.readShort());
147 }
148
149 public static VlanVid read2BytesOF10(ChannelBuffer c) throws OFParseError {
150 return VlanVid.ofVlanOF10(c.readShort());
Yotam Harcholf3f11152013-09-05 16:47:16 -0700151 }
152
153 @Override
154 public VlanVid applyMask(VlanVid mask) {
Andreas Wundsam55b71ce2013-10-01 19:26:46 -0700155 return VlanVid.ofRawVid((short)(this.vid & mask.vid));
Yotam Harcholf3f11152013-09-05 16:47:16 -0700156 }
157
Andreas Wundsam85c961f2013-09-29 21:22:12 -0700158 @Override
159 public int compareTo(VlanVid o) {
160 return Shorts.compare(vid, o.vid);
161 }
162
Yotam Harcholf3f11152013-09-05 16:47:16 -0700163}