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 | -<?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 | - |
of/ctl/conf/findbugs/exclude.xml
deleted
100644 → 0
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> | ... | ... |
-
Please register or login to post a comment