alshabib

adding packet types

Showing 34 changed files with 4945 additions and 344 deletions
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
21 <groupId>com.google.guava</groupId> 21 <groupId>com.google.guava</groupId>
22 <artifactId>guava-testlib</artifactId> 22 <artifactId>guava-testlib</artifactId>
23 </dependency> 23 </dependency>
24 + <dependency>
25 + <groupId>org.onlab.onos</groupId>
26 + <artifactId>onlab-misc</artifactId>
27 + </dependency>
24 </dependencies> 28 </dependencies>
25 29
26 </project> 30 </project>
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
56 </execution> 56 </execution>
57 </executions> 57 </executions>
58 </plugin> 58 </plugin>
59 -
60 <plugin> 59 <plugin>
61 <groupId>org.apache.felix</groupId> 60 <groupId>org.apache.felix</groupId>
62 <artifactId>maven-bundle-plugin</artifactId> 61 <artifactId>maven-bundle-plugin</artifactId>
......
1 +package org.onlab.onos.of.controller;
2 +
3 +import org.onlab.packet.Ethernet;
4 +import org.projectfloodlight.openflow.protocol.OFPacketIn;
5 +import org.projectfloodlight.openflow.protocol.OFPacketOut;
6 +import org.projectfloodlight.openflow.types.OFPort;
7 +
8 +public class DefaultPacketContext implements PacketContext {
9 +
10 + private boolean free = true;
11 + private boolean isBuilt = false;
12 + private final OpenFlowSwitch sw;
13 + private final OFPacketIn pktin;
14 + private final OFPacketOut pktout = null;
15 +
16 + private DefaultPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
17 + this.sw = s;
18 + this.pktin = pkt;
19 + }
20 +
21 + @Override
22 + public void block() {
23 + free = false;
24 + }
25 +
26 + @Override
27 + public void send() {
28 + if (free && isBuilt) {
29 + sw.sendMsg(pktout);
30 + }
31 +
32 + }
33 +
34 + @Override
35 + public void build(OFPort outPort) {
36 + isBuilt = true;
37 +
38 + }
39 +
40 + @Override
41 + public void build(Ethernet ethFrame, OFPort outPort) {
42 + // TODO Auto-generated method stub
43 +
44 + }
45 +
46 + @Override
47 + public Ethernet parsed() {
48 + // TODO Auto-generated method stub
49 + return null;
50 + }
51 +
52 + @Override
53 + public Dpid dpid() {
54 + // TODO Auto-generated method stub
55 + return null;
56 + }
57 +
58 + public static PacketContext PacketContextFromPacketIn(OpenFlowSwitch s, OFPacketIn pkt) {
59 + return new DefaultPacketContext(s, pkt);
60 + }
61 +
62 +}
...@@ -87,9 +87,10 @@ public interface OpenFlowController { ...@@ -87,9 +87,10 @@ public interface OpenFlowController {
87 /** 87 /**
88 * Process a message and notify the appropriate listeners. 88 * Process a message and notify the appropriate listeners.
89 * 89 *
90 + * @param dpid the dpid the message arrived on
90 * @param msg the message to process. 91 * @param msg the message to process.
91 */ 92 */
92 - public void processPacket(OFMessage msg); 93 + public void processPacket(Dpid dpid, OFMessage msg);
93 94
94 /** 95 /**
95 * Sets the role for a given switch. 96 * Sets the role for a given switch.
......
1 package org.onlab.onos.of.controller; 1 package org.onlab.onos.of.controller;
2 2
3 +import org.onlab.packet.Ethernet;
3 import org.projectfloodlight.openflow.types.OFPort; 4 import org.projectfloodlight.openflow.types.OFPort;
4 5
5 /** 6 /**
...@@ -34,13 +35,13 @@ public interface PacketContext { ...@@ -34,13 +35,13 @@ public interface PacketContext {
34 * @param ethFrame the actual packet to send out. 35 * @param ethFrame the actual packet to send out.
35 * @param outPort the out port to send to packet out of. 36 * @param outPort the out port to send to packet out of.
36 */ 37 */
37 - public void build(Object ethFrame, OFPort outPort); 38 + public void build(Ethernet ethFrame, OFPort outPort);
38 39
39 /** 40 /**
40 * Provided a handle onto the parsed payload. 41 * Provided a handle onto the parsed payload.
41 * @return the parsed form of the payload. 42 * @return the parsed form of the payload.
42 */ 43 */
43 - public Object parsed(); 44 + public Ethernet parsed();
44 45
45 /** 46 /**
46 * Provide the dpid of the switch where the packet in arrived. 47 * Provide the dpid of the switch where the packet in arrived.
......
...@@ -159,7 +159,7 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { ...@@ -159,7 +159,7 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
159 */ 159 */
160 @Override 160 @Override
161 public final void handleMessage(OFMessage m) { 161 public final void handleMessage(OFMessage m) {
162 - this.agent.processMessage(m); 162 + this.agent.processMessage(dpid, m);
163 } 163 }
164 164
165 @Override 165 @Override
......
...@@ -69,7 +69,9 @@ public interface OpenFlowAgent { ...@@ -69,7 +69,9 @@ public interface OpenFlowAgent {
69 69
70 /** 70 /**
71 * Process a message coming from a switch. 71 * Process a message coming from a switch.
72 + *
73 + * @param dpid the dpid the message came on.
72 * @param m the message to process 74 * @param m the message to process
73 */ 75 */
74 - public void processMessage(OFMessage m); 76 + public void processMessage(Dpid dpid, OFMessage m);
75 } 77 }
......
1 -# See: http://rolf-engelhard.de/2011/04/using-the-same-suppression-filter-for-checkstyle-in-eclipse-and-maven/
2 -config_loc=conf/checkstyle
1 -<?xml version="1.0"?>
2 -<!DOCTYPE module PUBLIC
3 - "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
4 - "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
5 -
6 -
7 -<!--
8 -
9 - Checkstyle configuration that checks the sun coding conventions from:
10 -
11 - - the Java Language Specification at
12 - http://java.sun.com/docs/books/jls/second_edition/html/index.html
13 -
14 - - the Sun Code Conventions at http://java.sun.com/docs/codeconv/
15 -
16 - - the Javadoc guidelines at
17 - http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
18 -
19 - - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
20 -
21 - - some best practices
22 -
23 - Checkstyle is very configurable. Be sure to read the documentation at
24 - http://checkstyle.sf.net (or in your downloaded distribution).
25 -
26 - Most Checks are configurable, be sure to consult the documentation.
27 -
28 - To completely disable a check, just comment it out or delete it from the file.
29 -
30 - Finally, it is worth reading the documentation.
31 -
32 --->
33 -
34 -
35 -<!--
36 - The default severity setting in checkstyle is 'error', so some
37 - of the rules below are configured to change the severity to
38 - 'warning'. Over time, these 'warning' settings should be
39 - removed as more of the ONOS source code is modified to
40 - follow the recommended rules.
41 --->
42 -
43 -
44 -
45 -<module name="Checker">
46 - <module name="SuppressionFilter">
47 - <property name="file" value="${config_loc}/suppressions.xml"/>
48 - </module>
49 - <!--
50 - If you set the basedir property below, then all reported file
51 - names will be relative to the specified directory. See
52 - http://checkstyle.sourceforge.net/5.x/config.html#Checker
53 -
54 - <property name="basedir" value="${basedir}"/>
55 - -->
56 - <!-- Checks that a package-info.java file exists for each package. -->
57 - <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
58 - <!-- ONOS does not currently supply package level Javadoc information
59 - in package-info files -->
60 - <!-- <module name="JavadocPackage"/> -->
61 -
62 - <!-- Checks whether files end with a new line. -->
63 - <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
64 - <module name="NewlineAtEndOfFile"/>
65 -
66 - <!-- Checks that property files contain the same keys. -->
67 - <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
68 - <module name="Translation"/>
69 -
70 - <!-- Checks for Size Violations. -->
71 - <!-- See http://checkstyle.sf.net/config_sizes.html -->
72 - <module name="FileLength">
73 - <property name="max" value="2500"/>
74 - </module>
75 -
76 - <!-- Checks for whitespace -->
77 - <!-- See http://checkstyle.sf.net/config_whitespace.html -->
78 - <module name="FileTabCharacter"/>
79 -
80 - <!-- Miscellaneous other checks. -->
81 - <!-- See http://checkstyle.sf.net/config_misc.html -->
82 - <module name="RegexpSingleline">
83 - <property name="format" value="\s+$"/>
84 - <property name="minimum" value="0"/>
85 - <property name="maximum" value="0"/>
86 - <property name="message" value="Line has trailing spaces."/>
87 - </module>
88 -
89 - <!-- Checks for Headers -->
90 - <!-- See http://checkstyle.sf.net/config_header.html -->
91 - <!-- <module name="Header"> -->
92 - <!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
93 - <!-- <property name="fileExtensions" value="java"/> -->
94 - <!-- </module> -->
95 -
96 - <module name="SuppressionCommentFilter">
97 - <property name="offCommentFormat" value="(CHECKSTYLE\:OFF|Generated by the protocol buffer compiler.)"/>
98 - <property name="onCommentFormat" value="CHECKSTYLE:ON"/>
99 - </module>
100 -
101 - <module name="SuppressWithNearbyCommentFilter">
102 - <property name="commentFormat" value="CHECKSTYLE IGNORE THIS LINE" />
103 - <property name="checkFormat" value=".*" />
104 - <property name="influenceFormat" value="0" />
105 - </module>
106 -
107 - <!-- Example: // CHECKSTYLE IGNORE FinalClass FOR NEXT 1 LINES -->
108 - <module name="SuppressWithNearbyCommentFilter">
109 - <property name="commentFormat" value="CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES"/>
110 - <property name="checkFormat" value="$1"/>
111 - <property name="influenceFormat" value="$2"/>
112 - </module>
113 -
114 - <module name="TreeWalker">
115 -
116 - <module name="FileContentsHolder"/>
117 - <!-- Checks for Javadoc comments. -->
118 - <!-- See http://checkstyle.sf.net/config_javadoc.html -->
119 - <module name="JavadocMethod">
120 - <property name="severity" value="warning"/>
121 - <property name="allowUndeclaredRTE" value="true"/>
122 - </module>
123 - <module name="JavadocType">
124 - <property name="severity" value="warning"/>
125 - </module>
126 - <module name="JavadocVariable">
127 - <!-- Suppress check for private member Javadocs.
128 - Possibly revist fixing these. -->
129 - <property name="scope" value="public"/>
130 - <property name="severity" value="warning"/>
131 - </module>
132 - <module name="JavadocStyle"/>
133 - <!-- @author tag should not be used -->
134 - <module name="WriteTag">
135 - <property name="tag" value="@author"/>
136 - <property name="tagFormat" value="\S"/>
137 - <property name="severity" value="ignore"/>
138 - <property name="tagSeverity" value="error"/>
139 - </module>
140 -
141 -
142 - <!-- Checks for Naming Conventions. -->
143 - <!-- See http://checkstyle.sf.net/config_naming.html -->
144 - <module name="ConstantName">
145 - <!-- ONOS allows the name "log" for static final Loggers -->
146 - <property name="format"
147 - value="^log$|^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"/>
148 - </module>
149 - <module name="LocalFinalVariableName"/>
150 -
151 - <module name="LocalVariableName"/>
152 -
153 - <module name="MemberName"/>
154 - <module name="MethodName"/>
155 - <module name="PackageName"/>
156 - <module name="ParameterName"/>
157 - <module name="StaticVariableName"/>
158 - <module name="TypeName"/>
159 -
160 - <!-- Checks for imports -->
161 - <!-- See http://checkstyle.sf.net/config_import.html -->
162 - <module name="AvoidStarImport">
163 - <property name="allowStaticMemberImports" value="true"/>
164 - </module>
165 - <module name="IllegalImport"/>
166 - <!-- defaults to sun.* packages -->
167 - <module name="RedundantImport"/>
168 - <module name="UnusedImports"/>
169 -
170 -
171 - <!-- Checks for Size Violations. -->
172 - <!-- See http://checkstyle.sf.net/config_sizes.html -->
173 - <module name="LineLength">
174 - <!-- ONOS standard usage is 80 columns, but we allow up
175 - to 120 to not break the build. -->
176 - <property name="max" value="120"/>
177 - <property name="ignorePattern" value="^import"/>
178 - </module>
179 - <module name="MethodLength">
180 - <property name="max" value="400"/>
181 - </module>
182 -
183 - <module name="ParameterNumber"/>
184 -
185 - <!-- Checks for whitespace -->
186 - <!-- See http://checkstyle.sf.net/config_whitespace.html -->
187 - <module name="EmptyForIteratorPad"/>
188 - <module name="GenericWhitespace"/>
189 - <module name="MethodParamPad"/>
190 - <module name="NoWhitespaceAfter"/>
191 - <module name="NoWhitespaceBefore"/>
192 -
193 - <!-- Disabled for ONOS. Default rules specify undesired behavior for the '?' operator -->
194 - <!-- <module name="OperatorWrap"/> -->
195 - <module name="ParenPad"/>
196 - <module name="TypecastParenPad"/>
197 - <module name="WhitespaceAfter"/>
198 - <module name="WhitespaceAround">
199 - <property name="allowEmptyConstructors" value="true"/>
200 - <property name="allowEmptyMethods" value="true"/>
201 - </module>
202 -
203 -
204 -
205 - <!-- Modifier Checks -->
206 - <!-- See http://checkstyle.sf.net/config_modifiers.html -->
207 - <module name="ModifierOrder"/>
208 -
209 - <!-- Disabled for ONOS to allow use of public -->
210 - <!-- modifiers in interfaces. -->
211 - <!-- <module name="RedundantModifier"/> -->
212 -
213 -
214 - <!-- Checks for blocks. You know, those {}'s -->
215 - <!-- See http://checkstyle.sf.net/config_blocks.html -->
216 - <module name="AvoidNestedBlocks">
217 - <!-- ONOS alows declarations inside of switch case blocks -->
218 - <property name="allowInSwitchCase" value="true"/>
219 - </module>
220 - <module name="EmptyBlock"/>
221 - <module name="LeftCurly"/>
222 - <module name="NeedBraces"/>
223 - <module name="RightCurly"/>
224 -
225 - <!-- Checks for common coding problems -->
226 - <!-- See http://checkstyle.sf.net/config_coding.html -->
227 - <!-- ONOS allows conditional operators -->
228 - <!-- <module name="AvoidInlineConditionals"/> -->
229 - <module name="EmptyStatement"/>
230 - <module name="EqualsHashCode"/>
231 -
232 - <module name="HiddenField">
233 - <property name="ignoreSetter" value="true"/>
234 - <property name="ignoreConstructorParameter" value="true"/>
235 - </module>
236 -
237 - <module name="IllegalInstantiation"/>
238 - <module name="InnerAssignment"/>
239 -
240 - <!-- Many violations of this rule present, revist in a
241 - subsequent round of cleanups -->
242 - <!-- <module name="MagicNumber"/> -->
243 - <module name="MissingSwitchDefault"/>
244 -
245 - <module name="RedundantThrows">
246 - <property name="allowSubclasses" value="true"/>
247 - <property name="allowUnchecked" value="true"/>
248 - <property name="suppressLoadErrors" value="true"/>
249 - </module>
250 -
251 - <module name="SimplifyBooleanExpression"/>
252 - <module name="SimplifyBooleanReturn"/>
253 -
254 - <!-- Checks for class design -->
255 - <!-- See http://checkstyle.sf.net/config_design.html -->
256 - <!-- ONOS produces many warnings of this type.
257 - Fixing all of these is outside the scope of the current cleanup. -->
258 - <!-- <module name="DesignForExtension"/> -->
259 - <module name="FinalClass"/>
260 -
261 - <module name="HideUtilityClassConstructor"/>
262 -
263 - <module name="InterfaceIsType"/>
264 -
265 - <module name="VisibilityModifier">
266 - <property name="severity" value="warning"/>
267 - </module>
268 -
269 -
270 -
271 - <!-- Miscellaneous other checks. -->
272 - <!-- See http://checkstyle.sf.net/config_misc.html -->
273 - <module name="ArrayTypeStyle"/>
274 -
275 - <!-- Many violations of this rule currently, too many to fix
276 - in the current cleanup. -->
277 - <!-- <module name="FinalParameters"/> -->
278 - <!-- ONOS allows TODO markers in checked in source code -->
279 - <!-- <module name="TodoComment"/> -->
280 - <module name="UpperEll"/>
281 -
282 - </module>
283 -
284 - </module>
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN" "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
3 -
4 -<suppressions>
5 - <!--
6 - Note: Exclusion definition exists in multiple places.
7 - - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
8 - - In file conf/checkstyle/onos_suppressions.xml (this file)
9 - - maven-pmd-plugin configuration in pom.xml
10 - (under build and reporting)
11 - -->
12 -
13 - <suppress files=".*" checks="FinalParametersCheck"/>
14 - <suppress files=".*" checks="MagicNumbersCheck"/>
15 - <suppress files=".*" checks="DesignForExtensionCheck"/>
16 - <suppress files=".*" checks="TodoCommentCheck"/>
17 - <suppress files=".*" checks="AvoidInlineConditionalsCheck"/>
18 - <suppress files=".*" checks="OperatorWrapCheck"/>
19 -</suppressions>
20 -
1 -<FindBugsFilter>
2 - <!--
3 - Note: Exclusion definition exists in multiple places.
4 - - In file ${findbugs.excludeFilterFile} defined at top of pom.xml (this file)
5 - - In file conf/checkstyle/onos_suppressions.xml
6 - - maven-pmd-plugin configuration in pom.xml
7 - (under build and reporting)
8 - -->
9 - <Match>
10 - <Class name="~net\.onrc\.onos\.core\.datastore\.serializers\..*" />
11 - </Match>
12 - <Match>
13 - <Class name="~.*edu\.stanford\..*"/>
14 - </Match>
15 - <Match>
16 - <Class name="~.org\.projectfloodlight\..*"/>
17 - </Match>
18 -</FindBugsFilter>
...@@ -6,9 +6,7 @@ import java.util.concurrent.locks.Lock; ...@@ -6,9 +6,7 @@ import java.util.concurrent.locks.Lock;
6 import java.util.concurrent.locks.ReentrantLock; 6 import java.util.concurrent.locks.ReentrantLock;
7 7
8 import org.apache.felix.scr.annotations.Activate; 8 import org.apache.felix.scr.annotations.Activate;
9 -import org.apache.felix.scr.annotations.Component;
10 import org.apache.felix.scr.annotations.Deactivate; 9 import org.apache.felix.scr.annotations.Deactivate;
11 -import org.apache.felix.scr.annotations.Service;
12 import org.onlab.onos.of.controller.Dpid; 10 import org.onlab.onos.of.controller.Dpid;
13 import org.onlab.onos.of.controller.OpenFlowController; 11 import org.onlab.onos.of.controller.OpenFlowController;
14 import org.onlab.onos.of.controller.OpenFlowSwitch; 12 import org.onlab.onos.of.controller.OpenFlowSwitch;
...@@ -17,11 +15,10 @@ import org.onlab.onos.of.controller.PacketListener; ...@@ -17,11 +15,10 @@ import org.onlab.onos.of.controller.PacketListener;
17 import org.onlab.onos.of.controller.RoleState; 15 import org.onlab.onos.of.controller.RoleState;
18 import org.onlab.onos.of.controller.driver.OpenFlowAgent; 16 import org.onlab.onos.of.controller.driver.OpenFlowAgent;
19 import org.projectfloodlight.openflow.protocol.OFMessage; 17 import org.projectfloodlight.openflow.protocol.OFMessage;
18 +import org.projectfloodlight.openflow.protocol.OFPortStatus;
20 import org.slf4j.Logger; 19 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory; 20 import org.slf4j.LoggerFactory;
22 21
23 -@Component(immediate = true)
24 -@Service
25 public class OpenFlowControllerImpl implements OpenFlowController { 22 public class OpenFlowControllerImpl implements OpenFlowController {
26 23
27 private static final Logger log = 24 private static final Logger log =
...@@ -38,6 +35,9 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -38,6 +35,9 @@ public class OpenFlowControllerImpl implements OpenFlowController {
38 protected ArrayList<OpenFlowSwitchListener> ofEventListener = 35 protected ArrayList<OpenFlowSwitchListener> ofEventListener =
39 new ArrayList<OpenFlowSwitchListener>(); 36 new ArrayList<OpenFlowSwitchListener>();
40 37
38 + protected ArrayList<PacketListener> ofPacketListener =
39 + new ArrayList<PacketListener>();
40 +
41 private final Controller ctrl = new Controller(); 41 private final Controller ctrl = new Controller();
42 42
43 @Activate 43 @Activate
...@@ -94,14 +94,12 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -94,14 +94,12 @@ public class OpenFlowControllerImpl implements OpenFlowController {
94 94
95 @Override 95 @Override
96 public void addPacketListener(int priority, PacketListener listener) { 96 public void addPacketListener(int priority, PacketListener listener) {
97 - // TODO Auto-generated method stub 97 + ofPacketListener.add(priority, listener);
98 -
99 } 98 }
100 99
101 @Override 100 @Override
102 public void removePacketListener(PacketListener listener) { 101 public void removePacketListener(PacketListener listener) {
103 - // TODO Auto-generated method stub 102 + ofPacketListener.remove(listener);
104 -
105 } 103 }
106 104
107 @Override 105 @Override
...@@ -110,8 +108,22 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -110,8 +108,22 @@ public class OpenFlowControllerImpl implements OpenFlowController {
110 } 108 }
111 109
112 @Override 110 @Override
113 - public void processPacket(OFMessage msg) { 111 + public void processPacket(Dpid dpid, OFMessage msg) {
114 - log.info("Got message {}", msg); 112 + switch (msg.getType()) {
113 + case PORT_STATUS:
114 + for (OpenFlowSwitchListener l : ofEventListener) {
115 + l.portChanged(dpid, (OFPortStatus) msg);
116 + }
117 + break;
118 + case PACKET_IN:
119 + for (PacketListener p : ofPacketListener) {
120 + //TODO fix me!
121 + p.handlePacket(null);
122 + }
123 + break;
124 + default:
125 + log.warn("Handling message type {} not yet implemented", msg.getType());
126 + }
115 } 127 }
116 128
117 @Override 129 @Override
...@@ -252,8 +264,8 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -252,8 +264,8 @@ public class OpenFlowControllerImpl implements OpenFlowController {
252 } 264 }
253 265
254 @Override 266 @Override
255 - public void processMessage(OFMessage m) { 267 + public void processMessage(Dpid dpid, OFMessage m) {
256 - processPacket(m); 268 + processPacket(dpid, m);
257 } 269 }
258 } 270 }
259 271
......
...@@ -22,6 +22,13 @@ ...@@ -22,6 +22,13 @@
22 <module>drivers</module> 22 <module>drivers</module>
23 </modules> 23 </modules>
24 24
25 + <dependencies>
26 + <dependency>
27 + <groupId>org.onlab.onos</groupId>
28 + <artifactId>onlab-misc</artifactId>
29 + </dependency>
30 + </dependencies>
31 +
25 <build> 32 <build>
26 <plugins> 33 <plugins>
27 <plugin> 34 <plugin>
......
1 package org.onlab.onos.provider.of.link.impl; 1 package org.onlab.onos.provider.of.link.impl;
2 2
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
3 import org.apache.felix.scr.annotations.Activate; 5 import org.apache.felix.scr.annotations.Activate;
4 import org.apache.felix.scr.annotations.Component; 6 import org.apache.felix.scr.annotations.Component;
5 import org.apache.felix.scr.annotations.Deactivate; 7 import org.apache.felix.scr.annotations.Deactivate;
...@@ -11,10 +13,10 @@ import org.onlab.onos.net.link.LinkProviderService; ...@@ -11,10 +13,10 @@ import org.onlab.onos.net.link.LinkProviderService;
11 import org.onlab.onos.net.provider.AbstractProvider; 13 import org.onlab.onos.net.provider.AbstractProvider;
12 import org.onlab.onos.net.provider.ProviderId; 14 import org.onlab.onos.net.provider.ProviderId;
13 import org.onlab.onos.of.controller.OpenFlowController; 15 import org.onlab.onos.of.controller.OpenFlowController;
16 +import org.onlab.onos.of.controller.PacketContext;
17 +import org.onlab.onos.of.controller.PacketListener;
14 import org.slf4j.Logger; 18 import org.slf4j.Logger;
15 19
16 -import static org.slf4j.LoggerFactory.getLogger;
17 -
18 /** 20 /**
19 * Provider which uses an OpenFlow controller to detect network 21 * Provider which uses an OpenFlow controller to detect network
20 * infrastructure links. 22 * infrastructure links.
...@@ -32,6 +34,8 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid ...@@ -32,6 +34,8 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid
32 34
33 private LinkProviderService providerService; 35 private LinkProviderService providerService;
34 36
37 + private final PacketListener listener = new InternalLinkProvider();
38 +
35 /** 39 /**
36 * Creates an OpenFlow link provider. 40 * Creates an OpenFlow link provider.
37 */ 41 */
...@@ -42,14 +46,26 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid ...@@ -42,14 +46,26 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid
42 @Activate 46 @Activate
43 public void activate() { 47 public void activate() {
44 providerService = providerRegistry.register(this); 48 providerService = providerRegistry.register(this);
49 + controller.addPacketListener(0, listener);
45 log.info("Started"); 50 log.info("Started");
46 } 51 }
47 52
48 @Deactivate 53 @Deactivate
49 public void deactivate() { 54 public void deactivate() {
50 providerRegistry.unregister(this); 55 providerRegistry.unregister(this);
56 + controller.removePacketListener(listener);
51 providerService = null; 57 providerService = null;
52 log.info("Stopped"); 58 log.info("Stopped");
53 } 59 }
54 60
61 +
62 + private class InternalLinkProvider implements PacketListener {
63 +
64 + @Override
65 + public void handlePacket(PacketContext pktCtx) {
66 +
67 + }
68 +
69 + }
70 +
55 } 71 }
......
...@@ -25,5 +25,7 @@ ...@@ -25,5 +25,7 @@
25 <suppress files=".*" checks="TodoCommentCheck"/> 25 <suppress files=".*" checks="TodoCommentCheck"/>
26 <suppress files=".*" checks="AvoidInlineConditionalsCheck"/> 26 <suppress files=".*" checks="AvoidInlineConditionalsCheck"/>
27 <suppress files=".*" checks="OperatorWrapCheck"/> 27 <suppress files=".*" checks="OperatorWrapCheck"/>
28 + <suppress files=".*" checks="HiddenField"/>
29 +
28 </suppressions> 30 </suppressions>
29 31
......
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.nio.ByteBuffer;
36 +import java.util.Arrays;
37 +
38 +/**
39 + *
40 + * @author David Erickson (daviderickson@cs.stanford.edu)
41 + */
42 +public class ARP extends BasePacket {
43 + public static final short HW_TYPE_ETHERNET = 0x1;
44 +
45 + public static final short PROTO_TYPE_IP = 0x800;
46 +
47 + public static final short OP_REQUEST = 0x1;
48 + public static final short OP_REPLY = 0x2;
49 + public static final short OP_RARP_REQUEST = 0x3;
50 + public static final short OP_RARP_REPLY = 0x4;
51 +
52 + protected short hardwareType;
53 + protected short protocolType;
54 + protected byte hardwareAddressLength;
55 + protected byte protocolAddressLength;
56 + protected short opCode;
57 + protected byte[] senderHardwareAddress;
58 + protected byte[] senderProtocolAddress;
59 + protected byte[] targetHardwareAddress;
60 + protected byte[] targetProtocolAddress;
61 +
62 + /**
63 + * @return the hardwareType
64 + */
65 + public short getHardwareType() {
66 + return this.hardwareType;
67 + }
68 +
69 + /**
70 + * @param hardwareType
71 + * the hardwareType to set
72 + */
73 + public ARP setHardwareType(final short hwType) {
74 + this.hardwareType = hwType;
75 + return this;
76 + }
77 +
78 + /**
79 + * @return the protocolType
80 + */
81 + public short getProtocolType() {
82 + return this.protocolType;
83 + }
84 +
85 + /**
86 + * @param protocolType
87 + * the protocolType to set
88 + */
89 + public ARP setProtocolType(final short protoType) {
90 + this.protocolType = protoType;
91 + return this;
92 + }
93 +
94 + /**
95 + * @return the hardwareAddressLength
96 + */
97 + public byte getHardwareAddressLength() {
98 + return this.hardwareAddressLength;
99 + }
100 +
101 + /**
102 + * @param hwAddressLength
103 + * the hardwareAddressLength to set
104 + */
105 + public ARP setHardwareAddressLength(final byte hwAddressLength) {
106 + this.hardwareAddressLength = hwAddressLength;
107 + return this;
108 + }
109 +
110 + /**
111 + * @return the protocolAddressLength
112 + */
113 + public byte getProtocolAddressLength() {
114 + return this.protocolAddressLength;
115 + }
116 +
117 + /**
118 + * @param protocolAddressLength
119 + * the protocolAddressLength to set
120 + */
121 + public ARP setProtocolAddressLength(final byte protoAddressLength) {
122 + this.protocolAddressLength = protoAddressLength;
123 + return this;
124 + }
125 +
126 + /**
127 + * @return the opCode
128 + */
129 + public short getOpCode() {
130 + return this.opCode;
131 + }
132 +
133 + /**
134 + * @param opCode
135 + * the opCode to set
136 + */
137 + public ARP setOpCode(final short op) {
138 + this.opCode = op;
139 + return this;
140 + }
141 +
142 + /**
143 + * @return the senderHardwareAddress
144 + */
145 + public byte[] getSenderHardwareAddress() {
146 + return this.senderHardwareAddress;
147 + }
148 +
149 + /**
150 + * @param senderHardwareAddress
151 + * the senderHardwareAddress to set
152 + */
153 + public ARP setSenderHardwareAddress(final byte[] senderHWAddress) {
154 + this.senderHardwareAddress = senderHWAddress;
155 + return this;
156 + }
157 +
158 + /**
159 + * @return the senderProtocolAddress
160 + */
161 + public byte[] getSenderProtocolAddress() {
162 + return this.senderProtocolAddress;
163 + }
164 +
165 + /**
166 + * @param senderProtocolAddress
167 + * the senderProtocolAddress to set
168 + */
169 + public ARP setSenderProtocolAddress(final byte[] senderProtoAddress) {
170 + this.senderProtocolAddress = senderProtoAddress;
171 + return this;
172 + }
173 +
174 + public ARP setSenderProtocolAddress(final int address) {
175 + this.senderProtocolAddress = ByteBuffer.allocate(4).putInt(address)
176 + .array();
177 + return this;
178 + }
179 +
180 + /**
181 + * @return the targetHardwareAddress
182 + */
183 + public byte[] getTargetHardwareAddress() {
184 + return this.targetHardwareAddress;
185 + }
186 +
187 + /**
188 + * @param targetHardwareAddress
189 + * the targetHardwareAddress to set
190 + */
191 + public ARP setTargetHardwareAddress(final byte[] targetHWAddress) {
192 + this.targetHardwareAddress = targetHWAddress;
193 + return this;
194 + }
195 +
196 + /**
197 + * @return the targetProtocolAddress
198 + */
199 + public byte[] getTargetProtocolAddress() {
200 + return this.targetProtocolAddress;
201 + }
202 +
203 + /**
204 + * @return True if gratuitous ARP (SPA = TPA), false otherwise
205 + */
206 + public boolean isGratuitous() {
207 + assert this.senderProtocolAddress.length == this.targetProtocolAddress.length;
208 +
209 + int indx = 0;
210 + while (indx < this.senderProtocolAddress.length) {
211 + if (this.senderProtocolAddress[indx] != this.targetProtocolAddress[indx]) {
212 + return false;
213 + }
214 + indx++;
215 + }
216 +
217 + return true;
218 + }
219 +
220 + /**
221 + * @param targetProtocolAddress
222 + * the targetProtocolAddress to set
223 + */
224 + public ARP setTargetProtocolAddress(final byte[] targetProtoAddress) {
225 + this.targetProtocolAddress = targetProtoAddress;
226 + return this;
227 + }
228 +
229 + public ARP setTargetProtocolAddress(final int address) {
230 + this.targetProtocolAddress = ByteBuffer.allocate(4).putInt(address)
231 + .array();
232 + return this;
233 + }
234 +
235 + @Override
236 + public byte[] serialize() {
237 + final int length = 8 + 2 * (0xff & this.hardwareAddressLength) + 2
238 + * (0xff & this.protocolAddressLength);
239 + final byte[] data = new byte[length];
240 + final ByteBuffer bb = ByteBuffer.wrap(data);
241 + bb.putShort(this.hardwareType);
242 + bb.putShort(this.protocolType);
243 + bb.put(this.hardwareAddressLength);
244 + bb.put(this.protocolAddressLength);
245 + bb.putShort(this.opCode);
246 + bb.put(this.senderHardwareAddress, 0, 0xff & this.hardwareAddressLength);
247 + bb.put(this.senderProtocolAddress, 0, 0xff & this.protocolAddressLength);
248 + bb.put(this.targetHardwareAddress, 0, 0xff & this.hardwareAddressLength);
249 + bb.put(this.targetProtocolAddress, 0, 0xff & this.protocolAddressLength);
250 + return data;
251 + }
252 +
253 + @Override
254 + public IPacket deserialize(final byte[] data, final int offset,
255 + final int length) {
256 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
257 + this.hardwareType = bb.getShort();
258 + this.protocolType = bb.getShort();
259 + this.hardwareAddressLength = bb.get();
260 + this.protocolAddressLength = bb.get();
261 + this.opCode = bb.getShort();
262 + this.senderHardwareAddress = new byte[0xff & this.hardwareAddressLength];
263 + bb.get(this.senderHardwareAddress, 0, this.senderHardwareAddress.length);
264 + this.senderProtocolAddress = new byte[0xff & this.protocolAddressLength];
265 + bb.get(this.senderProtocolAddress, 0, this.senderProtocolAddress.length);
266 + this.targetHardwareAddress = new byte[0xff & this.hardwareAddressLength];
267 + bb.get(this.targetHardwareAddress, 0, this.targetHardwareAddress.length);
268 + this.targetProtocolAddress = new byte[0xff & this.protocolAddressLength];
269 + bb.get(this.targetProtocolAddress, 0, this.targetProtocolAddress.length);
270 + return this;
271 + }
272 +
273 + /*
274 + * (non-Javadoc)
275 + *
276 + * @see java.lang.Object#hashCode()
277 + */
278 + @Override
279 + public int hashCode() {
280 + final int prime = 13121;
281 + int result = super.hashCode();
282 + result = prime * result + this.hardwareAddressLength;
283 + result = prime * result + this.hardwareType;
284 + result = prime * result + this.opCode;
285 + result = prime * result + this.protocolAddressLength;
286 + result = prime * result + this.protocolType;
287 + result = prime * result + Arrays.hashCode(this.senderHardwareAddress);
288 + result = prime * result + Arrays.hashCode(this.senderProtocolAddress);
289 + result = prime * result + Arrays.hashCode(this.targetHardwareAddress);
290 + result = prime * result + Arrays.hashCode(this.targetProtocolAddress);
291 + return result;
292 + }
293 +
294 + /*
295 + * (non-Javadoc)
296 + *
297 + * @see java.lang.Object#equals(java.lang.Object)
298 + */
299 + @Override
300 + public boolean equals(final Object obj) {
301 + if (this == obj) {
302 + return true;
303 + }
304 + if (!super.equals(obj)) {
305 + return false;
306 + }
307 + if (!(obj instanceof ARP)) {
308 + return false;
309 + }
310 + final ARP other = (ARP) obj;
311 + if (this.hardwareAddressLength != other.hardwareAddressLength) {
312 + return false;
313 + }
314 + if (this.hardwareType != other.hardwareType) {
315 + return false;
316 + }
317 + if (this.opCode != other.opCode) {
318 + return false;
319 + }
320 + if (this.protocolAddressLength != other.protocolAddressLength) {
321 + return false;
322 + }
323 + if (this.protocolType != other.protocolType) {
324 + return false;
325 + }
326 + if (!Arrays.equals(this.senderHardwareAddress,
327 + other.senderHardwareAddress)) {
328 + return false;
329 + }
330 + if (!Arrays.equals(this.senderProtocolAddress,
331 + other.senderProtocolAddress)) {
332 + return false;
333 + }
334 + if (!Arrays.equals(this.targetHardwareAddress,
335 + other.targetHardwareAddress)) {
336 + return false;
337 + }
338 + if (!Arrays.equals(this.targetProtocolAddress,
339 + other.targetProtocolAddress)) {
340 + return false;
341 + }
342 + return true;
343 + }
344 +
345 + /*
346 + * (non-Javadoc)
347 + *
348 + * @see java.lang.Object#toString()
349 + */
350 + @Override
351 + public String toString() {
352 + return "ARP [hardwareType=" + this.hardwareType + ", protocolType="
353 + + this.protocolType + ", hardwareAddressLength="
354 + + this.hardwareAddressLength + ", protocolAddressLength="
355 + + this.protocolAddressLength + ", opCode=" + this.opCode
356 + + ", senderHardwareAddress="
357 + + Arrays.toString(this.senderHardwareAddress)
358 + + ", senderProtocolAddress="
359 + + Arrays.toString(this.senderProtocolAddress)
360 + + ", targetHardwareAddress="
361 + + Arrays.toString(this.targetHardwareAddress)
362 + + ", targetProtocolAddress="
363 + + Arrays.toString(this.targetProtocolAddress) + "]";
364 + }
365 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +/**
36 + *
37 + * @author David Erickson (daviderickson@cs.stanford.edu)
38 + */
39 +public abstract class BasePacket implements IPacket {
40 + protected IPacket parent;
41 + protected IPacket payload;
42 +
43 + /**
44 + * @return the parent
45 + */
46 + @Override
47 + public IPacket getParent() {
48 + return this.parent;
49 + }
50 +
51 + /**
52 + * @param parent
53 + * the parent to set
54 + */
55 + @Override
56 + public IPacket setParent(final IPacket parent) {
57 + this.parent = parent;
58 + return this;
59 + }
60 +
61 + /**
62 + * @return the payload
63 + */
64 + @Override
65 + public IPacket getPayload() {
66 + return this.payload;
67 + }
68 +
69 + /**
70 + * @param payload
71 + * the payload to set
72 + */
73 + @Override
74 + public IPacket setPayload(final IPacket payload) {
75 + this.payload = payload;
76 + return this;
77 + }
78 +
79 + @Override
80 + public void resetChecksum() {
81 + if (this.parent != null) {
82 + this.parent.resetChecksum();
83 + }
84 + }
85 +
86 + /*
87 + * (non-Javadoc)
88 + *
89 + * @see java.lang.Object#hashCode()
90 + */
91 + @Override
92 + public int hashCode() {
93 + final int prime = 6733;
94 + int result = 1;
95 + result = prime * result
96 + + (this.payload == null ? 0 : this.payload.hashCode());
97 + return result;
98 + }
99 +
100 + /*
101 + * (non-Javadoc)
102 + *
103 + * @see java.lang.Object#equals(java.lang.Object)
104 + */
105 + @Override
106 + public boolean equals(final Object obj) {
107 + if (this == obj) {
108 + return true;
109 + }
110 + if (obj == null) {
111 + return false;
112 + }
113 + if (!(obj instanceof BasePacket)) {
114 + return false;
115 + }
116 + final BasePacket other = (BasePacket) obj;
117 + if (this.payload == null) {
118 + if (other.payload != null) {
119 + return false;
120 + }
121 + } else if (!this.payload.equals(other.payload)) {
122 + return false;
123 + }
124 + return true;
125 + }
126 +
127 + @Override
128 + public Object clone() {
129 + IPacket pkt;
130 + try {
131 + pkt = this.getClass().newInstance();
132 + } catch (final Exception e) {
133 + throw new RuntimeException("Could not clone packet");
134 + }
135 + // TODO: we are using serialize()/deserialize() to perform the
136 + // cloning. Not the most efficient way but simple. We can revisit
137 + // if we hit performance problems.
138 + final byte[] data = this.serialize();
139 + pkt.deserialize(this.serialize(), 0, data.length);
140 + pkt.setParent(this.parent);
141 + return pkt;
142 + }
143 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.io.UnsupportedEncodingException;
36 +import java.nio.ByteBuffer;
37 +import java.util.ArrayList;
38 +import java.util.List;
39 +import java.util.ListIterator;
40 +
41 +/**
42 + *
43 + * @author David Erickson (daviderickson@cs.stanford.edu)
44 + */
45 +public class DHCP extends BasePacket {
46 + /**
47 + * Dynamic Host Configuration Protocol packet.
48 + * ------------------------------------------ |op (1) | htype(1) | hlen(1) |
49 + * hops(1) | ------------------------------------------ | xid (4) |
50 + * ------------------------------------------ | secs (2) | flags (2) |
51 + * ------------------------------------------ | ciaddr (4) |
52 + * ------------------------------------------ | yiaddr (4) |
53 + * ------------------------------------------ | siaddr (4) |
54 + * ------------------------------------------ | giaddr (4) |
55 + * ------------------------------------------ | chaddr (16) |
56 + * ------------------------------------------ | sname (64) |
57 + * ------------------------------------------ | file (128) |
58 + * ------------------------------------------ | options (312) |
59 + * ------------------------------------------
60 + *
61 + */
62 + // Header + magic without options
63 + public static final int MIN_HEADER_LENGTH = 240;
64 + public static final byte OPCODE_REQUEST = 0x1;
65 + public static final byte OPCODE_REPLY = 0x2;
66 +
67 + public static final byte HWTYPE_ETHERNET = 0x1;
68 +
69 + public enum DHCPOptionCode {
70 + OptionCode_SubnetMask((byte) 1), OptionCode_RequestedIP((byte) 50), OptionCode_LeaseTime(
71 + (byte) 51), OptionCode_MessageType((byte) 53), OptionCode_DHCPServerIp(
72 + (byte) 54), OptionCode_RequestedParameters((byte) 55), OptionCode_RenewalTime(
73 + (byte) 58), OPtionCode_RebindingTime((byte) 59), OptionCode_ClientID(
74 + (byte) 61), OptionCode_END((byte) 255);
75 +
76 + protected byte value;
77 +
78 + private DHCPOptionCode(final byte value) {
79 + this.value = value;
80 + }
81 +
82 + public byte getValue() {
83 + return this.value;
84 + }
85 + }
86 +
87 + protected byte opCode;
88 + protected byte hardwareType;
89 + protected byte hardwareAddressLength;
90 + protected byte hops;
91 + protected int transactionId;
92 + protected short seconds;
93 + protected short flags;
94 + protected int clientIPAddress;
95 + protected int yourIPAddress;
96 + protected int serverIPAddress;
97 + protected int gatewayIPAddress;
98 + protected byte[] clientHardwareAddress;
99 + protected String serverName;
100 + protected String bootFileName;
101 + protected List<DHCPOption> options = new ArrayList<DHCPOption>();
102 +
103 + /**
104 + * @return the opCode
105 + */
106 + public byte getOpCode() {
107 + return this.opCode;
108 + }
109 +
110 + /**
111 + * @param opCode
112 + * the opCode to set
113 + */
114 + public DHCP setOpCode(final byte opCode) {
115 + this.opCode = opCode;
116 + return this;
117 + }
118 +
119 + /**
120 + * @return the hardwareType
121 + */
122 + public byte getHardwareType() {
123 + return this.hardwareType;
124 + }
125 +
126 + /**
127 + * @param hardwareType
128 + * the hardwareType to set
129 + */
130 + public DHCP setHardwareType(final byte hardwareType) {
131 + this.hardwareType = hardwareType;
132 + return this;
133 + }
134 +
135 + /**
136 + * @return the hardwareAddressLength
137 + */
138 + public byte getHardwareAddressLength() {
139 + return this.hardwareAddressLength;
140 + }
141 +
142 + /**
143 + * @param hardwareAddressLength
144 + * the hardwareAddressLength to set
145 + */
146 + public DHCP setHardwareAddressLength(final byte hardwareAddressLength) {
147 + this.hardwareAddressLength = hardwareAddressLength;
148 + return this;
149 + }
150 +
151 + /**
152 + * @return the hops
153 + */
154 + public byte getHops() {
155 + return this.hops;
156 + }
157 +
158 + /**
159 + * @param hops
160 + * the hops to set
161 + */
162 + public DHCP setHops(final byte hops) {
163 + this.hops = hops;
164 + return this;
165 + }
166 +
167 + /**
168 + * @return the transactionId
169 + */
170 + public int getTransactionId() {
171 + return this.transactionId;
172 + }
173 +
174 + /**
175 + * @param transactionId
176 + * the transactionId to set
177 + */
178 + public DHCP setTransactionId(final int transactionId) {
179 + this.transactionId = transactionId;
180 + return this;
181 + }
182 +
183 + /**
184 + * @return the seconds
185 + */
186 + public short getSeconds() {
187 + return this.seconds;
188 + }
189 +
190 + /**
191 + * @param seconds
192 + * the seconds to set
193 + */
194 + public DHCP setSeconds(final short seconds) {
195 + this.seconds = seconds;
196 + return this;
197 + }
198 +
199 + /**
200 + * @return the flags
201 + */
202 + public short getFlags() {
203 + return this.flags;
204 + }
205 +
206 + /**
207 + * @param flags
208 + * the flags to set
209 + */
210 + public DHCP setFlags(final short flags) {
211 + this.flags = flags;
212 + return this;
213 + }
214 +
215 + /**
216 + * @return the clientIPAddress
217 + */
218 + public int getClientIPAddress() {
219 + return this.clientIPAddress;
220 + }
221 +
222 + /**
223 + * @param clientIPAddress
224 + * the clientIPAddress to set
225 + */
226 + public DHCP setClientIPAddress(final int clientIPAddress) {
227 + this.clientIPAddress = clientIPAddress;
228 + return this;
229 + }
230 +
231 + /**
232 + * @return the yourIPAddress
233 + */
234 + public int getYourIPAddress() {
235 + return this.yourIPAddress;
236 + }
237 +
238 + /**
239 + * @param yourIPAddress
240 + * the yourIPAddress to set
241 + */
242 + public DHCP setYourIPAddress(final int yourIPAddress) {
243 + this.yourIPAddress = yourIPAddress;
244 + return this;
245 + }
246 +
247 + /**
248 + * @return the serverIPAddress
249 + */
250 + public int getServerIPAddress() {
251 + return this.serverIPAddress;
252 + }
253 +
254 + /**
255 + * @param serverIPAddress
256 + * the serverIPAddress to set
257 + */
258 + public DHCP setServerIPAddress(final int serverIPAddress) {
259 + this.serverIPAddress = serverIPAddress;
260 + return this;
261 + }
262 +
263 + /**
264 + * @return the gatewayIPAddress
265 + */
266 + public int getGatewayIPAddress() {
267 + return this.gatewayIPAddress;
268 + }
269 +
270 + /**
271 + * @param gatewayIPAddress
272 + * the gatewayIPAddress to set
273 + */
274 + public DHCP setGatewayIPAddress(final int gatewayIPAddress) {
275 + this.gatewayIPAddress = gatewayIPAddress;
276 + return this;
277 + }
278 +
279 + /**
280 + * @return the clientHardwareAddress
281 + */
282 + public byte[] getClientHardwareAddress() {
283 + return this.clientHardwareAddress;
284 + }
285 +
286 + /**
287 + * @param clientHardwareAddress
288 + * the clientHardwareAddress to set
289 + */
290 + public DHCP setClientHardwareAddress(final byte[] clientHardwareAddress) {
291 + this.clientHardwareAddress = clientHardwareAddress;
292 + return this;
293 + }
294 +
295 + /**
296 + * Gets a specific DHCP option parameter.
297 + *
298 + * @param opetionCode
299 + * The option code to get
300 + * @return The value of the option if it exists, null otherwise
301 + */
302 + public DHCPOption getOption(final DHCPOptionCode optionCode) {
303 + for (final DHCPOption opt : this.options) {
304 + if (opt.code == optionCode.value) {
305 + return opt;
306 + }
307 + }
308 + return null;
309 + }
310 +
311 + /**
312 + * @return the options
313 + */
314 + public List<DHCPOption> getOptions() {
315 + return this.options;
316 + }
317 +
318 + /**
319 + * @param options
320 + * the options to set
321 + */
322 + public DHCP setOptions(final List<DHCPOption> options) {
323 + this.options = options;
324 + return this;
325 + }
326 +
327 + /**
328 + * @return the packetType base on option 53
329 + */
330 + public DHCPPacketType getPacketType() {
331 + final ListIterator<DHCPOption> lit = this.options.listIterator();
332 + while (lit.hasNext()) {
333 + final DHCPOption option = lit.next();
334 + // only care option 53
335 + if (option.getCode() == 53) {
336 + return DHCPPacketType.getType(option.getData()[0]);
337 + }
338 + }
339 + return null;
340 + }
341 +
342 + /**
343 + * @return the serverName
344 + */
345 + public String getServerName() {
346 + return this.serverName;
347 + }
348 +
349 + /**
350 + * @param server
351 + * the serverName to set
352 + */
353 + public DHCP setServerName(final String server) {
354 + this.serverName = server;
355 + return this;
356 + }
357 +
358 + /**
359 + * @return the bootFileName
360 + */
361 + public String getBootFileName() {
362 + return this.bootFileName;
363 + }
364 +
365 + /**
366 + * @param bootFile
367 + * the bootFileName to set
368 + */
369 + public DHCP setBootFileName(final String bootFile) {
370 + this.bootFileName = bootFile;
371 + return this;
372 + }
373 +
374 + @Override
375 + public byte[] serialize() {
376 + // not guaranteed to retain length/exact format
377 + this.resetChecksum();
378 +
379 + // minimum size 240 including magic cookie, options generally padded to
380 + // 300
381 + int optionsLength = 0;
382 + for (final DHCPOption option : this.options) {
383 + if (option.getCode() == 0 || option.getCode() == 255) {
384 + optionsLength += 1;
385 + } else {
386 + optionsLength += 2 + (0xff & option.getLength());
387 + }
388 + }
389 + int optionsPadLength = 0;
390 + if (optionsLength < 60) {
391 + optionsPadLength = 60 - optionsLength;
392 + }
393 +
394 + final byte[] data = new byte[240 + optionsLength + optionsPadLength];
395 + final ByteBuffer bb = ByteBuffer.wrap(data);
396 + bb.put(this.opCode);
397 + bb.put(this.hardwareType);
398 + bb.put(this.hardwareAddressLength);
399 + bb.put(this.hops);
400 + bb.putInt(this.transactionId);
401 + bb.putShort(this.seconds);
402 + bb.putShort(this.flags);
403 + bb.putInt(this.clientIPAddress);
404 + bb.putInt(this.yourIPAddress);
405 + bb.putInt(this.serverIPAddress);
406 + bb.putInt(this.gatewayIPAddress);
407 + bb.put(this.clientHardwareAddress);
408 + if (this.clientHardwareAddress.length < 16) {
409 + for (int i = 0; i < 16 - this.clientHardwareAddress.length; ++i) {
410 + bb.put((byte) 0x0);
411 + }
412 + }
413 + this.writeString(this.serverName, bb, 64);
414 + this.writeString(this.bootFileName, bb, 128);
415 + // magic cookie
416 + bb.put((byte) 0x63);
417 + bb.put((byte) 0x82);
418 + bb.put((byte) 0x53);
419 + bb.put((byte) 0x63);
420 + for (final DHCPOption option : this.options) {
421 + final int code = option.getCode() & 0xff;
422 + bb.put((byte) code);
423 + if (code != 0 && code != 255) {
424 + bb.put(option.getLength());
425 + bb.put(option.getData());
426 + }
427 + }
428 + // assume the rest is padded out with zeroes
429 + return data;
430 + }
431 +
432 + protected void writeString(final String string, final ByteBuffer bb,
433 + final int maxLength) {
434 + if (string == null) {
435 + for (int i = 0; i < maxLength; ++i) {
436 + bb.put((byte) 0x0);
437 + }
438 + } else {
439 + byte[] bytes = null;
440 + try {
441 + bytes = string.getBytes("ascii");
442 + } catch (final UnsupportedEncodingException e) {
443 + throw new RuntimeException("Failure encoding server name", e);
444 + }
445 + int writeLength = bytes.length;
446 + if (writeLength > maxLength) {
447 + writeLength = maxLength;
448 + }
449 + bb.put(bytes, 0, writeLength);
450 + for (int i = writeLength; i < maxLength; ++i) {
451 + bb.put((byte) 0x0);
452 + }
453 + }
454 + }
455 +
456 + @Override
457 + public IPacket deserialize(final byte[] data, final int offset,
458 + final int length) {
459 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
460 + if (bb.remaining() < DHCP.MIN_HEADER_LENGTH) {
461 + return this;
462 + }
463 +
464 + this.opCode = bb.get();
465 + this.hardwareType = bb.get();
466 + this.hardwareAddressLength = bb.get();
467 + this.hops = bb.get();
468 + this.transactionId = bb.getInt();
469 + this.seconds = bb.getShort();
470 + this.flags = bb.getShort();
471 + this.clientIPAddress = bb.getInt();
472 + this.yourIPAddress = bb.getInt();
473 + this.serverIPAddress = bb.getInt();
474 + this.gatewayIPAddress = bb.getInt();
475 + final int hardwareAddressLength = 0xff & this.hardwareAddressLength;
476 + this.clientHardwareAddress = new byte[hardwareAddressLength];
477 +
478 + bb.get(this.clientHardwareAddress);
479 + for (int i = hardwareAddressLength; i < 16; ++i) {
480 + bb.get();
481 + }
482 + this.serverName = this.readString(bb, 64);
483 + this.bootFileName = this.readString(bb, 128);
484 + // read the magic cookie
485 + // magic cookie
486 + bb.get();
487 + bb.get();
488 + bb.get();
489 + bb.get();
490 + // read options
491 + while (bb.hasRemaining()) {
492 + final DHCPOption option = new DHCPOption();
493 + int code = 0xff & bb.get(); // convert signed byte to int in range
494 + // [0,255]
495 + option.setCode((byte) code);
496 + if (code == 0) {
497 + // skip these
498 + continue;
499 + } else if (code != 255) {
500 + if (bb.hasRemaining()) {
501 + final int l = 0xff & bb.get(); // convert signed byte to
502 + // int in range [0,255]
503 + option.setLength((byte) l);
504 + if (bb.remaining() >= l) {
505 + final byte[] optionData = new byte[l];
506 + bb.get(optionData);
507 + option.setData(optionData);
508 + } else {
509 + // Skip the invalid option and set the END option
510 + code = 0xff;
511 + option.setCode((byte) code);
512 + option.setLength((byte) 0);
513 + }
514 + } else {
515 + // Skip the invalid option and set the END option
516 + code = 0xff;
517 + option.setCode((byte) code);
518 + option.setLength((byte) 0);
519 + }
520 + }
521 + this.options.add(option);
522 + if (code == 255) {
523 + // remaining bytes are supposed to be 0, but ignore them just in
524 + // case
525 + break;
526 + }
527 + }
528 +
529 + return this;
530 + }
531 +
532 + protected String readString(final ByteBuffer bb, final int maxLength) {
533 + final byte[] bytes = new byte[maxLength];
534 + bb.get(bytes);
535 + String result = null;
536 + try {
537 + result = new String(bytes, "ascii").trim();
538 + } catch (final UnsupportedEncodingException e) {
539 + throw new RuntimeException("Failure decoding string", e);
540 + }
541 + return result;
542 + }
543 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.util.Arrays;
36 +
37 +/**
38 + *
39 + * @author David Erickson (daviderickson@cs.stanford.edu)
40 + */
41 +public class DHCPOption {
42 + protected byte code;
43 + protected byte length;
44 + protected byte[] data;
45 +
46 + /**
47 + * @return the code
48 + */
49 + public byte getCode() {
50 + return this.code;
51 + }
52 +
53 + /**
54 + * @param code
55 + * the code to set
56 + */
57 + public DHCPOption setCode(final byte code) {
58 + this.code = code;
59 + return this;
60 + }
61 +
62 + /**
63 + * @return the length
64 + */
65 + public byte getLength() {
66 + return this.length;
67 + }
68 +
69 + /**
70 + * @param length
71 + * the length to set
72 + */
73 + public DHCPOption setLength(final byte length) {
74 + this.length = length;
75 + return this;
76 + }
77 +
78 + /**
79 + * @return the data
80 + */
81 + public byte[] getData() {
82 + return this.data;
83 + }
84 +
85 + /**
86 + * @param data
87 + * the data to set
88 + */
89 + public DHCPOption setData(final byte[] data) {
90 + this.data = data;
91 + return this;
92 + }
93 +
94 + /*
95 + * (non-Javadoc)
96 + *
97 + * @see java.lang.Object#hashCode()
98 + */
99 + @Override
100 + public int hashCode() {
101 + final int prime = 31;
102 + int result = 1;
103 + result = prime * result + this.code;
104 + result = prime * result + Arrays.hashCode(this.data);
105 + result = prime * result + this.length;
106 + return result;
107 + }
108 +
109 + /*
110 + * (non-Javadoc)
111 + *
112 + * @see java.lang.Object#equals(java.lang.Object)
113 + */
114 + @Override
115 + public boolean equals(final Object obj) {
116 + if (this == obj) {
117 + return true;
118 + }
119 + if (obj == null) {
120 + return false;
121 + }
122 + if (!(obj instanceof DHCPOption)) {
123 + return false;
124 + }
125 + final DHCPOption other = (DHCPOption) obj;
126 + if (this.code != other.code) {
127 + return false;
128 + }
129 + if (!Arrays.equals(this.data, other.data)) {
130 + return false;
131 + }
132 + if (this.length != other.length) {
133 + return false;
134 + }
135 + return true;
136 + }
137 +
138 + /*
139 + * (non-Javadoc)
140 + *
141 + * @see java.lang.Object#toString()
142 + */
143 + @Override
144 + public String toString() {
145 + return "DHCPOption [code=" + this.code + ", length=" + this.length
146 + + ", data=" + Arrays.toString(this.data) + "]";
147 + }
148 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +public enum DHCPPacketType {
36 + // From RFC 1533
37 + DHCPDISCOVER(1), DHCPOFFER(2), DHCPREQUEST(3), DHCPDECLINE(4), DHCPACK(5), DHCPNAK(
38 + 6), DHCPRELEASE(7),
39 +
40 + // From RFC2132
41 + DHCPINFORM(8),
42 +
43 + // From RFC3203
44 + DHCPFORCERENEW(9),
45 +
46 + // From RFC4388
47 + DHCPLEASEQUERY(10), DHCPLEASEUNASSIGNED(11), DHCPLEASEUNKNOWN(12), DHCPLEASEACTIVE(
48 + 13);
49 +
50 + protected int value;
51 +
52 + private DHCPPacketType(final int value) {
53 + this.value = value;
54 + }
55 +
56 + public int getValue() {
57 + return this.value;
58 + }
59 +
60 + @Override
61 + public String toString() {
62 + switch (this.value) {
63 + case 1:
64 + return "DHCPDISCOVER";
65 + case 2:
66 + return "DHCPOFFER";
67 + case 3:
68 + return "DHCPREQUEST";
69 + case 4:
70 + return "DHCPDECLINE";
71 + case 5:
72 + return "DHCPACK";
73 + case 6:
74 + return "DHCPNAK";
75 + case 7:
76 + return "DHCPRELEASE";
77 + case 8:
78 + return "DHCPINFORM";
79 + case 9:
80 + return "DHCPFORCERENEW";
81 + case 10:
82 + return "DHCPLEASEQUERY";
83 + case 11:
84 + return "DHCPLEASEUNASSIGNED";
85 + case 12:
86 + return "DHCPLEASEUNKNOWN";
87 + case 13:
88 + return "DHCPLEASEACTIVE";
89 + default:
90 + break;
91 + }
92 +
93 + return null;
94 + }
95 +
96 + public static DHCPPacketType getType(final int value) {
97 + switch (value) {
98 + case 1:
99 + return DHCPDISCOVER;
100 + case 2:
101 + return DHCPOFFER;
102 + case 3:
103 + return DHCPREQUEST;
104 + case 4:
105 + return DHCPDECLINE;
106 + case 5:
107 + return DHCPACK;
108 + case 6:
109 + return DHCPNAK;
110 + case 7:
111 + return DHCPRELEASE;
112 + case 8:
113 + return DHCPINFORM;
114 + case 9:
115 + return DHCPFORCERENEW;
116 + case 10:
117 + return DHCPLEASEQUERY;
118 + case 11:
119 + return DHCPLEASEUNASSIGNED;
120 + case 12:
121 + return DHCPLEASEUNKNOWN;
122 + case 13:
123 + return DHCPLEASEACTIVE;
124 + default:
125 + break;
126 + }
127 +
128 + return null;
129 + }
130 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.util.Arrays;
36 +
37 +/**
38 + *
39 + * @author David Erickson (daviderickson@cs.stanford.edu)
40 + */
41 +public class Data extends BasePacket {
42 + protected byte[] data;
43 +
44 + /**
45 + *
46 + */
47 + public Data() {
48 + }
49 +
50 + /**
51 + * @param data
52 + */
53 + public Data(final byte[] data) {
54 + this.data = data;
55 + }
56 +
57 + /**
58 + * @return the data
59 + */
60 + public byte[] getData() {
61 + return this.data;
62 + }
63 +
64 + /**
65 + * @param data
66 + * the data to set
67 + */
68 + public Data setData(final byte[] data) {
69 + this.data = data;
70 + return this;
71 + }
72 +
73 + @Override
74 + public byte[] serialize() {
75 + return this.data;
76 + }
77 +
78 + @Override
79 + public IPacket deserialize(final byte[] data, final int offset,
80 + final int length) {
81 + this.data = Arrays.copyOfRange(data, offset, data.length);
82 + return this;
83 + }
84 +
85 + /*
86 + * (non-Javadoc)
87 + *
88 + * @see java.lang.Object#hashCode()
89 + */
90 + @Override
91 + public int hashCode() {
92 + final int prime = 1571;
93 + int result = super.hashCode();
94 + result = prime * result + Arrays.hashCode(this.data);
95 + return result;
96 + }
97 +
98 + /*
99 + * (non-Javadoc)
100 + *
101 + * @see java.lang.Object#equals(java.lang.Object)
102 + */
103 + @Override
104 + public boolean equals(final Object obj) {
105 + if (this == obj) {
106 + return true;
107 + }
108 + if (!super.equals(obj)) {
109 + return false;
110 + }
111 + if (!(obj instanceof Data)) {
112 + return false;
113 + }
114 + final Data other = (Data) obj;
115 + if (!Arrays.equals(this.data, other.data)) {
116 + return false;
117 + }
118 + return true;
119 + }
120 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.nio.ByteBuffer;
36 +import java.util.Arrays;
37 +import java.util.HashMap;
38 +import java.util.Map;
39 +
40 +
41 +/**
42 + *
43 + * @author David Erickson (daviderickson@cs.stanford.edu)
44 + */
45 +public class Ethernet extends BasePacket {
46 + private static final String HEXES = "0123456789ABCDEF";
47 + public static final short TYPE_ARP = 0x0806;
48 + public static final short TYPE_RARP = (short) 0x8035;
49 + public static final short TYPE_IPV4 = 0x0800;
50 + public static final short TYPE_LLDP = (short) 0x88cc;
51 + public static final short TYPE_BSN = (short) 0x8942;
52 + public static final short VLAN_UNTAGGED = (short) 0xffff;
53 + public static final short DATALAYER_ADDRESS_LENGTH = 6; // bytes
54 + public static Map<Short, Class<? extends IPacket>> etherTypeClassMap;
55 +
56 + static {
57 + Ethernet.etherTypeClassMap = new HashMap<Short, Class<? extends IPacket>>();
58 + Ethernet.etherTypeClassMap.put(Ethernet.TYPE_ARP, ARP.class);
59 + Ethernet.etherTypeClassMap.put(Ethernet.TYPE_RARP, ARP.class);
60 + Ethernet.etherTypeClassMap.put(Ethernet.TYPE_IPV4, IPv4.class);
61 + Ethernet.etherTypeClassMap.put(Ethernet.TYPE_LLDP, LLDP.class);
62 + }
63 +
64 + protected MACAddress destinationMACAddress;
65 + protected MACAddress sourceMACAddress;
66 + protected byte priorityCode;
67 + protected short vlanID;
68 + protected short etherType;
69 + protected boolean pad = false;
70 +
71 + /**
72 + * By default, set Ethernet to untagged.
73 + */
74 + public Ethernet() {
75 + super();
76 + this.vlanID = Ethernet.VLAN_UNTAGGED;
77 + }
78 +
79 + /**
80 + * Gets the destination MAC address.
81 + *
82 + * @return the destination MAC as a byte array
83 + */
84 + public byte[] getDestinationMACAddress() {
85 + return this.destinationMACAddress.toBytes();
86 + }
87 +
88 + /**
89 + * Gets the destination MAC address.
90 + *
91 + * @return the destination MAC
92 + */
93 + public MACAddress getDestinationMAC() {
94 + return this.destinationMACAddress;
95 + }
96 +
97 + /**
98 + * Sets the destination MAC address.
99 + *
100 + * @param destinationMACAddress the destination MAC to set
101 + * @return the Ethernet frame
102 + */
103 + public Ethernet setDestinationMACAddress(final byte[] destMac) {
104 + this.destinationMACAddress = MACAddress.valueOf(destMac);
105 + return this;
106 + }
107 +
108 + /**
109 + * Sets the destination MAC address.
110 + *
111 + * @param destinationMACAddress the destination MAC to set
112 + * @return the Ethernet frame
113 + */
114 + public Ethernet setDestinationMACAddress(final String destMac) {
115 + this.destinationMACAddress = MACAddress.valueOf(destMac);
116 + return this;
117 + }
118 +
119 + /**
120 + * Gets the source MAC address.
121 + *
122 + * @return the source MACAddress as a byte array
123 + */
124 + public byte[] getSourceMACAddress() {
125 + return this.sourceMACAddress.toBytes();
126 + }
127 +
128 + /**
129 + * Gets the source MAC address.
130 + *
131 + * @return the source MACAddress
132 + */
133 + public MACAddress getSourceMAC() {
134 + return this.sourceMACAddress;
135 + }
136 +
137 + /**
138 + * Sets the source MAC address.
139 + *
140 + * @param sourceMACAddress the source MAC to set
141 + * @return the Ethernet frame
142 + */
143 + public Ethernet setSourceMACAddress(final byte[] sourceMac) {
144 + this.sourceMACAddress = MACAddress.valueOf(sourceMac);
145 + return this;
146 + }
147 +
148 + /**
149 + * Sets the source MAC address.
150 + *
151 + * @param sourceMACAddress the source MAC to set
152 + * @return the Ethernet frame
153 + */
154 + public Ethernet setSourceMACAddress(final String sourceMac) {
155 + this.sourceMACAddress = MACAddress.valueOf(sourceMac);
156 + return this;
157 + }
158 +
159 + /**
160 + * Gets the priority code.
161 + *
162 + * @return the priorityCode
163 + */
164 + public byte getPriorityCode() {
165 + return this.priorityCode;
166 + }
167 +
168 + /**
169 + * Sets the priority code.
170 + *
171 + * @param priorityCode the priorityCode to set
172 + * @return the Ethernet frame
173 + */
174 + public Ethernet setPriorityCode(final byte priority) {
175 + this.priorityCode = priority;
176 + return this;
177 + }
178 +
179 + /**
180 + * Gets the VLAN ID.
181 + *
182 + * @return the vlanID
183 + */
184 + public short getVlanID() {
185 + return this.vlanID;
186 + }
187 +
188 + /**
189 + * Sets the VLAN ID.
190 + *
191 + * @param vlanID the vlanID to set
192 + * @return the Ethernet frame
193 + */
194 + public Ethernet setVlanID(final short vlan) {
195 + this.vlanID = vlan;
196 + return this;
197 + }
198 +
199 + /**
200 + * Gets the Ethernet type.
201 + *
202 + * @return the etherType
203 + */
204 + public short getEtherType() {
205 + return this.etherType;
206 + }
207 +
208 + /**
209 + * Sets the Ethernet type.
210 + *
211 + * @param etherType the etherType to set
212 + * @return the Ethernet frame
213 + */
214 + public Ethernet setEtherType(final short ethType) {
215 + this.etherType = ethType;
216 + return this;
217 + }
218 +
219 + /**
220 + * @return True if the Ethernet frame is broadcast, false otherwise
221 + */
222 + public boolean isBroadcast() {
223 + assert this.destinationMACAddress.length() == 6;
224 + return this.destinationMACAddress.isBroadcast();
225 + }
226 +
227 + /**
228 + * @return True is the Ethernet frame is multicast, False otherwise
229 + */
230 + public boolean isMulticast() {
231 + return this.destinationMACAddress.isMulticast();
232 + }
233 +
234 + /**
235 + * Pad this packet to 60 bytes minimum, filling with zeros?
236 + *
237 + * @return the pad
238 + */
239 + public boolean isPad() {
240 + return this.pad;
241 + }
242 +
243 + /**
244 + * Pad this packet to 60 bytes minimum, filling with zeros?
245 + *
246 + * @param pad
247 + * the pad to set
248 + */
249 + public Ethernet setPad(final boolean pd) {
250 + this.pad = pd;
251 + return this;
252 + }
253 +
254 + @Override
255 + public byte[] serialize() {
256 + byte[] payloadData = null;
257 + if (this.payload != null) {
258 + this.payload.setParent(this);
259 + payloadData = this.payload.serialize();
260 + }
261 + int length = 14 + (this.vlanID == Ethernet.VLAN_UNTAGGED ? 0 : 4)
262 + + (payloadData == null ? 0 : payloadData.length);
263 + if (this.pad && length < 60) {
264 + length = 60;
265 + }
266 + final byte[] data = new byte[length];
267 + final ByteBuffer bb = ByteBuffer.wrap(data);
268 + bb.put(this.destinationMACAddress.toBytes());
269 + bb.put(this.sourceMACAddress.toBytes());
270 + if (this.vlanID != Ethernet.VLAN_UNTAGGED) {
271 + bb.putShort((short) 0x8100);
272 + bb.putShort((short) (this.priorityCode << 13 | this.vlanID & 0x0fff));
273 + }
274 + bb.putShort(this.etherType);
275 + if (payloadData != null) {
276 + bb.put(payloadData);
277 + }
278 + if (this.pad) {
279 + Arrays.fill(data, bb.position(), data.length, (byte) 0x0);
280 + }
281 + return data;
282 + }
283 +
284 + @Override
285 + public IPacket deserialize(final byte[] data, final int offset,
286 + final int length) {
287 + if (length <= 0) {
288 + return null;
289 + }
290 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
291 + if (this.destinationMACAddress == null) {
292 + this.destinationMACAddress = MACAddress.valueOf(new byte[6]);
293 + }
294 + final byte[] dstAddr = new byte[MACAddress.MAC_ADDRESS_LENGTH];
295 + bb.get(dstAddr);
296 + this.destinationMACAddress = MACAddress.valueOf(dstAddr);
297 +
298 + if (this.sourceMACAddress == null) {
299 + this.sourceMACAddress = MACAddress.valueOf(new byte[6]);
300 + }
301 + final byte[] srcAddr = new byte[MACAddress.MAC_ADDRESS_LENGTH];
302 + bb.get(srcAddr);
303 + this.sourceMACAddress = MACAddress.valueOf(srcAddr);
304 +
305 + short ethType = bb.getShort();
306 + if (ethType == (short) 0x8100) {
307 + final short tci = bb.getShort();
308 + this.priorityCode = (byte) (tci >> 13 & 0x07);
309 + this.vlanID = (short) (tci & 0x0fff);
310 + ethType = bb.getShort();
311 + } else {
312 + this.vlanID = Ethernet.VLAN_UNTAGGED;
313 + }
314 + this.etherType = ethType;
315 +
316 + IPacket payload;
317 + if (Ethernet.etherTypeClassMap.containsKey(this.etherType)) {
318 + final Class<? extends IPacket> clazz = Ethernet.etherTypeClassMap
319 + .get(this.etherType);
320 + try {
321 + payload = clazz.newInstance();
322 + } catch (final Exception e) {
323 + throw new RuntimeException(
324 + "Error parsing payload for Ethernet packet", e);
325 + }
326 + } else {
327 + payload = new Data();
328 + }
329 + this.payload = payload.deserialize(data, bb.position(),
330 + bb.limit() - bb.position());
331 + this.payload.setParent(this);
332 + return this;
333 + }
334 +
335 + /**
336 + * Checks to see if a string is a valid MAC address.
337 + *
338 + * @param macAddress
339 + * @return True if macAddress is a valid MAC, False otherwise
340 + */
341 + public static boolean isMACAddress(final String macAddress) {
342 + final String[] macBytes = macAddress.split(":");
343 + if (macBytes.length != 6) {
344 + return false;
345 + }
346 + for (int i = 0; i < 6; ++i) {
347 + if (Ethernet.HEXES.indexOf(macBytes[i].toUpperCase().charAt(0)) == -1
348 + || Ethernet.HEXES.indexOf(macBytes[i].toUpperCase().charAt(
349 + 1)) == -1) {
350 + return false;
351 + }
352 + }
353 + return true;
354 + }
355 +
356 + /**
357 + * Accepts a MAC address of the form 00:aa:11:bb:22:cc, case does not
358 + * matter, and returns a corresponding byte[].
359 + *
360 + * @param macAddress
361 + * The MAC address to convert into a bye array
362 + * @return The macAddress as a byte array
363 + */
364 + public static byte[] toMACAddress(final String macAddress) {
365 + return MACAddress.valueOf(macAddress).toBytes();
366 + }
367 +
368 + /**
369 + * Accepts a MAC address and returns the corresponding long, where the MAC
370 + * bytes are set on the lower order bytes of the long.
371 + *
372 + * @param macAddress
373 + * @return a long containing the mac address bytes
374 + */
375 + public static long toLong(final byte[] macAddress) {
376 + return MACAddress.valueOf(macAddress).toLong();
377 + }
378 +
379 + /**
380 + * Converts a long MAC address to a byte array.
381 + *
382 + * @param macAddress
383 + * @return the bytes of the mac address
384 + */
385 + public static byte[] toByteArray(final long macAddress) {
386 + return MACAddress.valueOf(macAddress).toBytes();
387 + }
388 +
389 + /*
390 + * (non-Javadoc)
391 + *
392 + * @see java.lang.Object#hashCode()
393 + */
394 + @Override
395 + public int hashCode() {
396 + final int prime = 7867;
397 + int result = super.hashCode();
398 + result = prime * result + this.destinationMACAddress.hashCode();
399 + result = prime * result + this.etherType;
400 + result = prime * result + this.vlanID;
401 + result = prime * result + this.priorityCode;
402 + result = prime * result + (this.pad ? 1231 : 1237);
403 + result = prime * result + this.sourceMACAddress.hashCode();
404 + return result;
405 + }
406 +
407 + /*
408 + * (non-Javadoc)
409 + *
410 + * @see java.lang.Object#equals(java.lang.Object)
411 + */
412 + @Override
413 + public boolean equals(final Object obj) {
414 + if (this == obj) {
415 + return true;
416 + }
417 + if (!super.equals(obj)) {
418 + return false;
419 + }
420 + if (!(obj instanceof Ethernet)) {
421 + return false;
422 + }
423 + final Ethernet other = (Ethernet) obj;
424 + if (!this.destinationMACAddress.equals(other.destinationMACAddress)) {
425 + return false;
426 + }
427 + if (this.priorityCode != other.priorityCode) {
428 + return false;
429 + }
430 + if (this.vlanID != other.vlanID) {
431 + return false;
432 + }
433 + if (this.etherType != other.etherType) {
434 + return false;
435 + }
436 + if (this.pad != other.pad) {
437 + return false;
438 + }
439 + if (!this.sourceMACAddress.equals(other.sourceMACAddress)) {
440 + return false;
441 + }
442 + return true;
443 + }
444 +
445 + /*
446 + * (non-Javadoc)
447 + *
448 + * @see java.lang.Object#toString(java.lang.Object)
449 + */
450 + @Override
451 + public String toString() {
452 +
453 + final StringBuffer sb = new StringBuffer("\n");
454 +
455 + final IPacket pkt = this.getPayload();
456 +
457 + if (pkt instanceof ARP) {
458 + sb.append("arp");
459 + } else if (pkt instanceof LLDP) {
460 + sb.append("lldp");
461 + } else if (pkt instanceof ICMP) {
462 + sb.append("icmp");
463 + } else if (pkt instanceof IPv4) {
464 + sb.append("ip");
465 + } else if (pkt instanceof DHCP) {
466 + sb.append("dhcp");
467 + } else {
468 + sb.append(this.getEtherType());
469 + }
470 +
471 + sb.append("\ndl_vlan: ");
472 + if (this.getVlanID() == Ethernet.VLAN_UNTAGGED) {
473 + sb.append("untagged");
474 + } else {
475 + sb.append(this.getVlanID());
476 + }
477 + sb.append("\ndl_vlan_pcp: ");
478 + sb.append(this.getPriorityCode());
479 + sb.append("\ndl_src: ");
480 + sb.append(bytesToHex(this.getSourceMACAddress()));
481 + sb.append("\ndl_dst: ");
482 + sb.append(bytesToHex(this.getDestinationMACAddress()));
483 +
484 + if (pkt instanceof ARP) {
485 + final ARP p = (ARP) pkt;
486 + sb.append("\nnw_src: ");
487 + sb.append(IPv4.fromIPv4Address(IPv4.toIPv4Address(p
488 + .getSenderProtocolAddress())));
489 + sb.append("\nnw_dst: ");
490 + sb.append(IPv4.fromIPv4Address(IPv4.toIPv4Address(p
491 + .getTargetProtocolAddress())));
492 + } else if (pkt instanceof LLDP) {
493 + sb.append("lldp packet");
494 + } else if (pkt instanceof ICMP) {
495 + final ICMP icmp = (ICMP) pkt;
496 + sb.append("\nicmp_type: ");
497 + sb.append(icmp.getIcmpType());
498 + sb.append("\nicmp_code: ");
499 + sb.append(icmp.getIcmpCode());
500 + } else if (pkt instanceof IPv4) {
501 + final IPv4 p = (IPv4) pkt;
502 + sb.append("\nnw_src: ");
503 + sb.append(IPv4.fromIPv4Address(p.getSourceAddress()));
504 + sb.append("\nnw_dst: ");
505 + sb.append(IPv4.fromIPv4Address(p.getDestinationAddress()));
506 + sb.append("\nnw_tos: ");
507 + sb.append(p.getDiffServ());
508 + sb.append("\nnw_proto: ");
509 + sb.append(p.getProtocol());
510 +
511 + if (pkt instanceof TCP) {
512 + sb.append("\ntp_src: ");
513 + sb.append(((TCP) pkt).getSourcePort());
514 + sb.append("\ntp_dst: ");
515 + sb.append(((TCP) pkt).getDestinationPort());
516 +
517 + } else if (pkt instanceof UDP) {
518 + sb.append("\ntp_src: ");
519 + sb.append(((UDP) pkt).getSourcePort());
520 + sb.append("\ntp_dst: ");
521 + sb.append(((UDP) pkt).getDestinationPort());
522 + }
523 +
524 + if (pkt instanceof ICMP) {
525 + final ICMP icmp = (ICMP) pkt;
526 + sb.append("\nicmp_type: ");
527 + sb.append(icmp.getIcmpType());
528 + sb.append("\nicmp_code: ");
529 + sb.append(icmp.getIcmpCode());
530 + }
531 +
532 + } else if (pkt instanceof DHCP) {
533 + sb.append("\ndhcp packet");
534 + } else if (pkt instanceof Data) {
535 + sb.append("\ndata packet");
536 + } else if (pkt instanceof LLC) {
537 + sb.append("\nllc packet");
538 + } else {
539 + sb.append("\nunknwon packet");
540 + }
541 +
542 + return sb.toString();
543 + }
544 +
545 + public static String bytesToHex(byte[] in) {
546 + final StringBuilder builder = new StringBuilder();
547 + for (byte b : in) {
548 + builder.append(String.format("%02x", b));
549 + }
550 + return builder.toString();
551 + }
552 +
553 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.nio.ByteBuffer;
36 +
37 +/**
38 + * Implements ICMP packet format.
39 + *
40 + * @author shudong.zhou@bigswitch.com
41 + */
42 +public class ICMP extends BasePacket {
43 + protected byte icmpType;
44 + protected byte icmpCode;
45 + protected short checksum;
46 +
47 + /**
48 + * @return the icmpType
49 + */
50 + public byte getIcmpType() {
51 + return this.icmpType;
52 + }
53 +
54 + /**
55 + * @param icmpType
56 + * to set
57 + */
58 + public ICMP setIcmpType(final byte icmpType) {
59 + this.icmpType = icmpType;
60 + return this;
61 + }
62 +
63 + /**
64 + * @return the icmp code
65 + */
66 + public byte getIcmpCode() {
67 + return this.icmpCode;
68 + }
69 +
70 + /**
71 + * @param icmpCode
72 + * code to set
73 + */
74 + public ICMP setIcmpCode(final byte icmpCode) {
75 + this.icmpCode = icmpCode;
76 + return this;
77 + }
78 +
79 + /**
80 + * @return the checksum
81 + */
82 + public short getChecksum() {
83 + return this.checksum;
84 + }
85 +
86 + /**
87 + * @param checksum
88 + * the checksum to set
89 + */
90 + public ICMP setChecksum(final short checksum) {
91 + this.checksum = checksum;
92 + return this;
93 + }
94 +
95 + /**
96 + * Serializes the packet. Will compute and set the following fields if they
97 + * are set to specific values at the time serialize is called: -checksum : 0
98 + * -length : 0
99 + */
100 + @Override
101 + public byte[] serialize() {
102 + int length = 4;
103 + byte[] payloadData = null;
104 + if (this.payload != null) {
105 + this.payload.setParent(this);
106 + payloadData = this.payload.serialize();
107 + length += payloadData.length;
108 + }
109 +
110 + final byte[] data = new byte[length];
111 + final ByteBuffer bb = ByteBuffer.wrap(data);
112 +
113 + bb.put(this.icmpType);
114 + bb.put(this.icmpCode);
115 + bb.putShort(this.checksum);
116 + if (payloadData != null) {
117 + bb.put(payloadData);
118 + }
119 +
120 + if (this.parent != null && this.parent instanceof IPv4) {
121 + ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_ICMP);
122 + }
123 +
124 + // compute checksum if needed
125 + if (this.checksum == 0) {
126 + bb.rewind();
127 + int accumulation = 0;
128 +
129 + for (int i = 0; i < length / 2; ++i) {
130 + accumulation += 0xffff & bb.getShort();
131 + }
132 + // pad to an even number of shorts
133 + if (length % 2 > 0) {
134 + accumulation += (bb.get() & 0xff) << 8;
135 + }
136 +
137 + accumulation = (accumulation >> 16 & 0xffff)
138 + + (accumulation & 0xffff);
139 + this.checksum = (short) (~accumulation & 0xffff);
140 + bb.putShort(2, this.checksum);
141 + }
142 + return data;
143 + }
144 +
145 + /*
146 + * (non-Javadoc)
147 + *
148 + * @see java.lang.Object#hashCode()
149 + */
150 + @Override
151 + public int hashCode() {
152 + final int prime = 5807;
153 + int result = super.hashCode();
154 + result = prime * result + this.icmpType;
155 + result = prime * result + this.icmpCode;
156 + result = prime * result + this.checksum;
157 + return result;
158 + }
159 +
160 + /*
161 + * (non-Javadoc)
162 + *
163 + * @see java.lang.Object#equals(java.lang.Object)
164 + */
165 + @Override
166 + public boolean equals(final Object obj) {
167 + if (this == obj) {
168 + return true;
169 + }
170 + if (!super.equals(obj)) {
171 + return false;
172 + }
173 + if (!(obj instanceof ICMP)) {
174 + return false;
175 + }
176 + final ICMP other = (ICMP) obj;
177 + if (this.icmpType != other.icmpType) {
178 + return false;
179 + }
180 + if (this.icmpCode != other.icmpCode) {
181 + return false;
182 + }
183 + if (this.checksum != other.checksum) {
184 + return false;
185 + }
186 + return true;
187 + }
188 +
189 + @Override
190 + public IPacket deserialize(final byte[] data, final int offset,
191 + final int length) {
192 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
193 + this.icmpType = bb.get();
194 + this.icmpCode = bb.get();
195 + this.checksum = bb.getShort();
196 +
197 + this.payload = new Data();
198 + this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
199 + - bb.position());
200 + this.payload.setParent(this);
201 + return this;
202 + }
203 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +/**
36 + *
37 + * @author David Erickson (daviderickson@cs.stanford.edu)
38 + */
39 +public interface IPacket {
40 + /**
41 + *
42 + * @return
43 + */
44 + public IPacket getPayload();
45 +
46 + /**
47 + *
48 + * @param packet
49 + * @return
50 + */
51 + public IPacket setPayload(IPacket packet);
52 +
53 + /**
54 + *
55 + * @return
56 + */
57 + public IPacket getParent();
58 +
59 + /**
60 + *
61 + * @param packet
62 + * @return
63 + */
64 + public IPacket setParent(IPacket packet);
65 +
66 + /**
67 + * Reset any checksums as needed, and call resetChecksum on all parents.
68 + */
69 + public void resetChecksum();
70 +
71 + /**
72 + * Sets all payloads parent packet if applicable, then serializes this
73 + * packet and all payloads.
74 + *
75 + * @return a byte[] containing this packet and payloads
76 + */
77 + public byte[] serialize();
78 +
79 + /**
80 + * Deserializes this packet layer and all possible payloads.
81 + *
82 + * @param data
83 + * @param offset
84 + * offset to start deserializing from
85 + * @param length
86 + * length of the data to deserialize
87 + * @return the deserialized data
88 + */
89 + public IPacket deserialize(byte[] data, int offset, int length);
90 +
91 + /**
92 + * Clone this packet and its payload packet but not its parent.
93 + *
94 + * @return
95 + */
96 + public Object clone();
97 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +/**
34 + *
35 + */
36 +package org.onlab.packet;
37 +
38 +import java.nio.ByteBuffer;
39 +import java.util.Arrays;
40 +import java.util.Collection;
41 +import java.util.HashMap;
42 +import java.util.Map;
43 +
44 +/**
45 + * @author David Erickson (daviderickson@cs.stanford.edu)
46 + *
47 + */
48 +public class IPv4 extends BasePacket {
49 + public static final byte PROTOCOL_ICMP = 0x1;
50 + public static final byte PROTOCOL_TCP = 0x6;
51 + public static final byte PROTOCOL_UDP = 0x11;
52 + public static Map<Byte, Class<? extends IPacket>> protocolClassMap;
53 +
54 + static {
55 + IPv4.protocolClassMap = new HashMap<Byte, Class<? extends IPacket>>();
56 + IPv4.protocolClassMap.put(IPv4.PROTOCOL_ICMP, ICMP.class);
57 + IPv4.protocolClassMap.put(IPv4.PROTOCOL_TCP, TCP.class);
58 + IPv4.protocolClassMap.put(IPv4.PROTOCOL_UDP, UDP.class);
59 + }
60 +
61 + protected byte version;
62 + protected byte headerLength;
63 + protected byte diffServ;
64 + protected short totalLength;
65 + protected short identification;
66 + protected byte flags;
67 + protected short fragmentOffset;
68 + protected byte ttl;
69 + protected byte protocol;
70 + protected short checksum;
71 + protected int sourceAddress;
72 + protected int destinationAddress;
73 + protected byte[] options;
74 +
75 + protected boolean isTruncated;
76 +
77 + /**
78 + * Default constructor that sets the version to 4.
79 + */
80 + public IPv4() {
81 + super();
82 + this.version = 4;
83 + this.isTruncated = false;
84 + }
85 +
86 + /**
87 + * @return the version
88 + */
89 + public byte getVersion() {
90 + return this.version;
91 + }
92 +
93 + /**
94 + * @param version
95 + * the version to set
96 + */
97 + public IPv4 setVersion(final byte version) {
98 + this.version = version;
99 + return this;
100 + }
101 +
102 + /**
103 + * @return the headerLength
104 + */
105 + public byte getHeaderLength() {
106 + return this.headerLength;
107 + }
108 +
109 + /**
110 + * @return the diffServ
111 + */
112 + public byte getDiffServ() {
113 + return this.diffServ;
114 + }
115 +
116 + /**
117 + * @param diffServ
118 + * the diffServ to set
119 + */
120 + public IPv4 setDiffServ(final byte diffServ) {
121 + this.diffServ = diffServ;
122 + return this;
123 + }
124 +
125 + /**
126 + * @return the totalLength
127 + */
128 + public short getTotalLength() {
129 + return this.totalLength;
130 + }
131 +
132 + /**
133 + * @return the identification
134 + */
135 + public short getIdentification() {
136 + return this.identification;
137 + }
138 +
139 + public boolean isTruncated() {
140 + return this.isTruncated;
141 + }
142 +
143 + public void setTruncated(final boolean isTruncated) {
144 + this.isTruncated = isTruncated;
145 + }
146 +
147 + /**
148 + * @param identification
149 + * the identification to set
150 + */
151 + public IPv4 setIdentification(final short identification) {
152 + this.identification = identification;
153 + return this;
154 + }
155 +
156 + /**
157 + * @return the flags
158 + */
159 + public byte getFlags() {
160 + return this.flags;
161 + }
162 +
163 + /**
164 + * @param flags
165 + * the flags to set
166 + */
167 + public IPv4 setFlags(final byte flags) {
168 + this.flags = flags;
169 + return this;
170 + }
171 +
172 + /**
173 + * @return the fragmentOffset
174 + */
175 + public short getFragmentOffset() {
176 + return this.fragmentOffset;
177 + }
178 +
179 + /**
180 + * @param fragmentOffset
181 + * the fragmentOffset to set
182 + */
183 + public IPv4 setFragmentOffset(final short fragmentOffset) {
184 + this.fragmentOffset = fragmentOffset;
185 + return this;
186 + }
187 +
188 + /**
189 + * @return the ttl
190 + */
191 + public byte getTtl() {
192 + return this.ttl;
193 + }
194 +
195 + /**
196 + * @param ttl
197 + * the ttl to set
198 + */
199 + public IPv4 setTtl(final byte ttl) {
200 + this.ttl = ttl;
201 + return this;
202 + }
203 +
204 + /**
205 + * @return the protocol
206 + */
207 + public byte getProtocol() {
208 + return this.protocol;
209 + }
210 +
211 + /**
212 + * @param protocol
213 + * the protocol to set
214 + */
215 + public IPv4 setProtocol(final byte protocol) {
216 + this.protocol = protocol;
217 + return this;
218 + }
219 +
220 + /**
221 + * @return the checksum
222 + */
223 + public short getChecksum() {
224 + return this.checksum;
225 + }
226 +
227 + /**
228 + * @param checksum
229 + * the checksum to set
230 + */
231 + public IPv4 setChecksum(final short checksum) {
232 + this.checksum = checksum;
233 + return this;
234 + }
235 +
236 + @Override
237 + public void resetChecksum() {
238 + this.checksum = 0;
239 + super.resetChecksum();
240 + }
241 +
242 + /**
243 + * @return the sourceAddress
244 + */
245 + public int getSourceAddress() {
246 + return this.sourceAddress;
247 + }
248 +
249 + /**
250 + * @param sourceAddress
251 + * the sourceAddress to set
252 + */
253 + public IPv4 setSourceAddress(final int sourceAddress) {
254 + this.sourceAddress = sourceAddress;
255 + return this;
256 + }
257 +
258 + /**
259 + * @param sourceAddress
260 + * the sourceAddress to set
261 + */
262 + public IPv4 setSourceAddress(final String sourceAddress) {
263 + this.sourceAddress = IPv4.toIPv4Address(sourceAddress);
264 + return this;
265 + }
266 +
267 + /**
268 + * @return the destinationAddress
269 + */
270 + public int getDestinationAddress() {
271 + return this.destinationAddress;
272 + }
273 +
274 + /**
275 + * @param destinationAddress
276 + * the destinationAddress to set
277 + */
278 + public IPv4 setDestinationAddress(final int destinationAddress) {
279 + this.destinationAddress = destinationAddress;
280 + return this;
281 + }
282 +
283 + /**
284 + * @param destinationAddress
285 + * the destinationAddress to set
286 + */
287 + public IPv4 setDestinationAddress(final String destinationAddress) {
288 + this.destinationAddress = IPv4.toIPv4Address(destinationAddress);
289 + return this;
290 + }
291 +
292 + /**
293 + * @return the options
294 + */
295 + public byte[] getOptions() {
296 + return this.options;
297 + }
298 +
299 + /**
300 + * @param options
301 + * the options to set
302 + */
303 + public IPv4 setOptions(final byte[] options) {
304 + if (options != null && options.length % 4 > 0) {
305 + throw new IllegalArgumentException(
306 + "Options length must be a multiple of 4");
307 + }
308 + this.options = options;
309 + return this;
310 + }
311 +
312 + /**
313 + * Serializes the packet. Will compute and set the following fields if they
314 + * are set to specific values at the time serialize is called: -checksum : 0
315 + * -headerLength : 0 -totalLength : 0
316 + */
317 + @Override
318 + public byte[] serialize() {
319 + byte[] payloadData = null;
320 + if (this.payload != null) {
321 + this.payload.setParent(this);
322 + payloadData = this.payload.serialize();
323 + }
324 +
325 + int optionsLength = 0;
326 + if (this.options != null) {
327 + optionsLength = this.options.length / 4;
328 + }
329 + this.headerLength = (byte) (5 + optionsLength);
330 +
331 + this.totalLength = (short) (this.headerLength * 4 + (payloadData == null ? 0
332 + : payloadData.length));
333 +
334 + final byte[] data = new byte[this.totalLength];
335 + final ByteBuffer bb = ByteBuffer.wrap(data);
336 +
337 + bb.put((byte) ((this.version & 0xf) << 4 | this.headerLength & 0xf));
338 + bb.put(this.diffServ);
339 + bb.putShort(this.totalLength);
340 + bb.putShort(this.identification);
341 + bb.putShort((short) ((this.flags & 0x7) << 13 | this.fragmentOffset & 0x1fff));
342 + bb.put(this.ttl);
343 + bb.put(this.protocol);
344 + bb.putShort(this.checksum);
345 + bb.putInt(this.sourceAddress);
346 + bb.putInt(this.destinationAddress);
347 + if (this.options != null) {
348 + bb.put(this.options);
349 + }
350 + if (payloadData != null) {
351 + bb.put(payloadData);
352 + }
353 +
354 + // compute checksum if needed
355 + if (this.checksum == 0) {
356 + bb.rewind();
357 + int accumulation = 0;
358 + for (int i = 0; i < this.headerLength * 2; ++i) {
359 + accumulation += 0xffff & bb.getShort();
360 + }
361 + accumulation = (accumulation >> 16 & 0xffff)
362 + + (accumulation & 0xffff);
363 + this.checksum = (short) (~accumulation & 0xffff);
364 + bb.putShort(10, this.checksum);
365 + }
366 + return data;
367 + }
368 +
369 + @Override
370 + public IPacket deserialize(final byte[] data, final int offset,
371 + final int length) {
372 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
373 + short sscratch;
374 +
375 + this.version = bb.get();
376 + this.headerLength = (byte) (this.version & 0xf);
377 + this.version = (byte) (this.version >> 4 & 0xf);
378 + this.diffServ = bb.get();
379 + this.totalLength = bb.getShort();
380 + this.identification = bb.getShort();
381 + sscratch = bb.getShort();
382 + this.flags = (byte) (sscratch >> 13 & 0x7);
383 + this.fragmentOffset = (short) (sscratch & 0x1fff);
384 + this.ttl = bb.get();
385 + this.protocol = bb.get();
386 + this.checksum = bb.getShort();
387 + this.sourceAddress = bb.getInt();
388 + this.destinationAddress = bb.getInt();
389 +
390 + if (this.headerLength > 5) {
391 + final int optionsLength = (this.headerLength - 5) * 4;
392 + this.options = new byte[optionsLength];
393 + bb.get(this.options);
394 + }
395 +
396 + IPacket payload;
397 + if (IPv4.protocolClassMap.containsKey(this.protocol)) {
398 + final Class<? extends IPacket> clazz = IPv4.protocolClassMap
399 + .get(this.protocol);
400 + try {
401 + payload = clazz.newInstance();
402 + } catch (final Exception e) {
403 + throw new RuntimeException(
404 + "Error parsing payload for IPv4 packet", e);
405 + }
406 + } else {
407 + payload = new Data();
408 + }
409 + this.payload = payload.deserialize(data, bb.position(),
410 + bb.limit() - bb.position());
411 + this.payload.setParent(this);
412 +
413 + if (this.totalLength != length) {
414 + this.isTruncated = true;
415 + } else {
416 + this.isTruncated = false;
417 + }
418 +
419 + return this;
420 + }
421 +
422 + /**
423 + * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
424 + * returns the corresponding 32 bit integer.
425 + *
426 + * @param ipAddress
427 + * @return
428 + */
429 + public static int toIPv4Address(final String ipAddress) {
430 + if (ipAddress == null) {
431 + throw new IllegalArgumentException("Specified IPv4 address must"
432 + + "contain 4 sets of numerical digits separated by periods");
433 + }
434 + final String[] octets = ipAddress.split("\\.");
435 + if (octets.length != 4) {
436 + throw new IllegalArgumentException("Specified IPv4 address must"
437 + + "contain 4 sets of numerical digits separated by periods");
438 + }
439 +
440 + int result = 0;
441 + for (int i = 0; i < 4; ++i) {
442 + result |= Integer.valueOf(octets[i]) << (3 - i) * 8;
443 + }
444 + return result;
445 + }
446 +
447 + /**
448 + * Accepts an IPv4 address in a byte array and returns the corresponding
449 + * 32-bit integer value.
450 + *
451 + * @param ipAddress
452 + * @return
453 + */
454 + public static int toIPv4Address(final byte[] ipAddress) {
455 + int ip = 0;
456 + for (int i = 0; i < 4; i++) {
457 + final int t = (ipAddress[i] & 0xff) << (3 - i) * 8;
458 + ip |= t;
459 + }
460 + return ip;
461 + }
462 +
463 + /**
464 + * Accepts an IPv4 address and returns of string of the form xxx.xxx.xxx.xxx,
465 + * e.g., 192.168.0.1.
466 + *
467 + * @param ipAddress
468 + * @return
469 + */
470 + public static String fromIPv4Address(final int ipAddress) {
471 + final StringBuffer sb = new StringBuffer();
472 + int result = 0;
473 + for (int i = 0; i < 4; ++i) {
474 + result = ipAddress >> (3 - i) * 8 & 0xff;
475 + sb.append(Integer.valueOf(result).toString());
476 + if (i != 3) {
477 + sb.append(".");
478 + }
479 + }
480 + return sb.toString();
481 + }
482 +
483 + /**
484 + * Accepts a collection of IPv4 addresses as integers and returns a single
485 + * String useful in toString method's containing collections of IP
486 + * addresses.
487 + *
488 + * @param ipAddresses
489 + * collection
490 + * @return
491 + */
492 + public static String fromIPv4AddressCollection(
493 + final Collection<Integer> ipAddresses) {
494 + if (ipAddresses == null) {
495 + return "null";
496 + }
497 + final StringBuffer sb = new StringBuffer();
498 + sb.append("[");
499 + for (final Integer ip : ipAddresses) {
500 + sb.append(IPv4.fromIPv4Address(ip));
501 + sb.append(",");
502 + }
503 + sb.replace(sb.length() - 1, sb.length(), "]");
504 + return sb.toString();
505 + }
506 +
507 + /**
508 + * Accepts an IPv4 address of the form xxx.xxx.xxx.xxx, ie 192.168.0.1 and
509 + * returns the corresponding byte array.
510 + *
511 + * @param ipAddress
512 + * The IP address in the form xx.xxx.xxx.xxx.
513 + * @return The IP address separated into bytes
514 + */
515 + public static byte[] toIPv4AddressBytes(final String ipAddress) {
516 + final String[] octets = ipAddress.split("\\.");
517 + if (octets.length != 4) {
518 + throw new IllegalArgumentException("Specified IPv4 address must"
519 + + "contain 4 sets of numerical digits separated by periods");
520 + }
521 +
522 + final byte[] result = new byte[4];
523 + for (int i = 0; i < 4; ++i) {
524 + result[i] = Integer.valueOf(octets[i]).byteValue();
525 + }
526 + return result;
527 + }
528 +
529 + /**
530 + * Accepts an IPv4 address in the form of an integer and returns the
531 + * corresponding byte array.
532 + *
533 + * @param ipAddress
534 + * The IP address as an integer.
535 + * @return The IP address separated into bytes.
536 + */
537 + public static byte[] toIPv4AddressBytes(final int ipAddress) {
538 + return new byte[] {(byte) (ipAddress >>> 24),
539 + (byte) (ipAddress >>> 16), (byte) (ipAddress >>> 8),
540 + (byte) ipAddress};
541 + }
542 +
543 + /*
544 + * (non-Javadoc)
545 + *
546 + * @see java.lang.Object#hashCode()
547 + */
548 + @Override
549 + public int hashCode() {
550 + final int prime = 2521;
551 + int result = super.hashCode();
552 + result = prime * result + this.checksum;
553 + result = prime * result + this.destinationAddress;
554 + result = prime * result + this.diffServ;
555 + result = prime * result + this.flags;
556 + result = prime * result + this.fragmentOffset;
557 + result = prime * result + this.headerLength;
558 + result = prime * result + this.identification;
559 + result = prime * result + Arrays.hashCode(this.options);
560 + result = prime * result + this.protocol;
561 + result = prime * result + this.sourceAddress;
562 + result = prime * result + this.totalLength;
563 + result = prime * result + this.ttl;
564 + result = prime * result + this.version;
565 + return result;
566 + }
567 +
568 + /*
569 + * (non-Javadoc)
570 + *
571 + * @see java.lang.Object#equals(java.lang.Object)
572 + */
573 + @Override
574 + public boolean equals(final Object obj) {
575 + if (this == obj) {
576 + return true;
577 + }
578 + if (!super.equals(obj)) {
579 + return false;
580 + }
581 + if (!(obj instanceof IPv4)) {
582 + return false;
583 + }
584 + final IPv4 other = (IPv4) obj;
585 + if (this.checksum != other.checksum) {
586 + return false;
587 + }
588 + if (this.destinationAddress != other.destinationAddress) {
589 + return false;
590 + }
591 + if (this.diffServ != other.diffServ) {
592 + return false;
593 + }
594 + if (this.flags != other.flags) {
595 + return false;
596 + }
597 + if (this.fragmentOffset != other.fragmentOffset) {
598 + return false;
599 + }
600 + if (this.headerLength != other.headerLength) {
601 + return false;
602 + }
603 + if (this.identification != other.identification) {
604 + return false;
605 + }
606 + if (!Arrays.equals(this.options, other.options)) {
607 + return false;
608 + }
609 + if (this.protocol != other.protocol) {
610 + return false;
611 + }
612 + if (this.sourceAddress != other.sourceAddress) {
613 + return false;
614 + }
615 + if (this.totalLength != other.totalLength) {
616 + return false;
617 + }
618 + if (this.ttl != other.ttl) {
619 + return false;
620 + }
621 + if (this.version != other.version) {
622 + return false;
623 + }
624 + return true;
625 + }
626 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.nio.ByteBuffer;
36 +
37 +/**
38 + * This class represents an Link Local Control header that is used in Ethernet
39 + * 802.3.
40 + *
41 + * @author alexreimers
42 + *
43 + */
44 +public class LLC extends BasePacket {
45 + private byte dsap = 0;
46 + private byte ssap = 0;
47 + private byte ctrl = 0;
48 +
49 + public byte getDsap() {
50 + return this.dsap;
51 + }
52 +
53 + public void setDsap(final byte dsap) {
54 + this.dsap = dsap;
55 + }
56 +
57 + public byte getSsap() {
58 + return this.ssap;
59 + }
60 +
61 + public void setSsap(final byte ssap) {
62 + this.ssap = ssap;
63 + }
64 +
65 + public byte getCtrl() {
66 + return this.ctrl;
67 + }
68 +
69 + public void setCtrl(final byte ctrl) {
70 + this.ctrl = ctrl;
71 + }
72 +
73 + @Override
74 + public byte[] serialize() {
75 + final byte[] data = new byte[3];
76 + final ByteBuffer bb = ByteBuffer.wrap(data);
77 + bb.put(this.dsap);
78 + bb.put(this.ssap);
79 + bb.put(this.ctrl);
80 + return data;
81 + }
82 +
83 + @Override
84 + public IPacket deserialize(final byte[] data, final int offset,
85 + final int length) {
86 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
87 + this.dsap = bb.get();
88 + this.ssap = bb.get();
89 + this.ctrl = bb.get();
90 + return this;
91 + }
92 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +/**
34 + *
35 + */
36 +package org.onlab.packet;
37 +
38 +import java.nio.ByteBuffer;
39 +import java.util.ArrayList;
40 +import java.util.List;
41 +
42 +/**
43 + * @author David Erickson (daviderickson@cs.stanford.edu)
44 + *
45 + */
46 +public class LLDP extends BasePacket {
47 + protected LLDPTLV chassisId;
48 + protected LLDPTLV portId;
49 + protected LLDPTLV ttl;
50 + protected List<LLDPTLV> optionalTLVList;
51 + protected short ethType;
52 +
53 + public LLDP() {
54 + this.optionalTLVList = new ArrayList<LLDPTLV>();
55 + this.ethType = Ethernet.TYPE_LLDP;
56 + }
57 +
58 + /**
59 + * @return the chassisId
60 + */
61 + public LLDPTLV getChassisId() {
62 + return this.chassisId;
63 + }
64 +
65 + /**
66 + * @param chassisId
67 + * the chassisId to set
68 + */
69 + public LLDP setChassisId(final LLDPTLV chassis) {
70 + this.chassisId = chassis;
71 + return this;
72 + }
73 +
74 + /**
75 + * @return the portId
76 + */
77 + public LLDPTLV getPortId() {
78 + return this.portId;
79 + }
80 +
81 + /**
82 + * @param portId
83 + * the portId to set
84 + */
85 + public LLDP setPortId(final LLDPTLV portId) {
86 + this.portId = portId;
87 + return this;
88 + }
89 +
90 + /**
91 + * @return the ttl
92 + */
93 + public LLDPTLV getTtl() {
94 + return this.ttl;
95 + }
96 +
97 + /**
98 + * @param ttl
99 + * the ttl to set
100 + */
101 + public LLDP setTtl(final LLDPTLV ttl) {
102 + this.ttl = ttl;
103 + return this;
104 + }
105 +
106 + /**
107 + * @return the optionalTLVList
108 + */
109 + public List<LLDPTLV> getOptionalTLVList() {
110 + return this.optionalTLVList;
111 + }
112 +
113 + /**
114 + * @param optionalTLVList
115 + * the optionalTLVList to set
116 + */
117 + public LLDP setOptionalTLVList(final List<LLDPTLV> optionalTLVList) {
118 + this.optionalTLVList = optionalTLVList;
119 + return this;
120 + }
121 +
122 + @Override
123 + public byte[] serialize() {
124 + int length = 2 + this.chassisId.getLength() + 2
125 + + this.portId.getLength() + 2 + this.ttl.getLength() + 2;
126 + for (final LLDPTLV tlv : this.optionalTLVList) {
127 + length += 2 + tlv.getLength();
128 + }
129 +
130 + final byte[] data = new byte[length];
131 + final ByteBuffer bb = ByteBuffer.wrap(data);
132 + bb.put(this.chassisId.serialize());
133 + bb.put(this.portId.serialize());
134 + bb.put(this.ttl.serialize());
135 + for (final LLDPTLV tlv : this.optionalTLVList) {
136 + bb.put(tlv.serialize());
137 + }
138 + bb.putShort((short) 0); // End of LLDPDU
139 +
140 + /*
141 + * if (this.parent != null && this.parent instanceof Ethernet) {
142 + * ((Ethernet) this.parent).setEtherType(this.ethType); }
143 + */
144 +
145 + return data;
146 + }
147 +
148 + @Override
149 + public IPacket deserialize(final byte[] data, final int offset,
150 + final int length) {
151 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
152 + LLDPTLV tlv;
153 + do {
154 + tlv = new LLDPTLV().deserialize(bb);
155 +
156 + // if there was a failure to deserialize stop processing TLVs
157 + if (tlv == null) {
158 + break;
159 + }
160 + switch (tlv.getType()) {
161 + case 0x0:
162 + // can throw this one away, its just an end delimiter
163 + break;
164 + case 0x1:
165 + this.chassisId = tlv;
166 + break;
167 + case 0x2:
168 + this.portId = tlv;
169 + break;
170 + case 0x3:
171 + this.ttl = tlv;
172 + break;
173 + default:
174 + this.optionalTLVList.add(tlv);
175 + break;
176 + }
177 + } while (tlv.getType() != 0 && bb.hasRemaining());
178 + return this;
179 + }
180 +
181 + /*
182 + * (non-Javadoc)
183 + *
184 + * @see java.lang.Object#hashCode()
185 + */
186 + @Override
187 + public int hashCode() {
188 + final int prime = 883;
189 + int result = super.hashCode();
190 + result = prime * result
191 + + (this.chassisId == null ? 0 : this.chassisId.hashCode());
192 + result = prime * result + this.optionalTLVList.hashCode();
193 + result = prime * result
194 + + (this.portId == null ? 0 : this.portId.hashCode());
195 + result = prime * result + (this.ttl == null ? 0 : this.ttl.hashCode());
196 + return result;
197 + }
198 +
199 + /*
200 + * (non-Javadoc)
201 + *
202 + * @see java.lang.Object#equals(java.lang.Object)
203 + */
204 + @Override
205 + public boolean equals(final Object obj) {
206 + if (this == obj) {
207 + return true;
208 + }
209 + if (!super.equals(obj)) {
210 + return false;
211 + }
212 + if (!(obj instanceof LLDP)) {
213 + return false;
214 + }
215 + final LLDP other = (LLDP) obj;
216 + if (this.chassisId == null) {
217 + if (other.chassisId != null) {
218 + return false;
219 + }
220 + } else if (!this.chassisId.equals(other.chassisId)) {
221 + return false;
222 + }
223 + if (!this.optionalTLVList.equals(other.optionalTLVList)) {
224 + return false;
225 + }
226 + if (this.portId == null) {
227 + if (other.portId != null) {
228 + return false;
229 + }
230 + } else if (!this.portId.equals(other.portId)) {
231 + return false;
232 + }
233 + if (this.ttl == null) {
234 + if (other.ttl != null) {
235 + return false;
236 + }
237 + } else if (!this.ttl.equals(other.ttl)) {
238 + return false;
239 + }
240 + return true;
241 + }
242 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
18 + * not use this file except in compliance with the License. You may obtain
19 + * a copy of the License at
20 + *
21 + * http://www.apache.org/licenses/LICENSE-2.0
22 + *
23 + * Unless required by applicable law or agreed to in writing, software
24 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
25 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26 + * License for the specific language governing permissions and limitations
27 + * under the License.
28 + **/
29 +
30 +package org.onlab.packet;
31 +
32 +import java.nio.ByteBuffer;
33 +import java.nio.charset.Charset;
34 +import java.util.Arrays;
35 +
36 +/**
37 + * The class representing LLDP Organizationally Specific TLV.
38 + *
39 + * @author Sho Shimizu (sho.shimizu@gmail.com)
40 + */
41 +public class LLDPOrganizationalTLV extends LLDPTLV {
42 + public static final int OUI_LENGTH = 3;
43 + public static final int SUBTYPE_LENGTH = 1;
44 + public static final byte ORGANIZATIONAL_TLV_TYPE = 127;
45 + public static final int MAX_INFOSTRING_LENGTH = 507;
46 +
47 + protected byte[] oui;
48 + protected byte subType;
49 + private byte[] infoString;
50 +
51 + public LLDPOrganizationalTLV() {
52 + this.type = LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE;
53 + }
54 +
55 + /**
56 + * Set the value of OUI.
57 + *
58 + * @param oui
59 + * The value of OUI to be set.
60 + * @return This LLDP Organizationally Specific TLV.
61 + */
62 + public LLDPOrganizationalTLV setOUI(final byte[] oui) {
63 + if (oui.length != LLDPOrganizationalTLV.OUI_LENGTH) {
64 + throw new IllegalArgumentException("The length of OUI must be "
65 + + LLDPOrganizationalTLV.OUI_LENGTH + ", but it is "
66 + + oui.length);
67 + }
68 + this.oui = Arrays.copyOf(oui, oui.length);
69 + return this;
70 + }
71 +
72 + /**
73 + * Returns the value of the OUI.
74 + *
75 + * @return The value of the OUI .
76 + */
77 + public byte[] getOUI() {
78 + return Arrays.copyOf(this.oui, this.oui.length);
79 + }
80 +
81 + /**
82 + * Set the value of sub type.
83 + *
84 + * @param subType
85 + * The value of sub type to be set.
86 + * @return This LLDP Organizationally Specific TLV.
87 + */
88 + public LLDPOrganizationalTLV setSubType(final byte subType) {
89 + this.subType = subType;
90 + return this;
91 + }
92 +
93 + /**
94 + * Returns the value of the sub type.
95 + *
96 + * @return The value of the sub type.
97 + */
98 + public byte getSubType() {
99 + return this.subType;
100 + }
101 +
102 + /**
103 + * Set the value of information string.
104 + *
105 + * @param infoString
106 + * the byte array of the value of information string.
107 + * @return This LLDP Organizationally Specific TLV.
108 + */
109 + public LLDPOrganizationalTLV setInfoString(final byte[] infoString) {
110 + if (infoString.length > LLDPOrganizationalTLV.MAX_INFOSTRING_LENGTH) {
111 + throw new IllegalArgumentException(
112 + "The length of infoString cannot exceed "
113 + + LLDPOrganizationalTLV.MAX_INFOSTRING_LENGTH);
114 + }
115 + this.infoString = Arrays.copyOf(infoString, infoString.length);
116 + return this;
117 + }
118 +
119 + /**
120 + * Set the value of information string. The String value is automatically
121 + * converted into byte array with UTF-8 encoding.
122 + *
123 + * @param infoString
124 + * the String value of information string.
125 + * @return This LLDP Organizationally Specific TLV.
126 + */
127 + public LLDPOrganizationalTLV setInfoString(final String infoString) {
128 + final byte[] infoStringBytes = infoString.getBytes(Charset
129 + .forName("UTF-8"));
130 + return this.setInfoString(infoStringBytes);
131 + }
132 +
133 + /**
134 + * Returns the value of information string.
135 + *
136 + * @return the value of information string.
137 + */
138 + public byte[] getInfoString() {
139 + return Arrays.copyOf(this.infoString, this.infoString.length);
140 + }
141 +
142 + @Override
143 + public byte[] serialize() {
144 + final int valueLength = LLDPOrganizationalTLV.OUI_LENGTH
145 + + LLDPOrganizationalTLV.SUBTYPE_LENGTH + this.infoString.length;
146 + this.value = new byte[valueLength];
147 + final ByteBuffer bb = ByteBuffer.wrap(this.value);
148 + bb.put(this.oui);
149 + bb.put(this.subType);
150 + bb.put(this.infoString);
151 + return super.serialize();
152 + }
153 +
154 + @Override
155 + public LLDPTLV deserialize(final ByteBuffer bb) {
156 + super.deserialize(bb);
157 + final ByteBuffer optionalField = ByteBuffer.wrap(this.value);
158 +
159 + final byte[] oui = new byte[LLDPOrganizationalTLV.OUI_LENGTH];
160 + optionalField.get(oui);
161 + this.setOUI(oui);
162 +
163 + this.setSubType(optionalField.get());
164 +
165 + final byte[] infoString = new byte[this.getLength()
166 + - LLDPOrganizationalTLV.OUI_LENGTH
167 + - LLDPOrganizationalTLV.SUBTYPE_LENGTH];
168 + optionalField.get(infoString);
169 + this.setInfoString(infoString);
170 + return this;
171 + }
172 +
173 + @Override
174 + public int hashCode() {
175 + final int prime = 1423;
176 + int result = 1;
177 + result = prime * result + this.type;
178 + result = prime * result + this.length;
179 + result = prime * result + Arrays.hashCode(this.oui);
180 + result = prime * result + this.subType;
181 + result = prime * result + Arrays.hashCode(this.infoString);
182 + return result;
183 + }
184 +
185 + @Override
186 + public boolean equals(final Object o) {
187 + if (o == this) {
188 + return true;
189 + }
190 +
191 + if (!(o instanceof LLDPOrganizationalTLV)) {
192 + return false;
193 + }
194 +
195 + final LLDPOrganizationalTLV other = (LLDPOrganizationalTLV) o;
196 + if (this.type != other.type) {
197 + return false;
198 + }
199 + if (this.length != other.length) {
200 + return false;
201 + }
202 + if (!Arrays.equals(this.oui, other.oui)) {
203 + return false;
204 + }
205 + if (this.subType != other.subType) {
206 + return false;
207 + }
208 + if (!Arrays.equals(this.infoString, other.infoString)) {
209 + return false;
210 + }
211 +
212 + return true;
213 + }
214 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.nio.ByteBuffer;
36 +import java.util.Arrays;
37 +
38 +/**
39 + *
40 + *
41 + * @author David Erickson (daviderickson@cs.stanford.edu)
42 + */
43 +public class LLDPTLV {
44 + protected byte type;
45 + protected short length;
46 + protected byte[] value;
47 +
48 + /**
49 + * @return the type
50 + */
51 + public byte getType() {
52 + return this.type;
53 + }
54 +
55 + /**
56 + * @param type
57 + * the type to set
58 + */
59 + public LLDPTLV setType(final byte type) {
60 + this.type = type;
61 + return this;
62 + }
63 +
64 + /**
65 + * @return the length
66 + */
67 + public short getLength() {
68 + return this.length;
69 + }
70 +
71 + /**
72 + * @param length
73 + * the length to set
74 + */
75 + public LLDPTLV setLength(final short length) {
76 + this.length = length;
77 + return this;
78 + }
79 +
80 + /**
81 + * @return the value
82 + */
83 + public byte[] getValue() {
84 + return this.value;
85 + }
86 +
87 + /**
88 + * @param value
89 + * the value to set
90 + */
91 + public LLDPTLV setValue(final byte[] value) {
92 + this.value = value;
93 + return this;
94 + }
95 +
96 + public byte[] serialize() {
97 + // type = 7 bits
98 + // info string length 9 bits, each value == byte
99 + // info string
100 + final short scratch = (short) ((0x7f & this.type) << 9 | 0x1ff & this.length);
101 + final byte[] data = new byte[2 + this.length];
102 + final ByteBuffer bb = ByteBuffer.wrap(data);
103 + bb.putShort(scratch);
104 + if (this.value != null) {
105 + bb.put(this.value);
106 + }
107 + return data;
108 + }
109 +
110 + public LLDPTLV deserialize(final ByteBuffer bb) {
111 + short sscratch;
112 + sscratch = bb.getShort();
113 + this.type = (byte) (sscratch >> 9 & 0x7f);
114 + this.length = (short) (sscratch & 0x1ff);
115 + if (this.length > 0) {
116 + this.value = new byte[this.length];
117 +
118 + // if there is an underrun just toss the TLV
119 + if (bb.remaining() < this.length) {
120 + return null;
121 + }
122 + bb.get(this.value);
123 + }
124 + return this;
125 + }
126 +
127 + /*
128 + * (non-Javadoc)
129 + *
130 + * @see java.lang.Object#hashCode()
131 + */
132 + @Override
133 + public int hashCode() {
134 + final int prime = 1423;
135 + int result = 1;
136 + result = prime * result + this.length;
137 + result = prime * result + this.type;
138 + result = prime * result + Arrays.hashCode(this.value);
139 + return result;
140 + }
141 +
142 + /*
143 + * (non-Javadoc)
144 + *
145 + * @see java.lang.Object#equals(java.lang.Object)
146 + */
147 + @Override
148 + public boolean equals(final Object obj) {
149 + if (this == obj) {
150 + return true;
151 + }
152 + if (obj == null) {
153 + return false;
154 + }
155 + if (!(obj instanceof LLDPTLV)) {
156 + return false;
157 + }
158 + final LLDPTLV other = (LLDPTLV) obj;
159 + if (this.length != other.length) {
160 + return false;
161 + }
162 + if (this.type != other.type) {
163 + return false;
164 + }
165 + if (!Arrays.equals(this.value, other.value)) {
166 + return false;
167 + }
168 + return true;
169 + }
170 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +package org.onlab.packet;
17 +
18 +import java.util.Arrays;
19 +
20 +/**
21 + * The class representing MAC address.
22 + *
23 + * @author Sho Shimizu (sho.shimizu@gmail.com)
24 + */
25 +public class MACAddress {
26 + public static final int MAC_ADDRESS_LENGTH = 6;
27 + private byte[] address = new byte[MACAddress.MAC_ADDRESS_LENGTH];
28 +
29 + public MACAddress(final byte[] address) {
30 + this.address = Arrays.copyOf(address, MACAddress.MAC_ADDRESS_LENGTH);
31 + }
32 +
33 + /**
34 + * Returns a MAC address instance representing the value of the specified
35 + * {@code String}.
36 + *
37 + * @param address
38 + * the String representation of the MAC Address to be parsed.
39 + * @return a MAC Address instance representing the value of the specified
40 + * {@code String}.
41 + * @throws IllegalArgumentException
42 + * if the string cannot be parsed as a MAC address.
43 + */
44 + public static MACAddress valueOf(final String address) {
45 + final String[] elements = address.split(":");
46 + if (elements.length != MACAddress.MAC_ADDRESS_LENGTH) {
47 + throw new IllegalArgumentException(
48 + "Specified MAC Address must contain 12 hex digits"
49 + + " separated pairwise by :'s.");
50 + }
51 +
52 + final byte[] addressInBytes = new byte[MACAddress.MAC_ADDRESS_LENGTH];
53 + for (int i = 0; i < MACAddress.MAC_ADDRESS_LENGTH; i++) {
54 + final String element = elements[i];
55 + addressInBytes[i] = (byte) Integer.parseInt(element, 16);
56 + }
57 +
58 + return new MACAddress(addressInBytes);
59 + }
60 +
61 + /**
62 + * Returns a MAC address instance representing the specified {@code byte}
63 + * array.
64 + *
65 + * @param address
66 + * the byte array to be parsed.
67 + * @return a MAC address instance representing the specified {@code byte}
68 + * array.
69 + * @throws IllegalArgumentException
70 + * if the byte array cannot be parsed as a MAC address.
71 + */
72 + public static MACAddress valueOf(final byte[] address) {
73 + if (address.length != MACAddress.MAC_ADDRESS_LENGTH) {
74 + throw new IllegalArgumentException("the length is not "
75 + + MACAddress.MAC_ADDRESS_LENGTH);
76 + }
77 +
78 + return new MACAddress(address);
79 + }
80 +
81 + /**
82 + * Returns a MAC address instance representing the specified {@code long}
83 + * value. The lower 48 bits of the long value are used to parse as a MAC
84 + * address.
85 + *
86 + * @param address
87 + * the long value to be parsed. The lower 48 bits are used for a
88 + * MAC address.
89 + * @return a MAC address instance representing the specified {@code long}
90 + * value.
91 + * @throws IllegalArgumentException
92 + * if the long value cannot be parsed as a MAC address.
93 + */
94 + public static MACAddress valueOf(final long address) {
95 + final byte[] addressInBytes = new byte[] {
96 + (byte) (address >> 40 & 0xff), (byte) (address >> 32 & 0xff),
97 + (byte) (address >> 24 & 0xff), (byte) (address >> 16 & 0xff),
98 + (byte) (address >> 8 & 0xff), (byte) (address >> 0 & 0xff) };
99 +
100 + return new MACAddress(addressInBytes);
101 + }
102 +
103 + /**
104 + * Returns the length of the {@code MACAddress}.
105 + *
106 + * @return the length of the {@code MACAddress}.
107 + */
108 + public int length() {
109 + return this.address.length;
110 + }
111 +
112 + /**
113 + * Returns the value of the {@code MACAddress} as a {@code byte} array.
114 + *
115 + * @return the numeric value represented by this object after conversion to
116 + * type {@code byte} array.
117 + */
118 + public byte[] toBytes() {
119 + return Arrays.copyOf(this.address, this.address.length);
120 + }
121 +
122 + /**
123 + * Returns the value of the {@code MACAddress} as a {@code long}.
124 + *
125 + * @return the numeric value represented by this object after conversion to
126 + * type {@code long}.
127 + */
128 + public long toLong() {
129 + long mac = 0;
130 + for (int i = 0; i < 6; i++) {
131 + final long t = (this.address[i] & 0xffL) << (5 - i) * 8;
132 + mac |= t;
133 + }
134 + return mac;
135 + }
136 +
137 + /**
138 + * Returns {@code true} if the MAC address is the broadcast address.
139 + *
140 + * @return {@code true} if the MAC address is the broadcast address.
141 + */
142 + public boolean isBroadcast() {
143 + for (final byte b : this.address) {
144 + if (b != -1) {
145 + return false;
146 + }
147 + }
148 + return true;
149 + }
150 +
151 + /**
152 + * Returns {@code true} if the MAC address is the multicast address.
153 + *
154 + * @return {@code true} if the MAC address is the multicast address.
155 + */
156 + public boolean isMulticast() {
157 + if (this.isBroadcast()) {
158 + return false;
159 + }
160 + return (this.address[0] & 0x01) != 0;
161 + }
162 +
163 + @Override
164 + public boolean equals(final Object o) {
165 + if (o == this) {
166 + return true;
167 + }
168 +
169 + if (!(o instanceof MACAddress)) {
170 + return false;
171 + }
172 +
173 + final MACAddress other = (MACAddress) o;
174 + return Arrays.equals(this.address, other.address);
175 + }
176 +
177 + @Override
178 + public int hashCode() {
179 + return Arrays.hashCode(this.address);
180 + }
181 +
182 + @Override
183 + public String toString() {
184 + final StringBuilder builder = new StringBuilder();
185 + for (final byte b : this.address) {
186 + if (builder.length() > 0) {
187 + builder.append(":");
188 + }
189 + builder.append(String.format("%02X", b & 0xFF));
190 + }
191 + return builder.toString();
192 + }
193 +
194 + /**
195 + * @return MAC address in string representation without colons (useful for
196 + * radix tree storage)
197 + */
198 + public String toStringNoColon() {
199 + final StringBuilder builder = new StringBuilder();
200 + for (final byte b : this.address) {
201 + builder.append(String.format("%02X", b & 0xFF));
202 + }
203 + return builder.toString();
204 + }
205 +
206 + public byte[] getAddress() {
207 + return this.address;
208 + }
209 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +package org.onlab.packet;
17 +
18 +import java.nio.ByteBuffer;
19 +import java.util.Arrays;
20 +import java.util.LinkedList;
21 +import java.util.List;
22 +
23 +import org.apache.commons.lang.ArrayUtils;
24 +
25 +
26 +/**
27 + * LLDP packets OpenVirteX uses for discovery of physical network topology.
28 + * Refer to IEEE Std 802.1ABTM-2009 for more information.
29 + *
30 + */
31 +@SuppressWarnings("rawtypes")
32 +public class OVXLLDP extends LLDP {
33 +
34 + // ON.Lab OUI and OVX name for organizationally specific TLVs
35 + public static final byte[] ONLAB_OUI = {(byte) 0xa4, 0x23, 0x05};
36 + public static final String OVX_NAME = "OpenVirteX";
37 + public static final byte[] LLDP_NICIRA = {0x01, 0x23, 0x20, 0x00, 0x00,
38 + 0x01};
39 + public static final byte[] LLDP_MULTICAST = {0x01, (byte) 0x80,
40 + (byte) 0xc2, 0x00, 0x00, 0x0e};
41 + public static final byte[] BDDP_MULTICAST = {(byte) 0xff, (byte) 0xff,
42 + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
43 + public static final short ETHERTYPE_VLAN = (short) 0x8100;
44 +
45 + // TLV constants: type, size and subtype
46 + // Organizationally specific TLV also have packet offset and contents of TLV
47 + // header
48 + private static final byte CHASSIS_TLV_TYPE = 1;
49 + private static final byte CHASSIS_TLV_SIZE = 7;
50 + private static final byte CHASSIS_TLV_SUBTYPE = 4;
51 +
52 + private static final byte PORT_TLV_TYPE = 2;
53 + private static final byte PORT_TLV_SIZE = 7;
54 + private static final byte PORT_TLV_SUBTYPE = 2;
55 +
56 + private static final byte TTL_TLV_TYPE = 3;
57 + private static final byte TTL_TLV_SIZE = 2;
58 +
59 + private static final byte NAME_TLV_TYPE = 127;
60 + // 4 = OUI (3) + subtype (1)
61 + private static final byte NAME_TLV_SIZE = (byte) (4 + OVXLLDP.OVX_NAME.length());
62 + private static final byte NAME_TLV_SUBTYPE = 1;
63 + private static final short NAME_TLV_OFFSET = 32;
64 + private static final short NAME_TLV_HEADER = (short) ((NAME_TLV_TYPE << 9) | NAME_TLV_SIZE);
65 + // Contents of full name TLV
66 + private static final byte[] NAME_TLV = ByteBuffer.allocate(NAME_TLV_SIZE + 2)
67 + .putShort(NAME_TLV_HEADER).put(ONLAB_OUI).put(NAME_TLV_SUBTYPE)
68 + .put(OVX_NAME.getBytes()).array();
69 +
70 + private static final byte DPID_TLV_TYPE = 127;
71 + private static final byte DPID_TLV_SIZE = (byte) (12); // 12 = OUI (3) + subtype
72 + // (1) + dpid (8)
73 + private static final byte DPID_TLV_SUBTYPE = 2;
74 + private static final short DPID_TLV_HEADER = (short) ((DPID_TLV_TYPE << 9) | DPID_TLV_SIZE);
75 + // Contents of dpid TLV
76 + // Note that this does *not* contain the actual dpid since we cannot match
77 + // on it
78 + private static final byte[] DPID_TLV = ByteBuffer.allocate(DPID_TLV_SIZE + 2 - 8)
79 + .putShort(DPID_TLV_HEADER).put(ONLAB_OUI).put(DPID_TLV_SUBTYPE)
80 + .array();
81 +
82 + // Pre-built contents of both organizationally specific TLVs
83 + private static final byte[] OUI_TLV = ArrayUtils.addAll(NAME_TLV, DPID_TLV);
84 +
85 + // Default switch, port number and TTL
86 + private static final byte[] DEFAULT_DPID = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 + 0x00, 0x00 };
88 + private static final short DEFAULT_PORT = 0;
89 + private static final short DEFAULT_TTL = 120; // in seconds
90 +
91 + // Minimum and OVX-generated LLDP packet sizes
92 + private static final short MINIMUM_LLDP_SIZE = 61;
93 + // Add 12 for 2-byte header of each TLV and a single EndOfLLDPTLV
94 + private static final short OVX_LLDP_SIZE = (short) (CHASSIS_TLV_SIZE
95 + + PORT_TLV_SIZE + TTL_TLV_SIZE + NAME_TLV_SIZE + DPID_TLV_SIZE + 12);
96 +
97 + // Field offsets in OVX-generated LLDP
98 + private static final short ETHERTYPE_OFFSET = 12;
99 + private static final short PORT_OFFSET = 26;
100 + private static final short DPID_OFFSET = 54;
101 +
102 + // Private member fields
103 + // Byte arrays for TLV information string
104 + private ByteBuffer bb;
105 + private final byte[] chassisId = new byte[CHASSIS_TLV_SIZE];
106 + private final byte[] portId = new byte[PORT_TLV_SIZE];
107 + private final byte[] ttl = new byte[TTL_TLV_SIZE];
108 + private final byte[] ouiName = new byte[NAME_TLV_SIZE];
109 + private final byte[] ouiDpid = new byte[DPID_TLV_SIZE];
110 +
111 + // TLVs
112 + private final LLDPTLV chassisTLV;
113 + private final LLDPTLV portTLV;
114 + private final LLDPTLV ttlTLV;
115 + private final LLDPTLV ouiNameTLV;
116 + private final LLDPTLV ouiDpidTLV;
117 + private final List<LLDPTLV> optionalTLVList;
118 +
119 + /**
120 + * Instantiates a new OVX LDDP message.
121 + */
122 + public OVXLLDP() {
123 + // Create TLVs
124 + this.chassisTLV = new LLDPTLV();
125 + this.portTLV = new LLDPTLV();
126 + this.ttlTLV = new LLDPTLV();
127 + this.ouiNameTLV = new LLDPTLV();
128 + this.ouiDpidTLV = new LLDPTLV();
129 + this.optionalTLVList = new LinkedList<LLDPTLV>();
130 + this.optionalTLVList.add(this.ouiNameTLV);
131 + this.optionalTLVList.add(this.ouiDpidTLV);
132 +
133 + // Add TLVs to LLDP packet
134 + this.setChassisId(this.chassisTLV);
135 + this.setPortId(this.portTLV);
136 + this.setTtl(this.ttlTLV);
137 + this.setOptionalTLVList(this.optionalTLVList);
138 +
139 + // Set TLVs to default values
140 + this.setChassisTLV(DEFAULT_DPID);
141 + this.setPortTLV(DEFAULT_PORT);
142 + this.setTTLTLV(DEFAULT_TTL);
143 + this.setOUIName(OVXLLDP.OVX_NAME);
144 + this.setOUIDpid(DEFAULT_DPID);
145 + }
146 +
147 + /**
148 + * Sets chassis TLV. Note that we can only put 6 bytes in the chassis ID, so
149 + * we use another organizationally specific TLV to put the full dpid (see
150 + * setOUIDpid()).
151 + *
152 + * @param dpid the switch DPID
153 + */
154 + private void setChassisTLV(final byte[] dpid) {
155 + this.bb = ByteBuffer.wrap(this.chassisId);
156 + this.bb.put(CHASSIS_TLV_SUBTYPE);
157 + for (int i = 2; i < 8; i++) {
158 + bb.put(dpid[i]);
159 + }
160 + this.chassisTLV.setLength(CHASSIS_TLV_SIZE);
161 + this.chassisTLV.setType(CHASSIS_TLV_TYPE);
162 + this.chassisTLV.setValue(this.chassisId);
163 + }
164 +
165 + /**
166 + * Sets port TLV.
167 + *
168 + * @param portNumber the port number
169 + */
170 + private void setPortTLV(final long portNumber) {
171 + this.bb = ByteBuffer.wrap(this.portId);
172 + this.bb.put(PORT_TLV_SUBTYPE);
173 + this.bb.putLong(portNumber);
174 +
175 + this.portTLV.setLength(PORT_TLV_SIZE);
176 + this.portTLV.setType(PORT_TLV_TYPE);
177 + this.portTLV.setValue(this.portId);
178 + }
179 +
180 + /**
181 + * Sets Time To Live TLV.
182 + *
183 + * @param time the time to live
184 + */
185 + private void setTTLTLV(final short time) {
186 + this.bb = ByteBuffer.wrap(this.ttl);
187 + this.bb.putShort(time);
188 +
189 + this.ttlTLV.setLength(TTL_TLV_SIZE);
190 + this.ttlTLV.setType(TTL_TLV_TYPE);
191 + this.ttlTLV.setValue(this.ttl);
192 + }
193 +
194 + /**
195 + * Set. organizationally specific TLV for OVX name (subtype 1).
196 + *
197 + * @param name the name
198 + */
199 + private void setOUIName(final String name) {
200 + this.bb = ByteBuffer.wrap(ouiName);
201 + this.bb.put(OVXLLDP.ONLAB_OUI);
202 + this.bb.put(NAME_TLV_SUBTYPE);
203 + this.bb.put(name.getBytes());
204 +
205 + this.ouiNameTLV.setLength(NAME_TLV_SIZE);
206 + this.ouiNameTLV.setType(NAME_TLV_TYPE);
207 + this.ouiNameTLV.setValue(ouiName);
208 + }
209 +
210 + /**
211 + * Sets organizationally specific TLV for OVX full dpid (subtype 2).
212 + *
213 + * @param dpid the switch DPID
214 + */
215 + private void setOUIDpid(final byte[] dpid) {
216 + this.bb = ByteBuffer.wrap(ouiDpid);
217 + this.bb.put(OVXLLDP.ONLAB_OUI);
218 + this.bb.put(DPID_TLV_SUBTYPE);
219 + this.bb.put(dpid);
220 +
221 + this.ouiDpidTLV.setLength(DPID_TLV_SIZE);
222 + this.ouiDpidTLV.setType(DPID_TLV_TYPE);
223 + this.ouiDpidTLV.setValue(ouiDpid);
224 + }
225 +
226 + /**
227 + * Sets switch DPID in LLDP packet.
228 + *
229 + * @param sw the switch instance
230 + */
231 + public void setSwitch(long dp) {
232 + final byte[] dpid = ByteBuffer.allocate(8).putLong(dp)
233 + .array();
234 + this.setChassisTLV(dpid);
235 + this.setOUIDpid(dpid);
236 + }
237 +
238 + /**
239 + * Sets port in LLDP packet.
240 + *
241 + * @param port the port instance
242 + */
243 + public void setPort(long port) {
244 + long portNumber = port;
245 + this.setPortTLV(portNumber);
246 + }
247 +
248 + /**
249 + * Serializes full LLDP packet to byte array. Need to set both switch and
250 + * port before you can serialize.
251 + */
252 + @Override
253 + public byte[] serialize() {
254 + return super.serialize();
255 + }
256 +
257 + /**
258 + * Checks if LLDP packet has correct size, LLDP multicast address, and
259 + * ethertype. Packet assumed to have Ethernet header.
260 + *
261 + * @param packet
262 + * @return true if packet is LLDP, false otherwise
263 + */
264 + public static boolean isLLDP(final byte[] packet) {
265 + // Does packet exist and does it have the mininum size?
266 + if (packet == null || packet.length < MINIMUM_LLDP_SIZE) {
267 + return false;
268 + }
269 +
270 + // Packet has LLDP multicast destination address?
271 + final ByteBuffer bb = ByteBuffer.wrap(packet);
272 + final byte[] dst = new byte[6];
273 + bb.get(dst);
274 +
275 + if (!(Arrays.equals(dst, OVXLLDP.LLDP_NICIRA)
276 + || Arrays.equals(dst, OVXLLDP.LLDP_MULTICAST) || Arrays.equals(
277 + dst, OVXLLDP.BDDP_MULTICAST))) {
278 +
279 + return false;
280 + }
281 +
282 + // Fetch ethertype, skip VLAN tag if it's there
283 + short etherType = bb.getShort(ETHERTYPE_OFFSET);
284 + if (etherType == ETHERTYPE_VLAN) {
285 + etherType = bb.getShort(ETHERTYPE_OFFSET + 4);
286 + }
287 +
288 + // Check ethertype
289 + if (etherType == Ethernet.TYPE_LLDP) {
290 + return true;
291 + }
292 + if (etherType == Ethernet.TYPE_BSN) {
293 + return true;
294 + }
295 +
296 + return false;
297 +
298 + }
299 +
300 + /**
301 + * Checks if packet has size of OVX-generated LLDP, and correctness of two
302 + * organizationally specific TLVs that use ON.Lab's OUI. Assumes packet is
303 + * valid LLDP packet
304 + *
305 + * @param packet
306 + * @return
307 + */
308 + public static boolean isOVXLLDP(byte[] packet) {
309 + if (packet.length < OVX_LLDP_SIZE) {
310 + return false;
311 + }
312 +
313 + // Extra offset due to VLAN tag
314 + final ByteBuffer bb = ByteBuffer.wrap(packet);
315 + int offset = 0;
316 + if (bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_LLDP
317 + && bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_BSN) {
318 + offset = 4;
319 + }
320 +
321 + // Compare packet's organizationally specific TLVs to the expected
322 + // values
323 + for (int i = 0; i < OUI_TLV.length; i++) {
324 + if (packet[NAME_TLV_OFFSET + offset + i] != OUI_TLV[i]) {
325 + return false;
326 + }
327 + }
328 +
329 + return true;
330 + }
331 +
332 + /**
333 + * Extracts dpid and port from OVX-generated LLDP packet.
334 + *
335 + * @param packet
336 + * @return Dpid and port
337 + */
338 + /* public static long parseLLDP(final byte[] packet) {
339 + final ByteBuffer bb = ByteBuffer.wrap(packet);
340 +
341 + // Extra offset due to VLAN tag
342 + int offset = 0;
343 + if (bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_LLDP
344 + && bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_BSN) {
345 + offset = 4;
346 + }
347 +
348 + final short port = bb.getLong(PORT_OFFSET + offset);
349 + final long dpid = bb.getLong(DPID_OFFSET + offset);
350 +
351 + return dpid
352 + }
353 + */
354 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.nio.ByteBuffer;
36 +
37 +/**
38 + *
39 + * @author shudong.zhou@bigswitch.com
40 + */
41 +
42 +public class TCP extends BasePacket {
43 + protected short sourcePort;
44 + protected short destinationPort;
45 + protected int sequence;
46 + protected int acknowledge;
47 + protected byte dataOffset;
48 + protected short flags;
49 + protected short windowSize;
50 + protected short checksum;
51 + protected short urgentPointer;
52 + protected byte[] options;
53 +
54 + /**
55 + * @return the sourcePort
56 + */
57 + public short getSourcePort() {
58 + return this.sourcePort;
59 + }
60 +
61 + /**
62 + * @param sourcePort
63 + * the sourcePort to set
64 + */
65 + public TCP setSourcePort(final short sourcePort) {
66 + this.sourcePort = sourcePort;
67 + return this;
68 + }
69 +
70 + /**
71 + * @return the destinationPort
72 + */
73 + public short getDestinationPort() {
74 + return this.destinationPort;
75 + }
76 +
77 + /**
78 + * @param destinationPort
79 + * the destinationPort to set
80 + */
81 + public TCP setDestinationPort(final short destinationPort) {
82 + this.destinationPort = destinationPort;
83 + return this;
84 + }
85 +
86 + /**
87 + * @return the checksum
88 + */
89 + public short getChecksum() {
90 + return this.checksum;
91 + }
92 +
93 + public int getSequence() {
94 + return this.sequence;
95 + }
96 +
97 + public TCP setSequence(final int seq) {
98 + this.sequence = seq;
99 + return this;
100 + }
101 +
102 + public int getAcknowledge() {
103 + return this.acknowledge;
104 + }
105 +
106 + public TCP setAcknowledge(final int ack) {
107 + this.acknowledge = ack;
108 + return this;
109 + }
110 +
111 + public byte getDataOffset() {
112 + return this.dataOffset;
113 + }
114 +
115 + public TCP setDataOffset(final byte offset) {
116 + this.dataOffset = offset;
117 + return this;
118 + }
119 +
120 + public short getFlags() {
121 + return this.flags;
122 + }
123 +
124 + public TCP setFlags(final short flags) {
125 + this.flags = flags;
126 + return this;
127 + }
128 +
129 + public short getWindowSize() {
130 + return this.windowSize;
131 + }
132 +
133 + public TCP setWindowSize(final short windowSize) {
134 + this.windowSize = windowSize;
135 + return this;
136 + }
137 +
138 + public short getTcpChecksum() {
139 + return this.checksum;
140 + }
141 +
142 + public TCP setTcpChecksum(final short checksum) {
143 + this.checksum = checksum;
144 + return this;
145 + }
146 +
147 + @Override
148 + public void resetChecksum() {
149 + this.checksum = 0;
150 + super.resetChecksum();
151 + }
152 +
153 + public short getUrgentPointer(final short urgentPointer) {
154 + return this.urgentPointer;
155 + }
156 +
157 + public TCP setUrgentPointer(final short urgentPointer) {
158 + this.urgentPointer = urgentPointer;
159 + return this;
160 + }
161 +
162 + public byte[] getOptions() {
163 + return this.options;
164 + }
165 +
166 + public TCP setOptions(final byte[] options) {
167 + this.options = options;
168 + this.dataOffset = (byte) (20 + options.length + 3 >> 2);
169 + return this;
170 + }
171 +
172 + /**
173 + * @param checksum
174 + * the checksum to set
175 + */
176 + public TCP setChecksum(final short checksum) {
177 + this.checksum = checksum;
178 + return this;
179 + }
180 +
181 + /**
182 + * Serializes the packet. Will compute and set the following fields if they
183 + * are set to specific values at the time serialize is called: -checksum : 0
184 + * -length : 0
185 + */
186 + @Override
187 + public byte[] serialize() {
188 + int length;
189 + if (this.dataOffset == 0) {
190 + this.dataOffset = 5; // default header length
191 + }
192 + length = this.dataOffset << 2;
193 + byte[] payloadData = null;
194 + if (this.payload != null) {
195 + this.payload.setParent(this);
196 + payloadData = this.payload.serialize();
197 + length += payloadData.length;
198 + }
199 +
200 + final byte[] data = new byte[length];
201 + final ByteBuffer bb = ByteBuffer.wrap(data);
202 +
203 + bb.putShort(this.sourcePort);
204 + bb.putShort(this.destinationPort);
205 + bb.putInt(this.sequence);
206 + bb.putInt(this.acknowledge);
207 + bb.putShort((short) (this.flags | this.dataOffset << 12));
208 + bb.putShort(this.windowSize);
209 + bb.putShort(this.checksum);
210 + bb.putShort(this.urgentPointer);
211 + if (this.dataOffset > 5) {
212 + int padding;
213 + bb.put(this.options);
214 + padding = (this.dataOffset << 2) - 20 - this.options.length;
215 + for (int i = 0; i < padding; i++) {
216 + bb.put((byte) 0);
217 + }
218 + }
219 + if (payloadData != null) {
220 + bb.put(payloadData);
221 + }
222 +
223 + if (this.parent != null && this.parent instanceof IPv4) {
224 + ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_TCP);
225 + }
226 +
227 + // compute checksum if needed
228 + if (this.checksum == 0) {
229 + bb.rewind();
230 + int accumulation = 0;
231 +
232 + // compute pseudo header mac
233 + if (this.parent != null && this.parent instanceof IPv4) {
234 + final IPv4 ipv4 = (IPv4) this.parent;
235 + accumulation += (ipv4.getSourceAddress() >> 16 & 0xffff)
236 + + (ipv4.getSourceAddress() & 0xffff);
237 + accumulation += (ipv4.getDestinationAddress() >> 16 & 0xffff)
238 + + (ipv4.getDestinationAddress() & 0xffff);
239 + accumulation += ipv4.getProtocol() & 0xff;
240 + accumulation += length & 0xffff;
241 + }
242 +
243 + for (int i = 0; i < length / 2; ++i) {
244 + accumulation += 0xffff & bb.getShort();
245 + }
246 + // pad to an even number of shorts
247 + if (length % 2 > 0) {
248 + accumulation += (bb.get() & 0xff) << 8;
249 + }
250 +
251 + accumulation = (accumulation >> 16 & 0xffff)
252 + + (accumulation & 0xffff);
253 + this.checksum = (short) (~accumulation & 0xffff);
254 + bb.putShort(16, this.checksum);
255 + }
256 + return data;
257 + }
258 +
259 + /*
260 + * (non-Javadoc)
261 + *
262 + * @see java.lang.Object#hashCode()
263 + */
264 + @Override
265 + public int hashCode() {
266 + final int prime = 5807;
267 + int result = super.hashCode();
268 + result = prime * result + this.checksum;
269 + result = prime * result + this.destinationPort;
270 + result = prime * result + this.sourcePort;
271 + return result;
272 + }
273 +
274 + /*
275 + * (non-Javadoc)
276 + *
277 + * @see java.lang.Object#equals(java.lang.Object)
278 + */
279 + @Override
280 + public boolean equals(final Object obj) {
281 + if (this == obj) {
282 + return true;
283 + }
284 + if (!super.equals(obj)) {
285 + return false;
286 + }
287 + if (!(obj instanceof TCP)) {
288 + return false;
289 + }
290 + final TCP other = (TCP) obj;
291 + // May want to compare fields based on the flags set
292 + return this.checksum == other.checksum
293 + && this.destinationPort == other.destinationPort
294 + && this.sourcePort == other.sourcePort
295 + && this.sequence == other.sequence
296 + && this.acknowledge == other.acknowledge
297 + && this.dataOffset == other.dataOffset
298 + && this.flags == other.flags
299 + && this.windowSize == other.windowSize
300 + && this.urgentPointer == other.urgentPointer
301 + && (this.dataOffset == 5 || this.options.equals(other.options));
302 + }
303 +
304 + @Override
305 + public IPacket deserialize(final byte[] data, final int offset,
306 + final int length) {
307 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
308 + this.sourcePort = bb.getShort();
309 + this.destinationPort = bb.getShort();
310 + this.sequence = bb.getInt();
311 + this.acknowledge = bb.getInt();
312 + this.flags = bb.getShort();
313 + this.dataOffset = (byte) (this.flags >> 12 & 0xf);
314 + this.flags = (short) (this.flags & 0x1ff);
315 + this.windowSize = bb.getShort();
316 + this.checksum = bb.getShort();
317 + this.urgentPointer = bb.getShort();
318 + if (this.dataOffset > 5) {
319 + int optLength = (this.dataOffset << 2) - 20;
320 + if (bb.limit() < bb.position() + optLength) {
321 + optLength = bb.limit() - bb.position();
322 + }
323 + try {
324 + this.options = new byte[optLength];
325 + bb.get(this.options, 0, optLength);
326 + } catch (final IndexOutOfBoundsException e) {
327 + this.options = null;
328 + }
329 + }
330 +
331 + this.payload = new Data();
332 + this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
333 + - bb.position());
334 + this.payload.setParent(this);
335 + return this;
336 + }
337 +}
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +/**
17 + * Copyright 2011, Big Switch Networks, Inc.
18 + * Originally created by David Erickson, Stanford University
19 + *
20 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
21 + * not use this file except in compliance with the License. You may obtain
22 + * a copy of the License at
23 + *
24 + * http://www.apache.org/licenses/LICENSE-2.0
25 + *
26 + * Unless required by applicable law or agreed to in writing, software
27 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 + * License for the specific language governing permissions and limitations
30 + * under the License.
31 + **/
32 +
33 +package org.onlab.packet;
34 +
35 +import java.nio.ByteBuffer;
36 +import java.util.HashMap;
37 +import java.util.Map;
38 +
39 +/**
40 + *
41 + * @author David Erickson (daviderickson@cs.stanford.edu)
42 + */
43 +
44 +public class UDP extends BasePacket {
45 + public static Map<Short, Class<? extends IPacket>> decodeMap;
46 + public static final short DHCP_SERVER_PORT = (short) 67;
47 + public static final short DHCP_CLIENT_PORT = (short) 68;
48 +
49 + static {
50 + UDP.decodeMap = new HashMap<Short, Class<? extends IPacket>>();
51 + /*
52 + * Disable DHCP until the deserialize code is hardened to deal with
53 + * garbage input
54 + */
55 + UDP.decodeMap.put(UDP.DHCP_SERVER_PORT, DHCP.class);
56 + UDP.decodeMap.put(UDP.DHCP_CLIENT_PORT, DHCP.class);
57 +
58 + }
59 +
60 + protected short sourcePort;
61 + protected short destinationPort;
62 + protected short length;
63 + protected short checksum;
64 +
65 + /**
66 + * @return the sourcePort
67 + */
68 + public short getSourcePort() {
69 + return this.sourcePort;
70 + }
71 +
72 + /**
73 + * @param sourcePort
74 + * the sourcePort to set
75 + */
76 + public UDP setSourcePort(final short sourcePort) {
77 + this.sourcePort = sourcePort;
78 + return this;
79 + }
80 +
81 + /**
82 + * @return the destinationPort
83 + */
84 + public short getDestinationPort() {
85 + return this.destinationPort;
86 + }
87 +
88 + /**
89 + * @param destinationPort
90 + * the destinationPort to set
91 + */
92 + public UDP setDestinationPort(final short destinationPort) {
93 + this.destinationPort = destinationPort;
94 + return this;
95 + }
96 +
97 + /**
98 + * @return the length
99 + */
100 + public short getLength() {
101 + return this.length;
102 + }
103 +
104 + /**
105 + * @return the checksum
106 + */
107 + public short getChecksum() {
108 + return this.checksum;
109 + }
110 +
111 + /**
112 + * @param checksum
113 + * the checksum to set
114 + */
115 + public UDP setChecksum(final short checksum) {
116 + this.checksum = checksum;
117 + return this;
118 + }
119 +
120 + @Override
121 + public void resetChecksum() {
122 + this.checksum = 0;
123 + super.resetChecksum();
124 + }
125 +
126 + /**
127 + * Serializes the packet. Will compute and set the following fields if they
128 + * are set to specific values at the time serialize is called: -checksum : 0
129 + * -length : 0
130 + */
131 + @Override
132 + public byte[] serialize() {
133 + byte[] payloadData = null;
134 + if (this.payload != null) {
135 + this.payload.setParent(this);
136 + payloadData = this.payload.serialize();
137 + }
138 +
139 + this.length = (short) (8 + (payloadData == null ? 0
140 + : payloadData.length));
141 +
142 + final byte[] data = new byte[this.length];
143 + final ByteBuffer bb = ByteBuffer.wrap(data);
144 +
145 + bb.putShort(this.sourcePort);
146 + bb.putShort(this.destinationPort);
147 + bb.putShort(this.length);
148 + bb.putShort(this.checksum);
149 + if (payloadData != null) {
150 + bb.put(payloadData);
151 + }
152 +
153 + if (this.parent != null && this.parent instanceof IPv4) {
154 + ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_UDP);
155 + }
156 +
157 + // compute checksum if needed
158 + if (this.checksum == 0) {
159 + bb.rewind();
160 + int accumulation = 0;
161 +
162 + // compute pseudo header mac
163 + if (this.parent != null && this.parent instanceof IPv4) {
164 + final IPv4 ipv4 = (IPv4) this.parent;
165 + accumulation += (ipv4.getSourceAddress() >> 16 & 0xffff)
166 + + (ipv4.getSourceAddress() & 0xffff);
167 + accumulation += (ipv4.getDestinationAddress() >> 16 & 0xffff)
168 + + (ipv4.getDestinationAddress() & 0xffff);
169 + accumulation += ipv4.getProtocol() & 0xff;
170 + accumulation += this.length & 0xffff;
171 + }
172 +
173 + for (int i = 0; i < this.length / 2; ++i) {
174 + accumulation += 0xffff & bb.getShort();
175 + }
176 + // pad to an even number of shorts
177 + if (this.length % 2 > 0) {
178 + accumulation += (bb.get() & 0xff) << 8;
179 + }
180 +
181 + accumulation = (accumulation >> 16 & 0xffff)
182 + + (accumulation & 0xffff);
183 + this.checksum = (short) (~accumulation & 0xffff);
184 + bb.putShort(6, this.checksum);
185 + }
186 + return data;
187 + }
188 +
189 + /*
190 + * (non-Javadoc)
191 + *
192 + * @see java.lang.Object#hashCode()
193 + */
194 + @Override
195 + public int hashCode() {
196 + final int prime = 5807;
197 + int result = super.hashCode();
198 + result = prime * result + this.checksum;
199 + result = prime * result + this.destinationPort;
200 + result = prime * result + this.length;
201 + result = prime * result + this.sourcePort;
202 + return result;
203 + }
204 +
205 + /*
206 + * (non-Javadoc)
207 + *
208 + * @see java.lang.Object#equals(java.lang.Object)
209 + */
210 + @Override
211 + public boolean equals(final Object obj) {
212 + if (this == obj) {
213 + return true;
214 + }
215 + if (!super.equals(obj)) {
216 + return false;
217 + }
218 + if (!(obj instanceof UDP)) {
219 + return false;
220 + }
221 + final UDP other = (UDP) obj;
222 + if (this.checksum != other.checksum) {
223 + return false;
224 + }
225 + if (this.destinationPort != other.destinationPort) {
226 + return false;
227 + }
228 + if (this.length != other.length) {
229 + return false;
230 + }
231 + if (this.sourcePort != other.sourcePort) {
232 + return false;
233 + }
234 + return true;
235 + }
236 +
237 + @Override
238 + public IPacket deserialize(final byte[] data, final int offset,
239 + final int length) {
240 + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
241 + this.sourcePort = bb.getShort();
242 + this.destinationPort = bb.getShort();
243 + this.length = bb.getShort();
244 + this.checksum = bb.getShort();
245 +
246 + if (UDP.decodeMap.containsKey(this.destinationPort)) {
247 + try {
248 + this.payload = UDP.decodeMap.get(this.destinationPort)
249 + .getConstructor().newInstance();
250 + } catch (final Exception e) {
251 + throw new RuntimeException("Failure instantiating class", e);
252 + }
253 + } else if (UDP.decodeMap.containsKey(this.sourcePort)) {
254 + try {
255 + this.payload = UDP.decodeMap.get(this.sourcePort)
256 + .getConstructor().newInstance();
257 + } catch (final Exception e) {
258 + throw new RuntimeException("Failure instantiating class", e);
259 + }
260 + } else {
261 + this.payload = new Data();
262 + }
263 + this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
264 + - bb.position());
265 + this.payload.setParent(this);
266 + return this;
267 + }
268 +}
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
27 <groupId>com.google.guava</groupId> 27 <groupId>com.google.guava</groupId>
28 <artifactId>guava</artifactId> 28 <artifactId>guava</artifactId>
29 </dependency> 29 </dependency>
30 + <dependency>
31 + <groupId>commons-lang</groupId>
32 + <artifactId>commons-lang</artifactId>
33 + <version>2.3</version>
34 + </dependency>
30 </dependencies> 35 </dependencies>
31 36
32 <build> 37 <build>
......