alshabib

initial import

Change-Id: Ief25aef0066ea96bd2c329ccef974c072b3a5a73
Showing 170 changed files with 19316 additions and 0 deletions
1 +<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2 +<!--
3 + ~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
4 + ~
5 + ~ This program and the accompanying materials are made available under the
6 + ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 + ~ and is available at http://www.eclipse.org/legal/epl-v10.html
8 + -->
9 +
10 +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
11 + name="net.onrc.onos-1.0.0">
12 + <repository>mvn:net.onrc.onos/onos-features/1.0.0-SNAPSHOT/xml/features</repository>
13 +
14 + <feature name="thirdparty" version="1.0.0"
15 + description="ONOS 3rd party dependencies">
16 + <bundle>mvn:com.google.code.findbugs/annotations/2.0.2</bundle>
17 + <bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
18 + <bundle>mvn:com.google.guava/guava/17.0</bundle>
19 + <bundle>mvn:com.google.guava/guava/15.0</bundle>
20 +
21 + </feature>
22 +
23 + <feature name="base" version="1.0.0"
24 + description="ONOS Base">
25 + <feature>scr</feature>
26 + <feature>thirdparty</feature>
27 + <bundle>mvn:net.onrc.onos.sb/onos-sb/0.0.1</bundle>
28 + <bundle>mvn:org.projectfloodlight/openflowj/0.3.6-SNAPSHOT</bundle>
29 + </feature>
30 +
31 +</features>
1 +package net.onrc.onos.api;
2 +
3 +/**
4 + * Base abstraction of a piece of information about network elements.
5 + */
6 +public interface Description {
7 +}
1 +package net.onrc.onos.api;
2 +
3 +import java.net.URI;
4 +
5 +/**
6 + * Immutable representaion of a device identity.
7 + */
8 +public class DeviceId {
9 +
10 + private final URI uri;
11 +
12 + public DeviceId(URI uri) {
13 + this.uri = uri;
14 + }
15 +
16 + /**
17 + * Returns the backing URI.
18 + *
19 + * @return backing device URI
20 + */
21 + public URI uri() {
22 + return uri;
23 + }
24 +
25 +}
1 +package net.onrc.onos.api;
2 +
3 +/**
4 + * Representation of a port number.
5 + */
6 +public interface PortNumber {
7 +}
1 +package net.onrc.onos.api;
2 +
3 +/**
4 + * Abstraction of a provider of information about network environment.
5 + */
6 +public interface Provider {
7 +
8 + ProviderId id();
9 +
10 +}
1 +package net.onrc.onos.api;
2 +
3 +/**
4 + * Broker used for registering/unregistering information providers with the core.
5 + *
6 + * @param <T> type of the information provider
7 + * @param <S> type of the provider service
8 + */
9 +public interface ProviderBroker<T extends Provider, S extends ProviderService> {
10 +
11 + /**
12 + * Registers the supplied provider with the core.
13 + *
14 + * @param provider provider to be registered
15 + * @return provider service for injecting information into core
16 + */
17 + S register(T provider);
18 +
19 + /**
20 + * Unregisters the supplied provider. As a result the previously issued
21 + * provider service will be invalidated.
22 + *
23 + * @param provider provider to be unregistered
24 + */
25 + void unregister(T provider);
26 +
27 +}
1 +package net.onrc.onos.api;
2 +
3 +/**
4 + * Notion of provider identity.
5 + */
6 +public class ProviderId {
7 +
8 + private final String id;
9 +
10 + public ProviderId(String id) {
11 + this.id = id;
12 + }
13 +
14 + @Override
15 + public boolean equals(Object o) {
16 + if (this == o) {
17 + return true;
18 + }
19 + if (o == null || getClass() != o.getClass()) {
20 + return false;
21 + }
22 +
23 + ProviderId that = (ProviderId) o;
24 +
25 + if (!id.equals(that.id)) {
26 + return false;
27 + }
28 +
29 + return true;
30 + }
31 +
32 + @Override
33 + public int hashCode() {
34 + return id.hashCode();
35 + }
36 +
37 + @Override
38 + public String toString() {
39 + return "ProviderId{" +
40 + "id='" + id + '\'' +
41 + '}';
42 + }
43 +}
1 +package net.onrc.onos.api;
2 +
3 +/**
4 + * Abstraction of a service through which providers can inject information
5 + * about the network environment into the core.
6 + */
7 +public interface ProviderService {
8 +}
1 +package net.onrc.onos.api.device;
2 +
3 +import net.onrc.onos.api.Description;
4 +
5 +import java.net.URI;
6 +
7 +/**
8 + * Carrier of immutable information about a device.
9 + */
10 +public interface DeviceDescription extends Description {
11 +
12 + /**
13 + * Protocol/provider specific URI that can be used to encode the identity
14 + * information required to communicate with the device externally, e.g.
15 + * datapath ID.
16 + *
17 + * @return provider specific URI for the device
18 + */
19 + URI deviceURI();
20 +
21 +}
...\ No newline at end of file ...\ No newline at end of file
1 +package net.onrc.onos.api.device;
2 +
3 +import net.onrc.onos.api.Provider;
4 +
5 +/**
6 + * Abstraction of a device information provider.
7 + */
8 +public interface DeviceProvider extends Provider {
9 +}
1 +package net.onrc.onos.api.device;
2 +
3 +import net.onrc.onos.api.ProviderBroker;
4 +
5 +/**
6 + * Abstraction of a device provider brokerage.
7 + */
8 +public interface DeviceProviderBroker
9 + extends ProviderBroker<DeviceProvider, DeviceProviderService> {
10 +}
1 +package net.onrc.onos.api.device;
2 +
3 +import net.onrc.onos.api.ProviderService;
4 +
5 +import java.util.List;
6 +
7 +/**
8 + * Service through which device providers can inject device information into
9 + * the core.
10 + */
11 +public interface DeviceProviderService extends ProviderService {
12 +
13 + // TODO: define suspend and remove actions on the mezzanine administrative API
14 +
15 + /**
16 + * Signals the core that a device has connected or has been detected somehow.
17 + *
18 + * @param deviceDescription information about network device
19 + */
20 + void deviceConnected(DeviceDescription deviceDescription);
21 +
22 + /**
23 + * Signals the core that a device has disconnected or is no longer reachable.
24 + *
25 + * @param deviceDescription device to be removed
26 + */
27 + void deviceDisconnected(DeviceDescription deviceDescription);
28 +
29 + /**
30 + * Sends information about all ports of a device. It is up to the core to
31 + * determine what has changed.
32 + *
33 + * @param ports list of device ports
34 + */
35 + void updatePorts(List<PortDescription> ports);
36 +
37 + /**
38 + * Used to notify the core about port status change of a single port.
39 + *
40 + * @param port description of the port that changed
41 + */
42 + void portStatusChanged(PortDescription port);
43 +
44 +}
1 +package net.onrc.onos.api.device;
2 +
3 +/**
4 + * Information about a port.
5 + */
6 +public interface PortDescription {
7 +
8 + // TODO: possibly relocate this to a common ground so that this can also used by host tracking if required
9 +
10 +}
1 +package net.onrc.onos.api.host;
2 +
3 +/**
4 + * Information describing host and its location.
5 + */
6 +public interface HostDescription {
7 +
8 + // IP, MAC, VLAN-ID, HostLocation -> (ConnectionPoint + timestamp)
9 +
10 +
11 +}
1 +package net.onrc.onos.api.host;
2 +
3 +import net.onrc.onos.api.Provider;
4 +
5 +/**
6 + * Provider of information about hosts and their location on the network.
7 + */
8 +public interface HostProvider extends Provider {
9 +}
1 +package net.onrc.onos.api.host;
2 +
3 +import net.onrc.onos.api.ProviderBroker;
4 +
5 +/**
6 + * Abstraction of a host provider brokerage.
7 + */
8 +public interface HostProviderBroker
9 + extends ProviderBroker<HostProvider, HostProviderService> {
10 +}
1 +package net.onrc.onos.api.host;
2 +
3 +import net.onrc.onos.api.ProviderService;
4 +
5 +/**
6 + * Means of conveying host information to the core.
7 + */
8 +public interface HostProviderService extends ProviderService {
9 +
10 + void hostDetected(HostDescription hostDescription);
11 +
12 +}
1 +package net.onrc.onos.api.link;
2 +
3 +/**
4 + * Describes an infrastructure link.
5 + */
6 +public interface LinkDescription {
7 +
8 + // TODO: src, dst connection points, which are pairs of (DeviceId, PortNumber)
9 +
10 +// On the north:
11 +// Link = (ConnectPoint src, ConnectPoint dst);
12 +// ConnectPoint = (DeviceId, PortNumber);
13 +
14 +// On the south
15 +// LinkDescription ~ Link
16 +
17 +}
1 +package net.onrc.onos.api.link;
2 +
3 +import net.onrc.onos.api.Provider;
4 +
5 +/**
6 + * Abstraction of an entity providing information about infrastructure links
7 + * to the core.
8 + */
9 +public interface LinkProvider extends Provider {
10 +}
1 +package net.onrc.onos.api.link;
2 +
3 +import net.onrc.onos.api.ProviderBroker;
4 +
5 +/**
6 + * Abstraction of an infrastructure link provider brokerage.
7 + */
8 +public interface LinkProviderBroker
9 + extends ProviderBroker<LinkProvider, LinkProviderService> {
10 +}
1 +package net.onrc.onos.api.link;
2 +
3 +import net.onrc.onos.api.ProviderService;
4 +
5 +/**
6 + * Means for injecting link information into the core.
7 + */
8 +public interface LinkProviderService extends ProviderService {
9 +
10 + /**
11 + * Signals that an infrastructure link has been connected.
12 + *
13 + * @param linkDescription link information
14 + */
15 + void linkConnected(LinkDescription linkDescription);
16 +
17 + /**
18 + * Signals that an infrastructure link has been disconnected.
19 + *
20 + * @param linkDescription link information
21 + */
22 + void linkDisconnected(LinkDescription linkDescription);
23 +
24 +}
1 +# See: http://rolf-engelhard.de/2011/04/using-the-same-suppression-filter-for-checkstyle-in-eclipse-and-maven/
2 +config_loc=conf/checkstyle
1 +<?xml version="1.0"?>
2 +<!DOCTYPE module PUBLIC
3 + "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
4 + "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
5 +
6 +
7 +<!--
8 +
9 + Checkstyle configuration that checks the sun coding conventions from:
10 +
11 + - the Java Language Specification at
12 + http://java.sun.com/docs/books/jls/second_edition/html/index.html
13 +
14 + - the Sun Code Conventions at http://java.sun.com/docs/codeconv/
15 +
16 + - the Javadoc guidelines at
17 + http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
18 +
19 + - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
20 +
21 + - some best practices
22 +
23 + Checkstyle is very configurable. Be sure to read the documentation at
24 + http://checkstyle.sf.net (or in your downloaded distribution).
25 +
26 + Most Checks are configurable, be sure to consult the documentation.
27 +
28 + To completely disable a check, just comment it out or delete it from the file.
29 +
30 + Finally, it is worth reading the documentation.
31 +
32 +-->
33 +
34 +
35 +<!--
36 + The default severity setting in checkstyle is 'error', so some
37 + of the rules below are configured to change the severity to
38 + 'warning'. Over time, these 'warning' settings should be
39 + removed as more of the ONOS source code is modified to
40 + follow the recommended rules.
41 +-->
42 +
43 +
44 +
45 +<module name="Checker">
46 + <module name="SuppressionFilter">
47 + <property name="file" value="${config_loc}/suppressions.xml"/>
48 + </module>
49 + <!--
50 + If you set the basedir property below, then all reported file
51 + names will be relative to the specified directory. See
52 + http://checkstyle.sourceforge.net/5.x/config.html#Checker
53 +
54 + <property name="basedir" value="${basedir}"/>
55 + -->
56 + <!-- Checks that a package-info.java file exists for each package. -->
57 + <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
58 + <!-- ONOS does not currently supply package level Javadoc information
59 + in package-info files -->
60 + <!-- <module name="JavadocPackage"/> -->
61 +
62 + <!-- Checks whether files end with a new line. -->
63 + <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
64 + <module name="NewlineAtEndOfFile"/>
65 +
66 + <!-- Checks that property files contain the same keys. -->
67 + <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
68 + <module name="Translation"/>
69 +
70 + <!-- Checks for Size Violations. -->
71 + <!-- See http://checkstyle.sf.net/config_sizes.html -->
72 + <module name="FileLength">
73 + <property name="max" value="2500"/>
74 + </module>
75 +
76 + <!-- Checks for whitespace -->
77 + <!-- See http://checkstyle.sf.net/config_whitespace.html -->
78 + <module name="FileTabCharacter"/>
79 +
80 + <!-- Miscellaneous other checks. -->
81 + <!-- See http://checkstyle.sf.net/config_misc.html -->
82 + <module name="RegexpSingleline">
83 + <property name="format" value="\s+$"/>
84 + <property name="minimum" value="0"/>
85 + <property name="maximum" value="0"/>
86 + <property name="message" value="Line has trailing spaces."/>
87 + </module>
88 +
89 + <!-- Checks for Headers -->
90 + <!-- See http://checkstyle.sf.net/config_header.html -->
91 + <!-- <module name="Header"> -->
92 + <!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
93 + <!-- <property name="fileExtensions" value="java"/> -->
94 + <!-- </module> -->
95 +
96 + <module name="SuppressionCommentFilter">
97 + <property name="offCommentFormat" value="(CHECKSTYLE\:OFF|Generated by the protocol buffer compiler.)"/>
98 + <property name="onCommentFormat" value="CHECKSTYLE:ON"/>
99 + </module>
100 +
101 + <module name="SuppressWithNearbyCommentFilter">
102 + <property name="commentFormat" value="CHECKSTYLE IGNORE THIS LINE" />
103 + <property name="checkFormat" value=".*" />
104 + <property name="influenceFormat" value="0" />
105 + </module>
106 +
107 + <!-- Example: // CHECKSTYLE IGNORE FinalClass FOR NEXT 1 LINES -->
108 + <module name="SuppressWithNearbyCommentFilter">
109 + <property name="commentFormat" value="CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES"/>
110 + <property name="checkFormat" value="$1"/>
111 + <property name="influenceFormat" value="$2"/>
112 + </module>
113 +
114 + <module name="TreeWalker">
115 +
116 + <module name="FileContentsHolder"/>
117 + <!-- Checks for Javadoc comments. -->
118 + <!-- See http://checkstyle.sf.net/config_javadoc.html -->
119 + <module name="JavadocMethod">
120 + <property name="severity" value="warning"/>
121 + <property name="allowUndeclaredRTE" value="true"/>
122 + </module>
123 + <module name="JavadocType">
124 + <property name="severity" value="warning"/>
125 + </module>
126 + <module name="JavadocVariable">
127 + <!-- Suppress check for private member Javadocs.
128 + Possibly revist fixing these. -->
129 + <property name="scope" value="public"/>
130 + <property name="severity" value="warning"/>
131 + </module>
132 + <module name="JavadocStyle"/>
133 + <!-- @author tag should not be used -->
134 + <module name="WriteTag">
135 + <property name="tag" value="@author"/>
136 + <property name="tagFormat" value="\S"/>
137 + <property name="severity" value="ignore"/>
138 + <property name="tagSeverity" value="error"/>
139 + </module>
140 +
141 +
142 + <!-- Checks for Naming Conventions. -->
143 + <!-- See http://checkstyle.sf.net/config_naming.html -->
144 + <module name="ConstantName">
145 + <!-- ONOS allows the name "log" for static final Loggers -->
146 + <property name="format"
147 + value="^log$|^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"/>
148 + </module>
149 + <module name="LocalFinalVariableName"/>
150 +
151 + <module name="LocalVariableName"/>
152 +
153 + <module name="MemberName"/>
154 + <module name="MethodName"/>
155 + <module name="PackageName"/>
156 + <module name="ParameterName"/>
157 + <module name="StaticVariableName"/>
158 + <module name="TypeName"/>
159 +
160 + <!-- Checks for imports -->
161 + <!-- See http://checkstyle.sf.net/config_import.html -->
162 + <module name="AvoidStarImport">
163 + <property name="allowStaticMemberImports" value="true"/>
164 + </module>
165 + <module name="IllegalImport"/>
166 + <!-- defaults to sun.* packages -->
167 + <module name="RedundantImport"/>
168 + <module name="UnusedImports"/>
169 +
170 +
171 + <!-- Checks for Size Violations. -->
172 + <!-- See http://checkstyle.sf.net/config_sizes.html -->
173 + <module name="LineLength">
174 + <!-- ONOS standard usage is 80 columns, but we allow up
175 + to 120 to not break the build. -->
176 + <property name="max" value="120"/>
177 + <property name="ignorePattern" value="^import"/>
178 + </module>
179 + <module name="MethodLength">
180 + <property name="max" value="400"/>
181 + </module>
182 +
183 + <module name="ParameterNumber"/>
184 +
185 + <!-- Checks for whitespace -->
186 + <!-- See http://checkstyle.sf.net/config_whitespace.html -->
187 + <module name="EmptyForIteratorPad"/>
188 + <module name="GenericWhitespace"/>
189 + <module name="MethodParamPad"/>
190 + <module name="NoWhitespaceAfter"/>
191 + <module name="NoWhitespaceBefore"/>
192 +
193 + <!-- Disabled for ONOS. Default rules specify undesired behavior for the '?' operator -->
194 + <!-- <module name="OperatorWrap"/> -->
195 + <module name="ParenPad"/>
196 + <module name="TypecastParenPad"/>
197 + <module name="WhitespaceAfter"/>
198 + <module name="WhitespaceAround">
199 + <property name="allowEmptyConstructors" value="true"/>
200 + <property name="allowEmptyMethods" value="true"/>
201 + </module>
202 +
203 +
204 +
205 + <!-- Modifier Checks -->
206 + <!-- See http://checkstyle.sf.net/config_modifiers.html -->
207 + <module name="ModifierOrder"/>
208 +
209 + <!-- Disabled for ONOS to allow use of public -->
210 + <!-- modifiers in interfaces. -->
211 + <!-- <module name="RedundantModifier"/> -->
212 +
213 +
214 + <!-- Checks for blocks. You know, those {}'s -->
215 + <!-- See http://checkstyle.sf.net/config_blocks.html -->
216 + <module name="AvoidNestedBlocks">
217 + <!-- ONOS alows declarations inside of switch case blocks -->
218 + <property name="allowInSwitchCase" value="true"/>
219 + </module>
220 + <module name="EmptyBlock"/>
221 + <module name="LeftCurly"/>
222 + <module name="NeedBraces"/>
223 + <module name="RightCurly"/>
224 +
225 + <!-- Checks for common coding problems -->
226 + <!-- See http://checkstyle.sf.net/config_coding.html -->
227 + <!-- ONOS allows conditional operators -->
228 + <!-- <module name="AvoidInlineConditionals"/> -->
229 + <module name="EmptyStatement"/>
230 + <module name="EqualsHashCode"/>
231 +
232 + <module name="HiddenField">
233 + <property name="ignoreSetter" value="true"/>
234 + <property name="ignoreConstructorParameter" value="true"/>
235 + </module>
236 +
237 + <module name="IllegalInstantiation"/>
238 + <module name="InnerAssignment"/>
239 +
240 + <!-- Many violations of this rule present, revist in a
241 + subsequent round of cleanups -->
242 + <!-- <module name="MagicNumber"/> -->
243 + <module name="MissingSwitchDefault"/>
244 +
245 + <module name="RedundantThrows">
246 + <property name="allowSubclasses" value="true"/>
247 + <property name="allowUnchecked" value="true"/>
248 + <property name="suppressLoadErrors" value="true"/>
249 + </module>
250 +
251 + <module name="SimplifyBooleanExpression"/>
252 + <module name="SimplifyBooleanReturn"/>
253 +
254 + <!-- Checks for class design -->
255 + <!-- See http://checkstyle.sf.net/config_design.html -->
256 + <!-- ONOS produces many warnings of this type.
257 + Fixing all of these is outside the scope of the current cleanup. -->
258 + <!-- <module name="DesignForExtension"/> -->
259 + <module name="FinalClass"/>
260 +
261 + <module name="HideUtilityClassConstructor"/>
262 +
263 + <module name="InterfaceIsType"/>
264 +
265 + <module name="VisibilityModifier">
266 + <property name="severity" value="warning"/>
267 + </module>
268 +
269 +
270 +
271 + <!-- Miscellaneous other checks. -->
272 + <!-- See http://checkstyle.sf.net/config_misc.html -->
273 + <module name="ArrayTypeStyle"/>
274 +
275 + <!-- Many violations of this rule currently, too many to fix
276 + in the current cleanup. -->
277 + <!-- <module name="FinalParameters"/> -->
278 + <!-- ONOS allows TODO markers in checked in source code -->
279 + <!-- <module name="TodoComment"/> -->
280 + <module name="UpperEll"/>
281 +
282 + </module>
283 +
284 + </module>
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN" "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
3 +
4 +<suppressions>
5 + <!--
6 + Note: Exclusion definition exists in multiple places.
7 + - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
8 + - In file conf/checkstyle/onos_suppressions.xml (this file)
9 + - maven-pmd-plugin configuration in pom.xml
10 + (under build and reporting)
11 + -->
12 +
13 + <suppress files=".*" checks="FinalParametersCheck"/>
14 + <suppress files=".*" checks="MagicNumbersCheck"/>
15 + <suppress files=".*" checks="DesignForExtensionCheck"/>
16 + <suppress files=".*" checks="TodoCommentCheck"/>
17 + <suppress files=".*" checks="AvoidInlineConditionalsCheck"/>
18 + <suppress files=".*" checks="OperatorWrapCheck"/>
19 +</suppressions>
20 +
1 +<FindBugsFilter>
2 + <!--
3 + Note: Exclusion definition exists in multiple places.
4 + - In file ${findbugs.excludeFilterFile} defined at top of pom.xml (this file)
5 + - In file conf/checkstyle/onos_suppressions.xml
6 + - maven-pmd-plugin configuration in pom.xml
7 + (under build and reporting)
8 + -->
9 + <Match>
10 + <Class name="~net\.onrc\.onos\.core\.datastore\.serializers\..*" />
11 + </Match>
12 + <Match>
13 + <Class name="~.*edu\.stanford\..*"/>
14 + </Match>
15 + <Match>
16 + <Class name="~.org\.projectfloodlight\..*"/>
17 + </Match>
18 +</FindBugsFilter>
1 +<?xml version="1.0"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3 + <modelVersion>4.0.0</modelVersion>
4 + <prerequisites>
5 + <maven>3.0.4</maven>
6 + </prerequisites>
7 + <groupId>net.onrc.onos.sb</groupId>
8 + <artifactId>onos-sb</artifactId>
9 + <version>0.0.1</version>
10 + <packaging>bundle</packaging>
11 + <name>ONOS-SB</name>
12 + <url>http://onlab.us/</url>
13 + <licenses>
14 + <license>
15 + <name>Apache License, Version 2.0</name>
16 + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
17 + </license>
18 + </licenses>
19 + <repositories>
20 + <repository>
21 + <id>central</id>
22 + <name>Maven Central repository</name>
23 + <url>https://repo1.maven.org/maven2</url>
24 + </repository>
25 + <repository>
26 + <id>maven-restlet</id>
27 + <name>Public online Restlet repository</name>
28 + <url>http://maven.restlet.org</url>
29 + <snapshots>
30 + <enabled>false</enabled>
31 + </snapshots>
32 + </repository>
33 + <repository>
34 + <id>sonatype-oss-snapshot</id>
35 + <name>Sonatype OSS snapshot repository</name>
36 + <url>https://oss.sonatype.org/content/repositories/snapshots</url>
37 + <releases>
38 + <enabled>false</enabled>
39 + </releases>
40 + </repository>
41 + </repositories>
42 + <properties>
43 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
44 + <powermock.version>1.5.5</powermock.version>
45 + <restlet.version>2.1.4</restlet.version>
46 + <cobertura-maven-plugin.version>2.6</cobertura-maven-plugin.version>
47 + <!-- Following 2 findbugs version needs to be updated in sync to match the
48 + findbugs version used in findbugs-plugin -->
49 + <findbugs.version>3.0.0</findbugs.version>
50 + <findbugs-plugin.version>3.0.0</findbugs-plugin.version>
51 + <findbugs.effort>Max</findbugs.effort>
52 + <findbugs.excludeFilterFile>conf/findbugs/exclude.xml</findbugs.excludeFilterFile>
53 + <checkstyle-plugin.version>2.12</checkstyle-plugin.version>
54 + <!-- To publish javadoc to github,
55 + uncomment com.github.github site-maven-plugin and
56 + see https://github.com/OPENNETWORKINGLAB/ONOS/pull/425
57 + <github.global.server>github</github.global.server>
58 + -->
59 + <metrics.version>3.0.2</metrics.version>
60 + <maven.surefire.plugin.version>2.16</maven.surefire.plugin.version>
61 + </properties>
62 + <build>
63 + <plugins>
64 + <plugin>
65 + <groupId>org.apache.felix</groupId>
66 + <artifactId>maven-scr-plugin</artifactId>
67 + <version>1.15.0</version>
68 + <executions>
69 + <execution>
70 + <id>generate-scr-srcdescriptor</id>
71 + <goals>
72 + <goal>scr</goal>
73 + </goals>
74 + </execution>
75 + </executions>
76 + <configuration>
77 + <supportedProjectTypes>
78 + <supportedProjectType>bundle</supportedProjectType>
79 + <supportedProjectType>war</supportedProjectType>
80 + </supportedProjectTypes>
81 + </configuration>
82 +</plugin>
83 + <plugin>
84 + <groupId>org.apache.felix</groupId>
85 + <artifactId>maven-bundle-plugin</artifactId>
86 + <version>2.3.6</version>
87 + <extensions>true</extensions>
88 + <configuration>
89 + <instructions>
90 + <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
91 + </instructions>
92 + </configuration>
93 + </plugin>
94 + <!-- Note: the checkstyle configuration is also in the reporting section -->
95 + <plugin>
96 + <groupId>org.apache.maven.plugins</groupId>
97 + <artifactId>maven-checkstyle-plugin</artifactId>
98 + <version>${checkstyle-plugin.version}</version>
99 + <configuration>
100 + <configLocation>conf/checkstyle/sun_checks.xml</configLocation>
101 + <propertiesLocation>${basedir}/conf/checkstyle/checkstyle_maven.properties</propertiesLocation>
102 + <failsOnError>false</failsOnError>
103 + <logViolationsToConsole>true</logViolationsToConsole>
104 + <includeTestSourceDirectory>true</includeTestSourceDirectory>
105 + </configuration>
106 + <executions>
107 + <execution>
108 + <id>validate-checkstyle</id>
109 + <phase>verify</phase>
110 + <goals>
111 + <goal>check</goal>
112 + </goals>
113 + </execution>
114 + </executions>
115 + </plugin>
116 + <plugin>
117 + <groupId>org.apache.maven.plugins</groupId>
118 + <artifactId>maven-install-plugin</artifactId>
119 + <version>2.5.1</version>
120 + <executions>
121 + </executions>
122 + </plugin>
123 + <!-- guice maven plugin for dependency injection inside maven -->
124 + <plugin>
125 + <groupId>org.apache.camel</groupId>
126 + <artifactId>guice-maven-plugin</artifactId>
127 + <version>2.11.0</version>
128 + </plugin>
129 + <plugin>
130 + <artifactId>maven-clean-plugin</artifactId>
131 + <version>2.5</version>
132 + </plugin>
133 + <plugin>
134 + <artifactId>maven-deploy-plugin</artifactId>
135 + <version>2.8</version>
136 + </plugin>
137 + <plugin>
138 + <artifactId>maven-jar-plugin</artifactId>
139 + <version>2.4</version>
140 + </plugin>
141 + <plugin>
142 + <artifactId>maven-resources-plugin</artifactId>
143 + <version>2.6</version>
144 + </plugin>
145 + <plugin>
146 + <artifactId>maven-site-plugin</artifactId>
147 + <version>3.3</version>
148 + </plugin>
149 + <plugin>
150 + <groupId>org.apache.maven.plugins</groupId>
151 + <artifactId>maven-compiler-plugin</artifactId>
152 + <version>3.1</version>
153 + <configuration>
154 + <source>1.7</source>
155 + <target>1.7</target>
156 + <encoding>UTF-8</encoding>
157 + <showDeprecation>true</showDeprecation>
158 + <showWarnings>true</showWarnings>
159 + <compilerArgs>
160 + <arg>-Xlint:all</arg>
161 + <arg>-Xlint:-serial</arg>
162 + <arg>-Werror</arg>
163 + </compilerArgs>
164 + </configuration>
165 + <executions>
166 + </executions>
167 + </plugin>
168 + <plugin>
169 + <groupId>org.apache.maven.plugins</groupId>
170 + <artifactId>maven-surefire-plugin</artifactId>
171 + <version>${maven.surefire.plugin.version}</version>
172 + <configuration>
173 + <!-- FIXME -XX:-UseSplitVerifier added as workaround for JDK 1.7.0u65 + PowerMock issue
174 + https://issues.jboss.org/browse/JASSIST-228 -->
175 + <argLine>-XX:MaxPermSize=256m -XX:-UseSplitVerifier</argLine>
176 + <redirectTestOutputToFile>false</redirectTestOutputToFile>
177 + <excludedGroups>net.onrc.onos.core.util.IntegrationTest</excludedGroups>
178 + </configuration>
179 + </plugin>
180 + <!-- TODO exec:java no longer used remove at some point? -->
181 + <plugin>
182 + <groupId>org.codehaus.mojo</groupId>
183 + <artifactId>exec-maven-plugin</artifactId>
184 + <version>1.2.1</version>
185 + <configuration>
186 + <mainClass>net.onrc.onos.core.main.Main</mainClass>
187 + </configuration>
188 + <executions>
189 + </executions>
190 + </plugin>
191 + <plugin>
192 + <groupId>org.apache.maven.plugins</groupId>
193 + <artifactId>maven-javadoc-plugin</artifactId>
194 + <version>2.9.1</version>
195 + <configuration>
196 + <charset>UTF-8</charset>
197 + <locale>en</locale>
198 + <author>false</author>
199 + <excludePackageNames>net.floodlightcontroller.*:net.onrc.onos.core.datastore.serializers</excludePackageNames>
200 + </configuration>
201 + </plugin>
202 +<!-- Remove me when we're sure that system test no longer need JaCoCo
203 + <plugin>
204 + <groupId>org.jacoco</groupId>
205 + <artifactId>jacoco-maven-plugin</artifactId>
206 + <version>0.6.3.201306030806</version>
207 + <executions>
208 + <execution>
209 + <id>jacoco-initialize</id>
210 + <goals>
211 + <goal>prepare-agent</goal>
212 + </goals>
213 + </execution>
214 + <execution>
215 + <id>jacoco-site</id>
216 + <phase>package</phase>
217 + <goals>
218 + <goal>report</goal>
219 + </goals>
220 + </execution>
221 + </executions>
222 + </plugin>
223 +-->
224 + <!-- Uncomment when publishing javadoc to github in the future.
225 + <plugin>
226 + <groupId>com.github.github</groupId>
227 + <artifactId>site-maven-plugin</artifactId>
228 + <version>0.8</version>
229 + <configuration>
230 + <message>Creating site for ${project.version}</message>
231 + <dryRun>true</dryRun>
232 + <repositoryName>ONOS</repositoryName>
233 + <repositoryOwner>OPENNETWORKINGLAB</repositoryOwner>
234 + <path>javadoc/${project.version}/</path>
235 + </configuration>
236 + <executions>
237 + <execution>
238 + <goals>
239 + <goal>site</goal>
240 + </goals>
241 + <phase>site</phase>
242 + </execution>
243 + </executions>
244 + </plugin>
245 + -->
246 + <plugin>
247 + <artifactId>maven-assembly-plugin</artifactId>
248 + <version>2.4</version>
249 + <configuration>
250 + <descriptorRefs>
251 + <descriptorRef>jar-with-dependencies</descriptorRef>
252 + </descriptorRefs>
253 + </configuration>
254 + </plugin>
255 + <plugin>
256 + <!-- Using groovy script to set maven property ${hostname}.
257 + This is a workaround to get hostname as a property inside pom file,
258 + which current Maven does not provide. -->
259 + <groupId>org.codehaus.gmaven</groupId>
260 + <artifactId>groovy-maven-plugin</artifactId>
261 + <version>2.0</version>
262 + <executions>
263 + <execution>
264 + <phase>initialize</phase>
265 + <goals>
266 + <goal>execute</goal>
267 + </goals>
268 + <configuration>
269 + <source>
270 + project.properties["hostname"] = InetAddress.getLocalHost().getHostName()
271 + </source>
272 + </configuration>
273 + </execution>
274 + </executions>
275 + </plugin>
276 + <plugin>
277 + <groupId>org.apache.maven.plugins</groupId>
278 + <artifactId>maven-dependency-plugin</artifactId>
279 + <version>2.8</version>
280 + <executions>
281 + <execution>
282 + <id>build-classpath</id>
283 + <phase>compile</phase>
284 + <goals>
285 + <goal>build-classpath</goal>
286 + </goals>
287 + <configuration>
288 + <outputFile>${project.basedir}/.javacp.${hostname}</outputFile>
289 + </configuration>
290 + </execution>
291 + </executions>
292 + </plugin>
293 + <plugin>
294 + <groupId>org.codehaus.mojo</groupId>
295 + <artifactId>cobertura-maven-plugin</artifactId>
296 + <version>${cobertura-maven-plugin.version}</version>
297 + <configuration>
298 + <instrumentation>
299 + <ignores>
300 + <ignore>org.slf4j.*</ignore>
301 + </ignores>
302 + <excludes>
303 + <exclude>edu/stanford/ramcloud/**/*.class</exclude>
304 + <exclude>net/floodlightcontroller/**/web/**/*.class</exclude>
305 + </excludes>
306 + </instrumentation>
307 + <quiet>true</quiet>
308 + </configuration>
309 + <executions>
310 + <execution>
311 + <goals>
312 + <goal>clean</goal>
313 + </goals>
314 + </execution>
315 + </executions>
316 + </plugin>
317 + <!-- Note: the findbugs configuration is also in the reporting section -->
318 + <plugin>
319 + <groupId>org.codehaus.mojo</groupId>
320 + <artifactId>findbugs-maven-plugin</artifactId>
321 + <version>${findbugs-plugin.version}</version>
322 + <configuration>
323 + <effort>${findbugs.effort}</effort>
324 + <excludeFilterFile>${findbugs.excludeFilterFile}</excludeFilterFile>
325 + </configuration>
326 + <executions>
327 + <execution>
328 + <id>validate-findbugs</id>
329 + <phase>verify</phase>
330 + <goals>
331 + <goal>check</goal>
332 + </goals>
333 + </execution>
334 + </executions>
335 + </plugin>
336 + <plugin>
337 + <groupId>org.apache.maven.plugins</groupId>
338 + <artifactId>maven-pmd-plugin</artifactId>
339 + <version>3.1</version>
340 + <configuration>
341 + <!--
342 + Note: Exclusion definition exists in multiple places.
343 + - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
344 + - In file conf/checkstyle/onos_suppressions.xml
345 + - maven-pmd-plugin configuration in pom.xml
346 + (under build and reporting)
347 + -->
348 + <excludes>
349 + <exclude>**/datastore/serializers/**</exclude>
350 + <exclude>**/edu/stanford/**</exclude>
351 + <exclude>**/net/floodlightcontroller/**</exclude>
352 + </excludes>
353 + <rulesets>
354 + <ruleset>${basedir}/conf/pmd/onos_ruleset.xml</ruleset>
355 + </rulesets>
356 + </configuration>
357 + <executions>
358 + <execution>
359 + <id>validate-pmd</id>
360 + <phase>verify</phase>
361 + <goals>
362 + <!-- Uncomment this goal to make the build fail on pmd errors -->
363 + <!--<goal>check</goal>-->
364 + </goals>
365 + </execution>
366 + </executions>
367 + </plugin>
368 + </plugins>
369 + <pluginManagement>
370 + <plugins>
371 + <!--This plugin's configuration is used to store Eclipse m2e settings
372 + only. It has no influence on the Maven build itself. -->
373 + <plugin>
374 + <groupId>org.eclipse.m2e</groupId>
375 + <artifactId>lifecycle-mapping</artifactId>
376 + <version>1.0.0</version>
377 + <configuration>
378 + <lifecycleMappingMetadata>
379 + <pluginExecutions>
380 + <pluginExecution>
381 + <pluginExecutionFilter>
382 + <groupId>
383 + org.apache.maven.plugins
384 + </groupId>
385 + <artifactId>
386 + maven-dependency-plugin
387 + </artifactId>
388 + <versionRange>[2.8,)</versionRange>
389 + <goals>
390 + <goal>build-classpath</goal>
391 + </goals>
392 + </pluginExecutionFilter>
393 + <action>
394 + <ignore></ignore>
395 + </action>
396 + </pluginExecution>
397 + <pluginExecution>
398 + <pluginExecutionFilter>
399 + <groupId>org.codehaus.gmaven</groupId>
400 + <artifactId>groovy-maven-plugin</artifactId>
401 + <versionRange>[2.0,)</versionRange>
402 + <goals>
403 + <goal>execute</goal>
404 + </goals>
405 + </pluginExecutionFilter>
406 + <action>
407 + <ignore></ignore>
408 + </action>
409 + </pluginExecution>
410 + </pluginExecutions>
411 + </lifecycleMappingMetadata>
412 + </configuration>
413 + </plugin>
414 + </plugins>
415 + </pluginManagement>
416 + </build>
417 + <!-- for getting visualization reporting -->
418 + <reporting>
419 + <excludeDefaults>true</excludeDefaults>
420 + <outputDirectory>${project.build.directory}/site</outputDirectory>
421 + <plugins>
422 + <plugin>
423 + <groupId>org.apache.maven.plugins</groupId>
424 + <artifactId>maven-project-info-reports-plugin</artifactId>
425 + <version>2.7</version>
426 + <configuration>
427 + <dependencyDetailsEnabled>false</dependencyDetailsEnabled>
428 + <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
429 + </configuration>
430 + <reportSets>
431 + <reportSet>
432 + <reports>
433 + <report>dependencies</report>
434 + <report>scm</report>
435 + </reports>
436 + </reportSet>
437 + </reportSets>
438 + </plugin>
439 + <plugin>
440 + <groupId>org.apache.maven.plugins</groupId>
441 + <artifactId>maven-javadoc-plugin</artifactId>
442 + <version>2.9.1</version>
443 + <configuration>
444 + <charset>UTF-8</charset>
445 + <locale>en</locale>
446 + <author>false</author>
447 + <excludePackageNames>net.floodlightcontroller.*:net.onrc.onos.core.datastore.serializers</excludePackageNames>
448 + </configuration>
449 + </plugin>
450 + <plugin>
451 + <!-- Note: the checkstyle configuration is also in the build section -->
452 + <groupId>org.apache.maven.plugins</groupId>
453 + <artifactId>maven-checkstyle-plugin</artifactId>
454 + <version>${checkstyle-plugin.version}</version>
455 + <configuration>
456 + <configLocation>conf/checkstyle/sun_checks.xml</configLocation>
457 + <!--
458 + Note: Exclusion definition exists in multiple places.
459 + - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
460 + - maven-checkstyle-plugin configuration in pom.xml
461 + - maven-pmd-plugin configuration in pom.xml
462 + (under build and reporting)
463 + -->
464 + <propertiesLocation>${basedir}/conf/checkstyle/checkstyle_maven.properties</propertiesLocation>
465 + <includeTestSourceDirectory>true</includeTestSourceDirectory>
466 + </configuration>
467 + <reportSets>
468 + <reportSet>
469 + <reports>
470 + <report>checkstyle</report>
471 + </reports>
472 + </reportSet>
473 + </reportSets>
474 + </plugin>
475 + <!-- Note: the findbugs configuration is also in the build section -->
476 + <plugin>
477 + <groupId>org.codehaus.mojo</groupId>
478 + <artifactId>findbugs-maven-plugin</artifactId>
479 + <version>${findbugs-plugin.version}</version>
480 + <configuration>
481 + <effort>${findbugs.effort}</effort>
482 + <excludeFilterFile>${findbugs.excludeFilterFile}</excludeFilterFile>
483 + <reportPlugins>
484 + <plugin>
485 + <groupId>org.codehaus.mojo</groupId>
486 + <artifactId>findbugs-maven-plugin</artifactId>
487 + </plugin>
488 + </reportPlugins>
489 + </configuration>
490 + </plugin>
491 + <plugin>
492 + <groupId>org.apache.maven.plugins</groupId>
493 + <artifactId>maven-pmd-plugin</artifactId>
494 + <version>3.1</version>
495 + <configuration>
496 + <!--
497 + Note: Exclusion definition exists in multiple places.
498 + - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
499 + - In file conf/checkstyle/onos_suppressions.xml
500 + - maven-pmd-plugin configuration in pom.xml
501 + (under build and reporting)
502 + -->
503 + <excludes>
504 + <exclude>**/datastore/serializers/**</exclude>
505 + <exclude>**/edu/stanford/**</exclude>
506 + <exclude>**/net/floodlightcontroller/**</exclude>
507 + </excludes>
508 + <rulesets>
509 + <ruleset>${basedir}/conf/pmd/onos_ruleset.xml</ruleset>
510 + </rulesets>
511 + </configuration>
512 + </plugin>
513 + <plugin>
514 + <groupId>org.apache.maven.plugins</groupId>
515 + <artifactId>maven-jxr-plugin</artifactId>
516 + <version>2.4</version>
517 + </plugin>
518 + <plugin>
519 + <groupId>org.codehaus.mojo</groupId>
520 + <artifactId>cobertura-maven-plugin</artifactId>
521 + <version>${cobertura-maven-plugin.version}</version>
522 + </plugin>
523 + </plugins>
524 + </reporting>
525 + <dependencies>
526 + <!-- ONOS's direct dependencies -->
527 + <dependency>
528 + <groupId>org.apache.felix</groupId>
529 + <artifactId>org.apache.felix.scr.annotations</artifactId>
530 + <version>1.9.6</version>
531 + </dependency>
532 + <dependency>
533 + <groupId>ch.qos.logback</groupId>
534 + <artifactId>logback-classic</artifactId>
535 + <version>1.1.2</version>
536 + </dependency>
537 + <dependency>
538 + <groupId>ch.qos.logback</groupId>
539 + <artifactId>logback-core</artifactId>
540 + <version>1.1.2</version>
541 + </dependency>
542 + <dependency>
543 + <groupId>org.slf4j</groupId>
544 + <artifactId>slf4j-api</artifactId>
545 + <version>1.7.5</version>
546 + </dependency>
547 + <dependency>
548 + <!-- findbugs suppression annotation and @GuardedBy, etc. -->
549 + <groupId>com.google.code.findbugs</groupId>
550 + <artifactId>annotations</artifactId>
551 + <version>${findbugs.version}</version>
552 + </dependency>
553 + <dependency>
554 + <groupId>org.projectfloodlight</groupId>
555 + <artifactId>openflowj</artifactId>
556 + <version>0.3.6-SNAPSHOT</version>
557 + </dependency>
558 + <!-- Floodlight's dependencies -->
559 + <dependency>
560 + <!-- dependency to old version of netty? -->
561 + <groupId>io.netty</groupId>
562 + <artifactId>netty</artifactId>
563 + <version>3.9.2.Final</version>
564 + </dependency>
565 + <!-- Dependency for libraries used for testing -->
566 + <dependency>
567 + <groupId>junit</groupId>
568 + <artifactId>junit</artifactId>
569 + <version>4.11</version>
570 + <scope>test</scope>
571 + </dependency>
572 + <dependency>
573 + <groupId>org.easymock</groupId>
574 + <artifactId>easymock</artifactId>
575 + <version>3.2</version>
576 + <scope>test</scope>
577 + </dependency>
578 + <dependency>
579 + <groupId>org.powermock</groupId>
580 + <artifactId>powermock-module-junit4</artifactId>
581 + <version>${powermock.version}</version>
582 + <scope>test</scope>
583 + </dependency>
584 + <dependency>
585 + <groupId>org.powermock</groupId>
586 + <artifactId>powermock-api-easymock</artifactId>
587 + <version>${powermock.version}</version>
588 + <scope>test</scope>
589 + </dependency>
590 + </dependencies>
591 + <profiles>
592 + <!-- Jenkins by default defines a property BUILD_NUMBER which is used to
593 + enable the profile. -->
594 + <profile>
595 + <id>jenkins</id>
596 + <activation>
597 + <property>
598 + <name>env.BUILD_NUMBER</name>
599 + </property>
600 + </activation>
601 + <build>
602 + <plugins>
603 + <plugin>
604 + <groupId>org.codehaus.mojo</groupId>
605 + <artifactId>cobertura-maven-plugin</artifactId>
606 + <version>${cobertura-maven-plugin.version}</version>
607 + <configuration>
608 + <formats>
609 + <format>xml</format>
610 + </formats>
611 + <quiet>true</quiet>
612 + </configuration>
613 + <executions>
614 + <execution>
615 + <phase>package</phase>
616 + <goals>
617 + <goal>cobertura</goal>
618 + </goals>
619 + </execution>
620 + </executions>
621 + </plugin>
622 + </plugins>
623 + </build>
624 + </profile>
625 + <profile>
626 + <id>all-tests</id>
627 + <build>
628 + <plugins>
629 + <plugin>
630 + <groupId>org.apache.maven.plugins</groupId>
631 + <artifactId>maven-surefire-plugin</artifactId>
632 + <version>${maven.surefire.plugin.version}</version>
633 + <configuration combine.self="merge">
634 + <excludedGroups></excludedGroups>
635 + </configuration>
636 + </plugin>
637 + </plugins>
638 + </build>
639 + </profile>
640 + <profile>
641 + <id>error-prone</id>
642 + <build>
643 + <plugins>
644 + <plugin>
645 + <groupId>org.apache.maven.plugins</groupId>
646 + <artifactId>maven-compiler-plugin</artifactId>
647 + <version>3.1</version>
648 + <configuration>
649 + <compilerArgs combine.children="append">
650 + <!-- FIXME -Xlint:-path required when using findbugs + error-prone -->
651 + <arg>-Xlint:-path</arg>
652 + </compilerArgs>
653 + <!-- Turn on error-prone -->
654 + <compilerId>javac-with-errorprone</compilerId>
655 + <forceJavacCompilerUse>true</forceJavacCompilerUse>
656 + </configuration>
657 + <dependencies combine.children="append">
658 + <dependency>
659 + <groupId>com.google.errorprone</groupId>
660 + <artifactId>error_prone_core</artifactId>
661 + <version>1.1.2</version>
662 + </dependency>
663 + <dependency>
664 + <groupId>org.codehaus.plexus</groupId>
665 + <artifactId>plexus-compiler-javac</artifactId>
666 + <version>2.3</version>
667 + </dependency>
668 + <dependency>
669 + <groupId>org.codehaus.plexus</groupId>
670 + <artifactId>plexus-compiler-javac-errorprone</artifactId>
671 + <version>2.3</version>
672 + </dependency>
673 + </dependencies>
674 + </plugin>
675 + </plugins>
676 + </build>
677 + </profile>
678 + </profiles>
679 +</project>
1 +/**
2 + * Copyright 2011, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl;
19 +
20 +import java.io.IOException;
21 +import java.util.Collection;
22 +import java.util.Date;
23 +import java.util.List;
24 +import java.util.Map;
25 +import java.util.Set;
26 +import java.util.concurrent.Future;
27 +
28 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService;
29 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterException;
30 +import net.onrc.onos.of.ctl.util.OrderedCollection;
31 +
32 +import org.jboss.netty.channel.Channel;
33 +import org.projectfloodlight.openflow.protocol.OFActionType;
34 +import org.projectfloodlight.openflow.protocol.OFCapabilities;
35 +import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
36 +import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
37 +import org.projectfloodlight.openflow.protocol.OFMessage;
38 +import org.projectfloodlight.openflow.protocol.OFPortDesc;
39 +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
40 +import org.projectfloodlight.openflow.protocol.OFPortStatus;
41 +import org.projectfloodlight.openflow.protocol.OFStatsReply;
42 +import org.projectfloodlight.openflow.protocol.OFStatsRequest;
43 +import org.projectfloodlight.openflow.protocol.OFVersion;
44 +import org.projectfloodlight.openflow.types.U64;
45 +
46 +
47 +public interface IOFSwitch {
48 +
49 + /**
50 + * OF1.3 switches should support role-request messages as in the 1.3 spec.
51 + * OF1.0 switches may or may not support the Nicira role request extensions.
52 + * To indicate the support, this property should be set by the associated
53 + * OF1.0 switch driver in the net.onrc.onos.core.drivermanager package.
54 + * The property will be ignored for OF1.3 switches.
55 + */
56 + public static final String SWITCH_SUPPORTS_NX_ROLE = "supportsNxRole";
57 +
58 +
59 + //************************
60 + // Channel related
61 + //************************
62 +
63 + /**
64 + * Disconnects the switch by closing the TCP connection. Results in a call
65 + * to the channel handler's channelDisconnected method for cleanup
66 + * @throws IOException
67 + */
68 + public void disconnectSwitch();
69 +
70 + /**
71 + * Writes to the OFMessage to the output stream.
72 + * The message will be handed to the floodlightProvider for possible filtering
73 + * and processing by message listeners
74 + *
75 + * @param m
76 + * @param bc
77 + * @throws IOException
78 + */
79 + public void write(OFMessage m) throws IOException;
80 +
81 + /**
82 + * Writes the list of messages to the output stream.
83 + * The message will be handed to the floodlightProvider for possible filtering
84 + * and processing by message listeners.
85 + *
86 + * @param msglist
87 + * @param bc
88 + * @throws IOException
89 + */
90 + public void write(List<OFMessage> msglist) throws IOException;
91 +
92 + /**
93 + * Gets the date the switch connected to this controller.
94 + *
95 + * @return the date
96 + */
97 + public Date getConnectedSince();
98 +
99 + /**
100 + * Gets the next available transaction id.
101 + *
102 + * @return the next transaction ID
103 + */
104 + public int getNextTransactionId();
105 +
106 + /**
107 + * Checks if the switch is still connected.
108 + * Only call while holding processMessageLock
109 + *
110 + * @return whether the switch is still disconnected
111 + */
112 + public boolean isConnected();
113 +
114 + /**
115 + * Sets whether the switch is connected.
116 + * Only call while holding modifySwitchLock
117 + *
118 + * @param connected whether the switch is connected
119 + */
120 + public void setConnected(boolean connected);
121 +
122 + /**
123 + * Flushes all flows queued for this switch in the current thread.
124 + * NOTE: The contract is limited to the current thread
125 + */
126 + public void flush();
127 +
128 + /**
129 + * Sets the Netty Channel this switch instance is associated with.
130 + * <p>
131 + * Called immediately after instantiation
132 + *
133 + * @param channel the channel
134 + */
135 + public void setChannel(Channel channel);
136 +
137 + //************************
138 + // Switch features related
139 + //************************
140 +
141 + /**
142 + * Gets the datapathId of the switch.
143 + *
144 + * @return the switch buffers
145 + */
146 + public long getId();
147 +
148 + /**
149 + * Gets a string version of the ID for this switch.
150 + *
151 + * @return string version of the ID
152 + */
153 + public String getStringId();
154 +
155 + /**
156 + * Gets the number of buffers.
157 + *
158 + * @return the number of buffers
159 + */
160 + public int getNumBuffers();
161 +
162 + public Set<OFCapabilities> getCapabilities();
163 +
164 + public byte getNumTables();
165 +
166 + /**
167 + * Returns an OFDescStatsReply message object. Use the methods contained
168 + * to retrieve switch descriptions for Manufacturer, Hw/Sw version etc.
169 + */
170 + public OFDescStatsReply getSwitchDescription();
171 +
172 + /**
173 + * Cancel features reply with a specific transaction ID.
174 + * @param transactionId the transaction ID
175 + */
176 + public void cancelFeaturesReply(int transactionId);
177 +
178 + /**
179 + * Gets the OFActionType set.
180 + * <p>
181 + * getActions has relevance only for an OpenFlow 1.0 switch.
182 + * For OF1.3, each table can support different actions
183 + *
184 + * @return the action set
185 + */
186 + public Set<OFActionType> getActions();
187 +
188 + public void setOFVersion(OFVersion ofv);
189 +
190 + public OFVersion getOFVersion();
191 +
192 +
193 + //************************
194 + // Switch port related
195 + //************************
196 +
197 + /**
198 + * the type of change that happened to an open flow port.
199 + */
200 + public enum PortChangeType {
201 + /** Either a new port has been added by the switch, or we are
202 + * adding a port we just deleted (via a prior notification) due to
203 + * a change in the portNumber-portName mapping.
204 + */
205 + ADD,
206 + /** some other feature of the port has changed (eg. speed)*/
207 + OTHER_UPDATE,
208 + /** Either a port has been deleted by the switch, or we are deleting
209 + * a port whose portNumber-portName mapping has changed. Note that in
210 + * the latter case, a subsequent notification will be sent out to add a
211 + * port with the new portNumber-portName mapping.
212 + */
213 + DELETE,
214 + /** Port is up (i.e. enabled). Presumably an earlier notification had
215 + * indicated that it was down. To be UP implies that the port is
216 + * administratively considered UP (see ofp_port_config) AND the port
217 + * link is up AND the port is no longer blocked (see ofp_port_state).
218 + */
219 + UP,
220 + /** Port is down (i.e. disabled). Presumably an earlier notification had
221 + * indicated that it was up, or the port was always up.
222 + * To be DOWN implies that the port has been either
223 + * administratively brought down (see ofp_port_config) OR the port
224 + * link is down OR the port is blocked (see ofp_port_state).
225 + */
226 + DOWN,
227 + }
228 +
229 + /**
230 + * Describes a change of an open flow port.
231 + */
232 + public static class PortChangeEvent {
233 + public final OFPortDesc port;
234 + public final PortChangeType type;
235 + /**
236 + * @param port
237 + * @param type
238 + */
239 + public PortChangeEvent(OFPortDesc port,
240 + PortChangeType type) {
241 + this.port = port;
242 + this.type = type;
243 + }
244 + /* (non-Javadoc)
245 + * @see java.lang.Object#hashCode()
246 + */
247 + @Override
248 + public int hashCode() {
249 + final int prime = 31;
250 + int result = 1;
251 + result = prime * result + ((port == null) ? 0 : port.hashCode());
252 + result = prime * result + ((type == null) ? 0 : type.hashCode());
253 + return result;
254 + }
255 + /* (non-Javadoc)
256 + * @see java.lang.Object#equals(java.lang.Object)
257 + */
258 + @Override
259 + public boolean equals(Object obj) {
260 + if (this == obj) {
261 + return true;
262 + }
263 + if (obj == null) {
264 + return false;
265 + }
266 + if (getClass() != obj.getClass()) {
267 + return false;
268 + }
269 + PortChangeEvent other = (PortChangeEvent) obj;
270 + if (port == null) {
271 + if (other.port != null) {
272 + return false;
273 + }
274 + } else if (!port.equals(other.port)) {
275 + return false;
276 + }
277 + if (type != other.type) {
278 + return false;
279 + }
280 + return true;
281 + }
282 + /* (non-Javadoc)
283 + * @see java.lang.Object#toString()
284 + */
285 + @Override
286 + public String toString() {
287 + return "[" + type + " " + port.toString() + "]";
288 + }
289 + }
290 +
291 +
292 + /**
293 + * Get list of all enabled ports. This will typically be different from
294 + * the list of ports in the OFFeaturesReply, since that one is a static
295 + * snapshot of the ports at the time the switch connected to the controller
296 + * whereas this port list also reflects the port status messages that have
297 + * been received.
298 + *
299 + * @return Unmodifiable list of ports not backed by the underlying collection
300 + */
301 + public Collection<OFPortDesc> getEnabledPorts();
302 +
303 + /**
304 + * Get list of the port numbers of all enabled ports. This will typically
305 + * be different from the list of ports in the OFFeaturesReply, since that
306 + * one is a static snapshot of the ports at the time the switch connected
307 + * to the controller whereas this port list also reflects the port status
308 + * messages that have been received.
309 + *
310 + * @return Unmodifiable list of ports not backed by the underlying collection
311 + */
312 + public Collection<Integer> getEnabledPortNumbers();
313 +
314 + /**
315 + * Retrieve the port object by the port number. The port object
316 + * is the one that reflects the port status updates that have been
317 + * received, not the one from the features reply.
318 + *
319 + * @param portNumber
320 + * @return port object
321 + */
322 + public OFPortDesc getPort(int portNumber);
323 +
324 + /**
325 + * Retrieve the port object by the port name. The port object
326 + * is the one that reflects the port status updates that have been
327 + * received, not the one from the features reply.
328 + *
329 + * @param portName
330 + * @return port object
331 + */
332 + public OFPortDesc getPort(String portName);
333 +
334 + /**
335 + * Add or modify a switch port. This is called by the core controller
336 + * code in response to a OFPortStatus message. It should not typically be
337 + * called by other floodlight applications.
338 + *
339 + * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow
340 + * spec is not clear on whether portNames are portNumbers are considered
341 + * authoritative identifiers. We treat portNames <-> portNumber mappings
342 + * as fixed. If they change, we delete all previous conflicting ports and
343 + * add all new ports.
344 + *
345 + * @param ps the port status message
346 + * @return the ordered Collection of changes "applied" to the old ports
347 + * of the switch according to the PortStatus message. A single PortStatus
348 + * message can result in multiple changes.
349 + * If portName <-> portNumber mappings have
350 + * changed, the iteration order ensures that delete events for old
351 + * conflicting appear before before events adding new ports
352 + */
353 + public OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps);
354 +
355 + /**
356 + * Get list of all ports. This will typically be different from
357 + * the list of ports in the OFFeaturesReply, since that one is a static
358 + * snapshot of the ports at the time the switch connected to the controller
359 + * whereas this port list also reflects the port status messages that have
360 + * been received.
361 + *
362 + * @return Unmodifiable list of ports
363 + */
364 + public Collection<OFPortDesc> getPorts();
365 +
366 + /**
367 + * @param portName
368 + * @return Whether a port is enabled per latest port status message
369 + * (not configured down nor link down nor in spanning tree blocking state)
370 + */
371 + public boolean portEnabled(int portName);
372 +
373 + /**
374 + * @param portNumber
375 + * @return Whether a port is enabled per latest port status message
376 + * (not configured down nor link down nor in spanning tree blocking state)
377 + */
378 + public boolean portEnabled(String portName);
379 +
380 + /**
381 + * Compute the changes that would be required to replace the old ports
382 + * of this switch with the new ports.
383 + * @param ports new ports to set
384 + * @return the ordered collection of changes "applied" to the old ports
385 + * of the switch in order to set them to the new set.
386 + * If portName <-> portNumber mappings have
387 + * changed, the iteration order ensures that delete events for old
388 + * conflicting appear before before events adding new ports
389 + */
390 + public OrderedCollection<PortChangeEvent>
391 + comparePorts(Collection<OFPortDesc> ports);
392 +
393 + /**
394 + * Replace the ports of this switch with the given ports.
395 + * @param ports new ports to set
396 + * @return the ordered collection of changes "applied" to the old ports
397 + * of the switch in order to set them to the new set.
398 + * If portName <-> portNumber mappings have
399 + * changed, the iteration order ensures that delete events for old
400 + * conflicting appear before before events adding new ports
401 + */
402 + public OrderedCollection<PortChangeEvent>
403 + setPorts(Collection<OFPortDesc> ports);
404 +
405 +// XXX S The odd use of providing an API call to 'set ports' (above) would
406 +// logically suggest that there should be a way to delete or unset the ports.
407 +// Right now we forbid this. We should probably not use setPorts too.
408 +//
409 +// /**
410 +// * Delete a port for the switch. This is called by the core controller
411 +// * code in response to a OFPortStatus message. It should not typically be
412 +// * called by other floodlight applications.
413 +// *
414 +// * @param portNumber
415 +// */
416 +// public void deletePort(short portNumber);
417 +//
418 +// /**
419 +// * Delete a port for the switch. This is called by the core controller
420 +// * code in response to a OFPortStatus message. It should not typically be
421 +// * called by other floodlight applications.
422 +// *
423 +// * @param portName
424 +// */
425 +// public void deletePort(String portName);
426 +
427 +
428 + //*******************************************
429 + // IOFSwitch object attributes
430 + //************************
431 +
432 + /**
433 + * Gets attributes of this switch.
434 + *
435 + * @return attributes of the switch
436 + */
437 + public Map<Object, Object> getAttributes();
438 +
439 + /**
440 + * Checks if a specific switch property exists for this switch.
441 + *
442 + * @param name name of property
443 + * @return value for name
444 + */
445 + boolean hasAttribute(String name);
446 +
447 + /**
448 + * Gets properties for switch specific behavior.
449 + *
450 + * @param name name of property
451 + * @return 'value' for 'name', or null if no entry for 'name' exists
452 + */
453 + Object getAttribute(String name);
454 +
455 + /**
456 + * Sets properties for switch specific behavior.
457 + *
458 + * @param name name of property
459 + * @param value value for name
460 + */
461 + void setAttribute(String name, Object value);
462 +
463 + /**
464 + * Removes properties for switch specific behavior.
465 + *
466 + * @param name name of property
467 + * @return current value for name or null (if not present)
468 + */
469 + Object removeAttribute(String name);
470 +
471 + //************************
472 + // Switch statistics
473 + //************************
474 +
475 + /**
476 + * Delivers the statistics future reply.
477 + *
478 + * @param reply the reply to deliver
479 + */
480 + public void deliverStatisticsReply(OFMessage reply);
481 +
482 + /**
483 + * Cancels the statistics reply with the given transaction ID.
484 + *
485 + * @param transactionId the transaction ID
486 + */
487 + public void cancelStatisticsReply(int transactionId);
488 +
489 + /**
490 + * Cancels all statistics replies.
491 + */
492 + public void cancelAllStatisticsReplies();
493 +
494 + /**
495 + * Gets a Future object that can be used to retrieve the asynchronous.
496 + * OFStatisticsReply when it is available.
497 + *
498 + * @param request statistics request
499 + * @return Future object wrapping OFStatisticsReply
500 + * @throws IOException
501 + */
502 + public Future<List<OFStatsReply>> getStatistics(OFStatsRequest<?> request)
503 + throws IOException;
504 +
505 + //************************
506 + // Switch other utilities
507 + //************************
508 +
509 + /**
510 + * Clears all flowmods on this switch.
511 + */
512 + public void clearAllFlowMods();
513 +
514 + /**
515 + * Gets the current role of this controller for this IOFSwitch.
516 + */
517 + public Role getRole();
518 +
519 + /**
520 + * Sets this controller's Role for this IOFSwitch to role.
521 + *
522 + * @param role
523 + */
524 + public void setRole(Role role);
525 +
526 + /**
527 + * Gets the next generation ID.
528 + * <p>
529 + * Note: relevant for role request messages in OF1.3
530 + *
531 + * @return next generation ID
532 + */
533 + public U64 getNextGenerationId();
534 +
535 +
536 + /**
537 + * Set debug counter service for per-switch counters.
538 + * Called immediately after instantiation.
539 + * @param debugCounters
540 + * @throws CounterException
541 + */
542 + public void setDebugCounterService(IDebugCounterService debugCounter)
543 + throws CounterException;
544 +
545 + /**
546 + * Start this switch driver's sub handshake. This might be a no-op but
547 + * this method must be called at least once for the switch to be become
548 + * ready.
549 + * This method must only be called from the I/O thread
550 + * @throws IOException
551 + * @throws SwitchDriverSubHandshakeAlreadyStarted if the sub-handshake has
552 + * already been started
553 + */
554 + public void startDriverHandshake() throws IOException;
555 +
556 + /**
557 + * Check if the sub-handshake for this switch driver has been completed.
558 + * This method can only be called after startDriverHandshake()
559 + *
560 + * This methods must only be called from the I/O thread
561 + * @return true if the sub-handshake has been completed. False otherwise
562 + * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has
563 + * not been called yet.
564 + */
565 + public boolean isDriverHandshakeComplete();
566 +
567 + /**
568 + * Pass the given OFMessage to the driver as part of this driver's
569 + * sub-handshake. Must not be called after the handshake has been completed
570 + * This methods must only be called from the I/O thread
571 + * @param m The message that the driver should process
572 + * @throws SwitchDriverSubHandshakeCompleted if isDriverHandshake() returns
573 + * false before this method call
574 + * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has
575 + * not been called yet.
576 + */
577 + public void processDriverHandshakeMessage(OFMessage m);
578 +
579 + /**
580 + * Set the flow table full flag in the switch.
581 + * XXX S Rethink this for multiple tables
582 + */
583 + public void setTableFull(boolean isFull);
584 +
585 + /**
586 + * Save the features reply for this switch.
587 + *
588 + * @param featuresReply
589 + */
590 + public void setFeaturesReply(OFFeaturesReply featuresReply);
591 +
592 + /**
593 + * Save the portset for this switch.
594 + *
595 + * @param portDescReply
596 + */
597 + public void setPortDescReply(OFPortDescStatsReply portDescReply);
598 +
599 + //************************
600 + // Message handling
601 + //************************
602 + /**
603 + * Handle the message coming from the dataplane.
604 + *
605 + * @param m the actual message
606 + */
607 + public void handleMessage(OFMessage m);
608 +
609 +
610 +}
1 +package net.onrc.onos.of.ctl;
2 +
3 +import org.projectfloodlight.openflow.protocol.OFVersion;
4 +
5 +import net.onrc.onos.of.ctl.registry.IControllerRegistry;
6 +
7 +/**
8 + * Interface to passed to controller class in order to allow
9 + * it to spawn the appropriate type of switch and furthermore
10 + * specify a registry object (ie. ZooKeeper).
11 + *
12 + */
13 +public interface IOFSwitchManager {
14 +
15 + /**
16 + * Given a description string for a switch spawn the
17 + * concrete representation of that switch.
18 + *
19 + * @param mfr manufacturer description
20 + * @param hwDesc hardware description
21 + * @param swDesc software description
22 + * @param ofv openflow version
23 + * @return A switch of type IOFSwitch.
24 + */
25 + public IOFSwitch getSwitchImpl(String mfr, String hwDesc, String swDesc, OFVersion ofv);
26 +
27 + /**
28 + * Returns the mastership registry used during controller-switch role election.
29 + * @return the registry
30 + */
31 + public IControllerRegistry getRegistry();
32 +
33 +}
1 +package net.onrc.onos.of.ctl;
2 +
3 +import org.projectfloodlight.openflow.protocol.OFControllerRole;
4 +
5 +/**
6 + * The role of the controller as it pertains to a particular switch.
7 + * Note that this definition of the role enum is different from the
8 + * OF1.3 definition. It is maintained here to be backward compatible to
9 + * earlier versions of the controller code. This enum is translated
10 + * to the OF1.3 enum, before role messages are sent to the switch.
11 + * See sendRoleRequestMessage method in OFSwitchImpl
12 + */
13 +public enum Role {
14 + EQUAL(OFControllerRole.ROLE_EQUAL),
15 + MASTER(OFControllerRole.ROLE_MASTER),
16 + SLAVE(OFControllerRole.ROLE_SLAVE);
17 +
18 + private Role(OFControllerRole nxRole) {
19 + nxRole.ordinal();
20 + }
21 + /*
22 + private static Map<Integer,Role> nxRoleToEnum
23 + = new HashMap<Integer,Role>();
24 + static {
25 + for(Role r: Role.values())
26 + nxRoleToEnum.put(r.toNxRole(), r);
27 + }
28 + public int toNxRole() {
29 + return nxRole;
30 + }
31 + // Return the enum representing the given nxRole or null if no
32 + // such role exists
33 + public static Role fromNxRole(int nxRole) {
34 + return nxRoleToEnum.get(nxRole);
35 + }*/
36 +}
1 +/**
2 + * Copyright 2012, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.annotations;
19 +
20 +import java.lang.annotation.ElementType;
21 +import java.lang.annotation.Target;
22 +
23 +/**
24 + * Annotation used to set the category for log messages for a class.
25 + *
26 + */
27 +@Target({ ElementType.TYPE, ElementType.METHOD })
28 +public @interface LogMessageCategory {
29 +
30 + /**
31 + * The category for the log messages for this class.
32 + *
33 + * @return
34 + */
35 + String value() default "Core";
36 +}
1 +/**
2 + * Copyright 2012, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.annotations;
19 +
20 +import java.lang.annotation.ElementType;
21 +import java.lang.annotation.Target;
22 +
23 +/**
24 + * Annotation used to document log messages. This can be used to generate
25 + * documentation on syslog output.
26 + *
27 + */
28 +@Target({ ElementType.TYPE, ElementType.METHOD })
29 +public @interface LogMessageDoc {
30 + public static final String NO_ACTION = "No action is required.";
31 + public static final String UNKNOWN_ERROR = "An unknown error occured";
32 + public static final String GENERIC_ACTION =
33 + "Examine the returned error or exception and take " +
34 + "appropriate action.";
35 + public static final String CHECK_SWITCH =
36 + "Check the health of the indicated switch. " +
37 + "Test and troubleshoot IP connectivity.";
38 + public static final String CHECK_CONTROLLER =
39 + "Verify controller system health, CPU usage, and memory. " +
40 + "Rebooting the controller node may help if the controller " +
41 + "node is in a distressed state.";
42 + public static final String REPORT_CONTROLLER_BUG =
43 + "This is likely a defect in the controller. Please report this " +
44 + "issue. Restarting the controller or switch may help to " +
45 + "alleviate.";
46 + public static final String REPORT_SWITCH_BUG =
47 + "This is likely a defect in the switch. Please report this " +
48 + "issue. Restarting the controller or switch may help to " +
49 + "alleviate.";
50 +
51 + /**
52 + * The log level for the log message.
53 + *
54 + * @return the log level as a tring
55 + */
56 + String level() default "INFO";
57 +
58 + /**
59 + * The message that will be printed.
60 + *
61 + * @return the message
62 + */
63 + String message() default UNKNOWN_ERROR;
64 +
65 + /**
66 + * An explanation of the meaning of the log message.
67 + *
68 + * @return the explanation
69 + */
70 + String explanation() default UNKNOWN_ERROR;
71 +
72 + /**
73 + * The recommendated action associated with the log message.
74 + *
75 + * @return the recommendation
76 + */
77 + String recommendation() default NO_ACTION;
78 +}
1 +/**
2 + * Copyright 2012, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.annotations;
19 +
20 +import java.lang.annotation.ElementType;
21 +import java.lang.annotation.Target;
22 +
23 +/**
24 + * Annotation used to document log messages. This can be used to generate
25 + * documentation on syslog output. This version allows multiple log messages
26 + * to be documentated on an interface.
27 + *
28 + */
29 +@Target({ ElementType.TYPE, ElementType.METHOD })
30 +public @interface LogMessageDocs {
31 + /**
32 + * A list of {@link LogMessageDoc} elements.
33 + *
34 + * @return the list of log message doc
35 + */
36 + LogMessageDoc[] value();
37 +}
1 +package net.onrc.onos.of.ctl.debugcounter;
2 +
3 +import java.util.ArrayList;
4 +import java.util.Arrays;
5 +import java.util.Collections;
6 +import java.util.HashSet;
7 +import java.util.List;
8 +import java.util.Map;
9 +import java.util.Set;
10 +import java.util.concurrent.ConcurrentHashMap;
11 +import java.util.concurrent.atomic.AtomicInteger;
12 +import java.util.concurrent.atomic.AtomicLong;
13 +
14 +import org.slf4j.Logger;
15 +import org.slf4j.LoggerFactory;
16 +
17 +
18 +import com.google.common.collect.Sets;
19 +
20 +
21 +
22 +/**
23 + * This class implements a central store for all counters used for debugging the
24 + * system. For counters based on traffic-type, see ICounterStoreService.
25 + *
26 + */
27 +public class DebugCounter implements IDebugCounterService {
28 + protected static final Logger log = LoggerFactory.getLogger(DebugCounter.class);
29 +
30 + /**
31 + * registered counters need a counter id.
32 + */
33 + protected AtomicInteger counterIdCounter = new AtomicInteger();
34 +
35 + /**
36 + * The counter value.
37 + */
38 + protected static class MutableLong {
39 + long value = 0;
40 + public void increment() { value += 1; }
41 + public void increment(long incr) { value += incr; }
42 + public long get() { return value; }
43 + public void set(long val) { value = val; }
44 + }
45 +
46 + /**
47 + * protected class to store counter information.
48 + */
49 + public static class CounterInfo {
50 + String moduleCounterHierarchy;
51 + String counterDesc;
52 + CounterType ctype;
53 + String moduleName;
54 + String counterHierarchy;
55 + int counterId;
56 + boolean enabled;
57 + String[] metaData;
58 +
59 + public CounterInfo(int counterId, boolean enabled,
60 + String moduleName, String counterHierarchy,
61 + String desc, CounterType ctype, String... metaData) {
62 + this.moduleCounterHierarchy = moduleName + "/" + counterHierarchy;
63 + this.moduleName = moduleName;
64 + this.counterHierarchy = counterHierarchy;
65 + this.counterDesc = desc;
66 + this.ctype = ctype;
67 + this.counterId = counterId;
68 + this.enabled = enabled;
69 + this.metaData = metaData;
70 + }
71 +
72 + public String getModuleCounterHierarchy() { return moduleCounterHierarchy; }
73 + public String getCounterDesc() { return counterDesc; }
74 + public CounterType getCtype() { return ctype; }
75 + public String getModuleName() { return moduleName; }
76 + public String getCounterHierarchy() { return counterHierarchy; }
77 + public int getCounterId() { return counterId; }
78 + public boolean isEnabled() { return enabled; }
79 + public String[] getMetaData() { return this.metaData.clone(); }
80 + }
81 +
82 + //******************
83 + // Global stores
84 + //******************
85 +
86 + /**
87 + * Counter info for a debug counter.
88 + */
89 + public static class DebugCounterInfo {
90 + CounterInfo cinfo;
91 + AtomicLong cvalue;
92 +
93 + public DebugCounterInfo(CounterInfo cinfo) {
94 + this.cinfo = cinfo;
95 + this.cvalue = new AtomicLong();
96 + }
97 + public CounterInfo getCounterInfo() {
98 + return cinfo;
99 + }
100 + public Long getCounterValue() {
101 + return cvalue.get();
102 + }
103 + }
104 +
105 + /**
106 + * Global debug-counter storage across all threads. These are
107 + * updated from the local per thread counters by the flush counters method.
108 + */
109 + private static final DebugCounterInfo[] ALLCOUNTERS =
110 + new DebugCounterInfo[MAX_COUNTERS];
111 +
112 +
113 + /**
114 + * per module counters, indexed by the module name and storing three levels
115 + * of Counter information in the form of CounterIndexStore.
116 + */
117 + protected ConcurrentHashMap<String, ConcurrentHashMap<String, CounterIndexStore>>
118 + moduleCounters = new ConcurrentHashMap<String,
119 + ConcurrentHashMap<String,
120 + CounterIndexStore>>();
121 +
122 + protected static class CounterIndexStore {
123 + int index;
124 + Map<String, CounterIndexStore> nextLevel;
125 +
126 + public CounterIndexStore(int index, Map<String, CounterIndexStore> cis) {
127 + this.index = index;
128 + this.nextLevel = cis;
129 + }
130 + }
131 +
132 + /**
133 + * fast global cache for counter ids that are currently active.
134 + */
135 + protected Set<Integer> currentCounters = Collections.newSetFromMap(
136 + new ConcurrentHashMap<Integer, Boolean>());
137 +
138 + //******************
139 + // Thread local stores
140 + //******************
141 +
142 + /**
143 + * Thread local storage of counter info.
144 + */
145 + protected static class LocalCounterInfo {
146 + boolean enabled;
147 + MutableLong cvalue;
148 +
149 + public LocalCounterInfo(boolean enabled) {
150 + this.enabled = enabled;
151 + this.cvalue = new MutableLong();
152 + }
153 + }
154 +
155 + /**
156 + * Thread local debug counters used for maintaining counters local to a thread.
157 + */
158 + protected final ThreadLocal<LocalCounterInfo[]> threadlocalCounters =
159 + new ThreadLocal<LocalCounterInfo[]>() {
160 + @Override
161 + protected LocalCounterInfo[] initialValue() {
162 + return new LocalCounterInfo[MAX_COUNTERS];
163 + }
164 + };
165 +
166 + /**
167 + * Thread local cache for counter ids that are currently active.
168 + */
169 + protected final ThreadLocal<Set<Integer>> threadlocalCurrentCounters =
170 + new ThreadLocal<Set<Integer>>() {
171 + @Override
172 + protected Set<Integer> initialValue() {
173 + return new HashSet<Integer>();
174 + }
175 + };
176 +
177 + //*******************************
178 + // IDebugCounter
179 + //*******************************
180 +
181 + protected class CounterImpl implements IDebugCounter {
182 + private final int counterId;
183 +
184 + public CounterImpl(int counterId) {
185 + this.counterId = counterId;
186 + }
187 +
188 + @Override
189 + public void updateCounterWithFlush() {
190 + if (!validCounterId()) {
191 + return;
192 + }
193 + updateCounter(counterId, 1, true);
194 + }
195 +
196 + @Override
197 + public void updateCounterNoFlush() {
198 + if (!validCounterId()) {
199 + return;
200 + }
201 + updateCounter(counterId, 1, false);
202 + }
203 +
204 + @Override
205 + public void updateCounterWithFlush(int incr) {
206 + if (!validCounterId()) {
207 + return;
208 + }
209 + updateCounter(counterId, incr, true);
210 + }
211 +
212 + @Override
213 + public void updateCounterNoFlush(int incr) {
214 + if (!validCounterId()) {
215 + return;
216 + }
217 + updateCounter(counterId, incr, false);
218 + }
219 +
220 + @Override
221 + public long getCounterValue() {
222 + if (!validCounterId()) {
223 + return -1;
224 + }
225 + return ALLCOUNTERS[counterId].cvalue.get();
226 + }
227 +
228 + /**
229 + * Checks if this is a valid counter.
230 + * @return true if the counter id is valid
231 + */
232 + private boolean validCounterId() {
233 + if (counterId < 0 || counterId >= MAX_COUNTERS) {
234 + log.error("Invalid counterId invoked");
235 + return false;
236 + }
237 + return true;
238 + }
239 +
240 + }
241 +
242 + //*******************************
243 + // IDebugCounterService
244 + //*******************************
245 +
246 + @Override
247 + public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
248 + String counterDescription, CounterType counterType,
249 + String... metaData)
250 + throws CounterException {
251 + // check if counter already exists
252 + if (!moduleCounters.containsKey(moduleName)) {
253 + moduleCounters.putIfAbsent(moduleName,
254 + new ConcurrentHashMap<String, CounterIndexStore>());
255 + }
256 + RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
257 + if (rci.allLevelsFound) {
258 + // counter exists
259 + log.info("Counter exists for {}/{} -- resetting counters", moduleName,
260 + counterHierarchy);
261 + resetCounterHierarchy(moduleName, counterHierarchy);
262 + return new CounterImpl(rci.ctrIds[rci.foundUptoLevel - 1]);
263 + }
264 + // check for validity of counter
265 + if (rci.levels.length > MAX_HIERARCHY) {
266 + String err = "Registry of counterHierarchy " + counterHierarchy +
267 + " exceeds max hierachy " + MAX_HIERARCHY + ".. aborting";
268 + throw new MaxHierarchyRegistered(err);
269 + }
270 + if (rci.foundUptoLevel < rci.levels.length - 1) {
271 + StringBuilder sb = new StringBuilder();
272 + for (int i = 0; i <= rci.foundUptoLevel; i++) {
273 + sb.append(rci.levels[i]);
274 + }
275 + String needToRegister = sb.toString();
276 + String err = "Attempting to register hierarchical counterHierarchy " +
277 + counterHierarchy + " but parts of hierarchy missing. " +
278 + "Please register " + needToRegister + " first";
279 + throw new MissingHierarchicalLevel(err);
280 + }
281 +
282 + // get a new counter id
283 + int counterId = counterIdCounter.getAndIncrement();
284 + if (counterId >= MAX_COUNTERS) {
285 + throw new MaxCountersRegistered("max counters reached");
286 + }
287 + // create storage for counter
288 + boolean enabled = (counterType == CounterType.ALWAYS_COUNT) ? true : false;
289 + CounterInfo ci = new CounterInfo(counterId, enabled, moduleName,
290 + counterHierarchy, counterDescription,
291 + counterType, metaData);
292 + ALLCOUNTERS[counterId] = new DebugCounterInfo(ci);
293 +
294 + // account for the new counter in the module counter hierarchy
295 + addToModuleCounterHierarchy(moduleName, counterId, rci);
296 +
297 + // finally add to active counters
298 + if (enabled) {
299 + currentCounters.add(counterId);
300 + }
301 + return new CounterImpl(counterId);
302 + }
303 +
304 + private void updateCounter(int counterId, int incr, boolean flushNow) {
305 + if (counterId < 0 || counterId >= MAX_COUNTERS) {
306 + return;
307 + }
308 +
309 + LocalCounterInfo[] thiscounters = this.threadlocalCounters.get();
310 + if (thiscounters[counterId] == null) {
311 + // seeing this counter for the first time in this thread - create local
312 + // store by consulting global store
313 + DebugCounterInfo dc = ALLCOUNTERS[counterId];
314 + if (dc != null) {
315 + thiscounters[counterId] = new LocalCounterInfo(dc.cinfo.enabled);
316 + if (dc.cinfo.enabled) {
317 + Set<Integer> thisset = this.threadlocalCurrentCounters.get();
318 + thisset.add(counterId);
319 + }
320 + } else {
321 + log.error("updateCounter seen locally for counter {} but no global"
322 + + "storage exists for it yet .. not updating", counterId);
323 + return;
324 + }
325 + }
326 +
327 + // update local store if enabled locally for updating
328 + LocalCounterInfo lc = thiscounters[counterId];
329 + if (lc.enabled) {
330 + lc.cvalue.increment(incr);
331 + if (flushNow) {
332 + DebugCounterInfo dc = ALLCOUNTERS[counterId];
333 + if (dc.cinfo.enabled) {
334 + // globally enabled - flush now
335 + dc.cvalue.addAndGet(lc.cvalue.get());
336 + lc.cvalue.set(0);
337 + } else {
338 + // global counter is disabled - don't flush, disable locally
339 + lc.enabled = false;
340 + Set<Integer> thisset = this.threadlocalCurrentCounters.get();
341 + thisset.remove(counterId);
342 + }
343 + }
344 + }
345 + }
346 +
347 + @Override
348 + public void flushCounters() {
349 + LocalCounterInfo[] thiscounters = this.threadlocalCounters.get();
350 + Set<Integer> thisset = this.threadlocalCurrentCounters.get();
351 + ArrayList<Integer> temp = new ArrayList<Integer>();
352 +
353 + for (int counterId : thisset) {
354 + LocalCounterInfo lc = thiscounters[counterId];
355 + if (lc.cvalue.get() > 0) {
356 + DebugCounterInfo dc = ALLCOUNTERS[counterId];
357 + if (dc.cinfo.enabled) {
358 + // globally enabled - flush now
359 + dc.cvalue.addAndGet(lc.cvalue.get());
360 + lc.cvalue.set(0);
361 + } else {
362 + // global counter is disabled - don't flush, disable locally
363 + lc.enabled = false;
364 + temp.add(counterId);
365 + }
366 + }
367 + }
368 + for (int cId : temp) {
369 + thisset.remove(cId);
370 + }
371 +
372 + // At this point it is possible that the thread-local set does not
373 + // include a counter that has been enabled and is present in the global set.
374 + // We need to sync thread-local currently enabled set of counterIds with
375 + // the global set.
376 + Sets.SetView<Integer> sv = Sets.difference(currentCounters, thisset);
377 + for (int counterId : sv) {
378 + if (thiscounters[counterId] != null) {
379 + thiscounters[counterId].enabled = true;
380 + thisset.add(counterId);
381 + }
382 + }
383 + }
384 +
385 + @Override
386 + public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
387 + RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
388 + if (!rci.allLevelsFound) {
389 + String missing = rci.levels[rci.foundUptoLevel];
390 + log.error("Cannot reset counter hierarchy - missing counter {}", missing);
391 + return;
392 + }
393 + // reset at this level
394 + ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]].cvalue.set(0);
395 + // reset all levels below
396 + ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
397 + for (int index : resetIds) {
398 + ALLCOUNTERS[index].cvalue.set(0);
399 + }
400 + }
401 +
402 + @Override
403 + public void resetAllCounters() {
404 + RetCtrInfo rci = new RetCtrInfo();
405 + rci.levels = "".split("/");
406 + for (String moduleName : moduleCounters.keySet()) {
407 + ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
408 + for (int index : resetIds) {
409 + ALLCOUNTERS[index].cvalue.set(0);
410 + }
411 + }
412 + }
413 +
414 + @Override
415 + public void resetAllModuleCounters(String moduleName) {
416 + Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
417 + RetCtrInfo rci = new RetCtrInfo();
418 + rci.levels = "".split("/");
419 +
420 + if (target != null) {
421 + ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
422 + for (int index : resetIds) {
423 + ALLCOUNTERS[index].cvalue.set(0);
424 + }
425 + } else {
426 + if (log.isDebugEnabled()) {
427 + log.debug("No module found with name {}", moduleName);
428 + }
429 + }
430 + }
431 +
432 + @Override
433 + public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
434 + RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
435 + if (!rci.allLevelsFound) {
436 + String missing = rci.levels[rci.foundUptoLevel];
437 + log.error("Cannot enable counter - counter not found {}", missing);
438 + return;
439 + }
440 + // enable specific counter
441 + DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
442 + dc.cinfo.enabled = true;
443 + currentCounters.add(dc.cinfo.counterId);
444 + }
445 +
446 + @Override
447 + public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
448 + RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
449 + if (!rci.allLevelsFound) {
450 + String missing = rci.levels[rci.foundUptoLevel];
451 + log.error("Cannot disable counter - counter not found {}", missing);
452 + return;
453 + }
454 + // disable specific counter
455 + DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
456 + if (dc.cinfo.ctype == CounterType.COUNT_ON_DEMAND) {
457 + dc.cinfo.enabled = false;
458 + dc.cvalue.set(0);
459 + currentCounters.remove(dc.cinfo.counterId);
460 + }
461 + }
462 +
463 + @Override
464 + public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
465 + String counterHierarchy) {
466 + RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
467 + if (!rci.allLevelsFound) {
468 + String missing = rci.levels[rci.foundUptoLevel];
469 + log.error("Cannot fetch counter - counter not found {}", missing);
470 + return Collections.emptyList();
471 + }
472 + ArrayList<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
473 + // get counter and all below it
474 + DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
475 + dcilist.add(dc);
476 + ArrayList<Integer> belowIds = getHierarchyBelow(moduleName, rci);
477 + for (int index : belowIds) {
478 + dcilist.add(ALLCOUNTERS[index]);
479 + }
480 + return dcilist;
481 + }
482 +
483 + @Override
484 + public List<DebugCounterInfo> getAllCounterValues() {
485 + List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
486 + RetCtrInfo rci = new RetCtrInfo();
487 + rci.levels = "".split("/");
488 +
489 + for (String moduleName : moduleCounters.keySet()) {
490 + ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
491 + for (int index : resetIds) {
492 + dcilist.add(ALLCOUNTERS[index]);
493 + }
494 + }
495 + return dcilist;
496 + }
497 +
498 + @Override
499 + public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
500 + List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
501 + RetCtrInfo rci = new RetCtrInfo();
502 + rci.levels = "".split("/");
503 +
504 + if (moduleCounters.containsKey(moduleName)) {
505 + ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
506 + for (int index : resetIds) {
507 + dcilist.add(ALLCOUNTERS[index]);
508 + }
509 + }
510 + return dcilist;
511 + }
512 +
513 + @Override
514 + public boolean containsModuleCounterHierarchy(String moduleName,
515 + String counterHierarchy) {
516 + if (!moduleCounters.containsKey(moduleName)) {
517 + return false;
518 + }
519 + RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
520 + return rci.allLevelsFound;
521 + }
522 +
523 + @Override
524 + public boolean containsModuleName(String moduleName) {
525 + return (moduleCounters.containsKey(moduleName)) ? true : false;
526 + }
527 +
528 + @Override
529 + public List<String> getModuleList() {
530 + List<String> retval = new ArrayList<String>();
531 + retval.addAll(moduleCounters.keySet());
532 + return retval;
533 + }
534 +
535 + @Override
536 + public List<String> getModuleCounterList(String moduleName) {
537 + if (!moduleCounters.containsKey(moduleName)) {
538 + return Collections.emptyList();
539 + }
540 +
541 + List<String> retval = new ArrayList<String>();
542 + RetCtrInfo rci = new RetCtrInfo();
543 + rci.levels = "".split("/");
544 +
545 + ArrayList<Integer> cids = getHierarchyBelow(moduleName, rci);
546 + for (int index : cids) {
547 + retval.add(ALLCOUNTERS[index].cinfo.counterHierarchy);
548 + }
549 + return retval;
550 + }
551 +
552 + //*******************************
553 + // Internal Methods
554 + //*******************************
555 +
556 + protected class RetCtrInfo {
557 + boolean allLevelsFound; // counter indices found all the way down the hierarchy
558 + boolean hierarchical; // true if counterHierarchy is hierarchical
559 + int foundUptoLevel;
560 + int[] ctrIds;
561 + String[] levels;
562 +
563 + public RetCtrInfo() {
564 + ctrIds = new int[MAX_HIERARCHY];
565 + for (int i = 0; i < MAX_HIERARCHY; i++) {
566 + ctrIds[i] = -1;
567 + }
568 + }
569 +
570 + @Override
571 + public int hashCode() {
572 + final int prime = 31;
573 + int result = 1;
574 + result = prime * result + getOuterType().hashCode();
575 + result = prime * result + (allLevelsFound ? 1231 : 1237);
576 + result = prime * result + Arrays.hashCode(ctrIds);
577 + result = prime * result + foundUptoLevel;
578 + result = prime * result + (hierarchical ? 1231 : 1237);
579 + result = prime * result + Arrays.hashCode(levels);
580 + return result;
581 + }
582 +
583 + @Override
584 + public boolean equals(Object oth) {
585 + if (!(oth instanceof RetCtrInfo)) {
586 + return false;
587 + }
588 + RetCtrInfo other = (RetCtrInfo) oth;
589 + if (other.allLevelsFound != this.allLevelsFound) {
590 + return false;
591 + }
592 + if (other.hierarchical != this.hierarchical) {
593 + return false;
594 + }
595 + if (other.foundUptoLevel != this.foundUptoLevel) {
596 + return false;
597 + }
598 + if (!Arrays.equals(other.ctrIds, this.ctrIds)) {
599 + return false;
600 + }
601 + if (!Arrays.equals(other.levels, this.levels)) {
602 + return false;
603 + }
604 + return true;
605 + }
606 +
607 + private DebugCounter getOuterType() {
608 + return DebugCounter.this;
609 + }
610 +
611 +
612 +
613 + }
614 +
615 + protected RetCtrInfo getCounterId(String moduleName, String counterHierarchy) {
616 + RetCtrInfo rci = new RetCtrInfo();
617 + Map<String, CounterIndexStore> templevel = moduleCounters.get(moduleName);
618 + rci.levels = counterHierarchy.split("/");
619 + if (rci.levels.length > 1) {
620 + rci.hierarchical = true;
621 + }
622 + if (templevel == null) {
623 + log.error("moduleName {} does not exist in debugCounters", moduleName);
624 + return rci;
625 + }
626 +
627 + /*
628 + if (rci.levels.length > MAX_HIERARCHY) {
629 + // chop off all array elems greater that MAX_HIERARCHY
630 + String[] temp = new String[MAX_HIERARCHY];
631 + System.arraycopy(rci.levels, 0, temp, 0, MAX_HIERARCHY);
632 + rci.levels = temp;
633 + }
634 + */
635 + for (int i = 0; i < rci.levels.length; i++) {
636 + if (templevel != null) {
637 + CounterIndexStore cis = templevel.get(rci.levels[i]);
638 + if (cis == null) {
639 + // could not find counterHierarchy part at this level
640 + break;
641 + } else {
642 + rci.ctrIds[i] = cis.index;
643 + templevel = cis.nextLevel;
644 + rci.foundUptoLevel++;
645 + if (i == rci.levels.length - 1) {
646 + rci.allLevelsFound = true;
647 + }
648 + }
649 + } else {
650 + // there are no more levels, which means that some part of the
651 + // counterHierarchy has no corresponding map
652 + break;
653 + }
654 + }
655 + return rci;
656 + }
657 +
658 + protected void addToModuleCounterHierarchy(String moduleName, int counterId,
659 + RetCtrInfo rci) {
660 + Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
661 + if (target == null) {
662 + return;
663 + }
664 + CounterIndexStore cis = null;
665 +
666 + for (int i = 0; i < rci.foundUptoLevel; i++) {
667 + cis = target.get(rci.levels[i]);
668 + target = cis.nextLevel;
669 + }
670 + if (cis != null) {
671 + if (cis.nextLevel == null) {
672 + cis.nextLevel = new ConcurrentHashMap<String, CounterIndexStore>();
673 + }
674 + cis.nextLevel.put(rci.levels[rci.foundUptoLevel],
675 + new CounterIndexStore(counterId, null));
676 + } else {
677 + target.put(rci.levels[rci.foundUptoLevel],
678 + new CounterIndexStore(counterId, null));
679 + }
680 + }
681 +
682 + // given a partial hierarchical counter, return the rest of the hierarchy
683 + protected ArrayList<Integer> getHierarchyBelow(String moduleName, RetCtrInfo rci) {
684 + Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
685 + CounterIndexStore cis = null;
686 + ArrayList<Integer> retval = new ArrayList<Integer>();
687 + if (target == null) {
688 + return retval;
689 + }
690 +
691 + // get to the level given
692 + for (int i = 0; i < rci.foundUptoLevel; i++) {
693 + cis = target.get(rci.levels[i]);
694 + target = cis.nextLevel;
695 + }
696 +
697 + if (target == null || rci.foundUptoLevel == MAX_HIERARCHY) {
698 + // no more levels
699 + return retval;
700 + } else {
701 + // recursively get all ids
702 + getIdsAtLevel(target, retval, rci.foundUptoLevel + 1);
703 + }
704 +
705 + return retval;
706 + }
707 +
708 + protected void getIdsAtLevel(Map<String, CounterIndexStore> hcy,
709 + ArrayList<Integer> retval, int level) {
710 + if (level > MAX_HIERARCHY) {
711 + return;
712 + }
713 + if (hcy == null || retval == null) {
714 + return;
715 + }
716 +
717 + // Can return the counter names as well but for now ids are enough.
718 + for (CounterIndexStore cistemp : hcy.values()) {
719 + retval.add(cistemp.index); // value at this level
720 + if (cistemp.nextLevel != null) {
721 + getIdsAtLevel(cistemp.nextLevel, retval, level + 1);
722 + }
723 + }
724 + }
725 +
726 +}
1 +package net.onrc.onos.of.ctl.debugcounter;
2 +
3 +public interface IDebugCounter {
4 + /**
5 + * Increments the counter by 1 thread-locally, and immediately flushes to
6 + * the global counter storage. This method should be used for counters that
7 + * are updated outside the OF message processing pipeline.
8 + */
9 + void updateCounterWithFlush();
10 +
11 + /**
12 + * Increments the counter by 1 thread-locally. Flushing to the global
13 + * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
14 + * resulting in higher performance. This method should be used for counters
15 + * updated in the OF message processing pipeline.
16 + */
17 + void updateCounterNoFlush();
18 +
19 + /**
20 + * Increments the counter thread-locally by the 'incr' specified, and immediately
21 + * flushes to the global counter storage. This method should be used for counters
22 + * that are updated outside the OF message processing pipeline.
23 + */
24 + void updateCounterWithFlush(int incr);
25 +
26 + /**
27 + * Increments the counter thread-locally by the 'incr' specified. Flushing to the global
28 + * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
29 + * resulting in higher performance. This method should be used for counters
30 + * updated in the OF message processing pipeline.
31 + */
32 + void updateCounterNoFlush(int incr);
33 +
34 + /**
35 + * Retrieve the value of the counter from the global counter store.
36 + */
37 + long getCounterValue();
38 +}
1 +package net.onrc.onos.of.ctl.debugcounter;
2 +
3 +
4 +
5 +import java.util.List;
6 +
7 +import net.onrc.onos.of.ctl.debugcounter.DebugCounter.DebugCounterInfo;
8 +
9 +public interface IDebugCounterService {
10 +
11 + /**
12 + * Different counter types. Counters that are meant to be counted-on-demand
13 + * need to be separately enabled/disabled.
14 + */
15 + public enum CounterType {
16 + ALWAYS_COUNT,
17 + COUNT_ON_DEMAND
18 + }
19 +
20 + /**
21 + * Debug Counter Qualifiers.
22 + */
23 + public static final String CTR_MDATA_WARN = "warn";
24 + public static final String CTR_MDATA_ERROR = "error";
25 + public static final String CTR_MDATA_DROP = "drop";
26 +
27 + /**
28 + * A limit on the maximum number of counters that can be created.
29 + */
30 + public static final int MAX_COUNTERS = 5000;
31 +
32 + /**
33 + * Exception thrown when MAX_COUNTERS have been registered.
34 + */
35 + public class MaxCountersRegistered extends CounterException {
36 + private static final long serialVersionUID = 3173747663719376745L;
37 + String errormsg;
38 + public MaxCountersRegistered(String errormsg) {
39 + this.errormsg = errormsg;
40 + }
41 + @Override
42 + public String getMessage() {
43 + return this.errormsg;
44 + }
45 + }
46 + /**
47 + * Exception thrown when MAX_HIERARCHY has been reached.
48 + */
49 + public class MaxHierarchyRegistered extends CounterException {
50 + private static final long serialVersionUID = 967431358683523871L;
51 + private String errormsg;
52 + public MaxHierarchyRegistered(String errormsg) {
53 + this.errormsg = errormsg;
54 + }
55 + @Override
56 + public String getMessage() {
57 + return this.errormsg;
58 + }
59 + }
60 + /**
61 + * Exception thrown when attempting to register a hierarchical counter
62 + * where higher levels of the hierarchy have not been pre-registered.
63 + */
64 + public class MissingHierarchicalLevel extends CounterException {
65 + private static final long serialVersionUID = 517315311533995739L;
66 + private String errormsg;
67 + public MissingHierarchicalLevel(String errormsg) {
68 + this.errormsg = errormsg;
69 + }
70 + @Override
71 + public String getMessage() {
72 + return this.errormsg;
73 + }
74 + }
75 +
76 + public class CounterException extends Exception {
77 + private static final long serialVersionUID = 2219781500857866035L;
78 + }
79 +
80 + /**
81 + * maximum levels of hierarchy.
82 + * Example of moduleName/counterHierarchy:
83 + * switch/00:00:00:00:01:02:03:04/pktin/drops where
84 + * moduleName ==> "switch" and
85 + * counterHierarchy of 3 ==> "00:00:00:00:01:02:03:04/pktin/drops"
86 + */
87 + public static final int MAX_HIERARCHY = 3;
88 +
89 + /**
90 + * All modules that wish to have the DebugCounterService count for them, must
91 + * register their counters by making this call (typically from that module's
92 + * 'startUp' method). The counter can then be updated, displayed, reset etc.
93 + * using the registered moduleName and counterHierarchy.
94 + *
95 + * @param moduleName the name of the module which is registering the
96 + * counter eg. linkdiscovery or controller or switch
97 + * @param counterHierarchy the hierarchical counter name specifying all
98 + * the hierarchical levels that come above it.
99 + * For example: to register a drop counter for
100 + * packet-ins from a switch, the counterHierarchy
101 + * can be "00:00:00:00:01:02:03:04/pktin/drops"
102 + * It is necessary that counters in hierarchical levels
103 + * above have already been pre-registered - in this
104 + * example: "00:00:00:00:01:02:03:04/pktin" and
105 + * "00:00:00:00:01:02:03:04"
106 + * @param counterDescription a descriptive string that gives more information
107 + * of what the counter is measuring. For example,
108 + * "Measures the number of incoming packets seen by
109 + * this module".
110 + * @param counterType One of CounterType. On-demand counter types
111 + * need to be explicitly enabled/disabled using other
112 + * methods in this API -- i.e. registering them is
113 + * not enough to start counting.
114 + * @param metaData variable arguments that qualify a counter
115 + * eg. warn, error etc.
116 + * @return IDebugCounter with update methods that can be
117 + * used to update a counter.
118 + * @throws MaxCountersRegistered
119 + * @throws MaxHierarchyRegistered
120 + * @throws MissingHierarchicalLevel
121 + */
122 + public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
123 + String counterDescription, CounterType counterType,
124 + String... metaData)
125 + throws CounterException;
126 +
127 + /**
128 + * Flush all thread-local counter values (from the current thread)
129 + * to the global counter store. This method is not intended for use by any
130 + * module. It's typical usage is from floodlight core and it is meant
131 + * to flush those counters that are updated in the packet-processing pipeline,
132 + * typically with the 'updateCounterNoFlush" methods in IDebugCounter.
133 + */
134 + public void flushCounters();
135 +
136 + /**
137 + * Resets the value of counters in the hierarchy to zero. Note that the reset
138 + * applies to the level of counter hierarchy specified AND ALL LEVELS BELOW it
139 + * in the hierarchy.
140 + * For example: If a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops"
141 + * specifying a reset hierarchy: "00:00:00:00:01:02:03:04"
142 + * will reset all counters for the switch dpid specified;
143 + * while specifying a reset hierarchy: ""00:00:00:00:01:02:03:04/pktin"
144 + * will reset the pktin counter and all levels below it (like drops)
145 + * for the switch dpid specified.
146 + */
147 + void resetCounterHierarchy(String moduleName, String counterHierarchy);
148 +
149 + /**
150 + * Resets the values of all counters in the system.
151 + */
152 + public void resetAllCounters();
153 +
154 + /**
155 + * Resets the values of all counters belonging
156 + * to a module with the given 'moduleName'.
157 + */
158 + public void resetAllModuleCounters(String moduleName);
159 +
160 + /**
161 + * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
162 + * enable counting on the counter. Note that this step is necessary to start
163 + * counting for these counter types - merely registering the counter is not
164 + * enough (as is the case for CounterType.ALWAYS_COUNT). Newly
165 + * enabled counters start from an initial value of zero.
166 + *
167 + * Enabling a counter in a counterHierarchy enables only THAT counter. It
168 + * does not enable any other part of the counterHierarchy. For example, if
169 + * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the
170 + * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then enabling
171 + * the 'pktin' counter by specifying the counterHierarchy as
172 + * "00:00:00:00:01:02:03:04/pktin" does NOT enable the 'drops' counter.
173 + */
174 + public void enableCtrOnDemand(String moduleName, String counterHierarchy);
175 +
176 + /**
177 + * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
178 + * enable counting on the counter. Note that disabling a counter results in a loss
179 + * of the counter value. When re-enabled the counter will restart from zero.
180 + *
181 + * Disabling a counter in a counterHierarchy disables only THAT counter. It
182 + * does not disable any other part of the counterHierarchy. For example, if
183 + * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the
184 + * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then disabling
185 + * the 'pktin' counter by specifying the counterHierarchy as
186 + * "00:00:00:00:01:02:03:04/pktin" does NOT disable the 'drops' counter.
187 + */
188 + public void disableCtrOnDemand(String moduleName, String counterHierarchy);
189 +
190 + /**
191 + * Get counter value and associated information for the specified counterHierarchy.
192 + * Note that information on the level of counter hierarchy specified
193 + * AND ALL LEVELS BELOW it in the hierarchy will be returned.
194 + *
195 + * For example,
196 + * if a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", then
197 + * specifying a counterHierarchy of "00:00:00:00:01:02:03:04/pktin" in the
198 + * get call will return information on the 'pktin' as well as the 'drops'
199 + * counters for the switch dpid specified.
200 + *
201 + * @return A list of DebugCounterInfo or an empty list if the counter
202 + * could not be found
203 + */
204 + public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
205 + String counterHierarchy);
206 +
207 + /**
208 + * Get counter values and associated information for all counters in the
209 + * system.
210 + *
211 + * @return the list of values/info or an empty list
212 + */
213 + public List<DebugCounterInfo> getAllCounterValues();
214 +
215 + /**
216 + * Get counter values and associated information for all counters associated
217 + * with a module.
218 + *
219 + * @param moduleName
220 + * @return the list of values/info or an empty list
221 + */
222 + public List<DebugCounterInfo> getModuleCounterValues(String moduleName);
223 +
224 + /**
225 + * Convenience method to figure out if the the given 'counterHierarchy' corresponds
226 + * to a registered counterHierarchy for 'moduleName'. Note that the counter may or
227 + * may not be enabled for counting, but if it is registered the method will
228 + * return true.
229 + *
230 + * @param param
231 + * @return false if moduleCounterHierarchy is not a registered counter
232 + */
233 + public boolean containsModuleCounterHierarchy(String moduleName,
234 + String counterHierarchy);
235 +
236 + /**
237 + * Convenience method to figure out if the the given 'moduleName' corresponds
238 + * to a registered moduleName or not. Note that the module may or may not have
239 + * a counter enabled for counting, but if it is registered the method will
240 + * return true.
241 + *
242 + * @param param
243 + * @return false if moduleName is not a registered counter
244 + */
245 + public boolean containsModuleName(String moduleName);
246 +
247 + /**
248 + * Returns a list of moduleNames registered for debug counters or an empty
249 + * list if no counters have been registered in the system.
250 + */
251 + public List<String> getModuleList();
252 +
253 + /**
254 + * Returns a list of all counters registered for a specific moduleName
255 + * or a empty list.
256 + */
257 + public List<String> getModuleCounterList(String moduleName);
258 +
259 +
260 +}
1 +package net.onrc.onos.of.ctl.debugcounter;
2 +
3 +import java.util.Collections;
4 +import java.util.List;
5 +
6 +import net.onrc.onos.of.ctl.debugcounter.DebugCounter.DebugCounterInfo;
7 +
8 +public class NullDebugCounter implements IDebugCounterService {
9 +
10 + @Override
11 + public void flushCounters() {
12 +
13 + }
14 +
15 + @Override
16 + public void resetAllCounters() {
17 +
18 + }
19 +
20 + @Override
21 + public void resetAllModuleCounters(String moduleName) {
22 +
23 + }
24 +
25 +
26 + @Override
27 + public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
28 +
29 + }
30 +
31 + @Override
32 + public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
33 +
34 + }
35 +
36 + @Override
37 + public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
38 +
39 + }
40 +
41 + @Override
42 + public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
43 + String counterHierarchy) {
44 + return Collections.emptyList();
45 + }
46 +
47 + @Override
48 + public List<DebugCounterInfo> getAllCounterValues() {
49 + return Collections.emptyList();
50 + }
51 +
52 + @Override
53 + public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
54 + return Collections.emptyList();
55 + }
56 +
57 + @Override
58 + public boolean containsModuleCounterHierarchy(String moduleName,
59 + String counterHierarchy) {
60 + return false;
61 + }
62 +
63 + @Override
64 + public boolean containsModuleName(String moduleName) {
65 + return false;
66 + }
67 +
68 + @Override
69 + public
70 + IDebugCounter
71 + registerCounter(String moduleName, String counterHierarchy,
72 + String counterDescription,
73 + CounterType counterType, String... metaData)
74 + throws MaxCountersRegistered {
75 + return new NullCounterImpl();
76 + }
77 +
78 + @Override
79 + public List<String> getModuleList() {
80 + return Collections.emptyList();
81 + }
82 +
83 + @Override
84 + public List<String> getModuleCounterList(String moduleName) {
85 + return Collections.emptyList();
86 + }
87 +
88 + public static class NullCounterImpl implements IDebugCounter {
89 +
90 + @Override
91 + public void updateCounterWithFlush() {
92 +
93 + }
94 +
95 + @Override
96 + public void updateCounterNoFlush() {
97 +
98 + }
99 +
100 + @Override
101 + public void updateCounterWithFlush(int incr) {
102 + }
103 +
104 + @Override
105 + public void updateCounterNoFlush(int incr) {
106 +
107 + }
108 +
109 + @Override
110 + public long getCounterValue() {
111 + return -1;
112 + }
113 +
114 + }
115 +
116 +}
1 +/**
2 + * Copyright 2011, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.internal;
19 +
20 +import java.lang.management.ManagementFactory;
21 +import java.lang.management.RuntimeMXBean;
22 +import java.net.InetSocketAddress;
23 +import java.net.UnknownHostException;
24 +import java.util.Collections;
25 +import java.util.HashMap;
26 +import java.util.HashSet;
27 +import java.util.Map;
28 +import java.util.Set;
29 +import java.util.concurrent.ConcurrentHashMap;
30 +import java.util.concurrent.Executors;
31 +
32 +import net.onrc.onos.of.ctl.IOFSwitchManager;
33 +import net.onrc.onos.of.ctl.Role;
34 +import net.onrc.onos.of.ctl.annotations.LogMessageDoc;
35 +import net.onrc.onos.of.ctl.annotations.LogMessageDocs;
36 +import net.onrc.onos.of.ctl.debugcounter.DebugCounter;
37 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounter;
38 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService;
39 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterException;
40 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterType;
41 +import net.onrc.onos.of.ctl.internal.OFChannelHandler.RoleRecvStatus;
42 +import net.onrc.onos.of.ctl.registry.IControllerRegistry;
43 +import net.onrc.onos.of.ctl.registry.RegistryException;
44 +import net.onrc.onos.of.ctl.registry.IControllerRegistry.ControlChangeCallback;
45 +import net.onrc.onos.of.ctl.util.Dpid;
46 +import net.onrc.onos.of.ctl.util.DummySwitchForTesting;
47 +import net.onrc.onos.of.ctl.util.InstanceId;
48 +import net.onrc.onos.of.ctl.IOFSwitch;
49 +import net.onrc.onos.of.ctl.IOFSwitch.PortChangeType;
50 +
51 +import org.apache.felix.scr.annotations.Activate;
52 +import org.apache.felix.scr.annotations.Component;
53 +import org.jboss.netty.bootstrap.ServerBootstrap;
54 +import org.jboss.netty.channel.ChannelPipelineFactory;
55 +import org.jboss.netty.channel.group.ChannelGroup;
56 +import org.jboss.netty.channel.group.DefaultChannelGroup;
57 +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
58 +import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
59 +import org.projectfloodlight.openflow.protocol.OFFactories;
60 +import org.projectfloodlight.openflow.protocol.OFFactory;
61 +import org.projectfloodlight.openflow.protocol.OFPortDesc;
62 +import org.projectfloodlight.openflow.protocol.OFVersion;
63 +import org.projectfloodlight.openflow.util.HexString;
64 +import org.slf4j.Logger;
65 +import org.slf4j.LoggerFactory;
66 +
67 +
68 +/**
69 + * The main controller class. Handles all setup and network listeners
70 + * - Distributed ownership control of switch through IControllerRegistryService
71 + */
72 +@Component(immediate = true)
73 +public class Controller {
74 +
75 + protected static final Logger log = LoggerFactory.getLogger(Controller.class);
76 + static final String ERROR_DATABASE =
77 + "The controller could not communicate with the system database.";
78 + protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
79 + protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
80 +
81 + // connectedSwitches cache contains all connected switch's channelHandlers
82 + // including ones where this controller is a master/equal/slave controller
83 + // as well as ones that have not been activated yet
84 + protected ConcurrentHashMap<Long, OFChannelHandler> connectedSwitches;
85 + // These caches contains only those switches that are active
86 + protected ConcurrentHashMap<Long, IOFSwitch> activeMasterSwitches;
87 + protected ConcurrentHashMap<Long, IOFSwitch> activeEqualSwitches;
88 + // lock to synchronize on, when manipulating multiple caches above
89 + private Object multiCacheLock;
90 +
91 + // The controllerNodeIPsCache maps Controller IDs to their IP address.
92 + // It's only used by handleControllerNodeIPsChanged
93 + protected HashMap<String, String> controllerNodeIPsCache;
94 +
95 + // Module dependencies
96 +
97 + protected IControllerRegistry registryService;
98 + protected IDebugCounterService debugCounters;
99 +
100 +
101 + private IOFSwitchManager switchManager;
102 +
103 + // Configuration options
104 + protected int openFlowPort = 6633;
105 + protected int workerThreads = 0;
106 +
107 + // defined counters
108 + private Counters counters;
109 +
110 + // Start time of the controller
111 + protected long systemStartTime;
112 +
113 + // Flag to always flush flow table on switch reconnect (HA or otherwise)
114 + protected boolean alwaysClearFlowsOnSwAdd = false;
115 + private InstanceId instanceId;
116 +
117 + // Perf. related configuration
118 + protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
119 + protected static final int BATCH_MAX_SIZE = 100;
120 + protected static final boolean ALWAYS_DECODE_ETH = true;
121 +
122 + protected boolean addConnectedSwitch(long dpid, OFChannelHandler h) {
123 + if (connectedSwitches.get(dpid) != null) {
124 + log.error("Trying to add connectedSwitch but found a previous "
125 + + "value for dpid: {}", dpid);
126 + return false;
127 + } else {
128 + log.error("Added switch {}", dpid);
129 + connectedSwitches.put(dpid, h);
130 + return true;
131 + }
132 + }
133 +
134 + private boolean validActivation(long dpid) {
135 + if (connectedSwitches.get(dpid) == null) {
136 + log.error("Trying to activate switch but is not in "
137 + + "connected switches: dpid {}. Aborting ..",
138 + HexString.toHexString(dpid));
139 + return false;
140 + }
141 + if (activeMasterSwitches.get(dpid) != null ||
142 + activeEqualSwitches.get(dpid) != null) {
143 + log.error("Trying to activate switch but it is already "
144 + + "activated: dpid {}. Found in activeMaster: {} "
145 + + "Found in activeEqual: {}. Aborting ..", new Object[] {
146 + HexString.toHexString(dpid),
147 + (activeMasterSwitches.get(dpid) == null) ? 'Y' : 'N',
148 + (activeEqualSwitches.get(dpid) == null) ? 'Y' : 'N'});
149 + counters.switchWithSameDpidActivated.updateCounterWithFlush();
150 + return false;
151 + }
152 + return true;
153 + }
154 +
155 + /**
156 + * Called when a switch is activated, with this controller's role as MASTER.
157 + */
158 + protected boolean addActivatedMasterSwitch(long dpid, IOFSwitch sw) {
159 + synchronized (multiCacheLock) {
160 + if (!validActivation(dpid)) {
161 + return false;
162 + }
163 + activeMasterSwitches.put(dpid, sw);
164 + }
165 + //update counters and events
166 + counters.switchActivated.updateCounterWithFlush();
167 +
168 + return true;
169 + }
170 +
171 + /**
172 + * Called when a switch is activated, with this controller's role as EQUAL.
173 + */
174 + protected boolean addActivatedEqualSwitch(long dpid, IOFSwitch sw) {
175 + synchronized (multiCacheLock) {
176 + if (!validActivation(dpid)) {
177 + return false;
178 + }
179 + activeEqualSwitches.put(dpid, sw);
180 + }
181 + //update counters and events
182 + counters.switchActivated.updateCounterWithFlush();
183 + return true;
184 + }
185 +
186 + /**
187 + * Called when this controller's role for a switch transitions from equal
188 + * to master. For 1.0 switches, we internally refer to the role 'slave' as
189 + * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
190 + */
191 + protected void transitionToMasterSwitch(long dpid) {
192 + synchronized (multiCacheLock) {
193 + IOFSwitch sw = activeEqualSwitches.remove(dpid);
194 + if (sw == null) {
195 + log.error("Transition to master called on sw {}, but switch "
196 + + "was not found in controller-cache", dpid);
197 + return;
198 + }
199 + activeMasterSwitches.put(dpid, sw);
200 + }
201 + }
202 +
203 +
204 + /**
205 + * Called when this controller's role for a switch transitions to equal.
206 + * For 1.0 switches, we internally refer to the role 'slave' as
207 + * 'equal'.
208 + */
209 + protected void transitionToEqualSwitch(long dpid) {
210 + synchronized (multiCacheLock) {
211 + IOFSwitch sw = activeMasterSwitches.remove(dpid);
212 + if (sw == null) {
213 + log.error("Transition to equal called on sw {}, but switch "
214 + + "was not found in controller-cache", dpid);
215 + return;
216 + }
217 + activeEqualSwitches.put(dpid, sw);
218 + }
219 +
220 + }
221 +
222 + /**
223 + * Clear all state in controller switch maps for a switch that has
224 + * disconnected from the local controller. Also release control for
225 + * that switch from the global repository. Notify switch listeners.
226 + */
227 + protected void removeConnectedSwitch(long dpid) {
228 + releaseRegistryControl(dpid);
229 + connectedSwitches.remove(dpid);
230 + IOFSwitch sw = activeMasterSwitches.remove(dpid);
231 + if (sw == null) {
232 + sw = activeEqualSwitches.remove(dpid);
233 + }
234 + if (sw != null) {
235 + sw.cancelAllStatisticsReplies();
236 + sw.setConnected(false); // do we need this?
237 + }
238 + counters.switchDisconnected.updateCounterWithFlush();
239 +
240 + }
241 +
242 + /**
243 + * Indicates that ports on the given switch have changed. Enqueue a
244 + * switch update.
245 + * @param sw
246 + */
247 + protected void notifyPortChanged(long dpid, OFPortDesc port,
248 + PortChangeType changeType) {
249 + if (port == null || changeType == null) {
250 + String msg = String.format("Switch port or changetType must not "
251 + + "be null in port change notification");
252 + throw new NullPointerException(msg);
253 + }
254 + if (connectedSwitches.get(dpid) == null || getSwitch(dpid) == null) {
255 + log.warn("Port change update on switch {} not connected or activated "
256 + + "... Aborting.", HexString.toHexString(dpid));
257 + return;
258 + }
259 +
260 + }
261 +
262 + // ***************
263 + // Getters/Setters
264 + // ***************
265 +
266 +
267 + public synchronized void setIOFSwitchManager(IOFSwitchManager swManager) {
268 + this.switchManager = swManager;
269 + this.registryService = swManager.getRegistry();
270 + }
271 +
272 +
273 + public void setDebugCounter(IDebugCounterService dcs) {
274 + this.debugCounters = dcs;
275 + }
276 +
277 + IDebugCounterService getDebugCounter() {
278 + return this.debugCounters;
279 + }
280 +
281 + // **********************
282 + // Role Handling
283 + // **********************
284 +
285 + /**
286 + * created by ONOS - works with registry service.
287 + */
288 + protected class RoleChangeCallback implements ControlChangeCallback {
289 + @Override
290 + public void controlChanged(long dpidLong, boolean hasControl) {
291 + Dpid dpid = new Dpid(dpidLong);
292 + log.info("Role change callback for switch {}, hasControl {}",
293 + dpid, hasControl);
294 +
295 + Role role = null;
296 +
297 + /*
298 + * issue #229
299 + * Cannot rely on sw.getRole() as it can be behind due to pending
300 + * role changes in the queue. Just submit it and late the
301 + * RoleChanger handle duplicates.
302 + */
303 +
304 + if (hasControl) {
305 + role = Role.MASTER;
306 + } else {
307 + role = Role.EQUAL; // treat the same as Role.SLAVE
308 + }
309 +
310 + OFChannelHandler swCh = connectedSwitches.get(dpid.value());
311 + if (swCh == null) {
312 + log.warn("Switch {} not found in connected switches", dpid);
313 + return;
314 + }
315 +
316 + log.debug("Sending role request {} msg to {}", role, dpid);
317 + swCh.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE);
318 + }
319 + }
320 +
321 + /**
322 + * Submit request to the registry service for mastership of the
323 + * switch.
324 + * @param dpid this datapath to get role for
325 + */
326 + public synchronized void submitRegistryRequest(long dpid) {
327 + if (registryService == null) {
328 + /*
329 + * If we have no registry then simply assign
330 + * mastership to this controller.
331 + */
332 + new RoleChangeCallback().controlChanged(dpid, true);
333 + return;
334 + }
335 + OFChannelHandler h = connectedSwitches.get(dpid);
336 + if (h == null) {
337 + log.error("Trying to request registry control for switch {} "
338 + + "not in connected switches. Aborting.. ",
339 + HexString.toHexString(dpid));
340 + connectedSwitches.get(dpid).disconnectSwitch();
341 + return;
342 + }
343 + //Request control of the switch from the global registry
344 + try {
345 + h.controlRequested = Boolean.TRUE;
346 + registryService.requestControl(dpid, new RoleChangeCallback());
347 + } catch (RegistryException e) {
348 + log.debug("Registry error: {}", e.getMessage());
349 + h.controlRequested = Boolean.FALSE;
350 + }
351 + if (!h.controlRequested) { // XXX what is being attempted here?
352 + // yield to allow other thread(s) to release control
353 + // TODO AAS: this is awful and needs to be fixed
354 + Thread.yield();
355 + // safer to bounce the switch to reconnect here than proceeding further
356 + // XXX S why? can't we just try again a little later?
357 + log.debug("Closing sw:{} because we weren't able to request control " +
358 + "successfully" + dpid);
359 + connectedSwitches.get(dpid).disconnectSwitch();
360 + }
361 + }
362 +
363 + /**
364 + * Relinquish role for the switch.
365 + * @param dpidLong the controlled datapath
366 + */
367 + public synchronized void releaseRegistryControl(long dpidLong) {
368 + OFChannelHandler h = connectedSwitches.get(dpidLong);
369 + if (h == null) {
370 + log.error("Trying to release registry control for switch {} "
371 + + "not in connected switches. Aborting.. ",
372 + HexString.toHexString(dpidLong));
373 + return;
374 + }
375 + if (h.controlRequested) {
376 + registryService.releaseControl(dpidLong);
377 + }
378 + }
379 +
380 +
381 +
382 + // ***************
383 + // IFloodlightProviderService
384 + // ***************
385 +
386 + // FIXME: remove this method
387 + public Map<Long, IOFSwitch> getSwitches() {
388 + return getMasterSwitches();
389 + }
390 +
391 + // FIXME: remove this method
392 + public Map<Long, IOFSwitch> getMasterSwitches() {
393 + return Collections.unmodifiableMap(activeMasterSwitches);
394 + }
395 +
396 +
397 +
398 + public Set<Long> getAllSwitchDpids() {
399 + Set<Long> dpids = new HashSet<Long>();
400 + dpids.addAll(activeMasterSwitches.keySet());
401 + dpids.addAll(activeEqualSwitches.keySet());
402 + return dpids;
403 + }
404 +
405 +
406 + public Set<Long> getAllMasterSwitchDpids() {
407 + Set<Long> dpids = new HashSet<Long>();
408 + dpids.addAll(activeMasterSwitches.keySet());
409 + return dpids;
410 + }
411 +
412 +
413 + public Set<Long> getAllEqualSwitchDpids() {
414 + Set<Long> dpids = new HashSet<Long>();
415 + dpids.addAll(activeEqualSwitches.keySet());
416 + return dpids;
417 + }
418 +
419 +
420 + public IOFSwitch getSwitch(long dpid) {
421 + IOFSwitch sw = null;
422 + sw = activeMasterSwitches.get(dpid);
423 + if (sw != null) {
424 + return sw;
425 + }
426 + sw = activeEqualSwitches.get(dpid);
427 + if (sw != null) {
428 + return sw;
429 + }
430 + return sw;
431 + }
432 +
433 +
434 + public IOFSwitch getMasterSwitch(long dpid) {
435 + return activeMasterSwitches.get(dpid);
436 + }
437 +
438 +
439 + public IOFSwitch getEqualSwitch(long dpid) {
440 + return activeEqualSwitches.get(dpid);
441 + }
442 +
443 +
444 +
445 +
446 +
447 + public OFFactory getOFMessageFactory10() {
448 + return FACTORY10;
449 + }
450 +
451 +
452 + public OFFactory getOFMessageFactory13() {
453 + return FACTORY13;
454 + }
455 +
456 +
457 +
458 + public Map<String, String> getControllerNodeIPs() {
459 + // We return a copy of the mapping so we can guarantee that
460 + // the mapping return is the same as one that will be (or was)
461 + // dispatched to IHAListeners
462 + HashMap<String, String> retval = new HashMap<String, String>();
463 + synchronized (controllerNodeIPsCache) {
464 + retval.putAll(controllerNodeIPsCache);
465 + }
466 + return retval;
467 + }
468 +
469 +
470 + public long getSystemStartTime() {
471 + return (this.systemStartTime);
472 + }
473 +
474 +
475 + public void setAlwaysClearFlowsOnSwAdd(boolean value) {
476 + this.alwaysClearFlowsOnSwAdd = value;
477 + }
478 +
479 +
480 + public InstanceId getInstanceId() {
481 + return instanceId;
482 + }
483 +
484 +
485 + // **************
486 + // Initialization
487 + // **************
488 +
489 + /**
490 + * Tell controller that we're ready to accept switches loop.
491 + *
492 + * @throws IOException
493 + */
494 + @LogMessageDocs({
495 + @LogMessageDoc(message = "Listening for switch connections on {address}",
496 + explanation = "The controller is ready and listening for new" +
497 + " switch connections"),
498 + @LogMessageDoc(message = "Storage exception in controller " +
499 + "updates loop; terminating process",
500 + explanation = ERROR_DATABASE,
501 + recommendation = LogMessageDoc.CHECK_CONTROLLER),
502 + @LogMessageDoc(level = "ERROR",
503 + message = "Exception in controller updates loop",
504 + explanation = "Failed to dispatch controller event",
505 + recommendation = LogMessageDoc.GENERIC_ACTION)
506 + })
507 + public void run() {
508 +
509 + try {
510 + final ServerBootstrap bootstrap = createServerBootStrap();
511 +
512 + bootstrap.setOption("reuseAddr", true);
513 + bootstrap.setOption("child.keepAlive", true);
514 + bootstrap.setOption("child.tcpNoDelay", true);
515 + bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
516 +
517 + ChannelPipelineFactory pfact =
518 + new OpenflowPipelineFactory(this, null);
519 + bootstrap.setPipelineFactory(pfact);
520 + InetSocketAddress sa = new InetSocketAddress(openFlowPort);
521 + final ChannelGroup cg = new DefaultChannelGroup();
522 + cg.add(bootstrap.bind(sa));
523 +
524 + log.info("Listening for switch connections on {}", sa);
525 + } catch (Exception e) {
526 + throw new RuntimeException(e);
527 + }
528 +
529 + }
530 +
531 + private ServerBootstrap createServerBootStrap() {
532 + if (workerThreads == 0) {
533 + return new ServerBootstrap(
534 + new NioServerSocketChannelFactory(
535 + Executors.newCachedThreadPool(),
536 + Executors.newCachedThreadPool()));
537 + } else {
538 + return new ServerBootstrap(
539 + new NioServerSocketChannelFactory(
540 + Executors.newCachedThreadPool(),
541 + Executors.newCachedThreadPool(), workerThreads));
542 + }
543 + }
544 +
545 + public void setConfigParams(Map<String, String> configParams) {
546 + String ofPort = configParams.get("openflowport");
547 + if (ofPort != null) {
548 + this.openFlowPort = Integer.parseInt(ofPort);
549 + }
550 + log.debug("OpenFlow port set to {}", this.openFlowPort);
551 + String threads = configParams.get("workerthreads");
552 + if (threads != null) {
553 + this.workerThreads = Integer.parseInt(threads);
554 + }
555 + log.debug("Number of worker threads set to {}", this.workerThreads);
556 + String controllerId = configParams.get("controllerid");
557 + if (controllerId != null) {
558 + this.instanceId = new InstanceId(controllerId);
559 + } else {
560 + //Try to get the hostname of the machine and use that for controller ID
561 + try {
562 + String hostname = java.net.InetAddress.getLocalHost().getHostName();
563 + this.instanceId = new InstanceId(hostname);
564 + } catch (UnknownHostException e) {
565 + log.warn("Can't get hostname, using the default");
566 + }
567 + }
568 +
569 + log.debug("ControllerId set to {}", this.instanceId);
570 + }
571 +
572 +
573 + /**
574 + * Initialize internal data structures.
575 + */
576 + public void init(Map<String, String> configParams) {
577 + // These data structures are initialized here because other
578 + // module's startUp() might be called before ours
579 + this.activeMasterSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
580 + this.activeEqualSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
581 + this.connectedSwitches = new ConcurrentHashMap<Long, OFChannelHandler>();
582 + this.controllerNodeIPsCache = new HashMap<String, String>();
583 +
584 + setConfigParams(configParams);
585 + this.systemStartTime = System.currentTimeMillis();
586 + this.setDebugCounter(new DebugCounter());
587 + this.counters = new Counters();
588 + this.multiCacheLock = new Object();
589 +
590 +
591 + String option = configParams.get("flushSwitchesOnReconnect");
592 + if (option != null && option.equalsIgnoreCase("true")) {
593 + this.setAlwaysClearFlowsOnSwActivate(true);
594 + log.info("Flush switches on reconnect -- Enabled.");
595 + } else {
596 + this.setAlwaysClearFlowsOnSwActivate(false);
597 + log.info("Flush switches on reconnect -- Disabled");
598 + }
599 + }
600 +
601 + /**
602 + * Startup all of the controller's components.
603 + */
604 + @LogMessageDoc(message = "Waiting for storage source",
605 + explanation = "The system database is not yet ready",
606 + recommendation = "If this message persists, this indicates " +
607 + "that the system database has failed to start. " +
608 + LogMessageDoc.CHECK_CONTROLLER)
609 + public synchronized void startupComponents() {
610 + try {
611 + if (registryService != null) {
612 + registryService.registerController(instanceId.toString());
613 + }
614 + } catch (RegistryException e) {
615 + log.warn("Registry service error: {}", e.getMessage());
616 + }
617 +
618 + // register counters and events
619 + try {
620 + this.counters.createCounters(debugCounters);
621 + } catch (CounterException e) {
622 + log.warn("Counters unavailable: {}", e.getMessage());
623 + }
624 + }
625 +
626 + // **************
627 + // debugCounter registrations
628 + // **************
629 +
630 + public static class Counters {
631 + public static final String PREFIX = "controller";
632 + public IDebugCounter switchActivated;
633 + public IDebugCounter switchWithSameDpidActivated; // warn
634 + public IDebugCounter switchDisconnected;
635 + public IDebugCounter messageReceived;
636 + public IDebugCounter switchDisconnectReadTimeout;
637 + public IDebugCounter switchDisconnectHandshakeTimeout;
638 + public IDebugCounter switchDisconnectIOError;
639 + public IDebugCounter switchDisconnectParseError;
640 + public IDebugCounter switchDisconnectSwitchStateException;
641 + public IDebugCounter rejectedExecutionException;
642 + public IDebugCounter switchDisconnectOtherException;
643 + public IDebugCounter switchConnected;
644 + public IDebugCounter unhandledMessage;
645 + public IDebugCounter packetInWhileSwitchIsSlave;
646 + public IDebugCounter epermErrorWhileSwitchIsMaster;
647 + public IDebugCounter roleReplyTimeout;
648 + public IDebugCounter roleReplyReceived; // expected RoleReply received
649 + public IDebugCounter roleReplyErrorUnsupported;
650 + public IDebugCounter switchCounterRegistrationFailed;
651 +
652 + void createCounters(IDebugCounterService debugCounters) throws CounterException {
653 +
654 + switchActivated =
655 + debugCounters.registerCounter(
656 + PREFIX, "switch-activated",
657 + "A switch connected to this controller is now " +
658 + "in MASTER role",
659 + CounterType.ALWAYS_COUNT);
660 +
661 + switchWithSameDpidActivated = // warn
662 + debugCounters.registerCounter(
663 + PREFIX, "switch-with-same-dpid-activated",
664 + "A switch with the same DPID as another switch " +
665 + "connected to the controller. This can be " +
666 + "caused by multiple switches configured with " +
667 + "the same DPID or by a switch reconnecting very " +
668 + "quickly.",
669 + CounterType.COUNT_ON_DEMAND,
670 + IDebugCounterService.CTR_MDATA_WARN);
671 +
672 + switchDisconnected =
673 + debugCounters.registerCounter(
674 + PREFIX, "switch-disconnected",
675 + "FIXME: switch has disconnected",
676 + CounterType.ALWAYS_COUNT);
677 +
678 + //------------------------
679 + // channel handler counters. Factor them out ??
680 + messageReceived =
681 + debugCounters.registerCounter(
682 + PREFIX, "message-received",
683 + "Number of OpenFlow messages received. Some of " +
684 + "these might be throttled",
685 + CounterType.ALWAYS_COUNT);
686 +
687 + switchDisconnectReadTimeout =
688 + debugCounters.registerCounter(
689 + PREFIX, "switch-disconnect-read-timeout",
690 + "Number of times a switch was disconnected due " +
691 + "due the switch failing to send OpenFlow " +
692 + "messages or responding to OpenFlow ECHOs",
693 + CounterType.ALWAYS_COUNT,
694 + IDebugCounterService.CTR_MDATA_ERROR);
695 + switchDisconnectHandshakeTimeout =
696 + debugCounters.registerCounter(
697 + PREFIX, "switch-disconnect-handshake-timeout",
698 + "Number of times a switch was disconnected " +
699 + "because it failed to complete the handshake " +
700 + "in time.",
701 + CounterType.ALWAYS_COUNT,
702 + IDebugCounterService.CTR_MDATA_ERROR);
703 + switchDisconnectIOError =
704 + debugCounters.registerCounter(
705 + PREFIX, "switch-disconnect-io-error",
706 + "Number of times a switch was disconnected " +
707 + "due to IO errors on the switch connection.",
708 + CounterType.ALWAYS_COUNT,
709 + IDebugCounterService.CTR_MDATA_ERROR);
710 + switchDisconnectParseError =
711 + debugCounters.registerCounter(
712 + PREFIX, "switch-disconnect-parse-error",
713 + "Number of times a switch was disconnected " +
714 + "because it sent an invalid packet that could " +
715 + "not be parsed",
716 + CounterType.ALWAYS_COUNT,
717 + IDebugCounterService.CTR_MDATA_ERROR);
718 +
719 + switchDisconnectSwitchStateException =
720 + debugCounters.registerCounter(
721 + PREFIX, "switch-disconnect-switch-state-exception",
722 + "Number of times a switch was disconnected " +
723 + "because it sent messages that were invalid " +
724 + "given the switch connection's state.",
725 + CounterType.ALWAYS_COUNT,
726 + IDebugCounterService.CTR_MDATA_ERROR);
727 + rejectedExecutionException =
728 + debugCounters.registerCounter(
729 + PREFIX, "rejected-execution-exception",
730 + "TODO",
731 + CounterType.ALWAYS_COUNT,
732 + IDebugCounterService.CTR_MDATA_ERROR);
733 +
734 + switchDisconnectOtherException =
735 + debugCounters.registerCounter(
736 + PREFIX, "switch-disconnect-other-exception",
737 + "Number of times a switch was disconnected " +
738 + "due to an exceptional situation not covered " +
739 + "by other counters",
740 + CounterType.ALWAYS_COUNT,
741 + IDebugCounterService.CTR_MDATA_ERROR);
742 +
743 + switchConnected =
744 + debugCounters.registerCounter(
745 + PREFIX, "switch-connected",
746 + "Number of times a new switch connection was " +
747 + "established",
748 + CounterType.ALWAYS_COUNT);
749 +
750 + unhandledMessage =
751 + debugCounters.registerCounter(
752 + PREFIX, "unhandled-message",
753 + "Number of times an OpenFlow message was " +
754 + "received that the controller ignored because " +
755 + "it was inapproriate given the switch " +
756 + "connection's state.",
757 + CounterType.ALWAYS_COUNT,
758 + IDebugCounterService.CTR_MDATA_WARN);
759 + // might be less than warning
760 +
761 + packetInWhileSwitchIsSlave =
762 + debugCounters.registerCounter(
763 + PREFIX, "packet-in-while-switch-is-slave",
764 + "Number of times a packet in was received " +
765 + "from a switch that was in SLAVE role. " +
766 + "Possibly inidicates inconsistent roles.",
767 + CounterType.ALWAYS_COUNT);
768 + epermErrorWhileSwitchIsMaster =
769 + debugCounters.registerCounter(
770 + PREFIX, "eperm-error-while-switch-is-master",
771 + "Number of times a permission error was " +
772 + "received while the switch was in MASTER role. " +
773 + "Possibly inidicates inconsistent roles.",
774 + CounterType.ALWAYS_COUNT,
775 + IDebugCounterService.CTR_MDATA_WARN);
776 +
777 + roleReplyTimeout =
778 + debugCounters.registerCounter(
779 + PREFIX, "role-reply-timeout",
780 + "Number of times a role request message did not " +
781 + "receive the expected reply from a switch",
782 + CounterType.ALWAYS_COUNT,
783 + IDebugCounterService.CTR_MDATA_WARN);
784 +
785 + roleReplyReceived = // expected RoleReply received
786 + debugCounters.registerCounter(
787 + PREFIX, "role-reply-received",
788 + "Number of times the controller received the " +
789 + "expected role reply message from a switch",
790 + CounterType.ALWAYS_COUNT);
791 +
792 + roleReplyErrorUnsupported =
793 + debugCounters.registerCounter(
794 + PREFIX, "role-reply-error-unsupported",
795 + "Number of times the controller received an " +
796 + "error from a switch in response to a role " +
797 + "request indicating that the switch does not " +
798 + "support roles.",
799 + CounterType.ALWAYS_COUNT);
800 +
801 + switchCounterRegistrationFailed =
802 + debugCounters.registerCounter(PREFIX,
803 + "switch-counter-registration-failed",
804 + "Number of times the controller failed to " +
805 + "register per-switch debug counters",
806 + CounterType.ALWAYS_COUNT,
807 + IDebugCounterService.CTR_MDATA_WARN);
808 +
809 +
810 + }
811 + }
812 +
813 + public Counters getCounters() {
814 + return this.counters;
815 + }
816 +
817 +
818 + // **************
819 + // Utility methods
820 + // **************
821 +
822 +
823 + public void setAlwaysClearFlowsOnSwActivate(boolean value) {
824 + //this.alwaysClearFlowsOnSwActivate = value;
825 + // XXX S need to be a little more careful about this
826 + }
827 +
828 + public Map<String, Long> getMemory() {
829 + Map<String, Long> m = new HashMap<String, Long>();
830 + Runtime runtime = Runtime.getRuntime();
831 + m.put("total", runtime.totalMemory());
832 + m.put("free", runtime.freeMemory());
833 + return m;
834 + }
835 +
836 +
837 + public Long getUptime() {
838 + RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
839 + return rb.getUptime();
840 + }
841 +
842 + /**
843 + * Forward to the driver-manager to get an IOFSwitch instance.
844 + * @param desc
845 + * @return
846 + */
847 + protected IOFSwitch getOFSwitchInstance(OFDescStatsReply desc, OFVersion ofv) {
848 + if (switchManager == null) {
849 + return new DummySwitchForTesting();
850 + }
851 + return switchManager.getSwitchImpl(desc.getMfrDesc(), desc.getHwDesc(),
852 + desc.getSwDesc(), ofv);
853 + }
854 +
855 + @Activate
856 + public void activate() {
857 + log.info("Initialising OpenFlow Lib and IO");
858 + this.init(new HashMap<String, String>());
859 + this.startupComponents();
860 + this.run();
861 + }
862 +
863 +}
1 +/**
2 + * Copyright 2011, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.internal;
19 +
20 +/**
21 + * Exception is thrown when the handshake fails to complete.
22 + * before a specified time
23 + *
24 + */
25 +public class HandshakeTimeoutException extends Exception {
26 +
27 + private static final long serialVersionUID = 6859880268940337312L;
28 +
29 +}
1 +/**
2 +* Copyright 2011, Big Switch Networks, Inc.
3 +* Originally created by David Erickson, Stanford University
4 +*
5 +* Licensed under the Apache License, Version 2.0 (the "License"); you may
6 +* not use this file except in compliance with the License. You may obtain
7 +* a copy of the License at
8 +*
9 +* http://www.apache.org/licenses/LICENSE-2.0
10 +*
11 +* Unless required by applicable law or agreed to in writing, software
12 +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 +* License for the specific language governing permissions and limitations
15 +* under the License.
16 +**/
17 +
18 +package net.onrc.onos.of.ctl.internal;
19 +
20 +import java.util.concurrent.TimeUnit;
21 +
22 +import org.jboss.netty.channel.ChannelHandlerContext;
23 +import org.jboss.netty.channel.ChannelStateEvent;
24 +import org.jboss.netty.channel.Channels;
25 +import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
26 +import org.jboss.netty.util.Timeout;
27 +import org.jboss.netty.util.Timer;
28 +import org.jboss.netty.util.TimerTask;
29 +
30 +/**
31 + * Trigger a timeout if a switch fails to complete handshake soon enough.
32 + */
33 +public class HandshakeTimeoutHandler
34 + extends SimpleChannelUpstreamHandler {
35 + static final HandshakeTimeoutException EXCEPTION =
36 + new HandshakeTimeoutException();
37 +
38 + final OFChannelHandler channelHandler;
39 + final Timer timer;
40 + final long timeoutNanos;
41 + volatile Timeout timeout;
42 +
43 + public HandshakeTimeoutHandler(OFChannelHandler channelHandler,
44 + Timer timer,
45 + long timeoutSeconds) {
46 + super();
47 + this.channelHandler = channelHandler;
48 + this.timer = timer;
49 + this.timeoutNanos = TimeUnit.SECONDS.toNanos(timeoutSeconds);
50 +
51 + }
52 +
53 + @Override
54 + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
55 + throws Exception {
56 + if (timeoutNanos > 0) {
57 + timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx),
58 + timeoutNanos, TimeUnit.NANOSECONDS);
59 + }
60 + ctx.sendUpstream(e);
61 + }
62 +
63 + @Override
64 + public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
65 + throws Exception {
66 + if (timeout != null) {
67 + timeout.cancel();
68 + timeout = null;
69 + }
70 + }
71 +
72 + private final class HandshakeTimeoutTask implements TimerTask {
73 +
74 + private final ChannelHandlerContext ctx;
75 +
76 + HandshakeTimeoutTask(ChannelHandlerContext ctx) {
77 + this.ctx = ctx;
78 + }
79 +
80 + @Override
81 + public void run(Timeout t) throws Exception {
82 + if (t.isCancelled()) {
83 + return;
84 + }
85 +
86 + if (!ctx.getChannel().isOpen()) {
87 + return;
88 + }
89 + if (!channelHandler.isHandshakeComplete()) {
90 + Channels.fireExceptionCaught(ctx, EXCEPTION);
91 + }
92 + }
93 + }
94 +}
1 +package net.onrc.onos.of.ctl.internal;
2 +
3 +import java.io.IOException;
4 +import java.nio.channels.ClosedChannelException;
5 +import java.util.ArrayList;
6 +import java.util.Collection;
7 +import java.util.Collections;
8 +import java.util.List;
9 +import java.util.concurrent.CopyOnWriteArrayList;
10 +import java.util.concurrent.RejectedExecutionException;
11 +
12 +import net.onrc.onos.of.ctl.IOFSwitch;
13 +import net.onrc.onos.of.ctl.IOFSwitch.PortChangeEvent;
14 +import net.onrc.onos.of.ctl.Role;
15 +import net.onrc.onos.of.ctl.annotations.LogMessageDoc;
16 +import net.onrc.onos.of.ctl.annotations.LogMessageDocs;
17 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterException;
18 +import net.onrc.onos.of.ctl.internal.Controller.Counters;
19 +import net.onrc.onos.of.ctl.internal.OFChannelHandler.ChannelState.RoleReplyInfo;
20 +
21 +import org.jboss.netty.channel.Channel;
22 +import org.jboss.netty.channel.ChannelHandlerContext;
23 +import org.jboss.netty.channel.ChannelStateEvent;
24 +import org.jboss.netty.channel.ExceptionEvent;
25 +import org.jboss.netty.channel.MessageEvent;
26 +import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
27 +import org.jboss.netty.handler.timeout.IdleStateEvent;
28 +import org.jboss.netty.handler.timeout.ReadTimeoutException;
29 +import org.projectfloodlight.openflow.exceptions.OFParseError;
30 +import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
31 +import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
32 +import org.projectfloodlight.openflow.protocol.OFBarrierReply;
33 +import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
34 +import org.projectfloodlight.openflow.protocol.OFControllerRole;
35 +import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
36 +import org.projectfloodlight.openflow.protocol.OFDescStatsRequest;
37 +import org.projectfloodlight.openflow.protocol.OFEchoReply;
38 +import org.projectfloodlight.openflow.protocol.OFEchoRequest;
39 +import org.projectfloodlight.openflow.protocol.OFErrorMsg;
40 +import org.projectfloodlight.openflow.protocol.OFErrorType;
41 +import org.projectfloodlight.openflow.protocol.OFExperimenter;
42 +import org.projectfloodlight.openflow.protocol.OFFactory;
43 +import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
44 +import org.projectfloodlight.openflow.protocol.OFFlowModFailedCode;
45 +import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
46 +import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
47 +import org.projectfloodlight.openflow.protocol.OFGetConfigRequest;
48 +import org.projectfloodlight.openflow.protocol.OFHello;
49 +import org.projectfloodlight.openflow.protocol.OFHelloElem;
50 +import org.projectfloodlight.openflow.protocol.OFMessage;
51 +import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
52 +import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply;
53 +import org.projectfloodlight.openflow.protocol.OFPacketIn;
54 +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
55 +import org.projectfloodlight.openflow.protocol.OFPortDescStatsRequest;
56 +import org.projectfloodlight.openflow.protocol.OFPortStatus;
57 +import org.projectfloodlight.openflow.protocol.OFQueueGetConfigReply;
58 +import org.projectfloodlight.openflow.protocol.OFRoleReply;
59 +import org.projectfloodlight.openflow.protocol.OFRoleRequest;
60 +import org.projectfloodlight.openflow.protocol.OFSetConfig;
61 +import org.projectfloodlight.openflow.protocol.OFStatsReply;
62 +import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
63 +import org.projectfloodlight.openflow.protocol.OFStatsType;
64 +import org.projectfloodlight.openflow.protocol.OFType;
65 +import org.projectfloodlight.openflow.protocol.OFVersion;
66 +import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
67 +import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
68 +import org.projectfloodlight.openflow.protocol.errormsg.OFRoleRequestFailedErrorMsg;
69 +import org.projectfloodlight.openflow.types.U32;
70 +import org.projectfloodlight.openflow.types.U64;
71 +import org.slf4j.Logger;
72 +import org.slf4j.LoggerFactory;
73 +/**
74 + * Channel handler deals with the switch connection and dispatches
75 + * switch messages to the appropriate locations.
76 + */
77 +class OFChannelHandler extends IdleStateAwareChannelHandler {
78 + private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
79 + private static final long DEFAULT_ROLE_TIMEOUT_MS = 2 * 1000; // 10 sec
80 + private final Controller controller;
81 + private final Counters counters;
82 + private IOFSwitch sw;
83 + private long thisdpid; // channelHandler cached value of connected switch id
84 + private Channel channel;
85 + // State needs to be volatile because the HandshakeTimeoutHandler
86 + // needs to check if the handshake is complete
87 + private volatile ChannelState state;
88 +
89 + // All role messaging is handled by the roleChanger. The channel state machine
90 + // coordinates between the roleChanger and the controller-global-registry-service
91 + // to determine controller roles per switch.
92 + private RoleChanger roleChanger;
93 + // Used to coordinate between the controller and the cleanup thread(?)
94 + // for access to the global registry on a per switch basis.
95 + volatile Boolean controlRequested;
96 + // When a switch with a duplicate dpid is found (i.e we already have a
97 + // connected switch with the same dpid), the new switch is immediately
98 + // disconnected. At that point netty callsback channelDisconnected() which
99 + // proceeds to cleaup switch state - we need to ensure that it does not cleanup
100 + // switch state for the older (still connected) switch
101 + private volatile Boolean duplicateDpidFound;
102 +
103 + // Temporary storage for switch-features and port-description
104 + private OFFeaturesReply featuresReply;
105 + private OFPortDescStatsReply portDescReply;
106 + // a concurrent ArrayList to temporarily store port status messages
107 + // before we are ready to deal with them
108 + private final CopyOnWriteArrayList<OFPortStatus> pendingPortStatusMsg;
109 +
110 + //Indicates the openflow version used by this switch
111 + protected OFVersion ofVersion;
112 + protected OFFactory factory13;
113 + protected OFFactory factory10;
114 +
115 + /** transaction Ids to use during handshake. Since only one thread
116 + * calls into an OFChannelHandler instance, we don't need atomic.
117 + * We will count down
118 + */
119 + private int handshakeTransactionIds = -1;
120 +
121 + /**
122 + * Create a new unconnected OFChannelHandler.
123 + * @param controller
124 + */
125 + OFChannelHandler(Controller controller) {
126 + this.controller = controller;
127 + this.counters = controller.getCounters();
128 + this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_MS);
129 + this.state = ChannelState.INIT;
130 + this.pendingPortStatusMsg = new CopyOnWriteArrayList<OFPortStatus>();
131 + factory13 = controller.getOFMessageFactory13();
132 + factory10 = controller.getOFMessageFactory10();
133 + controlRequested = Boolean.FALSE;
134 + duplicateDpidFound = Boolean.FALSE;
135 + }
136 +
137 + //*******************
138 + // Role Handling
139 + //*******************
140 +
141 + /**
142 + * When we remove a pending role request we use this enum to indicate how we
143 + * arrived at the decision. When we send a role request to the switch, we
144 + * also use this enum to indicate what we expect back from the switch, so the
145 + * role changer can match the reply to our expectation.
146 + */
147 + public enum RoleRecvStatus {
148 + /** The switch returned an error indicating that roles are not.
149 + * supported*/
150 + UNSUPPORTED,
151 + /** The request timed out. */
152 + NO_REPLY,
153 + /** The reply was old, there is a newer request pending. */
154 + OLD_REPLY,
155 + /**
156 + * The reply's role matched the role that this controller set in the
157 + * request message - invoked either initially at startup or to reassert
158 + * current role.
159 + */
160 + MATCHED_CURRENT_ROLE,
161 + /**
162 + * The reply's role matched the role that this controller set in the
163 + * request message - this is the result of a callback from the
164 + * global registry, followed by a role request sent to the switch.
165 + */
166 + MATCHED_SET_ROLE,
167 + /**
168 + * The reply's role was a response to the query made by this controller.
169 + */
170 + REPLY_QUERY,
171 + /** We received a role reply message from the switch
172 + * but the expectation was unclear, or there was no expectation.
173 + */
174 + OTHER_EXPECTATION,
175 + }
176 +
177 + /**
178 + * Forwards to RoleChanger. See there.
179 + * @param role
180 + */
181 + public void sendRoleRequest(Role role, RoleRecvStatus expectation) {
182 + try {
183 + roleChanger.sendRoleRequest(role, expectation);
184 + } catch (IOException e) {
185 + log.error("Disconnecting switch {} due to IO Error: {}",
186 + getSwitchInfoString(), e.getMessage());
187 + channel.close();
188 + }
189 + }
190 +
191 + // XXX S consider if necessary
192 + public void disconnectSwitch() {
193 + sw.disconnectSwitch();
194 + }
195 +
196 + /**
197 + * A utility class to handle role requests and replies for this channel.
198 + * After a role request is submitted the role changer keeps track of the
199 + * pending request, collects the reply (if any) and times out the request
200 + * if necessary.
201 + *
202 + * To simplify role handling we only keep track of the /last/ pending
203 + * role reply send to the switch. If multiple requests are pending and
204 + * we receive replies for earlier requests we ignore them. However, this
205 + * way of handling pending requests implies that we could wait forever if
206 + * a new request is submitted before the timeout triggers. If necessary
207 + * we could work around that though.
208 + */
209 + private class RoleChanger {
210 + // indicates that a request is currently pending
211 + // needs to be volatile to allow correct double-check idiom
212 + private volatile boolean requestPending;
213 + // the transaction Id of the pending request
214 + private int pendingXid;
215 + // the role that's pending
216 + private Role pendingRole;
217 + // system time in MS when we send the request
218 + private long roleSubmitTime;
219 + // the timeout to use
220 + private final long roleTimeoutMs;
221 + // the expectation set by the caller for the returned role
222 + private RoleRecvStatus expectation;
223 +
224 + public RoleChanger(long roleTimeoutMs) {
225 + this.requestPending = false;
226 + this.roleSubmitTime = 0;
227 + this.pendingXid = -1;
228 + this.pendingRole = null;
229 + this.roleTimeoutMs = roleTimeoutMs;
230 + this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE;
231 + }
232 +
233 + /**
234 + * Send NX role request message to the switch requesting the specified
235 + * role.
236 + *
237 + * @param sw switch to send the role request message to
238 + * @param role role to request
239 + */
240 + private int sendNxRoleRequest(Role role) throws IOException {
241 + // Convert the role enum to the appropriate role to send
242 + OFNiciraControllerRole roleToSend = OFNiciraControllerRole.ROLE_OTHER;
243 + switch (role) {
244 + case MASTER:
245 + roleToSend = OFNiciraControllerRole.ROLE_MASTER;
246 + break;
247 + case SLAVE:
248 + case EQUAL:
249 + default:
250 + // ensuring that the only two roles sent to 1.0 switches with
251 + // Nicira role support, are MASTER and SLAVE
252 + roleToSend = OFNiciraControllerRole.ROLE_SLAVE;
253 + log.warn("Sending Nx Role.SLAVE to switch {}.", sw);
254 + }
255 + int xid = sw.getNextTransactionId();
256 + OFExperimenter roleRequest = factory10
257 + .buildNiciraControllerRoleRequest()
258 + .setXid(xid)
259 + .setRole(roleToSend)
260 + .build();
261 + sw.write(Collections.<OFMessage>singletonList(roleRequest));
262 + return xid;
263 + }
264 +
265 + private int sendOF13RoleRequest(Role role) throws IOException {
266 + // Convert the role enum to the appropriate role to send
267 + OFControllerRole roleToSend = OFControllerRole.ROLE_NOCHANGE;
268 + switch (role) {
269 + case EQUAL:
270 + roleToSend = OFControllerRole.ROLE_EQUAL;
271 + break;
272 + case MASTER:
273 + roleToSend = OFControllerRole.ROLE_MASTER;
274 + break;
275 + case SLAVE:
276 + roleToSend = OFControllerRole.ROLE_SLAVE;
277 + break;
278 + default:
279 + log.warn("Sending default role.noChange to switch {}."
280 + + " Should only be used for queries.", sw);
281 + }
282 +
283 + int xid = sw.getNextTransactionId();
284 + OFRoleRequest rrm = factory13
285 + .buildRoleRequest()
286 + .setRole(roleToSend)
287 + .setXid(xid)
288 + .setGenerationId(sw.getNextGenerationId())
289 + .build();
290 + sw.write(rrm);
291 + return xid;
292 + }
293 +
294 + /**
295 + * Send a role request with the given role to the switch and update
296 + * the pending request and timestamp.
297 + * Sends an OFPT_ROLE_REQUEST to an OF1.3 switch, OR
298 + * Sends an NX_ROLE_REQUEST to an OF1.0 switch if configured to support it
299 + * in the IOFSwitch driver. If not supported, this method sends nothing
300 + * and returns 'false'. The caller should take appropriate action.
301 + *
302 + * One other optimization we do here is that for OF1.0 switches with
303 + * Nicira role message support, we force the Role.EQUAL to become
304 + * Role.SLAVE, as there is no defined behavior for the Nicira role OTHER.
305 + * We cannot expect it to behave like SLAVE. We don't have this problem with
306 + * OF1.3 switches, because Role.EQUAL is well defined and we can simulate
307 + * SLAVE behavior by using ASYNC messages.
308 + *
309 + * @param role
310 + * @throws IOException
311 + * @returns false if and only if the switch does not support role-request
312 + * messages, according to the switch driver; true otherwise.
313 + */
314 + synchronized boolean sendRoleRequest(Role role, RoleRecvStatus exp)
315 + throws IOException {
316 + this.expectation = exp;
317 +
318 + if (ofVersion == OFVersion.OF_10) {
319 + Boolean supportsNxRole = (Boolean)
320 + sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE);
321 + if (!supportsNxRole) {
322 + log.debug("Switch driver indicates no support for Nicira "
323 + + "role request messages. Not sending ...");
324 + state.handleUnsentRoleMessage(OFChannelHandler.this, role,
325 + expectation);
326 + return false;
327 + }
328 + // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn.
329 + // make Role.EQUAL become Role.SLAVE
330 + role = (role == Role.EQUAL) ? Role.SLAVE : role;
331 + pendingXid = sendNxRoleRequest(role);
332 + pendingRole = role;
333 + roleSubmitTime = System.currentTimeMillis();
334 + requestPending = true;
335 + } else {
336 + // OF1.3 switch, use OFPT_ROLE_REQUEST message
337 + pendingXid = sendOF13RoleRequest(role);
338 + pendingRole = role;
339 + roleSubmitTime = System.currentTimeMillis();
340 + requestPending = true;
341 + }
342 + return true;
343 + }
344 +
345 + /**
346 + * Deliver a received role reply.
347 + *
348 + * Check if a request is pending and if the received reply matches the
349 + * the expected pending reply (we check both role and xid) we set
350 + * the role for the switch/channel.
351 + *
352 + * If a request is pending but doesn't match the reply we ignore it, and
353 + * return
354 + *
355 + * If no request is pending we disconnect with a SwitchStateException
356 + *
357 + * @param RoleReplyInfo information about role-reply in format that
358 + * controller can understand.
359 + * @throws SwitchStateException if no request is pending
360 + */
361 + synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
362 + throws SwitchStateException {
363 + if (!requestPending) {
364 + Role currentRole = (sw != null) ? sw.getRole() : null;
365 + if (currentRole != null) {
366 + if (currentRole == rri.getRole()) {
367 + // Don't disconnect if the role reply we received is
368 + // for the same role we are already in.
369 + log.debug("Received unexpected RoleReply from "
370 + + "Switch: {} in State: {}. "
371 + + "Role in reply is same as current role of this "
372 + + "controller for this sw. Ignoring ...",
373 + getSwitchInfoString(), state.toString());
374 + return RoleRecvStatus.OTHER_EXPECTATION;
375 + } else {
376 + String msg = String.format("Switch: [%s], State: [%s], "
377 + + "received unexpected RoleReply[%s]. "
378 + + "No roles are pending, and this controller's "
379 + + "current role:[%s] does not match reply. "
380 + + "Disconnecting switch ... ",
381 + OFChannelHandler.this.getSwitchInfoString(),
382 + OFChannelHandler.this.state.toString(),
383 + rri, currentRole);
384 + throw new SwitchStateException(msg);
385 + }
386 + }
387 + log.debug("Received unexpected RoleReply {} from "
388 + + "Switch: {} in State: {}. "
389 + + "This controller has no current role for this sw. "
390 + + "Ignoring ...", new Object[] {rri,
391 + getSwitchInfoString(), state});
392 + return RoleRecvStatus.OTHER_EXPECTATION;
393 + }
394 +
395 + int xid = (int) rri.getXid();
396 + Role role = rri.getRole();
397 + // XXX S should check generation id meaningfully and other cases of expectations
398 + // U64 genId = rri.getGenId();
399 +
400 + if (pendingXid != xid) {
401 + log.debug("Received older role reply from " +
402 + "switch {} ({}). Ignoring. " +
403 + "Waiting for {}, xid={}",
404 + new Object[] {getSwitchInfoString(), rri,
405 + pendingRole, pendingXid });
406 + return RoleRecvStatus.OLD_REPLY;
407 + }
408 +
409 + if (pendingRole == role) {
410 + log.debug("Received role reply message from {} that matched "
411 + + "expected role-reply {} with expectations {}",
412 + new Object[] {getSwitchInfoString(), role, expectation});
413 + counters.roleReplyReceived.updateCounterWithFlush();
414 + //setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY); dont want to set state here
415 + if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE ||
416 + expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
417 + return expectation;
418 + } else {
419 + return RoleRecvStatus.OTHER_EXPECTATION;
420 + }
421 + }
422 +
423 + // if xids match but role's don't, perhaps its a query (OF1.3)
424 + if (expectation == RoleRecvStatus.REPLY_QUERY) {
425 + return expectation;
426 + }
427 +
428 + return RoleRecvStatus.OTHER_EXPECTATION;
429 + }
430 +
431 + /**
432 + * Called if we receive an error message. If the xid matches the
433 + * pending request we handle it otherwise we ignore it.
434 + *
435 + * Note: since we only keep the last pending request we might get
436 + * error messages for earlier role requests that we won't be able
437 + * to handle
438 + */
439 + synchronized RoleRecvStatus deliverError(OFErrorMsg error)
440 + throws SwitchStateException {
441 + if (!requestPending) {
442 + log.debug("Received an error msg from sw {}, but no pending "
443 + + "requests in role-changer; not handling ...",
444 + getSwitchInfoString());
445 + return RoleRecvStatus.OTHER_EXPECTATION;
446 + }
447 + if (pendingXid != error.getXid()) {
448 + if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
449 + log.debug("Received an error msg from sw {} for a role request,"
450 + + " but not for pending request in role-changer; "
451 + + " ignoring error {} ...",
452 + getSwitchInfoString(), error);
453 + }
454 + return RoleRecvStatus.OTHER_EXPECTATION;
455 + }
456 + // it is an error related to a currently pending role request message
457 + if (error.getErrType() == OFErrorType.BAD_REQUEST) {
458 + counters.roleReplyErrorUnsupported.updateCounterWithFlush();
459 + log.error("Received a error msg {} from sw {} in state {} for "
460 + + "pending role request {}. Switch driver indicates "
461 + + "role-messaging is supported. Possible issues in "
462 + + "switch driver configuration?", new Object[] {
463 + ((OFBadRequestErrorMsg) error).toString(),
464 + getSwitchInfoString(), state, pendingRole
465 + });
466 + return RoleRecvStatus.UNSUPPORTED;
467 + }
468 +
469 + if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
470 + OFRoleRequestFailedErrorMsg rrerr =
471 + (OFRoleRequestFailedErrorMsg) error;
472 + switch (rrerr.getCode()) {
473 + case BAD_ROLE:
474 + // switch says that current-role-req has bad role?
475 + // for now we disconnect
476 + // fall-thru
477 + case STALE:
478 + // switch says that current-role-req has stale gen-id?
479 + // for now we disconnect
480 + // fall-thru
481 + case UNSUP:
482 + // switch says that current-role-req has role that
483 + // cannot be supported? for now we disconnect
484 + String msgx = String.format("Switch: [%s], State: [%s], "
485 + + "received Error to for pending role request [%s]. "
486 + + "Error:[%s]. Disconnecting switch ... ",
487 + OFChannelHandler.this.getSwitchInfoString(),
488 + OFChannelHandler.this.state.toString(),
489 + pendingRole, rrerr);
490 + throw new SwitchStateException(msgx);
491 + default:
492 + break;
493 + }
494 + }
495 +
496 + // This error message was for a role request message but we dont know
497 + // how to handle errors for nicira role request messages
498 + return RoleRecvStatus.OTHER_EXPECTATION;
499 + }
500 +
501 + /**
502 + * Check if a pending role request has timed out.
503 + */
504 + void checkTimeout() {
505 + if (!requestPending) {
506 + return;
507 + }
508 + synchronized (this) {
509 + if (!requestPending) {
510 + return;
511 + }
512 + long now = System.currentTimeMillis();
513 + if (now - roleSubmitTime > roleTimeoutMs) {
514 + // timeout triggered.
515 + counters.roleReplyTimeout.updateCounterWithFlush();
516 + //setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY);
517 + // XXX S come back to this
518 + }
519 + }
520 + }
521 +
522 + }
523 +
524 + //*************************
525 + // Channel State Machine
526 + //*************************
527 +
528 + /**
529 + * The state machine for handling the switch/channel state. All state
530 + * transitions should happen from within the state machine (and not from other
531 + * parts of the code)
532 + */
533 + enum ChannelState {
534 + /**
535 + * Initial state before channel is connected.
536 + */
537 + INIT(false) {
538 + @Override
539 + void processOFMessage(OFChannelHandler h, OFMessage m)
540 + throws IOException, SwitchStateException {
541 + illegalMessageReceived(h, m);
542 + }
543 +
544 + @Override
545 + void processOFError(OFChannelHandler h, OFErrorMsg m)
546 + throws IOException {
547 + // need to implement since its abstract but it will never
548 + // be called
549 + }
550 +
551 + @Override
552 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
553 + throws IOException {
554 + unhandledMessageReceived(h, m);
555 + }
556 + },
557 +
558 + /**
559 + * We send a OF 1.3 HELLO to the switch and wait for a Hello from the switch.
560 + * Once we receive the reply, we decide on OF 1.3 or 1.0 switch - no other
561 + * protocol version is accepted.
562 + * We send an OFFeaturesRequest depending on the protocol version selected
563 + * Next state is WAIT_FEATURES_REPLY
564 + */
565 + WAIT_HELLO(false) {
566 + @Override
567 + void processOFHello(OFChannelHandler h, OFHello m)
568 + throws IOException {
569 + // TODO We could check for the optional bitmap, but for now
570 + // we are just checking the version number.
571 + if (m.getVersion() == OFVersion.OF_13) {
572 + log.info("Received {} Hello from {}", m.getVersion(),
573 + h.channel.getRemoteAddress());
574 + h.ofVersion = OFVersion.OF_13;
575 + } else if (m.getVersion() == OFVersion.OF_10) {
576 + log.info("Received {} Hello from {} - switching to OF "
577 + + "version 1.0", m.getVersion(),
578 + h.channel.getRemoteAddress());
579 + h.ofVersion = OFVersion.OF_10;
580 + } else {
581 + log.error("Received Hello of version {} from switch at {}. "
582 + + "This controller works with OF1.0 and OF1.3 "
583 + + "switches. Disconnecting switch ...",
584 + m.getVersion(), h.channel.getRemoteAddress());
585 + h.channel.disconnect();
586 + return;
587 + }
588 + h.sendHandshakeFeaturesRequestMessage();
589 + h.setState(WAIT_FEATURES_REPLY);
590 + }
591 + @Override
592 + void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
593 + throws IOException, SwitchStateException {
594 + illegalMessageReceived(h, m);
595 + }
596 + @Override
597 + void processOFStatisticsReply(OFChannelHandler h,
598 + OFStatsReply m)
599 + throws IOException, SwitchStateException {
600 + illegalMessageReceived(h, m);
601 + }
602 + @Override
603 + void processOFError(OFChannelHandler h, OFErrorMsg m) {
604 + logErrorDisconnect(h, m);
605 + }
606 +
607 + @Override
608 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
609 + throws IOException {
610 + unhandledMessageReceived(h, m);
611 + }
612 + },
613 +
614 +
615 + /**
616 + * We are waiting for a features reply message. Once we receive it, the
617 + * behavior depends on whether this is a 1.0 or 1.3 switch. For 1.0,
618 + * we send a SetConfig request, barrier, and GetConfig request and the
619 + * next state is WAIT_CONFIG_REPLY. For 1.3, we send a Port description
620 + * request and the next state is WAIT_PORT_DESC_REPLY.
621 + */
622 + WAIT_FEATURES_REPLY(false) {
623 + @Override
624 + void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
625 + throws IOException {
626 + h.thisdpid = m.getDatapathId().getLong();
627 + log.info("Received features reply for switch at {} with dpid {}",
628 + h.getSwitchInfoString(), h.thisdpid);
629 + //update the controller about this connected switch
630 + boolean success = h.controller.addConnectedSwitch(
631 + h.thisdpid, h);
632 + if (!success) {
633 + disconnectDuplicate(h);
634 + return;
635 + }
636 +
637 + h.featuresReply = m; //temp store
638 + if (h.ofVersion == OFVersion.OF_10) {
639 + h.sendHandshakeSetConfig();
640 + h.setState(WAIT_CONFIG_REPLY);
641 + } else {
642 + //version is 1.3, must get switchport information
643 + h.sendHandshakeOFPortDescRequest();
644 + h.setState(WAIT_PORT_DESC_REPLY);
645 + }
646 + }
647 + @Override
648 + void processOFStatisticsReply(OFChannelHandler h,
649 + OFStatsReply m)
650 + throws IOException, SwitchStateException {
651 + illegalMessageReceived(h, m);
652 + }
653 + @Override
654 + void processOFError(OFChannelHandler h, OFErrorMsg m) {
655 + logErrorDisconnect(h, m);
656 + }
657 +
658 + @Override
659 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
660 + throws IOException {
661 + unhandledMessageReceived(h, m);
662 + }
663 + },
664 +
665 + /**
666 + * We are waiting for a description of the 1.3 switch ports.
667 + * Once received, we send a SetConfig request
668 + * Next State is WAIT_CONFIG_REPLY
669 + */
670 + WAIT_PORT_DESC_REPLY(false) {
671 +
672 + @Override
673 + void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
674 + throws SwitchStateException {
675 + // Read port description
676 + if (m.getStatsType() != OFStatsType.PORT_DESC) {
677 + log.warn("Expecting port description stats but received stats "
678 + + "type {} from {}. Ignoring ...", m.getStatsType(),
679 + h.channel.getRemoteAddress());
680 + return;
681 + }
682 + if (m.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
683 + log.warn("Stats reply indicates more stats from sw {} for "
684 + + "port description - not currently handled",
685 + h.getSwitchInfoString());
686 + }
687 + h.portDescReply = (OFPortDescStatsReply) m; // temp store
688 + log.info("Received port desc reply for switch at {}",
689 + h.getSwitchInfoString());
690 + try {
691 + h.sendHandshakeSetConfig();
692 + } catch (IOException e) {
693 + log.error("Unable to send setConfig after PortDescReply. "
694 + + "Error: {}", e.getMessage());
695 + }
696 + h.setState(WAIT_CONFIG_REPLY);
697 + }
698 +
699 + @Override
700 + void processOFError(OFChannelHandler h, OFErrorMsg m)
701 + throws IOException, SwitchStateException {
702 + logErrorDisconnect(h, m);
703 +
704 + }
705 +
706 + @Override
707 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
708 + throws IOException, SwitchStateException {
709 + unhandledMessageReceived(h, m);
710 +
711 + }
712 + },
713 +
714 + /**
715 + * We are waiting for a config reply message. Once we receive it
716 + * we send a DescriptionStatsRequest to the switch.
717 + * Next state: WAIT_DESCRIPTION_STAT_REPLY
718 + */
719 + WAIT_CONFIG_REPLY(false) {
720 + @Override
721 + @LogMessageDocs({
722 + @LogMessageDoc(level = "WARN",
723 + message = "Config Reply from {switch} has "
724 + + "miss length set to {length}",
725 + explanation = "The controller requires that the switch "
726 + + "use a miss length of 0xffff for correct "
727 + + "function",
728 + recommendation = "Use a different switch to ensure "
729 + + "correct function")
730 + })
731 + void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m)
732 + throws IOException {
733 + if (m.getMissSendLen() == 0xffff) {
734 + log.trace("Config Reply from switch {} confirms "
735 + + "miss length set to 0xffff",
736 + h.getSwitchInfoString());
737 + } else {
738 + // FIXME: we can't really deal with switches that don't send
739 + // full packets. Shouldn't we drop the connection here?
740 + log.warn("Config Reply from switch {} has"
741 + + "miss length set to {}",
742 + h.getSwitchInfoString(),
743 + m.getMissSendLen());
744 + }
745 + h.sendHandshakeDescriptionStatsRequest();
746 + h.setState(WAIT_DESCRIPTION_STAT_REPLY);
747 + }
748 +
749 + @Override
750 + void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) {
751 + // do nothing;
752 + }
753 +
754 + @Override
755 + void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
756 + throws IOException, SwitchStateException {
757 + illegalMessageReceived(h, m);
758 + }
759 + @Override
760 + void processOFStatisticsReply(OFChannelHandler h,
761 + OFStatsReply m)
762 + throws IOException, SwitchStateException {
763 + log.error("Received multipart(stats) message sub-type {}",
764 + m.getStatsType());
765 + illegalMessageReceived(h, m);
766 + }
767 +
768 + @Override
769 + void processOFError(OFChannelHandler h, OFErrorMsg m) {
770 + logErrorDisconnect(h, m);
771 + }
772 +
773 + @Override
774 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
775 + throws IOException {
776 + h.pendingPortStatusMsg.add(m);
777 + }
778 + },
779 +
780 +
781 + /**
782 + * We are waiting for a OFDescriptionStat message from the switch.
783 + * Once we receive any stat message we try to parse it. If it's not
784 + * a description stats message we disconnect. If its the expected
785 + * description stats message, we:
786 + * - use the switch driver to bind the switch and get an IOFSwitch instance
787 + * - setup the IOFSwitch instance
788 + * - add switch to FloodlightProvider(Controller) and send the initial role
789 + * request to the switch.
790 + * Next state: WAIT_INITIAL_ROLE
791 + * In the typical case, where switches support role request messages
792 + * the next state is where we expect the role reply message.
793 + * In the special case that where the switch does not support any kind
794 + * of role request messages, we don't send a role message, but we do
795 + * request mastership from the registry service. This controller
796 + * should become master once we hear back from the registry service.
797 + * All following states will have a h.sw instance!
798 + */
799 + WAIT_DESCRIPTION_STAT_REPLY(false) {
800 + @LogMessageDoc(message = "Switch {switch info} bound to class "
801 + + "{switch driver}, description {switch description}",
802 + explanation = "The specified switch has been bound to "
803 + + "a switch driver based on the switch description"
804 + + "received from the switch")
805 + @Override
806 + void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
807 + throws SwitchStateException {
808 + // Read description, if it has been updated
809 + if (m.getStatsType() != OFStatsType.DESC) {
810 + log.warn("Expecting Description stats but received stats "
811 + + "type {} from {}. Ignoring ...", m.getStatsType(),
812 + h.channel.getRemoteAddress());
813 + return;
814 + }
815 + log.info("Received switch description reply from switch at {}",
816 + h.channel.getRemoteAddress());
817 + OFDescStatsReply drep = (OFDescStatsReply) m;
818 + // Here is where we differentiate between different kinds of switches
819 + h.sw = h.controller.getOFSwitchInstance(drep, h.ofVersion);
820 + // set switch information
821 + h.sw.setOFVersion(h.ofVersion);
822 + h.sw.setFeaturesReply(h.featuresReply);
823 + h.sw.setPortDescReply(h.portDescReply);
824 + h.sw.setConnected(true);
825 + h.sw.setChannel(h.channel);
826 +
827 + try {
828 + h.sw.setDebugCounterService(h.controller.getDebugCounter());
829 + } catch (CounterException e) {
830 + h.counters.switchCounterRegistrationFailed
831 + .updateCounterNoFlush();
832 + log.warn("Could not register counters for switch {} ",
833 + h.getSwitchInfoString(), e);
834 + }
835 +
836 + log.info("Switch {} bound to class {}, description {}",
837 + new Object[] {h.sw, h.sw.getClass(), drep });
838 + //Put switch in EQUAL mode until we hear back from the global registry
839 + log.debug("Setting new switch {} to EQUAL and sending Role request",
840 + h.sw.getStringId());
841 + h.setSwitchRole(Role.EQUAL);
842 + try {
843 + boolean supportsRRMsg = h.roleChanger.sendRoleRequest(Role.EQUAL,
844 + RoleRecvStatus.MATCHED_CURRENT_ROLE);
845 + if (!supportsRRMsg) {
846 + log.warn("Switch {} does not support role request messages "
847 + + "of any kind. No role messages were sent. "
848 + + "This controller instance SHOULD become MASTER "
849 + + "from the registry process. ",
850 + h.getSwitchInfoString());
851 + }
852 + h.setState(WAIT_INITIAL_ROLE);
853 + // request control of switch from global registry -
854 + // necessary even if this is the only controller the
855 + // switch is connected to.
856 + h.controller.submitRegistryRequest(h.sw.getId());
857 + } catch (IOException e) {
858 + log.error("Exception when sending role request: {} ",
859 + e.getMessage());
860 + // FIXME shouldn't we disconnect?
861 + }
862 + }
863 +
864 + @Override
865 + void processOFError(OFChannelHandler h, OFErrorMsg m) {
866 + logErrorDisconnect(h, m);
867 + }
868 +
869 + @Override
870 + void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
871 + throws IOException, SwitchStateException {
872 + illegalMessageReceived(h, m);
873 + }
874 +
875 + @Override
876 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
877 + throws IOException {
878 + h.pendingPortStatusMsg.add(m);
879 + }
880 + },
881 +
882 + /**
883 + * We are waiting for a role reply message in response to a role request
884 + * sent after hearing back from the registry service -- OR -- we are
885 + * just waiting to hear back from the registry service in the case that
886 + * the switch does not support role messages. If completed successfully,
887 + * the controller's role for this switch will be set here.
888 + * Before we move to the state corresponding to the role, we allow the
889 + * switch specific driver to complete its configuration. This configuration
890 + * typically depends on the role the controller is playing for this switch.
891 + * And so we set the switch role (for 'this' controller) before we start
892 + * the driver-sub-handshake.
893 + * Next State: WAIT_SWITCH_DRIVER_SUB_HANDSHAKE
894 + */
895 + WAIT_INITIAL_ROLE(false) {
896 + @Override
897 + void processOFError(OFChannelHandler h, OFErrorMsg m)
898 + throws SwitchStateException {
899 + // role changer will ignore the error if it isn't for it
900 + RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
901 + if (rrstatus == RoleRecvStatus.OTHER_EXPECTATION) {
902 + logError(h, m);
903 + }
904 + }
905 +
906 + @Override
907 + void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
908 + throws IOException, SwitchStateException {
909 + Role role = extractNiciraRoleReply(h, m);
910 + // If role == null it means the vendor (experimenter) message
911 + // wasn't really a Nicira role reply. We ignore this case.
912 + if (role != null) {
913 + RoleReplyInfo rri = new RoleReplyInfo(role, null, m.getXid());
914 + RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
915 + if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
916 + setRoleAndStartDriverHandshake(h, rri.getRole());
917 + } // else do nothing - wait for the correct expected reply
918 + } else {
919 + unhandledMessageReceived(h, m);
920 + }
921 + }
922 +
923 + @Override
924 + void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
925 + throws SwitchStateException, IOException {
926 + RoleReplyInfo rri = extractOFRoleReply(h, m);
927 + RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
928 + if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
929 + setRoleAndStartDriverHandshake(h, rri.getRole());
930 + } // else do nothing - wait for the correct expected reply
931 + }
932 +
933 + @Override
934 + void handleUnsentRoleMessage(OFChannelHandler h, Role role,
935 + RoleRecvStatus expectation) throws IOException {
936 + // typically this is triggered for a switch where role messages
937 + // are not supported - we confirm that the role being set is
938 + // master and move to the next state
939 + if (expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
940 + if (role == Role.MASTER) {
941 + setRoleAndStartDriverHandshake(h, role);
942 + } else {
943 + log.error("Expected MASTER role from registry for switch "
944 + + "which has no support for role-messages."
945 + + "Received {}. It is possible that this switch "
946 + + "is connected to other controllers, in which "
947 + + "case it should support role messages - not "
948 + + "moving forward.", role);
949 + }
950 + } // else do nothing - wait to hear back from registry
951 +
952 + }
953 +
954 + private void setRoleAndStartDriverHandshake(OFChannelHandler h,
955 + Role role) throws IOException {
956 + h.setSwitchRole(role);
957 + h.sw.startDriverHandshake();
958 + if (h.sw.isDriverHandshakeComplete()) {
959 + Role mySwitchRole = h.sw.getRole();
960 + if (mySwitchRole == Role.MASTER) {
961 + log.info("Switch-driver sub-handshake complete. "
962 + + "Activating switch {} with Role: MASTER",
963 + h.getSwitchInfoString());
964 + handlePendingPortStatusMessages(h); //before activation
965 + boolean success = h.controller.addActivatedMasterSwitch(
966 + h.sw.getId(), h.sw);
967 + if (!success) {
968 + disconnectDuplicate(h);
969 + return;
970 + }
971 + h.setState(MASTER);
972 + } else {
973 + log.info("Switch-driver sub-handshake complete. "
974 + + "Activating switch {} with Role: EQUAL",
975 + h.getSwitchInfoString());
976 + handlePendingPortStatusMessages(h); //before activation
977 + boolean success = h.controller.addActivatedEqualSwitch(
978 + h.sw.getId(), h.sw);
979 + if (!success) {
980 + disconnectDuplicate(h);
981 + return;
982 + }
983 + h.setState(EQUAL);
984 + }
985 + } else {
986 + h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
987 + }
988 + }
989 +
990 + @Override
991 + void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
992 + throws IOException, SwitchStateException {
993 + illegalMessageReceived(h, m);
994 + }
995 +
996 + @Override
997 + void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
998 + throws SwitchStateException {
999 + illegalMessageReceived(h, m);
1000 + }
1001 +
1002 + @Override
1003 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
1004 + throws IOException, SwitchStateException {
1005 + h.pendingPortStatusMsg.add(m);
1006 +
1007 + }
1008 + },
1009 +
1010 + /**
1011 + * We are waiting for the respective switch driver to complete its
1012 + * configuration. Notice that we do not consider this to be part of the main
1013 + * switch-controller handshake. But we do consider it as a step that comes
1014 + * before we declare the switch as available to the controller.
1015 + * Next State: depends on the role of this controller for this switch - either
1016 + * MASTER or EQUAL.
1017 + */
1018 + WAIT_SWITCH_DRIVER_SUB_HANDSHAKE(true) {
1019 +
1020 + @Override
1021 + void processOFError(OFChannelHandler h, OFErrorMsg m)
1022 + throws IOException {
1023 + // will never be called. We override processOFMessage
1024 + }
1025 +
1026 + @Override
1027 + void processOFMessage(OFChannelHandler h, OFMessage m)
1028 + throws IOException {
1029 + if (m.getType() == OFType.ECHO_REQUEST) {
1030 + processOFEchoRequest(h, (OFEchoRequest) m);
1031 + } else {
1032 + // FIXME: other message to handle here?
1033 + h.sw.processDriverHandshakeMessage(m);
1034 + if (h.sw.isDriverHandshakeComplete()) {
1035 + // consult the h.sw role and goto that state
1036 + Role mySwitchRole = h.sw.getRole();
1037 + if (mySwitchRole == Role.MASTER) {
1038 + log.info("Switch-driver sub-handshake complete. "
1039 + + "Activating switch {} with Role: MASTER",
1040 + h.getSwitchInfoString());
1041 + handlePendingPortStatusMessages(h); //before activation
1042 + boolean success = h.controller.addActivatedMasterSwitch(
1043 + h.sw.getId(), h.sw);
1044 + if (!success) {
1045 + disconnectDuplicate(h);
1046 + return;
1047 + }
1048 + h.setState(MASTER);
1049 + } else {
1050 + log.info("Switch-driver sub-handshake complete. "
1051 + + "Activating switch {} with Role: EQUAL",
1052 + h.getSwitchInfoString());
1053 + handlePendingPortStatusMessages(h); //before activation
1054 + boolean success = h.controller.addActivatedEqualSwitch(
1055 + h.sw.getId(), h.sw);
1056 + if (!success) {
1057 + disconnectDuplicate(h);
1058 + return;
1059 + }
1060 + h.setState(EQUAL);
1061 + }
1062 + }
1063 + }
1064 + }
1065 +
1066 + @Override
1067 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
1068 + throws IOException, SwitchStateException {
1069 + h.pendingPortStatusMsg.add(m);
1070 + }
1071 + },
1072 +
1073 +
1074 + /**
1075 + * This controller is in MASTER role for this switch. We enter this state
1076 + * after requesting and winning control from the global registry.
1077 + * The main handshake as well as the switch-driver sub-handshake
1078 + * is complete at this point.
1079 + * // XXX S reconsider below
1080 + * In the (near) future we may deterministically assign controllers to
1081 + * switches at startup.
1082 + * We only leave this state if the switch disconnects or
1083 + * if we send a role request for SLAVE /and/ receive the role reply for
1084 + * SLAVE.
1085 + */
1086 + MASTER(true) {
1087 + @LogMessageDoc(level = "WARN",
1088 + message = "Received permission error from switch {} while"
1089 + + "being master. Reasserting master role.",
1090 + explanation = "The switch has denied an operation likely "
1091 + + "indicating inconsistent controller roles",
1092 + recommendation = "This situation can occurs transiently during role"
1093 + + " changes. If, however, the condition persists or happens"
1094 + + " frequently this indicates a role inconsistency. "
1095 + + LogMessageDoc.CHECK_CONTROLLER)
1096 + @Override
1097 + void processOFError(OFChannelHandler h, OFErrorMsg m)
1098 + throws IOException, SwitchStateException {
1099 + // first check if the error msg is in response to a role-request message
1100 + RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
1101 + if (rrstatus != RoleRecvStatus.OTHER_EXPECTATION) {
1102 + // rolechanger has handled the error message - we are done
1103 + return;
1104 + }
1105 +
1106 + // if we get here, then the error message is for something else
1107 + if (m.getErrType() == OFErrorType.BAD_REQUEST &&
1108 + ((OFBadRequestErrorMsg) m).getCode() ==
1109 + OFBadRequestCode.EPERM) {
1110 + // We are the master controller and the switch returned
1111 + // a permission error. This is a likely indicator that
1112 + // the switch thinks we are slave. Reassert our
1113 + // role
1114 + // FIXME: this could be really bad during role transitions
1115 + // if two controllers are master (even if its only for
1116 + // a brief period). We might need to see if these errors
1117 + // persist before we reassert
1118 + h.counters.epermErrorWhileSwitchIsMaster.updateCounterWithFlush();
1119 + log.warn("Received permission error from switch {} while" +
1120 + "being master. Reasserting master role.",
1121 + h.getSwitchInfoString());
1122 + //h.controller.reassertRole(h, Role.MASTER);
1123 + // XXX S reassert in role changer or reconsider if all this
1124 + // stuff is really needed
1125 + } else if (m.getErrType() == OFErrorType.FLOW_MOD_FAILED &&
1126 + ((OFFlowModFailedErrorMsg) m).getCode() ==
1127 + OFFlowModFailedCode.ALL_TABLES_FULL) {
1128 + h.sw.setTableFull(true);
1129 + } else {
1130 + logError(h, m);
1131 + }
1132 + h.dispatchMessage(m);
1133 + }
1134 +
1135 + @Override
1136 + void processOFStatisticsReply(OFChannelHandler h,
1137 + OFStatsReply m) {
1138 + h.sw.deliverStatisticsReply(m);
1139 + }
1140 +
1141 + @Override
1142 + void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
1143 + throws IOException, SwitchStateException {
1144 + Role role = extractNiciraRoleReply(h, m);
1145 + if (role == null) {
1146 + // The message wasn't really a Nicira role reply. We just
1147 + // dispatch it to the OFMessage listeners in this case.
1148 + h.dispatchMessage(m);
1149 + return;
1150 + }
1151 +
1152 + RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(
1153 + new RoleReplyInfo(role, null, m.getXid()));
1154 + if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
1155 + checkAndSetRoleTransition(h, role);
1156 + }
1157 + }
1158 +
1159 + @Override
1160 + void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
1161 + throws SwitchStateException, IOException {
1162 + RoleReplyInfo rri = extractOFRoleReply(h, m);
1163 + RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
1164 + if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
1165 + checkAndSetRoleTransition(h, rri.getRole());
1166 + }
1167 + }
1168 +
1169 + @Override
1170 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
1171 + throws IOException, SwitchStateException {
1172 + handlePortStatusMessage(h, m, true);
1173 + h.dispatchMessage(m);
1174 + }
1175 +
1176 + @Override
1177 + void processOFPacketIn(OFChannelHandler h, OFPacketIn m)
1178 + throws IOException {
1179 + h.dispatchMessage(m);
1180 + }
1181 +
1182 + @Override
1183 + void processOFFlowRemoved(OFChannelHandler h,
1184 + OFFlowRemoved m) throws IOException {
1185 + h.dispatchMessage(m);
1186 + }
1187 +
1188 + @Override
1189 + void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m)
1190 + throws IOException {
1191 + h.dispatchMessage(m);
1192 + }
1193 +
1194 + },
1195 +
1196 + /**
1197 + * This controller is in EQUAL role for this switch. We enter this state
1198 + * after some /other/ controller instance wins mastership-role over this
1199 + * switch. The EQUAL role can be considered the same as the SLAVE role
1200 + * if this controller does NOT send commands or packets to the switch.
1201 + * This should always be true for OF1.0 switches. XXX S need to enforce.
1202 + *
1203 + * For OF1.3 switches, choosing this state as EQUAL instead of SLAVE,
1204 + * gives us the flexibility that if an app wants to send commands/packets
1205 + * to switches, it can, even thought it is running on a controller instance
1206 + * that is not in a MASTER role for this switch. Of course, it is the job
1207 + * of the app to ensure that commands/packets sent by this (EQUAL) controller
1208 + * instance does not clash/conflict with commands/packets sent by the MASTER
1209 + * controller for this switch. Neither the controller instances, nor the
1210 + * switch provides any kind of resolution mechanism should conflicts occur.
1211 + */
1212 + EQUAL(true) {
1213 + @Override
1214 + void processOFError(OFChannelHandler h, OFErrorMsg m)
1215 + throws IOException, SwitchStateException {
1216 + // role changer will ignore the error if it isn't for it
1217 + RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
1218 + if (rrstatus == RoleRecvStatus.OTHER_EXPECTATION) {
1219 + logError(h, m);
1220 + h.dispatchMessage(m);
1221 + }
1222 + }
1223 +
1224 + @Override
1225 + void processOFStatisticsReply(OFChannelHandler h,
1226 + OFStatsReply m) {
1227 + h.sw.deliverStatisticsReply(m);
1228 + }
1229 +
1230 + @Override
1231 + void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
1232 + throws IOException, SwitchStateException {
1233 + Role role = extractNiciraRoleReply(h, m);
1234 + // If role == null it means the message wasn't really a
1235 + // Nicira role reply. We ignore it in this state.
1236 + if (role != null) {
1237 + RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(
1238 + new RoleReplyInfo(role, null, m.getXid()));
1239 + if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
1240 + checkAndSetRoleTransition(h, role);
1241 + }
1242 + } else {
1243 + unhandledMessageReceived(h, m);
1244 + }
1245 + }
1246 +
1247 + @Override
1248 + void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
1249 + throws SwitchStateException, IOException {
1250 + RoleReplyInfo rri = extractOFRoleReply(h, m);
1251 + RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
1252 + if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
1253 + checkAndSetRoleTransition(h, rri.getRole());
1254 + }
1255 + }
1256 +
1257 + // XXX S needs more handlers for 1.3 switches in equal role
1258 +
1259 + @Override
1260 + void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
1261 + throws IOException, SwitchStateException {
1262 + handlePortStatusMessage(h, m, true);
1263 + }
1264 +
1265 + @Override
1266 + @LogMessageDoc(level = "WARN",
1267 + message = "Received PacketIn from switch {} while "
1268 + + "being slave. Reasserting slave role.",
1269 + explanation = "The switch has receive a PacketIn despite being "
1270 + + "in slave role indicating inconsistent controller roles",
1271 + recommendation = "This situation can occurs transiently during role"
1272 + + " changes. If, however, the condition persists or happens"
1273 + + " frequently this indicates a role inconsistency. "
1274 + + LogMessageDoc.CHECK_CONTROLLER)
1275 + void processOFPacketIn(OFChannelHandler h, OFPacketIn m) throws IOException {
1276 + // we don't expect packetIn while slave, reassert we are slave
1277 + h.counters.packetInWhileSwitchIsSlave.updateCounterNoFlush();
1278 + log.warn("Received PacketIn from switch {} while" +
1279 + "being slave. Reasserting slave role.", h.sw);
1280 + //h.controller.reassertRole(h, Role.SLAVE);
1281 + // XXX reassert in role changer
1282 + }
1283 + };
1284 +
1285 + private final boolean handshakeComplete;
1286 + ChannelState(boolean handshakeComplete) {
1287 + this.handshakeComplete = handshakeComplete;
1288 + }
1289 +
1290 + /**
1291 + * Is this a state in which the handshake has completed?
1292 + * @return true if the handshake is complete
1293 + */
1294 + public boolean isHandshakeComplete() {
1295 + return handshakeComplete;
1296 + }
1297 +
1298 + /**
1299 + * Get a string specifying the switch connection, state, and
1300 + * message received. To be used as message for SwitchStateException
1301 + * or log messages
1302 + * @param h The channel handler (to get switch information_
1303 + * @param m The OFMessage that has just been received
1304 + * @param details A string giving more details about the exact nature
1305 + * of the problem.
1306 + * @return
1307 + */
1308 + // needs to be protected because enum members are actually subclasses
1309 + protected String getSwitchStateMessage(OFChannelHandler h,
1310 + OFMessage m,
1311 + String details) {
1312 + return String.format("Switch: [%s], State: [%s], received: [%s]"
1313 + + ", details: %s",
1314 + h.getSwitchInfoString(),
1315 + this.toString(),
1316 + m.getType().toString(),
1317 + details);
1318 + }
1319 +
1320 + /**
1321 + * We have an OFMessage we didn't expect given the current state and
1322 + * we want to treat this as an error.
1323 + * We currently throw an exception that will terminate the connection
1324 + * However, we could be more forgiving
1325 + * @param h the channel handler that received the message
1326 + * @param m the message
1327 + * @throws SwitchStateException
1328 + * @throws SwitchStateExeption we always through the execption
1329 + */
1330 + // needs to be protected because enum members are acutally subclasses
1331 + protected void illegalMessageReceived(OFChannelHandler h, OFMessage m)
1332 + throws SwitchStateException {
1333 + String msg = getSwitchStateMessage(h, m,
1334 + "Switch should never send this message in the current state");
1335 + throw new SwitchStateException(msg);
1336 +
1337 + }
1338 +
1339 + /**
1340 + * We have an OFMessage we didn't expect given the current state and
1341 + * we want to ignore the message.
1342 + * @param h the channel handler the received the message
1343 + * @param m the message
1344 + */
1345 + protected void unhandledMessageReceived(OFChannelHandler h,
1346 + OFMessage m) {
1347 + h.counters.unhandledMessage.updateCounterNoFlush();
1348 + if (log.isDebugEnabled()) {
1349 + String msg = getSwitchStateMessage(h, m,
1350 + "Ignoring unexpected message");
1351 + log.debug(msg);
1352 + }
1353 + }
1354 +
1355 + /**
1356 + * Log an OpenFlow error message from a switch.
1357 + * @param sw The switch that sent the error
1358 + * @param error The error message
1359 + */
1360 + @LogMessageDoc(level = "ERROR",
1361 + message = "Error {error type} {error code} from {switch} "
1362 + + "in state {state}",
1363 + explanation = "The switch responded with an unexpected error"
1364 + + "to an OpenFlow message from the controller",
1365 + recommendation = "This could indicate improper network operation. "
1366 + + "If the problem persists restarting the switch and "
1367 + + "controller may help."
1368 + )
1369 + protected void logError(OFChannelHandler h, OFErrorMsg error) {
1370 + log.error("{} from switch {} in state {}",
1371 + new Object[] {
1372 + error,
1373 + h.getSwitchInfoString(),
1374 + this.toString()});
1375 + }
1376 +
1377 + /**
1378 + * Log an OpenFlow error message from a switch and disconnect the
1379 + * channel.
1380 + *
1381 + * @param h the IO channel for this switch.
1382 + * @param error The error message
1383 + */
1384 + protected void logErrorDisconnect(OFChannelHandler h, OFErrorMsg error) {
1385 + logError(h, error);
1386 + h.channel.disconnect();
1387 + }
1388 +
1389 + /**
1390 + * log an error message for a duplicate dpid and disconnect this channel.
1391 + * @param h the IO channel for this switch.
1392 + */
1393 + protected void disconnectDuplicate(OFChannelHandler h) {
1394 + log.error("Duplicated dpid or incompleted cleanup - "
1395 + + "disconnecting channel {}", h.getSwitchInfoString());
1396 + h.duplicateDpidFound = Boolean.TRUE;
1397 + h.channel.disconnect();
1398 + }
1399 +
1400 + /**
1401 + * Extract the role from an OFVendor message.
1402 + *
1403 + * Extract the role from an OFVendor message if the message is a
1404 + * Nicira role reply. Otherwise return null.
1405 + *
1406 + * @param h The channel handler receiving the message
1407 + * @param vendorMessage The vendor message to parse.
1408 + * @return The role in the message if the message is a Nicira role
1409 + * reply, null otherwise.
1410 + * @throws SwitchStateException If the message is a Nicira role reply
1411 + * but the numeric role value is unknown.
1412 + */
1413 + protected Role extractNiciraRoleReply(OFChannelHandler h,
1414 + OFExperimenter experimenterMsg) throws SwitchStateException {
1415 + int vendor = (int) experimenterMsg.getExperimenter();
1416 + if (vendor != 0x2320) {
1417 + return null;
1418 + }
1419 + OFNiciraControllerRoleReply nrr =
1420 + (OFNiciraControllerRoleReply) experimenterMsg;
1421 +
1422 + Role role = null;
1423 + OFNiciraControllerRole ncr = nrr.getRole();
1424 + switch(ncr) {
1425 + case ROLE_MASTER:
1426 + role = Role.MASTER;
1427 + break;
1428 + case ROLE_OTHER:
1429 + role = Role.EQUAL;
1430 + break;
1431 + case ROLE_SLAVE:
1432 + role = Role.SLAVE;
1433 + break;
1434 + default: //handled below
1435 + }
1436 +
1437 + if (role == null) {
1438 + String msg = String.format("Switch: [%s], State: [%s], "
1439 + + "received NX_ROLE_REPLY with invalid role "
1440 + + "value %s",
1441 + h.getSwitchInfoString(),
1442 + this.toString(),
1443 + nrr.getRole());
1444 + throw new SwitchStateException(msg);
1445 + }
1446 + return role;
1447 + }
1448 +
1449 + /**
1450 + * Helper class returns role reply information in the format understood
1451 + * by the controller.
1452 + */
1453 + protected static class RoleReplyInfo {
1454 + private Role role;
1455 + private U64 genId;
1456 + private long xid;
1457 +
1458 + RoleReplyInfo(Role role, U64 genId, long xid) {
1459 + this.role = role;
1460 + this.genId = genId;
1461 + this.xid = xid;
1462 + }
1463 + public Role getRole() { return role; }
1464 + public U64 getGenId() { return genId; }
1465 + public long getXid() { return xid; }
1466 + @Override
1467 + public String toString() {
1468 + return "[Role:" + role + " GenId:" + genId + " Xid:" + xid + "]";
1469 + }
1470 + }
1471 +
1472 + /**
1473 + * Extract the role information from an OF1.3 Role Reply Message.
1474 + * @param h
1475 + * @param rrmsg
1476 + * @return RoleReplyInfo object
1477 + * @throws SwitchStateException
1478 + */
1479 + protected RoleReplyInfo extractOFRoleReply(OFChannelHandler h,
1480 + OFRoleReply rrmsg) throws SwitchStateException {
1481 + OFControllerRole cr = rrmsg.getRole();
1482 + Role role = null;
1483 + switch(cr) {
1484 + case ROLE_EQUAL:
1485 + role = Role.EQUAL;
1486 + break;
1487 + case ROLE_MASTER:
1488 + role = Role.MASTER;
1489 + break;
1490 + case ROLE_SLAVE:
1491 + role = Role.SLAVE;
1492 + break;
1493 + case ROLE_NOCHANGE: // switch should send current role
1494 + default:
1495 + String msg = String.format("Unknown controller role %s "
1496 + + "received from switch %s", cr, h.sw);
1497 + throw new SwitchStateException(msg);
1498 + }
1499 +
1500 + return new RoleReplyInfo(role, rrmsg.getGenerationId(), rrmsg.getXid());
1501 + }
1502 +
1503 + /**
1504 + * Handles all pending port status messages before a switch is declared
1505 + * activated in MASTER or EQUAL role. Note that since this handling
1506 + * precedes the activation (and therefore notification to IOFSwitchListerners)
1507 + * the changes to ports will already be visible once the switch is
1508 + * activated. As a result, no notifications are sent out for these
1509 + * pending portStatus messages.
1510 + * @param h
1511 + * @throws SwitchStateException
1512 + */
1513 + protected void handlePendingPortStatusMessages(OFChannelHandler h) {
1514 + try {
1515 + handlePendingPortStatusMessages(h, 0);
1516 + } catch (SwitchStateException e) {
1517 + log.error(e.getMessage());
1518 + }
1519 + }
1520 +
1521 + private void handlePendingPortStatusMessages(OFChannelHandler h, int index)
1522 + throws SwitchStateException {
1523 + if (h.sw == null) {
1524 + String msg = "State machine error: switch is null. Should never " +
1525 + "happen";
1526 + throw new SwitchStateException(msg);
1527 + }
1528 + ArrayList<OFPortStatus> temp = new ArrayList<OFPortStatus>();
1529 + for (OFPortStatus ps: h.pendingPortStatusMsg) {
1530 + temp.add(ps);
1531 + handlePortStatusMessage(h, ps, false);
1532 + }
1533 + temp.clear();
1534 + // expensive but ok - we don't expect too many port-status messages
1535 + // note that we cannot use clear(), because of the reasons below
1536 + h.pendingPortStatusMsg.removeAll(temp);
1537 + // the iterator above takes a snapshot of the list - so while we were
1538 + // dealing with the pending port-status messages, we could have received
1539 + // newer ones. Handle them recursively, but break the recursion after
1540 + // five steps to avoid an attack.
1541 + if (!h.pendingPortStatusMsg.isEmpty() && ++index < 5) {
1542 + handlePendingPortStatusMessages(h, index);
1543 + }
1544 + }
1545 +
1546 + /**
1547 + * Handle a port status message.
1548 + *
1549 + * Handle a port status message by updating the port maps in the
1550 + * IOFSwitch instance and notifying Controller about the change so
1551 + * it can dispatch a switch update.
1552 + *
1553 + * @param h The OFChannelHhandler that received the message
1554 + * @param m The PortStatus message we received
1555 + * @param doNotify if true switch port changed events will be
1556 + * dispatched
1557 + * @throws SwitchStateException
1558 + *
1559 + */
1560 + protected void handlePortStatusMessage(OFChannelHandler h, OFPortStatus m,
1561 + boolean doNotify) throws SwitchStateException {
1562 + if (h.sw == null) {
1563 + String msg = getSwitchStateMessage(h, m,
1564 + "State machine error: switch is null. Should never " +
1565 + "happen");
1566 + throw new SwitchStateException(msg);
1567 + }
1568 +
1569 + Collection<PortChangeEvent> changes = h.sw.processOFPortStatus(m);
1570 + if (doNotify) {
1571 + for (PortChangeEvent ev: changes) {
1572 + h.controller.notifyPortChanged(h.sw.getId(), ev.port, ev.type);
1573 + }
1574 + }
1575 + }
1576 +
1577 + /**
1578 + * Checks if the role received (from the role-reply msg) is different
1579 + * from the existing role in the IOFSwitch object for this controller.
1580 + * If so, it transitions the controller to the new role. Note that
1581 + * the caller should have already verified that the role-reply msg
1582 + * received was in response to a role-request msg sent out by this
1583 + * controller after hearing from the registry service.
1584 + *
1585 + * @param h the ChannelHandler that received the message
1586 + * @param role the role in the recieved role reply message
1587 + */
1588 + protected void checkAndSetRoleTransition(OFChannelHandler h, Role role) {
1589 + // we received a role-reply in response to a role message
1590 + // sent after hearing from the registry service. It is
1591 + // possible that the role of this controller instance for
1592 + // this switch has changed:
1593 + // for 1.0 switch: from MASTER to SLAVE
1594 + // for 1.3 switch: from MASTER to EQUAL
1595 + if ((h.sw.getRole() == Role.MASTER && role == Role.SLAVE) ||
1596 + (h.sw.getRole() == Role.MASTER && role == Role.EQUAL)) {
1597 + // the mastership has changed
1598 + h.sw.setRole(role);
1599 + h.setState(EQUAL);
1600 + h.controller.transitionToEqualSwitch(h.sw.getId());
1601 + return;
1602 + }
1603 +
1604 + // or for both 1.0 and 1.3 switches from EQUAL to MASTER.
1605 + // note that for 1.0, even though we mean SLAVE,
1606 + // internally we call the role EQUAL.
1607 + if (h.sw.getRole() == Role.EQUAL && role == Role.MASTER) {
1608 + // the mastership has changed
1609 + h.sw.setRole(role);
1610 + h.setState(MASTER);
1611 + h.controller.transitionToMasterSwitch(h.sw.getId());
1612 + return;
1613 + }
1614 + }
1615 +
1616 + /**
1617 + * Process an OF message received on the channel and
1618 + * update state accordingly.
1619 + *
1620 + * The main "event" of the state machine. Process the received message,
1621 + * send follow up message if required and update state if required.
1622 + *
1623 + * Switches on the message type and calls more specific event handlers
1624 + * for each individual OF message type. If we receive a message that
1625 + * is supposed to be sent from a controller to a switch we throw
1626 + * a SwitchStateExeption.
1627 + *
1628 + * The more specific handlers can also throw SwitchStateExceptions
1629 + *
1630 + * @param h The OFChannelHandler that received the message
1631 + * @param m The message we received.
1632 + * @throws SwitchStateException
1633 + * @throws IOException
1634 + */
1635 + void processOFMessage(OFChannelHandler h, OFMessage m)
1636 + throws IOException, SwitchStateException {
1637 + h.roleChanger.checkTimeout();
1638 + switch(m.getType()) {
1639 + case HELLO:
1640 + processOFHello(h, (OFHello) m);
1641 + break;
1642 + case BARRIER_REPLY:
1643 + processOFBarrierReply(h, (OFBarrierReply) m);
1644 + break;
1645 + case ECHO_REPLY:
1646 + processOFEchoReply(h, (OFEchoReply) m);
1647 + break;
1648 + case ECHO_REQUEST:
1649 + processOFEchoRequest(h, (OFEchoRequest) m);
1650 + break;
1651 + case ERROR:
1652 + processOFError(h, (OFErrorMsg) m);
1653 + break;
1654 + case FEATURES_REPLY:
1655 + processOFFeaturesReply(h, (OFFeaturesReply) m);
1656 + break;
1657 + case FLOW_REMOVED:
1658 + processOFFlowRemoved(h, (OFFlowRemoved) m);
1659 + break;
1660 + case GET_CONFIG_REPLY:
1661 + processOFGetConfigReply(h, (OFGetConfigReply) m);
1662 + break;
1663 + case PACKET_IN:
1664 + processOFPacketIn(h, (OFPacketIn) m);
1665 + break;
1666 + case PORT_STATUS:
1667 + processOFPortStatus(h, (OFPortStatus) m);
1668 + break;
1669 + case QUEUE_GET_CONFIG_REPLY:
1670 + processOFQueueGetConfigReply(h, (OFQueueGetConfigReply) m);
1671 + break;
1672 + case STATS_REPLY: // multipart_reply in 1.3
1673 + processOFStatisticsReply(h, (OFStatsReply) m);
1674 + break;
1675 + case EXPERIMENTER:
1676 + processOFExperimenter(h, (OFExperimenter) m);
1677 + break;
1678 + case ROLE_REPLY:
1679 + processOFRoleReply(h, (OFRoleReply) m);
1680 + break;
1681 + case GET_ASYNC_REPLY:
1682 + processOFGetAsyncReply(h, (OFAsyncGetReply) m);
1683 + break;
1684 +
1685 + // The following messages are sent to switches. The controller
1686 + // should never receive them
1687 + case SET_CONFIG:
1688 + case GET_CONFIG_REQUEST:
1689 + case PACKET_OUT:
1690 + case PORT_MOD:
1691 + case QUEUE_GET_CONFIG_REQUEST:
1692 + case BARRIER_REQUEST:
1693 + case STATS_REQUEST: // multipart request in 1.3
1694 + case FEATURES_REQUEST:
1695 + case FLOW_MOD:
1696 + case GROUP_MOD:
1697 + case TABLE_MOD:
1698 + case GET_ASYNC_REQUEST:
1699 + case SET_ASYNC:
1700 + case METER_MOD:
1701 + default:
1702 + illegalMessageReceived(h, m);
1703 + break;
1704 + }
1705 + }
1706 +
1707 + /*-----------------------------------------------------------------
1708 + * Default implementation for message handlers in any state.
1709 + *
1710 + * Individual states must override these if they want a behavior
1711 + * that differs from the default.
1712 + *
1713 + * In general, these handlers simply ignore the message and do
1714 + * nothing.
1715 + *
1716 + * There are some exceptions though, since some messages really
1717 + * are handled the same way in every state (e.g., ECHO_REQUST) or
1718 + * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY
1719 + -----------------------------------------------------------------*/
1720 +
1721 + void processOFHello(OFChannelHandler h, OFHello m)
1722 + throws IOException, SwitchStateException {
1723 + // we only expect hello in the WAIT_HELLO state
1724 + illegalMessageReceived(h, m);
1725 + }
1726 +
1727 + void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m)
1728 + throws IOException {
1729 + // Silently ignore.
1730 + }
1731 +
1732 + void processOFEchoRequest(OFChannelHandler h, OFEchoRequest m)
1733 + throws IOException {
1734 + if (h.ofVersion == null) {
1735 + log.error("No OF version set for {}. Not sending Echo REPLY",
1736 + h.channel.getRemoteAddress());
1737 + return;
1738 + }
1739 + OFFactory factory = (h.ofVersion == OFVersion.OF_13) ?
1740 + h.controller.getOFMessageFactory13() : h.controller.getOFMessageFactory10();
1741 + OFEchoReply reply = factory
1742 + .buildEchoReply()
1743 + .setXid(m.getXid())
1744 + .setData(m.getData())
1745 + .build();
1746 + h.channel.write(Collections.singletonList(reply));
1747 + }
1748 +
1749 + void processOFEchoReply(OFChannelHandler h, OFEchoReply m)
1750 + throws IOException {
1751 + // Do nothing with EchoReplies !!
1752 + }
1753 +
1754 + // no default implementation for OFError
1755 + // every state must override it
1756 + abstract void processOFError(OFChannelHandler h, OFErrorMsg m)
1757 + throws IOException, SwitchStateException;
1758 +
1759 +
1760 + void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
1761 + throws IOException, SwitchStateException {
1762 + unhandledMessageReceived(h, m);
1763 + }
1764 +
1765 + void processOFFlowRemoved(OFChannelHandler h, OFFlowRemoved m)
1766 + throws IOException {
1767 + unhandledMessageReceived(h, m);
1768 + }
1769 +
1770 + void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m)
1771 + throws IOException, SwitchStateException {
1772 + // we only expect config replies in the WAIT_CONFIG_REPLY state
1773 + illegalMessageReceived(h, m);
1774 + }
1775 +
1776 + void processOFPacketIn(OFChannelHandler h, OFPacketIn m)
1777 + throws IOException {
1778 + unhandledMessageReceived(h, m);
1779 + }
1780 +
1781 + // no default implementation. Every state needs to handle it.
1782 + abstract void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
1783 + throws IOException, SwitchStateException;
1784 +
1785 + void processOFQueueGetConfigReply(OFChannelHandler h,
1786 + OFQueueGetConfigReply m)
1787 + throws IOException {
1788 + unhandledMessageReceived(h, m);
1789 + }
1790 +
1791 + void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
1792 + throws IOException, SwitchStateException {
1793 + unhandledMessageReceived(h, m);
1794 + }
1795 +
1796 + void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
1797 + throws IOException, SwitchStateException {
1798 + // TODO: it might make sense to parse the vendor message here
1799 + // into the known vendor messages we support and then call more
1800 + // specific event handlers
1801 + unhandledMessageReceived(h, m);
1802 + }
1803 +
1804 + void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
1805 + throws SwitchStateException, IOException {
1806 + unhandledMessageReceived(h, m);
1807 + }
1808 +
1809 + void processOFGetAsyncReply(OFChannelHandler h,
1810 + OFAsyncGetReply m) {
1811 + unhandledMessageReceived(h, m);
1812 + }
1813 +
1814 + void handleUnsentRoleMessage(OFChannelHandler h, Role role,
1815 + RoleRecvStatus expectation) throws IOException {
1816 + // do nothing in most states
1817 + }
1818 + }
1819 +
1820 +
1821 +
1822 + //*************************
1823 + // Channel handler methods
1824 + //*************************
1825 +
1826 + @Override
1827 + @LogMessageDoc(message = "New switch connection from {ip address}",
1828 + explanation = "A new switch has connected from the "
1829 + + "specified IP address")
1830 + public void channelConnected(ChannelHandlerContext ctx,
1831 + ChannelStateEvent e) throws Exception {
1832 + counters.switchConnected.updateCounterWithFlush();
1833 + channel = e.getChannel();
1834 + log.info("New switch connection from {}",
1835 + channel.getRemoteAddress());
1836 + sendHandshakeHelloMessage();
1837 + setState(ChannelState.WAIT_HELLO);
1838 + }
1839 +
1840 + @Override
1841 + @LogMessageDoc(message = "Disconnected switch {switch information}",
1842 + explanation = "The specified switch has disconnected.")
1843 + public void channelDisconnected(ChannelHandlerContext ctx,
1844 + ChannelStateEvent e) throws Exception {
1845 + log.info("Switch disconnected callback for sw:{}. Cleaning up ...",
1846 + getSwitchInfoString());
1847 + if (thisdpid != 0) {
1848 + if (!duplicateDpidFound) {
1849 + // if the disconnected switch (on this ChannelHandler)
1850 + // was not one with a duplicate-dpid, it is safe to remove all
1851 + // state for it at the controller. Notice that if the disconnected
1852 + // switch was a duplicate-dpid, calling the method below would clear
1853 + // all state for the original switch (with the same dpid),
1854 + // which we obviously don't want.
1855 + controller.removeConnectedSwitch(thisdpid);
1856 + } else {
1857 + // A duplicate was disconnected on this ChannelHandler,
1858 + // this is the same switch reconnecting, but the original state was
1859 + // not cleaned up - XXX check liveness of original ChannelHandler
1860 + duplicateDpidFound = Boolean.FALSE;
1861 + }
1862 + } else {
1863 + log.warn("no dpid in channelHandler registered for "
1864 + + "disconnected switch {}", getSwitchInfoString());
1865 + }
1866 + }
1867 +
1868 + @Override
1869 + @LogMessageDocs({
1870 + @LogMessageDoc(level = "ERROR",
1871 + message = "Disconnecting switch {switch} due to read timeout",
1872 + explanation = "The connected switch has failed to send any "
1873 + + "messages or respond to echo requests",
1874 + recommendation = LogMessageDoc.CHECK_SWITCH),
1875 + @LogMessageDoc(level = "ERROR",
1876 + message = "Disconnecting switch {switch}: failed to "
1877 + + "complete handshake",
1878 + explanation = "The switch did not respond correctly "
1879 + + "to handshake messages",
1880 + recommendation = LogMessageDoc.CHECK_SWITCH),
1881 + @LogMessageDoc(level = "ERROR",
1882 + message = "Disconnecting switch {switch} due to IO Error: {}",
1883 + explanation = "There was an error communicating with the switch",
1884 + recommendation = LogMessageDoc.CHECK_SWITCH),
1885 + @LogMessageDoc(level = "ERROR",
1886 + message = "Disconnecting switch {switch} due to switch "
1887 + + "state error: {error}",
1888 + explanation = "The switch sent an unexpected message",
1889 + recommendation = LogMessageDoc.CHECK_SWITCH),
1890 + @LogMessageDoc(level = "ERROR",
1891 + message = "Disconnecting switch {switch} due to "
1892 + + "message parse failure",
1893 + explanation = "Could not parse a message from the switch",
1894 + recommendation = LogMessageDoc.CHECK_SWITCH),
1895 + @LogMessageDoc(level = "ERROR",
1896 + message = "Terminating controller due to storage exception",
1897 + explanation = Controller.ERROR_DATABASE,
1898 + recommendation = LogMessageDoc.CHECK_CONTROLLER),
1899 + @LogMessageDoc(level = "ERROR",
1900 + message = "Could not process message: queue full",
1901 + explanation = "OpenFlow messages are arriving faster than "
1902 + + "the controller can process them.",
1903 + recommendation = LogMessageDoc.CHECK_CONTROLLER),
1904 + @LogMessageDoc(level = "ERROR",
1905 + message = "Error while processing message "
1906 + + "from switch {switch} {cause}",
1907 + explanation = "An error occurred processing the switch message",
1908 + recommendation = LogMessageDoc.GENERIC_ACTION)
1909 + })
1910 + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
1911 + throws Exception {
1912 + if (e.getCause() instanceof ReadTimeoutException) {
1913 + // switch timeout
1914 + log.error("Disconnecting switch {} due to read timeout",
1915 + getSwitchInfoString());
1916 + counters.switchDisconnectReadTimeout.updateCounterWithFlush();
1917 + ctx.getChannel().close();
1918 + } else if (e.getCause() instanceof HandshakeTimeoutException) {
1919 + log.error("Disconnecting switch {}: failed to complete handshake",
1920 + getSwitchInfoString());
1921 + counters.switchDisconnectHandshakeTimeout.updateCounterWithFlush();
1922 + ctx.getChannel().close();
1923 + } else if (e.getCause() instanceof ClosedChannelException) {
1924 + log.debug("Channel for sw {} already closed", getSwitchInfoString());
1925 + } else if (e.getCause() instanceof IOException) {
1926 + log.error("Disconnecting switch {} due to IO Error: {}",
1927 + getSwitchInfoString(), e.getCause().getMessage());
1928 + if (log.isDebugEnabled()) {
1929 + // still print stack trace if debug is enabled
1930 + log.debug("StackTrace for previous Exception: ", e.getCause());
1931 + }
1932 + counters.switchDisconnectIOError.updateCounterWithFlush();
1933 + ctx.getChannel().close();
1934 + } else if (e.getCause() instanceof SwitchStateException) {
1935 + log.error("Disconnecting switch {} due to switch state error: {}",
1936 + getSwitchInfoString(), e.getCause().getMessage());
1937 + if (log.isDebugEnabled()) {
1938 + // still print stack trace if debug is enabled
1939 + log.debug("StackTrace for previous Exception: ", e.getCause());
1940 + }
1941 + counters.switchDisconnectSwitchStateException.updateCounterWithFlush();
1942 + ctx.getChannel().close();
1943 + } else if (e.getCause() instanceof OFParseError) {
1944 + log.error("Disconnecting switch "
1945 + + getSwitchInfoString() +
1946 + " due to message parse failure",
1947 + e.getCause());
1948 + counters.switchDisconnectParseError.updateCounterWithFlush();
1949 + ctx.getChannel().close();
1950 + } else if (e.getCause() instanceof RejectedExecutionException) {
1951 + log.warn("Could not process message: queue full");
1952 + counters.rejectedExecutionException.updateCounterWithFlush();
1953 + } else {
1954 + log.error("Error while processing message from switch "
1955 + + getSwitchInfoString()
1956 + + "state " + this.state, e.getCause());
1957 + counters.switchDisconnectOtherException.updateCounterWithFlush();
1958 + ctx.getChannel().close();
1959 + }
1960 + }
1961 +
1962 + @Override
1963 + public String toString() {
1964 + return getSwitchInfoString();
1965 + }
1966 +
1967 + @Override
1968 + public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
1969 + throws Exception {
1970 + OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
1971 + OFMessage m = factory.buildEchoRequest().build();
1972 + log.info("Sending Echo Request on idle channel: {}",
1973 + e.getChannel().getPipeline().getLast().toString());
1974 + e.getChannel().write(Collections.singletonList(m));
1975 + // XXX S some problems here -- echo request has no transaction id, and
1976 + // echo reply is not correlated to the echo request.
1977 + }
1978 +
1979 + @Override
1980 + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
1981 + throws Exception {
1982 + if (e.getMessage() instanceof List) {
1983 + @SuppressWarnings("unchecked")
1984 + List<OFMessage> msglist = (List<OFMessage>) e.getMessage();
1985 +
1986 +
1987 + for (OFMessage ofm : msglist) {
1988 + counters.messageReceived.updateCounterNoFlush();
1989 + // Do the actual packet processing
1990 + state.processOFMessage(this, ofm);
1991 + }
1992 + } else {
1993 + counters.messageReceived.updateCounterNoFlush();
1994 + state.processOFMessage(this, (OFMessage) e.getMessage());
1995 + }
1996 + }
1997 +
1998 +
1999 +
2000 + //*************************
2001 + // Channel utility methods
2002 + //*************************
2003 +
2004 + /**
2005 + * Is this a state in which the handshake has completed?
2006 + * @return true if the handshake is complete
2007 + */
2008 + public boolean isHandshakeComplete() {
2009 + return this.state.isHandshakeComplete();
2010 + }
2011 +
2012 + private void dispatchMessage(OFMessage m) throws IOException {
2013 + sw.handleMessage(m);
2014 + }
2015 +
2016 + /**
2017 + * Return a string describing this switch based on the already available
2018 + * information (DPID and/or remote socket).
2019 + * @return
2020 + */
2021 + private String getSwitchInfoString() {
2022 + if (sw != null) {
2023 + return sw.toString();
2024 + }
2025 + String channelString;
2026 + if (channel == null || channel.getRemoteAddress() == null) {
2027 + channelString = "?";
2028 + } else {
2029 + channelString = channel.getRemoteAddress().toString();
2030 + }
2031 + String dpidString;
2032 + if (featuresReply == null) {
2033 + dpidString = "?";
2034 + } else {
2035 + dpidString = featuresReply.getDatapathId().toString();
2036 + }
2037 + return String.format("[%s DPID[%s]]", channelString, dpidString);
2038 + }
2039 +
2040 + /**
2041 + * Update the channels state. Only called from the state machine.
2042 + * TODO: enforce restricted state transitions
2043 + * @param state
2044 + */
2045 + private void setState(ChannelState state) {
2046 + this.state = state;
2047 + }
2048 +
2049 + /**
2050 + * Send hello message to the switch using the handshake transactions ids.
2051 + * @throws IOException
2052 + */
2053 + private void sendHandshakeHelloMessage() throws IOException {
2054 + // The OF protocol requires us to start things off by sending the highest
2055 + // version of the protocol supported.
2056 +
2057 + // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04)
2058 + // see Sec. 7.5.1 of the OF1.3.4 spec
2059 + U32 bitmap = U32.ofRaw(0x00000012);
2060 + OFHelloElem hem = factory13.buildHelloElemVersionbitmap()
2061 + .setBitmaps(Collections.singletonList(bitmap))
2062 + .build();
2063 + OFMessage.Builder mb = factory13.buildHello()
2064 + .setXid(this.handshakeTransactionIds--)
2065 + .setElements(Collections.singletonList(hem));
2066 + log.info("Sending OF_13 Hello to {}", channel.getRemoteAddress());
2067 + channel.write(Collections.singletonList(mb.build()));
2068 + }
2069 +
2070 + /**
2071 + * Send featuresRequest msg to the switch using the handshake transactions ids.
2072 + * @throws IOException
2073 + */
2074 + private void sendHandshakeFeaturesRequestMessage() throws IOException {
2075 + OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
2076 + OFMessage m = factory.buildFeaturesRequest()
2077 + .setXid(this.handshakeTransactionIds--)
2078 + .build();
2079 + channel.write(Collections.singletonList(m));
2080 + }
2081 +
2082 + private void setSwitchRole(Role role) {
2083 + sw.setRole(role);
2084 + }
2085 +
2086 + /**
2087 + * Send the configuration requests to tell the switch we want full
2088 + * packets.
2089 + * @throws IOException
2090 + */
2091 + private void sendHandshakeSetConfig() throws IOException {
2092 + OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
2093 + //log.debug("Sending CONFIG_REQUEST to {}", channel.getRemoteAddress());
2094 + List<OFMessage> msglist = new ArrayList<OFMessage>(3);
2095 +
2096 + // Ensure we receive the full packet via PacketIn
2097 + // FIXME: We don't set the reassembly flags.
2098 + OFSetConfig sc = factory
2099 + .buildSetConfig()
2100 + .setMissSendLen((short) 0xffff)
2101 + .setXid(this.handshakeTransactionIds--)
2102 + .build();
2103 + msglist.add(sc);
2104 +
2105 + // Barrier
2106 + OFBarrierRequest br = factory
2107 + .buildBarrierRequest()
2108 + .setXid(this.handshakeTransactionIds--)
2109 + .build();
2110 + msglist.add(br);
2111 +
2112 + // Verify (need barrier?)
2113 + OFGetConfigRequest gcr = factory
2114 + .buildGetConfigRequest()
2115 + .setXid(this.handshakeTransactionIds--)
2116 + .build();
2117 + msglist.add(gcr);
2118 + channel.write(msglist);
2119 + }
2120 +
2121 + /**
2122 + * send a description state request.
2123 + * @throws IOException
2124 + */
2125 + private void sendHandshakeDescriptionStatsRequest() throws IOException {
2126 + // Get Description to set switch-specific flags
2127 + OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
2128 + OFDescStatsRequest dreq = factory
2129 + .buildDescStatsRequest()
2130 + .setXid(handshakeTransactionIds--)
2131 + .build();
2132 + channel.write(Collections.singletonList(dreq));
2133 + }
2134 +
2135 + private void sendHandshakeOFPortDescRequest() throws IOException {
2136 + // Get port description for 1.3 switch
2137 + OFPortDescStatsRequest preq = factory13
2138 + .buildPortDescStatsRequest()
2139 + .setXid(handshakeTransactionIds--)
2140 + .build();
2141 + channel.write(Collections.singletonList(preq));
2142 + }
2143 +
2144 + ChannelState getStateForTesting() {
2145 + return state;
2146 + }
2147 +
2148 + void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) {
2149 + roleChanger = new RoleChanger(roleTimeoutMs);
2150 + }
2151 +
2152 +
2153 +}
1 +/**
2 + * Copyright 2011, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.internal;
19 +
20 +
21 +import org.jboss.netty.buffer.ChannelBuffer;
22 +import org.jboss.netty.channel.Channel;
23 +import org.jboss.netty.channel.ChannelHandlerContext;
24 +import org.jboss.netty.handler.codec.frame.FrameDecoder;
25 +import org.projectfloodlight.openflow.protocol.OFFactories;
26 +import org.projectfloodlight.openflow.protocol.OFMessage;
27 +import org.projectfloodlight.openflow.protocol.OFMessageReader;
28 +
29 +/**
30 + * Decode an openflow message from a Channel, for use in a netty pipeline.
31 + */
32 +public class OFMessageDecoder extends FrameDecoder {
33 +
34 + @Override
35 + protected Object decode(ChannelHandlerContext ctx, Channel channel,
36 + ChannelBuffer buffer) throws Exception {
37 + if (!channel.isConnected()) {
38 + // In testing, I see decode being called AFTER decode last.
39 + // This check avoids that from reading corrupted frames
40 + return null;
41 + }
42 +
43 + // Note that a single call to decode results in reading a single
44 + // OFMessage from the channel buffer, which is passed on to, and processed
45 + // by, the controller (in OFChannelHandler).
46 + // This is different from earlier behavior (with the original openflowj),
47 + // where we parsed all the messages in the buffer, before passing on
48 + // a list of the parsed messages to the controller.
49 + // The performance *may or may not* not be as good as before.
50 + OFMessageReader<OFMessage> reader = OFFactories.getGenericReader();
51 + OFMessage message = reader.readFrom(buffer);
52 +
53 + return message;
54 + }
55 +
56 +}
1 +/**
2 + * Copyright 2011, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.internal;
19 +
20 +import java.util.List;
21 +
22 +import org.jboss.netty.buffer.ChannelBuffer;
23 +import org.jboss.netty.buffer.ChannelBuffers;
24 +import org.jboss.netty.channel.Channel;
25 +import org.jboss.netty.channel.ChannelHandlerContext;
26 +import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
27 +import org.projectfloodlight.openflow.protocol.OFMessage;
28 +
29 +
30 +/**
31 + * Encode an openflow message for output into a ChannelBuffer, for use in a
32 + * netty pipeline.
33 + */
34 +public class OFMessageEncoder extends OneToOneEncoder {
35 +
36 + @Override
37 + protected Object encode(ChannelHandlerContext ctx, Channel channel,
38 + Object msg) throws Exception {
39 + if (!(msg instanceof List)) {
40 + return msg;
41 + }
42 +
43 + @SuppressWarnings("unchecked")
44 + List<OFMessage> msglist = (List<OFMessage>) msg;
45 + /* XXX S can't get length of OFMessage in loxigen's openflowj??
46 + int size = 0;
47 + for (OFMessage ofm : msglist) {
48 + size += ofm.getLengthU();
49 + }*/
50 +
51 + ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
52 +
53 + for (OFMessage ofm : msglist) {
54 + ofm.writeTo(buf);
55 + }
56 + return buf;
57 + }
58 +
59 +}
1 +/**
2 +* Copyright 2011, Big Switch Networks, Inc.
3 +* Originally created by David Erickson, Stanford University
4 +*
5 +* Licensed under the Apache License, Version 2.0 (the "License"); you may
6 +* not use this file except in compliance with the License. You may obtain
7 +* a copy of the License at
8 +*
9 +* http://www.apache.org/licenses/LICENSE-2.0
10 +*
11 +* Unless required by applicable law or agreed to in writing, software
12 +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 +* License for the specific language governing permissions and limitations
15 +* under the License.
16 +**/
17 +
18 +package net.onrc.onos.of.ctl.internal;
19 +
20 +import java.util.concurrent.ThreadPoolExecutor;
21 +
22 +import org.jboss.netty.channel.ChannelPipeline;
23 +import org.jboss.netty.channel.ChannelPipelineFactory;
24 +import org.jboss.netty.channel.Channels;
25 +import org.jboss.netty.handler.execution.ExecutionHandler;
26 +import org.jboss.netty.handler.timeout.IdleStateHandler;
27 +import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
28 +import org.jboss.netty.util.ExternalResourceReleasable;
29 +import org.jboss.netty.util.HashedWheelTimer;
30 +import org.jboss.netty.util.Timer;
31 +
32 +/**
33 + * Creates a ChannelPipeline for a server-side openflow channel.
34 + */
35 +public class OpenflowPipelineFactory
36 + implements ChannelPipelineFactory, ExternalResourceReleasable {
37 +
38 + protected Controller controller;
39 + protected ThreadPoolExecutor pipelineExecutor;
40 + protected Timer timer;
41 + protected IdleStateHandler idleHandler;
42 + protected ReadTimeoutHandler readTimeoutHandler;
43 +
44 + public OpenflowPipelineFactory(Controller controller,
45 + ThreadPoolExecutor pipelineExecutor) {
46 + super();
47 + this.controller = controller;
48 + this.pipelineExecutor = pipelineExecutor;
49 + this.timer = new HashedWheelTimer();
50 + this.idleHandler = new IdleStateHandler(timer, 20, 25, 0);
51 + this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30);
52 + }
53 +
54 + @Override
55 + public ChannelPipeline getPipeline() throws Exception {
56 + OFChannelHandler handler = new OFChannelHandler(controller);
57 +
58 + ChannelPipeline pipeline = Channels.pipeline();
59 + pipeline.addLast("ofmessagedecoder", new OFMessageDecoder());
60 + pipeline.addLast("ofmessageencoder", new OFMessageEncoder());
61 + pipeline.addLast("idle", idleHandler);
62 + pipeline.addLast("timeout", readTimeoutHandler);
63 + // XXX S ONOS: was 15 increased it to fix Issue #296
64 + pipeline.addLast("handshaketimeout",
65 + new HandshakeTimeoutHandler(handler, timer, 60));
66 + if (pipelineExecutor != null) {
67 + pipeline.addLast("pipelineExecutor",
68 + new ExecutionHandler(pipelineExecutor));
69 + }
70 + pipeline.addLast("handler", handler);
71 + return pipeline;
72 + }
73 +
74 + @Override
75 + public void releaseExternalResources() {
76 + timer.stop();
77 + }
78 +}
1 +package net.onrc.onos.of.ctl.internal;
2 +
3 +/**
4 + * Thrown when IOFSwitch.startDriverHandshake() is called more than once.
5 + *
6 + */
7 +public class SwitchDriverSubHandshakeAlreadyStarted extends
8 + SwitchDriverSubHandshakeException {
9 + private static final long serialVersionUID = -5491845708752443501L;
10 +
11 + public SwitchDriverSubHandshakeAlreadyStarted() {
12 + super();
13 + }
14 +}
1 +package net.onrc.onos.of.ctl.internal;
2 +
3 +import org.projectfloodlight.openflow.protocol.OFMessage;
4 +
5 +
6 +/**
7 + * Indicates that a message was passed to a switch driver's subhandshake
8 + * handling code but the driver has already completed the sub-handshake.
9 + *
10 + */
11 +public class SwitchDriverSubHandshakeCompleted
12 + extends SwitchDriverSubHandshakeException {
13 + private static final long serialVersionUID = -8817822245846375995L;
14 +
15 + public SwitchDriverSubHandshakeCompleted(OFMessage m) {
16 + super("Sub-Handshake is already complete but received message "
17 + + m.getType());
18 + }
19 +}
1 +package net.onrc.onos.of.ctl.internal;
2 +
3 +/**
4 + * Base class for exception thrown by switch driver sub-handshake processing.
5 + *
6 + */
7 +public class SwitchDriverSubHandshakeException extends RuntimeException {
8 + private static final long serialVersionUID = -6257836781419604438L;
9 +
10 + protected SwitchDriverSubHandshakeException() {
11 + super();
12 + }
13 +
14 + protected SwitchDriverSubHandshakeException(String arg0, Throwable arg1) {
15 + super(arg0, arg1);
16 + }
17 +
18 + protected SwitchDriverSubHandshakeException(String arg0) {
19 + super(arg0);
20 + }
21 +
22 + protected SwitchDriverSubHandshakeException(Throwable arg0) {
23 + super(arg0);
24 + }
25 +
26 +}
1 +package net.onrc.onos.of.ctl.internal;
2 +
3 +/**
4 + * Thrown when a switch driver's sub-handshake has not been started but an
5 + * operation requiring the sub-handshake has been attempted.
6 + *
7 + */
8 +public class SwitchDriverSubHandshakeNotStarted extends
9 + SwitchDriverSubHandshakeException {
10 + private static final long serialVersionUID = -5491845708752443501L;
11 +
12 + public SwitchDriverSubHandshakeNotStarted() {
13 + super();
14 + }
15 +}
1 +package net.onrc.onos.of.ctl.internal;
2 +
3 +/**
4 + * Thrown when a switch driver's sub-handshake state-machine receives an
5 + * unexpected OFMessage and/or is in an invald state.
6 + *
7 + */
8 +public class SwitchDriverSubHandshakeStateException extends
9 + SwitchDriverSubHandshakeException {
10 + private static final long serialVersionUID = -8249926069195147051L;
11 +
12 + public SwitchDriverSubHandshakeStateException(String msg) {
13 + super(msg);
14 + }
15 +}
1 +/**
2 + * Copyright 2011, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.internal;
19 +
20 +/**
21 + * This exception indicates an error or unexpected message during
22 + * message handling. E.g., if an OFMessage is received that is illegal or
23 + * unexpected given the current handshake state.
24 + *
25 + * We don't allow wrapping other exception in a switch state exception. We
26 + * only log the SwitchStateExceptions message so the causing exceptions
27 + * stack trace is generally not available.
28 + *
29 + */
30 +public class SwitchStateException extends Exception {
31 +
32 + private static final long serialVersionUID = 9153954512470002631L;
33 +
34 + public SwitchStateException() {
35 + super();
36 + }
37 +
38 + public SwitchStateException(String arg0, Throwable arg1) {
39 + super(arg0, arg1);
40 + }
41 +
42 + public SwitchStateException(String arg0) {
43 + super(arg0);
44 + }
45 +
46 + public SwitchStateException(Throwable arg0) {
47 + super(arg0);
48 + }
49 +
50 +}
1 +package net.onrc.onos.of.ctl.registry;
2 +
3 +
4 +
5 +public class ControllerRegistryEntry implements Comparable<ControllerRegistryEntry> {
6 + //
7 + // TODO: Refactor the implementation and decide whether controllerId
8 + // is needed. If "yes", we might need to consider it inside the
9 + // compareTo(), equals() and hashCode() implementations.
10 + //
11 + private final String controllerId;
12 + private final int sequenceNumber;
13 +
14 + public ControllerRegistryEntry(String controllerId, int sequenceNumber) {
15 + this.controllerId = controllerId;
16 + this.sequenceNumber = sequenceNumber;
17 + }
18 +
19 + public String getControllerId() {
20 + return controllerId;
21 + }
22 +
23 + /**
24 + * Compares this object with the specified object for order.
25 + * NOTE: the test is based on ControllerRegistryEntry sequence numbers,
26 + * and doesn't include the controllerId.
27 + *
28 + * @param o the object to be compared.
29 + * @return a negative integer, zero, or a positive integer as this object
30 + * is less than, equal to, or greater than the specified object.
31 + */
32 + @Override
33 + public int compareTo(ControllerRegistryEntry o) {
34 + return this.sequenceNumber - o.sequenceNumber;
35 + }
36 +
37 + /**
38 + * Test whether some other object is "equal to" this one.
39 + * NOTE: the test is based on ControllerRegistryEntry sequence numbers,
40 + * and doesn't include the controllerId.
41 + *
42 + * @param obj the reference object with which to compare.
43 + * @return true if this object is the same as the obj argument; false
44 + * otherwise.
45 + */
46 + @Override
47 + public boolean equals(Object obj) {
48 + if (obj instanceof ControllerRegistryEntry) {
49 + ControllerRegistryEntry other = (ControllerRegistryEntry) obj;
50 + return this.sequenceNumber == other.sequenceNumber;
51 + }
52 + return false;
53 + }
54 +
55 + /**
56 + * Get the hash code for the object.
57 + * NOTE: the computation is based on ControllerRegistryEntry sequence
58 + * numbers, and doesn't include the controller ID.
59 + *
60 + * @return a hash code value for this object.
61 + */
62 + @Override
63 + public int hashCode() {
64 + return Integer.valueOf(this.sequenceNumber).hashCode();
65 + }
66 +}
1 +package net.onrc.onos.of.ctl.registry;
2 +
3 +import java.util.Collection;
4 +import java.util.List;
5 +import java.util.Map;
6 +
7 +import net.onrc.onos.of.ctl.util.InstanceId;
8 +
9 +/**
10 + * A registry service that allows ONOS to register controllers and switches in a
11 + * way that is global to the entire ONOS cluster. The registry is the arbiter
12 + * for allowing controllers to control switches.
13 + * <p/>
14 + * The OVS/OF1.{2,3} fault tolerance model is a switch connects to multiple
15 + * controllers, and the controllers send role requests to tell the switch their
16 + * role in controlling the switch.
17 + * <p/>
18 + * The ONOS fault tolerance model allows only a single controller to have
19 + * control of a switch (MASTER role) at once. Controllers therefore need a
20 + * mechanism that enables them to decide who should control a each switch. The
21 + * registry service provides this mechanism.
22 + */
23 +public interface IControllerRegistry {
24 +
25 + /**
26 + * Callback interface for control change events.
27 + */
28 + public interface ControlChangeCallback {
29 + /**
30 + * Called whenever the control changes from the point of view of the
31 + * registry. The callee can check whether they have control or not using
32 + * the hasControl parameter.
33 + *
34 + * @param dpid The switch that control has changed for
35 + * @param hasControl Whether the listener now has control or not
36 + */
37 + void controlChanged(long dpid, boolean hasControl);
38 + }
39 +
40 + /**
41 + * Request for control of a switch. This method does not block. When control
42 + * for a switch changes, the controlChanged method on the callback object
43 + * will be called. This happens any time the control changes while the
44 + * request is still active (until releaseControl is called)
45 + *
46 + * @param dpid Switch to request control for
47 + * @param cb Callback that will be used to notify caller of control changes
48 + * @throws RegistryException Errors contacting the registry service
49 + */
50 + public void requestControl(long dpid, ControlChangeCallback cb)
51 + throws RegistryException;
52 +
53 + /**
54 + * Stop trying to take control of a switch. This removes the entry for this
55 + * controller requesting this switch in the registry. If the controller had
56 + * control when this is called, another controller will now gain control of
57 + * the switch. This call doesn't block.
58 + *
59 + * @param dpid Switch to release control of
60 + */
61 + public void releaseControl(long dpid);
62 +
63 + /**
64 + * Check whether the controller has control of the switch This call doesn't
65 + * block.
66 + *
67 + * @param dpid Switch to check control of
68 + * @return true if controller has control of the switch.
69 + */
70 + public boolean hasControl(long dpid);
71 +
72 + /**
73 + * Check whether this instance is the leader for the cluster. This call
74 + * doesn't block.
75 + *
76 + * @return true if the instance is the leader for the cluster, otherwise
77 + * false.
78 + */
79 + public boolean isClusterLeader();
80 +
81 + /**
82 + * Gets the unique ID used to identify this ONOS instance in the cluster.
83 + *
84 + * @return Instance ID.
85 + */
86 + public InstanceId getOnosInstanceId();
87 +
88 + /**
89 + * Register a controller to the ONOS cluster. Must be called before the
90 + * registry can be used to take control of any switches.
91 + *
92 + * @param controllerId A unique string ID identifying this controller in the
93 + * cluster
94 + * @throws RegistryException for errors connecting to registry service,
95 + * controllerId already registered
96 + */
97 + public void registerController(String controllerId)
98 + throws RegistryException;
99 +
100 + /**
101 + * Get all controllers in the cluster.
102 + *
103 + * @return Collection of controller IDs
104 + * @throws RegistryException on error
105 + */
106 + public Collection<String> getAllControllers() throws RegistryException;
107 +
108 + /**
109 + * Get all switches in the cluster, along with which controller is in
110 + * control of them (if any) and any other controllers that have requested
111 + * control.
112 + *
113 + * @return Map of all switches.
114 + */
115 + public Map<String, List<ControllerRegistryEntry>> getAllSwitches();
116 +
117 + /**
118 + * Get the controller that has control of a given switch.
119 + *
120 + * @param dpid Switch to find controller for
121 + * @return controller ID
122 + * @throws RegistryException Errors contacting registry service
123 + */
124 + public String getControllerForSwitch(long dpid) throws RegistryException;
125 +
126 + /**
127 + * Get all switches controlled by a given controller.
128 + *
129 + * @param controllerId ID of the controller
130 + * @return Collection of dpids
131 + */
132 + public Collection<Long> getSwitchesControlledByController(String controllerId);
133 +
134 + /**
135 + * Get a unique Id Block.
136 + *
137 + * @return Id Block.
138 + */
139 + public IdBlock allocateUniqueIdBlock();
140 +
141 + /**
142 + * Get next unique id and retrieve a new range of ids if needed.
143 + *
144 + * @param range range to use for the identifier
145 + * @return Id Block.
146 + */
147 + public IdBlock allocateUniqueIdBlock(long range);
148 +
149 + /**
150 + * Get a globally unique ID.
151 + *
152 + * @return a globally unique ID.
153 + */
154 + public long getNextUniqueId();
155 +}
1 +package net.onrc.onos.of.ctl.registry;
2 +
3 +public class IdBlock {
4 + private final long start;
5 + private final long end;
6 + private final long size;
7 +
8 + public IdBlock(long start, long end, long size) {
9 + this.start = start;
10 + this.end = end;
11 + this.size = size;
12 + }
13 +
14 + public long getStart() {
15 + return start;
16 + }
17 +
18 + public long getEnd() {
19 + return end;
20 + }
21 +
22 + public long getSize() {
23 + return size;
24 + }
25 +
26 + @Override
27 + public String toString() {
28 + return "IdBlock [start=" + start + ", end=" + end + ", size=" + size
29 + + "]";
30 + }
31 +}
32 +
1 +package net.onrc.onos.of.ctl.registry;
2 +
3 +public class RegistryException extends Exception {
4 +
5 + private static final long serialVersionUID = -8276300722010217913L;
6 +
7 + public RegistryException(String message) {
8 + super(message);
9 + }
10 +
11 + public RegistryException(String message, Throwable cause) {
12 + super(message, cause);
13 + }
14 +
15 +}
1 +package net.onrc.onos.of.ctl.util;
2 +
3 +import org.projectfloodlight.openflow.util.HexString;
4 +
5 +/**
6 + * The class representing a network switch DPID.
7 + * This class is immutable.
8 + */
9 +public final class Dpid {
10 + private static final long UNKNOWN = 0;
11 + private final long value;
12 +
13 + /**
14 + * Default constructor.
15 + */
16 + public Dpid() {
17 + this.value = Dpid.UNKNOWN;
18 + }
19 +
20 + /**
21 + * Constructor from a long value.
22 + *
23 + * @param value the value to use.
24 + */
25 + public Dpid(long value) {
26 + this.value = value;
27 + }
28 +
29 + /**
30 + * Constructor from a string.
31 + *
32 + * @param value the value to use.
33 + */
34 + public Dpid(String value) {
35 + this.value = HexString.toLong(value);
36 + }
37 +
38 + /**
39 + * Get the value of the DPID.
40 + *
41 + * @return the value of the DPID.
42 + */
43 + public long value() {
44 + return value;
45 + }
46 +
47 + /**
48 + * Convert the DPID value to a ':' separated hexadecimal string.
49 + *
50 + * @return the DPID value as a ':' separated hexadecimal string.
51 + */
52 + @Override
53 + public String toString() {
54 + return HexString.toHexString(this.value);
55 + }
56 +
57 + @Override
58 + public boolean equals(Object other) {
59 + if (!(other instanceof Dpid)) {
60 + return false;
61 + }
62 +
63 + Dpid otherDpid = (Dpid) other;
64 +
65 + return value == otherDpid.value;
66 + }
67 +
68 + @Override
69 + public int hashCode() {
70 + int hash = 17;
71 + hash += 31 * hash + (int) (value ^ value >>> 32);
72 + return hash;
73 + }
74 +}
1 +package net.onrc.onos.of.ctl.util;
2 +
3 +import java.io.IOException;
4 +import java.util.Collection;
5 +import java.util.Date;
6 +import java.util.List;
7 +import java.util.Map;
8 +import java.util.Set;
9 +import java.util.concurrent.Future;
10 +
11 +import org.jboss.netty.channel.Channel;
12 +import org.projectfloodlight.openflow.protocol.OFActionType;
13 +import org.projectfloodlight.openflow.protocol.OFCapabilities;
14 +import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
15 +import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
16 +import org.projectfloodlight.openflow.protocol.OFMessage;
17 +import org.projectfloodlight.openflow.protocol.OFPortDesc;
18 +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
19 +import org.projectfloodlight.openflow.protocol.OFPortStatus;
20 +import org.projectfloodlight.openflow.protocol.OFStatsReply;
21 +import org.projectfloodlight.openflow.protocol.OFStatsRequest;
22 +import org.projectfloodlight.openflow.protocol.OFVersion;
23 +import org.projectfloodlight.openflow.types.DatapathId;
24 +import org.projectfloodlight.openflow.types.U64;
25 +import org.slf4j.Logger;
26 +import org.slf4j.LoggerFactory;
27 +
28 +import net.onrc.onos.of.ctl.IOFSwitch;
29 +import net.onrc.onos.of.ctl.Role;
30 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService;
31 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterException;
32 +
33 +public class DummySwitchForTesting implements IOFSwitch {
34 +
35 + protected static final Logger log = LoggerFactory.getLogger(DummySwitchForTesting.class);
36 +
37 + private Channel channel;
38 + private boolean connected = false;
39 + private OFVersion ofv = OFVersion.OF_10;
40 +
41 + private Collection<OFPortDesc> ports;
42 +
43 + private DatapathId datapathId;
44 +
45 + private Set<OFCapabilities> capabilities;
46 +
47 + private int buffers;
48 +
49 + private byte tables;
50 +
51 + private String stringId;
52 +
53 + private Role role;
54 +
55 + @Override
56 + public void disconnectSwitch() {
57 + this.channel.close();
58 + }
59 +
60 + @Override
61 + public void write(OFMessage m) throws IOException {
62 + this.channel.write(m);
63 +
64 + }
65 +
66 + @Override
67 + public void write(List<OFMessage> msglist) throws IOException {
68 + for (OFMessage m : msglist) {
69 + this.channel.write(m);
70 + }
71 +
72 + }
73 +
74 + @Override
75 + public Date getConnectedSince() {
76 + // TODO Auto-generated method stub
77 + return null;
78 + }
79 +
80 + @Override
81 + public int getNextTransactionId() {
82 + return 0;
83 + }
84 +
85 + @Override
86 + public boolean isConnected() {
87 + return this.connected;
88 + }
89 +
90 + @Override
91 + public void setConnected(boolean connected) {
92 + this.connected = connected;
93 +
94 + }
95 +
96 + @Override
97 + public void flush() {
98 + // TODO Auto-generated method stub
99 +
100 + }
101 +
102 + @Override
103 + public void setChannel(Channel channel) {
104 + this.channel = channel;
105 +
106 + }
107 +
108 + @Override
109 + public long getId() {
110 + if (this.stringId == null) {
111 + throw new RuntimeException("Features reply has not yet been set");
112 + }
113 + return this.datapathId.getLong();
114 + }
115 +
116 + @Override
117 + public String getStringId() {
118 + // TODO Auto-generated method stub
119 + return "DummySwitch";
120 + }
121 +
122 + @Override
123 + public int getNumBuffers() {
124 + // TODO Auto-generated method stub
125 + return 0;
126 + }
127 +
128 + @Override
129 + public Set<OFCapabilities> getCapabilities() {
130 + // TODO Auto-generated method stub
131 + return null;
132 + }
133 +
134 + @Override
135 + public byte getNumTables() {
136 + // TODO Auto-generated method stub
137 + return 0;
138 + }
139 +
140 + @Override
141 + public OFDescStatsReply getSwitchDescription() {
142 + // TODO Auto-generated method stub
143 + return null;
144 + }
145 +
146 + @Override
147 + public void cancelFeaturesReply(int transactionId) {
148 + // TODO Auto-generated method stub
149 +
150 + }
151 +
152 + @Override
153 + public Set<OFActionType> getActions() {
154 + // TODO Auto-generated method stub
155 + return null;
156 + }
157 +
158 + @Override
159 + public void setOFVersion(OFVersion version) {
160 + // TODO Auto-generated method stub
161 +
162 + }
163 +
164 + @Override
165 + public OFVersion getOFVersion() {
166 + return this.ofv;
167 + }
168 +
169 + @Override
170 + public Collection<OFPortDesc> getEnabledPorts() {
171 + // TODO Auto-generated method stub
172 + return null;
173 + }
174 +
175 + @Override
176 + public Collection<Integer> getEnabledPortNumbers() {
177 + // TODO Auto-generated method stub
178 + return null;
179 + }
180 +
181 + @Override
182 + public OFPortDesc getPort(int portNumber) {
183 + // TODO Auto-generated method stub
184 + return null;
185 + }
186 +
187 + @Override
188 + public OFPortDesc getPort(String portName) {
189 + // TODO Auto-generated method stub
190 + return null;
191 + }
192 +
193 + @Override
194 + public OrderedCollection<PortChangeEvent> processOFPortStatus(
195 + OFPortStatus ps) {
196 + // TODO Auto-generated method stub
197 + return null;
198 + }
199 +
200 + @Override
201 + public Collection<OFPortDesc> getPorts() {
202 + return ports;
203 + }
204 +
205 + @Override
206 + public boolean portEnabled(int portName) {
207 + // TODO Auto-generated method stub
208 + return false;
209 + }
210 +
211 + @Override
212 + public OrderedCollection<PortChangeEvent> setPorts(
213 + Collection<OFPortDesc> p) {
214 + this.ports = p;
215 + return null;
216 + }
217 +
218 + @Override
219 + public Map<Object, Object> getAttributes() {
220 + return null;
221 + }
222 +
223 + @Override
224 + public boolean hasAttribute(String name) {
225 + // TODO Auto-generated method stub
226 + return false;
227 + }
228 +
229 + @Override
230 + public Object getAttribute(String name) {
231 + return Boolean.FALSE;
232 + }
233 +
234 + @Override
235 + public void setAttribute(String name, Object value) {
236 + // TODO Auto-generated method stub
237 +
238 + }
239 +
240 + @Override
241 + public Object removeAttribute(String name) {
242 + // TODO Auto-generated method stub
243 + return null;
244 + }
245 +
246 + @Override
247 + public void deliverStatisticsReply(OFMessage reply) {
248 + // TODO Auto-generated method stub
249 +
250 + }
251 +
252 + @Override
253 + public void cancelStatisticsReply(int transactionId) {
254 + // TODO Auto-generated method stub
255 +
256 + }
257 +
258 + @Override
259 + public void cancelAllStatisticsReplies() {
260 + // TODO Auto-generated method stub
261 +
262 + }
263 +
264 + @Override
265 + public Future<List<OFStatsReply>> getStatistics(OFStatsRequest<?> request)
266 + throws IOException {
267 + // TODO Auto-generated method stub
268 + return null;
269 + }
270 +
271 + @Override
272 + public void clearAllFlowMods() {
273 + // TODO Auto-generated method stub
274 +
275 + }
276 +
277 + @Override
278 + public Role getRole() {
279 + return this.role;
280 + }
281 +
282 + @Override
283 + public void setRole(Role role) {
284 + this.role = role;
285 + }
286 +
287 + @Override
288 + public U64 getNextGenerationId() {
289 + // TODO Auto-generated method stub
290 + return null;
291 + }
292 +
293 + @Override
294 + public void setDebugCounterService(IDebugCounterService debugCounter)
295 + throws CounterException {
296 + // TODO Auto-generated method stub
297 +
298 + }
299 +
300 + @Override
301 + public void startDriverHandshake() throws IOException {
302 + // TODO Auto-generated method stub
303 +
304 + }
305 +
306 + @Override
307 + public boolean isDriverHandshakeComplete() {
308 + return true;
309 + }
310 +
311 + @Override
312 + public void processDriverHandshakeMessage(OFMessage m) {
313 +
314 + }
315 +
316 + @Override
317 + public void setTableFull(boolean isFull) {
318 + // TODO Auto-generated method stub
319 +
320 + }
321 +
322 + @Override
323 + public void setFeaturesReply(OFFeaturesReply featuresReply) {
324 + if (featuresReply == null) {
325 + log.error("Error setting featuresReply for switch: {}", getStringId());
326 + return;
327 + }
328 + this.datapathId = featuresReply.getDatapathId();
329 + this.capabilities = featuresReply.getCapabilities();
330 + this.buffers = (int) featuresReply.getNBuffers();
331 + this.tables = (byte) featuresReply.getNTables();
332 + this.stringId = this.datapathId.toString();
333 +
334 + }
335 +
336 + @Override
337 + public void setPortDescReply(OFPortDescStatsReply portDescReply) {
338 + // TODO Auto-generated method stub
339 +
340 + }
341 +
342 + @Override
343 + public void handleMessage(OFMessage m) {
344 + log.info("Got packet {} but I am dumb so I don't know what to do.", m);
345 + }
346 +
347 + @Override
348 + public boolean portEnabled(String portName) {
349 + // TODO Auto-generated method stub
350 + return false;
351 + }
352 +
353 + @Override
354 + public OrderedCollection<PortChangeEvent> comparePorts(
355 + Collection<OFPortDesc> p) {
356 + // TODO Auto-generated method stub
357 + return null;
358 + }
359 +
360 +}
1 +package net.onrc.onos.of.ctl.util;
2 +
3 +import java.util.EnumSet;
4 +import java.util.Set;
5 +
6 +/**
7 + * A utility class to convert between integer based bitmaps for (OpenFlow)
8 + * flags and Enum and EnumSet based representations.
9 + *
10 + * The enum used to represent individual flags needs to implement the
11 + * BitmapableEnum interface.
12 + *
13 + * Example:
14 + * {@code
15 + * int bitmap = 0x11; // OFPPC_PORT_DOWN | OFPPC_NO_STP
16 + * EnumSet<OFPortConfig> s = toEnumSet(OFPortConfig.class, bitmap);
17 + * // s will contain OFPPC_PORT_DOWN and OFPPC_NO_STP
18 + * }
19 + *
20 + * {@code
21 + * EnumSet<OFPortConfig> s = EnumSet.of(OFPPC_NO_STP, OFPPC_PORT_DOWN);
22 + * int bitmap = toBitmap(s); // returns 0x11
23 + * }
24 + *
25 + */
26 +public final class EnumBitmaps {
27 +
28 +
29 + private EnumBitmaps() { }
30 +
31 + /**
32 + * Enums used to represent individual flags needs to implement this
33 + * interface.
34 + */
35 + public interface BitmapableEnum {
36 + /** Return the value in the bitmap that the enum constant represents.
37 + * The returned value must have only a single bit set. E.g.,1 << 3
38 + */
39 + int getValue();
40 + }
41 +
42 +
43 + /**
44 + * Convert an integer bitmap to an EnumSet.
45 + *
46 + * See class description for example
47 + * @param type The Enum class to use. Must implement BitmapableEnum
48 + * @param bitmap The integer bitmap
49 + * @return A newly allocated EnumSet representing the bits set in the
50 + * bitmap
51 + * @throws NullPointerException if type is null
52 + * @throws IllegalArgumentException if any enum constant from type has
53 + * more than one bit set.
54 + * @throws IllegalArgumentException if the bitmap has any bits set not
55 + * represented by an enum constant.
56 + */
57 + public static <E extends Enum<E> & BitmapableEnum>
58 + EnumSet<E> toEnumSet(Class<E> type, int bitmap) {
59 + if (type == null) {
60 + throw new NullPointerException("Given enum type must not be null");
61 + }
62 + EnumSet<E> s = EnumSet.noneOf(type);
63 + // allSetBitmap will eventually have all valid bits for the given
64 + // type set.
65 + int allSetBitmap = 0;
66 + for (E element: type.getEnumConstants()) {
67 + if (Integer.bitCount(element.getValue()) != 1) {
68 + String msg = String.format("The %s (%x) constant of the " +
69 + "enum %s is supposed to represent a bitmap entry but " +
70 + "has more than one bit set.",
71 + element.toString(), element.getValue(), type.getName());
72 + throw new IllegalArgumentException(msg);
73 + }
74 + allSetBitmap |= element.getValue();
75 + if ((bitmap & element.getValue()) != 0) {
76 + s.add(element);
77 + }
78 + }
79 + if (((~allSetBitmap) & bitmap) != 0) {
80 + // check if only valid flags are set in the given bitmap
81 + String msg = String.format("The bitmap %x for enum %s has " +
82 + "bits set that are presented by any enum constant",
83 + bitmap, type.getName());
84 + throw new IllegalArgumentException(msg);
85 + }
86 + return s;
87 + }
88 +
89 + /**
90 + * Return the bitmap mask with all possible bits set. E.g., If a bitmap
91 + * has the individual flags 0x1, 0x2, and 0x8 (note the missing 0x4) then
92 + * the mask will be 0xb (1011 binary)
93 + *
94 + * @param type The Enum class to use. Must implement BitmapableEnum
95 + * @throws NullPointerException if type is null
96 + * @throws IllegalArgumentException if any enum constant from type has
97 + * more than one bit set
98 + * @return an integer with all possible bits for the given bitmap enum
99 + * type set.
100 + */
101 + public static <E extends Enum<E> & BitmapableEnum>
102 + int getMask(Class<E> type) {
103 + if (type == null) {
104 + throw new NullPointerException("Given enum type must not be null");
105 + }
106 + // allSetBitmap will eventually have all valid bits for the given
107 + // type set.
108 + int allSetBitmap = 0;
109 + for (E element: type.getEnumConstants()) {
110 + if (Integer.bitCount(element.getValue()) != 1) {
111 + String msg = String.format("The %s (%x) constant of the " +
112 + "enum %s is supposed to represent a bitmap entry but " +
113 + "has more than one bit set.",
114 + element.toString(), element.getValue(), type.getName());
115 + throw new IllegalArgumentException(msg);
116 + }
117 + allSetBitmap |= element.getValue();
118 + }
119 + return allSetBitmap;
120 + }
121 +
122 + /**
123 + * Convert the given EnumSet to the integer bitmap representation.
124 + * @param set The EnumSet to convert. The enum must implement
125 + * BitmapableEnum
126 + * @return the integer bitmap
127 + * @throws IllegalArgumentException if an enum constant from the set (!) has
128 + * more than one bit set
129 + * @throws NullPointerException if the set is null
130 + */
131 + public static <E extends Enum<E> & BitmapableEnum>
132 + int toBitmap(Set<E> set) {
133 + if (set == null) {
134 + throw new NullPointerException("Given set must not be null");
135 + }
136 + int bitmap = 0;
137 + for (E element: set) {
138 + if (Integer.bitCount(element.getValue()) != 1) {
139 + String msg = String.format("The %s (%x) constant in the set " +
140 + "is supposed to represent a bitmap entry but " +
141 + "has more than one bit set.",
142 + element.toString(), element.getValue());
143 + throw new IllegalArgumentException(msg);
144 + }
145 + bitmap |= element.getValue();
146 + }
147 + return bitmap;
148 + }
149 +}
1 +/**
2 + * Copyright 2012, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.util;
19 +
20 +import java.util.Iterator;
21 +import java.util.NoSuchElementException;
22 +
23 +/**
24 + * An iterator that will filter values from an iterator and return only
25 + * those values that match the predicate.
26 + */
27 +public abstract class FilterIterator<T> implements Iterator<T> {
28 + protected Iterator<T> subIterator;
29 + protected T next;
30 +
31 + /**
32 + * Construct a filter iterator from the given sub iterator.
33 + *
34 + * @param subIterator the sub iterator over which we'll filter
35 + */
36 + public FilterIterator(Iterator<T> subIterator) {
37 + super();
38 + this.subIterator = subIterator;
39 + }
40 +
41 + /**
42 + * Check whether the given value should be returned by the
43 + * filter.
44 + *
45 + * @param value the value to check
46 + * @return true if the value should be included
47 + */
48 + protected abstract boolean matches(T value);
49 +
50 + // ***********
51 + // Iterator<T>
52 + // ***********
53 +
54 + @Override
55 + public boolean hasNext() {
56 + if (next != null) {
57 + return true;
58 + }
59 +
60 + while (subIterator.hasNext()) {
61 + next = subIterator.next();
62 + if (matches(next)) {
63 + return true;
64 + }
65 + }
66 + next = null;
67 + return false;
68 + }
69 +
70 + @Override
71 + public T next() {
72 + if (hasNext()) {
73 + T cur = next;
74 + next = null;
75 + return cur;
76 + }
77 + throw new NoSuchElementException();
78 + }
79 +
80 + @Override
81 + public void remove() {
82 + throw new UnsupportedOperationException();
83 + }
84 +
85 +}
1 +package net.onrc.onos.of.ctl.util;
2 +
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +import static com.google.common.base.Preconditions.checkArgument;
5 +
6 +/**
7 + * The class representing an ONOS Instance ID.
8 + *
9 + * This class is immutable.
10 + */
11 +public final class InstanceId {
12 + private final String id;
13 +
14 + /**
15 + * Constructor from a string value.
16 + *
17 + * @param id the value to use.
18 + */
19 + public InstanceId(String id) {
20 + this.id = checkNotNull(id);
21 + checkArgument(!id.isEmpty(), "Empty ONOS Instance ID");
22 + }
23 +
24 + @Override
25 + public int hashCode() {
26 + return id.hashCode();
27 + }
28 +
29 + @Override
30 + public boolean equals(Object obj) {
31 + if (obj == this) {
32 + return true;
33 + }
34 +
35 + if (!(obj instanceof InstanceId)) {
36 + return false;
37 + }
38 +
39 + InstanceId that = (InstanceId) obj;
40 + return this.id.equals(that.id);
41 + }
42 +
43 + @Override
44 + public String toString() {
45 + return id;
46 + }
47 +}
1 +/**
2 + * Copyright 2012 Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.util;
19 +
20 +import java.util.Iterator;
21 +import java.util.NoSuchElementException;
22 +
23 +/**
24 + * Iterator over all values in an iterator of iterators.
25 + *
26 + * @param <T> the type of elements returned by this iterator
27 + */
28 +public class IterableIterator<T> implements Iterator<T> {
29 + Iterator<? extends Iterable<T>> subIterator;
30 + Iterator<T> current = null;
31 +
32 + public IterableIterator(Iterator<? extends Iterable<T>> subIterator) {
33 + super();
34 + this.subIterator = subIterator;
35 + }
36 +
37 + @Override
38 + public boolean hasNext() {
39 + if (current == null) {
40 + if (subIterator.hasNext()) {
41 + current = subIterator.next().iterator();
42 + } else {
43 + return false;
44 + }
45 + }
46 + while (!current.hasNext() && subIterator.hasNext()) {
47 + current = subIterator.next().iterator();
48 + }
49 +
50 + return current.hasNext();
51 + }
52 +
53 + @Override
54 + public T next() {
55 + if (hasNext()) {
56 + return current.next();
57 + }
58 + throw new NoSuchElementException();
59 + }
60 +
61 + @Override
62 + public void remove() {
63 + if (hasNext()) {
64 + current.remove();
65 + }
66 + throw new NoSuchElementException();
67 + }
68 +}
1 +/**
2 + * Copyright 2011, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.util;
19 +
20 +import java.util.LinkedHashMap;
21 +import java.util.Map;
22 +
23 +public class LRUHashMap<K, V> extends LinkedHashMap<K, V> {
24 +
25 + private static final long serialVersionUID = 1L;
26 +
27 + private final int capacity;
28 +
29 + public LRUHashMap(int capacity) {
30 + super(capacity + 1, 0.75f, true);
31 + this.capacity = capacity;
32 + }
33 +
34 + protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
35 + return size() > capacity;
36 + }
37 +
38 +}
1 +package net.onrc.onos.of.ctl.util;
2 +
3 +import java.util.Collection;
4 +import java.util.LinkedHashSet;
5 +
6 +import com.google.common.collect.ForwardingCollection;
7 +
8 +/**
9 + * A simple wrapper / forwarder that forwards all calls to a LinkedHashSet.
10 + * This wrappers sole reason for existence is to implement the
11 + * OrderedCollection marker interface.
12 + *
13 + */
14 +public class LinkedHashSetWrapper<E>
15 + extends ForwardingCollection<E> implements OrderedCollection<E> {
16 + private final Collection<E> delegate;
17 +
18 + public LinkedHashSetWrapper() {
19 + super();
20 + this.delegate = new LinkedHashSet<E>();
21 + }
22 +
23 + public LinkedHashSetWrapper(Collection<? extends E> c) {
24 + super();
25 + this.delegate = new LinkedHashSet<E>(c);
26 + }
27 +
28 + @Override
29 + protected Collection<E> delegate() {
30 + return this.delegate;
31 + }
32 +}
1 +/**
2 + * Copyright 2012 Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.util;
19 +
20 +import java.util.Iterator;
21 +import java.util.NoSuchElementException;
22 +
23 +/**
24 + * Iterator over all values in an iterator of iterators.
25 + *
26 + * @param <T> the type of elements returned by this iterator
27 + */
28 +public class MultiIterator<T> implements Iterator<T> {
29 + Iterator<Iterator<T>> subIterator;
30 + Iterator<T> current = null;
31 +
32 + public MultiIterator(Iterator<Iterator<T>> subIterator) {
33 + super();
34 + this.subIterator = subIterator;
35 + }
36 +
37 + @Override
38 + public boolean hasNext() {
39 + if (current == null) {
40 + if (subIterator.hasNext()) {
41 + current = subIterator.next();
42 + } else {
43 + return false;
44 + }
45 + }
46 + while (!current.hasNext() && subIterator.hasNext()) {
47 + current = subIterator.next();
48 + }
49 +
50 + return current.hasNext();
51 + }
52 +
53 + @Override
54 + public T next() {
55 + if (hasNext()) {
56 + return current.next();
57 + }
58 + throw new NoSuchElementException();
59 + }
60 +
61 + @Override
62 + public void remove() {
63 + if (hasNext()) {
64 + current.remove();
65 + }
66 + throw new NoSuchElementException();
67 + }
68 +}
1 +package net.onrc.onos.of.ctl.util;
2 +
3 +import java.util.Collection;
4 +
5 +/**
6 + * A marker interface indicating that this Collection defines a particular
7 + * iteration order. The details about the iteration order are specified by
8 + * the concrete implementation.
9 + *
10 + * @param <E>
11 + */
12 +public interface OrderedCollection<E> extends Collection<E> {
13 +
14 +}
1 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3 + <modelVersion>4.0.0</modelVersion>
4 +
5 + <parent>
6 + <groupId>org.sonatype.oss</groupId>
7 + <artifactId>oss-parent</artifactId>
8 + <version>7</version>
9 + </parent>
10 +
11 + <groupId>org.projectfloodlight</groupId>
12 + <artifactId>openflowj</artifactId>
13 + <version>0.3.6-SNAPSHOT</version>
14 + <packaging>bundle</packaging>
15 +
16 + <name>OpenFlowJ-Loxi</name>
17 + <description>OpenFlowJ API supporting OpenFlow versions 1.0 through 1.3.1, generated by LoxiGen</description>
18 + <url>http://www.projectfloodlight.org/projects/</url>
19 + <licenses>
20 + <license>
21 + <name>The Apache Software License, Version 2.0</name>
22 + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
23 + <distribution>repo</distribution>
24 + </license>
25 + </licenses>
26 + <scm>
27 + <connection>scm:git:git@github.com:floodlight/loxigen.git</connection>
28 + <developerConnection>scm:git:git@github.com:floodlight/loxigen.git</developerConnection>
29 + <url>git@github.com:floodlight/loxigen.git</url>
30 + </scm>
31 +
32 + <properties>
33 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
34 + </properties>
35 +
36 + <dependencies>
37 + <dependency>
38 + <groupId>com.google.code.findbugs</groupId>
39 + <artifactId>annotations</artifactId>
40 + <version>2.0.2</version>
41 + </dependency>
42 + <dependency>
43 + <groupId>junit</groupId>
44 + <artifactId>junit</artifactId>
45 + <version>4.11</version>
46 + <scope>test</scope>
47 + </dependency>
48 + <dependency>
49 + <groupId>org.hamcrest</groupId>
50 + <artifactId>hamcrest-integration</artifactId>
51 + <version>1.3</version>
52 + <scope>test</scope>
53 + </dependency>
54 + <dependency>
55 + <groupId>io.netty</groupId>
56 + <artifactId>netty</artifactId>
57 + <version>3.9.0.Final</version>
58 + </dependency>
59 + <dependency>
60 + <groupId>com.google.guava</groupId>
61 + <artifactId>guava</artifactId>
62 + <version>15.0</version>
63 + </dependency>
64 + <dependency>
65 + <groupId>org.slf4j</groupId>
66 + <artifactId>slf4j-api</artifactId>
67 + <version>1.7.5</version>
68 + </dependency>
69 + <dependency>
70 + <groupId>ch.qos.logback</groupId>
71 + <artifactId>logback-core</artifactId>
72 + <version>1.0.13</version>
73 + </dependency>
74 + <dependency>
75 + <groupId>ch.qos.logback</groupId>
76 + <artifactId>logback-classic</artifactId>
77 + <version>1.0.13</version>
78 + </dependency>
79 + </dependencies>
80 + <build>
81 + <plugins>
82 + <plugin>
83 + <groupId>org.apache.felix</groupId>
84 + <artifactId>maven-bundle-plugin</artifactId>
85 + <version>2.3.6</version>
86 + <extensions>true</extensions>
87 + <configuration>
88 + <instructions>
89 + <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
90 + </instructions>
91 + </configuration>
92 + </plugin>
93 + <plugin>
94 + <groupId>org.apache.maven.plugins</groupId>
95 + <artifactId>maven-compiler-plugin</artifactId>
96 + <version>3.1</version>
97 + <configuration>
98 + <source>1.7</source>
99 + <target>1.7</target>
100 + </configuration>
101 + </plugin>
102 + <plugin>
103 + <!-- pick up sources from gen-src -->
104 + <groupId>org.codehaus.mojo</groupId>
105 + <artifactId>build-helper-maven-plugin</artifactId>
106 + <version>1.8</version>
107 + <executions>
108 + <execution>
109 + <id>gen-src-add-source</id>
110 + <phase>generate-sources</phase>
111 + <goals><goal>add-source</goal></goals>
112 + <configuration>
113 + <sources>
114 + <source>gen-src/main/java</source>
115 + </sources>
116 + </configuration>
117 + </execution>
118 + <execution>
119 + <id>add-gen-src-test-source</id>
120 + <!-- note: purposefully not using phase generate-test-sources, because that is not picked up by eclipse:eclipse -->
121 + <phase>validate</phase>
122 + <goals><goal>add-test-source</goal></goals>
123 + <configuration>
124 + <sources>
125 + <source>gen-src/test/java</source>
126 + </sources>
127 + </configuration>
128 + </execution>
129 + </executions>
130 + </plugin>
131 + <!-- attach sources -->
132 + <plugin>
133 + <groupId>org.apache.maven.plugins</groupId>
134 + <artifactId>maven-source-plugin</artifactId>
135 + <version>2.2.1</version>
136 + <executions>
137 + <execution>
138 + <id>attach-sources</id>
139 + <goals>
140 + <goal>jar</goal>
141 + </goals>
142 + </execution>
143 + </executions>
144 + </plugin>
145 + <!-- attach javadoc -->
146 + <plugin>
147 + <groupId>org.apache.maven.plugins</groupId>
148 + <artifactId>maven-javadoc-plugin</artifactId>
149 + <version>2.9.1</version>
150 + <executions>
151 + <execution>
152 + <id>attach-javadocs</id>
153 + <goals>
154 + <goal>jar</goal>
155 + </goals>
156 + </execution>
157 + </executions>
158 + </plugin>
159 + <plugin>
160 + <groupId>org.apache.maven.plugins</groupId>
161 + <artifactId>maven-eclipse-plugin</artifactId>
162 + <version>2.9</version>
163 + <configuration>
164 + <downloadSources>true</downloadSources>
165 + <downloadJavadocs>true</downloadJavadocs>
166 + </configuration>
167 + </plugin>
168 + <!-- use maven git-commit-id plugin to provide vcs metadata -->
169 + <plugin>
170 + <groupId>pl.project13.maven</groupId>
171 + <artifactId>git-commit-id-plugin</artifactId>
172 + <version>2.1.5</version>
173 + <executions>
174 + <execution>
175 + <goals>
176 + <goal>revision</goal>
177 + </goals>
178 + </execution>
179 + </executions>
180 +
181 + <configuration>
182 + <!-- our BuildInfoManager expects dates to be in ISO-8601 format -->
183 + <dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
184 +
185 + <verbose>true</verbose>
186 +
187 + <skipPoms>true</skipPoms>
188 + <generateGitPropertiesFile>false</generateGitPropertiesFile>
189 + <dotGitDirectory>${project.basedir}/../../.git</dotGitDirectory>
190 + <failOnNoGitDirectory>false</failOnNoGitDirectory>
191 +
192 + <gitDescribe>
193 + <skip>true</skip>
194 + <always>true</always>
195 + <abbrev>7</abbrev>
196 + <dirty>-dirty</dirty>
197 + <forceLongFormat>false</forceLongFormat>
198 + </gitDescribe>
199 + </configuration>
200 + </plugin>
201 + <!-- include git info in generated jars -->
202 + <plugin>
203 + <groupId>org.apache.maven.plugins</groupId>
204 + <artifactId>maven-jar-plugin</artifactId>
205 + <version>2.4</version>
206 + <executions>
207 + <execution>
208 + <goals>
209 + <goal>test-jar</goal>
210 + </goals>
211 + </execution>
212 + </executions>
213 + <configuration>
214 + <archive>
215 + <manifest>
216 + <mainClass>org.projectfloodlight.core.Main</mainClass>
217 + </manifest>
218 + <manifestSections>
219 + <manifestSection>
220 + <name>Floodlight-buildinfo</name>
221 + <manifestEntries>
222 + <projectName>${project.name}</projectName>
223 + <version>${project.version}</version>
224 + <vcsRevision>${git.commit.id.abbrev}</vcsRevision>
225 + <!-- note: git.branch does not work in jenkins, because jenkins
226 + builds the system in 'detached head' state. Because we mostly
227 + about jenkins builds, we instead use the environment variable
228 + GIT_BRANCH set by jenkins here -->
229 + <vcsBranch>${env.GIT_BRANCH}</vcsBranch>
230 + <buildUser>${user.name}</buildUser>
231 + <buildDate>${git.build.time}</buildDate>
232 + <!-- continuous integration information from jenkins env variables:
233 + https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-below -->
234 + <ciBuildNumber>${env.BUILD_NUMBER}</ciBuildNumber>
235 + <ciBuildId>${env.BUILD_ID}</ciBuildId>
236 + <ciBuildTag>${env.BUILD_TAG}</ciBuildTag>
237 + <ciJobName>${env.JOB_NAME}</ciJobName>
238 +i <ciNodeName>${env.NODE_NAME}</ciNodeName>
239 + </manifestEntries>
240 + </manifestSection>
241 + </manifestSections>
242 + </archive>
243 + </configuration>
244 + </plugin>
245 +
246 + <!--
247 + <plugin>
248 + <groupId>org.apache.maven.plugins</groupId>
249 + <artifactId>maven-gpg-plugin</artifactId>
250 + <version>1.4</version>
251 + <executions>
252 + <execution>
253 + <id>sign-artifacts</id>
254 + <phase>verify</phase>
255 + <goals>
256 + <goal>sign</goal>
257 + </goals>
258 + </execution>
259 + </executions>
260 + </plugin>
261 + -->
262 + </plugins>
263 + <resources>
264 + <resource>
265 + <directory>${basedir}</directory>
266 + <filtering>false</filtering>
267 + <includes>
268 + <include>LICENSE.txt</include>
269 + </includes>
270 + </resource>
271 + </resources>
272 + </build>
273 +</project>
1 +package org.projectfloodlight.openflow.annotations;
2 +
3 +/**
4 + * This annotation marks a class that is considered externally immutable. I.e.,
5 + * the externally visible state of the class will not change after its
6 + * construction. Such a class can be freely shared between threads and does not
7 + * require defensive copying (don't call clone).
8 + *
9 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
10 + */
11 +public @interface Immutable {
12 +
13 +}
1 +package org.projectfloodlight.openflow.exceptions;
2 +
3 +/**
4 + * Error: someone asked to create an OFMessage with wireformat type and version,
5 + * but that doesn't exist
6 + *
7 + * @author capveg
8 + */
9 +public class NonExistantMessage extends Exception {
10 +
11 + private static final long serialVersionUID = 1L;
12 + byte type;
13 + byte version;
14 +
15 + /**
16 + * Error: someone asked to create an OFMessage with wireformat type and
17 + * version, but that doesn't exist
18 + *
19 + * @param type
20 + * the wire format
21 + * @param version
22 + * the OpenFlow wireformat version number, e.g. 1 == v1.1, 2 =
23 + * v1.2, etc.
24 + */
25 + public NonExistantMessage(final byte type, final byte version) {
26 + this.type = type;
27 + this.version = version;
28 + }
29 +
30 +}
1 +package org.projectfloodlight.openflow.exceptions;
2 +
3 +public class OFParseError extends Exception {
4 + private static final long serialVersionUID = 1L;
5 +
6 + public OFParseError() {
7 + super();
8 + }
9 +
10 + public OFParseError(final String message, final Throwable cause) {
11 + super(message, cause);
12 + }
13 +
14 + public OFParseError(final String message) {
15 + super(message);
16 + }
17 +
18 + public OFParseError(final Throwable cause) {
19 + super(cause);
20 + }
21 +
22 +}
1 +package org.projectfloodlight.openflow.exceptions;
2 +
3 +public class OFShortRead extends Exception {
4 + private static final long serialVersionUID = 1L;
5 +
6 +}
1 +package org.projectfloodlight.openflow.exceptions;
2 +
3 +public class OFShortWrite extends Exception {
4 +
5 + private static final long serialVersionUID = 1L;
6 +
7 +}
1 +package org.projectfloodlight.openflow.exceptions;
2 +
3 +public class OFUnsupported extends Exception {
4 +
5 + private static final long serialVersionUID = 1L;
6 +
7 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +public class OFBsnVportQInQT {
4 +
5 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +import org.projectfloodlight.openflow.types.PrimitiveSinkable;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +
7 +public class OFMatchBmap implements PrimitiveSinkable{
8 +
9 + @Override
10 + public void putTo(PrimitiveSink sink) {
11 + }
12 +
13 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +public interface OFMessageReader<T> {
7 + T readFrom(ChannelBuffer bb) throws OFParseError;
8 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +public interface OFMessageWriter<T> {
7 + public void write(ChannelBuffer bb, T message) throws OFParseError;
8 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +import org.projectfloodlight.openflow.types.PrimitiveSinkable;
4 +
5 +
6 +/**
7 + * Base interface of all OpenFlow objects (e.g., messages, actions, stats, etc.)
8 + */
9 +public interface OFObject extends Writeable, PrimitiveSinkable {
10 + OFVersion getVersion();
11 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +public interface OFObjectFactory<T extends OFObject> {
6 + T read(ChannelBuffer buffer);
7 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +import java.util.EnumMap;
4 +import java.util.Iterator;
5 +import java.util.Map;
6 +
7 +import org.jboss.netty.buffer.ChannelBuffer;
8 +import org.projectfloodlight.openflow.exceptions.OFParseError;
9 +import org.projectfloodlight.openflow.protocol.match.MatchField;
10 +import org.projectfloodlight.openflow.protocol.match.MatchFields;
11 +import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
12 +import org.projectfloodlight.openflow.types.OFValueType;
13 +import org.projectfloodlight.openflow.types.PrimitiveSinkable;
14 +import org.projectfloodlight.openflow.util.ChannelUtils;
15 +import org.slf4j.Logger;
16 +import org.slf4j.LoggerFactory;
17 +
18 +import com.google.common.base.Objects;
19 +import com.google.common.collect.ImmutableMap;
20 +import com.google.common.hash.PrimitiveSink;
21 +
22 +public class OFOxmList implements Iterable<OFOxm<?>>, Writeable, PrimitiveSinkable {
23 + private static final Logger logger = LoggerFactory.getLogger(OFOxmList.class);
24 +
25 + private final Map<MatchFields, OFOxm<?>> oxmMap;
26 +
27 + public final static OFOxmList EMPTY = new OFOxmList(ImmutableMap.<MatchFields, OFOxm<?>>of());
28 +
29 + private OFOxmList(Map<MatchFields, OFOxm<?>> oxmMap) {
30 + this.oxmMap = oxmMap;
31 + }
32 +
33 + @SuppressWarnings("unchecked")
34 + public <T extends OFValueType<T>> OFOxm<T> get(MatchField<T> matchField) {
35 + return (OFOxm<T>) oxmMap.get(matchField.id);
36 + }
37 +
38 + public static class Builder {
39 + private final Map<MatchFields, OFOxm<?>> oxmMap;
40 +
41 + public Builder() {
42 + oxmMap = new EnumMap<MatchFields, OFOxm<?>>(MatchFields.class);
43 + }
44 +
45 + public Builder(EnumMap<MatchFields, OFOxm<?>> oxmMap) {
46 + this.oxmMap = oxmMap;
47 + }
48 +
49 + public <T extends OFValueType<T>> void set(OFOxm<T> oxm) {
50 + oxmMap.put(oxm.getMatchField().id, oxm);
51 + }
52 +
53 + public <T extends OFValueType<T>> void unset(MatchField<T> matchField) {
54 + oxmMap.remove(matchField.id);
55 + }
56 +
57 + public OFOxmList build() {
58 + return OFOxmList.ofList(oxmMap.values());
59 + }
60 + }
61 +
62 + @Override
63 + public Iterator<OFOxm<?>> iterator() {
64 + return oxmMap.values().iterator();
65 + }
66 +
67 + public static OFOxmList ofList(Iterable<OFOxm<?>> oxmList) {
68 + Map<MatchFields, OFOxm<?>> map = new EnumMap<MatchFields, OFOxm<?>>(
69 + MatchFields.class);
70 + for (OFOxm<?> o : oxmList) {
71 + OFOxm<?> canonical = o.getCanonical();
72 +
73 + if(logger.isDebugEnabled() && !Objects.equal(o, canonical)) {
74 + logger.debug("OFOxmList: normalized non-canonical OXM {} to {}", o, canonical);
75 + }
76 +
77 + if(canonical != null)
78 + map.put(canonical.getMatchField().id, canonical);
79 +
80 + }
81 + return new OFOxmList(map);
82 + }
83 +
84 + public static OFOxmList of(OFOxm<?>... oxms) {
85 + Map<MatchFields, OFOxm<?>> map = new EnumMap<MatchFields, OFOxm<?>>(
86 + MatchFields.class);
87 + for (OFOxm<?> o : oxms) {
88 + OFOxm<?> canonical = o.getCanonical();
89 +
90 + if(logger.isDebugEnabled() && !Objects.equal(o, canonical)) {
91 + logger.debug("OFOxmList: normalized non-canonical OXM {} to {}", o, canonical);
92 + }
93 +
94 + if(canonical != null)
95 + map.put(canonical.getMatchField().id, canonical);
96 + }
97 + return new OFOxmList(map);
98 + }
99 +
100 + public static OFOxmList readFrom(ChannelBuffer bb, int length,
101 + OFMessageReader<OFOxm<?>> reader) throws OFParseError {
102 + return ofList(ChannelUtils.readList(bb, length, reader));
103 + }
104 +
105 + @Override
106 + public void writeTo(ChannelBuffer bb) {
107 + for (OFOxm<?> o : this) {
108 + o.writeTo(bb);
109 + }
110 + }
111 +
112 + public OFOxmList.Builder createBuilder() {
113 + return new OFOxmList.Builder(new EnumMap<MatchFields, OFOxm<?>>(oxmMap));
114 + }
115 +
116 + @Override
117 + public int hashCode() {
118 + final int prime = 31;
119 + int result = 1;
120 + result = prime * result + ((oxmMap == null) ? 0 : oxmMap.hashCode());
121 + return result;
122 + }
123 +
124 + @Override
125 + public boolean equals(Object obj) {
126 + if (this == obj)
127 + return true;
128 + if (obj == null)
129 + return false;
130 + if (getClass() != obj.getClass())
131 + return false;
132 + OFOxmList other = (OFOxmList) obj;
133 + if (oxmMap == null) {
134 + if (other.oxmMap != null)
135 + return false;
136 + } else if (!oxmMap.equals(other.oxmMap))
137 + return false;
138 + return true;
139 + }
140 +
141 + @Override
142 + public String toString() {
143 + return "OFOxmList" + oxmMap;
144 + }
145 +
146 + @Override
147 + public void putTo(PrimitiveSink sink) {
148 + for (OFOxm<?> o : this) {
149 + o.putTo(sink);
150 + }
151 + }
152 +
153 +
154 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +/** Type safety interface. Enables type safe combinations of requests and replies */
4 +public interface OFRequest<REPLY extends OFMessage> extends OFMessage {
5 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +public class OFTableFeature {
4 + // FIXME implement
5 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +public enum OFVersion {
4 + OF_10(1), OF_11(2), OF_12(3), OF_13(4);
5 +
6 + public final int wireVersion;
7 +
8 + OFVersion(final int wireVersion) {
9 + this.wireVersion = wireVersion;
10 + }
11 +
12 + public int getWireVersion() {
13 + return wireVersion;
14 + }
15 +
16 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +public interface Writeable {
6 + void writeTo(ChannelBuffer bb);
7 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +public interface XidGenerator {
4 + long nextXid();
5 +}
1 +package org.projectfloodlight.openflow.protocol;
2 +
3 +import java.util.concurrent.atomic.AtomicLong;
4 +
5 +public class XidGenerators {
6 + private static final XidGenerator GLOBAL_XID_GENERATOR = new StandardXidGenerator();
7 +
8 + public static XidGenerator create() {
9 + return new StandardXidGenerator();
10 + }
11 +
12 + public static XidGenerator global() {
13 + return GLOBAL_XID_GENERATOR;
14 + }
15 +}
16 +
17 +class StandardXidGenerator implements XidGenerator {
18 +
19 + private final AtomicLong xidGen = new AtomicLong();
20 + long MAX_XID = 0xFFffFFffL;
21 +
22 + @Override
23 + public long nextXid() {
24 + long xid;
25 + do {
26 + xid = xidGen.incrementAndGet();
27 + if(xid > MAX_XID) {
28 + synchronized(this) {
29 + if(xidGen.get() > MAX_XID) {
30 + xidGen.set(0);
31 + }
32 + }
33 + }
34 + } while(xid > MAX_XID);
35 + return xid;
36 + }
37 +
38 +}
...\ No newline at end of file ...\ No newline at end of file
1 +package org.projectfloodlight.openflow.protocol.match;
2 +
3 +import org.projectfloodlight.openflow.protocol.OFObject;
4 +import org.projectfloodlight.openflow.types.Masked;
5 +import org.projectfloodlight.openflow.types.OFValueType;
6 +
7 +/**
8 + * Generic interface for version-agnostic immutable Match structure.
9 + * The Match structure is defined in the OpenFlow protocol, and it contains information on
10 + * the fields to be matched in a specific flow record.
11 + * This interface does not assume anything on the fields in the Match structure. If in
12 + * some version, the match structure cannot handle a certain field, it may return <code>false</code>
13 + * for <code>supports(...)</code> calls, and throw <code>UnsupportedOperationException</code> from all
14 + * other methods in such cases.
15 + * <br><br>
16 + * On wildcards and masks:<br>
17 + * This interface defines the following masking notations for fields:
18 + * <ul>
19 + * <li><b>Exact</b>: field is matched exactly against a single, fixed value (no mask, or mask is all ones).
20 + * <li><b>Wildcarded</b>: field is not being matched. It is fully masked (mask=0) and any value of it
21 + * will match the flow record having this match.
22 + * <li><b>Partially masked</b>: field is matched using a specified mask which is neither 0 nor all ones. Mask can
23 + * be either arbitrary or require some specific structure.
24 + * </ul>
25 + * Implementing classes may or may not support all types of these masking types. They may also support
26 + * them in part. For example, OF1.0 supports exact match and (full) wildcarding for all fields, but it
27 + * does only supports partial masking for IP source/destination fields, and this partial masking must be
28 + * in the CIDR prefix format. Thus, OF1.0 implementation may throw <code>UnsupportedOperationException</code> if given
29 + * in <code>setMasked</code> an IP mask of, for example, 255.0.255.0, or if <code>setMasked</code> is called for any field
30 + * which is not IP source/destination address.
31 + * <br><br>
32 + * On prerequisites:<br>
33 + * From the OF1.1 spec, page 28, the OF1.0 spec failed to explicitly specify this, but it
34 + * is the behavior of OF1.0 switches:
35 + * "Protocol-specific fields within ofp_match will be ignored within a single table when
36 + * the corresponding protocol is not specified in the match. The MPLS match fields will
37 + * be ignored unless the Ethertype is specified as MPLS. Likewise, the IP header and
38 + * transport header fields will be ignored unless the Ethertype is specified as either
39 + * IPv4 or ARP. The tp_src and tp_dst fields will be ignored unless the network protocol
40 + * specified is as TCP, UDP or SCTP. Fields that are ignored don't need to be wildcarded
41 + * and should be set to 0."
42 + * <br><br>
43 + * This interface uses generics to assure type safety in users code. However, implementing classes may have to suppress
44 + * 'unchecked cast' warnings while making sure they correctly cast base on their implementation details.
45 + *
46 + * @author Yotam Harchol (yotam.harchol@bigswitch.com)
47 + */
48 +public interface Match extends OFObject {
49 +
50 + /**
51 + * Returns a value for the given field if:
52 + * <ul>
53 + * <li>Field is supported
54 + * <li>Field is not fully wildcarded
55 + * <li>Prerequisites are ok
56 + * </ul>
57 + * If one of the above conditions does not hold, returns null. Value is returned masked if partially wildcarded.
58 + *
59 + * @param field Match field to retrieve
60 + * @return Value of match field (may be masked), or <code>null</code> if field is one of the conditions above does not hold.
61 + * @throws UnsupportedOperationException If field is not supported.
62 + */
63 + public <F extends OFValueType<F>> F get(MatchField<F> field) throws UnsupportedOperationException;
64 +
65 + /**
66 + * Returns the masked value for the given field from this match, along with the mask itself.
67 + * Prerequisite: field is partially masked.
68 + * If prerequisite is not met, a <code>null</code> is returned.
69 + *
70 + * @param field Match field to retrieve.
71 + * @return Masked value of match field or null if no mask is set.
72 + * @throws UnsupportedOperationException If field is not supported.
73 + */
74 + public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field) throws UnsupportedOperationException;
75 +
76 + /**
77 + * Returns true if and only if this match object supports the given match field.
78 + *
79 + * @param field Match field
80 + * @return true if field is supported, false otherwise.
81 + */
82 + public boolean supports(MatchField<?> field);
83 +
84 + /**
85 + * Returns true if and only if this match object supports partially bitmasking of the given field.
86 + * (note: not all possible values of this bitmask have to be acceptable)
87 + *
88 + * @param field Match field.
89 + * @return true if field can be partially masked, false otherwise.
90 + * @throws UnsupportedOperationException If field is not supported.
91 + */
92 + public boolean supportsMasked(MatchField<?> field) throws UnsupportedOperationException;
93 +
94 + /**
95 + * Returns true if and only if this field is currently specified in the match with an exact value and
96 + * no mask. I.e., the specified match will only select packets that match the exact value of getValue(field).
97 + *
98 + * @param field Match field.
99 + * @return true if field has a specific exact value, false if not.
100 + * @throws UnsupportedOperationException If field is not supported.
101 + */
102 + public boolean isExact(MatchField<?> field) throws UnsupportedOperationException;
103 +
104 + /**
105 + * True if and only if this field is currently logically unspecified in the match, i.e, the
106 + * value returned by getValue(f) has no impact on whether a packet will be selected
107 + * by the match or not.
108 + *
109 + * @param field Match field.
110 + * @return true if field is fully wildcarded, false if not.
111 + * @throws UnsupportedOperationException If field is not supported.
112 + */
113 + public boolean isFullyWildcarded(MatchField<?> field) throws UnsupportedOperationException;
114 +
115 + /**
116 + * True if and only if this field is currently partially specified in the match, i.e, the
117 + * match will only select packets that match (p.value & getMask(field)) == getValue(field),
118 + * and getMask(field) != 0.
119 + *
120 + * @param field Match field.
121 + * @return true if field is partially masked, false if not.
122 + * @throws UnsupportedOperationException If field is not supported.
123 + */
124 + public boolean isPartiallyMasked(MatchField<?> field) throws UnsupportedOperationException;
125 +
126 + /**
127 + * Get an Iterable over the match fields that have been specified for the
128 + * match. This includes the match fields that are exact or masked match
129 + * (but not fully wildcarded).
130 + *
131 + * @return
132 + */
133 + public Iterable<MatchField<?>> getMatchFields();
134 +
135 + /**
136 + * Returns a builder to build new instances of this type of match object.
137 + * @return Match builder
138 + */
139 + public Builder createBuilder();
140 +
141 + /**
142 + * Builder interface for Match objects.
143 + * Builder is used to create new Match objects and it creates the match according to the version it
144 + * corresponds to. The builder uses the same notation of wildcards and masks, and can also throw
145 + * <code>UnsupportedOperationException</code> if it is asked to create some matching that is not supported in
146 + * the version it represents.
147 + *
148 + * While used, MatchBuilder may not be consistent in terms of field prerequisites. However, user must
149 + * solve these before using the generated Match object as these prerequisites should be enforced in the
150 + * getters.
151 + *
152 + * @author Yotam Harchol (yotam.harchol@bigswitch.com)
153 + */
154 + interface Builder {
155 + public <F extends OFValueType<F>> F get(MatchField<F> field) throws UnsupportedOperationException;
156 +
157 + public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field) throws UnsupportedOperationException;
158 +
159 + public boolean supports(MatchField<?> field);
160 +
161 + public boolean supportsMasked(MatchField<?> field) throws UnsupportedOperationException;
162 +
163 + public boolean isExact(MatchField<?> field) throws UnsupportedOperationException;
164 +
165 + public boolean isFullyWildcarded(MatchField<?> field) throws UnsupportedOperationException;
166 +
167 + public boolean isPartiallyMasked(MatchField<?> field) throws UnsupportedOperationException;
168 +
169 + /**
170 + * Sets a specific exact value for a field.
171 + *
172 + * @param field Match field to set.
173 + * @param value Value of match field.
174 + * @return the Builder instance used.
175 + * @throws UnsupportedOperationException If field is not supported.
176 + */
177 + public <F extends OFValueType<F>> Builder setExact(MatchField<F> field, F value) throws UnsupportedOperationException;
178 +
179 + /**
180 + * Sets a masked value for a field.
181 + *
182 + * @param field Match field to set.
183 + * @param value Value of field.
184 + * @param mask Mask value.
185 + * @return the Builder instance used.
186 + * @throws UnsupportedOperationException If field is not supported, if field is supported but does not support masking, or if mask structure is not supported.
187 + */
188 + public <F extends OFValueType<F>> Builder setMasked(MatchField<F> field, F value, F mask) throws UnsupportedOperationException;
189 +
190 + /**
191 + * Sets a masked value for a field.
192 + *
193 + * @param field Match field to set.
194 + * @param valueWithMask Compound Masked object contains the value and the mask.
195 + * @return the Builder instance used.
196 + * @throws UnsupportedOperationException If field is not supported, if field is supported but does not support masking, or if mask structure is not supported.
197 + */
198 + public <F extends OFValueType<F>> Builder setMasked(MatchField<F> field, Masked<F> valueWithMask) throws UnsupportedOperationException;
199 +
200 + /**
201 + * Unsets any value given for the field and wildcards it so that it matches any value.
202 + *
203 + * @param field Match field to unset.
204 + * @return the Builder instance used.
205 + * @throws UnsupportedOperationException If field is not supported.
206 + */
207 + public <F extends OFValueType<F>> Builder wildcard(MatchField<F> field) throws UnsupportedOperationException;
208 +
209 + /**
210 + * Returns the match created by this builder.
211 + *
212 + * @return a Match object.
213 + */
214 + public Match build();
215 + }
216 +}
...\ No newline at end of file ...\ No newline at end of file
1 +package org.projectfloodlight.openflow.protocol.match;
2 +
3 +import org.projectfloodlight.openflow.types.ArpOpcode;
4 +import org.projectfloodlight.openflow.types.ClassId;
5 +import org.projectfloodlight.openflow.types.EthType;
6 +import org.projectfloodlight.openflow.types.ICMPv4Code;
7 +import org.projectfloodlight.openflow.types.ICMPv4Type;
8 +import org.projectfloodlight.openflow.types.IPv4Address;
9 +import org.projectfloodlight.openflow.types.IPv6Address;
10 +import org.projectfloodlight.openflow.types.IPv6FlowLabel;
11 +import org.projectfloodlight.openflow.types.IpDscp;
12 +import org.projectfloodlight.openflow.types.IpEcn;
13 +import org.projectfloodlight.openflow.types.IpProtocol;
14 +import org.projectfloodlight.openflow.types.LagId;
15 +import org.projectfloodlight.openflow.types.MacAddress;
16 +import org.projectfloodlight.openflow.types.OFBitMask128;
17 +import org.projectfloodlight.openflow.types.OFBooleanValue;
18 +import org.projectfloodlight.openflow.types.OFMetadata;
19 +import org.projectfloodlight.openflow.types.OFPort;
20 +import org.projectfloodlight.openflow.types.OFValueType;
21 +import org.projectfloodlight.openflow.types.OFVlanVidMatch;
22 +import org.projectfloodlight.openflow.types.TransportPort;
23 +import org.projectfloodlight.openflow.types.U16;
24 +import org.projectfloodlight.openflow.types.U64;
25 +import org.projectfloodlight.openflow.types.U32;
26 +import org.projectfloodlight.openflow.types.U8;
27 +import org.projectfloodlight.openflow.types.UDF;
28 +import org.projectfloodlight.openflow.types.VRF;
29 +import org.projectfloodlight.openflow.types.VlanPcp;
30 +
31 +@SuppressWarnings("unchecked")
32 +public class MatchField<F extends OFValueType<F>> {
33 + private final String name;
34 + public final MatchFields id;
35 + private final Prerequisite<?>[] prerequisites;
36 +
37 + private MatchField(final String name, final MatchFields id, Prerequisite<?>... prerequisites) {
38 + this.name = name;
39 + this.id = id;
40 + this.prerequisites = prerequisites;
41 + }
42 +
43 + public final static MatchField<OFPort> IN_PORT =
44 + new MatchField<OFPort>("in_port", MatchFields.IN_PORT);
45 +
46 + public final static MatchField<OFPort> IN_PHY_PORT =
47 + new MatchField<OFPort>("in_phy_port", MatchFields.IN_PHY_PORT,
48 + new Prerequisite<OFPort>(MatchField.IN_PORT));
49 +
50 + public final static MatchField<OFMetadata> METADATA =
51 + new MatchField<OFMetadata>("metadata", MatchFields.METADATA);
52 +
53 + public final static MatchField<MacAddress> ETH_DST =
54 + new MatchField<MacAddress>("eth_dst", MatchFields.ETH_DST);
55 +
56 + public final static MatchField<MacAddress> ETH_SRC =
57 + new MatchField<MacAddress>("eth_src", MatchFields.ETH_SRC);
58 +
59 + public final static MatchField<EthType> ETH_TYPE =
60 + new MatchField<EthType>("eth_type", MatchFields.ETH_TYPE);
61 +
62 + public final static MatchField<OFVlanVidMatch> VLAN_VID =
63 + new MatchField<OFVlanVidMatch>("vlan_vid", MatchFields.VLAN_VID);
64 +
65 + public final static MatchField<VlanPcp> VLAN_PCP =
66 + new MatchField<VlanPcp>("vlan_pcp", MatchFields.VLAN_PCP,
67 + new Prerequisite<OFVlanVidMatch>(MatchField.VLAN_VID));
68 +
69 + public final static MatchField<IpDscp> IP_DSCP =
70 + new MatchField<IpDscp>("ip_dscp", MatchFields.IP_DSCP,
71 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv4, EthType.IPv6));
72 +
73 + public final static MatchField<IpEcn> IP_ECN =
74 + new MatchField<IpEcn>("ip_ecn", MatchFields.IP_ECN,
75 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv4, EthType.IPv6));
76 +
77 + public final static MatchField<IpProtocol> IP_PROTO =
78 + new MatchField<IpProtocol>("ip_proto", MatchFields.IP_PROTO,
79 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv4, EthType.IPv6));
80 +
81 + public final static MatchField<IPv4Address> IPV4_SRC =
82 + new MatchField<IPv4Address>("ipv4_src", MatchFields.IPV4_SRC,
83 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv4));
84 +
85 + public final static MatchField<IPv4Address> IPV4_DST =
86 + new MatchField<IPv4Address>("ipv4_dst", MatchFields.IPV4_DST,
87 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv4));
88 +
89 + public final static MatchField<TransportPort> TCP_SRC = new MatchField<TransportPort>(
90 + "tcp_src", MatchFields.TCP_SRC,
91 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.TCP));
92 +
93 + public final static MatchField<TransportPort> TCP_DST = new MatchField<TransportPort>(
94 + "tcp_dst", MatchFields.TCP_DST,
95 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.TCP));
96 +
97 + public final static MatchField<TransportPort> UDP_SRC = new MatchField<TransportPort>(
98 + "udp_src", MatchFields.UDP_SRC,
99 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.UDP));
100 +
101 + public final static MatchField<TransportPort> UDP_DST = new MatchField<TransportPort>(
102 + "udp_dst", MatchFields.UDP_DST,
103 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.UDP));
104 +
105 + public final static MatchField<TransportPort> SCTP_SRC = new MatchField<TransportPort>(
106 + "sctp_src", MatchFields.SCTP_SRC,
107 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.SCTP));
108 +
109 + public final static MatchField<TransportPort> SCTP_DST = new MatchField<TransportPort>(
110 + "sctp_dst", MatchFields.SCTP_DST,
111 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.SCTP));
112 +
113 + public final static MatchField<ICMPv4Type> ICMPV4_TYPE = new MatchField<ICMPv4Type>(
114 + "icmpv4_type", MatchFields.ICMPV4_TYPE,
115 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.ICMP));
116 +
117 + public final static MatchField<ICMPv4Code> ICMPV4_CODE = new MatchField<ICMPv4Code>(
118 + "icmpv4_code", MatchFields.ICMPV4_CODE,
119 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.ICMP));
120 +
121 + public final static MatchField<ArpOpcode> ARP_OP = new MatchField<ArpOpcode>(
122 + "arp_op", MatchFields.ARP_OP,
123 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ARP));
124 +
125 + public final static MatchField<IPv4Address> ARP_SPA =
126 + new MatchField<IPv4Address>("arp_spa", MatchFields.ARP_SPA,
127 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ARP));
128 +
129 + public final static MatchField<IPv4Address> ARP_TPA =
130 + new MatchField<IPv4Address>("arp_tpa", MatchFields.ARP_TPA,
131 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ARP));
132 +
133 + public final static MatchField<MacAddress> ARP_SHA =
134 + new MatchField<MacAddress>("arp_sha", MatchFields.ARP_SHA,
135 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ARP));
136 +
137 + public final static MatchField<MacAddress> ARP_THA =
138 + new MatchField<MacAddress>("arp_tha", MatchFields.ARP_THA,
139 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ARP));
140 +
141 + public final static MatchField<IPv6Address> IPV6_SRC =
142 + new MatchField<IPv6Address>("ipv6_src", MatchFields.IPV6_SRC,
143 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv6));
144 +
145 + public final static MatchField<IPv6Address> IPV6_DST =
146 + new MatchField<IPv6Address>("ipv6_dst", MatchFields.IPV6_DST,
147 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv6));
148 +
149 + public final static MatchField<IPv6FlowLabel> IPV6_FLABEL =
150 + new MatchField<IPv6FlowLabel>("ipv6_flabel", MatchFields.IPV6_FLABEL,
151 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv6));
152 +
153 + public final static MatchField<U8> ICMPV6_TYPE =
154 + new MatchField<U8>("icmpv6_type", MatchFields.ICMPV6_TYPE,
155 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IPv6_ICMP));
156 +
157 + public final static MatchField<U8> ICMPV6_CODE =
158 + new MatchField<U8>("icmpv6_code", MatchFields.ICMPV6_CODE,
159 + new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IPv6_ICMP));
160 +
161 + public final static MatchField<IPv6Address> IPV6_ND_TARGET =
162 + new MatchField<IPv6Address>("ipv6_nd_target", MatchFields.IPV6_ND_TARGET,
163 + new Prerequisite<U8>(MatchField.ICMPV6_TYPE, U8.of((short)135), U8.of((short)136)));
164 +
165 + public final static MatchField<MacAddress> IPV6_ND_SLL =
166 + new MatchField<MacAddress>("ipv6_nd_sll", MatchFields.IPV6_ND_SLL,
167 + new Prerequisite<U8>(MatchField.ICMPV6_TYPE, U8.of((short)135)));
168 +
169 + public final static MatchField<MacAddress> IPV6_ND_TLL =
170 + new MatchField<MacAddress>("ipv6_nd_tll", MatchFields.IPV6_ND_TLL,
171 + new Prerequisite<U8>(MatchField.ICMPV6_TYPE, U8.of((short)136)));
172 +
173 + public final static MatchField<U32> MPLS_LABEL =
174 + new MatchField<U32>("mpls_label", MatchFields.MPLS_LABEL,
175 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.MPLS_UNICAST, EthType.MPLS_MULTICAST));
176 +
177 + public final static MatchField<U8> MPLS_TC =
178 + new MatchField<U8>("mpls_tc", MatchFields.MPLS_TC,
179 + new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.MPLS_UNICAST, EthType.MPLS_MULTICAST));
180 +
181 + public final static MatchField<U64> TUNNEL_ID =
182 + new MatchField<U64>("tunnel_id", MatchFields.TUNNEL_ID);
183 +
184 + public final static MatchField<OFBitMask128> BSN_IN_PORTS_128 =
185 + new MatchField<OFBitMask128>("bsn_in_ports_128", MatchFields.BSN_IN_PORTS_128);
186 +
187 + public final static MatchField<LagId> BSN_LAG_ID =
188 + new MatchField<LagId>("bsn_lag_id", MatchFields.BSN_LAG_ID);
189 +
190 + public final static MatchField<VRF> BSN_VRF =
191 + new MatchField<VRF>("bsn_vrf", MatchFields.BSN_VRF);
192 +
193 + public final static MatchField<OFBooleanValue> BSN_GLOBAL_VRF_ALLOWED =
194 + new MatchField<OFBooleanValue>("bsn_global_vrf_allowed", MatchFields.BSN_GLOBAL_VRF_ALLOWED);
195 +
196 + public final static MatchField<ClassId> BSN_L3_INTERFACE_CLASS_ID =
197 + new MatchField<ClassId>("bsn_l3_interface_class_id", MatchFields.BSN_L3_INTERFACE_CLASS_ID);
198 +
199 + public final static MatchField<ClassId> BSN_L3_SRC_CLASS_ID =
200 + new MatchField<ClassId>("bsn_l3_src_class_id", MatchFields.BSN_L3_SRC_CLASS_ID);
201 +
202 + public final static MatchField<ClassId> BSN_L3_DST_CLASS_ID =
203 + new MatchField<ClassId>("bsn_l3_dst_class_id", MatchFields.BSN_L3_DST_CLASS_ID);
204 +
205 + public final static MatchField<ClassId> BSN_EGR_PORT_GROUP_ID =
206 + new MatchField<ClassId>("bsn_egr_port_group_id", MatchFields.BSN_EGR_PORT_GROUP_ID);
207 +
208 + public final static MatchField<UDF> BSN_UDF0 =
209 + new MatchField<UDF>("bsn_udf", MatchFields.BSN_UDF0);
210 +
211 + public final static MatchField<UDF> BSN_UDF1 =
212 + new MatchField<UDF>("bsn_udf", MatchFields.BSN_UDF1);
213 +
214 + public final static MatchField<UDF> BSN_UDF2 =
215 + new MatchField<UDF>("bsn_udf", MatchFields.BSN_UDF2);
216 +
217 + public final static MatchField<UDF> BSN_UDF3 =
218 + new MatchField<UDF>("bsn_udf", MatchFields.BSN_UDF3);
219 +
220 + public final static MatchField<UDF> BSN_UDF4 =
221 + new MatchField<UDF>("bsn_udf", MatchFields.BSN_UDF4);
222 +
223 + public final static MatchField<UDF> BSN_UDF5 =
224 + new MatchField<UDF>("bsn_udf", MatchFields.BSN_UDF5);
225 +
226 + public final static MatchField<UDF> BSN_UDF6 =
227 + new MatchField<UDF>("bsn_udf", MatchFields.BSN_UDF6);
228 +
229 + public final static MatchField<UDF> BSN_UDF7 =
230 + new MatchField<UDF>("bsn_udf", MatchFields.BSN_UDF7);
231 +
232 + public final static MatchField<U16> BSN_TCP_FLAGS =
233 + new MatchField<U16>("bsn_tcp_flags", MatchFields.BSN_TCP_FLAGS);
234 +
235 + public String getName() {
236 + return name;
237 + }
238 +
239 + public boolean arePrerequisitesOK(Match match) {
240 + for (Prerequisite<?> p : this.prerequisites) {
241 + if (!p.isSatisfied(match)) {
242 + return false;
243 + }
244 + }
245 + return true;
246 + }
247 +
248 +}
1 +package org.projectfloodlight.openflow.protocol.match;
2 +
3 +// MUST BE ORDERED BY THE ORDER OF OF SPEC!!!
4 +public enum MatchFields {
5 + IN_PORT,
6 + IN_PHY_PORT,
7 + METADATA,
8 + ETH_DST,
9 + ETH_SRC,
10 + ETH_TYPE,
11 + VLAN_VID,
12 + VLAN_PCP,
13 + IP_DSCP,
14 + IP_ECN,
15 + IP_PROTO,
16 + IPV4_SRC,
17 + IPV4_DST,
18 + TCP_SRC,
19 + TCP_DST,
20 + UDP_SRC,
21 + UDP_DST,
22 + SCTP_SRC,
23 + SCTP_DST,
24 + ICMPV4_TYPE,
25 + ICMPV4_CODE,
26 + ARP_OP,
27 + ARP_SPA,
28 + ARP_TPA,
29 + ARP_SHA,
30 + ARP_THA,
31 + IPV6_SRC,
32 + IPV6_DST,
33 + IPV6_FLABEL,
34 + ICMPV6_TYPE,
35 + ICMPV6_CODE,
36 + IPV6_ND_TARGET,
37 + IPV6_ND_SLL,
38 + IPV6_ND_TLL,
39 + MPLS_LABEL,
40 + MPLS_TC,
41 + TUNNEL_ID,
42 + BSN_IN_PORTS_128,
43 + BSN_LAG_ID,
44 + BSN_VRF,
45 + BSN_GLOBAL_VRF_ALLOWED,
46 + BSN_L3_INTERFACE_CLASS_ID,
47 + BSN_L3_SRC_CLASS_ID,
48 + BSN_L3_DST_CLASS_ID,
49 + BSN_EGR_PORT_GROUP_ID,
50 + BSN_UDF0,
51 + BSN_UDF1,
52 + BSN_UDF2,
53 + BSN_UDF3,
54 + BSN_UDF4,
55 + BSN_UDF5,
56 + BSN_UDF6,
57 + BSN_UDF7,
58 + BSN_TCP_FLAGS,
59 +}
1 +package org.projectfloodlight.openflow.protocol.match;
2 +
3 +import java.util.HashSet;
4 +import java.util.Set;
5 +
6 +import org.projectfloodlight.openflow.types.OFValueType;
7 +
8 +public class Prerequisite<T extends OFValueType<T>> {
9 + private final MatchField<T> field;
10 + private final Set<OFValueType<T>> values;
11 + private boolean any;
12 +
13 + @SafeVarargs
14 + public Prerequisite(MatchField<T> field, OFValueType<T>... values) {
15 + this.values = new HashSet<OFValueType<T>>();
16 + this.field = field;
17 + if (values == null || values.length == 0) {
18 + this.any = true;
19 + } else {
20 + this.any = false;
21 + for (OFValueType<T> value : values) {
22 + this.values.add(value);
23 + }
24 + }
25 + }
26 +
27 + /**
28 + * Returns true if this prerequisite is satisfied by the given match object.
29 + *
30 + * @param match Match object
31 + * @return true iff prerequisite is satisfied.
32 + */
33 + public boolean isSatisfied(Match match) {
34 + OFValueType<T> res = match.get(this.field);
35 + if (res == null)
36 + return false;
37 + if (this.any)
38 + return true;
39 + if (this.values.contains(res)) {
40 + return true;
41 + }
42 + return false;
43 + }
44 +
45 +}
1 +package org.projectfloodlight.openflow.protocol.ver10;
2 +
3 +import java.util.EnumSet;
4 +import java.util.Set;
5 +
6 +import org.jboss.netty.buffer.ChannelBuffer;
7 +import org.projectfloodlight.openflow.exceptions.OFParseError;
8 +import org.projectfloodlight.openflow.protocol.OFActionType;
9 +import org.projectfloodlight.openflow.protocol.match.Match;
10 +
11 +import com.google.common.hash.PrimitiveSink;
12 +
13 +/**
14 + * Collection of helper functions for reading and writing into ChannelBuffers
15 + *
16 + * @author capveg
17 + */
18 +
19 +public class ChannelUtilsVer10 {
20 + public static Match readOFMatch(final ChannelBuffer bb) throws OFParseError {
21 + return OFMatchV1Ver10.READER.readFrom(bb);
22 + }
23 +
24 + public static Set<OFActionType> readSupportedActions(ChannelBuffer bb) {
25 + int actions = bb.readInt();
26 + EnumSet<OFActionType> supportedActions = EnumSet.noneOf(OFActionType.class);
27 + if ((actions & (1 << OFActionTypeSerializerVer10.OUTPUT_VAL)) != 0)
28 + supportedActions.add(OFActionType.OUTPUT);
29 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_VLAN_VID_VAL)) != 0)
30 + supportedActions.add(OFActionType.SET_VLAN_VID);
31 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_VLAN_PCP_VAL)) != 0)
32 + supportedActions.add(OFActionType.SET_VLAN_PCP);
33 + if ((actions & (1 << OFActionTypeSerializerVer10.STRIP_VLAN_VAL)) != 0)
34 + supportedActions.add(OFActionType.STRIP_VLAN);
35 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_DL_SRC_VAL)) != 0)
36 + supportedActions.add(OFActionType.SET_DL_SRC);
37 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_DL_DST_VAL)) != 0)
38 + supportedActions.add(OFActionType.SET_DL_DST);
39 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_NW_SRC_VAL)) != 0)
40 + supportedActions.add(OFActionType.SET_NW_SRC);
41 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_NW_DST_VAL)) != 0)
42 + supportedActions.add(OFActionType.SET_NW_DST);
43 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_NW_TOS_VAL)) != 0)
44 + supportedActions.add(OFActionType.SET_NW_TOS);
45 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_TP_SRC_VAL)) != 0)
46 + supportedActions.add(OFActionType.SET_TP_SRC);
47 + if ((actions & (1 << OFActionTypeSerializerVer10.SET_TP_DST_VAL)) != 0)
48 + supportedActions.add(OFActionType.SET_TP_DST);
49 + if ((actions & (1 << OFActionTypeSerializerVer10.ENQUEUE_VAL)) != 0)
50 + supportedActions.add(OFActionType.ENQUEUE);
51 + return supportedActions;
52 + }
53 +
54 + public static int supportedActionsToWire(Set<OFActionType> supportedActions) {
55 + int supportedActionsVal = 0;
56 + if (supportedActions.contains(OFActionType.OUTPUT))
57 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.OUTPUT_VAL);
58 + if (supportedActions.contains(OFActionType.SET_VLAN_VID))
59 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_VLAN_VID_VAL);
60 + if (supportedActions.contains(OFActionType.SET_VLAN_PCP))
61 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_VLAN_PCP_VAL);
62 + if (supportedActions.contains(OFActionType.STRIP_VLAN))
63 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.STRIP_VLAN_VAL);
64 + if (supportedActions.contains(OFActionType.SET_DL_SRC))
65 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_DL_SRC_VAL);
66 + if (supportedActions.contains(OFActionType.SET_DL_DST))
67 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_DL_DST_VAL);
68 + if (supportedActions.contains(OFActionType.SET_NW_SRC))
69 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_NW_SRC_VAL);
70 + if (supportedActions.contains(OFActionType.SET_NW_DST))
71 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_NW_DST_VAL);
72 + if (supportedActions.contains(OFActionType.SET_NW_TOS))
73 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_NW_TOS_VAL);
74 + if (supportedActions.contains(OFActionType.SET_TP_SRC))
75 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_TP_SRC_VAL);
76 + if (supportedActions.contains(OFActionType.SET_TP_DST))
77 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_TP_DST_VAL);
78 + if (supportedActions.contains(OFActionType.ENQUEUE))
79 + supportedActionsVal |= (1 << OFActionTypeSerializerVer10.ENQUEUE_VAL);
80 + return supportedActionsVal;
81 + }
82 +
83 + public static void putSupportedActionsTo(Set<OFActionType> supportedActions, PrimitiveSink sink) {
84 + sink.putInt(supportedActionsToWire(supportedActions));
85 + }
86 +
87 + public static void writeSupportedActions(ChannelBuffer bb, Set<OFActionType> supportedActions) {
88 + bb.writeInt(supportedActionsToWire(supportedActions));
89 + }
90 +
91 +}
1 +package org.projectfloodlight.openflow.protocol.ver11;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +import org.projectfloodlight.openflow.protocol.OFMatchBmap;
6 +import org.projectfloodlight.openflow.protocol.match.Match;
7 +
8 +/**
9 + * Collection of helper functions for reading and writing into ChannelBuffers
10 + *
11 + * @author capveg
12 + */
13 +
14 +public class ChannelUtilsVer11 {
15 + public static Match readOFMatch(final ChannelBuffer bb) throws OFParseError {
16 + return OFMatchV2Ver11.READER.readFrom(bb);
17 + }
18 +
19 + public static OFMatchBmap readOFMatchBmap(ChannelBuffer bb) {
20 + throw new UnsupportedOperationException("not implemented");
21 + }
22 +
23 + public static void writeOFMatchBmap(ChannelBuffer bb, OFMatchBmap match) {
24 + throw new UnsupportedOperationException("not implemented");
25 + }
26 +}
1 +package org.projectfloodlight.openflow.protocol.ver12;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +import org.projectfloodlight.openflow.protocol.OFMatchBmap;
6 +import org.projectfloodlight.openflow.protocol.match.Match;
7 +import org.projectfloodlight.openflow.protocol.ver12.OFMatchV3Ver12;
8 +import org.projectfloodlight.openflow.protocol.OFBsnVportQInQ;
9 +
10 +/**
11 + * Collection of helper functions for reading and writing into ChannelBuffers
12 + *
13 + * @author capveg
14 + */
15 +
16 +public class ChannelUtilsVer12 {
17 + public static Match readOFMatch(final ChannelBuffer bb) throws OFParseError {
18 + return OFMatchV3Ver12.READER.readFrom(bb);
19 + }
20 +
21 + // TODO these need to be figured out / removed
22 +
23 + public static OFBsnVportQInQ readOFBsnVportQInQ(ChannelBuffer bb) {
24 + throw new UnsupportedOperationException("not implemented");
25 + }
26 +
27 + public static void writeOFBsnVportQInQ(ChannelBuffer bb,
28 + OFBsnVportQInQ vport) {
29 + throw new UnsupportedOperationException("not implemented");
30 +
31 + }
32 +
33 + public static OFMatchBmap readOFMatchBmap(ChannelBuffer bb) {
34 + throw new UnsupportedOperationException("not implemented");
35 + }
36 +
37 + public static void writeOFMatchBmap(ChannelBuffer bb, OFMatchBmap match) {
38 + throw new UnsupportedOperationException("not implemented");
39 + }
40 +}
1 +package org.projectfloodlight.openflow.protocol.ver13;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +import org.projectfloodlight.openflow.protocol.OFMatchBmap;
6 +import org.projectfloodlight.openflow.protocol.match.Match;
7 +
8 +/**
9 + * Collection of helper functions for reading and writing into ChannelBuffers
10 + *
11 + * @author capveg
12 + */
13 +
14 +public class ChannelUtilsVer13 {
15 + public static Match readOFMatch(final ChannelBuffer bb) throws OFParseError {
16 + return OFMatchV3Ver13.READER.readFrom(bb);
17 + }
18 +
19 + public static OFMatchBmap readOFMatchBmap(ChannelBuffer bb) {
20 + throw new UnsupportedOperationException("not implemented");
21 + }
22 +
23 + public static void writeOFMatchBmap(ChannelBuffer bb, OFMatchBmap match) {
24 + throw new UnsupportedOperationException("not implemented");
25 + }
26 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +import com.google.common.primitives.UnsignedInts;
7 +
8 +public class ArpOpcode implements OFValueType<ArpOpcode> {
9 +
10 + final static int LENGTH = 2;
11 +
12 + private static final int VAL_REQUEST = 1;
13 + private static final int VAL_REPLY = 2;
14 + private static final int VAL_REQUEST_REVERSE = 3;
15 + private static final int VAL_REPLY_REVERSE = 4;
16 + private static final int VAL_DRARP_REQUEST = 5;
17 + private static final int VAL_DRARP_REPLY = 6;
18 + private static final int VAL_DRARP_ERROR = 7;
19 + private static final int VAL_INARP_REQUEST = 8;
20 + private static final int VAL_INARP_REPLY = 9;
21 + private static final int VAL_ARP_NAK = 10;
22 + private static final int VAL_MARS_REQUEST = 11;
23 + private static final int VAL_MARS_MULTI = 12;
24 + private static final int VAL_MARS_MSERV = 13;
25 + private static final int VAL_MARS_JOIN = 14;
26 + private static final int VAL_MARS_LEAVE = 15;
27 + private static final int VAL_MARS_NAK = 16;
28 + private static final int VAL_MARS_UNSERV = 17;
29 + private static final int VAL_MARS_SJOIN = 18;
30 + private static final int VAL_MARS_SLEAVE = 19;
31 + private static final int VAL_MARS_GROUPLIST_REQUEST = 20;
32 + private static final int VAL_MARS_GROUPLIST_REPLY = 21;
33 + private static final int VAL_MARS_REDIRECT_MAP = 22;
34 + private static final int VAL_MAPOS_UNARP = 23;
35 + private static final int VAL_OP_EXP1 = 24;
36 + private static final int VAL_OP_EXP2 = 25;
37 +
38 + public static final ArpOpcode REQUEST = new ArpOpcode(VAL_REQUEST);
39 + public static final ArpOpcode REPLY = new ArpOpcode(VAL_REPLY);
40 + public static final ArpOpcode REQUEST_REVERSE = new ArpOpcode(VAL_REQUEST_REVERSE);
41 + public static final ArpOpcode REPLY_REVERSE = new ArpOpcode(VAL_REPLY_REVERSE);
42 + public static final ArpOpcode DRARP_REQUEST = new ArpOpcode(VAL_DRARP_REQUEST);
43 + public static final ArpOpcode DRARP_REPLY = new ArpOpcode(VAL_DRARP_REPLY);
44 + public static final ArpOpcode DRARP_ERROR = new ArpOpcode(VAL_DRARP_ERROR);
45 + public static final ArpOpcode INARP_REQUEST = new ArpOpcode(VAL_INARP_REQUEST);
46 + public static final ArpOpcode INARP_REPLY = new ArpOpcode(VAL_INARP_REPLY);
47 + public static final ArpOpcode ARP_NAK = new ArpOpcode(VAL_ARP_NAK);
48 + public static final ArpOpcode MARS_REQUEST = new ArpOpcode(VAL_MARS_REQUEST);
49 + public static final ArpOpcode MARS_MULTI = new ArpOpcode(VAL_MARS_MULTI);
50 + public static final ArpOpcode MARS_MSERV = new ArpOpcode(VAL_MARS_MSERV);
51 + public static final ArpOpcode MARS_JOIN = new ArpOpcode(VAL_MARS_JOIN);
52 + public static final ArpOpcode MARS_LEAVE = new ArpOpcode(VAL_MARS_LEAVE);
53 + public static final ArpOpcode MARS_NAK = new ArpOpcode(VAL_MARS_NAK);
54 + public static final ArpOpcode MARS_UNSERV = new ArpOpcode(VAL_MARS_UNSERV);
55 + public static final ArpOpcode MARS_SJOIN = new ArpOpcode(VAL_MARS_SJOIN);
56 + public static final ArpOpcode MARS_SLEAVE = new ArpOpcode(VAL_MARS_SLEAVE);
57 + public static final ArpOpcode MARS_GROUPLIST_REQUEST = new ArpOpcode(VAL_MARS_GROUPLIST_REQUEST);
58 + public static final ArpOpcode MARS_GROUPLIST_REPLY = new ArpOpcode(VAL_MARS_GROUPLIST_REPLY);
59 + public static final ArpOpcode MARS_REDIRECT_MAP = new ArpOpcode(VAL_MARS_REDIRECT_MAP);
60 + public static final ArpOpcode MAPOS_UNARP = new ArpOpcode(VAL_MAPOS_UNARP);
61 + public static final ArpOpcode OP_EXP1 = new ArpOpcode(VAL_OP_EXP1);
62 + public static final ArpOpcode OP_EXP2 = new ArpOpcode(VAL_OP_EXP2);
63 +
64 + private static final int MIN_OPCODE = 0;
65 + private static final int MAX_OPCODE = 0xFFFF;
66 +
67 + private static final int NONE_VAL = 0;
68 + public static final ArpOpcode NONE = new ArpOpcode(NONE_VAL);
69 +
70 + public static final ArpOpcode NO_MASK = new ArpOpcode(0xFFFFFFFF);
71 + public static final ArpOpcode FULL_MASK = new ArpOpcode(0x00000000);
72 +
73 + private final int opcode;
74 +
75 + private ArpOpcode(int opcode) {
76 + this.opcode = opcode;
77 + }
78 +
79 + @Override
80 + public int getLength() {
81 + return LENGTH;
82 + }
83 +
84 + public int getOpcode() {
85 + return this.opcode;
86 + }
87 +
88 + public static ArpOpcode of(int opcode) {
89 + if (opcode < MIN_OPCODE || opcode > MAX_OPCODE)
90 + throw new IllegalArgumentException("Invalid ARP opcode: " + opcode);
91 + switch (opcode) {
92 + case NONE_VAL:
93 + return NONE;
94 + case VAL_REQUEST:
95 + return REQUEST;
96 + case VAL_REPLY:
97 + return REPLY;
98 + case VAL_REQUEST_REVERSE:
99 + return REQUEST_REVERSE;
100 + case VAL_REPLY_REVERSE:
101 + return REPLY_REVERSE;
102 + case VAL_DRARP_REQUEST:
103 + return DRARP_REQUEST;
104 + case VAL_DRARP_REPLY:
105 + return DRARP_REPLY;
106 + case VAL_DRARP_ERROR:
107 + return DRARP_ERROR;
108 + case VAL_INARP_REQUEST:
109 + return INARP_REQUEST;
110 + case VAL_INARP_REPLY:
111 + return INARP_REPLY;
112 + case VAL_ARP_NAK:
113 + return ARP_NAK;
114 + case VAL_MARS_REQUEST:
115 + return MARS_REQUEST;
116 + case VAL_MARS_MULTI:
117 + return MARS_MULTI;
118 + case VAL_MARS_MSERV:
119 + return MARS_MSERV;
120 + case VAL_MARS_JOIN:
121 + return MARS_JOIN;
122 + case VAL_MARS_LEAVE:
123 + return MARS_LEAVE;
124 + case VAL_MARS_NAK:
125 + return MARS_NAK;
126 + case VAL_MARS_UNSERV:
127 + return MARS_UNSERV;
128 + case VAL_MARS_SJOIN:
129 + return MARS_SJOIN;
130 + case VAL_MARS_SLEAVE:
131 + return MARS_SLEAVE;
132 + case VAL_MARS_GROUPLIST_REQUEST:
133 + return MARS_GROUPLIST_REQUEST;
134 + case VAL_MARS_GROUPLIST_REPLY:
135 + return MARS_GROUPLIST_REPLY;
136 + case VAL_MARS_REDIRECT_MAP:
137 + return MARS_REDIRECT_MAP;
138 + case VAL_MAPOS_UNARP:
139 + return MAPOS_UNARP;
140 + case VAL_OP_EXP1:
141 + return OP_EXP1;
142 + case VAL_OP_EXP2:
143 + return OP_EXP2;
144 + default:
145 + return new ArpOpcode(opcode);
146 + }
147 + }
148 +
149 + public void write2Bytes(ChannelBuffer c) {
150 + c.writeShort(this.opcode);
151 + }
152 +
153 + public static ArpOpcode read2Bytes(ChannelBuffer c) {
154 + return ArpOpcode.of(c.readUnsignedShort());
155 + }
156 +
157 + @Override
158 + public ArpOpcode applyMask(ArpOpcode mask) {
159 + return ArpOpcode.of(this.opcode & mask.opcode);
160 + }
161 +
162 + @Override
163 + public int hashCode() {
164 + final int prime = 31;
165 + int result = 1;
166 + result = prime * result + opcode;
167 + return result;
168 + }
169 +
170 + @Override
171 + public boolean equals(Object obj) {
172 + if (this == obj)
173 + return true;
174 + if (obj == null)
175 + return false;
176 + if (getClass() != obj.getClass())
177 + return false;
178 + ArpOpcode other = (ArpOpcode) obj;
179 + if (opcode != other.opcode)
180 + return false;
181 + return true;
182 + }
183 +
184 + @Override
185 + public int compareTo(ArpOpcode o) {
186 + return UnsignedInts.compare(opcode, o.opcode);
187 + }
188 +
189 + @Override
190 + public void putTo(PrimitiveSink sink) {
191 + sink.putShort((short) this.opcode);
192 + }
193 +
194 + @Override
195 + public String toString() {
196 + return String.valueOf(this.opcode);
197 + }
198 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import javax.annotation.concurrent.Immutable;
4 +
5 +import org.jboss.netty.buffer.ChannelBuffer;
6 +
7 +import com.google.common.hash.PrimitiveSink;
8 +import com.google.common.primitives.UnsignedInts;
9 +
10 +@Immutable
11 +public class ClassId implements OFValueType<ClassId> {
12 + static final int LENGTH = 4;
13 +
14 + private final static int NONE_VAL = 0;
15 + public final static ClassId NONE = new ClassId(NONE_VAL);
16 +
17 + private final static int NO_MASK_VAL = 0xFFFFFFFF;
18 + public final static ClassId NO_MASK = new ClassId(NO_MASK_VAL);
19 + public final static ClassId FULL_MASK = NONE;
20 +
21 + private final int rawValue;
22 +
23 + private ClassId(final int rawValue) {
24 + this.rawValue = rawValue;
25 + }
26 +
27 + public static ClassId of(final int raw) {
28 + if(raw == NONE_VAL)
29 + return NONE;
30 + else if(raw == NO_MASK_VAL)
31 + return NO_MASK;
32 + return new ClassId(raw);
33 + }
34 +
35 + public int getInt() {
36 + return rawValue;
37 + }
38 +
39 + @Override
40 + public int getLength() {
41 + return LENGTH;
42 + }
43 +
44 + @Override
45 + public String toString() {
46 + return Integer.toString(rawValue);
47 + }
48 +
49 + @Override
50 + public ClassId applyMask(ClassId mask) {
51 + return ClassId.of(rawValue & mask.rawValue); }
52 +
53 + @Override
54 + public int hashCode() {
55 + final int prime = 31;
56 + int result = 1;
57 + result = prime * result + rawValue;
58 + return result;
59 + }
60 +
61 + @Override
62 + public boolean equals(Object obj) {
63 + if (this == obj)
64 + return true;
65 + if (obj == null)
66 + return false;
67 + if (getClass() != obj.getClass())
68 + return false;
69 + ClassId other = (ClassId) obj;
70 + if (rawValue != other.rawValue)
71 + return false;
72 + return true;
73 + }
74 +
75 + public void write4Bytes(ChannelBuffer c) {
76 + c.writeInt(rawValue);
77 + }
78 +
79 + public static ClassId read4Bytes(ChannelBuffer c) {
80 + return ClassId.of(c.readInt());
81 + }
82 +
83 + @Override
84 + public int compareTo(ClassId o) {
85 + return UnsignedInts.compare(rawValue, rawValue);
86 + }
87 +
88 + @Override
89 + public void putTo(PrimitiveSink sink) {
90 + sink.putInt(rawValue);
91 + }
92 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.projectfloodlight.openflow.annotations.Immutable;
4 +import org.projectfloodlight.openflow.util.HexString;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +import com.google.common.primitives.Longs;
8 +import com.google.common.primitives.UnsignedLongs;
9 +
10 +/**
11 + * Abstraction of a datapath ID that can be set and/or accessed as either a
12 + * long value or a colon-separated string. Immutable
13 + *
14 + * @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com>
15 + */
16 +@Immutable
17 +public class DatapathId implements PrimitiveSinkable, Comparable<DatapathId> {
18 +
19 + public static final DatapathId NONE = new DatapathId(0);
20 +
21 + private final long rawValue;
22 +
23 + private DatapathId(long rawValue) {
24 + this.rawValue = rawValue;
25 + }
26 +
27 + public static DatapathId of(long rawValue) {
28 + return new DatapathId(rawValue);
29 + }
30 +
31 + public static DatapathId of(String s) {
32 + return new DatapathId(HexString.toLong(s));
33 + }
34 +
35 + public static DatapathId of(byte[] bytes) {
36 + return new DatapathId(Longs.fromByteArray(bytes));
37 + }
38 +
39 + public long getLong() {
40 + return rawValue;
41 + }
42 +
43 + public U64 getUnsignedLong() {
44 + return U64.of(rawValue);
45 + }
46 +
47 + public byte[] getBytes() {
48 + return Longs.toByteArray(rawValue);
49 + }
50 +
51 + @Override
52 + public String toString() {
53 + return HexString.toHexString(rawValue);
54 + }
55 +
56 + @Override
57 + public int hashCode() {
58 + final int prime = 31;
59 + int result = 1;
60 + result = prime * result + (int) (rawValue ^ (rawValue >>> 32));
61 + return result;
62 + }
63 +
64 + @Override
65 + public boolean equals(Object obj) {
66 + if (this == obj)
67 + return true;
68 + if (obj == null)
69 + return false;
70 + if (getClass() != obj.getClass())
71 + return false;
72 + DatapathId other = (DatapathId) obj;
73 + if (rawValue != other.rawValue)
74 + return false;
75 + return true;
76 + }
77 +
78 + @Override
79 + public void putTo(PrimitiveSink sink) {
80 + sink.putLong(rawValue);
81 + }
82 +
83 + @Override
84 + public int compareTo(DatapathId o) {
85 + return UnsignedLongs.compare(rawValue, o.rawValue);
86 + }
87 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +import com.google.common.primitives.UnsignedInts;
7 +
8 +
9 +/**
10 + * EtherType field representation.
11 + *
12 + * @author Yotam Harchol (yotam.harchol@bigswitch.com)
13 + */
14 +public class EthType implements OFValueType<EthType> {
15 + static final int LENGTH = 2;
16 +
17 + private final int rawValue;
18 +
19 + static final int VAL_IPv4 = 0x0800; // Internet Protocol version 4 (IPv4)
20 + static final int VAL_ARP = 0x0806; // Address Resolution Protocol (ARP)
21 + static final int VAL_WAKE_ON_LAN = 0x0842; // Wake-on-LAN[3]
22 + static final int VAL_TRILL = 0x22F3; // IETF TRILL Protocol
23 + static final int VAL_DECNET_IV = 0x6003; // DECnet Phase IV
24 + static final int VAL_REV_ARP = 0x8035; // Reverse Address Resolution Protocol
25 + static final int VAL_APPLE_TALK = 0x809B; // AppleTalk (Ethertalk)
26 + static final int VAL_APPLE_TALK_ARP = 0x80F3; // AppleTalk Address Resolution Protocol (AARP)
27 + static final int VAL_VLAN_FRAME = 0x8100; // VLAN-tagged frame (IEEE 802.1Q) & Shortest Path Bridging IEEE 802.1aq[4]
28 + static final int VAL_IPX_8137 = 0x8137; // IPX
29 + static final int VAL_IPX_8138 = 0x8138; // IPX
30 + static final int VAL_QNX = 0x8204; // QNX Qnet
31 + static final int VAL_IPv6 = 0x86DD; // Internet Protocol Version 6 (IPv6)
32 + static final int VAL_ETH_FLOW = 0x8808; // Ethernet flow control
33 + static final int VAL_SLOW_PROTOCOLS = 0x8809; // Slow Protocols (IEEE 802.3)
34 + static final int VAL_COBRANET = 0x8819; // CobraNet
35 + static final int VAL_MPLS_UNICAST = 0x8847; // MPLS unicast
36 + static final int VAL_MPLS_MULTICAST = 0x8848; // MPLS multicast
37 + static final int VAL_PPPoE_DISCOVERY = 0x8863; // PPPoE Discovery Stage
38 + static final int VAL_PPPoE_SESSION = 0x8864; // PPPoE Session Stage
39 + static final int VAL_JUMBO_FRAMES = 0x8870; // Jumbo Frames
40 + static final int VAL_HOMEPLUG_10 = 0x887B; // HomePlug 1.0 MME
41 + static final int VAL_EAP_OVER_LAN = 0x888E; // EAP over LAN (IEEE 802.1X)
42 + static final int VAL_PROFINET = 0x8892; // PROFINET Protocol
43 + static final int VAL_HYPERSCSI = 0x889A; // HyperSCSI (SCSI over Ethernet)
44 + static final int VAL_ATA_OVER_ETH = 0x88A2; // ATA over Ethernet
45 + static final int VAL_ETHERCAT = 0x88A4; // EtherCAT Protocol
46 + static final int VAL_BRIDGING = 0x88A8; // Provider Bridging (IEEE 802.1ad) & Shortest Path Bridging IEEE 802.1aq[5]
47 + static final int VAL_POWERLINK = 0x88AB; // Ethernet Powerlink[citation needed]
48 + static final int VAL_LLDP = 0x88CC; // Link Layer Discovery Protocol (LLDP)
49 + static final int VAL_SERCOS = 0x88CD; // SERCOS III
50 + static final int VAL_HOMEPLUG_AV = 0x88E1; // HomePlug AV MME[citation needed]
51 + static final int VAL_MRP = 0x88E3; // Media Redundancy Protocol (IEC62439-2)
52 + static final int VAL_MAC_SEC = 0x88E5; // MAC security (IEEE 802.1AE)
53 + static final int VAL_PTP = 0x88F7; // Precision Time Protocol (IEEE 1588)
54 + static final int VAL_CFM = 0x8902; // IEEE 802.1ag Connectivity Fault Management (CFM) Protocol / ITU-T Recommendation Y.1731 (OAM)
55 + static final int VAL_FCoE = 0x8906; // Fibre Channel over Ethernet (FCoE)
56 + static final int VAL_FCoE_INIT = 0x8914; // FCoE Initialization Protocol
57 + static final int VAL_RoCE = 0x8915; // RDMA over Converged Ethernet (RoCE)
58 + static final int VAL_HSR = 0x892F; // High-availability Seamless Redundancy (HSR)
59 + static final int VAL_CONF_TEST = 0x9000; // Ethernet Configuration Testing Protocol[6]
60 + static final int VAL_Q_IN_Q = 0x9100; // Q-in-Q
61 + static final int VAL_LLT = 0xCAFE; // Veritas Low Latency Transport (LLT)[7] for Veritas Cluster Server
62 +
63 + public static final EthType IPv4 = new EthType(VAL_IPv4);
64 + public static final EthType ARP = new EthType(VAL_ARP);
65 + public static final EthType WAKE_ON_LAN = new EthType(VAL_WAKE_ON_LAN);
66 + public static final EthType TRILL = new EthType(VAL_TRILL);
67 + public static final EthType DECNET_IV = new EthType(VAL_DECNET_IV);
68 + public static final EthType REV_ARP = new EthType(VAL_REV_ARP );
69 + public static final EthType APPLE_TALK = new EthType(VAL_APPLE_TALK);
70 + public static final EthType APPLE_TALK_ARP = new EthType(VAL_APPLE_TALK_ARP);
71 + public static final EthType VLAN_FRAME = new EthType(VAL_VLAN_FRAME );
72 + public static final EthType IPX_8137 = new EthType(VAL_IPX_8137 );
73 + public static final EthType IPX_8138 = new EthType(VAL_IPX_8138 );
74 + public static final EthType QNX = new EthType(VAL_QNX );
75 + public static final EthType IPv6 = new EthType(VAL_IPv6 );
76 + public static final EthType ETH_FLOW = new EthType(VAL_ETH_FLOW);
77 + public static final EthType SLOW_PROTOCOLS = new EthType(VAL_SLOW_PROTOCOLS );
78 + public static final EthType COBRANET = new EthType(VAL_COBRANET );
79 + public static final EthType MPLS_UNICAST = new EthType(VAL_MPLS_UNICAST );
80 + public static final EthType MPLS_MULTICAST = new EthType(VAL_MPLS_MULTICAST );
81 + public static final EthType PPPoE_DISCOVERY = new EthType(VAL_PPPoE_DISCOVERY);
82 + public static final EthType PPPoE_SESSION = new EthType(VAL_PPPoE_SESSION );
83 + public static final EthType JUMBO_FRAMES = new EthType(VAL_JUMBO_FRAMES );
84 + public static final EthType HOMEPLUG_10 = new EthType(VAL_HOMEPLUG_10 );
85 + public static final EthType EAP_OVER_LAN = new EthType(VAL_EAP_OVER_LAN );
86 + public static final EthType PROFINET = new EthType(VAL_PROFINET );
87 + public static final EthType HYPERSCSI = new EthType(VAL_HYPERSCSI );
88 + public static final EthType ATA_OVER_ETH = new EthType(VAL_ATA_OVER_ETH);
89 + public static final EthType ETHERCAT = new EthType(VAL_ETHERCAT );
90 + public static final EthType BRIDGING = new EthType(VAL_BRIDGING );
91 + public static final EthType POWERLINK = new EthType(VAL_POWERLINK );
92 + public static final EthType LLDP = new EthType(VAL_LLDP );
93 + public static final EthType SERCOS = new EthType(VAL_SERCOS );
94 + public static final EthType HOMEPLUG_AV = new EthType(VAL_HOMEPLUG_AV );
95 + public static final EthType MRP = new EthType(VAL_MRP );
96 + public static final EthType MAC_SEC = new EthType(VAL_MAC_SEC);
97 + public static final EthType PTP = new EthType(VAL_PTP );
98 + public static final EthType CFM = new EthType(VAL_CFM );
99 + public static final EthType FCoE = new EthType(VAL_FCoE );
100 + public static final EthType FCoE_INIT = new EthType(VAL_FCoE_INIT );
101 + public static final EthType RoCE = new EthType(VAL_RoCE );
102 + public static final EthType HSR = new EthType(VAL_HSR );
103 + public static final EthType CONF_TEST = new EthType(VAL_CONF_TEST );
104 + public static final EthType Q_IN_Q = new EthType(VAL_Q_IN_Q );
105 + public static final EthType LLT = new EthType(VAL_LLT );
106 +
107 +
108 + private static final int NONE_VAL = 0x0;
109 + public static final EthType NONE = new EthType(NONE_VAL);
110 +
111 + public static final EthType NO_MASK = new EthType(0xFFFFFFFF);
112 + public static final EthType FULL_MASK = new EthType(0x00000000);
113 +
114 + private EthType(int type) {
115 + this.rawValue = type;
116 + }
117 +
118 + @Override
119 + public int getLength() {
120 + return LENGTH;
121 + }
122 +
123 + public static EthType of(int type) {
124 + switch (type) {
125 + case NONE_VAL:
126 + return NONE;
127 + case VAL_IPv4:
128 + return IPv4;
129 + case VAL_ARP:
130 + return ARP;
131 + case VAL_WAKE_ON_LAN:
132 + return WAKE_ON_LAN;
133 + case VAL_TRILL:
134 + return TRILL;
135 + case VAL_DECNET_IV:
136 + return DECNET_IV;
137 + case VAL_REV_ARP:
138 + return REV_ARP;
139 + case VAL_APPLE_TALK:
140 + return APPLE_TALK;
141 + case VAL_APPLE_TALK_ARP:
142 + return APPLE_TALK_ARP;
143 + case VAL_VLAN_FRAME:
144 + return VLAN_FRAME;
145 + case VAL_IPX_8137:
146 + return IPX_8137;
147 + case VAL_IPX_8138:
148 + return IPX_8138;
149 + case VAL_QNX:
150 + return QNX;
151 + case VAL_IPv6:
152 + return IPv6;
153 + case VAL_ETH_FLOW:
154 + return ETH_FLOW;
155 + case VAL_SLOW_PROTOCOLS:
156 + return SLOW_PROTOCOLS;
157 + case VAL_COBRANET:
158 + return COBRANET;
159 + case VAL_MPLS_UNICAST:
160 + return MPLS_UNICAST;
161 + case VAL_MPLS_MULTICAST:
162 + return MPLS_MULTICAST;
163 + case VAL_PPPoE_DISCOVERY:
164 + return PPPoE_DISCOVERY;
165 + case VAL_PPPoE_SESSION:
166 + return PPPoE_SESSION;
167 + case VAL_JUMBO_FRAMES:
168 + return JUMBO_FRAMES;
169 + case VAL_HOMEPLUG_10:
170 + return HOMEPLUG_10;
171 + case VAL_EAP_OVER_LAN:
172 + return EAP_OVER_LAN;
173 + case VAL_PROFINET:
174 + return PROFINET;
175 + case VAL_HYPERSCSI:
176 + return HYPERSCSI;
177 + case VAL_ATA_OVER_ETH:
178 + return ATA_OVER_ETH;
179 + case VAL_ETHERCAT:
180 + return ETHERCAT;
181 + case VAL_BRIDGING:
182 + return BRIDGING;
183 + case VAL_POWERLINK:
184 + return POWERLINK;
185 + case VAL_LLDP:
186 + return LLDP;
187 + case VAL_SERCOS:
188 + return SERCOS;
189 + case VAL_HOMEPLUG_AV:
190 + return HOMEPLUG_AV;
191 + case VAL_MRP:
192 + return MRP;
193 + case VAL_MAC_SEC:
194 + return MAC_SEC;
195 + case VAL_PTP:
196 + return PTP;
197 + case VAL_CFM:
198 + return CFM;
199 + case VAL_FCoE:
200 + return FCoE;
201 + case VAL_FCoE_INIT:
202 + return FCoE_INIT;
203 + case VAL_RoCE:
204 + return RoCE;
205 + case VAL_HSR:
206 + return HSR;
207 + case VAL_CONF_TEST:
208 + return CONF_TEST;
209 + case VAL_Q_IN_Q:
210 + return Q_IN_Q;
211 + case VAL_LLT:
212 + return LLT;
213 + default:
214 + // TODO: What's here?
215 + return new EthType(type);
216 + }
217 + }
218 +
219 + @Override
220 + public String toString() {
221 + return Integer.toHexString(rawValue);
222 + }
223 +
224 + public void write2Bytes(ChannelBuffer c) {
225 + c.writeShort(this.rawValue);
226 + }
227 +
228 + public static EthType read2Bytes(ChannelBuffer c) {
229 + return EthType.of(c.readUnsignedShort());
230 + }
231 +
232 + @Override
233 + public EthType applyMask(EthType mask) {
234 + return EthType.of(this.rawValue & mask.rawValue);
235 + }
236 +
237 + public int getValue() {
238 + return rawValue;
239 + }
240 +
241 + @Override
242 + public boolean equals(Object obj) {
243 + if (!(obj instanceof EthType))
244 + return false;
245 + EthType o = (EthType)obj;
246 + if (o.rawValue != this.rawValue)
247 + return false;
248 + return true;
249 + }
250 +
251 + @Override
252 + public int hashCode() {
253 + final int prime = 37;
254 + int result = 1;
255 + result = prime * result + rawValue;
256 + return result;
257 + }
258 +
259 + @Override
260 + public int compareTo(EthType o) {
261 + return UnsignedInts.compare(rawValue, o.rawValue);
262 + }
263 +
264 + @Override
265 + public void putTo(PrimitiveSink sink) {
266 + sink.putInt(rawValue);
267 + }
268 +
269 +
270 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +import com.google.common.primitives.UnsignedInts;
8 +
9 +public class GenTableId implements OFValueType<GenTableId>, Comparable<GenTableId> {
10 + final static int LENGTH = 2;
11 +
12 + private static final int VALIDATION_MASK = 0xFFFF;
13 +
14 + private static final int ALL_VAL = 0xFFFF;
15 + private static final int NONE_VAL = 0x0000;
16 + public static final GenTableId NONE = new GenTableId(NONE_VAL);
17 +
18 + public static final GenTableId ALL = new GenTableId(ALL_VAL);
19 + public static final GenTableId ZERO = NONE;
20 +
21 + private final int id;
22 +
23 + private GenTableId(int id) {
24 + this.id = id;
25 + }
26 +
27 + public static GenTableId of(int id) {
28 + switch(id) {
29 + case NONE_VAL:
30 + return NONE;
31 + case ALL_VAL:
32 + return ALL;
33 + default:
34 + if ((id & VALIDATION_MASK) != id)
35 + throw new IllegalArgumentException("Illegal Table id value: " + id);
36 + return new GenTableId(id);
37 + }
38 + }
39 +
40 + @Override
41 + public String toString() {
42 + return "0x" + Integer.toHexString(id);
43 + }
44 +
45 + public int getValue() {
46 + return id;
47 + }
48 +
49 + @Override
50 + public int getLength() {
51 + return LENGTH;
52 + }
53 +
54 + public void write2Bytes(ChannelBuffer c) {
55 + c.writeShort(this.id);
56 + }
57 +
58 + public static GenTableId read2Bytes(ChannelBuffer c) throws OFParseError {
59 + return GenTableId.of(c.readUnsignedShort());
60 + }
61 +
62 + @Override
63 + public GenTableId applyMask(GenTableId mask) {
64 + return GenTableId.of(this.id & mask.id);
65 + }
66 +
67 + @Override
68 + public boolean equals(Object obj) {
69 + if (!(obj instanceof GenTableId))
70 + return false;
71 + GenTableId other = (GenTableId)obj;
72 + if (other.id != this.id)
73 + return false;
74 + return true;
75 + }
76 +
77 + @Override
78 + public int hashCode() {
79 + int prime = 13873;
80 + return this.id * prime;
81 + }
82 +
83 + @Override
84 + public int compareTo(GenTableId other) {
85 + return UnsignedInts.compare(this.id, other.id);
86 + }
87 +
88 + @Override
89 + public void putTo(PrimitiveSink sink) {
90 + sink.putShort((byte) id);
91 + }
92 +
93 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import javax.annotation.concurrent.Immutable;
4 +
5 +/** a hash value that supports bit-wise combinations, mainly to calculate hash values for
6 + * reconciliation operations.
7 + *
8 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
9 + *
10 + * @param <H> - this type, for return type safety.
11 + */
12 +@Immutable
13 +public interface HashValue<H extends HashValue<H>> {
14 + /** return the "numBits" highest-order bits of the hash.
15 + * @param numBits number of higest-order bits to return [0-32].
16 + * @return a numberic value of the 0-32 highest-order bits.
17 + */
18 + int prefixBits(int numBits);
19 +
20 + /** @return the bitwise inverse of this value */
21 + H inverse();
22 +
23 + /** or this value with another value value of the same type */
24 + H or(H other);
25 +
26 + /** and this value with another value value of the same type */
27 + H and(H other);
28 +
29 + /** xor this value with another value value of the same type */
30 + H xor(H other);
31 +
32 + /** calculate a combined hash value of this hash value (the <b>Key</b>) and the hash value
33 + * specified as a parameter (the <b>Value</b>).
34 + * <p>
35 + * The value is constructed as follows:
36 + * <ul>
37 + * <li>the first keyBits bits are taken only from the Key
38 + * <li>the other bits are taken from key xor value.
39 + * </ul>
40 + * The overall result looks like this:
41 + * <pre>
42 + * MSB LSB
43 + * +---------+--------------+
44 + * | key | key ^ value |
45 + * +---------+--------------+
46 + * |-keyBits-|
47 + * </pre>
48 + *
49 + * @param value - hash value to be compared with this value (the key)
50 + * @param keyBits number of prefix bits that are just taken from key
51 + * @return the combined value.
52 + */
53 + H combineWithValue(H value, int keyBits);
54 +}
...\ No newline at end of file ...\ No newline at end of file
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import com.google.common.base.Preconditions;
4 +
5 +public class HashValueUtils {
6 + private HashValueUtils() { }
7 +
8 + public static long combineWithValue(long key, long value, int keyBits) {
9 + Preconditions.checkArgument(keyBits >= 0 && keyBits <= 64, "keyBits must be [0,64]");
10 +
11 + int valueBits = 64 - keyBits;
12 + long valueMask = valueBits == 64 ? 0xFFFFFFFFFFFFFFFFL : (1L << valueBits) - 1;
13 +
14 + return key ^ (value & valueMask);
15 + }
16 +
17 + public static int prefixBits(long raw1, int numBits) {
18 + Preconditions.checkArgument(numBits >= 0 && numBits <= 32,
19 + "numBits must be in range [0, 32]");
20 +
21 + if(numBits == 0)
22 + return 0;
23 +
24 + final int shiftDown = 64 - numBits;
25 +
26 + return (int) (raw1 >>> shiftDown);
27 + }
28 +
29 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +import com.google.common.primitives.Shorts;
7 +
8 +/**
9 + *
10 + * @author Yotam Harchol (yotam.harchol@bigswitch.com)
11 + *
12 + */
13 +public class ICMPv4Code implements OFValueType<ICMPv4Code> {
14 +
15 + final static int LENGTH = 1;
16 + final static short MAX_CODE = 0xFF;
17 +
18 + private final short code;
19 +
20 + private static final short NONE_VAL = 0;
21 + public static final ICMPv4Code NONE = new ICMPv4Code(NONE_VAL);
22 +
23 + public static final ICMPv4Code NO_MASK = new ICMPv4Code((short)0xFFFF);
24 + public static final ICMPv4Code FULL_MASK = new ICMPv4Code((short)0x0000);
25 +
26 + private ICMPv4Code(short code) {
27 + this.code = code;
28 + }
29 +
30 + public static ICMPv4Code of(short code) {
31 + if(code == NONE_VAL)
32 + return NONE;
33 +
34 + if (code > MAX_CODE || code < 0)
35 + throw new IllegalArgumentException("Illegal ICMPv4 code: " + code);
36 + return new ICMPv4Code(code);
37 + }
38 +
39 + @Override
40 + public int getLength() {
41 + return LENGTH;
42 + }
43 +
44 + public short getCode() {
45 + return code;
46 + }
47 +
48 + public void writeByte(ChannelBuffer c) {
49 + c.writeByte(this.code);
50 + }
51 +
52 + public static ICMPv4Code readByte(ChannelBuffer c) {
53 + return ICMPv4Code.of(c.readUnsignedByte());
54 + }
55 +
56 + @Override
57 + public ICMPv4Code applyMask(ICMPv4Code mask) {
58 + return ICMPv4Code.of((short)(this.code & mask.code));
59 + }
60 +
61 +
62 + @Override
63 + public int hashCode() {
64 + final int prime = 31;
65 + int result = 1;
66 + result = prime * result + code;
67 + return result;
68 + }
69 +
70 + @Override
71 + public boolean equals(Object obj) {
72 + if (this == obj)
73 + return true;
74 + if (obj == null)
75 + return false;
76 + if (getClass() != obj.getClass())
77 + return false;
78 + ICMPv4Code other = (ICMPv4Code) obj;
79 + if (code != other.code)
80 + return false;
81 + return true;
82 + }
83 +
84 + @Override
85 + public int compareTo(ICMPv4Code o) {
86 + return Shorts.compare(code, o.code);
87 + }
88 +
89 + @Override
90 + public void putTo(PrimitiveSink sink) {
91 + sink.putShort(code);
92 + }
93 +
94 + @Override
95 + public String toString() {
96 + return String.valueOf(this.code);
97 + }
98 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +import com.google.common.primitives.Shorts;
7 +
8 +public class ICMPv4Type implements OFValueType<ICMPv4Type> {
9 + final static int LENGTH = 1;
10 +
11 + private static final short VAL_ECHO_REPLY = 0;
12 + private static final short VAL_DESTINATION_UNREACHABLE = 3;
13 + private static final short VAL_SOURCE_QUENCH = 4;
14 + private static final short VAL_REDIRECT = 5;
15 + private static final short VAL_ALTERNATE_HOST_ADDRESS = 6;
16 + private static final short VAL_ECHO = 8;
17 + private static final short VAL_ROUTER_ADVERTISEMENT = 9;
18 + private static final short VAL_ROUTER_SOLICITATION = 10;
19 + private static final short VAL_TIME_EXCEEDED = 11;
20 + private static final short VAL_PARAMETER_PROBLEM = 12;
21 + private static final short VAL_TIMESTAMP = 13;
22 + private static final short VAL_TIMESTAMP_REPLY = 14;
23 + private static final short VAL_INFORMATION_REQUEST = 15;
24 + private static final short VAL_INFORMATION_REPLY = 16;
25 + private static final short VAL_ADDRESS_MASK_REQUEST = 17;
26 + private static final short VAL_ADDRESS_MASK_REPLY = 18;
27 + private static final short VAL_TRACEROUTE = 30;
28 + private static final short VAL_DATAGRAM_CONVERSION_ERROR = 31;
29 + private static final short VAL_MOBILE_HOST_REDIRECT = 32;
30 + private static final short VAL_IPV6_WHERE_ARE_YOU = 33;
31 + private static final short VAL_IPV6_I_AM_HERE = 34;
32 + private static final short VAL_MOBILE_REGISTRATION_REQUEST = 35;
33 + private static final short VAL_MOBILE_REGISTRATION_REPLY = 36;
34 + private static final short VAL_DOMAIN_NAME_REQUEST = 37;
35 + private static final short VAL_DOMAIN_NAME_REPLY = 38;
36 + private static final short VAL_SKIP = 39;
37 + private static final short VAL_PHOTURIS = 40;
38 + private static final short VAL_EXPERIMENTAL_MOBILITY = 41;
39 +
40 + public static final ICMPv4Type ECHO_REPLY = new ICMPv4Type(VAL_ECHO_REPLY);
41 + public static final ICMPv4Type DESTINATION_UNREACHABLE = new ICMPv4Type(VAL_DESTINATION_UNREACHABLE);
42 + public static final ICMPv4Type SOURCE_QUENCH = new ICMPv4Type(VAL_SOURCE_QUENCH);
43 + public static final ICMPv4Type REDIRECT = new ICMPv4Type(VAL_REDIRECT);
44 + public static final ICMPv4Type ALTERNATE_HOST_ADDRESS = new ICMPv4Type(VAL_ALTERNATE_HOST_ADDRESS);
45 + public static final ICMPv4Type ECHO = new ICMPv4Type(VAL_ECHO);
46 + public static final ICMPv4Type ROUTER_ADVERTISEMENT = new ICMPv4Type(VAL_ROUTER_ADVERTISEMENT);
47 + public static final ICMPv4Type ROUTER_SOLICITATION = new ICMPv4Type(VAL_ROUTER_SOLICITATION);
48 + public static final ICMPv4Type TIME_EXCEEDED = new ICMPv4Type(VAL_TIME_EXCEEDED);
49 + public static final ICMPv4Type PARAMETER_PROBLEM = new ICMPv4Type(VAL_PARAMETER_PROBLEM);
50 + public static final ICMPv4Type TIMESTAMP = new ICMPv4Type(VAL_TIMESTAMP);
51 + public static final ICMPv4Type TIMESTAMP_REPLY = new ICMPv4Type(VAL_TIMESTAMP_REPLY);
52 + public static final ICMPv4Type INFORMATION_REQUEST = new ICMPv4Type(VAL_INFORMATION_REQUEST);
53 + public static final ICMPv4Type INFORMATION_REPLY = new ICMPv4Type(VAL_INFORMATION_REPLY);
54 + public static final ICMPv4Type ADDRESS_MASK_REQUEST = new ICMPv4Type(VAL_ADDRESS_MASK_REQUEST);
55 + public static final ICMPv4Type ADDRESS_MASK_REPLY = new ICMPv4Type(VAL_ADDRESS_MASK_REPLY);
56 + public static final ICMPv4Type TRACEROUTE = new ICMPv4Type(VAL_TRACEROUTE);
57 + public static final ICMPv4Type DATAGRAM_CONVERSION_ERROR = new ICMPv4Type(VAL_DATAGRAM_CONVERSION_ERROR);
58 + public static final ICMPv4Type MOBILE_HOST_REDIRECT = new ICMPv4Type(VAL_MOBILE_HOST_REDIRECT);
59 + public static final ICMPv4Type IPV6_WHERE_ARE_YOU = new ICMPv4Type(VAL_IPV6_WHERE_ARE_YOU);
60 + public static final ICMPv4Type IPV6_I_AM_HERE = new ICMPv4Type(VAL_IPV6_I_AM_HERE);
61 + public static final ICMPv4Type MOBILE_REGISTRATION_REQUEST = new ICMPv4Type(VAL_MOBILE_REGISTRATION_REQUEST);
62 + public static final ICMPv4Type MOBILE_REGISTRATION_REPLY = new ICMPv4Type(VAL_MOBILE_REGISTRATION_REPLY);
63 + public static final ICMPv4Type DOMAIN_NAME_REQUEST = new ICMPv4Type(VAL_DOMAIN_NAME_REQUEST);
64 + public static final ICMPv4Type DOMAIN_NAME_REPLY = new ICMPv4Type(VAL_DOMAIN_NAME_REPLY);
65 + public static final ICMPv4Type SKIP = new ICMPv4Type(VAL_SKIP);
66 + public static final ICMPv4Type PHOTURIS = new ICMPv4Type(VAL_PHOTURIS);
67 + public static final ICMPv4Type EXPERIMENTAL_MOBILITY = new ICMPv4Type(VAL_EXPERIMENTAL_MOBILITY);
68 +
69 + // HACK alert - we're disapproriating ECHO_REPLY (value 0) as 'none' as well
70 + public static final ICMPv4Type NONE = ECHO_REPLY;
71 +
72 + public static final ICMPv4Type NO_MASK = new ICMPv4Type((short)0xFFFF);
73 + public static final ICMPv4Type FULL_MASK = new ICMPv4Type((short)0x0000);
74 +
75 + private final short type;
76 +
77 + private static final int MIN_TYPE = 0;
78 + private static final int MAX_TYPE = 0xFF;
79 +
80 + private ICMPv4Type(short type) {
81 + this.type = type;
82 + }
83 +
84 + public static ICMPv4Type of(short type) {
85 + if (type < MIN_TYPE || type > MAX_TYPE)
86 + throw new IllegalArgumentException("Invalid ICMPv4 type: " + type);
87 + switch (type) {
88 + case VAL_ECHO_REPLY:
89 + return ECHO_REPLY;
90 + case VAL_DESTINATION_UNREACHABLE:
91 + return DESTINATION_UNREACHABLE;
92 + case VAL_SOURCE_QUENCH:
93 + return SOURCE_QUENCH;
94 + case VAL_REDIRECT:
95 + return REDIRECT;
96 + case VAL_ALTERNATE_HOST_ADDRESS:
97 + return ALTERNATE_HOST_ADDRESS;
98 + case VAL_ECHO:
99 + return ECHO;
100 + case VAL_ROUTER_ADVERTISEMENT:
101 + return ROUTER_ADVERTISEMENT;
102 + case VAL_ROUTER_SOLICITATION:
103 + return ROUTER_SOLICITATION;
104 + case VAL_TIME_EXCEEDED:
105 + return TIME_EXCEEDED;
106 + case VAL_PARAMETER_PROBLEM:
107 + return PARAMETER_PROBLEM;
108 + case VAL_TIMESTAMP:
109 + return TIMESTAMP;
110 + case VAL_TIMESTAMP_REPLY:
111 + return TIMESTAMP_REPLY;
112 + case VAL_INFORMATION_REQUEST:
113 + return INFORMATION_REQUEST;
114 + case VAL_INFORMATION_REPLY:
115 + return INFORMATION_REPLY;
116 + case VAL_ADDRESS_MASK_REQUEST:
117 + return ADDRESS_MASK_REQUEST;
118 + case VAL_ADDRESS_MASK_REPLY:
119 + return ADDRESS_MASK_REPLY;
120 + case VAL_TRACEROUTE:
121 + return TRACEROUTE;
122 + case VAL_DATAGRAM_CONVERSION_ERROR:
123 + return DATAGRAM_CONVERSION_ERROR;
124 + case VAL_MOBILE_HOST_REDIRECT:
125 + return MOBILE_HOST_REDIRECT;
126 + case VAL_IPV6_WHERE_ARE_YOU:
127 + return IPV6_WHERE_ARE_YOU;
128 + case VAL_IPV6_I_AM_HERE:
129 + return IPV6_I_AM_HERE;
130 + case VAL_MOBILE_REGISTRATION_REQUEST:
131 + return MOBILE_REGISTRATION_REQUEST;
132 + case VAL_MOBILE_REGISTRATION_REPLY:
133 + return MOBILE_REGISTRATION_REPLY;
134 + case VAL_DOMAIN_NAME_REQUEST:
135 + return DOMAIN_NAME_REQUEST;
136 + case VAL_DOMAIN_NAME_REPLY:
137 + return DOMAIN_NAME_REPLY;
138 + case VAL_SKIP:
139 + return SKIP;
140 + case VAL_PHOTURIS:
141 + return PHOTURIS;
142 + case VAL_EXPERIMENTAL_MOBILITY:
143 + return EXPERIMENTAL_MOBILITY;
144 + default:
145 + return new ICMPv4Type(type);
146 + }
147 + }
148 +
149 + @Override
150 + public int getLength() {
151 + return LENGTH;
152 + }
153 +
154 + public short getType() {
155 + return type;
156 + }
157 +
158 + public void writeByte(ChannelBuffer c) {
159 + c.writeByte(this.type);
160 + }
161 +
162 + public static ICMPv4Type readByte(ChannelBuffer c) {
163 + return ICMPv4Type.of(c.readUnsignedByte());
164 + }
165 +
166 + @Override
167 + public ICMPv4Type applyMask(ICMPv4Type mask) {
168 + return ICMPv4Type.of((short)(this.type & mask.type));
169 + }
170 +
171 + @Override
172 + public int hashCode() {
173 + final int prime = 31;
174 + int result = 1;
175 + result = prime * result + type;
176 + return result;
177 + }
178 +
179 + @Override
180 + public boolean equals(Object obj) {
181 + if (this == obj)
182 + return true;
183 + if (obj == null)
184 + return false;
185 + if (getClass() != obj.getClass())
186 + return false;
187 + ICMPv4Type other = (ICMPv4Type) obj;
188 + if (type != other.type)
189 + return false;
190 + return true;
191 + }
192 +
193 + @Override
194 + public int compareTo(ICMPv4Type o) {
195 + return Shorts.compare(type, o.type);
196 + }
197 +
198 + @Override
199 + public void putTo(PrimitiveSink sink) {
200 + sink.putShort(type);
201 + }
202 +
203 + @Override
204 + public String toString() {
205 + return String.valueOf(this.type);
206 + }
207 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.net.Inet4Address;
4 +import java.net.Inet6Address;
5 +import java.net.InetAddress;
6 +
7 +import javax.annotation.Nonnull;
8 +
9 +import com.google.common.base.Preconditions;
10 +
11 +public abstract class IPAddress<F extends IPAddress<F>> implements OFValueType<F> {
12 +
13 + public abstract IPVersion getIpVersion();
14 +
15 + /**
16 + * Checks if this IPAddress represents a valid CIDR style netmask, i.e.,
17 + * it has a set of leading "1" bits followed by only "0" bits
18 + * @return true if this represents a valid CIDR style netmask, false
19 + * otherwise
20 + */
21 + public abstract boolean isCidrMask();
22 +
23 + /**
24 + * If this IPAddress represents a valid CIDR style netmask (see
25 + * isCidrMask()) returns the length of the prefix (the number of "1" bits).
26 + * @return length of CIDR mask if this represents a valid CIDR mask
27 + * @throws IllegalStateException if isCidrMask() == false
28 + */
29 + public abstract int asCidrMaskLength();
30 +
31 + /**
32 + * Checks if the IPAddress is the global broadcast address
33 + * 255.255.255.255 in case of IPv4
34 + * @return boolean true or false
35 + */
36 + public abstract boolean isBroadcast();
37 +
38 + /**
39 + * Perform a low level AND operation on the bits of two IPAddress<?> objects
40 + * @param other IPAddress<?>
41 + * @return new IPAddress<?> object after the AND oper
42 + */
43 + public abstract F and(F other);
44 +
45 + /**
46 + * Perform a low level OR operation on the bits of two IPAddress<?> objects
47 + * @param other IPAddress<?>
48 + * @return new IPAddress<?> object after the AND oper
49 + */
50 + public abstract F or(F other);
51 +
52 + /**
53 + * Returns a new IPAddress object with the bits inverted
54 + * @return IPAddress<?>
55 + */
56 + public abstract F not();
57 +
58 + @Override
59 + public abstract boolean equals(Object other);
60 +
61 + @Override
62 + public abstract int hashCode();
63 +
64 + /** parse an IPv4Address or IPv6Address from their conventional string representation.
65 + * For details on supported representations, refer to {@link IPv4Address#of(String)}
66 + * and {@link IPv6Address#of(String)}
67 + *
68 + * @param ip a string representation of an IP address
69 + * @return the parsed IP address
70 + * @throws NullPointerException if ip is null
71 + * @throws IllegalArgumentException if string is not a valid IP address
72 + */
73 + @Nonnull
74 + public static IPAddress<?> of(@Nonnull String ip) {
75 + Preconditions.checkNotNull(ip, "ip must not be null");
76 + if (ip.indexOf('.') != -1)
77 + return IPv4Address.of(ip);
78 + else if (ip.indexOf(':') != -1)
79 + return IPv6Address.of(ip);
80 + else
81 + throw new IllegalArgumentException("IP Address not well formed: " + ip);
82 + }
83 +
84 + /**
85 + * Factory function for InetAddress values.
86 + * @param address the InetAddress you wish to parse into an IPAddress object.
87 + * @return the IPAddress object.
88 + * @throws NullPointerException if address is null
89 + */
90 + @Nonnull
91 + public static IPAddress<?> fromInetAddress(@Nonnull InetAddress address) {
92 + Preconditions.checkNotNull(address, "address must not be null");
93 + byte [] bytes = address.getAddress();
94 + if(address instanceof Inet4Address)
95 + return IPv4Address.of(bytes);
96 + else if (address instanceof Inet6Address)
97 + return IPv6Address.of(bytes);
98 + else
99 + return IPAddress.of(address.getHostAddress());
100 + }
101 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +
4 +public abstract class IPAddressWithMask<F extends IPAddress<F>> extends Masked<F> {
5 +
6 + protected IPAddressWithMask(F value, F mask) {
7 + super(value, mask);
8 + }
9 +
10 + public abstract IPVersion getIpVersion();
11 +
12 + public F getSubnetBroadcastAddress() {
13 + if (!mask.isCidrMask()) {
14 + throw new IllegalArgumentException("Mask Invalid " + mask +
15 + " cannot get subnet for non CIDR mask");
16 + }
17 + return value.or(mask.not());
18 + }
19 +
20 + public boolean isSubnetBroadcastAddress(F candidate) {
21 + return getSubnetBroadcastAddress().equals(candidate);
22 + }
23 +
24 + public static IPAddressWithMask<?> of(String ip) {
25 + if (ip == null) {
26 + throw new NullPointerException("String ip must not be null");
27 + }
28 + if (ip.indexOf('.') != -1)
29 + return IPv4AddressWithMask.of(ip);
30 + else if (ip.indexOf(':') != -1)
31 + return IPv6AddressWithMask.of(ip);
32 + else
33 + throw new IllegalArgumentException("IP Address not well formed: " + ip);
34 + }
35 +
36 + @Override
37 + public String toString() {
38 + StringBuilder res = new StringBuilder();
39 + res.append(value.toString());
40 +
41 + res.append('/');
42 + if (mask.isCidrMask()) {
43 + // CIDR notation
44 + res.append(mask.asCidrMaskLength());
45 + } else {
46 + // Full address mask
47 + res.append(mask.toString());
48 + }
49 +
50 + return res.toString();
51 + }
52 +
53 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +public enum IPVersion {
4 + IPv4,
5 + IPv6
6 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.util.Arrays;
4 +
5 +import javax.annotation.Nonnull;
6 +
7 +import org.jboss.netty.buffer.ChannelBuffer;
8 +
9 +import com.google.common.hash.PrimitiveSink;
10 +import com.google.common.primitives.UnsignedInts;
11 +
12 +
13 +
14 +/**
15 + * Wrapper around an IPv4Address address
16 + *
17 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
18 + */
19 +public class IPv4Address extends IPAddress<IPv4Address> {
20 + static final int LENGTH = 4;
21 + private final int rawValue;
22 +
23 + private static final int NOT_A_CIDR_MASK = -1;
24 + private static final int CIDR_MASK_CACHE_UNSET = -2;
25 + // Must appear before the static IPv4Address constant assignments
26 + private volatile int cidrMaskLengthCache = CIDR_MASK_CACHE_UNSET;
27 +
28 + private final static int NONE_VAL = 0x0;
29 + public final static IPv4Address NONE = new IPv4Address(NONE_VAL);
30 +
31 + public static final IPv4Address NO_MASK = IPv4Address.of(0xFFFFFFFF);
32 + public static final IPv4Address FULL_MASK = IPv4Address.of(0x00000000);
33 +
34 + private IPv4Address(final int rawValue) {
35 + this.rawValue = rawValue;
36 + }
37 +
38 + @Override
39 + public IPVersion getIpVersion() {
40 + return IPVersion.IPv4;
41 + }
42 +
43 + private int asCidrMaskLengthInternal() {
44 + if (cidrMaskLengthCache == CIDR_MASK_CACHE_UNSET) {
45 + // No lock required. We only write cidrMaskLengthCache once
46 + int maskint = getInt();
47 + if (maskint == 0) {
48 + cidrMaskLengthCache = 0;
49 + } else if (Integer.bitCount((~maskint) + 1) == 1) {
50 + // IP represents a true CIDR prefix length
51 + cidrMaskLengthCache = Integer.bitCount(maskint);
52 + } else {
53 + cidrMaskLengthCache = NOT_A_CIDR_MASK;
54 + }
55 + }
56 + return cidrMaskLengthCache;
57 + }
58 +
59 + @Override
60 + public boolean isCidrMask() {
61 + return asCidrMaskLengthInternal() != NOT_A_CIDR_MASK;
62 + }
63 +
64 + @Override
65 + public int asCidrMaskLength() {
66 + if (!isCidrMask()) {
67 + throw new IllegalStateException("IP is not a valid CIDR prefix " +
68 + "mask " + toString());
69 + } else {
70 + return asCidrMaskLengthInternal();
71 + }
72 + }
73 +
74 + @Override
75 + public boolean isBroadcast() {
76 + return this.equals(NO_MASK);
77 + }
78 +
79 + @Override
80 + public IPv4Address and(IPv4Address other) {
81 + if (other == null) {
82 + throw new NullPointerException("Other IP Address must not be null");
83 + }
84 + IPv4Address otherIp = (IPv4Address) other;
85 + return IPv4Address.of(rawValue & otherIp.rawValue);
86 + }
87 +
88 + @Override
89 + public IPv4Address or(IPv4Address other) {
90 + if (other == null) {
91 + throw new NullPointerException("Other IP Address must not be null");
92 + }
93 + IPv4Address otherIp = (IPv4Address) other;
94 + return IPv4Address.of(rawValue | otherIp.rawValue);
95 + }
96 +
97 + @Override
98 + public IPv4Address not() {
99 + return IPv4Address.of(~rawValue);
100 + }
101 +
102 + public static IPv4Address of(final byte[] address) {
103 + if (address == null) {
104 + throw new NullPointerException("Address must not be null");
105 + }
106 + if (address.length != LENGTH) {
107 + throw new IllegalArgumentException(
108 + "Invalid byte array length for IPv4Address address: " + address.length);
109 + }
110 +
111 + int raw =
112 + (address[0] & 0xFF) << 24 | (address[1] & 0xFF) << 16
113 + | (address[2] & 0xFF) << 8 | (address[3] & 0xFF) << 0;
114 + return IPv4Address.of(raw);
115 + }
116 +
117 + /** construct an IPv4Address from a 32-bit integer value.
118 + *
119 + * @param raw the IPAdress represented as a 32-bit integer
120 + * @return the constructed IPv4Address
121 + */
122 + public static IPv4Address of(final int raw) {
123 + if(raw == NONE_VAL)
124 + return NONE;
125 + return new IPv4Address(raw);
126 + }
127 +
128 + /** parse an IPv4Address from the canonical dotted-quad representation
129 + * (1.2.3.4).
130 + *
131 + * @param string an IPv4 address in dotted-quad representation
132 + * @return the parsed IPv4 address
133 + * @throws NullPointerException if string is null
134 + * @throws IllegalArgumentException if string is not a valid IPv4Address
135 + */
136 + @Nonnull
137 + public static IPv4Address of(@Nonnull final String string) throws IllegalArgumentException {
138 + if (string == null) {
139 + throw new NullPointerException("String must not be null");
140 + }
141 + int start = 0;
142 + int shift = 24;
143 +
144 + int raw = 0;
145 + while (shift >= 0) {
146 + int end = string.indexOf('.', start);
147 + if (end == start || !((shift > 0) ^ (end < 0)))
148 + throw new IllegalArgumentException("IP Address not well formed: " + string);
149 +
150 + String substr =
151 + end > 0 ? string.substring(start, end) : string.substring(start);
152 + int val = Integer.parseInt(substr);
153 + if (val < 0 || val > 255)
154 + throw new IllegalArgumentException("IP Address not well formed: " + string);
155 +
156 + raw |= val << shift;
157 +
158 + shift -= 8;
159 + start = end + 1;
160 + }
161 + return IPv4Address.of(raw);
162 + }
163 +
164 + public int getInt() {
165 + return rawValue;
166 + }
167 +
168 + private volatile byte[] bytesCache = null;
169 +
170 + public byte[] getBytes() {
171 + if (bytesCache == null) {
172 + synchronized (this) {
173 + if (bytesCache == null) {
174 + bytesCache =
175 + new byte[] { (byte) ((rawValue >>> 24) & 0xFF),
176 + (byte) ((rawValue >>> 16) & 0xFF),
177 + (byte) ((rawValue >>> 8) & 0xFF),
178 + (byte) ((rawValue >>> 0) & 0xFF) };
179 + }
180 + }
181 + }
182 + return Arrays.copyOf(bytesCache, bytesCache.length);
183 + }
184 +
185 + @Override
186 + public int getLength() {
187 + return LENGTH;
188 + }
189 +
190 + @Override
191 + public String toString() {
192 + StringBuilder res = new StringBuilder();
193 + res.append((rawValue >> 24) & 0xFF).append('.');
194 + res.append((rawValue >> 16) & 0xFF).append('.');
195 + res.append((rawValue >> 8) & 0xFF).append('.');
196 + res.append((rawValue >> 0) & 0xFF);
197 + return res.toString();
198 + }
199 +
200 + public void write4Bytes(ChannelBuffer c) {
201 + c.writeInt(rawValue);
202 + }
203 +
204 + public static IPv4Address read4Bytes(ChannelBuffer c) {
205 + return IPv4Address.of(c.readInt());
206 + }
207 +
208 + @Override
209 + public IPv4Address applyMask(IPv4Address mask) {
210 + return and(mask);
211 + }
212 +
213 + @Override
214 + public int hashCode() {
215 + final int prime = 31;
216 + int result = 1;
217 + result = prime * result + rawValue;
218 + return result;
219 + }
220 +
221 + @Override
222 + public boolean equals(Object obj) {
223 + if (this == obj)
224 + return true;
225 + if (obj == null)
226 + return false;
227 + if (getClass() != obj.getClass())
228 + return false;
229 + IPv4Address other = (IPv4Address) obj;
230 + if (rawValue != other.rawValue)
231 + return false;
232 + return true;
233 + }
234 +
235 + @Override
236 + public int compareTo(IPv4Address o) {
237 + return UnsignedInts.compare(rawValue, o.rawValue);
238 + }
239 +
240 + @Override
241 + public void putTo(PrimitiveSink sink) {
242 + sink.putInt(rawValue);
243 + }
244 +
245 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +
4 +public class IPv4AddressWithMask extends IPAddressWithMask<IPv4Address> {
5 + public final static IPv4AddressWithMask NONE = of(IPv4Address.NONE, IPv4Address.NONE);
6 +
7 + private IPv4AddressWithMask(int rawValue, int rawMask) {
8 + super(IPv4Address.of(rawValue), IPv4Address.of(rawMask));
9 + }
10 +
11 + private IPv4AddressWithMask(IPv4Address value, IPv4Address mask) {
12 + super(value, mask);
13 + }
14 +
15 + @Override
16 + public IPVersion getIpVersion() {
17 + return IPVersion.IPv4;
18 + }
19 +
20 + public static IPv4AddressWithMask of(int rawValue, int rawMask) {
21 + return new IPv4AddressWithMask(rawValue, rawMask);
22 + }
23 +
24 + public static IPv4AddressWithMask of(IPv4Address value, IPv4Address mask) {
25 + if (value == null) {
26 + throw new NullPointerException("Value must not be null");
27 + }
28 + if (mask == null) {
29 + throw new NullPointerException("Mask must not be null");
30 + }
31 + return new IPv4AddressWithMask(value, mask);
32 + }
33 +
34 + public static IPv4AddressWithMask of(final String string) {
35 + if (string == null) {
36 + throw new NullPointerException("String must not be null");
37 + }
38 + int slashPos;
39 + String ip = string;
40 + int maskBits = 32;
41 + IPv4Address maskAddress = null;
42 +
43 + // Read mask suffix
44 + if ((slashPos = string.indexOf('/')) != -1) {
45 + ip = string.substring(0, slashPos);
46 + try {
47 + String suffix = string.substring(slashPos + 1);
48 + if (suffix.length() == 0)
49 + throw new IllegalArgumentException("IP Address not well formed: " + string);
50 + if (suffix.indexOf('.') != -1) {
51 + // Full mask
52 + maskAddress = IPv4Address.of(suffix);
53 + } else {
54 + // CIDR Suffix
55 + maskBits = Integer.parseInt(suffix);
56 + }
57 + } catch (NumberFormatException e) {
58 + throw new IllegalArgumentException("IP Address not well formed: " + string);
59 + }
60 + if (maskBits < 0 || maskBits > 32) {
61 + throw new IllegalArgumentException("IP Address not well formed: " + string);
62 + }
63 + }
64 +
65 + // Read IP
66 + IPv4Address ipv4 = IPv4Address.of(ip);
67 +
68 + if (maskAddress != null) {
69 + // Full address mask
70 + return IPv4AddressWithMask.of(ipv4, maskAddress);
71 + } else if (maskBits == 32) {
72 + // No mask
73 + return IPv4AddressWithMask.of(ipv4, IPv4Address.NO_MASK);
74 + } else if (maskBits == 0) {
75 + // No mask
76 + return IPv4AddressWithMask.of(ipv4, IPv4Address.FULL_MASK);
77 + } else {
78 + // With mask
79 + int mask = (-1) << (32 - maskBits);
80 + return IPv4AddressWithMask.of(ipv4, IPv4Address.of(mask));
81 + }
82 + }
83 +
84 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.util.Arrays;
4 +import java.util.regex.Pattern;
5 +
6 +import javax.annotation.Nonnull;
7 +
8 +import org.jboss.netty.buffer.ChannelBuffer;
9 +import org.projectfloodlight.openflow.exceptions.OFParseError;
10 +
11 +import com.google.common.hash.PrimitiveSink;
12 +import com.google.common.primitives.Longs;
13 +
14 +/**
15 + * IPv6 address object. Instance controlled, immutable. Internal representation:
16 + * two 64 bit longs (not that you'd have to know).
17 + *
18 + * @author Andreas Wundsam <andreas.wundsam@teleteach.de>
19 + */
20 +public class IPv6Address extends IPAddress<IPv6Address> {
21 + static final int LENGTH = 16;
22 + private final long raw1;
23 + private final long raw2;
24 +
25 + private static final int NOT_A_CIDR_MASK = -1;
26 + private static final int CIDR_MASK_CACHE_UNSET = -2;
27 + // Must appear before the static IPv4Address constant assignments
28 + private volatile int cidrMaskLengthCache = CIDR_MASK_CACHE_UNSET;
29 +
30 + private final static long NONE_VAL1 = 0x0L;
31 + private final static long NONE_VAL2 = 0x0L;
32 + public static final IPv6Address NONE = new IPv6Address(NONE_VAL1, NONE_VAL2);
33 +
34 +
35 + public static final IPv6Address NO_MASK = IPv6Address.of(0xFFFFFFFFFFFFFFFFl, 0xFFFFFFFFFFFFFFFFl);
36 + public static final IPv6Address FULL_MASK = IPv6Address.of(0x0, 0x0);
37 +
38 + private IPv6Address(final long raw1, final long raw2) {
39 + this.raw1 = raw1;
40 + this.raw2 = raw2;
41 + }
42 +
43 + @Override
44 + public IPVersion getIpVersion() {
45 + return IPVersion.IPv6;
46 + }
47 +
48 +
49 + private int computeCidrMask64(long raw) {
50 + long mask = raw;
51 + if (raw == 0)
52 + return 0;
53 + else if (Long.bitCount((~mask) + 1) == 1) {
54 + // represent a true CIDR prefix length
55 + return Long.bitCount(mask);
56 + }
57 + else {
58 + // Not a true prefix
59 + return NOT_A_CIDR_MASK;
60 + }
61 + }
62 +
63 + private int asCidrMaskLengthInternal() {
64 + if (cidrMaskLengthCache == CIDR_MASK_CACHE_UNSET) {
65 + // No synchronization needed. Writing cidrMaskLengthCache only once
66 + if (raw1 == 0 && raw2 == 0) {
67 + cidrMaskLengthCache = 0;
68 + } else if (raw1 == -1L) {
69 + // top half is all 1 bits
70 + int tmpLength = computeCidrMask64(raw2);
71 + if (tmpLength != NOT_A_CIDR_MASK)
72 + tmpLength += 64;
73 + cidrMaskLengthCache = tmpLength;
74 + } else if (raw2 == 0) {
75 + cidrMaskLengthCache = computeCidrMask64(raw1);
76 + } else {
77 + cidrMaskLengthCache = NOT_A_CIDR_MASK;
78 + }
79 + }
80 + return cidrMaskLengthCache;
81 + }
82 +
83 + @Override
84 + public boolean isCidrMask() {
85 + return asCidrMaskLengthInternal() != NOT_A_CIDR_MASK;
86 + }
87 +
88 + @Override
89 + public int asCidrMaskLength() {
90 + if (!isCidrMask()) {
91 + throw new IllegalStateException("IP is not a valid CIDR prefix " +
92 + "mask " + toString());
93 + } else {
94 + return asCidrMaskLengthInternal();
95 + }
96 + }
97 +
98 + @Override
99 + public boolean isBroadcast() {
100 + return this.equals(NO_MASK);
101 + }
102 +
103 + @Override
104 + public IPv6Address and(IPv6Address other) {
105 + if (other == null) {
106 + throw new NullPointerException("Other IP Address must not be null");
107 + }
108 + IPv6Address otherIp = (IPv6Address) other;
109 + return IPv6Address.of((raw1 & otherIp.raw1), (raw2 & otherIp.raw2));
110 + }
111 +
112 + @Override
113 + public IPv6Address or(IPv6Address other) {
114 + if (other == null) {
115 + throw new NullPointerException("Other IP Address must not be null");
116 + }
117 + IPv6Address otherIp = (IPv6Address) other;
118 + return IPv6Address.of((raw1 | otherIp.raw1), (raw2 | otherIp.raw2));
119 + }
120 +
121 + @Override
122 + public IPv6Address not() {
123 + return IPv6Address.of(~raw1, ~raw2);
124 + }
125 +
126 + public static IPv6Address of(final byte[] address) {
127 + if (address == null) {
128 + throw new NullPointerException("Address must not be null");
129 + }
130 + if (address.length != LENGTH) {
131 + throw new IllegalArgumentException(
132 + "Invalid byte array length for IPv6 address: " + address.length);
133 + }
134 +
135 + long raw1 =
136 + (address[0] & 0xFFL) << 56 | (address[1] & 0xFFL) << 48
137 + | (address[2] & 0xFFL) << 40 | (address[3] & 0xFFL) << 32
138 + | (address[4] & 0xFFL) << 24 | (address[5] & 0xFFL) << 16
139 + | (address[6] & 0xFFL) << 8 | (address[7]);
140 +
141 + long raw2 =
142 + (address[8] & 0xFFL) << 56 | (address[9] & 0xFFL) << 48
143 + | (address[10] & 0xFFL) << 40 | (address[11] & 0xFFL) << 32
144 + | (address[12] & 0xFFL) << 24 | (address[13] & 0xFFL) << 16
145 + | (address[14] & 0xFFL) << 8 | (address[15]);
146 +
147 + return IPv6Address.of(raw1, raw2);
148 + }
149 +
150 + private static class IPv6Builder {
151 + private long raw1, raw2;
152 +
153 + public void setUnsignedShortWord(final int i, final int value) {
154 + int shift = 48 - (i % 4) * 16;
155 +
156 + if (value < 0 || value > 0xFFFF)
157 + throw new IllegalArgumentException("16 bit word must be in [0, 0xFFFF]");
158 +
159 + if (i >= 0 && i < 4)
160 + raw1 = raw1 & ~(0xFFFFL << shift) | (value & 0xFFFFL) << shift;
161 + else if (i >= 4 && i < 8)
162 + raw2 = raw2 & ~(0xFFFFL << shift) | (value & 0xFFFFL) << shift;
163 + else
164 + throw new IllegalArgumentException("16 bit word index must be in [0,7]");
165 + }
166 +
167 + public IPv6Address getIPv6() {
168 + return IPv6Address.of(raw1, raw2);
169 + }
170 + }
171 +
172 + private final static Pattern colonPattern = Pattern.compile(":");
173 +
174 + /** parse an IPv6Address from its conventional string representation.
175 + * <p>
176 + * Expects up to 8 groups of 16-bit hex words seperated by colons
177 + * (e.g., 2001:db8:85a3:8d3:1319:8a2e:370:7348).
178 + * <p>
179 + * Supports zero compression (e.g., 2001:db8::7348).
180 + * Does <b>not</b> currently support embedding a dotted-quad IPv4 address
181 + * into the IPv6 address (e.g., 2001:db8::192.168.0.1).
182 + *
183 + * @param string a string representation of an IPv6 address
184 + * @return the parsed IPv6 address
185 + * @throws NullPointerException if string is null
186 + * @throws IllegalArgumentException if string is not a valid IPv6Address
187 + */
188 + @Nonnull
189 + public static IPv6Address of(@Nonnull final String string) throws IllegalArgumentException {
190 + if (string == null) {
191 + throw new NullPointerException("String must not be null");
192 + }
193 + IPv6Builder builder = new IPv6Builder();
194 + String[] parts = colonPattern.split(string, -1);
195 +
196 + int leftWord = 0;
197 + int leftIndex = 0;
198 +
199 + boolean hitZeroCompression = false;
200 +
201 + for (leftIndex = 0; leftIndex < parts.length; leftIndex++) {
202 + String part = parts[leftIndex];
203 + if (part.length() == 0) {
204 + // hit empty group of zero compression
205 + hitZeroCompression = true;
206 + break;
207 + }
208 + builder.setUnsignedShortWord(leftWord++, Integer.parseInt(part, 16));
209 + }
210 +
211 + if (hitZeroCompression) {
212 + if (leftIndex == 0) {
213 + // if colon is at the start, two columns must be at the start,
214 + // move to the second empty group
215 + leftIndex = 1;
216 + if (parts.length < 2 || parts[1].length() > 0)
217 + throw new IllegalArgumentException("Malformed IPv6 address: " + string);
218 + }
219 +
220 + int rightWord = 7;
221 + int rightIndex;
222 + for (rightIndex = parts.length - 1; rightIndex > leftIndex; rightIndex--) {
223 + String part = parts[rightIndex];
224 + if (part.length() == 0)
225 + break;
226 + builder.setUnsignedShortWord(rightWord--, Integer.parseInt(part, 16));
227 + }
228 + if (rightIndex == parts.length - 1) {
229 + // if colon is at the end, two columns must be at the end, move
230 + // to the second empty group
231 + if (rightIndex < 1 || parts[rightIndex - 1].length() > 0)
232 + throw new IllegalArgumentException("Malformed IPv6 address: " + string);
233 + rightIndex--;
234 + }
235 + if (leftIndex != rightIndex)
236 + throw new IllegalArgumentException("Malformed IPv6 address: " + string);
237 + } else {
238 + if (leftIndex != 8) {
239 + throw new IllegalArgumentException("Malformed IPv6 address: " + string);
240 + }
241 + }
242 + return builder.getIPv6();
243 + }
244 +
245 + /** construct an IPv6 adress from two 64 bit integers representing the first and
246 + * second 8-byte blocks of the address.
247 + *
248 + * @param raw1 - the first 8 byte block of the address
249 + * @param raw2 - the second 8 byte block of the address
250 + * @return the constructed IPv6Address
251 + */
252 + public static IPv6Address of(final long raw1, final long raw2) {
253 + if(raw1==NONE_VAL1 && raw2 == NONE_VAL2)
254 + return NONE;
255 + return new IPv6Address(raw1, raw2);
256 + }
257 +
258 + private volatile byte[] bytesCache = null;
259 +
260 + public byte[] getBytes() {
261 + if (bytesCache == null) {
262 + synchronized (this) {
263 + if (bytesCache == null) {
264 + bytesCache =
265 + new byte[] { (byte) ((raw1 >> 56) & 0xFF),
266 + (byte) ((raw1 >> 48) & 0xFF),
267 + (byte) ((raw1 >> 40) & 0xFF),
268 + (byte) ((raw1 >> 32) & 0xFF),
269 + (byte) ((raw1 >> 24) & 0xFF),
270 + (byte) ((raw1 >> 16) & 0xFF),
271 + (byte) ((raw1 >> 8) & 0xFF),
272 + (byte) ((raw1 >> 0) & 0xFF),
273 +
274 + (byte) ((raw2 >> 56) & 0xFF),
275 + (byte) ((raw2 >> 48) & 0xFF),
276 + (byte) ((raw2 >> 40) & 0xFF),
277 + (byte) ((raw2 >> 32) & 0xFF),
278 + (byte) ((raw2 >> 24) & 0xFF),
279 + (byte) ((raw2 >> 16) & 0xFF),
280 + (byte) ((raw2 >> 8) & 0xFF),
281 + (byte) ((raw2 >> 0) & 0xFF) };
282 + }
283 + }
284 + }
285 + return Arrays.copyOf(bytesCache, bytesCache.length);
286 + }
287 +
288 + @Override
289 + public int getLength() {
290 + return LENGTH;
291 + }
292 +
293 + @Override
294 + public String toString() {
295 + return toString(true, false);
296 + }
297 +
298 + public int getUnsignedShortWord(final int i) {
299 + if (i >= 0 && i < 4)
300 + return (int) ((raw1 >>> (48 - i * 16)) & 0xFFFF);
301 + else if (i >= 4 && i < 8)
302 + return (int) ((raw2 >>> (48 - (i - 4) * 16)) & 0xFFFF);
303 + else
304 + throw new IllegalArgumentException("16 bit word index must be in [0,7]");
305 + }
306 +
307 + /** get the index of the first word where to apply IPv6 zero compression */
308 + public int getZeroCompressStart() {
309 + int start = Integer.MAX_VALUE;
310 + int maxLength = -1;
311 +
312 + int candidateStart = -1;
313 +
314 + for (int i = 0; i < 8; i++) {
315 + if (candidateStart >= 0) {
316 + // in a zero octect
317 + if (getUnsignedShortWord(i) != 0) {
318 + // end of this candidate word
319 + int candidateLength = i - candidateStart;
320 + if (candidateLength >= maxLength) {
321 + start = candidateStart;
322 + maxLength = candidateLength;
323 + }
324 + candidateStart = -1;
325 + }
326 + } else {
327 + // not in a zero octect
328 + if (getUnsignedShortWord(i) == 0) {
329 + candidateStart = i;
330 + }
331 + }
332 + }
333 +
334 + if (candidateStart >= 0) {
335 + int candidateLength = 8 - candidateStart;
336 + if (candidateLength >= maxLength) {
337 + start = candidateStart;
338 + maxLength = candidateLength;
339 + }
340 + }
341 +
342 + return start;
343 + }
344 +
345 + public String toString(final boolean zeroCompression, final boolean leadingZeros) {
346 + StringBuilder res = new StringBuilder();
347 +
348 + int compressionStart = zeroCompression ? getZeroCompressStart() : Integer.MAX_VALUE;
349 + boolean inCompression = false;
350 + boolean colonNeeded = false;
351 +
352 + for (int i = 0; i < 8; i++) {
353 + int word = getUnsignedShortWord(i);
354 +
355 + if (word == 0) {
356 + if (inCompression)
357 + continue;
358 + else if (i == compressionStart) {
359 + res.append(':').append(':');
360 + inCompression = true;
361 + colonNeeded = false;
362 + continue;
363 + }
364 + } else {
365 + inCompression = false;
366 + }
367 +
368 + if (colonNeeded) {
369 + res.append(':');
370 + colonNeeded = false;
371 + }
372 +
373 + res.append(leadingZeros ? String.format("%04x", word) : Integer.toString(word,
374 + 16));
375 + colonNeeded = true;
376 + }
377 + return res.toString();
378 + }
379 +
380 + @Override
381 + public int hashCode() {
382 + final int prime = 31;
383 + int result = 1;
384 + result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
385 + result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
386 + return result;
387 + }
388 +
389 + @Override
390 + public boolean equals(final Object obj) {
391 + if (this == obj)
392 + return true;
393 + if (obj == null)
394 + return false;
395 + if (getClass() != obj.getClass())
396 + return false;
397 + IPv6Address other = (IPv6Address) obj;
398 + if (raw1 != other.raw1)
399 + return false;
400 + if (raw2 != other.raw2)
401 + return false;
402 + return true;
403 + }
404 +
405 + public void write16Bytes(ChannelBuffer c) {
406 + c.writeLong(this.raw1);
407 + c.writeLong(this.raw2);
408 + }
409 +
410 + public static IPv6Address read16Bytes(ChannelBuffer c) throws OFParseError {
411 + return IPv6Address.of(c.readLong(), c.readLong());
412 + }
413 +
414 + @Override
415 + public IPv6Address applyMask(IPv6Address mask) {
416 + return and(mask);
417 + }
418 +
419 + @Override
420 + public int compareTo(IPv6Address o) {
421 + int res = Longs.compare(raw1, o.raw1);
422 + if(res != 0)
423 + return res;
424 + else
425 + return Longs.compare(raw2, o.raw2);
426 + }
427 +
428 + @Override
429 + public void putTo(PrimitiveSink sink) {
430 + sink.putLong(raw1);
431 + sink.putLong(raw2);
432 + }
433 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.math.BigInteger;
4 +import java.util.Arrays;
5 +
6 +public class IPv6AddressWithMask extends IPAddressWithMask<IPv6Address> {
7 + public final static IPv6AddressWithMask NONE = of(IPv6Address.NONE, IPv6Address.NONE);
8 +
9 + private IPv6AddressWithMask(IPv6Address value, IPv6Address mask) {
10 + super(value, mask);
11 + }
12 +
13 + @Override
14 + public IPVersion getIpVersion() {
15 + return IPVersion.IPv6;
16 + }
17 +
18 + public static IPv6AddressWithMask of(IPv6Address value, IPv6Address mask) {
19 + if (value == null) {
20 + throw new NullPointerException("Value must not be null");
21 + }
22 + if (mask == null) {
23 + throw new NullPointerException("Mask must not be null");
24 + }
25 + return new IPv6AddressWithMask(value, mask);
26 + }
27 +
28 +
29 + public static IPv6AddressWithMask of(final String string) {
30 + if (string == null) {
31 + throw new NullPointerException("String must not be null");
32 + }
33 + int slashPos;
34 + String ip = string;
35 + int maskBits = 128;
36 + IPv6Address maskAddress = null;
37 +
38 + // Read mask suffix
39 + if ((slashPos = string.indexOf('/')) != -1) {
40 + ip = string.substring(0, slashPos);
41 + try {
42 + String suffix = string.substring(slashPos + 1);
43 + if (suffix.length() == 0)
44 + throw new IllegalArgumentException("IPv6 Address not well formed: " + string);
45 + if (suffix.indexOf(':') != -1) {
46 + // Full mask
47 + maskAddress = IPv6Address.of(suffix);
48 + } else {
49 + // CIDR Suffix
50 + maskBits = Integer.parseInt(suffix);
51 + }
52 + } catch (NumberFormatException e) {
53 + throw new IllegalArgumentException("IPv6 Address not well formed: " + string);
54 + }
55 + if (maskBits < 0 || maskBits > 128) {
56 + throw new IllegalArgumentException("IPv6 Address not well formed: " + string);
57 + }
58 + }
59 +
60 + // Read IP
61 + IPv6Address ipv6 = IPv6Address.of(ip);
62 +
63 + if (maskAddress != null) {
64 + // Full address mask
65 + return IPv6AddressWithMask.of(ipv6, maskAddress);
66 + } else if (maskBits == 128) {
67 + // No mask
68 + return IPv6AddressWithMask.of(ipv6, IPv6Address.NO_MASK);
69 + } else if (maskBits == 0) {
70 + // Entirely masked out
71 + return IPv6AddressWithMask.of(ipv6, IPv6Address.FULL_MASK);
72 + }else {
73 + // With mask
74 + BigInteger mask = BigInteger.ONE.negate().shiftLeft(128 - maskBits);
75 + byte[] maskBytesTemp = mask.toByteArray();
76 + byte[] maskBytes;
77 + if (maskBytesTemp.length < 16) {
78 + maskBytes = new byte[16];
79 + System.arraycopy(maskBytesTemp, 0, maskBytes, 16 - maskBytesTemp.length, maskBytesTemp.length);
80 + Arrays.fill(maskBytes, 0, 16 - maskBytesTemp.length, (byte)(0xFF));
81 + } else if (maskBytesTemp.length > 16) {
82 + maskBytes = new byte[16];
83 + System.arraycopy(maskBytesTemp, 0, maskBytes, 0, maskBytes.length);
84 + } else {
85 + maskBytes = maskBytesTemp;
86 + }
87 + return IPv6AddressWithMask.of(ipv6, IPv6Address.of(maskBytes));
88 + }
89 + }
90 +
91 +
92 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +import com.google.common.primitives.UnsignedInts;
8 +
9 +public class IPv6FlowLabel implements OFValueType<IPv6FlowLabel> {
10 +
11 + static final int LENGTH = 4;
12 +
13 + private final int label;
14 +
15 + private final static int NONE_VAL = 0x0;
16 + public static final IPv6FlowLabel NONE = new IPv6FlowLabel(NONE_VAL);
17 +
18 + public static final IPv6FlowLabel NO_MASK = IPv6FlowLabel.of(0xFFFFFFFF);
19 + public static final IPv6FlowLabel FULL_MASK = IPv6FlowLabel.of(0x0);
20 +
21 + private IPv6FlowLabel(int label) {
22 + this.label = label;
23 + }
24 +
25 + public static IPv6FlowLabel of(int label) {
26 + if(label == NONE_VAL)
27 + return NONE;
28 + return new IPv6FlowLabel(label);
29 + }
30 +
31 + @Override
32 + public int getLength() {
33 + return LENGTH;
34 + }
35 +
36 + @Override
37 + public boolean equals(Object obj) {
38 + if (!(obj instanceof IPv6FlowLabel))
39 + return false;
40 + IPv6FlowLabel other = (IPv6FlowLabel)obj;
41 + if (other.label != this.label)
42 + return false;
43 + return true;
44 + }
45 +
46 + @Override
47 + public int hashCode() {
48 + final int prime = 59;
49 + int result = 1;
50 + result = prime * result + label;
51 + return result;
52 + }
53 +
54 + @Override
55 + public String toString() {
56 + return Integer.toHexString(label);
57 + }
58 +
59 + public void write4Bytes(ChannelBuffer c) {
60 + c.writeInt(this.label);
61 + }
62 +
63 + public static IPv6FlowLabel read4Bytes(ChannelBuffer c) throws OFParseError {
64 + return IPv6FlowLabel.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
65 + }
66 +
67 + @Override
68 + public IPv6FlowLabel applyMask(IPv6FlowLabel mask) {
69 + return IPv6FlowLabel.of(this.label & mask.label);
70 + }
71 +
72 + public int getIPv6FlowLabelValue() {
73 + return label;
74 + }
75 +
76 + @Override
77 + public int compareTo(IPv6FlowLabel o) {
78 + return UnsignedInts.compare(label, o.label);
79 + }
80 +
81 + @Override
82 + public void putTo(PrimitiveSink sink) {
83 + sink.putInt(this.label);
84 + }
85 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +
8 +public enum IpDscp implements OFValueType<IpDscp> {
9 + DSCP_0((byte)0),
10 + DSCP_1((byte)1),
11 + DSCP_2((byte)2),
12 + DSCP_3((byte)3),
13 + DSCP_4((byte)4),
14 + DSCP_5((byte)5),
15 + DSCP_6((byte)6),
16 + DSCP_7((byte)7),
17 + DSCP_8((byte)8),
18 + DSCP_9((byte)9),
19 + DSCP_10((byte)10),
20 + DSCP_11((byte)11),
21 + DSCP_12((byte)12),
22 + DSCP_13((byte)13),
23 + DSCP_14((byte)14),
24 + DSCP_15((byte)15),
25 + DSCP_16((byte)16),
26 + DSCP_17((byte)17),
27 + DSCP_18((byte)18),
28 + DSCP_19((byte)19),
29 + DSCP_20((byte)20),
30 + DSCP_21((byte)21),
31 + DSCP_22((byte)22),
32 + DSCP_23((byte)23),
33 + DSCP_24((byte)24),
34 + DSCP_25((byte)25),
35 + DSCP_26((byte)26),
36 + DSCP_27((byte)27),
37 + DSCP_28((byte)28),
38 + DSCP_29((byte)29),
39 + DSCP_30((byte)30),
40 + DSCP_31((byte)31),
41 + DSCP_32((byte)32),
42 + DSCP_33((byte)33),
43 + DSCP_34((byte)34),
44 + DSCP_35((byte)35),
45 + DSCP_36((byte)36),
46 + DSCP_37((byte)37),
47 + DSCP_38((byte)38),
48 + DSCP_39((byte)39),
49 + DSCP_40((byte)40),
50 + DSCP_41((byte)41),
51 + DSCP_42((byte)42),
52 + DSCP_43((byte)43),
53 + DSCP_44((byte)44),
54 + DSCP_45((byte)45),
55 + DSCP_46((byte)46),
56 + DSCP_47((byte)47),
57 + DSCP_48((byte)48),
58 + DSCP_49((byte)49),
59 + DSCP_50((byte)50),
60 + DSCP_51((byte)51),
61 + DSCP_52((byte)52),
62 + DSCP_53((byte)53),
63 + DSCP_54((byte)54),
64 + DSCP_55((byte)55),
65 + DSCP_56((byte)56),
66 + DSCP_57((byte)57),
67 + DSCP_58((byte)58),
68 + DSCP_59((byte)59),
69 + DSCP_60((byte)60),
70 + DSCP_61((byte)61),
71 + DSCP_62((byte)62),
72 + DSCP_63((byte)63),
73 + DSCP_NO_MASK((byte)0xFF);
74 +
75 + static final int LENGTH = 1;
76 +
77 + public static final IpDscp NONE = DSCP_0;
78 +
79 + public static final IpDscp NO_MASK = DSCP_NO_MASK;
80 + public static final IpDscp FULL_MASK = DSCP_0;
81 +
82 + private final byte dscp;
83 +
84 + private IpDscp(byte dscp) {
85 + this.dscp = dscp;
86 + }
87 +
88 + public static IpDscp of(byte dscp) {
89 + switch (dscp) {
90 + case 0:
91 + return DSCP_0;
92 + case 1:
93 + return DSCP_1;
94 + case 2:
95 + return DSCP_2;
96 + case 3:
97 + return DSCP_3;
98 + case 4:
99 + return DSCP_4;
100 + case 5:
101 + return DSCP_5;
102 + case 6:
103 + return DSCP_6;
104 + case 7:
105 + return DSCP_7;
106 + case 8:
107 + return DSCP_8;
108 + case 9:
109 + return DSCP_9;
110 + case 10:
111 + return DSCP_10;
112 + case 11:
113 + return DSCP_11;
114 + case 12:
115 + return DSCP_12;
116 + case 13:
117 + return DSCP_13;
118 + case 14:
119 + return DSCP_14;
120 + case 15:
121 + return DSCP_15;
122 + case 16:
123 + return DSCP_16;
124 + case 17:
125 + return DSCP_17;
126 + case 18:
127 + return DSCP_18;
128 + case 19:
129 + return DSCP_19;
130 + case 20:
131 + return DSCP_20;
132 + case 21:
133 + return DSCP_21;
134 + case 22:
135 + return DSCP_22;
136 + case 23:
137 + return DSCP_23;
138 + case 24:
139 + return DSCP_24;
140 + case 25:
141 + return DSCP_25;
142 + case 26:
143 + return DSCP_26;
144 + case 27:
145 + return DSCP_27;
146 + case 28:
147 + return DSCP_28;
148 + case 29:
149 + return DSCP_29;
150 + case 30:
151 + return DSCP_30;
152 + case 31:
153 + return DSCP_31;
154 + case 32:
155 + return DSCP_32;
156 + case 33:
157 + return DSCP_33;
158 + case 34:
159 + return DSCP_34;
160 + case 35:
161 + return DSCP_35;
162 + case 36:
163 + return DSCP_36;
164 + case 37:
165 + return DSCP_37;
166 + case 38:
167 + return DSCP_38;
168 + case 39:
169 + return DSCP_39;
170 + case 40:
171 + return DSCP_40;
172 + case 41:
173 + return DSCP_41;
174 + case 42:
175 + return DSCP_42;
176 + case 43:
177 + return DSCP_43;
178 + case 44:
179 + return DSCP_44;
180 + case 45:
181 + return DSCP_45;
182 + case 46:
183 + return DSCP_46;
184 + case 47:
185 + return DSCP_47;
186 + case 48:
187 + return DSCP_48;
188 + case 49:
189 + return DSCP_49;
190 + case 50:
191 + return DSCP_50;
192 + case 51:
193 + return DSCP_51;
194 + case 52:
195 + return DSCP_52;
196 + case 53:
197 + return DSCP_53;
198 + case 54:
199 + return DSCP_54;
200 + case 55:
201 + return DSCP_55;
202 + case 56:
203 + return DSCP_56;
204 + case 57:
205 + return DSCP_57;
206 + case 58:
207 + return DSCP_58;
208 + case 59:
209 + return DSCP_59;
210 + case 60:
211 + return DSCP_60;
212 + case 61:
213 + return DSCP_61;
214 + case 62:
215 + return DSCP_62;
216 + case 63:
217 + return DSCP_63;
218 + default:
219 + throw new IllegalArgumentException("Illegal IPv4 DSCP value: " + dscp);
220 + }
221 + }
222 +
223 + @Override
224 + public int getLength() {
225 + return LENGTH;
226 + }
227 +
228 + @Override
229 + public String toString() {
230 + return Integer.toHexString(dscp);
231 + }
232 +
233 + public void writeByte(ChannelBuffer c) {
234 + c.writeByte(this.dscp);
235 + }
236 +
237 + public static IpDscp readByte(ChannelBuffer c) throws OFParseError {
238 + return IpDscp.of((byte)(c.readUnsignedByte()));
239 + }
240 +
241 + @Override
242 + public IpDscp applyMask(IpDscp mask) {
243 + return IpDscp.of((byte)(this.dscp & mask.dscp));
244 + }
245 +
246 + public byte getDscpValue() {
247 + return dscp;
248 + }
249 +
250 + @Override
251 + public void putTo(PrimitiveSink sink) {
252 + sink.putByte(dscp);
253 + }
254 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +
8 +public enum IpEcn implements OFValueType<IpEcn> {
9 + ECN_00((byte)0),
10 + ECN_01((byte)1),
11 + ECN_10((byte)2),
12 + ECN_11((byte)3),
13 + ECN_NO_MASK((byte)0xFF);
14 +
15 + public static final IpEcn NONE = ECN_00;
16 + public static final IpEcn NO_MASK = ECN_NO_MASK;
17 + public static final IpEcn FULL_MASK = ECN_00;
18 +
19 + static final int LENGTH = 1;
20 +
21 + private final byte ecn;
22 +
23 + private IpEcn(byte ecn) {
24 + this.ecn = ecn;
25 + }
26 +
27 + public static IpEcn of(byte ecn) {
28 + switch (ecn) {
29 + case 0:
30 + return ECN_00;
31 + case 1:
32 + return ECN_01;
33 + case 2:
34 + return ECN_10;
35 + case 3:
36 + return ECN_11;
37 + default:
38 + throw new IllegalArgumentException("Illegal IP ECN value: " + ecn);
39 + }
40 + }
41 +
42 + @Override
43 + public int getLength() {
44 + return LENGTH;
45 + }
46 +
47 + @Override
48 + public String toString() {
49 + return (ecn < 3 ? "0" : "") + Integer.toBinaryString(ecn);
50 + }
51 +
52 + public void writeByte(ChannelBuffer c) {
53 + c.writeByte(this.ecn);
54 + }
55 +
56 + public static IpEcn readByte(ChannelBuffer c) throws OFParseError {
57 + return IpEcn.of((byte)(c.readUnsignedByte()));
58 + }
59 +
60 + @Override
61 + public IpEcn applyMask(IpEcn mask) {
62 + return IpEcn.of((byte)(this.ecn & mask.ecn));
63 + }
64 +
65 + public byte getEcnValue() {
66 + return ecn;
67 + }
68 +
69 + @Override
70 + public void putTo(PrimitiveSink sink) {
71 + sink.putByte(ecn);
72 + }
73 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +import com.google.common.primitives.Shorts;
7 +
8 +/**
9 + * IP-Protocol field representation
10 + *
11 + * @author Yotam Harchol (yotam.harchol@bigswitch.com)
12 + */
13 +public class IpProtocol implements OFValueType<IpProtocol> {
14 +
15 + static final short MAX_PROTO = 0xFF;
16 + static final int LENGTH = 1;
17 +
18 + private final short proto;
19 +
20 + static final short NUM_HOPOPT = 0x00;
21 + static final short NUM_ICMP = 0x01;
22 + static final short NUM_IGMP = 0x02;
23 + static final short NUM_GGP = 0x03;
24 + static final short NUM_IPv4 = 0x04;
25 + static final short NUM_ST = 0x05;
26 + static final short NUM_TCP = 0x06;
27 + static final short NUM_CBT = 0x07;
28 + static final short NUM_EGP = 0x08;
29 + static final short NUM_IGP = 0x09;
30 + static final short NUM_BBN_RCC_MON = 0x0A;
31 + static final short NUM_NVP_II = 0x0B;
32 + static final short NUM_PUP = 0x0C;
33 + static final short NUM_ARGUS = 0x0D;
34 + static final short NUM_EMCON = 0x0E;
35 + static final short NUM_XNET = 0x0F;
36 + static final short NUM_CHAOS = 0x10;
37 + static final short NUM_UDP = 0x11;
38 + static final short NUM_MUX = 0x12;
39 + static final short NUM_DCN_MEAS = 0x13;
40 + static final short NUM_HMP = 0x14;
41 + static final short NUM_PRM = 0x15;
42 + static final short NUM_XNS_IDP = 0x16;
43 + static final short NUM_TRUNK_1 = 0x17;
44 + static final short NUM_TRUNK_2 = 0x18;
45 + static final short NUM_LEAF_1 = 0x19;
46 + static final short NUM_LEAF_2 = 0x1A;
47 + static final short NUM_RDP = 0x1B;
48 + static final short NUM_IRTP = 0x1C;
49 + static final short NUM_ISO_TP4 = 0x1D;
50 + static final short NUM_NETBLT = 0x1E;
51 + static final short NUM_MFE_NSP = 0x1F;
52 + static final short NUM_MERIT_INP = 0x20;
53 + static final short NUM_DCCP = 0x21;
54 + static final short NUM_3PC = 0x22;
55 + static final short NUM_IDPR = 0x23;
56 + static final short NUM_XTP = 0x24;
57 + static final short NUM_DDP = 0x25;
58 + static final short NUM_IDPR_CMTP = 0x26;
59 + static final short NUM_TP_PP = 0x27;
60 + static final short NUM_IL = 0x28;
61 + static final short NUM_IPv6 = 0x29;
62 + static final short NUM_SDRP = 0x2A;
63 + static final short NUM_IPv6_ROUTE = 0x2B;
64 + static final short NUM_IPv6_FRAG = 0x2C;
65 + static final short NUM_IDRP = 0x2D;
66 + static final short NUM_RSVP = 0x2E;
67 + static final short NUM_GRE = 0x2F;
68 + static final short NUM_MHRP = 0x30;
69 + static final short NUM_BNA = 0x31;
70 + static final short NUM_ESP = 0x32;
71 + static final short NUM_AH = 0x33;
72 + static final short NUM_I_NLSP = 0x34;
73 + static final short NUM_SWIPE = 0x35;
74 + static final short NUM_NARP = 0x36;
75 + static final short NUM_MOBILE = 0x37;
76 + static final short NUM_TLSP = 0x38;
77 + static final short NUM_SKIP = 0x39;
78 + static final short NUM_IPv6_ICMP = 0x3A;
79 + static final short NUM_IPv6_NO_NXT = 0x3B;
80 + static final short NUM_IPv6_OPTS = 0x3C;
81 + static final short NUM_HOST_INTERNAL = 0x3D;
82 + static final short NUM_CFTP = 0x3E;
83 + static final short NUM_LOCAL_NET = 0x3F;
84 + static final short NUM_SAT_EXPAK = 0x40;
85 + static final short NUM_KRYPTOLAN = 0x41;
86 + static final short NUM_RVD = 0x42;
87 + static final short NUM_IPPC = 0x43;
88 + static final short NUM_DIST_FS = 0x44;
89 + static final short NUM_SAT_MON = 0x45;
90 + static final short NUM_VISA = 0x46;
91 + static final short NUM_IPCV = 0x47;
92 + static final short NUM_CPNX = 0x48;
93 + static final short NUM_CPHB = 0x49;
94 + static final short NUM_WSN = 0x4A;
95 + static final short NUM_PVP = 0x4B;
96 + static final short NUM_BR_SAT_MON = 0x4C;
97 + static final short NUM_SUN_ND = 0x4D;
98 + static final short NUM_WB_MON = 0x4E;
99 + static final short NUM_WB_EXPAK = 0x4F;
100 + static final short NUM_ISO_IP = 0x50;
101 + static final short NUM_VMTP = 0x51;
102 + static final short NUM_SECURE_VMTP = 0x52;
103 + static final short NUM_VINES = 0x53;
104 + static final short NUM_TTP_IPTM = 0x54;
105 + static final short NUM_NSFNET_IGP = 0x55;
106 + static final short NUM_DGP = 0x56;
107 + static final short NUM_TCF = 0x57;
108 + static final short NUM_EIGRP = 0x58;
109 + static final short NUM_OSPF = 0x59;
110 + static final short NUM_Sprite_RPC = 0x5A;
111 + static final short NUM_LARP = 0x5B;
112 + static final short NUM_MTP = 0x5C;
113 + static final short NUM_AX_25 = 0x5D;
114 + static final short NUM_IPIP = 0x5E;
115 + static final short NUM_MICP = 0x5F;
116 + static final short NUM_SCC_SP = 0x60;
117 + static final short NUM_ETHERIP = 0x61;
118 + static final short NUM_ENCAP = 0x62;
119 + static final short NUM_PRIVATE_ENCRYPT = 0x63;
120 + static final short NUM_GMTP = 0x64;
121 + static final short NUM_IFMP = 0x65;
122 + static final short NUM_PNNI = 0x66;
123 + static final short NUM_PIM = 0x67;
124 + static final short NUM_ARIS = 0x68;
125 + static final short NUM_SCPS = 0x69;
126 + static final short NUM_QNX = 0x6A;
127 + static final short NUM_A_N = 0x6B;
128 + static final short NUM_IP_COMP = 0x6C;
129 + static final short NUM_SNP = 0x6D;
130 + static final short NUM_COMPAQ_PEER = 0x6E;
131 + static final short NUM_IPX_IN_IP = 0x6F;
132 + static final short NUM_VRRP = 0x70;
133 + static final short NUM_PGM = 0x71;
134 + static final short NUM_ZERO_HOP = 0x72;
135 + static final short NUM_L2TP = 0x73;
136 + static final short NUM_DDX = 0x74;
137 + static final short NUM_IATP = 0x75;
138 + static final short NUM_STP = 0x76;
139 + static final short NUM_SRP = 0x77;
140 + static final short NUM_UTI = 0x78;
141 + static final short NUM_SMP = 0x79;
142 + static final short NUM_SM = 0x7A;
143 + static final short NUM_PTP = 0x7B;
144 + static final short NUM_IS_IS_OVER_IPv4 = 0x7C;
145 + static final short NUM_FIRE = 0x7D;
146 + static final short NUM_CRTP = 0x7E;
147 + static final short NUM_CRUDP = 0x7F;
148 + static final short NUM_SSCOPMCE = 0x80;
149 + static final short NUM_IPLT = 0x81;
150 + static final short NUM_SPS = 0x82;
151 + static final short NUM_PIPE = 0x83;
152 + static final short NUM_SCTP = 0x84;
153 + static final short NUM_FC = 0x85;
154 + static final short NUM_RSVP_E2E_IGNORE = 0x86;
155 + static final short NUM_MOBILITY_HEADER = 0x87;
156 + static final short NUM_UDP_LITE = 0x88;
157 + static final short NUM_MPLS_IN_IP = 0x89;
158 + static final short NUM_MANET = 0x8A;
159 + static final short NUM_HIP = 0x8B;
160 + static final short NUM_SHIM6 = 0x8C;
161 +
162 + public static final IpProtocol HOPOPT = new IpProtocol(NUM_HOPOPT);
163 + public static final IpProtocol ICMP = new IpProtocol(NUM_ICMP);
164 + public static final IpProtocol IGMP = new IpProtocol(NUM_IGMP);
165 + public static final IpProtocol GGP = new IpProtocol(NUM_GGP);
166 + public static final IpProtocol IPv4 = new IpProtocol(NUM_IPv4);
167 + public static final IpProtocol ST = new IpProtocol(NUM_ST);
168 + public static final IpProtocol TCP = new IpProtocol(NUM_TCP);
169 + public static final IpProtocol CBT = new IpProtocol(NUM_CBT);
170 + public static final IpProtocol EGP = new IpProtocol(NUM_EGP);
171 + public static final IpProtocol IGP = new IpProtocol(NUM_IGP);
172 + public static final IpProtocol BBN_RCC_MON = new IpProtocol(NUM_BBN_RCC_MON);
173 + public static final IpProtocol NVP_II = new IpProtocol(NUM_NVP_II);
174 + public static final IpProtocol PUP = new IpProtocol(NUM_PUP);
175 + public static final IpProtocol ARGUS = new IpProtocol(NUM_ARGUS);
176 + public static final IpProtocol EMCON = new IpProtocol(NUM_EMCON);
177 + public static final IpProtocol XNET = new IpProtocol(NUM_XNET);
178 + public static final IpProtocol CHAOS = new IpProtocol(NUM_CHAOS);
179 + public static final IpProtocol UDP = new IpProtocol(NUM_UDP);
180 + public static final IpProtocol MUX = new IpProtocol(NUM_MUX);
181 + public static final IpProtocol DCN_MEAS = new IpProtocol(NUM_DCN_MEAS);
182 + public static final IpProtocol HMP = new IpProtocol(NUM_HMP);
183 + public static final IpProtocol PRM = new IpProtocol(NUM_PRM);
184 + public static final IpProtocol XNS_IDP = new IpProtocol(NUM_XNS_IDP);
185 + public static final IpProtocol TRUNK_1 = new IpProtocol(NUM_TRUNK_1);
186 + public static final IpProtocol TRUNK_2 = new IpProtocol(NUM_TRUNK_2);
187 + public static final IpProtocol LEAF_1 = new IpProtocol(NUM_LEAF_1);
188 + public static final IpProtocol LEAF_2 = new IpProtocol(NUM_LEAF_2);
189 + public static final IpProtocol RDP = new IpProtocol(NUM_RDP);
190 + public static final IpProtocol IRTP = new IpProtocol(NUM_IRTP);
191 + public static final IpProtocol ISO_TP4 = new IpProtocol(NUM_ISO_TP4);
192 + public static final IpProtocol NETBLT = new IpProtocol(NUM_NETBLT);
193 + public static final IpProtocol MFE_NSP = new IpProtocol(NUM_MFE_NSP);
194 + public static final IpProtocol MERIT_INP = new IpProtocol(NUM_MERIT_INP);
195 + public static final IpProtocol DCCP = new IpProtocol(NUM_DCCP);
196 + public static final IpProtocol _3PC = new IpProtocol(NUM_3PC);
197 + public static final IpProtocol IDPR = new IpProtocol(NUM_IDPR);
198 + public static final IpProtocol XTP = new IpProtocol(NUM_XTP);
199 + public static final IpProtocol DDP = new IpProtocol(NUM_DDP);
200 + public static final IpProtocol IDPR_CMTP = new IpProtocol(NUM_IDPR_CMTP);
201 + public static final IpProtocol TP_PP = new IpProtocol(NUM_TP_PP);
202 + public static final IpProtocol IL = new IpProtocol(NUM_IL);
203 + public static final IpProtocol IPv6 = new IpProtocol(NUM_IPv6);
204 + public static final IpProtocol SDRP = new IpProtocol(NUM_SDRP);
205 + public static final IpProtocol IPv6_ROUTE = new IpProtocol(NUM_IPv6_ROUTE);
206 + public static final IpProtocol IPv6_FRAG = new IpProtocol(NUM_IPv6_FRAG);
207 + public static final IpProtocol IDRP = new IpProtocol(NUM_IDRP);
208 + public static final IpProtocol RSVP = new IpProtocol(NUM_RSVP);
209 + public static final IpProtocol GRE = new IpProtocol(NUM_GRE);
210 + public static final IpProtocol MHRP = new IpProtocol(NUM_MHRP);
211 + public static final IpProtocol BNA = new IpProtocol(NUM_BNA);
212 + public static final IpProtocol ESP = new IpProtocol(NUM_ESP);
213 + public static final IpProtocol AH = new IpProtocol(NUM_AH);
214 + public static final IpProtocol I_NLSP = new IpProtocol(NUM_I_NLSP);
215 + public static final IpProtocol SWIPE = new IpProtocol(NUM_SWIPE);
216 + public static final IpProtocol NARP = new IpProtocol(NUM_NARP);
217 + public static final IpProtocol MOBILE = new IpProtocol(NUM_MOBILE);
218 + public static final IpProtocol TLSP = new IpProtocol(NUM_TLSP);
219 + public static final IpProtocol SKIP = new IpProtocol(NUM_SKIP);
220 + public static final IpProtocol IPv6_ICMP = new IpProtocol(NUM_IPv6_ICMP);
221 + public static final IpProtocol IPv6_NO_NXT = new IpProtocol(NUM_IPv6_NO_NXT);
222 + public static final IpProtocol IPv6_OPTS = new IpProtocol(NUM_IPv6_OPTS);
223 + public static final IpProtocol HOST_INTERNAL = new IpProtocol(NUM_HOST_INTERNAL);
224 + public static final IpProtocol CFTP = new IpProtocol(NUM_CFTP);
225 + public static final IpProtocol LOCAL_NET = new IpProtocol(NUM_LOCAL_NET);
226 + public static final IpProtocol SAT_EXPAK = new IpProtocol(NUM_SAT_EXPAK);
227 + public static final IpProtocol KRYPTOLAN = new IpProtocol(NUM_KRYPTOLAN);
228 + public static final IpProtocol RVD = new IpProtocol(NUM_RVD);
229 + public static final IpProtocol IPPC = new IpProtocol(NUM_IPPC);
230 + public static final IpProtocol DIST_FS = new IpProtocol(NUM_DIST_FS);
231 + public static final IpProtocol SAT_MON = new IpProtocol(NUM_SAT_MON);
232 + public static final IpProtocol VISA = new IpProtocol(NUM_VISA);
233 + public static final IpProtocol IPCV = new IpProtocol(NUM_IPCV);
234 + public static final IpProtocol CPNX = new IpProtocol(NUM_CPNX);
235 + public static final IpProtocol CPHB = new IpProtocol(NUM_CPHB);
236 + public static final IpProtocol WSN = new IpProtocol(NUM_WSN);
237 + public static final IpProtocol PVP = new IpProtocol(NUM_PVP);
238 + public static final IpProtocol BR_SAT_MON = new IpProtocol(NUM_BR_SAT_MON);
239 + public static final IpProtocol SUN_ND = new IpProtocol(NUM_SUN_ND);
240 + public static final IpProtocol WB_MON = new IpProtocol(NUM_WB_MON);
241 + public static final IpProtocol WB_EXPAK = new IpProtocol(NUM_WB_EXPAK);
242 + public static final IpProtocol ISO_IP = new IpProtocol(NUM_ISO_IP);
243 + public static final IpProtocol VMTP = new IpProtocol(NUM_VMTP);
244 + public static final IpProtocol SECURE_VMTP = new IpProtocol(NUM_SECURE_VMTP);
245 + public static final IpProtocol VINES = new IpProtocol(NUM_VINES);
246 + public static final IpProtocol TTP_IPTM = new IpProtocol(NUM_TTP_IPTM);
247 + public static final IpProtocol NSFNET_IGP = new IpProtocol(NUM_NSFNET_IGP);
248 + public static final IpProtocol DGP = new IpProtocol(NUM_DGP);
249 + public static final IpProtocol TCF = new IpProtocol(NUM_TCF);
250 + public static final IpProtocol EIGRP = new IpProtocol(NUM_EIGRP);
251 + public static final IpProtocol OSPF = new IpProtocol(NUM_OSPF);
252 + public static final IpProtocol Sprite_RPC = new IpProtocol(NUM_Sprite_RPC);
253 + public static final IpProtocol LARP = new IpProtocol(NUM_LARP);
254 + public static final IpProtocol MTP = new IpProtocol(NUM_MTP);
255 + public static final IpProtocol AX_25 = new IpProtocol(NUM_AX_25);
256 + public static final IpProtocol IPIP = new IpProtocol(NUM_IPIP);
257 + public static final IpProtocol MICP = new IpProtocol(NUM_MICP);
258 + public static final IpProtocol SCC_SP = new IpProtocol(NUM_SCC_SP);
259 + public static final IpProtocol ETHERIP = new IpProtocol(NUM_ETHERIP);
260 + public static final IpProtocol ENCAP = new IpProtocol(NUM_ENCAP);
261 + public static final IpProtocol PRIVATE_ENCRYPT = new IpProtocol(NUM_PRIVATE_ENCRYPT);
262 + public static final IpProtocol GMTP = new IpProtocol(NUM_GMTP);
263 + public static final IpProtocol IFMP = new IpProtocol(NUM_IFMP);
264 + public static final IpProtocol PNNI = new IpProtocol(NUM_PNNI);
265 + public static final IpProtocol PIM = new IpProtocol(NUM_PIM);
266 + public static final IpProtocol ARIS = new IpProtocol(NUM_ARIS);
267 + public static final IpProtocol SCPS = new IpProtocol(NUM_SCPS);
268 + public static final IpProtocol QNX = new IpProtocol(NUM_QNX);
269 + public static final IpProtocol A_N = new IpProtocol(NUM_A_N);
270 + public static final IpProtocol IP_COMP = new IpProtocol(NUM_IP_COMP);
271 + public static final IpProtocol SNP = new IpProtocol(NUM_SNP);
272 + public static final IpProtocol COMPAQ_PEER = new IpProtocol(NUM_COMPAQ_PEER);
273 + public static final IpProtocol IPX_IN_IP = new IpProtocol(NUM_IPX_IN_IP);
274 + public static final IpProtocol VRRP = new IpProtocol(NUM_VRRP);
275 + public static final IpProtocol PGM = new IpProtocol(NUM_PGM);
276 + public static final IpProtocol ZERO_HOP = new IpProtocol(NUM_ZERO_HOP);
277 + public static final IpProtocol L2TP = new IpProtocol(NUM_L2TP);
278 + public static final IpProtocol DDX = new IpProtocol(NUM_DDX);
279 + public static final IpProtocol IATP = new IpProtocol(NUM_IATP);
280 + public static final IpProtocol STP = new IpProtocol(NUM_STP);
281 + public static final IpProtocol SRP = new IpProtocol(NUM_SRP);
282 + public static final IpProtocol UTI = new IpProtocol(NUM_UTI);
283 + public static final IpProtocol SMP = new IpProtocol(NUM_SMP);
284 + public static final IpProtocol SM = new IpProtocol(NUM_SM);
285 + public static final IpProtocol PTP = new IpProtocol(NUM_PTP);
286 + public static final IpProtocol IS_IS_OVER_IPv4 = new IpProtocol(NUM_IS_IS_OVER_IPv4);
287 + public static final IpProtocol FIRE = new IpProtocol(NUM_FIRE);
288 + public static final IpProtocol CRTP = new IpProtocol(NUM_CRTP);
289 + public static final IpProtocol CRUDP = new IpProtocol(NUM_CRUDP);
290 + public static final IpProtocol SSCOPMCE = new IpProtocol(NUM_SSCOPMCE);
291 + public static final IpProtocol IPLT = new IpProtocol(NUM_IPLT);
292 + public static final IpProtocol SPS = new IpProtocol(NUM_SPS);
293 + public static final IpProtocol PIPE = new IpProtocol(NUM_PIPE);
294 + public static final IpProtocol SCTP = new IpProtocol(NUM_SCTP);
295 + public static final IpProtocol FC = new IpProtocol(NUM_FC);
296 + public static final IpProtocol RSVP_E2E_IGNORE = new IpProtocol(NUM_RSVP_E2E_IGNORE);
297 + public static final IpProtocol MOBILITY_HEADER = new IpProtocol(NUM_MOBILITY_HEADER);
298 + public static final IpProtocol UDP_LITE = new IpProtocol(NUM_UDP_LITE);
299 + public static final IpProtocol MPLS_IN_IP = new IpProtocol(NUM_MPLS_IN_IP);
300 + public static final IpProtocol MANET = new IpProtocol(NUM_MANET);
301 + public static final IpProtocol HIP = new IpProtocol(NUM_HIP);
302 + public static final IpProtocol SHIM6 = new IpProtocol(NUM_SHIM6);
303 +
304 + public static final IpProtocol NONE = HOPOPT;
305 +
306 + public static final IpProtocol NO_MASK = HOPOPT;
307 + public static final IpProtocol FULL_MASK = new IpProtocol((short)0x0000);
308 +
309 + private IpProtocol(short version) {
310 + this.proto = version;
311 + }
312 +
313 +
314 + @Override
315 + public int getLength() {
316 + return LENGTH;
317 + }
318 +
319 + public static IpProtocol of(short proto) {
320 + switch (proto) {
321 + case NUM_HOPOPT:
322 + return HOPOPT;
323 + case NUM_ICMP:
324 + return ICMP;
325 + case NUM_IGMP:
326 + return IGMP;
327 + case NUM_GGP:
328 + return GGP;
329 + case NUM_IPv4:
330 + return IPv4;
331 + case NUM_ST:
332 + return ST;
333 + case NUM_TCP:
334 + return TCP;
335 + case NUM_CBT:
336 + return CBT;
337 + case NUM_EGP:
338 + return EGP;
339 + case NUM_IGP:
340 + return IGP;
341 + case NUM_BBN_RCC_MON:
342 + return BBN_RCC_MON;
343 + case NUM_NVP_II:
344 + return NVP_II;
345 + case NUM_PUP:
346 + return PUP;
347 + case NUM_ARGUS:
348 + return ARGUS;
349 + case NUM_EMCON:
350 + return EMCON;
351 + case NUM_XNET:
352 + return XNET;
353 + case NUM_CHAOS:
354 + return CHAOS;
355 + case NUM_UDP:
356 + return UDP;
357 + case NUM_MUX:
358 + return MUX;
359 + case NUM_DCN_MEAS:
360 + return DCN_MEAS;
361 + case NUM_HMP:
362 + return HMP;
363 + case NUM_PRM:
364 + return PRM;
365 + case NUM_XNS_IDP:
366 + return XNS_IDP;
367 + case NUM_TRUNK_1:
368 + return TRUNK_1;
369 + case NUM_TRUNK_2:
370 + return TRUNK_2;
371 + case NUM_LEAF_1:
372 + return LEAF_1;
373 + case NUM_LEAF_2:
374 + return LEAF_2;
375 + case NUM_RDP:
376 + return RDP;
377 + case NUM_IRTP:
378 + return IRTP;
379 + case NUM_ISO_TP4:
380 + return ISO_TP4;
381 + case NUM_NETBLT:
382 + return NETBLT;
383 + case NUM_MFE_NSP:
384 + return MFE_NSP;
385 + case NUM_MERIT_INP:
386 + return MERIT_INP;
387 + case NUM_DCCP:
388 + return DCCP;
389 + case NUM_3PC:
390 + return _3PC;
391 + case NUM_IDPR:
392 + return IDPR;
393 + case NUM_XTP:
394 + return XTP;
395 + case NUM_DDP:
396 + return DDP;
397 + case NUM_IDPR_CMTP:
398 + return IDPR_CMTP;
399 + case NUM_TP_PP:
400 + return TP_PP;
401 + case NUM_IL:
402 + return IL;
403 + case NUM_IPv6:
404 + return IPv6;
405 + case NUM_SDRP:
406 + return SDRP;
407 + case NUM_IPv6_ROUTE:
408 + return IPv6_ROUTE;
409 + case NUM_IPv6_FRAG:
410 + return IPv6_FRAG;
411 + case NUM_IDRP:
412 + return IDRP;
413 + case NUM_RSVP:
414 + return RSVP;
415 + case NUM_GRE:
416 + return GRE;
417 + case NUM_MHRP:
418 + return MHRP;
419 + case NUM_BNA:
420 + return BNA;
421 + case NUM_ESP:
422 + return ESP;
423 + case NUM_AH:
424 + return AH;
425 + case NUM_I_NLSP:
426 + return I_NLSP;
427 + case NUM_SWIPE:
428 + return SWIPE;
429 + case NUM_NARP:
430 + return NARP;
431 + case NUM_MOBILE:
432 + return MOBILE;
433 + case NUM_TLSP:
434 + return TLSP;
435 + case NUM_SKIP:
436 + return SKIP;
437 + case NUM_IPv6_ICMP:
438 + return IPv6_ICMP;
439 + case NUM_IPv6_NO_NXT:
440 + return IPv6_NO_NXT;
441 + case NUM_IPv6_OPTS:
442 + return IPv6_OPTS;
443 + case NUM_HOST_INTERNAL:
444 + return HOST_INTERNAL;
445 + case NUM_CFTP:
446 + return CFTP;
447 + case NUM_LOCAL_NET:
448 + return LOCAL_NET;
449 + case NUM_SAT_EXPAK:
450 + return SAT_EXPAK;
451 + case NUM_KRYPTOLAN:
452 + return KRYPTOLAN;
453 + case NUM_RVD:
454 + return RVD;
455 + case NUM_IPPC:
456 + return IPPC;
457 + case NUM_DIST_FS:
458 + return DIST_FS;
459 + case NUM_SAT_MON:
460 + return SAT_MON;
461 + case NUM_VISA:
462 + return VISA;
463 + case NUM_IPCV:
464 + return IPCV;
465 + case NUM_CPNX:
466 + return CPNX;
467 + case NUM_CPHB:
468 + return CPHB;
469 + case NUM_WSN:
470 + return WSN;
471 + case NUM_PVP:
472 + return PVP;
473 + case NUM_BR_SAT_MON:
474 + return BR_SAT_MON;
475 + case NUM_SUN_ND:
476 + return SUN_ND;
477 + case NUM_WB_MON:
478 + return WB_MON;
479 + case NUM_WB_EXPAK:
480 + return WB_EXPAK;
481 + case NUM_ISO_IP:
482 + return ISO_IP;
483 + case NUM_VMTP:
484 + return VMTP;
485 + case NUM_SECURE_VMTP:
486 + return SECURE_VMTP;
487 + case NUM_VINES:
488 + return VINES;
489 + case NUM_TTP_IPTM:
490 + return TTP_IPTM;
491 + case NUM_NSFNET_IGP:
492 + return NSFNET_IGP;
493 + case NUM_DGP:
494 + return DGP;
495 + case NUM_TCF:
496 + return TCF;
497 + case NUM_EIGRP:
498 + return EIGRP;
499 + case NUM_OSPF:
500 + return OSPF;
501 + case NUM_Sprite_RPC:
502 + return Sprite_RPC;
503 + case NUM_LARP:
504 + return LARP;
505 + case NUM_MTP:
506 + return MTP;
507 + case NUM_AX_25:
508 + return AX_25;
509 + case NUM_IPIP:
510 + return IPIP;
511 + case NUM_MICP:
512 + return MICP;
513 + case NUM_SCC_SP:
514 + return SCC_SP;
515 + case NUM_ETHERIP:
516 + return ETHERIP;
517 + case NUM_ENCAP:
518 + return ENCAP;
519 + case NUM_PRIVATE_ENCRYPT:
520 + return PRIVATE_ENCRYPT;
521 + case NUM_GMTP:
522 + return GMTP;
523 + case NUM_IFMP:
524 + return IFMP;
525 + case NUM_PNNI:
526 + return PNNI;
527 + case NUM_PIM:
528 + return PIM;
529 + case NUM_ARIS:
530 + return ARIS;
531 + case NUM_SCPS:
532 + return SCPS;
533 + case NUM_QNX:
534 + return QNX;
535 + case NUM_A_N:
536 + return A_N;
537 + case NUM_IP_COMP:
538 + return IP_COMP;
539 + case NUM_SNP:
540 + return SNP;
541 + case NUM_COMPAQ_PEER:
542 + return COMPAQ_PEER;
543 + case NUM_IPX_IN_IP:
544 + return IPX_IN_IP;
545 + case NUM_VRRP:
546 + return VRRP;
547 + case NUM_PGM:
548 + return PGM;
549 + case NUM_ZERO_HOP:
550 + return ZERO_HOP;
551 + case NUM_L2TP:
552 + return L2TP;
553 + case NUM_DDX:
554 + return DDX;
555 + case NUM_IATP:
556 + return IATP;
557 + case NUM_STP:
558 + return STP;
559 + case NUM_SRP:
560 + return SRP;
561 + case NUM_UTI:
562 + return UTI;
563 + case NUM_SMP:
564 + return SMP;
565 + case NUM_SM:
566 + return SM;
567 + case NUM_PTP:
568 + return PTP;
569 + case NUM_IS_IS_OVER_IPv4:
570 + return IS_IS_OVER_IPv4;
571 + case NUM_FIRE:
572 + return FIRE;
573 + case NUM_CRTP:
574 + return CRTP;
575 + case NUM_CRUDP:
576 + return CRUDP;
577 + case NUM_SSCOPMCE:
578 + return SSCOPMCE;
579 + case NUM_IPLT:
580 + return IPLT;
581 + case NUM_SPS:
582 + return SPS;
583 + case NUM_PIPE:
584 + return PIPE;
585 + case NUM_SCTP:
586 + return SCTP;
587 + case NUM_FC:
588 + return FC;
589 + case NUM_RSVP_E2E_IGNORE:
590 + return RSVP_E2E_IGNORE;
591 + case NUM_MOBILITY_HEADER:
592 + return MOBILITY_HEADER;
593 + case NUM_UDP_LITE:
594 + return UDP_LITE;
595 + case NUM_MPLS_IN_IP:
596 + return MPLS_IN_IP;
597 + case NUM_MANET:
598 + return MANET;
599 + case NUM_HIP:
600 + return HIP;
601 + case NUM_SHIM6:
602 + return SHIM6;
603 + default:
604 + if (proto >= MAX_PROTO) {
605 + throw new IllegalArgumentException("Illegal IP protocol number: "
606 + + proto);
607 + } else {
608 + return new IpProtocol(proto);
609 + }
610 + }
611 + }
612 +
613 + @Override
614 + public String toString() {
615 + return Integer.toHexString(proto);
616 + }
617 +
618 + public void writeByte(ChannelBuffer c) {
619 + c.writeByte(this.proto);
620 + }
621 +
622 + public static IpProtocol readByte(ChannelBuffer c) {
623 + return IpProtocol.of(c.readUnsignedByte());
624 + }
625 +
626 + @Override
627 + public IpProtocol applyMask(IpProtocol mask) {
628 + return IpProtocol.of((short)(this.proto & mask.proto));
629 + }
630 +
631 + public short getIpProtocolNumber() {
632 + return proto;
633 + }
634 +
635 + @Override
636 + public boolean equals(Object obj) {
637 + if (!(obj instanceof IpProtocol))
638 + return false;
639 + IpProtocol o = (IpProtocol)obj;
640 + if (o.proto != this.proto)
641 + return false;
642 + return true;
643 + }
644 +
645 + @Override
646 + public int hashCode() {
647 + final int prime = 37;
648 + int result = 1;
649 + result = prime * result + proto;
650 + return result;
651 + }
652 +
653 +
654 + @Override
655 + public int compareTo(IpProtocol o) {
656 + return Shorts.compare(proto, o.proto);
657 + }
658 +
659 +
660 + @Override
661 + public void putTo(PrimitiveSink sink) {
662 + sink.putShort(proto);
663 + }
664 +
665 +}
...\ No newline at end of file ...\ No newline at end of file
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import javax.annotation.concurrent.Immutable;
4 +
5 +import org.jboss.netty.buffer.ChannelBuffer;
6 +
7 +import com.google.common.hash.PrimitiveSink;
8 +import com.google.common.primitives.UnsignedInts;
9 +
10 +@Immutable
11 +public class LagId implements OFValueType<LagId> {
12 + static final int LENGTH = 4;
13 + private final int rawValue;
14 +
15 + private final static int NONE_VAL = 0;
16 + public final static LagId NONE = new LagId(NONE_VAL);
17 +
18 + private final static int NO_MASK_VAL = 0xFFFFFFFF;
19 + public final static LagId NO_MASK = new LagId(NO_MASK_VAL);
20 + public final static LagId FULL_MASK = NONE;
21 +
22 + private LagId(final int rawValue) {
23 + this.rawValue = rawValue;
24 + }
25 +
26 + public static LagId of(final int raw) {
27 + if(raw == NONE_VAL)
28 + return NONE;
29 + else if (raw == NO_MASK_VAL)
30 + return NO_MASK;
31 + return new LagId(raw);
32 + }
33 +
34 + public int getInt() {
35 + return rawValue;
36 + }
37 +
38 + @Override
39 + public int getLength() {
40 + return LENGTH;
41 + }
42 +
43 + @Override
44 + public int hashCode() {
45 + final int prime = 31;
46 + int result = 1;
47 + result = prime * result + rawValue;
48 + return result;
49 + }
50 +
51 + @Override
52 + public String toString() {
53 + return Integer.toString(rawValue);
54 + }
55 +
56 + @Override
57 + public boolean equals(final Object obj) {
58 + if (this == obj)
59 + return true;
60 + if (obj == null)
61 + return false;
62 + if (getClass() != obj.getClass())
63 + return false;
64 + LagId other = (LagId) obj;
65 + if (rawValue != other.rawValue)
66 + return false;
67 + return true;
68 + }
69 +
70 + public void write4Bytes(ChannelBuffer c) {
71 + c.writeInt(rawValue);
72 + }
73 +
74 + public static LagId read4Bytes(ChannelBuffer c) {
75 + return LagId.of(c.readInt());
76 + }
77 +
78 + @Override
79 + public int compareTo(LagId o) {
80 + return UnsignedInts.compare(rawValue, o.rawValue);
81 + }
82 +
83 + @Override
84 + public LagId applyMask(LagId mask) {
85 + return LagId.of(rawValue & mask.rawValue);
86 + }
87 +
88 + @Override
89 + public void putTo(PrimitiveSink sink) {
90 + sink.putInt(rawValue);
91 + }
92 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.util.Arrays;
4 +
5 +import javax.annotation.Nonnull;
6 +
7 +import org.jboss.netty.buffer.ChannelBuffer;
8 +import org.projectfloodlight.openflow.exceptions.OFParseError;
9 +import org.projectfloodlight.openflow.util.HexString;
10 +
11 +import com.google.common.hash.PrimitiveSink;
12 +import com.google.common.primitives.Longs;
13 +
14 +/**
15 + * Wrapper around a 6 byte mac address.
16 + *
17 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
18 + */
19 +
20 +public class MacAddress implements OFValueType<MacAddress> {
21 + static final int MacAddrLen = 6;
22 + private final long rawValue;
23 +
24 + private final static long NONE_VAL = 0x0L;
25 + public static final MacAddress NONE = new MacAddress(NONE_VAL);
26 +
27 + private final static long BROADCAST_VAL = 0x0000FFFFFFFFFFFFL;
28 + public static final MacAddress BROADCAST = new MacAddress(BROADCAST_VAL);
29 +
30 + public static final MacAddress NO_MASK = MacAddress.of(0xFFFFFFFFFFFFFFFFl);
31 + public static final MacAddress FULL_MASK = MacAddress.of(0x0);
32 +
33 + private static final long LLDP_MAC_ADDRESS_MASK = 0xfffffffffff0L;
34 + private static final long LLDP_MAC_ADDRESS_VALUE = 0x0180c2000000L;
35 +
36 + private MacAddress(final long rawValue) {
37 + this.rawValue = rawValue;
38 + }
39 +
40 + public static MacAddress of(final byte[] address) {
41 + if (address.length != MacAddrLen)
42 + throw new IllegalArgumentException(
43 + "Mac address byte array must be exactly 6 bytes long; length = " + address.length);
44 + long raw =
45 + (address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32
46 + | (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16
47 + | (address[4] & 0xFFL) << 8 | (address[5] & 0xFFL);
48 + return MacAddress.of(raw);
49 + }
50 +
51 + public static MacAddress of(long raw) {
52 + raw &= BROADCAST_VAL;
53 + if(raw == NONE_VAL)
54 + return NONE;
55 + if (raw == BROADCAST_VAL)
56 + return BROADCAST;
57 + return new MacAddress(raw);
58 + }
59 +
60 + /** Parse a mac adress from the canonical string representation as
61 + * 6 hex bytes separated by colons (01:02:03:04:05:06).
62 + *
63 + * @param macString - a mac address in canonical string representation
64 + * @return the parsed MacAddress
65 + * @throws IllegalArgumentException if macString is not a valid mac adddress
66 + */
67 + @Nonnull
68 + public static MacAddress of(@Nonnull final String macString) throws IllegalArgumentException {
69 + if (macString == null) {
70 + throw new NullPointerException("macString must not be null");
71 + }
72 + int index = 0;
73 + int shift = 40;
74 + final String FORMAT_ERROR = "Mac address is not well-formed. " +
75 + "It must consist of 6 hex digit pairs separated by colons: ";
76 +
77 + long raw = 0;
78 + if (macString.length() != 6 * 2 + 5)
79 + throw new IllegalArgumentException(FORMAT_ERROR + macString);
80 +
81 + while (shift >= 0) {
82 + int digit1 = Character.digit(macString.charAt(index++), 16);
83 + int digit2 = Character.digit(macString.charAt(index++), 16);
84 + if ((digit1 < 0) || (digit2 < 0))
85 + throw new IllegalArgumentException(FORMAT_ERROR + macString);
86 + raw |= ((long) (digit1 << 4 | digit2)) << shift;
87 +
88 + if (shift == 0)
89 + break;
90 + if (macString.charAt(index++) != ':')
91 + throw new IllegalArgumentException(FORMAT_ERROR + macString);
92 + shift -= 8;
93 + }
94 + return MacAddress.of(raw);
95 + }
96 +
97 + private volatile byte[] bytesCache = null;
98 +
99 + public byte[] getBytes() {
100 + if (bytesCache == null) {
101 + synchronized (this) {
102 + if (bytesCache == null) {
103 + bytesCache =
104 + new byte[] { (byte) ((rawValue >> 40) & 0xFF),
105 + (byte) ((rawValue >> 32) & 0xFF),
106 + (byte) ((rawValue >> 24) & 0xFF),
107 + (byte) ((rawValue >> 16) & 0xFF),
108 + (byte) ((rawValue >> 8) & 0xFF),
109 + (byte) ((rawValue >> 0) & 0xFF) };
110 + }
111 + }
112 + }
113 + return Arrays.copyOf(bytesCache, bytesCache.length);
114 + }
115 +
116 + /**
117 + * Returns {@code true} if the MAC address is the broadcast address.
118 + * @return {@code true} if the MAC address is the broadcast address.
119 + */
120 + public boolean isBroadcast() {
121 + return this == BROADCAST;
122 + }
123 +
124 + /**
125 + * Returns {@code true} if the MAC address is a multicast address.
126 + * @return {@code true} if the MAC address is a multicast address.
127 + */
128 + public boolean isMulticast() {
129 + if (isBroadcast()) {
130 + return false;
131 + }
132 + return (rawValue & (0x01L << 40)) != 0;
133 + }
134 +
135 + /**
136 + * Returns {@code true} if the MAC address is an LLDP mac address.
137 + * @return {@code true} if the MAC address is an LLDP mac address.
138 + */
139 + public boolean isLLDPAddress() {
140 + return (rawValue & LLDP_MAC_ADDRESS_MASK) == LLDP_MAC_ADDRESS_VALUE;
141 + }
142 +
143 + @Override
144 + public int getLength() {
145 + return MacAddrLen;
146 + }
147 +
148 + @Override
149 + public String toString() {
150 + return HexString.toHexString(rawValue, 6);
151 + }
152 +
153 + @Override
154 + public int hashCode() {
155 + final int prime = 31;
156 + int result = 1;
157 + result = prime * result + (int) (rawValue ^ (rawValue >>> 32));
158 + return result;
159 + }
160 +
161 + @Override
162 + public boolean equals(final Object obj) {
163 + if (this == obj)
164 + return true;
165 + if (obj == null)
166 + return false;
167 + if (getClass() != obj.getClass())
168 + return false;
169 + MacAddress other = (MacAddress) obj;
170 + if (rawValue != other.rawValue)
171 + return false;
172 + return true;
173 + }
174 +
175 + public long getLong() {
176 + return rawValue;
177 + }
178 +
179 + public void write6Bytes(ChannelBuffer c) {
180 + c.writeInt((int) (this.rawValue >> 16));
181 + c.writeShort((int) this.rawValue & 0xFFFF);
182 + }
183 +
184 + public static MacAddress read6Bytes(ChannelBuffer c) throws OFParseError {
185 + long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort();
186 + return MacAddress.of(raw);
187 + }
188 +
189 + @Override
190 + public MacAddress applyMask(MacAddress mask) {
191 + return MacAddress.of(this.rawValue & mask.rawValue);
192 + }
193 +
194 + @Override
195 + public int compareTo(MacAddress o) {
196 + return Longs.compare(rawValue, o.rawValue);
197 + }
198 +
199 + @Override
200 + public void putTo(PrimitiveSink sink) {
201 + sink.putInt((int) (this.rawValue >> 16));
202 + sink.putShort((short) (this.rawValue & 0xFFFF));
203 + }
204 +
205 +
206 +
207 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import com.google.common.hash.PrimitiveSink;
4 +
5 +
6 +
7 +public class Masked<T extends OFValueType<T>> implements OFValueType<Masked<T>> {
8 + protected final T value;
9 +
10 + /** bitmask of the value. Note: a set (1) bit in this mask means 'match on this value'.
11 + * This the natural mask represenation as in IPv[46] netmasks. It is the inverse of the
12 + * OpenFlow 1.0 'wildcard' meaning.
13 + */
14 + protected final T mask;
15 +
16 + protected Masked(T value, T mask) {
17 + this.value = value.applyMask(mask);
18 + this.mask = mask;
19 + }
20 +
21 + public T getValue() {
22 + return value;
23 + }
24 +
25 + public T getMask() {
26 + return mask;
27 + }
28 +
29 + public static <T extends OFValueType<T>> Masked<T> of(T value, T mask) {
30 + return new Masked<T>(value, mask);
31 + }
32 +
33 + @Override
34 + public int getLength() {
35 + return this.value.getLength() + this.mask.getLength();
36 + }
37 +
38 + @Override
39 + public String toString() {
40 + // General representation: value/mask
41 + StringBuilder sb = new StringBuilder();
42 + sb.append(value.toString()).append('/').append(mask.toString());
43 + return sb.toString();
44 + }
45 +
46 + /** Determine whether candidate value is matched by this masked value
47 + * (i.e., does candiate lie in the 'network/range' specified by this masked
48 + * value).
49 + *
50 + * @param candidate the candidate value to test
51 + * @return true iff the candidate lies in the area specified by this masked
52 + * value.
53 + */
54 + public boolean matches(T candidate) {
55 + // candidate lies in the area of this masked value if its
56 + // value with the masked bit zero'ed out equals this's value
57 + // (e.g., our 'network address' for networks)
58 + return candidate.applyMask(this.mask).equals(this.value);
59 + }
60 +
61 + @Override
62 + public Masked<T> applyMask(Masked<T> mask) {
63 + return this;
64 + }
65 +
66 + @Override
67 + public boolean equals(Object obj) {
68 + if (!(obj instanceof Masked<?>))
69 + return false;
70 + Masked<?> mobj = (Masked<?>)obj;
71 + return this.value.equals(mobj.value) && this.mask.equals(mobj.mask);
72 + }
73 +
74 + @Override
75 + public int hashCode() {
76 + final int prime = 59;
77 + int result = 1;
78 + result = prime * result + this.value.hashCode();
79 + result = prime * result + this.mask.hashCode();
80 + return result;
81 + }
82 +
83 + @Override
84 + public int compareTo(Masked<T> o) {
85 + int res = value.compareTo(o.value);
86 + if(res != 0)
87 + return res;
88 + else
89 + return mask.compareTo(o.mask);
90 + }
91 +
92 + @Override
93 + public void putTo(PrimitiveSink sink) {
94 + value.putTo(sink);
95 + mask.putTo(sink);
96 + }
97 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +import com.google.common.primitives.Shorts;
8 +
9 +public class OFAuxId implements Comparable<OFAuxId>, PrimitiveSinkable {
10 +
11 + private static final short VALIDATION_MASK = 0xFF;
12 +
13 + private static final short MAIN_VAL = 0x0000;
14 +
15 + public static final OFAuxId MAIN = new OFAuxId(MAIN_VAL);
16 +
17 + private final short id;
18 +
19 + private OFAuxId(short id) {
20 + this.id = id;
21 + }
22 +
23 + public static OFAuxId of(short id) {
24 + switch(id) {
25 + case MAIN_VAL:
26 + return MAIN;
27 + default:
28 + if ((id & VALIDATION_MASK) != id)
29 + throw new IllegalArgumentException("Illegal Aux id value: " + id);
30 + return new OFAuxId(id);
31 + }
32 + }
33 +
34 + public static OFAuxId of(int id) {
35 + if((id & VALIDATION_MASK) != id)
36 + throw new IllegalArgumentException("Illegal Aux id value: "+id);
37 + return of((short) id);
38 + }
39 +
40 + @Override
41 + public String toString() {
42 + return "0x" + Integer.toHexString(id);
43 + }
44 +
45 + @Override
46 + public int hashCode() {
47 + final int prime = 31;
48 + int result = 1;
49 + result = prime * result + id;
50 + return result;
51 + }
52 +
53 + @Override
54 + public boolean equals(Object obj) {
55 + if (this == obj) return true;
56 + if (obj == null) return false;
57 + if (getClass() != obj.getClass()) return false;
58 + OFAuxId other = (OFAuxId) obj;
59 + if (id != other.id) return false;
60 + return true;
61 + }
62 +
63 + public short getValue() {
64 + return id;
65 + }
66 +
67 + public void writeByte(ChannelBuffer c) {
68 + c.writeByte(this.id);
69 + }
70 +
71 + public static OFAuxId readByte(ChannelBuffer c) throws OFParseError {
72 + return OFAuxId.of(c.readUnsignedByte());
73 + }
74 +
75 +
76 + @Override
77 + public int compareTo(OFAuxId other) {
78 + return Shorts.compare(this.id, other.id);
79 + }
80 +
81 + @Override
82 + public void putTo(PrimitiveSink sink) {
83 + sink.putByte((byte) id);
84 + }
85 +
86 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +
7 +public class OFBitMask128 implements OFValueType<OFBitMask128> {
8 +
9 + static final int LENGTH = 16;
10 +
11 + private final long raw1; // MSBs (ports 64-127)
12 + private final long raw2; // LSBs (ports 0-63)
13 +
14 + public static final OFBitMask128 ALL = new OFBitMask128(-1, -1);
15 + public static final OFBitMask128 NONE = new OFBitMask128(0, 0);
16 +
17 + public static final OFBitMask128 NO_MASK = ALL;
18 + public static final OFBitMask128 FULL_MASK = NONE;
19 +
20 + private OFBitMask128(long raw1, long raw2) {
21 + this.raw1 = raw1;
22 + this.raw2 = raw2;
23 + }
24 +
25 + public static OFBitMask128 of(long raw1, long raw2) {
26 + if (raw1 == -1 && raw2 == -1)
27 + return ALL;
28 + if (raw1 == 0 && raw2 == 0)
29 + return NONE;
30 + return new OFBitMask128(raw1, raw2);
31 + }
32 +
33 + @Override
34 + public int getLength() {
35 + return LENGTH;
36 + }
37 +
38 + @Override
39 + public OFBitMask128 applyMask(OFBitMask128 mask) {
40 + return of(this.raw1 & mask.raw1, this.raw2 & mask.raw2);
41 + }
42 +
43 + @Override
44 + public boolean equals(Object obj) {
45 + if (!(obj instanceof OFBitMask128))
46 + return false;
47 + OFBitMask128 other = (OFBitMask128)obj;
48 + return (other.raw1 == this.raw1 && other.raw2 == this.raw2);
49 + }
50 +
51 + @Override
52 + public int hashCode() {
53 + return (int)(31 * raw1 + raw2);
54 + }
55 +
56 + protected static boolean isBitOn(long raw1, long raw2, int bit) {
57 + if (bit < 0 || bit >= 128)
58 + throw new IndexOutOfBoundsException();
59 + long word;
60 + if (bit < 64) {
61 + word = raw2; // ports 0-63
62 + } else {
63 + word = raw1; // ports 64-127
64 + bit -= 64;
65 + }
66 + return (word & ((long)1 << bit)) != 0;
67 + }
68 +
69 + public void write16Bytes(ChannelBuffer cb) {
70 + cb.writeLong(raw1);
71 + cb.writeLong(raw2);
72 + }
73 +
74 + public static OFBitMask128 read16Bytes(ChannelBuffer cb) {
75 + long raw1 = cb.readLong();
76 + long raw2 = cb.readLong();
77 + return of(raw1, raw2);
78 + }
79 +
80 + public boolean isOn(int bit) {
81 + return isBitOn(raw1, raw2, bit);
82 + }
83 +
84 + @Override
85 + public String toString() {
86 + return (String.format("%64s", Long.toBinaryString(raw2)) + String.format("%64s", Long.toBinaryString(raw1))).replaceAll(" ", "0");
87 + }
88 +
89 + @Override
90 + public int compareTo(OFBitMask128 o) {
91 + long c = this.raw1 - o.raw1;
92 + if (c != 0)
93 + return Long.signum(c);
94 + return Long.signum(this.raw2 - o.raw2);
95 + }
96 +
97 + @Override
98 + public void putTo(PrimitiveSink sink) {
99 + sink.putLong(raw1);
100 + sink.putLong(raw2);
101 + }
102 +
103 +}
1 +/**
2 + * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 + * University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package org.projectfloodlight.openflow.types;
19 +
20 +import org.jboss.netty.buffer.ChannelBuffer;
21 +import org.projectfloodlight.openflow.exceptions.OFParseError;
22 +import org.projectfloodlight.openflow.protocol.OFMessageReader;
23 +import org.projectfloodlight.openflow.protocol.Writeable;
24 +
25 +import com.google.common.hash.PrimitiveSink;
26 +
27 +public class OFBooleanValue implements Writeable, OFValueType<OFBooleanValue> {
28 + public final static OFBooleanValue TRUE = new OFBooleanValue(true);
29 + public final static OFBooleanValue FALSE = new OFBooleanValue(false);
30 +
31 + public final static OFBooleanValue NO_MASK = TRUE;
32 + public final static OFBooleanValue FULL_MASK = FALSE;
33 +
34 + private final boolean value;
35 +
36 + private OFBooleanValue(boolean value) {
37 + this.value = value;
38 + }
39 +
40 + public static OFBooleanValue of(boolean value) {
41 + return value ? TRUE : FALSE;
42 + }
43 +
44 + public boolean getValue() {
45 + return value;
46 + }
47 +
48 + public int getInt() {
49 + return value ? 1 : 0;
50 + }
51 +
52 + @Override
53 + public String toString() {
54 + return "" + value;
55 + }
56 +
57 + @Override
58 + public int hashCode() {
59 + final int prime = 31;
60 + int result = 1;
61 + result = prime * result + getInt();
62 + return result;
63 + }
64 +
65 + @Override
66 + public boolean equals(Object obj) {
67 + if (this == obj)
68 + return true;
69 + if (obj == null)
70 + return false;
71 + if (getClass() != obj.getClass())
72 + return false;
73 + OFBooleanValue other = (OFBooleanValue) obj;
74 + if (value != other.value)
75 + return false;
76 + return true;
77 + }
78 +
79 + @Override
80 + public void writeTo(ChannelBuffer bb) {
81 + bb.writeByte(getInt());
82 + }
83 +
84 + private static class Reader implements OFMessageReader<OFBooleanValue> {
85 + @Override
86 + public OFBooleanValue readFrom(ChannelBuffer bb) throws OFParseError {
87 + return of(bb.readByte() != 0);
88 + }
89 + }
90 +
91 + @Override
92 + public int getLength() {
93 + return 1;
94 + }
95 +
96 + @Override
97 + public OFBooleanValue applyMask(OFBooleanValue mask) {
98 + return of(value && mask.value);
99 + }
100 +
101 + @Override
102 + public int compareTo(OFBooleanValue o) {
103 + return getInt() - o.getInt();
104 + }
105 +
106 + @Override
107 + public void putTo(PrimitiveSink sink) {
108 + sink.putByte((byte)getInt());
109 + }
110 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.projectfloodlight.openflow.annotations.Immutable;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +import com.google.common.primitives.UnsignedInts;
7 +
8 +/**
9 + * Abstraction of a buffer id in OpenFlow. Immutable.
10 + *
11 + * @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com>
12 + */
13 +@Immutable
14 +public class OFBufferId implements Comparable<OFBufferId>, PrimitiveSinkable {
15 + public static final OFBufferId NO_BUFFER = new OFBufferId(0xFFFFFFFF);
16 +
17 + private final int rawValue;
18 +
19 + private OFBufferId(int rawValue) {
20 + this.rawValue = rawValue;
21 + }
22 +
23 + public static OFBufferId of(final int rawValue) {
24 + if (rawValue == NO_BUFFER.getInt())
25 + return NO_BUFFER;
26 + return new OFBufferId(rawValue);
27 + }
28 +
29 + public int getInt() {
30 + return rawValue;
31 + }
32 +
33 + @Override
34 + public String toString() {
35 + return Long.toString(U32.f(rawValue));
36 + }
37 +
38 + @Override
39 + public int hashCode() {
40 + final int prime = 31;
41 + int result = 1;
42 + result = prime * result + rawValue;
43 + return result;
44 + }
45 +
46 + @Override
47 + public boolean equals(Object obj) {
48 + if (this == obj)
49 + return true;
50 + if (obj == null)
51 + return false;
52 + if (getClass() != obj.getClass())
53 + return false;
54 + OFBufferId other = (OFBufferId) obj;
55 + if (rawValue != other.rawValue)
56 + return false;
57 + return true;
58 + }
59 +
60 + @Override
61 + public int compareTo(OFBufferId o) {
62 + return UnsignedInts.compare(rawValue, o.rawValue);
63 + }
64 +
65 + @Override
66 + public void putTo(PrimitiveSink sink) {
67 + sink.putInt(rawValue);
68 + }
69 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.util.Arrays;
4 +
5 +import org.jboss.netty.buffer.ChannelBuffer;
6 +import org.jboss.netty.buffer.ChannelBuffers;
7 +import org.projectfloodlight.openflow.exceptions.OFParseError;
8 +import org.projectfloodlight.openflow.protocol.OFErrorMsg;
9 +import org.projectfloodlight.openflow.protocol.OFFactories;
10 +import org.projectfloodlight.openflow.protocol.OFFactory;
11 +import org.projectfloodlight.openflow.protocol.OFMessage;
12 +import org.projectfloodlight.openflow.protocol.OFVersion;
13 +import org.projectfloodlight.openflow.protocol.Writeable;
14 +import org.projectfloodlight.openflow.util.ChannelUtils;
15 +import org.slf4j.Logger;
16 +import org.slf4j.LoggerFactory;
17 +
18 +import com.google.common.base.Optional;
19 +import com.google.common.hash.PrimitiveSink;
20 +
21 +/** A special-purpose wrapper for the 'data' field in an {@link OFErrorMsg} message
22 + * that contains a byte serialization of the offending message.
23 + *
24 + * This attempts to parse the offending message on demand, and if successful
25 + * will present the parsed message.
26 + *
27 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
28 + */
29 +public class OFErrorCauseData implements Writeable, PrimitiveSinkable {
30 + private static final Logger logger =
31 + LoggerFactory.getLogger(OFErrorCauseData.class);
32 +
33 + /** A default 'empty' cause. Note: the OFVersion OF_13 passed in here is irrelevant,
34 + * because parsing of the 0-byte array will always return null, irrespective of the
35 + * version.
36 + */
37 + public static final OFErrorCauseData NONE = new OFErrorCauseData(new byte[0], OFVersion.OF_13);
38 +
39 + private final byte[] data;
40 + private final OFVersion version;
41 +
42 + private OFErrorCauseData(byte[] data, OFVersion version) {
43 + this.data = data;
44 + this.version = version;
45 + }
46 +
47 + public static OFErrorCauseData of(byte[] data, OFVersion version) {
48 + return new OFErrorCauseData(Arrays.copyOf(data, data.length), version);
49 + }
50 +
51 + public byte[] getData() {
52 + return Arrays.copyOf(data, data.length);
53 + }
54 +
55 + public Optional<OFMessage> getParsedMessage() {
56 + OFFactory factory = OFFactories.getFactory(version);
57 + try {
58 + OFMessage msg = factory.getReader().readFrom(ChannelBuffers.wrappedBuffer(data));
59 + if(msg != null)
60 + return Optional.of(msg);
61 + else
62 + return Optional.absent();
63 + } catch (OFParseError e) {
64 + logger.debug("Error parsing error cause data as OFMessage: {}", e.getMessage(), e);
65 + return Optional.absent();
66 + }
67 + }
68 +
69 + public static OFErrorCauseData read(ChannelBuffer bb, int length, OFVersion version) {
70 + byte[] bytes = ChannelUtils.readBytes(bb, length);
71 + return of(bytes, version);
72 + }
73 +
74 + @Override
75 + public void putTo(PrimitiveSink sink) {
76 + sink.putBytes(data);
77 + }
78 +
79 + @Override
80 + public void writeTo(ChannelBuffer bb) {
81 + bb.writeBytes(data);
82 + }
83 +
84 + @Override
85 + public String toString() {
86 + Optional<OFMessage> parsedMessage = getParsedMessage();
87 + if(parsedMessage.isPresent()) {
88 + return String.valueOf(parsedMessage.get());
89 + } else {
90 + StringBuilder b = new StringBuilder();
91 + b.append("[unparsed: ");
92 + for(int i=0; i<data.length; i++) {
93 + if(i>0)
94 + b.append(" ");
95 + b.append(String.format("%02x", data[i]));
96 + }
97 + b.append("]");
98 + return b.toString();
99 + }
100 + }
101 +
102 + @Override
103 + public int hashCode() {
104 + final int prime = 31;
105 + int result = 1;
106 + result = prime * result + Arrays.hashCode(data);
107 + result = prime * result + ((version == null) ? 0 : version.hashCode());
108 + return result;
109 + }
110 +
111 + @Override
112 + public boolean equals(Object obj) {
113 + if (this == obj)
114 + return true;
115 + if (obj == null)
116 + return false;
117 + if (getClass() != obj.getClass())
118 + return false;
119 + OFErrorCauseData other = (OFErrorCauseData) obj;
120 + if (!Arrays.equals(data, other.data))
121 + return false;
122 + if (version != other.version)
123 + return false;
124 + return true;
125 + }
126 +
127 +}
...\ No newline at end of file ...\ No newline at end of file
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.annotations.Immutable;
5 +import org.projectfloodlight.openflow.exceptions.OFParseError;
6 +
7 +import com.google.common.hash.PrimitiveSink;
8 +import com.google.common.primitives.UnsignedInts;
9 +
10 +/**
11 + * Abstraction of an logical / OpenFlow group (ofp_group) in OpenFlow.
12 + * Immutable.
13 + *
14 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
15 + */
16 +@Immutable
17 +public class OFGroup implements OFValueType<OFGroup> {
18 + static final int LENGTH = 4;
19 +
20 + // private int constants (OF1.1+) to avoid duplication in the code
21 + // should not have to use these outside this class
22 + private static final int ZERO_VAL = 0x00;
23 + private static final int MAX_VAL = 0xffffff00;
24 + private static final int ALL_VAL = 0xfffffffc;
25 + private static final int ANY_VAL = 0xffffffff;
26 +
27 +
28 + // ////////////// public constants - use to access well known OpenFlow group constants
29 +
30 + /** Maximum number of physical and logical switch groups. */
31 + public final static OFGroup MAX = new NamedGroup(MAX_VAL, "max");
32 +
33 + /** All groups */
34 + public final static OFGroup ALL = new NamedGroup(ALL_VAL, "all");
35 +
36 + /**
37 + * Wildcard group used only for flow mod (delete) and flow stats requests. */
38 + public final static OFGroup ANY = new NamedGroup(ANY_VAL, "any");
39 +
40 + /** group 0 in case we need it */
41 + public static final OFGroup ZERO = OFGroup.of(ZERO_VAL);
42 +
43 + public static final OFGroup NO_MASK = ANY;
44 + public static final OFGroup FULL_MASK = ZERO;
45 +
46 + /** raw openflow group number as a signed 32 bit integer */
47 + private final int groupNumber;
48 +
49 + /** private constructor. use of*-Factory methods instead */
50 + private OFGroup(final int portNumber) {
51 + this.groupNumber = portNumber;
52 + }
53 +
54 + /**
55 + * get an OFGroup object corresponding to a raw 32-bit integer group number.
56 + * NOTE: The group object may either be newly allocated or cached. Do not
57 + * rely on either behavior.
58 + *
59 + * @param groupNumber the raw 32-bit group number
60 + * @return a corresponding OFPort
61 + */
62 + public static OFGroup of(final int groupNumber) {
63 + switch(groupNumber) {
64 + case ZERO_VAL:
65 + return MAX;
66 + case MAX_VAL:
67 + return MAX;
68 + case ALL_VAL:
69 + return ALL;
70 + case ANY_VAL:
71 + return ANY;
72 + default:
73 + if(UnsignedInts.compare(groupNumber, MAX_VAL) > 0) {
74 + // greater than max_val, but not one of the reserved values
75 + throw new IllegalArgumentException("Unknown special group number: "
76 + + groupNumber);
77 + }
78 + return new OFGroup(groupNumber);
79 + }
80 + }
81 +
82 + /** return the group number as a int32 */
83 + public int getGroupNumber() {
84 + return groupNumber;
85 + }
86 +
87 + @Override
88 + public String toString() {
89 + return UnsignedInts.toString(groupNumber);
90 + }
91 +
92 + /** Extension of OFGroup for named groups */
93 + static class NamedGroup extends OFGroup {
94 + private final String name;
95 +
96 + NamedGroup(final int portNo, final String name) {
97 + super(portNo);
98 + this.name = name;
99 + }
100 +
101 + public String getName() {
102 + return name;
103 + }
104 +
105 + @Override
106 + public String toString() {
107 + return name;
108 + }
109 + }
110 +
111 + @Override
112 + public int getLength() {
113 + return LENGTH;
114 + }
115 +
116 + @Override
117 + public boolean equals(Object obj) {
118 + if (!(obj instanceof OFGroup))
119 + return false;
120 + OFGroup other = (OFGroup)obj;
121 + if (other.groupNumber != this.groupNumber)
122 + return false;
123 + return true;
124 + }
125 +
126 + @Override
127 + public int hashCode() {
128 + final int prime = 53;
129 + int result = 1;
130 + result = prime * result + groupNumber;
131 + return result;
132 + }
133 +
134 + public void write4Bytes(ChannelBuffer c) {
135 + c.writeInt(this.groupNumber);
136 + }
137 +
138 + public static OFGroup read4Bytes(ChannelBuffer c) throws OFParseError {
139 + return OFGroup.of(c.readInt());
140 + }
141 +
142 + @Override
143 + public OFGroup applyMask(OFGroup mask) {
144 + return OFGroup.of(this.groupNumber & mask.groupNumber);
145 + }
146 +
147 + @Override
148 + public int compareTo(OFGroup o) {
149 + return UnsignedInts.compare(this.groupNumber, o.groupNumber);
150 + }
151 +
152 + @Override
153 + public void putTo(PrimitiveSink sink) {
154 + sink.putInt(groupNumber);
155 + }
156 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +public interface OFHelloElement {
4 +
5 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +
5 +import com.google.common.hash.PrimitiveSink;
6 +
7 +public class OFMetadata implements OFValueType<OFMetadata> {
8 +
9 + static int LENGTH = 8;
10 +
11 + private final U64 u64;
12 +
13 + public static final OFMetadata NONE = OFMetadata.of(U64.ZERO);
14 +
15 + public static final OFMetadata NO_MASK = OFMetadata.of(U64.ofRaw(0xFFFFFFFFFFFFFFFFl));
16 + public static final OFMetadata FULL_MASK = OFMetadata.of(U64.ofRaw(0x0));
17 +
18 + public OFMetadata(U64 ofRaw) {
19 + u64 = ofRaw;
20 + }
21 +
22 + public static OFMetadata of(U64 u64) {
23 + return new OFMetadata(u64);
24 + }
25 +
26 + public static OFMetadata ofRaw(long raw) {
27 + return new OFMetadata(U64.ofRaw(raw));
28 + }
29 +
30 + public U64 getValue() {
31 + return u64;
32 + }
33 +
34 + public static OFMetadata read8Bytes(ChannelBuffer cb) {
35 + return OFMetadata.ofRaw(cb.readLong());
36 + }
37 +
38 + public void write8Bytes(ChannelBuffer cb) {
39 + u64.writeTo(cb);
40 + }
41 +
42 + @Override
43 + public int getLength() {
44 + return u64.getLength();
45 + }
46 +
47 + @Override
48 + public OFMetadata applyMask(OFMetadata mask) {
49 + return OFMetadata.of(this.u64.applyMask(mask.u64));
50 + }
51 +
52 + @Override
53 + public boolean equals(Object arg0) {
54 + if (!(arg0 instanceof OFMetadata))
55 + return false;
56 + OFMetadata other = (OFMetadata)arg0;
57 +
58 + return this.u64.equals(other.u64);
59 + }
60 +
61 + @Override
62 + public int hashCode() {
63 + int prime = 53;
64 + return this.u64.hashCode() * prime;
65 + }
66 +
67 + @Override
68 + public String toString() {
69 + return "Metadata: " + u64.toString();
70 + }
71 +
72 + @Override
73 + public int compareTo(OFMetadata o) {
74 + return u64.compareTo(o.u64);
75 + }
76 +
77 + @Override
78 + public void putTo(PrimitiveSink sink) {
79 + u64.putTo(sink);
80 + }
81 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.annotations.Immutable;
5 +import org.projectfloodlight.openflow.exceptions.OFParseError;
6 +
7 +import com.google.common.hash.PrimitiveSink;
8 +import com.google.common.primitives.UnsignedInts;
9 +
10 +/**
11 + * Abstraction of an logical / OpenFlow switch port (ofp_port_no) in OpenFlow.
12 + * Immutable. Note: Switch port numbers were changed in OpenFlow 1.1 from uint16
13 + * to uint32. This class uses a 32 bit representation internally. Port numbers
14 + * are converted from/to uint16 when constructed / getPortNumberasShort is
15 + * called. If this port is not representable in OpenFlow 1.0, an
16 + * IllegalStateException is raised.
17 + *
18 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
19 + */
20 +@Immutable
21 +public class OFPort implements OFValueType<OFPort> {
22 + static final int LENGTH = 4;
23 +
24 + // private int constants (OF1.1+) to avoid duplication in the code
25 + // should not have to use these outside this class
26 + private static final int OFPP_ANY_INT = 0xFFffFFff;
27 + private static final int OFPP_LOCAL_INT = 0xFFffFFfe;
28 + private static final int OFPP_CONTROLLER_INT = 0xFFffFFfd;
29 + private static final int OFPP_ALL_INT = 0xFFffFFfc;
30 + private static final int OFPP_FLOOD_INT = 0xFFffFFfb;
31 + private static final int OFPP_NORMAL_INT = 0xFFffFFfa;
32 + private static final int OFPP_TABLE_INT = 0xFFffFFf9;
33 + private static final int OFPP_MAX_INT = 0xFFffFF00;
34 + private static final int OFPP_IN_PORT_INT = 0xFFffFFf8;
35 +
36 + // private short constants (OF1.0) to avoid duplication in the code
37 + // should not have to use these outside this class
38 + private static final short OFPP_ANY_SHORT = (short) 0xFFff;
39 + private static final short OFPP_LOCAL_SHORT = (short) 0xFFfe;
40 + private static final short OFPP_CONTROLLER_SHORT = (short) 0xFFfd;
41 + private static final short OFPP_ALL_SHORT = (short) 0xFFfc;
42 + private static final short OFPP_FLOOD_SHORT = (short) 0xFFfb;
43 + private static final short OFPP_NORMAL_SHORT = (short) 0xFFfa;
44 + private static final short OFPP_TABLE_SHORT = (short) 0xFFf9;
45 + private static final short OFPP_IN_PORT_SHORT = (short) 0xFFf8;
46 + private static final short OFPP_MAX_SHORT = (short) 0xFF00;
47 + private static final int OFPP_MAX_SHORT_UNSIGNED = 0xFF00;
48 +
49 + // ////////////// public constants - use to access well known OpenFlow ports
50 +
51 + /** Maximum number of physical and logical switch ports. */
52 + public final static OFPort MAX = new NamedPort(OFPP_MAX_INT, "max");
53 +
54 + /**
55 + * Send the packet out the input port. This reserved port must be explicitly
56 + * used in order to send back out of the input port.
57 + */
58 + public final static OFPort IN_PORT = new NamedPort(OFPP_IN_PORT_INT, "in_port");
59 +
60 + /**
61 + * Submit the packet to the first flow table NB: This destination port can
62 + * only be used in packet-out messages.
63 + */
64 + public final static OFPort TABLE = new NamedPort(OFPP_TABLE_INT, "table");
65 +
66 + /** Process with normal L2/L3 switching. */
67 + public final static OFPort NORMAL = new NamedPort(OFPP_NORMAL_INT, "normal");
68 +
69 + /**
70 + * All physical ports in VLAN, except input port and those blocked or link
71 + * down
72 + */
73 + public final static OFPort FLOOD = new NamedPort(OFPP_FLOOD_INT, "flood");
74 +
75 + /** All physical ports except input port */
76 + public final static OFPort ALL = new NamedPort(OFPP_ALL_INT, "all");
77 +
78 + /** Send to controller */
79 + public final static OFPort CONTROLLER =
80 + new NamedPort(OFPP_CONTROLLER_INT, "controller");
81 +
82 + /** local openflow "port" */
83 + public final static OFPort LOCAL = new NamedPort(OFPP_LOCAL_INT, "local");
84 +
85 + /**
86 + * Wildcard port used only for flow mod (delete) and flow stats requests.
87 + * Selects all flows regardless of output port (including flows with no
88 + * output port). NOTE: OpenFlow 1.0 calls this 'NONE'
89 + */
90 + public final static OFPort ANY = new NamedPort(OFPP_ANY_INT, "any");
91 + /** the wildcarded default for OpenFlow 1.0 (value: 0). Elsewhere in OpenFlow
92 + * we need "ANY" as the default
93 + */
94 + public static final OFPort ZERO = OFPort.of(0);
95 +
96 + public static final OFPort NO_MASK = OFPort.of(0xFFFFFFFF);
97 + public static final OFPort FULL_MASK = ZERO;
98 +
99 + /** cache of frequently used ports */
100 + private static class PrecachedPort {
101 + private final static OFPort p0 = new OFPort(0);
102 + private final static OFPort p1 = new OFPort(1);
103 + private final static OFPort p2 = new OFPort(2);
104 + private final static OFPort p3 = new OFPort(3);
105 + private final static OFPort p4 = new OFPort(4);
106 + private final static OFPort p5 = new OFPort(5);
107 + private final static OFPort p6 = new OFPort(6);
108 + private final static OFPort p7 = new OFPort(7);
109 + private final static OFPort p8 = new OFPort(8);
110 + private final static OFPort p9 = new OFPort(9);
111 + private final static OFPort p10 = new OFPort(10);
112 + private final static OFPort p11 = new OFPort(11);
113 + private final static OFPort p12 = new OFPort(12);
114 + private final static OFPort p13 = new OFPort(13);
115 + private final static OFPort p14 = new OFPort(14);
116 + private final static OFPort p15 = new OFPort(15);
117 + private final static OFPort p16 = new OFPort(16);
118 + private final static OFPort p17 = new OFPort(17);
119 + private final static OFPort p18 = new OFPort(18);
120 + private final static OFPort p19 = new OFPort(19);
121 + private final static OFPort p20 = new OFPort(20);
122 + private final static OFPort p21 = new OFPort(21);
123 + private final static OFPort p22 = new OFPort(22);
124 + private final static OFPort p23 = new OFPort(23);
125 + private final static OFPort p24 = new OFPort(24);
126 + private final static OFPort p25 = new OFPort(25);
127 + private final static OFPort p26 = new OFPort(26);
128 + private final static OFPort p27 = new OFPort(27);
129 + private final static OFPort p28 = new OFPort(28);
130 + private final static OFPort p29 = new OFPort(29);
131 + private final static OFPort p31 = new OFPort(31);
132 + private final static OFPort p32 = new OFPort(32);
133 + private final static OFPort p33 = new OFPort(33);
134 + private final static OFPort p34 = new OFPort(34);
135 + private final static OFPort p35 = new OFPort(35);
136 + private final static OFPort p36 = new OFPort(36);
137 + private final static OFPort p37 = new OFPort(37);
138 + private final static OFPort p38 = new OFPort(38);
139 + private final static OFPort p39 = new OFPort(39);
140 + private final static OFPort p40 = new OFPort(40);
141 + private final static OFPort p41 = new OFPort(41);
142 + private final static OFPort p42 = new OFPort(42);
143 + private final static OFPort p43 = new OFPort(43);
144 + private final static OFPort p44 = new OFPort(44);
145 + private final static OFPort p45 = new OFPort(45);
146 + private final static OFPort p46 = new OFPort(46);
147 + private final static OFPort p47 = new OFPort(47);
148 + private final static OFPort p48 = new OFPort(48);
149 + }
150 +
151 + /** raw openflow port number as a signed 32 bit integer */
152 + private final int portNumber;
153 +
154 + /** private constructor. use of*-Factory methods instead */
155 + private OFPort(final int portNumber) {
156 + this.portNumber = portNumber;
157 + }
158 +
159 + /**
160 + * get an OFPort object corresponding to a raw 32-bit integer port number.
161 + * NOTE: The port object may either be newly allocated or cached. Do not
162 + * rely on either behavior.
163 + *
164 + * @param portNumber
165 + * @return a corresponding OFPort
166 + */
167 + public static OFPort ofInt(final int portNumber) {
168 + switch (portNumber) {
169 + case 0:
170 + return PrecachedPort.p0;
171 + case 1:
172 + return PrecachedPort.p1;
173 + case 2:
174 + return PrecachedPort.p2;
175 + case 3:
176 + return PrecachedPort.p3;
177 + case 4:
178 + return PrecachedPort.p4;
179 + case 5:
180 + return PrecachedPort.p5;
181 + case 6:
182 + return PrecachedPort.p6;
183 + case 7:
184 + return PrecachedPort.p7;
185 + case 8:
186 + return PrecachedPort.p8;
187 + case 9:
188 + return PrecachedPort.p9;
189 + case 10:
190 + return PrecachedPort.p10;
191 + case 11:
192 + return PrecachedPort.p11;
193 + case 12:
194 + return PrecachedPort.p12;
195 + case 13:
196 + return PrecachedPort.p13;
197 + case 14:
198 + return PrecachedPort.p14;
199 + case 15:
200 + return PrecachedPort.p15;
201 + case 16:
202 + return PrecachedPort.p16;
203 + case 17:
204 + return PrecachedPort.p17;
205 + case 18:
206 + return PrecachedPort.p18;
207 + case 19:
208 + return PrecachedPort.p19;
209 + case 20:
210 + return PrecachedPort.p20;
211 + case 21:
212 + return PrecachedPort.p21;
213 + case 22:
214 + return PrecachedPort.p22;
215 + case 23:
216 + return PrecachedPort.p23;
217 + case 24:
218 + return PrecachedPort.p24;
219 + case 25:
220 + return PrecachedPort.p25;
221 + case 26:
222 + return PrecachedPort.p26;
223 + case 27:
224 + return PrecachedPort.p27;
225 + case 28:
226 + return PrecachedPort.p28;
227 + case 29:
228 + return PrecachedPort.p29;
229 + case 31:
230 + return PrecachedPort.p31;
231 + case 32:
232 + return PrecachedPort.p32;
233 + case 33:
234 + return PrecachedPort.p33;
235 + case 34:
236 + return PrecachedPort.p34;
237 + case 35:
238 + return PrecachedPort.p35;
239 + case 36:
240 + return PrecachedPort.p36;
241 + case 37:
242 + return PrecachedPort.p37;
243 + case 38:
244 + return PrecachedPort.p38;
245 + case 39:
246 + return PrecachedPort.p39;
247 + case 40:
248 + return PrecachedPort.p40;
249 + case 41:
250 + return PrecachedPort.p41;
251 + case 42:
252 + return PrecachedPort.p42;
253 + case 43:
254 + return PrecachedPort.p43;
255 + case 44:
256 + return PrecachedPort.p44;
257 + case 45:
258 + return PrecachedPort.p45;
259 + case 46:
260 + return PrecachedPort.p46;
261 + case 47:
262 + return PrecachedPort.p47;
263 + case 48:
264 + return PrecachedPort.p48;
265 + case OFPP_MAX_INT:
266 + return MAX;
267 + case OFPP_IN_PORT_INT:
268 + return IN_PORT;
269 + case OFPP_TABLE_INT:
270 + return TABLE;
271 + case OFPP_NORMAL_INT:
272 + return NORMAL;
273 + case OFPP_FLOOD_INT:
274 + return FLOOD;
275 + case OFPP_ALL_INT:
276 + return ALL;
277 + case OFPP_CONTROLLER_INT:
278 + return CONTROLLER;
279 + case OFPP_LOCAL_INT:
280 + return LOCAL;
281 + case OFPP_ANY_INT:
282 + return ANY;
283 + default:
284 + // note: This means effectively : portNumber > OFPP_MAX_SHORT
285 + // accounting for
286 + // signedness of both portNumber and OFPP_MAX_INT(which is
287 + // -256).
288 + // Any unsigned integer value > OFPP_MAX_INT will be ]-256:0[
289 + // when read signed
290 + if (portNumber < 0 && portNumber > OFPP_MAX_INT)
291 + throw new IllegalArgumentException("Unknown special port number: "
292 + + portNumber);
293 + return new OFPort(portNumber);
294 + }
295 + }
296 +
297 + /** convenience function: delegates to ofInt */
298 + public static OFPort of(final int portNumber) {
299 + return ofInt(portNumber);
300 + }
301 +
302 + /**
303 + * get an OFPort object corresponding to a raw signed 16-bit integer port
304 + * number (OF1.0). Note that the port returned will have the corresponding
305 + * 32-bit integer value allocated as its port number. NOTE: The port object
306 + * may either be newly allocated or cached. Do not rely on either behavior.
307 + *
308 + * @param portNumber
309 + * @return a corresponding OFPort
310 + */
311 + public static OFPort ofShort(final short portNumber) {
312 + switch (portNumber) {
313 + case 0:
314 + return PrecachedPort.p0;
315 + case 1:
316 + return PrecachedPort.p1;
317 + case 2:
318 + return PrecachedPort.p2;
319 + case 3:
320 + return PrecachedPort.p3;
321 + case 4:
322 + return PrecachedPort.p4;
323 + case 5:
324 + return PrecachedPort.p5;
325 + case 6:
326 + return PrecachedPort.p6;
327 + case 7:
328 + return PrecachedPort.p7;
329 + case 8:
330 + return PrecachedPort.p8;
331 + case 9:
332 + return PrecachedPort.p9;
333 + case 10:
334 + return PrecachedPort.p10;
335 + case 11:
336 + return PrecachedPort.p11;
337 + case 12:
338 + return PrecachedPort.p12;
339 + case 13:
340 + return PrecachedPort.p13;
341 + case 14:
342 + return PrecachedPort.p14;
343 + case 15:
344 + return PrecachedPort.p15;
345 + case 16:
346 + return PrecachedPort.p16;
347 + case 17:
348 + return PrecachedPort.p17;
349 + case 18:
350 + return PrecachedPort.p18;
351 + case 19:
352 + return PrecachedPort.p19;
353 + case 20:
354 + return PrecachedPort.p20;
355 + case 21:
356 + return PrecachedPort.p21;
357 + case 22:
358 + return PrecachedPort.p22;
359 + case 23:
360 + return PrecachedPort.p23;
361 + case 24:
362 + return PrecachedPort.p24;
363 + case 25:
364 + return PrecachedPort.p25;
365 + case 26:
366 + return PrecachedPort.p26;
367 + case 27:
368 + return PrecachedPort.p27;
369 + case 28:
370 + return PrecachedPort.p28;
371 + case 29:
372 + return PrecachedPort.p29;
373 + case 31:
374 + return PrecachedPort.p31;
375 + case 32:
376 + return PrecachedPort.p32;
377 + case 33:
378 + return PrecachedPort.p33;
379 + case 34:
380 + return PrecachedPort.p34;
381 + case 35:
382 + return PrecachedPort.p35;
383 + case 36:
384 + return PrecachedPort.p36;
385 + case 37:
386 + return PrecachedPort.p37;
387 + case 38:
388 + return PrecachedPort.p38;
389 + case 39:
390 + return PrecachedPort.p39;
391 + case 40:
392 + return PrecachedPort.p40;
393 + case 41:
394 + return PrecachedPort.p41;
395 + case 42:
396 + return PrecachedPort.p42;
397 + case 43:
398 + return PrecachedPort.p43;
399 + case 44:
400 + return PrecachedPort.p44;
401 + case 45:
402 + return PrecachedPort.p45;
403 + case 46:
404 + return PrecachedPort.p46;
405 + case 47:
406 + return PrecachedPort.p47;
407 + case 48:
408 + return PrecachedPort.p48;
409 + case OFPP_MAX_SHORT:
410 + return MAX;
411 + case OFPP_IN_PORT_SHORT:
412 + return IN_PORT;
413 + case OFPP_TABLE_SHORT:
414 + return TABLE;
415 + case OFPP_NORMAL_SHORT:
416 + return NORMAL;
417 + case OFPP_FLOOD_SHORT:
418 + return FLOOD;
419 + case OFPP_ALL_SHORT:
420 + return ALL;
421 + case OFPP_CONTROLLER_SHORT:
422 + return CONTROLLER;
423 + case OFPP_LOCAL_SHORT:
424 + return LOCAL;
425 + case OFPP_ANY_SHORT:
426 + return ANY;
427 + default:
428 + // note: This means effectively : portNumber > OFPP_MAX_SHORT
429 + // accounting for
430 + // signedness of both portNumber and OFPP_MAX_SHORT (which is
431 + // -256).
432 + // Any unsigned integer value > OFPP_MAX_SHORT will be ]-256:0[
433 + // when read signed
434 + if (portNumber < 0 && portNumber > OFPP_MAX_SHORT)
435 + throw new IllegalArgumentException("Unknown special port number: "
436 + + portNumber);
437 + return new OFPort(portNumber);
438 + }
439 + }
440 +
441 + /** return the port number as a int32 */
442 + public int getPortNumber() {
443 + return portNumber;
444 + }
445 +
446 + /**
447 + * return the port number as int16. Special ports as defined by the OpenFlow
448 + * spec will be converted to their OpenFlow 1.0 equivalent. port numbers >=
449 + * FF00 will cause a IllegalArgumentException to be thrown
450 + *
451 + * @throws IllegalArgumentException
452 + * if a regular port number exceeds the maximum value in OF1.0
453 + **/
454 + public short getShortPortNumber() {
455 +
456 + switch (portNumber) {
457 + case OFPP_MAX_INT:
458 + return OFPP_MAX_SHORT;
459 + case OFPP_IN_PORT_INT:
460 + return OFPP_IN_PORT_SHORT;
461 + case OFPP_TABLE_INT:
462 + return OFPP_TABLE_SHORT;
463 + case OFPP_NORMAL_INT:
464 + return OFPP_NORMAL_SHORT;
465 + case OFPP_FLOOD_INT:
466 + return OFPP_FLOOD_SHORT;
467 + case OFPP_ALL_INT:
468 + return OFPP_ALL_SHORT;
469 + case OFPP_CONTROLLER_INT:
470 + return OFPP_CONTROLLER_SHORT;
471 + case OFPP_LOCAL_INT:
472 + return OFPP_LOCAL_SHORT;
473 + case OFPP_ANY_INT:
474 + return OFPP_ANY_SHORT;
475 +
476 + default:
477 + if (portNumber >= OFPP_MAX_SHORT_UNSIGNED || portNumber < 0)
478 + throw new IllegalArgumentException("32bit Port number "
479 + + U32.f(portNumber)
480 + + " cannot be represented as uint16 (OF1.0)");
481 +
482 + return (short) portNumber;
483 + }
484 + }
485 +
486 + @Override
487 + public String toString() {
488 + return Long.toString(U32.f(portNumber));
489 + }
490 +
491 + /** Extension of OFPort for named ports */
492 + static class NamedPort extends OFPort {
493 + private final String name;
494 +
495 + NamedPort(final int portNo, final String name) {
496 + super(portNo);
497 + this.name = name;
498 + }
499 +
500 + public String getName() {
501 + return name;
502 + }
503 +
504 + @Override
505 + public String toString() {
506 + return name;
507 + }
508 + }
509 +
510 + @Override
511 + public int getLength() {
512 + return LENGTH;
513 + }
514 +
515 + @Override
516 + public boolean equals(Object obj) {
517 + if (!(obj instanceof OFPort))
518 + return false;
519 + OFPort other = (OFPort)obj;
520 + if (other.portNumber != this.portNumber)
521 + return false;
522 + return true;
523 + }
524 +
525 + @Override
526 + public int hashCode() {
527 + final int prime = 53;
528 + int result = 1;
529 + result = prime * result + portNumber;
530 + return result;
531 + }
532 +
533 + public void write2Bytes(ChannelBuffer c) {
534 + c.writeShort(this.portNumber);
535 + }
536 +
537 + public static OFPort read2Bytes(ChannelBuffer c) throws OFParseError {
538 + return OFPort.ofShort(c.readShort());
539 + }
540 +
541 + public void write4Bytes(ChannelBuffer c) {
542 + c.writeInt(this.portNumber);
543 + }
544 +
545 + public static OFPort read4Bytes(ChannelBuffer c) throws OFParseError {
546 + return OFPort.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
547 + }
548 +
549 + @Override
550 + public OFPort applyMask(OFPort mask) {
551 + return OFPort.of(this.portNumber & mask.portNumber);
552 + }
553 +
554 + @Override
555 + public int compareTo(OFPort o) {
556 + return UnsignedInts.compare(this.portNumber, o.portNumber);
557 + }
558 +
559 + @Override
560 + public void putTo(PrimitiveSink sink) {
561 + sink.putInt(portNumber);
562 + }
563 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.util.ArrayList;
4 +
5 +import javax.annotation.concurrent.Immutable;
6 +
7 +
8 +/** User-facing object representing a bitmap of ports that can be matched on.
9 + * This is implemented by the custom BSN OXM type of_oxm_bsn_in_ports_182.
10 + *
11 + * You can call set() on the builder for all the Ports you want to match on
12 + * and unset to exclude the port.
13 + *
14 + * <b>Implementation note:</b> to comply with the matching semantics of OXM (which is a logical "AND" not "OR")
15 + * the underlying match uses a data format which is very unintuitive. The value is always
16 + * 0, and the mask has the bits set for the ports that should <b>NOT</b> be included in the
17 + * range.
18 + *
19 + * For the curious: We transformed the bitmap (a logical OR) problem into a logical
20 + * AND NOT problem.
21 + *
22 + * We logically mean: Inport is 1 OR 3
23 + * We technically say: Inport IS NOT 2 AND IS NOT 4 AND IS NOT 5 AND IS NOT ....
24 + * The second term cannot be represented in OXM, the second can.
25 + *
26 + * That said, all that craziness is hidden from the user of this object.
27 + *
28 + * <h2>Usage</h2>
29 + * OFPortBitmap is meant to be used with MatchField <tt>BSN_IN_PORTS_128</tt> in place
30 + * of the raw type Masked&lt;OFBitMask128&gt;.
31 + *
32 + * <h3>Example:</h3>:
33 + * <pre>
34 + * OFPortBitMap portBitMap;
35 + * Match.Builder matchBuilder;
36 + * // initialize
37 + * matchBuilder.setMasked(MatchField.BSN_IN_PORTS_128, portBitmap);
38 + * </pre>
39 + *
40 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
41 + */
42 +@Immutable
43 +public class OFPortBitMap extends Masked<OFBitMask128> {
44 +
45 + private OFPortBitMap(OFBitMask128 mask) {
46 + super(OFBitMask128.NONE, mask);
47 + }
48 +
49 + /** @return whether or not the given port is logically included in the
50 + * match, i.e., whether a packet from in-port <emph>port</emph> be matched by
51 + * this OXM.
52 + */
53 + public boolean isOn(OFPort port) {
54 + // see the implementation note above about the logical inversion of the mask
55 + return !(this.mask.isOn(port.getPortNumber()));
56 + }
57 +
58 + public static OFPortBitMap ofPorts(OFPort... ports) {
59 + Builder builder = new Builder();
60 + for (OFPort port: ports) {
61 + builder.set(port);
62 + }
63 + return builder.build();
64 + }
65 +
66 + /** @return an OFPortBitmap based on the 'mask' part of an OFBitMask128, as, e.g., returned
67 + * by the switch.
68 + **/
69 + public static OFPortBitMap of(OFBitMask128 mask) {
70 + return new OFPortBitMap(mask);
71 + }
72 +
73 + /** @return iterating over all ports that are logically included in the
74 + * match, i.e., whether a packet from in-port <emph>port</emph> be matched by
75 + * this OXM.
76 + */
77 + public Iterable<OFPort> getOnPorts() {
78 + ArrayList<OFPort> ports = new ArrayList<>();
79 + for(int i=0; i < 127; i++) {
80 + if(!(this.mask.isOn(i))) {
81 + ports.add(OFPort.of(i));
82 + }
83 + }
84 + return ports;
85 + }
86 +
87 + @Override
88 + public boolean equals(Object obj) {
89 + if (!(obj instanceof OFPortBitMap))
90 + return false;
91 + OFPortBitMap other = (OFPortBitMap)obj;
92 + return (other.value.equals(this.value) && other.mask.equals(this.mask));
93 + }
94 +
95 + @Override
96 + public int hashCode() {
97 + return 619 * mask.hashCode() + 257 * value.hashCode();
98 + }
99 +
100 + public static class Builder {
101 + private long raw1 = -1, raw2 = -1;
102 +
103 + public Builder() {
104 +
105 + }
106 +
107 + /** @return whether or not the given port is logically included in the
108 + * match, i.e., whether a packet from in-port <emph>port</emph> be matched by
109 + * this OXM.
110 + */
111 + public boolean isOn(OFPort port) {
112 + // see the implementation note above about the logical inversion of the mask
113 + return !(OFBitMask128.isBitOn(raw1, raw2, port.getPortNumber()));
114 + }
115 +
116 + /** remove this port from the match, i.e., packets from this in-port
117 + * will NOT be matched.
118 + */
119 + public Builder unset(OFPort port) {
120 + // see the implementation note above about the logical inversion of the mask
121 + int bit = port.getPortNumber();
122 + if (bit < 0 || bit > 127)
123 + throw new IndexOutOfBoundsException("Port number is out of bounds");
124 + else if (bit == 127)
125 + // the highest order bit in the bitmask is reserved. The switch will
126 + // set that bit for all ports >= 127. The reason is that we don't want
127 + // the OFPortMap to match all ports out of its range (i.e., a packet
128 + // coming in on port 181 would match *any* OFPortMap).
129 + throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
130 + else if (bit < 64) {
131 + raw2 |= ((long)1 << bit);
132 + } else {
133 + raw1 |= ((long)1 << (bit - 64));
134 + }
135 + return this;
136 + }
137 +
138 + /** add this port from the match, i.e., packets from this in-port
139 + * will NOT be matched.
140 + */
141 + public Builder set(OFPort port) {
142 + // see the implementation note above about the logical inversion of the mask
143 + int bit = port.getPortNumber();
144 + if (bit < 0 || bit > 127)
145 + throw new IndexOutOfBoundsException("Port number is out of bounds");
146 + else if (bit == 127)
147 + // the highest order bit in the bitmask is reserved. The switch will
148 + // set that bit for all ports >= 127. The reason is that we don't want
149 + // the OFPortMap to match all ports out of its range (i.e., a packet
150 + // coming in on port 181 would match *any* OFPortMap).
151 + throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
152 + else if (bit < 64) {
153 + raw2 &= ~((long)1 << bit);
154 + } else {
155 + raw1 &= ~((long)1 << (bit - 64));
156 + }
157 + return this;
158 + }
159 +
160 + public OFPortBitMap build() {
161 + return new OFPortBitMap(OFBitMask128.of(raw1, raw2));
162 + }
163 + }
164 +
165 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +
4 +
5 +
6 +public interface OFValueType<T extends OFValueType<T>> extends Comparable<T>, PrimitiveSinkable {
7 + public int getLength();
8 +
9 + public T applyMask(T mask);
10 +
11 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.util.Arrays;
4 +
5 +import javax.annotation.Nullable;
6 +
7 +import org.jboss.netty.buffer.ChannelBuffer;
8 +import org.projectfloodlight.openflow.exceptions.OFParseError;
9 +import org.slf4j.Logger;
10 +import org.slf4j.LoggerFactory;
11 +
12 +import com.google.common.hash.PrimitiveSink;
13 +import com.google.common.primitives.Shorts;
14 +
15 +/** Represents an OpenFlow Vlan VID for use in Matches, as specified by the OpenFlow 1.3 spec.
16 + *
17 + * <b> Note: this is not just the 12-bit vlan tag. OpenFlow defines
18 + * the additional mask bits 0x1000 to represent the presence of a vlan
19 + * tag. This additional bit will be stripped when writing a OF1.0 value
20 + * tag.
21 + * </b>
22 + *
23 + *
24 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
25 + *
26 + */
27 +public class OFVlanVidMatch implements OFValueType<OFVlanVidMatch> {
28 + private static final Logger logger = LoggerFactory.getLogger(OFVlanVidMatch.class);
29 +
30 + private static final short VALIDATION_MASK = 0x1FFF;
31 + private static final short PRESENT_VAL = 0x1000;
32 + private static final short VLAN_MASK = 0x0FFF;
33 + private static final short NONE_VAL = 0x0000;
34 + private static final short UNTAGGED_VAL_OF13 = (short) 0x0000;
35 + private static final short UNTAGGED_VAL_OF10 = (short) 0xFFFF;
36 + final static int LENGTH = 2;
37 +
38 + /** presence of a VLAN tag is indicated by the presence of bit 0x1000 */
39 + public static final OFVlanVidMatch PRESENT = new OFVlanVidMatch(PRESENT_VAL);
40 +
41 + /** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
42 + public static final OFVlanVidMatch NONE = new OFVlanVidMatch(NONE_VAL);
43 +
44 + /** for use with masking operations */
45 + public static final OFVlanVidMatch NO_MASK = new OFVlanVidMatch((short)0xFFFF);
46 + public static final OFVlanVidMatch FULL_MASK = NONE;
47 +
48 + /** an untagged packet is specified as 0000 in OF 1.0, but 0xFFFF in OF1.0. Special case that. */
49 + public static final OFVlanVidMatch UNTAGGED = new OFVlanVidMatch(NONE_VAL) {
50 + @Override
51 + public void write2BytesOF10(ChannelBuffer c) {
52 + c.writeShort(UNTAGGED_VAL_OF10);
53 + }
54 + };
55 +
56 + private final short vid;
57 +
58 + private OFVlanVidMatch(short vid) {
59 + this.vid = vid;
60 + }
61 +
62 + public static OFVlanVidMatch ofRawVid(short vid) {
63 + if(vid == UNTAGGED_VAL_OF13)
64 + return UNTAGGED;
65 + else if(vid == PRESENT_VAL)
66 + return PRESENT;
67 + else if(vid == UNTAGGED_VAL_OF10) {
68 + // workaround for IVS sometimes sending 0F1.0 untagged (0xFFFF) values
69 + logger.warn("Warning: received OF1.0 untagged vlan value (0xFFFF) in OF1.3 VlanVid. Treating as UNTAGGED");
70 + return UNTAGGED;
71 + } else if ((vid & VALIDATION_MASK) != vid)
72 + throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
73 + return new OFVlanVidMatch(vid);
74 + }
75 +
76 + public static OFVlanVidMatch ofVlanVid(VlanVid vid) {
77 + if(vid == null)
78 + return UNTAGGED;
79 + else if(VlanVid.NO_MASK.equals(vid))
80 + // NO_MASK is a special value in that it doesn't fit in the
81 + // allowed value space (0x1FFF) of this type. Do a manual conversion
82 + return NO_MASK;
83 + else
84 + return ofVlan(vid.getVlan());
85 + }
86 +
87 +
88 + public static OFVlanVidMatch ofVlan(int vlan) {
89 + if( (vlan & VLAN_MASK) != vlan)
90 + throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vlan));
91 + return ofRawVid( (short) (vlan | PRESENT_VAL));
92 + }
93 +
94 + public static OFVlanVidMatch ofVlanOF10(short of10vlan) {
95 + if(of10vlan == NONE_VAL) {
96 + return NONE;
97 + } else if(of10vlan == UNTAGGED_VAL_OF10) {
98 + return UNTAGGED;
99 + } else {
100 + return ofVlan(of10vlan);
101 + }
102 + }
103 +
104 + /** @return whether or not this VlanId has the present (0x1000) bit set */
105 + public boolean isPresentBitSet() {
106 + return (vid & PRESENT_VAL) != 0;
107 + }
108 +
109 + /** @return the actual VLAN tag this vid identifies */
110 + public short getVlan() {
111 + return (short) (vid & VLAN_MASK);
112 + }
113 +
114 + /** @return the actual vlan tag this vid identifies as a VlanVid object, if this
115 + * VlanVidMatch has the present bit set (i.e., identifies a tagged VLAN).
116 + * Else, returns null.
117 + */
118 + @Nullable
119 + public VlanVid getVlanVid() {
120 + if(this.equals(NO_MASK))
121 + return VlanVid.NO_MASK;
122 + else if(isPresentBitSet())
123 + return VlanVid.ofVlan((short) (vid & VLAN_MASK));
124 + else
125 + return null;
126 + }
127 +
128 + @Override
129 + public boolean equals(Object obj) {
130 + if (!(obj instanceof OFVlanVidMatch))
131 + return false;
132 + OFVlanVidMatch other = (OFVlanVidMatch)obj;
133 + if (other.vid != this.vid)
134 + return false;
135 + return true;
136 + }
137 +
138 + @Override
139 + public int hashCode() {
140 + int prime = 13873;
141 + return this.vid * prime;
142 + }
143 +
144 + @Override
145 + public String toString() {
146 + return "0x" + Integer.toHexString(vid);
147 + }
148 +
149 + public short getRawVid() {
150 + return vid;
151 + }
152 +
153 +
154 + @Override
155 + public int getLength() {
156 + return LENGTH;
157 + }
158 +
159 +
160 + private volatile byte[] bytesCache = null;
161 +
162 + public byte[] getBytes() {
163 + if (bytesCache == null) {
164 + synchronized (this) {
165 + if (bytesCache == null) {
166 + bytesCache =
167 + new byte[] { (byte) ((vid >>> 8) & 0xFF),
168 + (byte) ((vid >>> 0) & 0xFF) };
169 + }
170 + }
171 + }
172 + return Arrays.copyOf(bytesCache, bytesCache.length);
173 + }
174 +
175 + public void write2Bytes(ChannelBuffer c) {
176 + c.writeShort(this.vid);
177 + }
178 +
179 + public void write2BytesOF10(ChannelBuffer c) {
180 + c.writeShort(this.getVlan());
181 + }
182 +
183 + public static OFVlanVidMatch read2Bytes(ChannelBuffer c) throws OFParseError {
184 + return OFVlanVidMatch.ofRawVid(c.readShort());
185 + }
186 +
187 + public static OFVlanVidMatch read2BytesOF10(ChannelBuffer c) throws OFParseError {
188 + return OFVlanVidMatch.ofVlanOF10(c.readShort());
189 + }
190 +
191 + @Override
192 + public OFVlanVidMatch applyMask(OFVlanVidMatch mask) {
193 + return OFVlanVidMatch.ofRawVid((short)(this.vid & mask.vid));
194 + }
195 +
196 + @Override
197 + public int compareTo(OFVlanVidMatch o) {
198 + return Shorts.compare(vid, o.vid);
199 + }
200 + @Override
201 + public void putTo(PrimitiveSink sink) {
202 + sink.putShort(vid);
203 + }
204 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +public class OFVlanVidMatchWithMask extends Masked<OFVlanVidMatch> {
4 + private OFVlanVidMatchWithMask(OFVlanVidMatch value, OFVlanVidMatch mask) {
5 + super(value, mask);
6 + }
7 +
8 + /* a combination of Vlan Vid and mask that matches any tagged packet */
9 + public final static OFVlanVidMatchWithMask ANY_TAGGED = new OFVlanVidMatchWithMask(OFVlanVidMatch.PRESENT, OFVlanVidMatch.PRESENT);
10 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +/**
4 + * Represents the speed of a port
5 + */
6 +public enum PortSpeed {
7 + /** no speed set */
8 + SPEED_NONE(0),
9 + SPEED_10MB(10),
10 + SPEED_100MB(100),
11 + SPEED_1GB(1_000),
12 + SPEED_10GB(10_000),
13 + SPEED_40GB(40_000),
14 + SPEED_100GB(100_000),
15 + SPEED_1TB(1_000_000);
16 +
17 + private long speedInBps;
18 + private PortSpeed(int speedInMbps) {
19 + this.speedInBps = speedInMbps * 1000L*1000L;
20 + }
21 +
22 + public long getSpeedBps() {
23 + return this.speedInBps;
24 + }
25 +
26 + public static PortSpeed max(PortSpeed s1, PortSpeed s2) {
27 + return (s1.getSpeedBps() > s2.getSpeedBps()) ? s1 : s2;
28 + }
29 +
30 + public static PortSpeed min(PortSpeed s1, PortSpeed s2) {
31 + return (s1.getSpeedBps() < s2.getSpeedBps()) ? s1 : s2;
32 + }
33 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import com.google.common.hash.PrimitiveSink;
4 +
5 +public interface PrimitiveSinkable {
6 + public void putTo(PrimitiveSink sink);
7 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +import com.google.common.primitives.Shorts;
8 +
9 +public class TableId implements OFValueType<TableId>, Comparable<TableId> {
10 +
11 + final static int LENGTH = 1;
12 +
13 + private static final short VALIDATION_MASK = 0x00FF;
14 +
15 + private static final short ALL_VAL = 0x00FF;
16 + private static final short NONE_VAL = 0x0000;
17 + public static final TableId NONE = new TableId(NONE_VAL);
18 +
19 + public static final TableId ALL = new TableId(ALL_VAL);
20 + public static final TableId ZERO = NONE;
21 +
22 + private final short id;
23 +
24 + private TableId(short id) {
25 + this.id = id;
26 + }
27 +
28 + public static TableId of(short id) {
29 + switch(id) {
30 + case NONE_VAL:
31 + return NONE;
32 + case ALL_VAL:
33 + return ALL;
34 + default:
35 + if ((id & VALIDATION_MASK) != id)
36 + throw new IllegalArgumentException("Illegal Table id value: " + id);
37 + return new TableId(id);
38 + }
39 + }
40 +
41 + public static TableId of(int id) {
42 + if((id & VALIDATION_MASK) != id)
43 + throw new IllegalArgumentException("Illegal Table id value: "+id);
44 + return of((short) id);
45 + }
46 +
47 + @Override
48 + public String toString() {
49 + return "0x" + Integer.toHexString(id);
50 + }
51 +
52 + public short getValue() {
53 + return id;
54 + }
55 +
56 + @Override
57 + public int getLength() {
58 + return LENGTH;
59 + }
60 +
61 + public void writeByte(ChannelBuffer c) {
62 + c.writeByte(this.id);
63 + }
64 +
65 + public static TableId readByte(ChannelBuffer c) throws OFParseError {
66 + return TableId.of(c.readUnsignedByte());
67 + }
68 +
69 + @Override
70 + public TableId applyMask(TableId mask) {
71 + return TableId.of((short)(this.id & mask.id));
72 + }
73 +
74 + @Override
75 + public boolean equals(Object obj) {
76 + if (!(obj instanceof TableId))
77 + return false;
78 + TableId other = (TableId)obj;
79 + if (other.id != this.id)
80 + return false;
81 + return true;
82 + }
83 +
84 + @Override
85 + public int hashCode() {
86 + int prime = 13873;
87 + return this.id * prime;
88 + }
89 +
90 + @Override
91 + public int compareTo(TableId other) {
92 + return Shorts.compare(this.id, other.id);
93 + }
94 +
95 + @Override
96 + public void putTo(PrimitiveSink sink) {
97 + sink.putByte((byte) id);
98 + }
99 +
100 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +import com.google.common.primitives.Ints;
8 +
9 +/**
10 + * Represents L4 (Transport Layer) port (TCP, UDP, etc.)
11 + *
12 + * @author Yotam Harchol (yotam.harchol@bigswitch.com)
13 + */
14 +public class TransportPort implements OFValueType<TransportPort> {
15 +
16 + static final int LENGTH = 2;
17 + static final int MAX_PORT = 0xFFFF;
18 + static final int MIN_PORT = 0;
19 +
20 + private final static int NONE_VAL = 0;
21 + public final static TransportPort NONE = new TransportPort(NONE_VAL);
22 +
23 + public static final TransportPort NO_MASK = new TransportPort(0xFFFFFFFF);
24 + public static final TransportPort FULL_MASK = TransportPort.of(0x0);
25 +
26 + private final int port;
27 +
28 + private TransportPort(int port) {
29 + this.port = port;
30 + }
31 +
32 + public static TransportPort of(int port) {
33 + if(port == NONE_VAL)
34 + return NONE;
35 + else if (port == NO_MASK.port)
36 + return NO_MASK;
37 + else if (port < MIN_PORT || port > MAX_PORT) {
38 + throw new IllegalArgumentException("Illegal transport layer port number: " + port);
39 + }
40 + return new TransportPort(port);
41 + }
42 +
43 + @Override
44 + public int getLength() {
45 + return LENGTH;
46 + }
47 +
48 + public int getPort() {
49 + return port;
50 + }
51 +
52 + @Override
53 + public boolean equals(Object obj) {
54 + if (!(obj instanceof TransportPort))
55 + return false;
56 + TransportPort other = (TransportPort)obj;
57 + if (other.port != this.port)
58 + return false;
59 + return true;
60 + }
61 +
62 + @Override
63 + public int hashCode() {
64 + final int prime = 59;
65 + int result = 1;
66 + result = prime * result + port;
67 + return result;
68 + }
69 +
70 + @Override
71 + public String toString() {
72 + return Integer.toString(port);
73 + }
74 +
75 + public void write2Bytes(ChannelBuffer c) {
76 + c.writeShort(this.port);
77 + }
78 +
79 + public static TransportPort read2Bytes(ChannelBuffer c) throws OFParseError {
80 + return TransportPort.of((c.readUnsignedShort() & 0x0FFFF));
81 + }
82 +
83 + @Override
84 + public TransportPort applyMask(TransportPort mask) {
85 + return TransportPort.of(this.port & mask.port);
86 + }
87 +
88 + @Override
89 + public int compareTo(TransportPort o) {
90 + return Ints.compare(port, o.port);
91 + }
92 +
93 + @Override
94 + public void putTo(PrimitiveSink sink) {
95 + sink.putShort((short) port);
96 + }
97 +
98 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import javax.annotation.Nonnull;
4 +
5 +import org.jboss.netty.buffer.ChannelBuffer;
6 +
7 +import com.google.common.hash.PrimitiveSink;
8 +import com.google.common.primitives.UnsignedLongs;
9 +
10 +public class U128 implements OFValueType<U128>, HashValue<U128> {
11 +
12 + static final int LENGTH = 16;
13 +
14 + private final long raw1; // MSBs
15 + private final long raw2; // LSBs
16 +
17 + public static final U128 ZERO = new U128(0, 0);
18 +
19 + private U128(long raw1, long raw2) {
20 + this.raw1 = raw1;
21 + this.raw2 = raw2;
22 + }
23 +
24 + public static U128 of(long raw1, long raw2) {
25 + if (raw1 == 0 && raw2 == 0)
26 + return ZERO;
27 + return new U128(raw1, raw2);
28 + }
29 +
30 + @Override
31 + public int getLength() {
32 + return LENGTH;
33 + }
34 +
35 +
36 + public long getMsb() {
37 + return raw1;
38 + }
39 +
40 + public long getLsb() {
41 + return raw2;
42 + }
43 +
44 + @Override
45 + public U128 applyMask(U128 mask) {
46 + return and(mask);
47 + }
48 +
49 + @Override
50 + public int hashCode() {
51 + final int prime = 31;
52 + int result = 1;
53 + result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
54 + result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
55 + return result;
56 + }
57 +
58 + @Override
59 + public boolean equals(Object obj) {
60 + if (this == obj)
61 + return true;
62 + if (obj == null)
63 + return false;
64 + if (getClass() != obj.getClass())
65 + return false;
66 + U128 other = (U128) obj;
67 + if (raw1 != other.raw1)
68 + return false;
69 + if (raw2 != other.raw2)
70 + return false;
71 + return true;
72 + }
73 +
74 + public void write16Bytes(ChannelBuffer cb) {
75 + cb.writeLong(raw1);
76 + cb.writeLong(raw2);
77 + }
78 +
79 + public static U128 read16Bytes(ChannelBuffer cb) {
80 + long raw1 = cb.readLong();
81 + long raw2 = cb.readLong();
82 + return of(raw1, raw2);
83 + }
84 +
85 + @Override
86 + public String toString() {
87 + return String.format("0x%016x%016x", raw1, raw2);
88 + }
89 +
90 + @Override
91 + public int compareTo(@Nonnull U128 o) {
92 + int msb = UnsignedLongs.compare(this.raw1, o.raw1);
93 + if(msb != 0)
94 + return msb;
95 + else
96 + return UnsignedLongs.compare(this.raw2, o.raw2);
97 + }
98 +
99 + @Override
100 + public void putTo(PrimitiveSink sink) {
101 + sink.putLong(raw1);
102 + sink.putLong(raw2);
103 + }
104 +
105 + @Override
106 + public U128 inverse() {
107 + return U128.of(~raw1, ~raw2);
108 + }
109 +
110 + @Override
111 + public U128 or(U128 other) {
112 + return U128.of(raw1 | other.raw1, raw2 | other.raw2);
113 + }
114 +
115 + @Override
116 + public U128 and(U128 other) {
117 + return U128.of(raw1 & other.raw1, raw2 & other.raw2);
118 + }
119 +
120 + @Override
121 + public U128 xor(U128 other) {
122 + return U128.of(raw1 ^ other.raw1, raw2 ^ other.raw2);
123 + }
124 +
125 + @Override
126 + public int prefixBits(int numBits) {
127 + return HashValueUtils.prefixBits(this.raw1, numBits);
128 + }
129 +
130 + @Override
131 + public U128 combineWithValue(U128 value, int keyBits) {
132 + return U128.of(
133 + HashValueUtils.combineWithValue(this.raw1, value.raw1, Math.min(64, keyBits)),
134 + HashValueUtils.combineWithValue(this.raw2, value.raw2, Math.max(0,keyBits-64))
135 + );
136 + }
137 +}
1 +/**
2 + * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 + * University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package org.projectfloodlight.openflow.types;
19 +
20 +import org.jboss.netty.buffer.ChannelBuffer;
21 +import org.projectfloodlight.openflow.exceptions.OFParseError;
22 +import org.projectfloodlight.openflow.protocol.OFMessageReader;
23 +import org.projectfloodlight.openflow.protocol.Writeable;
24 +
25 +import com.google.common.hash.PrimitiveSink;
26 +import com.google.common.primitives.Ints;
27 +
28 +public class U16 implements Writeable, OFValueType<U16> {
29 + private final static short ZERO_VAL = 0;
30 + public final static U16 ZERO = new U16(ZERO_VAL);
31 +
32 + private static final short NO_MASK_VAL = (short)0xFFff;
33 + public final static U16 NO_MASK = new U16(NO_MASK_VAL);
34 + public static final U16 FULL_MASK = ZERO;
35 +
36 + public static int f(final short i) {
37 + return i & 0xffff;
38 + }
39 +
40 + public static short t(final int l) {
41 + return (short) l;
42 + }
43 +
44 + private final short raw;
45 +
46 + private U16(short raw) {
47 + this.raw = raw;
48 + }
49 +
50 + public static final U16 of(int value) {
51 + return ofRaw(t(value));
52 + }
53 +
54 + public static final U16 ofRaw(short raw) {
55 + if(raw == ZERO_VAL)
56 + return ZERO;
57 + return new U16(raw);
58 + }
59 +
60 + public int getValue() {
61 + return f(raw);
62 + }
63 +
64 + public short getRaw() {
65 + return raw;
66 + }
67 +
68 + @Override
69 + public String toString() {
70 + return String.format("0x%04x", raw);
71 + }
72 +
73 + @Override
74 + public int hashCode() {
75 + final int prime = 31;
76 + int result = 1;
77 + result = prime * result + raw;
78 + return result;
79 + }
80 +
81 + @Override
82 + public boolean equals(Object obj) {
83 + if (this == obj)
84 + return true;
85 + if (obj == null)
86 + return false;
87 + if (getClass() != obj.getClass())
88 + return false;
89 + U16 other = (U16) obj;
90 + if (raw != other.raw)
91 + return false;
92 + return true;
93 + }
94 +
95 +
96 + @Override
97 + public void writeTo(ChannelBuffer bb) {
98 + bb.writeShort(raw);
99 + }
100 +
101 +
102 + public final static Reader READER = new Reader();
103 +
104 + private static class Reader implements OFMessageReader<U16> {
105 + @Override
106 + public U16 readFrom(ChannelBuffer bb) throws OFParseError {
107 + return ofRaw(bb.readShort());
108 + }
109 + }
110 +
111 + @Override
112 + public int getLength() {
113 + return 2;
114 + }
115 +
116 + @Override
117 + public U16 applyMask(U16 mask) {
118 + return ofRaw( (short) (raw & mask.raw));
119 + }
120 +
121 + @Override
122 + public int compareTo(U16 o) {
123 + return Ints.compare(f(raw), f(o.raw));
124 + }
125 +
126 + @Override
127 + public void putTo(PrimitiveSink sink) {
128 + sink.putShort(raw);
129 + }
130 +}
1 +/**
2 + * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 + * University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package org.projectfloodlight.openflow.types;
19 +
20 +import org.jboss.netty.buffer.ChannelBuffer;
21 +import org.projectfloodlight.openflow.exceptions.OFParseError;
22 +import org.projectfloodlight.openflow.protocol.OFMessageReader;
23 +import org.projectfloodlight.openflow.protocol.Writeable;
24 +
25 +import com.google.common.hash.PrimitiveSink;
26 +import com.google.common.primitives.UnsignedInts;
27 +
28 +public class U32 implements Writeable, OFValueType<U32> {
29 + private final static int ZERO_VAL = 0;
30 + public final static U32 ZERO = new U32(ZERO_VAL);
31 +
32 + private static final int NO_MASK_VAL = 0xFFffFFff;
33 + public final static U32 NO_MASK = new U32(NO_MASK_VAL);
34 + public static final U32 FULL_MASK = ZERO;
35 +
36 + private final int raw;
37 +
38 + private U32(int raw) {
39 + this.raw = raw;
40 + }
41 +
42 + public static U32 of(long value) {
43 + return ofRaw(U32.t(value));
44 + }
45 +
46 + public static U32 ofRaw(int raw) {
47 + if(raw == ZERO_VAL)
48 + return ZERO;
49 + if(raw == NO_MASK_VAL)
50 + return NO_MASK;
51 + return new U32(raw);
52 + }
53 +
54 + public long getValue() {
55 + return f(raw);
56 + }
57 +
58 + public int getRaw() {
59 + return raw;
60 + }
61 +
62 + @Override
63 + public String toString() {
64 + return String.format("0x%08x", raw);
65 + }
66 +
67 + @Override
68 + public int hashCode() {
69 + final int prime = 31;
70 + int result = 1;
71 + result = prime * result + raw;
72 + return result;
73 + }
74 +
75 + @Override
76 + public boolean equals(Object obj) {
77 + if (this == obj)
78 + return true;
79 + if (obj == null)
80 + return false;
81 + if (getClass() != obj.getClass())
82 + return false;
83 + U32 other = (U32) obj;
84 + if (raw != other.raw)
85 + return false;
86 +
87 + return true;
88 + }
89 +
90 + public static long f(final int i) {
91 + return i & 0xffffffffL;
92 + }
93 +
94 + public static int t(final long l) {
95 + return (int) l;
96 + }
97 +
98 + @Override
99 + public void writeTo(ChannelBuffer bb) {
100 + bb.writeInt(raw);
101 + }
102 +
103 + public final static Reader READER = new Reader();
104 +
105 + private static class Reader implements OFMessageReader<U32> {
106 + @Override
107 + public U32 readFrom(ChannelBuffer bb) throws OFParseError {
108 + return new U32(bb.readInt());
109 + }
110 + }
111 +
112 + @Override
113 + public int getLength() {
114 + return 4;
115 + }
116 +
117 + @Override
118 + public U32 applyMask(U32 mask) {
119 + return ofRaw(raw & mask.raw);
120 + }
121 +
122 + @Override
123 + public int compareTo(U32 o) {
124 + return UnsignedInts.compare(raw, o.raw);
125 + }
126 +
127 + @Override
128 + public void putTo(PrimitiveSink sink) {
129 + sink.putInt(raw);
130 + }}
1 +/**
2 + * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 + * University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package org.projectfloodlight.openflow.types;
19 +
20 +import java.math.BigInteger;
21 +
22 +import org.jboss.netty.buffer.ChannelBuffer;
23 +import org.projectfloodlight.openflow.exceptions.OFParseError;
24 +import org.projectfloodlight.openflow.protocol.OFMessageReader;
25 +import org.projectfloodlight.openflow.protocol.Writeable;
26 +
27 +import com.google.common.hash.PrimitiveSink;
28 +import com.google.common.primitives.UnsignedLongs;
29 +
30 +public class U64 implements Writeable, OFValueType<U64>, HashValue<U64> {
31 + private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
32 + private final static long ZERO_VAL = 0;
33 + public final static U64 ZERO = new U64(ZERO_VAL);
34 +
35 + private static final long NO_MASK_VAL = 0xFFffFFffFFffFFffL;
36 + public final static U64 NO_MASK = new U64(NO_MASK_VAL);
37 + public static final U64 FULL_MASK = ZERO;
38 +
39 + private final long raw;
40 +
41 + protected U64(final long raw) {
42 + this.raw = raw;
43 + }
44 +
45 + public static U64 of(long raw) {
46 + return ofRaw(raw);
47 + }
48 +
49 + public static U64 ofRaw(final long raw) {
50 + if(raw == ZERO_VAL)
51 + return ZERO;
52 + return new U64(raw);
53 + }
54 +
55 + public static U64 parseHex(String hex) {
56 + return new U64(new BigInteger(hex, 16).longValue());
57 + }
58 +
59 + public long getValue() {
60 + return raw;
61 + }
62 +
63 + public BigInteger getBigInteger() {
64 + BigInteger bigInt = BigInteger.valueOf(raw & UNSIGNED_MASK);
65 + if (raw < 0) {
66 + bigInt = bigInt.setBit(Long.SIZE - 1);
67 + }
68 + return bigInt;
69 + }
70 +
71 + @Override
72 + public String toString() {
73 + return String.format("0x%016x", raw);
74 + }
75 +
76 + public static BigInteger f(final long value) {
77 + BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK);
78 + if (value < 0) {
79 + bigInt = bigInt.setBit(Long.SIZE - 1);
80 + }
81 + return bigInt;
82 + }
83 +
84 + public static long t(final BigInteger l) {
85 + return l.longValue();
86 + }
87 +
88 + @Override
89 + public int hashCode() {
90 + final int prime = 31;
91 + int result = 1;
92 + result = prime * result + (int) (raw ^ (raw >>> 32));
93 + return result;
94 + }
95 +
96 + @Override
97 + public boolean equals(Object obj) {
98 + if (this == obj)
99 + return true;
100 + if (obj == null)
101 + return false;
102 + if (getClass() != obj.getClass())
103 + return false;
104 + U64 other = (U64) obj;
105 + if (raw != other.raw)
106 + return false;
107 + return true;
108 + }
109 +
110 + @Override
111 + public int getLength() {
112 + return 8;
113 + }
114 +
115 + @Override
116 + public U64 applyMask(U64 mask) {
117 + return and(mask);
118 + }
119 +
120 + @Override
121 + public void writeTo(ChannelBuffer bb) {
122 + bb.writeLong(raw);
123 + }
124 +
125 + @Override
126 + public int compareTo(U64 o) {
127 + return UnsignedLongs.compare(raw, o.raw);
128 + }
129 +
130 + @Override
131 + public void putTo(PrimitiveSink sink) {
132 + sink.putLong(raw);
133 + }
134 +
135 + @Override
136 + public U64 inverse() {
137 + return U64.of(~raw);
138 + }
139 +
140 + @Override
141 + public U64 or(U64 other) {
142 + return U64.of(raw | other.raw);
143 + }
144 +
145 + @Override
146 + public U64 and(U64 other) {
147 + return ofRaw(raw & other.raw);
148 + }
149 + @Override
150 + public U64 xor(U64 other) {
151 + return U64.of(raw ^ other.raw);
152 + }
153 +
154 + /** return the "numBits" highest-order bits of the hash.
155 + * @param numBits number of higest-order bits to return [0-32].
156 + * @return a numberic value of the 0-32 highest-order bits.
157 + */
158 + @Override
159 + public int prefixBits(int numBits) {
160 + return HashValueUtils.prefixBits(raw, numBits);
161 + }
162 +
163 + @Override
164 + public U64 combineWithValue(U64 value, int keyBits) {
165 + return U64.of(HashValueUtils.combineWithValue(this.raw, value.raw, keyBits));
166 + }
167 +
168 + public final static Reader READER = new Reader();
169 +
170 + private static class Reader implements OFMessageReader<U64> {
171 + @Override
172 + public U64 readFrom(ChannelBuffer bb) throws OFParseError {
173 + return U64.ofRaw(bb.readLong());
174 + }
175 + }
176 +
177 +
178 +}
1 +/**
2 + * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 + * University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package org.projectfloodlight.openflow.types;
19 +
20 +import org.jboss.netty.buffer.ChannelBuffer;
21 +import org.projectfloodlight.openflow.exceptions.OFParseError;
22 +import org.projectfloodlight.openflow.protocol.OFMessageReader;
23 +import org.projectfloodlight.openflow.protocol.Writeable;
24 +
25 +import com.google.common.hash.PrimitiveSink;
26 +import com.google.common.primitives.UnsignedBytes;
27 +
28 +public class U8 implements Writeable, OFValueType<U8> {
29 + private final static byte ZERO_VAL = 0;
30 + public final static U8 ZERO = new U8(ZERO_VAL);
31 +
32 + private static final byte NO_MASK_VAL = (byte) 0xFF;
33 + public static final U8 NO_MASK = new U8(NO_MASK_VAL);
34 + public static final U8 FULL_MASK = ZERO;
35 +
36 + private final byte raw;
37 +
38 + private U8(byte raw) {
39 + this.raw = raw;
40 + }
41 +
42 + public static final U8 of(short value) {
43 + if(value == ZERO_VAL)
44 + return ZERO;
45 + if(value == NO_MASK_VAL)
46 + return NO_MASK;
47 +
48 + return new U8(t(value));
49 + }
50 +
51 + public static final U8 ofRaw(byte value) {
52 + return new U8(value);
53 + }
54 +
55 + public short getValue() {
56 + return f(raw);
57 + }
58 +
59 + public byte getRaw() {
60 + return raw;
61 + }
62 +
63 + @Override
64 + public String toString() {
65 + return String.format("0x%02x", raw);
66 + }
67 +
68 + @Override
69 + public int hashCode() {
70 + final int prime = 31;
71 + int result = 1;
72 + result = prime * result + raw;
73 + return result;
74 + }
75 +
76 + @Override
77 + public boolean equals(Object obj) {
78 + if (this == obj)
79 + return true;
80 + if (obj == null)
81 + return false;
82 + if (getClass() != obj.getClass())
83 + return false;
84 + U8 other = (U8) obj;
85 + if (raw != other.raw)
86 + return false;
87 + return true;
88 + }
89 +
90 +
91 + @Override
92 + public void writeTo(ChannelBuffer bb) {
93 + bb.writeByte(raw);
94 + }
95 +
96 + public static short f(final byte i) {
97 + return (short) (i & 0xff);
98 + }
99 +
100 + public static byte t(final short l) {
101 + return (byte) l;
102 + }
103 +
104 +
105 + public final static Reader READER = new Reader();
106 +
107 + private static class Reader implements OFMessageReader<U8> {
108 + @Override
109 + public U8 readFrom(ChannelBuffer bb) throws OFParseError {
110 + return new U8(bb.readByte());
111 + }
112 + }
113 +
114 + @Override
115 + public int getLength() {
116 + return 1;
117 + }
118 +
119 + @Override
120 + public U8 applyMask(U8 mask) {
121 + return ofRaw( (byte) (raw & mask.raw));
122 + }
123 +
124 + @Override
125 + public int compareTo(U8 o) {
126 + return UnsignedBytes.compare(raw, o.raw);
127 + }
128 +
129 + @Override
130 + public void putTo(PrimitiveSink sink) {
131 + sink.putByte(raw);
132 + }
133 + }
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import javax.annotation.concurrent.Immutable;
4 +
5 +import org.jboss.netty.buffer.ChannelBuffer;
6 +
7 +import com.google.common.hash.PrimitiveSink;
8 +import com.google.common.primitives.UnsignedInts;
9 +
10 +@Immutable
11 +public class UDF implements OFValueType<UDF> {
12 + static final int LENGTH = 4;
13 + private final int rawValue;
14 +
15 + public static final UDF ZERO = UDF.of(0x0);
16 + public static final UDF NO_MASK = UDF.of(0xFFFFFFFF);
17 + public static final UDF FULL_MASK = UDF.of(0x00000000);
18 +
19 + private UDF(final int rawValue) {
20 + this.rawValue = rawValue;
21 + }
22 +
23 + public static UDF of(final int raw) {
24 + return new UDF(raw);
25 + }
26 +
27 + public int getInt() {
28 + return rawValue;
29 + }
30 +
31 + @Override
32 + public int getLength() {
33 + return LENGTH;
34 + }
35 +
36 + @Override
37 + public int hashCode() {
38 + final int prime = 31;
39 + int result = 1;
40 + result = prime * result + rawValue;
41 + return result;
42 + }
43 +
44 + @Override
45 + public boolean equals(Object obj) {
46 + if (this == obj)
47 + return true;
48 + if (obj == null)
49 + return false;
50 + if (getClass() != obj.getClass())
51 + return false;
52 + UDF other = (UDF) obj;
53 + if (rawValue != other.rawValue)
54 + return false;
55 + return true;
56 + }
57 +
58 + @Override
59 + public String toString() {
60 + return Integer.toString(rawValue);
61 + }
62 +
63 + public void write4Bytes(ChannelBuffer c) {
64 + c.writeInt(rawValue);
65 + }
66 +
67 + public static UDF read4Bytes(ChannelBuffer c) {
68 + return UDF.of(c.readInt());
69 + }
70 +
71 + @Override
72 + public UDF applyMask(UDF mask) {
73 + return UDF.of(this.rawValue & mask.rawValue);
74 + }
75 +
76 + @Override
77 + public int compareTo(UDF o) {
78 + return UnsignedInts.compare(rawValue, o.rawValue);
79 + }
80 +
81 + @Override
82 + public void putTo(PrimitiveSink sink) {
83 + sink.putInt(rawValue);
84 + }
85 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import javax.annotation.concurrent.Immutable;
4 +
5 +import org.jboss.netty.buffer.ChannelBuffer;
6 +
7 +import com.google.common.hash.PrimitiveSink;
8 +import com.google.common.primitives.UnsignedInts;
9 +
10 +@Immutable
11 +public class VRF implements OFValueType<VRF> {
12 + static final int LENGTH = 4;
13 + private final int rawValue;
14 +
15 + public static final VRF ZERO = VRF.of(0x0);
16 + public static final VRF NO_MASK = VRF.of(0xFFFFFFFF);
17 + public static final VRF FULL_MASK = VRF.of(0x00000000);
18 +
19 + private VRF(final int rawValue) {
20 + this.rawValue = rawValue;
21 + }
22 +
23 + public static VRF of(final int raw) {
24 + return new VRF(raw);
25 + }
26 +
27 + public int getInt() {
28 + return rawValue;
29 + }
30 +
31 + @Override
32 + public int getLength() {
33 + return LENGTH;
34 + }
35 +
36 + @Override
37 + public int hashCode() {
38 + final int prime = 31;
39 + int result = 1;
40 + result = prime * result + rawValue;
41 + return result;
42 + }
43 +
44 + @Override
45 + public boolean equals(Object obj) {
46 + if (this == obj)
47 + return true;
48 + if (obj == null)
49 + return false;
50 + if (getClass() != obj.getClass())
51 + return false;
52 + VRF other = (VRF) obj;
53 + if (rawValue != other.rawValue)
54 + return false;
55 + return true;
56 + }
57 +
58 + @Override
59 + public String toString() {
60 + return Integer.toString(rawValue);
61 + }
62 +
63 + public void write4Bytes(ChannelBuffer c) {
64 + c.writeInt(rawValue);
65 + }
66 +
67 + public static VRF read4Bytes(ChannelBuffer c) {
68 + return VRF.of(c.readInt());
69 + }
70 +
71 + @Override
72 + public VRF applyMask(VRF mask) {
73 + return VRF.of(this.rawValue & mask.rawValue);
74 + }
75 +
76 + @Override
77 + public int compareTo(VRF o) {
78 + return UnsignedInts.compare(rawValue, o.rawValue);
79 + }
80 +
81 + @Override
82 + public void putTo(PrimitiveSink sink) {
83 + sink.putInt(rawValue);
84 + }
85 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.projectfloodlight.openflow.exceptions.OFParseError;
5 +
6 +import com.google.common.hash.PrimitiveSink;
7 +import com.google.common.primitives.UnsignedBytes;
8 +
9 +public class VlanPcp implements OFValueType<VlanPcp> {
10 +
11 + private static final byte VALIDATION_MASK = 0x07;
12 + private static final byte NONE_VAL = 0x00;
13 + static final int LENGTH = 1;
14 +
15 + private final byte pcp;
16 +
17 + public static final VlanPcp NONE = new VlanPcp(NONE_VAL);
18 + public static final VlanPcp NO_MASK = new VlanPcp((byte)0xFF);
19 + public static final VlanPcp FULL_MASK = VlanPcp.of((byte)0x0);
20 +
21 + private VlanPcp(byte pcp) {
22 + this.pcp = pcp;
23 + }
24 +
25 + public static VlanPcp of(byte pcp) {
26 + if ((pcp & VALIDATION_MASK) != pcp)
27 + throw new IllegalArgumentException("Illegal VLAN PCP value: " + pcp);
28 + return new VlanPcp(pcp);
29 + }
30 +
31 + @Override
32 + public boolean equals(Object obj) {
33 + if (!(obj instanceof VlanPcp))
34 + return false;
35 + VlanPcp other = (VlanPcp)obj;
36 + if (other.pcp != this.pcp)
37 + return false;
38 + return true;
39 + }
40 +
41 + @Override
42 + public int hashCode() {
43 + int prime = 20173;
44 + return this.pcp * prime;
45 + }
46 +
47 + @Override
48 + public String toString() {
49 + return "0x" + Integer.toHexString(pcp);
50 + }
51 +
52 + public byte getValue() {
53 + return pcp;
54 + }
55 +
56 + @Override
57 + public int getLength() {
58 + return LENGTH;
59 + }
60 +
61 + public void writeByte(ChannelBuffer c) {
62 + c.writeByte(this.pcp);
63 + }
64 +
65 + public static VlanPcp readByte(ChannelBuffer c) throws OFParseError {
66 + return VlanPcp.of((byte)(c.readUnsignedByte() & 0xFF));
67 + }
68 +
69 + @Override
70 + public VlanPcp applyMask(VlanPcp mask) {
71 + return VlanPcp.of((byte)(this.pcp & mask.pcp));
72 + }
73 +
74 + @Override
75 + public int compareTo(VlanPcp o) {
76 + return UnsignedBytes.compare(pcp, o.pcp);
77 + }
78 + @Override
79 + public void putTo(PrimitiveSink sink) {
80 + sink.putByte(pcp);
81 + }
82 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import java.util.Arrays;
4 +
5 +import org.jboss.netty.buffer.ChannelBuffer;
6 +import org.projectfloodlight.openflow.exceptions.OFParseError;
7 +
8 +import com.google.common.hash.PrimitiveSink;
9 +import com.google.common.primitives.Shorts;
10 +
11 +/** Represents an 802.1Q Vlan VID (12 bits).
12 + *
13 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
14 + *
15 + */
16 +public class VlanVid implements OFValueType<VlanVid> {
17 +
18 + private static final short VALIDATION_MASK = 0x0FFF;
19 + private static final short ZERO_VAL = 0x0000;
20 + final static int LENGTH = 2;
21 +
22 + /** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
23 + public static final VlanVid ZERO = new VlanVid(ZERO_VAL);
24 +
25 + /** for use with masking operations */
26 + public static final VlanVid NO_MASK = new VlanVid((short)0xFFFF);
27 + public static final VlanVid FULL_MASK = ZERO;
28 +
29 + private final short vid;
30 +
31 + private VlanVid(short vid) {
32 + this.vid = vid;
33 + }
34 +
35 + public static VlanVid ofVlan(int vid) {
36 + if (vid == NO_MASK.vid)
37 + return NO_MASK;
38 + if ((vid & VALIDATION_MASK) != vid)
39 + throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
40 + return new VlanVid((short) vid);
41 + }
42 +
43 + /** @return the actual VLAN tag this vid identifies */
44 + public short getVlan() {
45 + return vid;
46 + }
47 +
48 + @Override
49 + public boolean equals(Object obj) {
50 + if (!(obj instanceof VlanVid))
51 + return false;
52 + VlanVid other = (VlanVid)obj;
53 + if (other.vid != this.vid)
54 + return false;
55 + return true;
56 + }
57 +
58 + @Override
59 + public int hashCode() {
60 + int prime = 13873;
61 + return this.vid * prime;
62 + }
63 +
64 + @Override
65 + public String toString() {
66 + return "0x" + Integer.toHexString(vid);
67 + }
68 +
69 + @Override
70 + public int getLength() {
71 + return LENGTH;
72 + }
73 +
74 + private volatile byte[] bytesCache = null;
75 +
76 + public byte[] getBytes() {
77 + if (bytesCache == null) {
78 + synchronized (this) {
79 + if (bytesCache == null) {
80 + bytesCache =
81 + new byte[] { (byte) ((vid >>> 8) & 0xFF),
82 + (byte) ((vid >>> 0) & 0xFF) };
83 + }
84 + }
85 + }
86 + return Arrays.copyOf(bytesCache, bytesCache.length);
87 + }
88 +
89 + public void write2Bytes(ChannelBuffer c) {
90 + c.writeShort(this.vid);
91 + }
92 +
93 + public void write2BytesOF10(ChannelBuffer c) {
94 + c.writeShort(this.getVlan());
95 + }
96 +
97 + public static VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
98 + return VlanVid.ofVlan(c.readShort());
99 + }
100 +
101 + @Override
102 + public VlanVid applyMask(VlanVid mask) {
103 + return VlanVid.ofVlan((short)(this.vid & mask.vid));
104 + }
105 +
106 + @Override
107 + public int compareTo(VlanVid o) {
108 + return Shorts.compare(vid, o.vid);
109 + }
110 +
111 + @Override
112 + public void putTo(PrimitiveSink sink) {
113 + sink.putShort(vid);
114 + }
115 +}
1 +package org.projectfloodlight.openflow.util;
2 +
3 +import java.util.List;
4 +
5 +import org.projectfloodlight.openflow.protocol.OFFlowMod;
6 +import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
7 +import org.projectfloodlight.openflow.protocol.OFInstructionType;
8 +import org.projectfloodlight.openflow.protocol.OFVersion;
9 +import org.projectfloodlight.openflow.protocol.action.OFAction;
10 +import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
11 +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
12 +
13 +import com.google.common.collect.ImmutableList;
14 +
15 +public class ActionUtils {
16 + private ActionUtils() {}
17 +
18 + public static List<OFAction> getActions(OFFlowStatsEntry e) {
19 + if(e.getVersion() == OFVersion.OF_10) {
20 + return e.getActions();
21 + } else {
22 + for(OFInstruction i: e.getInstructions()) {
23 + if(i.getType() == OFInstructionType.APPLY_ACTIONS) {
24 + return ((OFInstructionApplyActions) i).getActions();
25 + }
26 + }
27 + return ImmutableList.of();
28 + }
29 + }
30 +
31 + public static List<OFAction> getActions(OFFlowMod e) {
32 + if(e.getVersion() == OFVersion.OF_10) {
33 + return e.getActions();
34 + } else {
35 + for(OFInstruction i: e.getInstructions()) {
36 + if(i.getType() == OFInstructionType.APPLY_ACTIONS) {
37 + return ((OFInstructionApplyActions) i).getActions();
38 + }
39 + }
40 + return ImmutableList.of();
41 + }
42 + }
43 +}
1 +package org.projectfloodlight.openflow.util;
2 +
3 +import java.util.List;
4 +
5 +import org.jboss.netty.buffer.ChannelBuffer;
6 +import org.projectfloodlight.openflow.exceptions.OFParseError;
7 +import org.projectfloodlight.openflow.protocol.OFMessageReader;
8 +import org.projectfloodlight.openflow.protocol.Writeable;
9 +import org.slf4j.Logger;
10 +import org.slf4j.LoggerFactory;
11 +
12 +import com.google.common.base.Charsets;
13 +import com.google.common.collect.ImmutableList;
14 +import com.google.common.collect.ImmutableList.Builder;
15 +
16 +/**
17 + * Collection of helper functions for reading and writing into ChannelBuffers
18 + *
19 + * @author capveg
20 + */
21 +
22 +public class ChannelUtils {
23 + private static final Logger logger = LoggerFactory.getLogger(ChannelUtils.class);
24 + public static String readFixedLengthString(ChannelBuffer bb, int length) {
25 + byte[] dst = new byte[length];
26 + bb.readBytes(dst, 0, length);
27 + int validLength = 0;
28 + for (validLength = 0; validLength < length; validLength++) {
29 + if (dst[validLength] == 0)
30 + break;
31 + }
32 + return new String(dst, 0, validLength, Charsets.US_ASCII);
33 + }
34 +
35 + public static void writeFixedLengthString(ChannelBuffer bb, String string,
36 + int length) {
37 + int l = string.length();
38 + if (l > length) {
39 + throw new IllegalArgumentException("Error writing string: length="
40 + + l + " > max Length=" + length);
41 + }
42 + bb.writeBytes(string.getBytes(Charsets.US_ASCII));
43 + if (l < length) {
44 + bb.writeZero(length - l);
45 + }
46 + }
47 +
48 + static public byte[] readBytes(final ChannelBuffer bb, final int length) {
49 + byte byteArray[] = new byte[length];
50 + bb.readBytes(byteArray);
51 + return byteArray;
52 + }
53 +
54 + static public void writeBytes(final ChannelBuffer bb,
55 + final byte byteArray[]) {
56 + bb.writeBytes(byteArray);
57 + }
58 +
59 + public static <T> List<T> readList(ChannelBuffer bb, int length, OFMessageReader<T> reader) throws OFParseError {
60 + int end = bb.readerIndex() + length;
61 + Builder<T> builder = ImmutableList.<T>builder();
62 + if(logger.isTraceEnabled())
63 + logger.trace("readList(length={}, reader={})", length, reader.getClass());
64 + while(bb.readerIndex() < end) {
65 + T read = reader.readFrom(bb);
66 + if(logger.isTraceEnabled())
67 + logger.trace("readList: read={}, left={}", read, end - bb.readerIndex());
68 + builder.add(read);
69 + }
70 + if(bb.readerIndex() != end) {
71 + throw new IllegalStateException("Overread length: length="+length + " overread by "+ (bb.readerIndex() - end) + " reader: "+reader);
72 + }
73 + return builder.build();
74 + }
75 +
76 + public static void writeList(ChannelBuffer bb, List<? extends Writeable> writeables) {
77 + for(Writeable w: writeables)
78 + w.writeTo(bb);
79 + }
80 +}
1 +package org.projectfloodlight.openflow.util;
2 +
3 +import java.util.List;
4 +
5 +import org.projectfloodlight.openflow.types.PrimitiveSinkable;
6 +
7 +import com.google.common.hash.PrimitiveSink;
8 +
9 +public class FunnelUtils {
10 + public static void putList(List<? extends PrimitiveSinkable> sinkables, PrimitiveSink sink) {
11 + for(PrimitiveSinkable p: sinkables)
12 + p.putTo(sink);
13 + }
14 +}
1 +/**
2 + * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 + * University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package org.projectfloodlight.openflow.util;
19 +
20 +import org.projectfloodlight.openflow.types.U8;
21 +
22 +public class HexString {
23 + /**
24 + * Convert a string of bytes to a ':' separated hex string
25 + *
26 + * @param bytes
27 + * @return "0f:ca:fe:de:ad:be:ef"
28 + */
29 + public static String toHexString(final byte[] bytes) {
30 + int i;
31 + String ret = "";
32 + String tmp;
33 + for (i = 0; i < bytes.length; i++) {
34 + if (i > 0)
35 + ret += ":";
36 + tmp = Integer.toHexString(U8.f(bytes[i]));
37 + if (tmp.length() == 1)
38 + ret += "0";
39 + ret += tmp;
40 + }
41 + return ret;
42 + }
43 +
44 + public static String toHexString(final long val, final int padTo) {
45 + char arr[] = Long.toHexString(val).toCharArray();
46 + String ret = "";
47 + // prepend the right number of leading zeros
48 + int i = 0;
49 + for (; i < (padTo * 2 - arr.length); i++) {
50 + ret += "0";
51 + if ((i % 2) != 0)
52 + ret += ":";
53 + }
54 + for (int j = 0; j < arr.length; j++) {
55 + ret += arr[j];
56 + if ((((i + j) % 2) != 0) && (j < (arr.length - 1)))
57 + ret += ":";
58 + }
59 + return ret;
60 + }
61 +
62 + public static String toHexString(final long val) {
63 + return toHexString(val, 8);
64 + }
65 +
66 + /**
67 + * Convert a string of hex values into a string of bytes
68 + *
69 + * @param values
70 + * "0f:ca:fe:de:ad:be:ef"
71 + * @return [15, 5 ,2, 5, 17]
72 + * @throws NumberFormatException
73 + * If the string can not be parsed
74 + */
75 + public static byte[] fromHexString(final String values) throws NumberFormatException {
76 + String[] octets = values.split(":");
77 + byte[] ret = new byte[octets.length];
78 +
79 + for (int i = 0; i < octets.length; i++) {
80 + if (octets[i].length() > 2)
81 + throw new NumberFormatException("Invalid octet length");
82 + ret[i] = Integer.valueOf(octets[i], 16).byteValue();
83 + }
84 + return ret;
85 + }
86 +
87 + public static long toLong(String value) throws NumberFormatException {
88 + String[] octets = value.split(":");
89 + if (octets.length > 8)
90 + throw new NumberFormatException("Input string is too big to fit in long: " + value);
91 + long l = 0;
92 + for (String octet: octets) {
93 + if (octet.length() > 2)
94 + throw new NumberFormatException("Each colon-separated byte component must consist of 1 or 2 hex digits: " + value);
95 + short s = Short.parseShort(octet, 16);
96 + l = (l << 8) + s;
97 + }
98 + return l;
99 + }
100 +}
1 +/**
2 + * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 + * University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package org.projectfloodlight.openflow.util;
19 +
20 +import java.util.LinkedHashMap;
21 +
22 +public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
23 + private static final long serialVersionUID = -2964986094089626647L;
24 + protected int maximumCapacity;
25 +
26 + public LRULinkedHashMap(final int initialCapacity, final int maximumCapacity) {
27 + super(initialCapacity, 0.75f, true);
28 + this.maximumCapacity = maximumCapacity;
29 + }
30 +
31 + public LRULinkedHashMap(final int maximumCapacity) {
32 + super(16, 0.75f, true);
33 + this.maximumCapacity = maximumCapacity;
34 + }
35 +
36 + @Override
37 + protected boolean removeEldestEntry(final java.util.Map.Entry<K, V> eldest) {
38 + if (this.size() > maximumCapacity)
39 + return true;
40 + return false;
41 + }
42 +}
1 +package org.projectfloodlight.openflow.util;
2 +
3 +import java.io.IOException;
4 +import java.io.InputStream;
5 +import java.io.OutputStream;
6 +import java.nio.ByteBuffer;
7 +import java.nio.ByteOrder;
8 +import java.nio.channels.GatheringByteChannel;
9 +import java.nio.channels.ScatteringByteChannel;
10 +import java.nio.charset.Charset;
11 +
12 +import org.jboss.netty.buffer.ChannelBuffer;
13 +import org.jboss.netty.buffer.ChannelBufferFactory;
14 +import org.jboss.netty.buffer.ChannelBufferIndexFinder;
15 +
16 +public class LengthCountingPseudoChannelBuffer implements ChannelBuffer {
17 +
18 + int writerIndex = 0;
19 + private int markedWriterIndex;
20 +
21 + @Override
22 + public ChannelBufferFactory factory() {
23 + return null;
24 + }
25 +
26 + @Override
27 + public int capacity() {
28 + return Integer.MAX_VALUE;
29 + }
30 +
31 + @Override
32 + public ByteOrder order() {
33 + return ByteOrder.BIG_ENDIAN;
34 + }
35 +
36 + @Override
37 + public boolean isDirect() {
38 + return true;
39 + }
40 +
41 + @Override
42 + public int readerIndex() {
43 + return 0;
44 + }
45 +
46 + @Override
47 + public void readerIndex(int readerIndex) {
48 + throw new UnsupportedOperationException();
49 + }
50 +
51 + @Override
52 + public int writerIndex() {
53 + return writerIndex;
54 + }
55 +
56 + @Override
57 + public void writerIndex(int writerIndex) {
58 + this.writerIndex = writerIndex;
59 + }
60 +
61 + @Override
62 + public void setIndex(int readerIndex, int writerIndex) {
63 + if(readerIndex != 0)
64 + throw new UnsupportedOperationException();
65 + this.writerIndex = writerIndex;
66 + }
67 +
68 + @Override
69 + public int readableBytes() {
70 + return writerIndex;
71 + }
72 +
73 + @Override
74 + public int writableBytes() {
75 + return Integer.MAX_VALUE - writerIndex;
76 + }
77 +
78 + @Override
79 + public boolean readable() {
80 + return writerIndex > 0;
81 + }
82 +
83 + @Override
84 + public boolean writable() {
85 + return writerIndex < Integer.MAX_VALUE;
86 + }
87 +
88 + @Override
89 + public void clear() {
90 + writerIndex = 0;
91 +
92 + }
93 +
94 + @Override
95 + public void markReaderIndex() {
96 + }
97 +
98 + @Override
99 + public void resetReaderIndex() {
100 + }
101 +
102 + @Override
103 + public void markWriterIndex() {
104 + markedWriterIndex = writerIndex;
105 + }
106 +
107 + @Override
108 + public void resetWriterIndex() {
109 + writerIndex = markedWriterIndex;
110 + }
111 +
112 + @Override
113 + public void discardReadBytes() {
114 + throw new UnsupportedOperationException();
115 + }
116 +
117 + @Override
118 + public void ensureWritableBytes(int writableBytes) {
119 + if(!((Integer.MAX_VALUE - writableBytes) > writerIndex))
120 + throw new IllegalStateException();
121 + }
122 +
123 + @Override
124 + public byte getByte(int index) {
125 + throw new UnsupportedOperationException();
126 + }
127 +
128 + @Override
129 + public short getUnsignedByte(int index) {
130 + throw new UnsupportedOperationException();
131 + }
132 +
133 + @Override
134 + public short getShort(int index) {
135 + throw new UnsupportedOperationException();
136 + }
137 +
138 + @Override
139 + public int getUnsignedShort(int index) {
140 + throw new UnsupportedOperationException();
141 + }
142 +
143 + @Override
144 + public int getMedium(int index) {
145 + throw new UnsupportedOperationException();
146 + }
147 +
148 + @Override
149 + public int getUnsignedMedium(int index) {
150 + throw new UnsupportedOperationException();
151 + }
152 +
153 + @Override
154 + public int getInt(int index) {
155 + throw new UnsupportedOperationException();
156 + }
157 +
158 + @Override
159 + public long getUnsignedInt(int index) {
160 + throw new UnsupportedOperationException();
161 + }
162 +
163 + @Override
164 + public long getLong(int index) {
165 + throw new UnsupportedOperationException();
166 + }
167 +
168 + @Override
169 + public char getChar(int index) {
170 + throw new UnsupportedOperationException();
171 + }
172 +
173 + @Override
174 + public float getFloat(int index) {
175 + throw new UnsupportedOperationException();
176 + }
177 +
178 + @Override
179 + public double getDouble(int index) {
180 + throw new UnsupportedOperationException();
181 + }
182 +
183 + @Override
184 + public void getBytes(int index, ChannelBuffer dst) {
185 + throw new UnsupportedOperationException();
186 + }
187 +
188 + @Override
189 + public void getBytes(int index, ChannelBuffer dst, int length) {
190 + throw new UnsupportedOperationException();
191 + }
192 +
193 + @Override
194 + public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
195 + throw new UnsupportedOperationException();
196 + }
197 +
198 + @Override
199 + public void getBytes(int index, byte[] dst) {
200 + throw new UnsupportedOperationException();
201 + }
202 +
203 + @Override
204 + public void getBytes(int index, byte[] dst, int dstIndex, int length) {
205 + throw new UnsupportedOperationException();
206 + }
207 +
208 + @Override
209 + public void getBytes(int index, ByteBuffer dst) {
210 + throw new UnsupportedOperationException();
211 + }
212 +
213 + @Override
214 + public void getBytes(int index, OutputStream out, int length)
215 + throws IOException {
216 + throw new UnsupportedOperationException();
217 + }
218 +
219 + @Override
220 + public int getBytes(int index, GatheringByteChannel out, int length)
221 + throws IOException {
222 + throw new UnsupportedOperationException();
223 + }
224 +
225 + @Override
226 + public void setByte(int index, int value) {
227 + }
228 +
229 + @Override
230 + public void setShort(int index, int value) {
231 + }
232 +
233 + @Override
234 + public void setMedium(int index, int value) {
235 + }
236 +
237 + @Override
238 + public void setInt(int index, int value) {
239 + }
240 +
241 + @Override
242 + public void setLong(int index, long value) {
243 + }
244 +
245 + @Override
246 + public void setChar(int index, int value) {
247 + }
248 +
249 + @Override
250 + public void setFloat(int index, float value) {
251 + }
252 +
253 + @Override
254 + public void setDouble(int index, double value) {
255 + }
256 +
257 + @Override
258 + public void setBytes(int index, ChannelBuffer src) {
259 + }
260 +
261 + @Override
262 + public void setBytes(int index, ChannelBuffer src, int length) {
263 + }
264 +
265 + @Override
266 + public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
267 + }
268 +
269 + @Override
270 + public void setBytes(int index, byte[] src) {
271 + }
272 +
273 + @Override
274 + public void setBytes(int index, byte[] src, int srcIndex, int length) {
275 + }
276 +
277 + @Override
278 + public void setBytes(int index, ByteBuffer src) {
279 +
280 + }
281 +
282 + @Override
283 + public int setBytes(int index, InputStream in, int length)
284 + throws IOException {
285 + throw new UnsupportedOperationException();
286 + }
287 +
288 + @Override
289 + public int setBytes(int index, ScatteringByteChannel in, int length)
290 + throws IOException {
291 + throw new UnsupportedOperationException();
292 + }
293 +
294 + @Override
295 + public void setZero(int index, int length) {
296 + }
297 +
298 + @Override
299 + public byte readByte() {
300 + throw new UnsupportedOperationException();
301 + }
302 +
303 + @Override
304 + public short readUnsignedByte() {
305 + throw new UnsupportedOperationException();
306 + }
307 +
308 + @Override
309 + public short readShort() {
310 + throw new UnsupportedOperationException();
311 + }
312 +
313 + @Override
314 + public int readUnsignedShort() {
315 + throw new UnsupportedOperationException();
316 + }
317 +
318 + @Override
319 + public int readMedium() {
320 + throw new UnsupportedOperationException();
321 + }
322 +
323 + @Override
324 + public int readUnsignedMedium() {
325 + throw new UnsupportedOperationException();
326 + }
327 +
328 + @Override
329 + public int readInt() {
330 + throw new UnsupportedOperationException();
331 + }
332 +
333 + @Override
334 + public long readUnsignedInt() {
335 + throw new UnsupportedOperationException();
336 + }
337 +
338 + @Override
339 + public long readLong() {
340 + throw new UnsupportedOperationException();
341 + }
342 +
343 + @Override
344 + public char readChar() {
345 + throw new UnsupportedOperationException();
346 + }
347 +
348 + @Override
349 + public float readFloat() {
350 + throw new UnsupportedOperationException();
351 + }
352 +
353 + @Override
354 + public double readDouble() {
355 + throw new UnsupportedOperationException();
356 + }
357 +
358 + @Override
359 + public ChannelBuffer readBytes(int length) {
360 + throw new UnsupportedOperationException();
361 + }
362 +
363 + @Override
364 + @Deprecated
365 + public ChannelBuffer readBytes(ChannelBufferIndexFinder indexFinder) {
366 + throw new UnsupportedOperationException();
367 + }
368 +
369 + @Override
370 + public ChannelBuffer readSlice(int length) {
371 + throw new UnsupportedOperationException();
372 + }
373 +
374 + @Override
375 + @Deprecated
376 + public
377 + ChannelBuffer readSlice(ChannelBufferIndexFinder indexFinder) {
378 + throw new UnsupportedOperationException();
379 + }
380 +
381 + @Override
382 + public void readBytes(ChannelBuffer dst) {
383 + throw new UnsupportedOperationException();
384 + }
385 +
386 + @Override
387 + public void readBytes(ChannelBuffer dst, int length) {
388 + throw new UnsupportedOperationException();
389 + }
390 +
391 + @Override
392 + public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
393 + throw new UnsupportedOperationException();
394 + }
395 +
396 + @Override
397 + public void readBytes(byte[] dst) {
398 + throw new UnsupportedOperationException();
399 + }
400 +
401 + @Override
402 + public void readBytes(byte[] dst, int dstIndex, int length) {
403 + throw new UnsupportedOperationException();
404 + }
405 +
406 + @Override
407 + public void readBytes(ByteBuffer dst) {
408 + throw new UnsupportedOperationException();
409 + }
410 +
411 + @Override
412 + public void readBytes(OutputStream out, int length) throws IOException {
413 + throw new UnsupportedOperationException();
414 + }
415 +
416 + @Override
417 + public int readBytes(GatheringByteChannel out, int length)
418 + throws IOException {
419 + throw new UnsupportedOperationException();
420 + }
421 +
422 + @Override
423 + public void skipBytes(int length) {
424 + throw new UnsupportedOperationException();
425 + }
426 +
427 + @Override
428 + @Deprecated
429 + public int skipBytes(ChannelBufferIndexFinder indexFinder) {
430 + throw new UnsupportedOperationException();
431 + }
432 +
433 + @Override
434 + public void writeByte(int value) {
435 + writerIndex++;
436 + }
437 +
438 + @Override
439 + public void writeShort(int value) {
440 + writerIndex += 2;
441 +}
442 +
443 +@Override
444 +public void writeMedium(int value) {
445 + writerIndex += 3;
446 +}
447 +
448 +@Override
449 +public void writeInt(int value) {
450 + writerIndex += 4;
451 +}
452 +
453 +@Override
454 +public void writeLong(long value) {
455 + writerIndex += 8;
456 +}
457 +
458 +
459 + @Override
460 + public void writeChar(int value) {
461 + writeShort(value);
462 + }
463 +
464 + @Override
465 + public void writeFloat(float value) {
466 + writeInt(Float.floatToIntBits(value));
467 + }
468 +
469 + @Override
470 + public void writeDouble(double value) {
471 + writeLong(Double.doubleToLongBits(value));
472 +
473 + }
474 +
475 + @Override
476 + public void writeBytes(ChannelBuffer src) {
477 + writerIndex += src.readableBytes();
478 +
479 + }
480 +
481 + @Override
482 + public void writeBytes(ChannelBuffer src, int length) {
483 + writerIndex += src.readableBytes();
484 +
485 + }
486 +
487 + @Override
488 + public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
489 + writerIndex += length;
490 + }
491 +
492 + @Override
493 + public void writeBytes(byte[] src) {
494 + writerIndex += src.length;
495 +
496 + }
497 +
498 + @Override
499 + public void writeBytes(byte[] src, int srcIndex, int length) {
500 + writerIndex += length;
501 + }
502 +
503 + @Override
504 + public void writeBytes(ByteBuffer src) {
505 + writerIndex += src.remaining();
506 +
507 + }
508 +
509 + @Override
510 + public int writeBytes(InputStream in, int length) throws IOException {
511 + writerIndex += length;
512 + return length;
513 + }
514 +
515 + @Override
516 + public int writeBytes(ScatteringByteChannel in, int length)
517 + throws IOException {
518 + writerIndex += length;
519 + return length;
520 + }
521 +
522 + @Override
523 + public void writeZero(int length) {
524 + writerIndex += length;
525 +
526 + }
527 +
528 + @Override
529 + public int indexOf(int fromIndex, int toIndex, byte value) {
530 + throw new UnsupportedOperationException();
531 + }
532 +
533 + @Override
534 + public int indexOf(int fromIndex, int toIndex,
535 + ChannelBufferIndexFinder indexFinder) {
536 + throw new UnsupportedOperationException();
537 + }
538 +
539 + @Override
540 + public int bytesBefore(byte value) {
541 + throw new UnsupportedOperationException();
542 + }
543 +
544 + @Override
545 + public int bytesBefore(ChannelBufferIndexFinder indexFinder) {
546 + throw new UnsupportedOperationException();
547 + }
548 +
549 + @Override
550 + public int bytesBefore(int length, byte value) {
551 + throw new UnsupportedOperationException();
552 + }
553 +
554 + @Override
555 + public int bytesBefore(int length, ChannelBufferIndexFinder indexFinder) {
556 + throw new UnsupportedOperationException();
557 + }
558 +
559 + @Override
560 + public int bytesBefore(int index, int length, byte value) {
561 + throw new UnsupportedOperationException();
562 + }
563 +
564 + @Override
565 + public int bytesBefore(int index, int length,
566 + ChannelBufferIndexFinder indexFinder) {
567 + throw new UnsupportedOperationException();
568 + }
569 +
570 + @Override
571 + public ChannelBuffer copy() {
572 + throw new UnsupportedOperationException();
573 + }
574 +
575 + @Override
576 + public ChannelBuffer copy(int index, int length) {
577 + throw new UnsupportedOperationException();
578 + }
579 +
580 + @Override
581 + public ChannelBuffer slice() {
582 + throw new UnsupportedOperationException();
583 + }
584 +
585 + @Override
586 + public ChannelBuffer slice(int index, int length) {
587 + throw new UnsupportedOperationException();
588 + }
589 +
590 + @Override
591 + public ChannelBuffer duplicate() {
592 + throw new UnsupportedOperationException();
593 + }
594 +
595 + @Override
596 + public ByteBuffer toByteBuffer() {
597 + throw new UnsupportedOperationException();
598 + }
599 +
600 + @Override
601 + public ByteBuffer toByteBuffer(int index, int length) {
602 + throw new UnsupportedOperationException();
603 + }
604 +
605 + @Override
606 + public ByteBuffer[] toByteBuffers() {
607 + throw new UnsupportedOperationException();
608 + }
609 +
610 + @Override
611 + public ByteBuffer[] toByteBuffers(int index, int length) {
612 + throw new UnsupportedOperationException();
613 + }
614 +
615 + @Override
616 + public boolean hasArray() {
617 + throw new UnsupportedOperationException();
618 + }
619 +
620 + @Override
621 + public byte[] array() {
622 + throw new UnsupportedOperationException();
623 + }
624 +
625 + @Override
626 + public int arrayOffset() {
627 + throw new UnsupportedOperationException();
628 + }
629 +
630 + @Override
631 + public String toString(Charset charset) {
632 + return "LengthCountingPseudoChannelBuffer(length="+writerIndex+")";
633 + }
634 +
635 + @Override
636 + public String toString(int index, int length, Charset charset) {
637 + return toString();
638 + }
639 +
640 + @Override
641 + @Deprecated
642 + public String toString(String charsetName) {
643 + return toString();
644 + }
645 +
646 + @Override
647 + @Deprecated
648 + public String toString(String charsetName,
649 + ChannelBufferIndexFinder terminatorFinder) {
650 + return toString();
651 + }
652 +
653 + @Override
654 + @Deprecated
655 + public String toString(int index, int length, String charsetName) {
656 + return toString();
657 + }
658 +
659 + @Override
660 + @Deprecated
661 + public
662 + String toString(int index, int length, String charsetName,
663 + ChannelBufferIndexFinder terminatorFinder) {
664 + return toString();
665 + }
666 +
667 + @Override
668 + public int compareTo(ChannelBuffer buffer) {
669 + throw new UnsupportedOperationException();
670 +
671 + }
672 +
673 +}
1 +package org.projectfloodlight.openflow.util;
2 +
3 +import java.util.Set;
4 +
5 +import com.google.common.collect.ImmutableSet;
6 +
7 +import org.projectfloodlight.openflow.types.U64;
8 +import org.projectfloodlight.openflow.protocol.OFBsnPktinFlag;
9 +import org.projectfloodlight.openflow.protocol.OFPacketIn;
10 +import org.projectfloodlight.openflow.protocol.OFVersion;
11 +import org.projectfloodlight.openflow.protocol.match.MatchField;
12 +import org.projectfloodlight.openflow.protocol.match.Match;
13 +import org.projectfloodlight.openflow.protocol.ver13.OFBsnPktinFlagSerializerVer13;
14 +import org.projectfloodlight.openflow.types.OFMetadata;
15 +
16 +
17 +public class MultiplePktInReasonUtil {
18 + private MultiplePktInReasonUtil() {}
19 +
20 + /**
21 + * This function is used in BVS T5/6 to decode the multiple packet in
22 + * reasons in Match.MetaData field.
23 + * */
24 + public static Set<OFBsnPktinFlag> getOFBsnPktinFlags(OFPacketIn pktIn) {
25 + if(pktIn.getVersion() != OFVersion.OF_13) {
26 + throw new IllegalArgumentException("multiple pkt in reasons are "
27 + + "only supported by BVS using "
28 + + "openflow 1.3");
29 + }
30 +
31 + Match match = pktIn.getMatch();
32 + if(match == null) {
33 + return ImmutableSet.<OFBsnPktinFlag>of();
34 + }
35 + OFMetadata metaData = match.get(MatchField.METADATA);
36 + if(metaData == null) {
37 + return ImmutableSet.<OFBsnPktinFlag>of();
38 + }
39 + U64 metaDataValue = metaData.getValue();
40 + if(metaDataValue == null) {
41 + return ImmutableSet.<OFBsnPktinFlag>of();
42 + }
43 + return OFBsnPktinFlagSerializerVer13.ofWireValue(metaDataValue
44 + .getValue());
45 + }
46 +}
1 +package org.projectfloodlight.openflow.util;
2 +
3 +import java.util.List;
4 +import java.util.SortedSet;
5 +
6 +import javax.annotation.Nullable;
7 +
8 +import org.projectfloodlight.openflow.types.PrimitiveSinkable;
9 +
10 +import com.google.common.hash.PrimitiveSink;
11 +
12 +/** Utility methods for dumping collections into primitive sinks.
13 + *
14 + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
15 + */
16 +public class PrimitiveSinkUtils {
17 + private PrimitiveSinkUtils() {}
18 +
19 + /** puts a nullable String into a primitive sink. The entry is prepended by a 'presence'
20 + * boolean bit and the string length;
21 + *
22 + *
23 + * @param sink the sink to put the object
24 + * @param nullableObj the potentially null string to put in the sink
25 + */
26 + public static void putNullableStringTo(PrimitiveSink sink,
27 + @Nullable CharSequence nullableChars) {
28 +
29 + sink.putBoolean(nullableChars != null);
30 + if(nullableChars != null) {
31 + sink.putInt(nullableChars.length());
32 + sink.putUnencodedChars(nullableChars);
33 + }
34 + }
35 +
36 + /** puts a nullable element into a primitive sink. The entry is prepended by a 'present' bit.
37 + *
38 + * @param sink the sink to put the object
39 + * @param nullableObj the nullable object
40 + */
41 + public static void putNullableTo(PrimitiveSink sink,
42 + @Nullable PrimitiveSinkable nullableObj) {
43 + sink.putBoolean(nullableObj != null);
44 + if(nullableObj != null)
45 + nullableObj.putTo(sink);
46 + }
47 +
48 + /** puts the elements of a sorted set into the {@link PrimitiveSink}. Does not support null
49 + * elements. The elements are assumed to be self-delimitating.
50 + *
51 + * @param sink
52 + * @param set
53 + */
54 + public static void putSortedSetTo(PrimitiveSink sink,
55 + SortedSet<? extends PrimitiveSinkable> set) {
56 + sink.putInt(set.size());
57 + for(PrimitiveSinkable e: set) {
58 + e.putTo(sink);
59 + }
60 + }
61 +
62 + /** puts the elements of a list into the {@link PrimitiveSink}. Does not support null
63 + * elements. The elements are assumed to be self-delimitating.
64 + *
65 + * @param sink
66 + * @param set
67 + */
68 + public static void putListTo(PrimitiveSink sink,
69 + List<? extends PrimitiveSinkable> set) {
70 + sink.putInt(set.size());
71 + for(PrimitiveSinkable e: set) {
72 + e.putTo(sink);
73 + }
74 + }
75 +}
1 +/**
2 + * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 + * University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package org.projectfloodlight.openflow.util;
19 +
20 +import java.io.UnsupportedEncodingException;
21 +import java.nio.charset.Charset;
22 +import java.util.Arrays;
23 +
24 +import org.jboss.netty.buffer.ChannelBuffer;
25 +
26 +public class StringByteSerializer {
27 + public static String readFrom(final ChannelBuffer data, final int length) {
28 + byte[] stringBytes = new byte[length];
29 + data.readBytes(stringBytes);
30 + // find the first index of 0
31 + int index = 0;
32 + for (byte b : stringBytes) {
33 + if (0 == b)
34 + break;
35 + ++index;
36 + }
37 + return new String(Arrays.copyOf(stringBytes, index), Charset.forName("ascii"));
38 + }
39 +
40 + public static void writeTo(final ChannelBuffer data, final int length,
41 + final String value) {
42 + try {
43 + byte[] name = value.getBytes("ASCII");
44 + if (name.length < length) {
45 + data.writeBytes(name);
46 + for (int i = name.length; i < length; ++i) {
47 + data.writeByte((byte) 0);
48 + }
49 + } else {
50 + data.writeBytes(name, 0, length - 1);
51 + data.writeByte((byte) 0);
52 + }
53 + } catch (UnsupportedEncodingException e) {
54 + throw new RuntimeException(e);
55 + }
56 +
57 + }
58 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.hamcrest.CoreMatchers.equalTo;
4 +import static org.junit.Assert.assertThat;
5 +
6 +import org.junit.Test;
7 +
8 +public class HashValueUtilsTest {
9 + @Test
10 + public void testBasic() {
11 + long key = 0x1234_5678_1234_5678L;
12 + long value = 0x8765_4321_8765_4321L;
13 + long firstword = 0xFFFF_FFFF_0000_0000L;
14 + long secondword = 0x0000_0000_FFFF_FFFFL;
15 + long xor = key ^ value;
16 +
17 + assertThat(HashValueUtils.combineWithValue(key, value, 0), equalTo(xor));
18 + assertThat(HashValueUtils.combineWithValue(key, value, 64), equalTo(key));
19 + assertThat(HashValueUtils.combineWithValue(key, value, 32), equalTo(key & firstword | xor & secondword ));
20 + assertThat(HashValueUtils.combineWithValue(key, value, 8), equalTo(0x1251_1559_9551_1559L));
21 + }
22 +
23 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.junit.Assert.assertNotNull;
4 +import static org.junit.Assert.fail;
5 +
6 +import java.net.UnknownHostException;
7 +
8 +import org.junit.Test;
9 +
10 +/**
11 + * Most tests are in IPv4AddressTest and IPv6AddressTest
12 + * Just exception testing here
13 + * @author gregor
14 + *
15 + */
16 +public class IPAddressTest {
17 + @Test
18 + public void testOfException() {
19 + try {
20 + IPAddress.of("Foobar");
21 + fail("Should have thrown IllegalArgumentException");
22 + } catch (IllegalArgumentException e) {
23 + // expected
24 + }
25 + try {
26 + IPAddressWithMask.of("Foobar");
27 + fail("Should have thrown IllegalArgumentException");
28 + } catch (IllegalArgumentException e) {
29 + // expected
30 + }
31 + try {
32 + IPAddress.of(null);
33 + fail("Should have thrown NullPointerException");
34 + } catch (NullPointerException e) {
35 + assertNotNull(e.getMessage());
36 + }
37 + try {
38 + IPAddressWithMask.of(null);
39 + fail("Should have thrown NullPointerException");
40 + } catch (NullPointerException e) {
41 + assertNotNull(e.getMessage());
42 + }
43 + try {
44 + IPAddress.of(null);
45 + fail("Should have thrown NullPointerException");
46 + } catch (NullPointerException e) {
47 + assertNotNull(e.getMessage());
48 + }
49 + try {
50 + IPAddressWithMask.of(null);
51 + fail("Should have thrown NullPointerException");
52 + } catch (NullPointerException e) {
53 + assertNotNull(e.getMessage());
54 + }
55 + }
56 +
57 + @Test
58 + public void testFromInetAddressException() throws UnknownHostException {
59 + try {
60 + IPAddress.fromInetAddress(null);
61 + fail("Should have thrown NullPointerException");
62 + } catch (NullPointerException e) {
63 + assertNotNull(e.getMessage());
64 + }
65 + }
66 +
67 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.hamcrest.CoreMatchers.equalTo;
4 +import static org.junit.Assert.assertArrayEquals;
5 +import static org.junit.Assert.assertEquals;
6 +import static org.junit.Assert.assertFalse;
7 +import static org.junit.Assert.assertNotNull;
8 +import static org.junit.Assert.assertThat;
9 +import static org.junit.Assert.assertTrue;
10 +import static org.junit.Assert.fail;
11 +
12 +import org.hamcrest.CoreMatchers;
13 +import org.jboss.netty.buffer.ChannelBuffers;
14 +import org.junit.Test;
15 +import org.projectfloodlight.openflow.exceptions.OFParseError;
16 +
17 +public class IPv4AddressTest {
18 + byte[][] testAddresses = new byte[][] {
19 + {0x01, 0x02, 0x03, 0x04 },
20 + {127, 0, 0, 1},
21 + {(byte) 192, (byte) 168, 0, 100 },
22 + {(byte) 255, (byte) 255, (byte) 255, (byte) 255 }
23 + };
24 +
25 + String[] testStrings = {
26 + "1.2.3.4",
27 + "127.0.0.1",
28 + "192.168.0.100",
29 + "255.255.255.255"
30 + };
31 +
32 + int[] testInts = {
33 + 0x01020304,
34 + 0x7f000001,
35 + (192 << 24) | (168 << 16) | 100,
36 + 0xffffffff
37 + };
38 +
39 + String[] invalidIPs = {
40 + "",
41 + ".",
42 + "1.2..3.4",
43 + "1.2.3.4.",
44 + "257.11.225.1",
45 + "256.11.225.1",
46 + "-1.2.3.4",
47 + "1.2.3.4.5",
48 + "1.x.3.4",
49 + "1.2x.3.4"
50 + };
51 +
52 + String[] ipsWithMask = {
53 + "1.2.3.4/24",
54 + "192.168.130.140/255.255.192.0",
55 + "127.0.0.1/8",
56 + "8.8.8.8",
57 + "8.8.8.8/32",
58 + "0.0.0.0/0",
59 + "192.168.130.140/255.0.255.0",
60 + "1.2.3.4/0.127.0.255"
61 + };
62 +
63 + boolean[] hasMask = {
64 + true,
65 + true,
66 + true,
67 + false,
68 + false,
69 + true,
70 + true,
71 + true
72 + };
73 +
74 + byte[][][] ipsWithMaskValues = {
75 + new byte[][] { new byte[] { (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00 } },
76 + new byte[][] { new byte[] { (byte)0xC0, (byte)0xA8, (byte)0x82, (byte)0x8C }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xC0, (byte)0x00 } },
77 + new byte[][] { new byte[] { (byte)0x7F, (byte)0x00, (byte)0x00, (byte)0x01 }, new byte[] { (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0x00 } },
78 + new byte[][] { new byte[] { (byte)0x08, (byte)0x08, (byte)0x08, (byte)0x08 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF } },
79 + new byte[][] { new byte[] { (byte)0x08, (byte)0x08, (byte)0x08, (byte)0x08 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF } },
80 + new byte[][] { new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }, new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 } },
81 + new byte[][] { new byte[] { (byte)0xC0, (byte)0xA8, (byte)0x82, (byte)0x8C }, new byte[] { (byte)0xFF, (byte)0x00, (byte)0xFF, (byte)0x00 } },
82 + new byte[][] { new byte[] { (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04 }, new byte[] { (byte)0x00, (byte)0x7F, (byte)0x00, (byte)0xFF } }
83 + };
84 +
85 + int[] ipsWithMaskLengths = {
86 + 24,
87 + 18,
88 + 8,
89 + 32,
90 + 32,
91 + 0,
92 + -1,
93 + -1
94 + };
95 +
96 + String[] invalidIpsWithMask = {
97 + "asdf",
98 + "1.2.3.4/33",
99 + "1.2.3.4/34",
100 + "1.2.3.4/-1",
101 + "1.2.3.4/256.0.0.0",
102 + "1.256.3.4/255.255.0.0",
103 + "1.2.3.4/255.255.0.0.0",
104 + };
105 +
106 + @Test
107 + public void testLogicalOperatorsBroadcast() {
108 + assertTrue(IPv4Address.NO_MASK.not().equals(IPv4Address.FULL_MASK));
109 + assertTrue(IPv4Address.NO_MASK.or(IPv4Address.FULL_MASK).
110 + equals(IPv4Address.NO_MASK));
111 + assertTrue(IPv4Address.NO_MASK.and(IPv4Address.FULL_MASK).
112 + equals(IPv4Address.FULL_MASK));
113 +
114 + assertTrue(IPv4Address.NO_MASK.isBroadcast());
115 + assertTrue(!IPv4Address.FULL_MASK.isBroadcast());
116 + }
117 +
118 + @Test
119 + public void testMaskedSubnetBroadcast() {
120 + assertTrue(IPv4AddressWithMask.of("10.10.10.1/24")
121 + .getSubnetBroadcastAddress()
122 + .equals(IPv4Address.of("10.10.10.255")));
123 + assertTrue(IPv4AddressWithMask.of("10.10.10.1/24")
124 + .isSubnetBroadcastAddress(IPv4Address.of("10.10.10.255")));
125 + assertTrue(!IPv4AddressWithMask.of("10.10.10.1/24")
126 + .isSubnetBroadcastAddress(IPv4Address.of("10.10.10.254")));
127 + }
128 +
129 + @Test
130 + public void testMaskedMatchesCidr() {
131 + IPv4AddressWithMask slash28 = IPv4AddressWithMask.of("10.0.42.16/28");
132 +
133 + String[] notContained = {"0.0.0.0", "11.0.42.16", "10.0.41.1", "10.0.42.0", "10.0.42.15",
134 + "10.0.42.32", "255.255.255.255" };
135 +
136 + for(String n: notContained) {
137 + assertThat(String.format("slash 28 %s should not contain address %s",
138 + slash28, n),
139 + slash28.matches(IPv4Address.of(n)), equalTo(false));
140 + }
141 + for(int i=16; i < 32; i++) {
142 + IPv4Address c = IPv4Address.of(String.format("10.0.42.%d", i));
143 + assertThat(String.format("slash 28 %s should contain address %s",
144 + slash28, c),
145 + slash28.matches(c), equalTo(true));
146 + }
147 + }
148 +
149 + @Test
150 + public void testMaskedMatchesArbitrary() {
151 + // irregular octect on the 3rd bitmask requires '1'bit to be set
152 + // 4 bit unset, all others arbitrary
153 + IPv4AddressWithMask slash28 = IPv4AddressWithMask.of("1.2.1.4/255.255.5.255");
154 +
155 + String[] notContained = {"0.0.0.0", "1.2.3.5", "1.2.3.3",
156 + "1.2.0.4", "1.2.2.4", "1.2.4.4", "1.2.5.4", "1.2.6.4", "1.2.7.4",
157 + "1.2.8.4", "1.2.12.4", "1.2.13.4"
158 + };
159 + String[] contained = {"1.2.1.4", "1.2.3.4", "1.2.9.4", "1.2.11.4", "1.2.251.4",
160 + };
161 +
162 + for(String n: notContained) {
163 + assertThat(String.format("slash 28 %s should not contain address %s",
164 + slash28, n),
165 + slash28.matches(IPv4Address.of(n)), equalTo(false));
166 + }
167 + for(String c: contained) {
168 + IPv4Address addr = IPv4Address.of(c);
169 + assertThat(String.format("slash 28 %s should contain address %s",
170 + slash28, addr),
171 + slash28.matches(addr), equalTo(true));
172 + }
173 +
174 + }
175 +
176 +
177 + @Test
178 + public void testConstants() {
179 + byte[] zeros = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
180 + byte[] ones = { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF };
181 + // Make sure class initializtation and static assignment don't get
182 + // messed up. Test everything twice for cached values
183 + assertTrue(IPv4Address.NONE.isCidrMask());
184 + assertEquals(0, IPv4Address.NONE.asCidrMaskLength());
185 + assertArrayEquals(zeros, IPv4Address.NONE.getBytes());
186 + assertTrue(IPv4Address.NONE.isCidrMask());
187 + assertEquals(0, IPv4Address.NONE.asCidrMaskLength());
188 + assertArrayEquals(zeros, IPv4Address.NONE.getBytes());
189 +
190 + assertTrue(IPv4Address.NO_MASK.isCidrMask());
191 + assertEquals(32, IPv4Address.NO_MASK.asCidrMaskLength());
192 + assertArrayEquals(ones, IPv4Address.NO_MASK.getBytes());
193 + assertTrue(IPv4Address.NO_MASK.isCidrMask());
194 + assertEquals(32, IPv4Address.NO_MASK.asCidrMaskLength());
195 + assertArrayEquals(ones, IPv4Address.NO_MASK.getBytes());
196 +
197 + assertTrue(IPv4Address.FULL_MASK.isCidrMask());
198 + assertEquals(0, IPv4Address.FULL_MASK.asCidrMaskLength());
199 + assertArrayEquals(zeros, IPv4Address.FULL_MASK.getBytes());
200 + assertTrue(IPv4Address.FULL_MASK.isCidrMask());
201 + assertEquals(0, IPv4Address.FULL_MASK.asCidrMaskLength());
202 + assertArrayEquals(zeros, IPv4Address.FULL_MASK.getBytes());
203 + }
204 +
205 +
206 + @Test
207 + public void testOfString() {
208 + for(int i=0; i < testAddresses.length; i++ ) {
209 + IPv4Address ip = IPv4Address.of(testStrings[i]);
210 + assertEquals(testInts[i], ip.getInt());
211 + assertArrayEquals(testAddresses[i], ip.getBytes());
212 + assertEquals(testStrings[i], ip.toString());
213 + }
214 + }
215 +
216 + @Test
217 + public void testOfByteArray() {
218 + for(int i=0; i < testAddresses.length; i++ ) {
219 + IPv4Address ip = IPv4Address.of(testAddresses[i]);
220 + assertEquals(testInts[i], ip.getInt());
221 + assertArrayEquals(testAddresses[i], ip.getBytes());
222 + assertEquals(testStrings[i], ip.toString());
223 + }
224 + }
225 +
226 + @Test
227 + public void testReadFrom() throws OFParseError {
228 + for(int i=0; i < testAddresses.length; i++ ) {
229 + IPv4Address ip = IPv4Address.read4Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
230 + assertEquals(testInts[i], ip.getInt());
231 + assertArrayEquals(testAddresses[i], ip.getBytes());
232 + assertEquals(testStrings[i], ip.toString());
233 + }
234 + }
235 +
236 +
237 + @Test
238 + public void testInvalidIPs() throws OFParseError {
239 + for(String invalid : invalidIPs) {
240 + try {
241 + IPv4Address.of(invalid);
242 + fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
243 + } catch(IllegalArgumentException e) {
244 + // ok
245 + }
246 + }
247 + }
248 +
249 + @Test
250 + public void testOfMasked() throws OFParseError {
251 + for (int i = 0; i < ipsWithMask.length; i++) {
252 + IPv4AddressWithMask value = IPv4AddressWithMask.of(ipsWithMask[i]);
253 + if (!hasMask[i]) {
254 + IPv4Address ip = value.getValue();
255 + assertArrayEquals(ipsWithMaskValues[i][0], ip.getBytes());
256 + }
257 + IPv4Address mask = value.getMask();
258 + if (ipsWithMaskLengths[i] == -1) {
259 + assertFalse(mask.isCidrMask());
260 + try {
261 + mask.asCidrMaskLength();
262 + fail("Expected IllegalStateException not thrown");
263 + } catch(IllegalStateException e) {
264 + //expected
265 + }
266 + } else {
267 + assertTrue(mask.isCidrMask());
268 + assertEquals(ipsWithMaskLengths[i], mask.asCidrMaskLength());
269 + }
270 + assertArrayEquals(ipsWithMaskValues[i][1], mask.getBytes());
271 + byte[] ipBytes = new byte[4];
272 + System.arraycopy(ipsWithMaskValues[i][0], 0, ipBytes, 0, 4);
273 + assertEquals(ipBytes.length, value.getValue().getBytes().length);
274 + for (int j = 0; j < ipBytes.length; j++) {
275 + ipBytes[j] &= ipsWithMaskValues[i][1][j];
276 + }
277 +
278 + assertArrayEquals(ipBytes, value.getValue().getBytes());
279 + assertThat(String.format("Byte comparison for mask of %s (%s)", ipsWithMask[i], value),
280 + value.getMask().getBytes(), CoreMatchers.equalTo(ipsWithMaskValues[i][1]));
281 + }
282 + }
283 +
284 + @Test
285 + public void testOfMaskedInvalid() throws Exception {
286 + for(String invalid : invalidIpsWithMask) {
287 + try {
288 + IPv4Address.of(invalid);
289 + fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
290 + } catch(IllegalArgumentException e) {
291 + // ok
292 + }
293 + }
294 + }
295 +
296 + @Test
297 + public void testSuperclass() throws Exception {
298 + for(String ipString: testStrings) {
299 + IPAddress<?> superIp = IPAddress.of(ipString);
300 + assertEquals(IPVersion.IPv4, superIp.getIpVersion());
301 + assertEquals(IPv4Address.of(ipString), superIp);
302 + }
303 +
304 + for(String ipMaskedString: ipsWithMask) {
305 + IPAddressWithMask<?> superIp = IPAddressWithMask.of(ipMaskedString);
306 + assertEquals(IPVersion.IPv4, superIp.getIpVersion());
307 + assertEquals(IPv4AddressWithMask.of(ipMaskedString), superIp);
308 + }
309 + }
310 +
311 + @Test
312 + public void testOfExceptions() {
313 + // We check if the message of a caught NPE is set to a useful message
314 + // as a hacky way of verifying that we got an NPE thrown by use rather
315 + // than one the JVM created for a null access.
316 + try {
317 + String s = null;
318 + IPv4Address.of(s);
319 + fail("Should have thrown NullPointerException");
320 + } catch (NullPointerException e) {
321 + assertNotNull(e.getMessage());
322 + }
323 + try {
324 + byte[] b = null;
325 + IPv4Address.of(b);
326 + fail("Should have thrown NullPointerException");
327 + } catch (NullPointerException e) {
328 + assertNotNull(e.getMessage());
329 + }
330 + try {
331 + byte[] b = new byte[3];
332 + IPv4Address.of(b);
333 + fail("Should have thrown IllegalArgumentException");
334 + } catch (IllegalArgumentException e) {
335 + // expected
336 + }
337 + try {
338 + byte[] b = new byte[5];
339 + IPv4Address.of(b);
340 + fail("Should have thrown IllegalArgumentException");
341 + } catch (IllegalArgumentException e) {
342 + // expected
343 + }
344 + try {
345 + IPv4AddressWithMask.of(null);
346 + fail("Should have thrown NullPointerException");
347 + } catch (NullPointerException e) {
348 + assertNotNull(e.getMessage());
349 + }
350 + try {
351 + IPv4AddressWithMask.of(IPv4Address.of("1.2.3.4"), null);
352 + fail("Should have thrown NullPointerException");
353 + } catch (NullPointerException e) {
354 + assertNotNull(e.getMessage());
355 + }
356 + try {
357 + IPv4AddressWithMask.of(null, IPv4Address.of("255.0.0.0"));
358 + fail("Should have thrown NullPointerException");
359 + } catch (NullPointerException e) {
360 + assertNotNull(e.getMessage());
361 + }
362 + try {
363 + IPv4AddressWithMask.of(IPv4Address.of("10.10.10.0"),
364 + IPv4Address.of("255.0.255.0"))
365 + .getSubnetBroadcastAddress();
366 + fail("Should have thrown IllegalArgumentException");
367 + } catch (IllegalArgumentException e) {
368 + assertNotNull(e.getMessage());
369 + }
370 + }
371 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.junit.Assert.*;
4 +
5 +import java.net.Inet6Address;
6 +import java.net.InetAddress;
7 +import java.net.UnknownHostException;
8 +
9 +import org.hamcrest.CoreMatchers;
10 +import org.jboss.netty.buffer.ChannelBuffers;
11 +import org.junit.Test;
12 +import org.projectfloodlight.openflow.exceptions.OFParseError;
13 +
14 +import com.google.common.io.BaseEncoding;
15 +
16 +public class IPv6AddressTest {
17 +
18 + String[] testStrings = {
19 + "::",
20 + "::1",
21 + "ffe0::",
22 + "1:2:3:4:5:6:7:8"
23 + };
24 +
25 +
26 + private final BaseEncoding hex = BaseEncoding.base16().omitPadding().lowerCase();
27 +
28 + private class WithMaskTaskCase {
29 + final String input;
30 + boolean hasMask;
31 + int expectedMaskLength = 128;
32 + byte[] expectedMask = hex.decode("ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff".replaceAll(" ", ""));
33 +
34 + public WithMaskTaskCase(String input) {
35 + super();
36 + this.input = input;
37 + }
38 +
39 + public WithMaskTaskCase maskHex(String string) {
40 + string = string.replaceAll(" ", "");
41 + this.hasMask = true;
42 + expectedMask = hex.decode(string);
43 + return this;
44 + }
45 +
46 + public WithMaskTaskCase expectedMaskLength(int expectedLength) {
47 + this.expectedMaskLength = expectedLength;
48 + return this;
49 + }
50 +
51 + }
52 +
53 + WithMaskTaskCase[] withMasks = new WithMaskTaskCase[] {
54 + new WithMaskTaskCase("1::1/80")
55 + .maskHex("ff ff ff ff ff ff ff ff ff ff 00 00 00 00 00 00")
56 + .expectedMaskLength(80),
57 +
58 + new WithMaskTaskCase("ffff:ffee:1::/ff00:ff00:ff00:ff00::")
59 + .maskHex("ff 00 ff 00 ff 00 ff 00 00 00 00 00 00 00 00 00")
60 + .expectedMaskLength(-1),
61 + new WithMaskTaskCase("1:2:3:4:5:6:7:8/1::ff00:ff00")
62 + .maskHex("00 01 00 00 00 00 00 00 00 00 00 00 ff 00 ff 00")
63 + .expectedMaskLength(-1),
64 + new WithMaskTaskCase("1:2:3:4:5:6:7:8/::ff00:ff00")
65 + .maskHex("00 00 00 00 00 00 00 00 00 00 00 00 ff 00 ff 00")
66 + .expectedMaskLength(-1),
67 + new WithMaskTaskCase("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff::ff00:ff00")
68 + .maskHex("ff ff ff ff ff ff ff ff ff ff 00 00 ff 00 ff 00")
69 + .expectedMaskLength(-1),
70 + new WithMaskTaskCase("8:8:8:8:8:8:8:8"),
71 + new WithMaskTaskCase("8:8:8:8:8:8:8:8"),
72 + new WithMaskTaskCase("1:2:3:4:5:6:7:8/128"),
73 + new WithMaskTaskCase("::/0")
74 + .maskHex("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00")
75 + .expectedMaskLength(0),
76 + };
77 +
78 + @Test
79 + public void testLogicalOperatorsBroadcast() {
80 + assertTrue(IPv6Address.NO_MASK.not().equals(IPv6Address.FULL_MASK));
81 + assertTrue(IPv6Address.NO_MASK.or(IPv6Address.FULL_MASK).
82 + equals(IPv6Address.NO_MASK));
83 + assertTrue(IPv6Address.NO_MASK.and(IPv6Address.FULL_MASK).
84 + equals(IPv6Address.FULL_MASK));
85 +
86 + assertTrue(IPv6Address.NO_MASK.isBroadcast());
87 + assertTrue(!IPv6Address.FULL_MASK.isBroadcast());
88 + }
89 +
90 + @Test
91 + public void testMaskedSubnetBroadcast() {
92 + assertTrue(IPv6AddressWithMask.of("10:10::1/112")
93 + .getSubnetBroadcastAddress()
94 + .equals(IPv6Address.of("10:10::ffff")));
95 + assertTrue(IPv6AddressWithMask.of("10:10::1/112")
96 + .isSubnetBroadcastAddress(IPv6Address.of("10:10::ffff")));
97 + assertTrue(!IPv6AddressWithMask.of("10:10::1/112")
98 + .isSubnetBroadcastAddress(IPv6Address.of("10:10::fffd")));
99 + }
100 +
101 + @Test
102 + public void testConstants() {
103 + byte[] zeros = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
104 + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
105 + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
106 + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
107 + byte[] ones = { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
108 + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
109 + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
110 + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF };
111 + // Make sure class initializtation and static assignment don't get
112 + // messed up. Test everything twice for cached values
113 + assertTrue(IPv6Address.NONE.isCidrMask());
114 + assertEquals(0, IPv6Address.NONE.asCidrMaskLength());
115 + assertArrayEquals(zeros, IPv6Address.NONE.getBytes());
116 + assertTrue(IPv6Address.NONE.isCidrMask());
117 + assertEquals(0, IPv6Address.NONE.asCidrMaskLength());
118 + assertArrayEquals(zeros, IPv6Address.NONE.getBytes());
119 +
120 + assertTrue(IPv6Address.NO_MASK.isCidrMask());
121 + assertEquals(128, IPv6Address.NO_MASK.asCidrMaskLength());
122 + assertArrayEquals(ones, IPv6Address.NO_MASK.getBytes());
123 + assertTrue(IPv6Address.NO_MASK.isCidrMask());
124 + assertEquals(128, IPv6Address.NO_MASK.asCidrMaskLength());
125 + assertArrayEquals(ones, IPv6Address.NO_MASK.getBytes());
126 +
127 + assertTrue(IPv6Address.FULL_MASK.isCidrMask());
128 + assertEquals(0, IPv6Address.FULL_MASK.asCidrMaskLength());
129 + assertArrayEquals(zeros, IPv6Address.FULL_MASK.getBytes());
130 + assertTrue(IPv6Address.FULL_MASK.isCidrMask());
131 + assertEquals(0, IPv6Address.FULL_MASK.asCidrMaskLength());
132 + assertArrayEquals(zeros, IPv6Address.FULL_MASK.getBytes());
133 + }
134 +
135 + @Test
136 + public void testMasked() throws UnknownHostException {
137 + for(WithMaskTaskCase w: withMasks) {
138 + IPv6AddressWithMask value = IPv6AddressWithMask.of(w.input);
139 + if (!w.hasMask) {
140 + IPv6Address ip = value.getValue();
141 + InetAddress inetAddress = InetAddress.getByName(w.input.split("/")[0]);
142 +
143 + assertArrayEquals(ip.getBytes(), inetAddress.getAddress());
144 + assertEquals(w.input.split("/")[0], ip.toString());
145 + }
146 + InetAddress inetAddress = InetAddress.getByName(w.input.split("/")[0]);
147 +
148 + if (w.expectedMaskLength == -1) {
149 + assertFalse(value.getMask().isCidrMask());
150 + try {
151 + value.getMask().asCidrMaskLength();
152 + fail("Expected IllegalStateException not thrown");
153 + } catch(IllegalStateException e) {
154 + //expected
155 + }
156 + } else {
157 + assertTrue(value.getMask().isCidrMask());
158 + assertEquals("Input " + w.input, w.expectedMaskLength,
159 + value.getMask().asCidrMaskLength());
160 + }
161 +
162 + byte[] address = inetAddress.getAddress();
163 + assertEquals(address.length, value.getValue().getBytes().length);
164 +
165 + for (int j = 0; j < address.length; j++) {
166 + address[j] &= w.expectedMask[j];
167 + }
168 +
169 + assertThat("Address bytes for input " + w.input + ", value=" + value, value.getValue().getBytes(), CoreMatchers.equalTo(address));
170 + assertThat("mask check for input " + w.input + ", value=" + value, value.getMask().getBytes(), CoreMatchers.equalTo(w.expectedMask));
171 + }
172 + for (int i = 0; i <= 128; i++) {
173 + String ipString = String.format("8001:2::1/%d", i);
174 + IPv6AddressWithMask value = IPv6AddressWithMask.of(ipString);
175 + assertEquals("Input " + ipString, i, value.getMask().asCidrMaskLength());
176 + }
177 + }
178 +
179 +
180 + @Test
181 + public void testOfString() throws UnknownHostException {
182 + for(int i=0; i < testStrings.length; i++ ) {
183 + IPv6Address ip = IPv6Address.of(testStrings[i]);
184 + InetAddress inetAddress = InetAddress.getByName(testStrings[i]);
185 +
186 + assertArrayEquals(ip.getBytes(), inetAddress.getAddress());
187 + assertEquals(testStrings[i], ip.toString());
188 + }
189 + }
190 +
191 + @Test
192 + public void testOfByteArray() throws UnknownHostException {
193 + for(int i=0; i < testStrings.length; i++ ) {
194 + byte[] bytes = Inet6Address.getByName(testStrings[i]).getAddress();
195 + IPv6Address ip = IPv6Address.of(bytes);
196 + assertEquals(testStrings[i], ip.toString());
197 + assertArrayEquals(bytes, ip.getBytes());
198 + }
199 + }
200 +
201 + @Test
202 + public void testReadFrom() throws OFParseError, UnknownHostException {
203 + for(int i=0; i < testStrings.length; i++ ) {
204 + byte[] bytes = Inet6Address.getByName(testStrings[i]).getAddress();
205 + IPv6Address ip = IPv6Address.read16Bytes(ChannelBuffers.copiedBuffer(bytes));
206 + assertEquals(testStrings[i], ip.toString());
207 + assertArrayEquals(bytes, ip.getBytes());
208 + }
209 + }
210 +
211 + String[] invalidIPs = {
212 + "",
213 + ":",
214 + "1:2:3:4:5:6:7:8:9",
215 + "1:2:3:4:5:6:7:8:",
216 + "1:2:3:4:5:6:7:8g",
217 + "1:2:3:",
218 + "12345::",
219 + "1::3::8",
220 + "::3::"
221 + };
222 +
223 + @Test
224 + public void testInvalidIPs() throws OFParseError {
225 + for(String invalid : invalidIPs) {
226 + try {
227 + IPv6Address.of(invalid);
228 + fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
229 + } catch(IllegalArgumentException e) {
230 + // ok
231 + }
232 + }
233 + }
234 +
235 + @Test
236 + public void testZeroCompression() throws OFParseError {
237 + assertEquals("::", IPv6Address.of("::").toString(true, false));
238 + assertEquals("0:0:0:0:0:0:0:0", IPv6Address.of("::").toString(false, false));
239 + assertEquals("0000:0000:0000:0000:0000:0000:0000:0000", IPv6Address.of("::").toString(false, true));
240 + assertEquals("1::4:5:6:0:8", IPv6Address.of("1:0:0:4:5:6:0:8").toString(true, false));
241 + assertEquals("1:0:0:4::8", IPv6Address.of("1:0:0:4:0:0:0:8").toString(true, false));
242 + }
243 +
244 + @Test
245 + public void testSuperclass() throws Exception {
246 + for(String ipString: testStrings) {
247 + IPAddress<?> superIp = IPAddress.of(ipString);
248 + assertEquals(IPVersion.IPv6, superIp.getIpVersion());
249 + assertEquals(IPv6Address.of(ipString), superIp);
250 + }
251 +
252 + for(WithMaskTaskCase w: withMasks) {
253 + String ipMaskedString = w.input;
254 + IPAddressWithMask<?> superIp = IPAddressWithMask.of(ipMaskedString);
255 + assertEquals(IPVersion.IPv6, superIp.getIpVersion());
256 + assertEquals(IPv6AddressWithMask.of(ipMaskedString), superIp);
257 + }
258 + }
259 +
260 + @Test
261 + public void testOfExceptions() throws Exception {
262 + try {
263 + IPv6AddressWithMask.of(null);
264 + fail("Should have thrown NullPointerException");
265 + } catch (NullPointerException e) {
266 + assertNotNull(e.getMessage());
267 + }
268 + try {
269 + String s = null;
270 + IPv6Address.of(s);
271 + fail("Should have thrown NullPointerException");
272 + } catch (NullPointerException e) {
273 + assertNotNull(e.getMessage());
274 + }
275 + try {
276 + byte[] b = null;
277 + IPv6Address.of(b);
278 + fail("Should have thrown NullPointerException");
279 + } catch (NullPointerException e) {
280 + assertNotNull(e.getMessage());
281 + }
282 + try {
283 + byte[] b = new byte[7];
284 + IPv6Address.of(b);
285 + fail("Should have thrown IllegalArgumentException");
286 + } catch (IllegalArgumentException e) {
287 + // expected
288 + }
289 + try {
290 + byte[] b = new byte[9];
291 + IPv6Address.of(b);
292 + fail("Should have thrown IllegalArgumentException");
293 + } catch (IllegalArgumentException e) {
294 + // expected
295 + }
296 + try {
297 + IPv6AddressWithMask.of(IPv6Address.of("1::"), null);
298 + fail("Should have thrown NullPointerException");
299 + } catch (NullPointerException e) {
300 + assertNotNull(e.getMessage());
301 + }
302 + try {
303 + IPv6AddressWithMask.of(null, IPv6Address.of("255::"));
304 + fail("Should have thrown NullPointerException");
305 + } catch (NullPointerException e) {
306 + assertNotNull(e.getMessage());
307 + }
308 + try {
309 + IPv6AddressWithMask.of(IPv6Address.of("10:10::0"),
310 + IPv6Address.of("ffff:0:ffff::"))
311 + .getSubnetBroadcastAddress();
312 + fail("Should have thrown IllegalArgumentException");
313 + } catch (IllegalArgumentException e) {
314 + assertNotNull(e.getMessage());
315 + }
316 + }
317 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.junit.Assert.assertArrayEquals;
4 +import static org.junit.Assert.assertEquals;
5 +import static org.junit.Assert.assertFalse;
6 +import static org.junit.Assert.assertTrue;
7 +import static org.junit.Assert.fail;
8 +
9 +import java.util.Arrays;
10 +
11 +import org.jboss.netty.buffer.ChannelBuffers;
12 +import org.junit.Test;
13 +import org.projectfloodlight.openflow.exceptions.OFParseError;
14 +
15 +public class MacAddressTest {
16 + byte[][] testAddresses = new byte[][] {
17 + {0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
18 + {(byte) 0x80, 0x0, 0x0, 0x0, 0x0, 0x01},
19 + {(byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255 }
20 + };
21 +
22 + String[] testStrings = {
23 + "01:02:03:04:05:06",
24 + "80:00:00:00:00:01",
25 + "ff:ff:ff:ff:ff:ff"
26 + };
27 +
28 + long[] testInts = {
29 + 0x00010203040506L,
30 + 0x00800000000001L,
31 + 0x00ffffffffffffL
32 + };
33 +
34 + String[] invalidMacStrings = {
35 + "",
36 + "1.2.3.4",
37 + "0T:00:01:02:03:04",
38 + "00:01:02:03:04:05:06",
39 + "00:ff:ef:12:12:ff:",
40 + "00:fff:ef:12:12:ff",
41 + "01:02:03:04:05;06",
42 + "0:1:2:3:4:5:6",
43 + "01:02:03:04"
44 + };
45 +
46 + byte[][] invalidMacBytes = {
47 + new byte[]{0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
48 + new byte[]{0x01, 0x01, 0x02, 0x03, 0x04}
49 + };
50 +
51 + @Test
52 + public void testOfString() {
53 + for(int i=0; i < testAddresses.length; i++ ) {
54 + MacAddress ip = MacAddress.of(testStrings[i]);
55 + assertEquals(testInts[i], ip.getLong());
56 + assertArrayEquals(testAddresses[i], ip.getBytes());
57 + assertEquals(testStrings[i], ip.toString());
58 + }
59 + }
60 +
61 + @Test
62 + public void testOfByteArray() {
63 + for(int i=0; i < testAddresses.length; i++ ) {
64 + MacAddress ip = MacAddress.of(testAddresses[i]);
65 + assertEquals("error checking long representation of "+Arrays.toString(testAddresses[i]) + "(should be "+Long.toHexString(testInts[i]) +")", testInts[i], ip.getLong());
66 + assertArrayEquals(testAddresses[i], ip.getBytes());
67 + assertEquals(testStrings[i], ip.toString());
68 + }
69 + }
70 +
71 + @Test
72 + public void testReadFrom() throws OFParseError {
73 + for(int i=0; i < testAddresses.length; i++ ) {
74 + MacAddress ip = MacAddress.read6Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
75 + assertEquals(testInts[i], ip.getLong());
76 + assertArrayEquals(testAddresses[i], ip.getBytes());
77 + assertEquals(testStrings[i], ip.toString());
78 + }
79 + }
80 +
81 +
82 + @Test
83 + public void testInvalidMacStrings() throws OFParseError {
84 + for(String invalid : invalidMacStrings) {
85 + try {
86 + MacAddress.of(invalid);
87 + fail("Invalid MAC address "+invalid+ " should have raised IllegalArgumentException");
88 + } catch(IllegalArgumentException e) {
89 + // ok
90 + }
91 + }
92 + }
93 +
94 + @Test
95 + public void testInvalidMacBytes() throws OFParseError {
96 + for(byte[] invalid : invalidMacBytes) {
97 + try {
98 + MacAddress.of(invalid);
99 + fail("Invalid MAC address bytes "+ Arrays.toString(invalid) + " should have raised IllegalArgumentException");
100 + } catch(IllegalArgumentException e) {
101 + // ok
102 + }
103 + }
104 + }
105 +
106 + // Test data is imported from org.projectfloodlight.packet.EthernetTest
107 + @Test
108 + public void testToLong() {
109 + assertEquals(
110 + 281474976710655L,
111 + MacAddress.of(new byte[]{(byte) 0xff, (byte) 0xff,
112 + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}).getLong());
113 +
114 + assertEquals(
115 + 1103823438081L,
116 + MacAddress.of(new byte[] { (byte) 0x01, (byte) 0x01,
117 + (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01 }).getLong());
118 +
119 + assertEquals(
120 + 141289400074368L,
121 + MacAddress.of(new byte[] { (byte) 0x80, (byte) 0x80,
122 + (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80 }).getLong());
123 +
124 + }
125 +
126 + @Test
127 + public void testIsBroadcast() {
128 + assertTrue(MacAddress.of("FF:FF:FF:FF:FF:FF").isBroadcast());
129 + assertTrue(MacAddress.of(-1).isBroadcast());
130 + assertTrue(MacAddress.of(0x05FFFFFFFFFFFFL).isBroadcast());
131 + assertFalse(MacAddress.of("11:22:33:44:55:66").isBroadcast());
132 + }
133 +
134 + @Test
135 + public void testIsMulticast() {
136 + assertTrue(MacAddress.of("01:80:C2:00:00:00").isMulticast());
137 + assertFalse(MacAddress.of("00:80:C2:00:00:00").isMulticast());
138 + assertFalse(MacAddress.of("FE:80:C2:00:00:00").isMulticast());
139 + assertFalse(MacAddress.of(-1).isMulticast());
140 + assertFalse(MacAddress.of(0x05FFFFFFFFFFFFL).isMulticast());
141 + assertFalse(MacAddress.of("FF:FF:FF:FF:FF:FF").isMulticast());
142 + }
143 +
144 + @Test
145 + public void testIsLLDPAddress() {
146 + assertTrue(MacAddress.of("01:80:C2:00:00:00").isLLDPAddress());
147 + assertTrue(MacAddress.of("01:80:C2:00:00:0f").isLLDPAddress());
148 + assertFalse(MacAddress.of("01:80:C2:00:00:50").isLLDPAddress());
149 + assertFalse(MacAddress.of("01:80:C2:00:10:00").isLLDPAddress());
150 + assertFalse(MacAddress.of("01:80:C2:40:00:01").isLLDPAddress());
151 + assertFalse(MacAddress.of("00:80:C2:f0:00:00").isLLDPAddress());
152 + assertFalse(MacAddress.of("FE:80:C2:00:00:00").isLLDPAddress());
153 + }
154 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.hamcrest.CoreMatchers.equalTo;
4 +import static org.junit.Assert.assertThat;
5 +
6 +import org.hamcrest.Matchers;
7 +import org.jboss.netty.buffer.ChannelBuffer;
8 +import org.jboss.netty.buffer.ChannelBuffers;
9 +import org.junit.Test;
10 +import org.projectfloodlight.openflow.protocol.OFFactories;
11 +import org.projectfloodlight.openflow.protocol.OFFlowAdd;
12 +import org.projectfloodlight.openflow.protocol.OFVersion;
13 +
14 +public class OFErrorCauseDataTest {
15 + @Test
16 + public void testEmpty() {
17 + OFErrorCauseData emptyCause = OFErrorCauseData.of(new byte[] {}, OFVersion.OF_13);
18 + assertThat(emptyCause.getData(), equalTo(new byte[] {}));
19 + assertThat(emptyCause.getParsedMessage().isPresent(), equalTo(false));
20 + assertThat(emptyCause.toString(), Matchers.containsString("unparsed"));
21 + }
22 +
23 + @Test
24 + public void testTooShort() {
25 + OFErrorCauseData emptyCause = OFErrorCauseData.of(new byte[] {0x1, 0x2}, OFVersion.OF_13);
26 + assertThat(emptyCause.getData(), equalTo(new byte[] {0x1, 0x2}));
27 + assertThat(emptyCause.getParsedMessage().isPresent(), equalTo(false));
28 + assertThat(emptyCause.toString(), Matchers.containsString("unparsed"));
29 + assertThat(emptyCause.toString(), Matchers.containsString("01 02"));
30 + }
31 +
32 + byte[] truncatedFlowAddd = new byte[] {
33 + 0x04, 0x0e, // version, type
34 + 0x00, (byte) 0x80, // length
35 + 0x12, 0x34, 0x56, 0x78, // xid
36 + (byte) 0xfe, (byte) 0xdc , (byte) 0xba, (byte) 0x98, 0x76, 0x54, 0x32, 0x10, // cookie
37 + (byte) 0xff, 0x00, (byte) 0xff, 0x00, (byte) 0xff, 0x00, (byte) 0xff, 0x00, // cookie_mask
38 + 0x03 // table_id
39 + // rest truncated
40 + };
41 +
42 + @Test
43 + public void testTruncated() {
44 + OFErrorCauseData emptyCause = OFErrorCauseData.of(truncatedFlowAddd, OFVersion.OF_13);
45 + assertThat(emptyCause.getData(), equalTo(truncatedFlowAddd));
46 + assertThat(emptyCause.getParsedMessage().isPresent(), equalTo(false));
47 + assertThat(emptyCause.toString(), Matchers.containsString("unparsed"));
48 + assertThat(emptyCause.toString(), Matchers.containsString("04 0e 00 80"));
49 + }
50 +
51 + @Test
52 + public void testFlowAdd() {
53 + OFFlowAdd flowAdd = OFFactories.getFactory(OFVersion.OF_13).buildFlowAdd()
54 + .setXid(0x12345678)
55 + .setCookie(U64.parseHex("FEDCBA9876543210"))
56 + .setCookieMask(U64.parseHex("FF00FF00FF00FF00"))
57 + .setTableId(TableId.of(3))
58 + .setIdleTimeout(5)
59 + .setHardTimeout(10)
60 + .setPriority(6000)
61 + .build();
62 +
63 + ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
64 + flowAdd.writeTo(bb);
65 + byte[] flowAddBytes = new byte[bb.readableBytes()];
66 + bb.readBytes(flowAddBytes);
67 +
68 + OFErrorCauseData emptyCause = OFErrorCauseData.of(flowAddBytes, OFVersion.OF_13);
69 + assertThat(emptyCause.getData(), equalTo(flowAddBytes));
70 + assertThat(emptyCause.getParsedMessage().isPresent(), equalTo(true));
71 + assertThat(emptyCause.toString(), Matchers.containsString("OFFlowAdd"));
72 + assertThat(emptyCause.toString(), Matchers.containsString("idleTimeout=5"));
73 + }
74 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.hamcrest.Matchers.contains;
4 +import static org.junit.Assert.assertArrayEquals;
5 +import static org.junit.Assert.assertThat;
6 +import junit.framework.TestCase;
7 +
8 +import org.junit.Test;
9 +
10 +public class OFPortBitMapTest extends TestCase {
11 + @Test
12 + public void testCreateAndIterate() {
13 + OFPortBitMap map = OFPortBitMap.ofPorts(OFPort.of(1), OFPort.of(2), OFPort.of(5));
14 +
15 + assertThat(map.getOnPorts(), contains(OFPort.of(1), OFPort.of(2), OFPort.of(5)));
16 + }
17 +
18 + @Test
19 + public void testOFBitMap() {
20 + OFBitMask128 bitmap = OFBitMask128.of(0xFFFF_FFFF_FFFF_FFFFL, 0xFFFF_FFFF_FFFF_FFD9L);
21 +
22 + OFPortBitMap map = OFPortBitMap.of(bitmap);
23 +
24 + assertThat(map.getOnPorts(), contains(OFPort.of(1), OFPort.of(2), OFPort.of(5)));
25 + }
26 +
27 + @Test
28 + public void testOFPortBitMap() {
29 + Boolean[] on = new Boolean[127];
30 + for (int i = 0; i < 127; i++) {
31 + on[i] = false;
32 + }
33 +
34 + OFPortBitMap.Builder builder = new OFPortBitMap.Builder();
35 +
36 + for (int i = 0; i < 127; i += 3) {
37 + OFPort p = OFPort.of(i);
38 + builder.set(p);
39 + on[p.getPortNumber()] = true;
40 + }
41 +
42 + // Test that all ports that were added are actually on, and all other ports are off
43 + OFPortBitMap portmap = builder.build();
44 + //System.out.println(portmap);
45 + Boolean[] actual = new Boolean[127];
46 + for (int i = 0; i < 127; i++) {
47 + actual[i] = false;
48 + }
49 + for (int i = 0; i < 127; i++) {
50 + actual[i] = portmap.isOn(OFPort.of(i));
51 + }
52 + assertArrayEquals(on, actual);
53 +
54 + // Turn some ports off
55 + for (int i = 0; i < 127; i += 7) {
56 + on[i] = false;
57 + builder.unset(OFPort.of(i));
58 + }
59 +
60 + // Test again
61 + portmap = builder.build();
62 + actual = new Boolean[127];
63 + for (int i = 0; i < 127; i++) {
64 + actual[i] = false;
65 + }
66 + for (int i = 0; i < 127; i++) {
67 + actual[i] = portmap.isOn(OFPort.of(i));
68 + }
69 + assertArrayEquals(on, actual);
70 + }
71 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.hamcrest.CoreMatchers.equalTo;
4 +import static org.junit.Assert.assertThat;
5 +
6 +import org.hamcrest.CoreMatchers;
7 +import org.junit.Test;
8 +
9 +public class OFVlanVidMatchTest {
10 + @Test
11 + public void testofVlanVid() {
12 + assertThat(
13 + (int) OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(1)).getRawVid(),
14 + equalTo(0x1001));
15 + assertThat(
16 + (int) OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(0xFFF)).getRawVid(),
17 + equalTo(0x1FFF));
18 + assertThat(OFVlanVidMatch.ofVlanVid(null), equalTo(OFVlanVidMatch.UNTAGGED));
19 + assertThat(OFVlanVidMatch.ofVlanVid(VlanVid.NO_MASK),
20 + equalTo(OFVlanVidMatch.NO_MASK));
21 + // a fully masked VlanVid means "PRESENT" in OFVlanVid
22 + // (because a VlanVid always specifies a Vlan)
23 + assertThat(OFVlanVidMatch.ofVlanVid(VlanVid.FULL_MASK),
24 + equalTo(OFVlanVidMatch.PRESENT));
25 + }
26 + @Test
27 + public void testtoVlanVid() {
28 + assertThat(
29 + OFVlanVidMatch.ofRawVid((short)0x1001).getVlanVid(),
30 + equalTo(VlanVid.ofVlan(1)));
31 + assertThat(
32 + OFVlanVidMatch.ofRawVid((short)0x1FFF).getVlanVid(),
33 + equalTo(VlanVid.ofVlan(0xFFF)));
34 + assertThat(OFVlanVidMatch.UNTAGGED.getVlanVid(), CoreMatchers.nullValue());
35 + assertThat(
36 + OFVlanVidMatch.NO_MASK.getVlanVid(),
37 + equalTo(VlanVid.NO_MASK));
38 + assertThat(
39 + OFVlanVidMatch.PRESENT.getVlanVid(),
40 + equalTo(VlanVid.FULL_MASK));
41 + }
42 +
43 +
44 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.hamcrest.CoreMatchers.equalTo;
4 +import static org.hamcrest.CoreMatchers.not;
5 +import static org.junit.Assert.assertEquals;
6 +import static org.junit.Assert.assertFalse;
7 +import static org.junit.Assert.assertNotEquals;
8 +import static org.junit.Assert.assertThat;
9 +import static org.junit.Assert.assertTrue;
10 +import static org.junit.Assert.fail;
11 +
12 +import org.hamcrest.Matchers;
13 +import org.junit.Test;
14 +
15 +import com.google.common.hash.HashCode;
16 +import com.google.common.hash.Hasher;
17 +import com.google.common.hash.Hashing;
18 +
19 +public class U128Test {
20 + @Test
21 + public void testPositiveRaws() {
22 + assertThat(U128.of(0, 0).getMsb(), equalTo(0L));
23 + assertThat(U128.of(0, 0).getLsb(), equalTo(0L));
24 +
25 + assertThat(U128.of(1, 2).getMsb(), equalTo(1L));
26 + assertThat(U128.of(1, 2).getLsb(), equalTo(2L));
27 + }
28 +
29 + @Test
30 + public void testPutTo() {
31 + U128 h = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
32 + U128 hSame = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
33 +
34 + U128 hBothDiff = U128.of(0x1234_5678_90ab_cdefL,0x1234_5678_90ab_cdefL);
35 + U128 hMsbDiff = U128.of(0x0234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
36 + U128 hLsbDiff = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeeeL);
37 +
38 + assertThat(hash(h), equalTo(hash(hSame)));
39 + assertThat(hash(h), not(hash(hBothDiff)));
40 + assertThat(hash(h), not(hash(hMsbDiff)));
41 + assertThat(hash(h), not(hash(hLsbDiff)));
42 + }
43 +
44 + private HashCode hash(U128 f) {
45 + Hasher hash = Hashing.murmur3_128().newHasher();
46 + f.putTo(hash);
47 + return hash.hash();
48 +
49 + }
50 +
51 + @Test
52 + public void testEqualHashCode() {
53 + U128 h1 = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
54 + U128 h2 = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
55 + U128 h3 = U128.of(0xeeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
56 + U128 h3_2 = U128.of(0xdeafbeefdeadbeefL, 0xeeafbeefdeadbeefL);
57 +
58 + assertTrue(h1.equals(h1));
59 + assertTrue(h1.equals(h2));
60 + assertFalse(h1.equals(h3));
61 + assertFalse(h1.equals(h3_2));
62 + assertTrue(h2.equals(h1));
63 +
64 + assertEquals(h1.hashCode(), h2.hashCode());
65 + assertNotEquals(h1.hashCode(), h3.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
66 + assertNotEquals(h1.hashCode(), h3_2.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
67 + }
68 +
69 + @Test
70 + public void testXor() {
71 + U128 hNull = U128.of(0, 0);
72 + U128 hDeadBeef = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
73 + assertThat(hNull.xor(hNull), equalTo(hNull));
74 + assertThat(hNull.xor(hDeadBeef), equalTo(hDeadBeef));
75 + assertThat(hDeadBeef.xor(hNull), equalTo(hDeadBeef));
76 + assertThat(hDeadBeef.xor(hDeadBeef), equalTo(hNull));
77 +
78 +
79 + U128 h1_0 = U128.of(1L, 0);
80 + U128 h8_0 = U128.of(0x8000000000000000L, 0);
81 + U128 h81_0 = U128.of(0x8000000000000001L, 0);
82 + assertThat(h1_0.xor(h8_0), equalTo(h81_0));
83 +
84 + U128 h0_1 = U128.of(0, 1L);
85 + U128 h0_8 = U128.of(0, 0x8000000000000000L);
86 + U128 h0_81 = U128.of(0, 0x8000000000000001L);
87 + assertThat(h0_1.xor(h0_8), equalTo(h0_81));
88 + }
89 +
90 + @Test
91 + public void testKeyBits() {
92 + U128 zeroU = U128.of(0,0);
93 + assertThat(zeroU.prefixBits(0), equalTo(0));
94 + assertThat(zeroU.prefixBits(16), equalTo(0));
95 + assertThat(zeroU.prefixBits(32), equalTo(0));
96 +
97 + checkInvalidKeyBitSize(zeroU, 33);
98 + checkInvalidKeyBitSize(zeroU, 64);
99 + assertThat(zeroU.prefixBits(3), equalTo(0));
100 +
101 + U128 positiveU = U128.of(0x1234_5678_1234_5678L, 0x1234_5678_1234_5678L);
102 + assertThat(positiveU.prefixBits(0), equalTo(0));
103 + assertThat(positiveU.prefixBits(16), equalTo(0x1234));
104 + assertThat(positiveU.prefixBits(32), equalTo(0x12345678));
105 + checkInvalidKeyBitSize(positiveU, 33);
106 + checkInvalidKeyBitSize(positiveU, 64);
107 +
108 + U128 signedBitU = U128.of(0x8765_4321_8765_4321L, 0x1234_5678_1234_5678L);
109 + assertThat(signedBitU.prefixBits(0), equalTo(0));
110 + assertThat(signedBitU.prefixBits(16), equalTo(0x8765));
111 + assertThat(signedBitU.prefixBits(32), equalTo(0x8765_4321));
112 + checkInvalidKeyBitSize(signedBitU, 33);
113 + checkInvalidKeyBitSize(signedBitU, 64);
114 + }
115 +
116 + private void
117 + checkInvalidKeyBitSize(U128 u, int prefixBit) {
118 + try {
119 + u.prefixBits(prefixBit);
120 + fail("Expected exception not thrown for "+prefixBit + " bits");
121 + } catch(IllegalArgumentException e) {
122 + // expected
123 + }
124 + }
125 +
126 +
127 + @Test
128 + public void testCompare() {
129 + U128 u0_0 = U128.of(0, 0);
130 + U128 u0_1 = U128.of(0, 1);
131 + U128 u0_8 = U128.of(0, 0x8765_4321_8765_4321L);
132 + U128 u1_0 = U128.of(0x1234_5678_1234_5678L, 0);
133 + U128 u8_0 = U128.of(0x8765_4321_8765_4321L, 0);
134 + U128 uf_0 = U128.of(0xFFFF_FFFF_FFFF_FFFFL, 0);
135 +
136 + U128[] us = new U128[] { u0_0, u0_1, u0_8, u1_0, u8_0, uf_0 };
137 +
138 + for(int i = 0; i< us.length; i++) {
139 + U128 u_base = us[i];
140 + assertThat(
141 + String.format("%s should be equal to itself (compareTo)", u_base),
142 + u_base.compareTo(u_base), equalTo(0));
143 + assertThat(
144 + String.format("%s should be equal to itself (equals)", u_base),
145 + u_base.equals(u_base), equalTo(true));
146 + assertThat(
147 + String.format("%s should be equal to itself (equals, by value)", u_base),
148 + u_base.equals(U128.of(u_base.getMsb(), u_base.getLsb())), equalTo(true));
149 +
150 + for(int j = i+1; j< us.length; j++) {
151 + U128 u_greater = us[j];
152 + assertThat(
153 + String.format("%s should not be equal to %s", u_base, u_greater),
154 + u_base.equals(u_base), equalTo(true));
155 + assertThat(
156 + String.format("%s should be smaller than %s", u_base, u_greater),
157 + u_base.compareTo(u_greater), Matchers.lessThan(0));
158 + assertThat(
159 + String.format("%s should be greater than %s", u_greater, u_base),
160 + u_greater.compareTo(u_base), Matchers.greaterThan(0));
161 + }
162 + }
163 + }
164 +
165 + @Test
166 + public void testCombine() {
167 + long key = 0x1234567890abcdefL;
168 + long val = 0xdeafbeefdeadbeefL;
169 + U128 hkey = U128.of(key, key*2);
170 + U128 hVal = U128.of(val, val/2);
171 +
172 + assertThat(hkey.combineWithValue(hVal, 0), equalTo(hkey.xor(hVal)));
173 + assertThat(hkey.combineWithValue(hVal, 64), equalTo(U128.of(hkey.getMsb(), hkey.getLsb() ^ hVal.getLsb())));
174 + assertThat(hkey.combineWithValue(hVal, 128), equalTo(hkey));
175 +
176 + long mask8 = 0xFF00_0000_0000_0000L;
177 +
178 + assertThat(hkey.combineWithValue(hVal, 8), equalTo(U128.of(hkey.getMsb() & mask8 | hkey.getMsb() ^ hVal.getMsb() & ~mask8,
179 + hkey.getLsb() ^ hVal.getLsb() )));
180 + }
181 +
182 +}
1 +package org.projectfloodlight.openflow.types;
2 +
3 +import static org.hamcrest.CoreMatchers.equalTo;
4 +import static org.junit.Assert.assertEquals;
5 +import static org.junit.Assert.assertFalse;
6 +import static org.junit.Assert.assertNotEquals;
7 +import static org.junit.Assert.assertThat;
8 +import static org.junit.Assert.assertTrue;
9 +import static org.junit.Assert.fail;
10 +
11 +import java.math.BigInteger;
12 +
13 +import org.junit.Test;
14 +
15 +public class U64Test {
16 +
17 + @Test
18 + public void testPositiveRaws() {
19 + for(long positive: new long[] { 0, 1, 100, Long.MAX_VALUE }) {
20 + assertEquals(positive, U64.ofRaw(positive).getValue());
21 + assertEquals(BigInteger.valueOf(positive), U64.ofRaw(positive).getBigInteger());
22 + }
23 + }
24 +
25 + @Test
26 + public void testNegativeRaws() {
27 + long minus_1 = 0xFFFF_FFFF_FFFF_FFFFL;
28 + assertEquals(minus_1, U64.ofRaw(minus_1).getValue());
29 + assertEquals(new BigInteger("FFFF_FFFF_FFFF_FFFF".replace("_", ""), 16), U64.ofRaw(minus_1).getBigInteger());
30 + assertEquals(new BigInteger("18446744073709551615"), U64.ofRaw(minus_1).getBigInteger());
31 + }
32 +
33 + @Test
34 + public void testEqualHashCode() {
35 + U64 h1 = U64.of(0xdeafbeefdeadbeefL);
36 + U64 h2 = U64.of(0xdeafbeefdeadbeefL);
37 + U64 h3 = U64.of(0xeeafbeefdeadbeefL);
38 +
39 + assertTrue(h1.equals(h1));
40 + assertTrue(h1.equals(h2));
41 + assertFalse(h1.equals(h3));
42 + assertTrue(h2.equals(h1));
43 +
44 + assertEquals(h1.hashCode(), h2.hashCode());
45 + assertNotEquals(h1.hashCode(), h3.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
46 + }
47 +
48 + @Test
49 + public void testXor() {
50 + U64 hNull = U64.of(0);
51 + U64 hDeadBeef = U64.of(0xdeafbeefdeadbeefL);
52 + assertThat(hNull.xor(hNull), equalTo(hNull));
53 + assertThat(hNull.xor(hDeadBeef), equalTo(hDeadBeef));
54 + assertThat(hDeadBeef.xor(hNull), equalTo(hDeadBeef));
55 + assertThat(hDeadBeef.xor(hDeadBeef), equalTo(hNull));
56 +
57 +
58 + U64 h1 = U64.of(1L);
59 + U64 h8 = U64.of(0x8000000000000000L);
60 + U64 h81 = U64.of(0x8000000000000001L);
61 + assertThat(h1.xor(h8), equalTo(h81));
62 + }
63 +
64 + @Test
65 + public void testCombine() {
66 + long key = 0x1234567890abcdefL;
67 + long val = 0xdeafbeefdeadbeefL;
68 + U64 hkey = U64.of(key);
69 + U64 hVal = U64.of(val);
70 +
71 + assertThat(hkey.combineWithValue(hVal, 0), equalTo(hkey.xor(hVal)));
72 + assertThat(hkey.combineWithValue(hVal, 64), equalTo(hkey));
73 + long mask32 = 0x00000000FFFFFFFFL;
74 + assertThat(hkey.combineWithValue(hVal, 32),
75 + equalTo(U64.of(key & ~mask32| (key ^ val) & mask32)));
76 +
77 + long tenMask = 0x003FFFFFFFFFFFFFL;
78 + assertThat(hkey.combineWithValue(hVal, 10),
79 + equalTo(U64.of(key & ~tenMask | (key ^ val) & tenMask)));
80 + }
81 +
82 + @Test
83 + public void testKeyBits() {
84 + U64 zeroU = U64.of(0);
85 + assertThat(zeroU.prefixBits(0), equalTo(0));
86 + assertThat(zeroU.prefixBits(16), equalTo(0));
87 + assertThat(zeroU.prefixBits(32), equalTo(0));
88 +
89 + checkInvalidKeyBitSize(zeroU, 33);
90 + checkInvalidKeyBitSize(zeroU, 64);
91 + assertThat(zeroU.prefixBits(3), equalTo(0));
92 +
93 + U64 positiveU = U64.of(0x1234_5678_1234_5678L);
94 + assertThat(positiveU.prefixBits(0), equalTo(0));
95 + assertThat(positiveU.prefixBits(16), equalTo(0x1234));
96 + assertThat(positiveU.prefixBits(32), equalTo(0x12345678));
97 + checkInvalidKeyBitSize(positiveU, 33);
98 + checkInvalidKeyBitSize(positiveU, 64);
99 +
100 + U64 signedBitU = U64.of(0x8765_4321_8765_4321L);
101 + assertThat(signedBitU.prefixBits(0), equalTo(0));
102 + assertThat(signedBitU.prefixBits(16), equalTo(0x8765));
103 + assertThat(signedBitU.prefixBits(32), equalTo(0x8765_4321));
104 + checkInvalidKeyBitSize(signedBitU, 33);
105 + checkInvalidKeyBitSize(signedBitU, 64);
106 + }
107 +
108 + private void
109 + checkInvalidKeyBitSize(U64 u, int prefixBit) {
110 + try {
111 + u.prefixBits(prefixBit);
112 + fail("Expected exception not thrown for "+prefixBit + " bits");
113 + } catch(IllegalArgumentException e) {
114 + // expected
115 + }
116 + }
117 +
118 +}
1 +/**
2 +* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 +* University
4 +*
5 +* Licensed under the Apache License, Version 2.0 (the "License"); you may
6 +* not use this file except in compliance with the License. You may obtain
7 +* a copy of the License at
8 +*
9 +* http://www.apache.org/licenses/LICENSE-2.0
10 +*
11 +* Unless required by applicable law or agreed to in writing, software
12 +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 +* License for the specific language governing permissions and limitations
15 +* under the License.
16 +**/
17 +
18 +package org.projectfloodlight.openflow.util;
19 +
20 +import static org.junit.Assert.assertEquals;
21 +
22 +import org.junit.Test;
23 +
24 +/**
25 + * Does hexstring conversion work?
26 + *
27 + * @author Rob Sherwood (rob.sherwood@stanford.edu)
28 + */
29 +public class HexStringTest {
30 +
31 + @Test
32 + public void testMarshalling() throws Exception {
33 + String dpidStr = "00:00:00:23:20:2d:16:71";
34 + long dpid = HexString.toLong(dpidStr);
35 + String testStr = HexString.toHexString(dpid);
36 + assertEquals(dpidStr, testStr);
37 + }
38 +
39 + @Test
40 + public void testToLong() {
41 + String dpidStr = "3e:1f:01:fc:72:8c:63:31";
42 + long valid = 0x3e1f01fc728c6331L;
43 + long testLong = HexString.toLong(dpidStr);
44 + assertEquals(valid, testLong);
45 + }
46 +
47 + @Test
48 + public void testToLong2() {
49 + String dpidStr = "1f:1:fc:72:3:f:31";
50 + long valid = 0x1f01fc72030f31L;
51 + long testLong = HexString.toLong(dpidStr);
52 + assertEquals(valid, testLong);
53 + }
54 +
55 + @Test
56 + public void testToLongMSB() {
57 + String dpidStr = "ca:7c:5e:d1:64:7a:95:9b";
58 + long valid = -3856102927509056101L;
59 + long testLong = HexString.toLong(dpidStr);
60 + assertEquals(valid, testLong);
61 + }
62 +
63 + @Test(expected=NumberFormatException.class)
64 + public void testToLongErrorTooManyBytes() {
65 + HexString.toLong("09:08:07:06:05:04:03:02:01");
66 + }
67 +
68 + @Test(expected=NumberFormatException.class)
69 + public void testToLongErrorByteValueTooLong() {
70 + HexString.toLong("234:01");
71 + }
72 +
73 + @Test(expected=NumberFormatException.class)
74 + public void testToLongErrorEmptyByte() {
75 + HexString.toLong("03::01");
76 + }
77 +
78 + @Test(expected=NumberFormatException.class)
79 + public void testToLongErrorInvalidHexDigit() {
80 + HexString.toLong("ss:01");
81 + }
82 +
83 + @Test(expected=NumberFormatException.class)
84 + public void testToLongErrorEmptyString() {
85 + HexString.toLong("");
86 + }
87 +
88 +
89 + @Test
90 + public void testToStringBytes() {
91 + byte[] dpid = { 0, 0, 0, 0, 0, 0, 0, -1 };
92 + String valid = "00:00:00:00:00:00:00:ff";
93 + String testString = HexString.toHexString(dpid);
94 + assertEquals(valid, testString);
95 + }
96 +
97 + @Test(expected=NumberFormatException.class)
98 + public void testFromHexStringError() {
99 + String invalidStr = "00:00:00:00:00:00:ffff";
100 + HexString.fromHexString(invalidStr);
101 + }
102 +}
103 +
1 +package org.projectfloodlight.openflow.util;
2 +
3 +import static org.hamcrest.CoreMatchers.equalTo;
4 +import static org.hamcrest.CoreMatchers.not;
5 +import static org.junit.Assert.assertThat;
6 +
7 +import java.util.Arrays;
8 +
9 +import org.junit.Before;
10 +import org.junit.Test;
11 +import org.projectfloodlight.openflow.types.OFPort;
12 +import org.projectfloodlight.openflow.types.PrimitiveSinkable;
13 +
14 +import com.google.common.collect.ImmutableSortedSet;
15 +import com.google.common.hash.HashCode;
16 +import com.google.common.hash.HashFunction;
17 +import com.google.common.hash.Hasher;
18 +import com.google.common.hash.Hashing;
19 +
20 +public class PrimitiveSinkUtilsTest {
21 +
22 + private HashFunction hash;
23 +
24 + @Before
25 + public void setup() {
26 + hash = Hashing.murmur3_128();
27 + }
28 +
29 + @Test
30 + public void testPutNullableString() {
31 + // test that these different invocations of putNullable
32 + // differ pairwise
33 + HashCode[] hs = new HashCode[] {
34 + calcPutNullableString((String) null),
35 + calcPutNullableString(""),
36 + calcPutNullableString(null, null),
37 + calcPutNullableString(null, ""),
38 + calcPutNullableString("", null),
39 + calcPutNullableString("a\0a", null),
40 + calcPutNullableString(null, "a\0a"),
41 + };
42 +
43 + checkPairwiseDifferent(hs);
44 + }
45 +
46 + @Test
47 + public void testPutNullable() {
48 + // test that these different invocations of putNullable
49 + // differ pairwise
50 + HashCode[] hs = new HashCode[] {
51 + calcPutNullables(),
52 + calcPutNullables(OFPort.of(1)),
53 + calcPutNullables(OFPort.of(1), null),
54 + calcPutNullables(OFPort.of(1), null, null),
55 + calcPutNullables(null, OFPort.of(1), null),
56 + calcPutNullables(null, null, OFPort.of(1))
57 + };
58 +
59 + checkPairwiseDifferent(hs);
60 + }
61 +
62 + private void checkPairwiseDifferent(HashCode[] hs) {
63 + for(int i=0;i<hs.length;i++) {
64 + for(int j=i+1; j<hs.length;j++) {
65 + assertThat(hs[i], not(hs[j]));
66 + }
67 + }
68 + }
69 +
70 + @Test
71 + public void testPutList() {
72 + HashCode[] hs = new HashCode[] {
73 + calcPutList(),
74 + calcPutList(OFPort.of(1)),
75 + calcPutList(OFPort.of(2)),
76 + calcPutList(OFPort.of(1), OFPort.of(2)),
77 + calcPutList(OFPort.of(2), OFPort.of(1)),
78 + calcPutList(OFPort.of(1), OFPort.of(3)),
79 + calcPutList(OFPort.of(1), OFPort.of(2), OFPort.of(3)),
80 + };
81 +
82 + checkPairwiseDifferent(hs);
83 + }
84 +
85 + @Test
86 + public void testPutSortedSet() {
87 + HashCode[] hs = new HashCode[] {
88 + calcPutSortedSet(),
89 + calcPutSortedSet(OFPort.of(1)),
90 + calcPutSortedSet(OFPort.of(2)),
91 + calcPutSortedSet(OFPort.of(1), OFPort.of(2)),
92 + calcPutSortedSet(OFPort.of(1), OFPort.of(3)),
93 + calcPutSortedSet(OFPort.of(1), OFPort.of(2), OFPort.of(3)),
94 + };
95 +
96 + checkPairwiseDifferent(hs);
97 +
98 + assertThat(calcPutSortedSet(OFPort.of(1), OFPort.of(2)),
99 + equalTo(calcPutSortedSet(OFPort.of(2), OFPort.of(1))));
100 + }
101 +
102 + private HashCode calcPutNullableString(String... strings) {
103 + Hasher h = hash.newHasher();
104 + for(String s: strings) {
105 + PrimitiveSinkUtils.putNullableStringTo(h, s);
106 + }
107 + return h.hash();
108 + }
109 +
110 + private HashCode calcPutSortedSet(OFPort... ports) {
111 + Hasher h = hash.newHasher();
112 + PrimitiveSinkUtils.putSortedSetTo(h, ImmutableSortedSet.copyOf(ports));
113 + return h.hash();
114 + }
115 +
116 + private HashCode calcPutList(OFPort... ports) {
117 + Hasher h = hash.newHasher();
118 + PrimitiveSinkUtils.putListTo(h, Arrays.asList(ports));
119 + return h.hash();
120 + }
121 +
122 +
123 + private HashCode calcPutNullables(PrimitiveSinkable... ps) {
124 + Hasher h = hash.newHasher();
125 + for(PrimitiveSinkable p : ps) {
126 + PrimitiveSinkUtils.putNullableTo(h, p);
127 + }
128 + return h.hash();
129 + }
130 +}
1 +package org.projectfloodlight.protocol;
2 +
3 +import static org.junit.Assert.assertFalse;
4 +import static org.junit.Assert.assertThat;
5 +
6 +import org.hamcrest.CoreMatchers;
7 +import org.junit.Before;
8 +import org.junit.Test;
9 +import org.projectfloodlight.openflow.protocol.OFFactories;
10 +import org.projectfloodlight.openflow.protocol.OFOxmList;
11 +import org.projectfloodlight.openflow.protocol.OFVersion;
12 +import org.projectfloodlight.openflow.protocol.match.MatchField;
13 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6DstMasked;
14 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6SrcMasked;
15 +import org.projectfloodlight.openflow.protocol.oxm.OFOxms;
16 +import org.projectfloodlight.openflow.types.IPv6AddressWithMask;
17 +
18 +public class OFOxmListTest {
19 + private OFOxms oxms;
20 +
21 + @Before
22 + public void setup() {
23 + oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
24 + }
25 +
26 + @Test
27 + public void testCanonicalize() {
28 + OFOxmList.Builder builder = new OFOxmList.Builder();
29 + IPv6AddressWithMask fullMasked = IPv6AddressWithMask.of("::/0");
30 + OFOxmIpv6DstMasked fullMaskedOxm = oxms.ipv6DstMasked(fullMasked.getValue(), fullMasked.getMask());
31 + builder.set(fullMaskedOxm);
32 +
33 + IPv6AddressWithMask address= IPv6AddressWithMask.of("1:2:3:4:5:6::8");
34 + OFOxmIpv6SrcMasked addressSrcOxm = oxms.ipv6SrcMasked(address.getValue(), address.getMask());
35 + builder.set(addressSrcOxm);
36 +
37 + OFOxmList list = builder.build();
38 + assertThat(list.get(MatchField.IPV6_DST), CoreMatchers.nullValue());
39 + assertFalse(list.get(MatchField.IPV6_SRC).isMasked());
40 + }
41 +}
1 +package org.projectfloodlight.protocol;
2 +
3 +import static org.junit.Assert.assertEquals;
4 +import static org.junit.Assert.assertFalse;
5 +import static org.junit.Assert.assertNull;
6 +import static org.junit.Assert.assertThat;
7 +import static org.junit.Assert.assertTrue;
8 +
9 +import org.hamcrest.CoreMatchers;
10 +import org.junit.Before;
11 +import org.junit.Test;
12 +import org.projectfloodlight.openflow.protocol.OFFactories;
13 +import org.projectfloodlight.openflow.protocol.OFVersion;
14 +import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
15 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Src;
16 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4SrcMasked;
17 +import org.projectfloodlight.openflow.protocol.oxm.OFOxms;
18 +import org.projectfloodlight.openflow.types.IPv4Address;
19 +import org.projectfloodlight.openflow.types.IPv4AddressWithMask;
20 +
21 +public class OFOxmTest {
22 + private OFOxms oxms;
23 +
24 + @Before
25 + public void setup() {
26 + oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
27 + }
28 +
29 + @Test
30 + public void testGetCanonicalFullMask() {
31 + IPv4AddressWithMask empty = IPv4AddressWithMask.of("0.0.0.0/0");
32 + assertEquals(IPv4Address.FULL_MASK, empty.getMask());
33 + OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(empty.getValue(), empty.getMask());
34 + // canonicalize should remove /0
35 + assertNull(ipv4SrcMasked.getCanonical());
36 + }
37 +
38 + @Test
39 + public void testGetCanonicalNoMask() {
40 + IPv4AddressWithMask fullIp = IPv4AddressWithMask.of("1.2.3.4/32");
41 + assertEquals(IPv4Address.NO_MASK, fullIp.getMask());
42 + OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(fullIp.getValue(), fullIp.getMask());
43 + assertTrue(ipv4SrcMasked.isMasked());
44 + assertEquals(IPv4Address.NO_MASK, ipv4SrcMasked.getMask());
45 +
46 + // canonicalize should convert the masked oxm to the non-masked one
47 + OFOxm<IPv4Address> canonical = ipv4SrcMasked.getCanonical();
48 + assertThat(canonical, CoreMatchers.instanceOf(OFOxmIpv4Src.class));
49 + assertFalse(canonical.isMasked());
50 + }
51 +
52 + @Test
53 + public void testGetCanonicalNormalMask() {
54 + IPv4AddressWithMask ip = IPv4AddressWithMask.of("1.2.3.0/24");
55 + OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(ip.getValue(), ip.getMask());
56 + assertTrue(ipv4SrcMasked.isMasked());
57 +
58 + // canonicalize should convert the masked oxm to the non-masked one
59 + OFOxm<IPv4Address> canonical = ipv4SrcMasked.getCanonical();
60 + assertEquals(ipv4SrcMasked, canonical);
61 + }
62 +}
1 +package org.projectfloodlight.protocol.match;
2 +
3 +import org.projectfloodlight.openflow.protocol.OFFactories;
4 +import org.projectfloodlight.openflow.protocol.OFVersion;
5 +
6 +public class MatchFieldIteration10Test extends MatchFieldIterationBase {
7 + public MatchFieldIteration10Test() {
8 + super(OFFactories.getFactory(OFVersion.OF_10));
9 + }
10 +}
1 +package org.projectfloodlight.protocol.match;
2 +
3 +import org.projectfloodlight.openflow.protocol.OFFactories;
4 +import org.projectfloodlight.openflow.protocol.OFVersion;
5 +
6 +public class MatchFieldIteration13Test extends MatchFieldIterationBase {
7 + public MatchFieldIteration13Test() {
8 + super(OFFactories.getFactory(OFVersion.OF_13));
9 + }
10 +}
1 +package org.projectfloodlight.protocol.match;
2 +
3 +import static org.hamcrest.CoreMatchers.is;
4 +import static org.junit.Assert.assertThat;
5 +import static org.junit.Assert.fail;
6 +
7 +import java.util.Iterator;
8 +
9 +import org.junit.Test;
10 +import org.projectfloodlight.openflow.protocol.OFFactory;
11 +import org.projectfloodlight.openflow.protocol.OFVersion;
12 +import org.projectfloodlight.openflow.protocol.match.Match;
13 +import org.projectfloodlight.openflow.protocol.match.MatchField;
14 +import org.projectfloodlight.openflow.protocol.match.MatchFields;
15 +import org.projectfloodlight.openflow.types.ArpOpcode;
16 +import org.projectfloodlight.openflow.types.EthType;
17 +import org.projectfloodlight.openflow.types.IPv4Address;
18 +import org.projectfloodlight.openflow.types.IpProtocol;
19 +import org.projectfloodlight.openflow.types.MacAddress;
20 +import org.projectfloodlight.openflow.types.Masked;
21 +import org.projectfloodlight.openflow.types.OFPort;
22 +import org.projectfloodlight.openflow.types.TransportPort;
23 +
24 +import com.google.common.collect.Iterables;
25 +
26 +public class MatchFieldIterationBase {
27 +
28 + private OFFactory factory;
29 +
30 + protected MatchFieldIterationBase(OFFactory factory) {
31 + this.factory = factory;
32 + }
33 +
34 + @Test
35 + public void iterateEmptyMatch() {
36 + Match match = factory.buildMatch().build();
37 + Iterator<MatchField<?>> iter = match.getMatchFields().iterator();
38 + assertThat(iter.hasNext(), is(false));
39 + }
40 +
41 + @Test
42 + public void iterateSingleExactMatchField() {
43 + OFPort port5 = OFPort.of(5);
44 + Match match = factory.buildMatch()
45 + .setExact(MatchField.IN_PORT, port5)
46 + .build();
47 + Iterator<MatchField<?>> iter = match.getMatchFields().iterator();
48 + assertThat(iter.hasNext(), is(true));
49 + MatchField<?> matchField = iter.next();
50 + assertThat(matchField.id, is(MatchFields.IN_PORT));
51 + assertThat(match.isExact(matchField), is(true));
52 + @SuppressWarnings("unchecked")
53 + MatchField<OFPort> portMatchField = (MatchField<OFPort>) matchField;
54 + OFPort port = match.get(portMatchField);
55 + assertThat(port, is(port5));
56 + assertThat(iter.hasNext(), is(false));
57 + }
58 +
59 + @SuppressWarnings("unchecked")
60 + @Test
61 + public void iterateExactMatchFields() {
62 + OFPort port5 = OFPort.of(5);
63 + MacAddress macSrc = MacAddress.of("00:01:02:03:04:05");
64 + MacAddress macDst = MacAddress.of("01:01:02:02:03:03");
65 + IPv4Address ipSrc = IPv4Address.of("10.192.20.1");
66 + IPv4Address ipDst = IPv4Address.of("10.192.20.2");
67 + TransportPort tcpSrc = TransportPort.of(100);
68 + TransportPort tcpDst = TransportPort.of(200);
69 + Match match = factory.buildMatch()
70 + .setExact(MatchField.IN_PORT, port5)
71 + .setExact(MatchField.ETH_TYPE, EthType.IPv4)
72 + .setExact(MatchField.ETH_SRC, macSrc)
73 + .setExact(MatchField.ETH_DST, macDst)
74 + .setExact(MatchField.IP_PROTO, IpProtocol.TCP)
75 + .setExact(MatchField.IPV4_SRC, ipSrc)
76 + .setExact(MatchField.IPV4_DST, ipDst)
77 + .setExact(MatchField.TCP_SRC, tcpSrc)
78 + .setExact(MatchField.TCP_DST, tcpDst)
79 + .build();
80 + assertThat(Iterables.size(match.getMatchFields()), is(9));
81 + for (MatchField<?> matchField: match.getMatchFields()) {
82 + switch (matchField.id) {
83 + case IN_PORT:
84 + OFPort port = match.get((MatchField<OFPort>) matchField);
85 + assertThat(port, is(port5));
86 + break;
87 + case ETH_TYPE:
88 + EthType ethType = match.get((MatchField<EthType>) matchField);
89 + assertThat(ethType, is(EthType.IPv4));
90 + break;
91 + case ETH_SRC:
92 + MacAddress mac = match.get((MatchField<MacAddress>) matchField);
93 + assertThat(mac, is(macSrc));
94 + break;
95 + case ETH_DST:
96 + mac = match.get((MatchField<MacAddress>) matchField);
97 + assertThat(mac, is(macDst));
98 + break;
99 + case IP_PROTO:
100 + IpProtocol ipProtocol = match.get((MatchField<IpProtocol>) matchField);
101 + assertThat(ipProtocol, is(IpProtocol.TCP));
102 + break;
103 + case IPV4_SRC:
104 + IPv4Address ip = match.get((MatchField<IPv4Address>) matchField);
105 + assertThat(ip, is(ipSrc));
106 + break;
107 + case IPV4_DST:
108 + ip = match.get((MatchField<IPv4Address>) matchField);
109 + assertThat(ip, is(ipDst));
110 + break;
111 + case TCP_SRC:
112 + TransportPort tcp = match.get((MatchField<TransportPort>) matchField);
113 + assertThat(tcp, is(tcpSrc));
114 + break;
115 + case TCP_DST:
116 + tcp = match.get((MatchField<TransportPort>) matchField);
117 + assertThat(tcp, is(tcpDst));
118 + break;
119 + default:
120 + fail("Unexpected match field returned from iterator");
121 + }
122 + }
123 + }
124 +
125 + @SuppressWarnings("unchecked")
126 + @Test
127 + public void iterateArpFields() {
128 + MacAddress macSrc = MacAddress.of("00:01:02:03:04:05");
129 + MacAddress macDst = MacAddress.of("01:01:02:02:03:03");
130 + IPv4Address ipSrc = IPv4Address.of("10.192.20.1");
131 + IPv4Address ipDst = IPv4Address.of("10.192.20.2");
132 + OFVersion version = factory.getVersion();
133 + boolean supportsArpHardwareAddress = (version != OFVersion.OF_10) &&
134 + (version != OFVersion.OF_11) && (version != OFVersion.OF_12);
135 + int matchFieldCount = 4;
136 + Match.Builder builder = factory.buildMatch();
137 + builder.setExact(MatchField.ETH_TYPE, EthType.ARP)
138 + .setExact(MatchField.ARP_OP, ArpOpcode.REPLY)
139 + .setExact(MatchField.ARP_SPA, ipSrc)
140 + .setExact(MatchField.ARP_TPA, ipDst);
141 + if (supportsArpHardwareAddress) {
142 + builder.setExact(MatchField.ARP_SHA, macSrc);
143 + builder.setExact(MatchField.ARP_THA, macDst);
144 + matchFieldCount += 2;
145 + }
146 + Match match = builder.build();
147 + assertThat(Iterables.size(match.getMatchFields()), is(matchFieldCount));
148 + for (MatchField<?> matchField: match.getMatchFields()) {
149 + switch (matchField.id) {
150 + case ETH_TYPE:
151 + EthType ethType = match.get((MatchField<EthType>) matchField);
152 + assertThat(ethType, is(EthType.ARP));
153 + break;
154 + case ARP_OP:
155 + ArpOpcode opcode = match.get((MatchField<ArpOpcode>) matchField);
156 + assertThat(opcode, is(ArpOpcode.REPLY));
157 + break;
158 + case ARP_SHA:
159 + MacAddress mac = match.get((MatchField<MacAddress>) matchField);
160 + assertThat(mac, is(macSrc));
161 + break;
162 + case ARP_THA:
163 + mac = match.get((MatchField<MacAddress>) matchField);
164 + assertThat(mac, is(macDst));
165 + break;
166 + case ARP_SPA:
167 + IPv4Address ip = match.get((MatchField<IPv4Address>) matchField);
168 + assertThat(ip, is(ipSrc));
169 + break;
170 + case ARP_TPA:
171 + ip = match.get((MatchField<IPv4Address>) matchField);
172 + assertThat(ip, is(ipDst));
173 + break;
174 + default:
175 + fail("Unexpected match field returned from iterator");
176 + }
177 + }
178 + }
179 +
180 + @SuppressWarnings("unchecked")
181 + @Test
182 + public void iterateMaskedFields() {
183 + MacAddress macSrc = MacAddress.of("01:02:03:04:00:00");
184 + MacAddress macSrcMask = MacAddress.of("FF:FF:FF:FF:00:00");
185 + MacAddress macDst = MacAddress.of("11:22:33:00:00:00");
186 + MacAddress macDstMask = MacAddress.of("FF:FF:FF:00:00:00");
187 + IPv4Address ipSrc = IPv4Address.of("10.192.20.0");
188 + IPv4Address ipSrcMask = IPv4Address.of("255.255.255.0");
189 + IPv4Address ipDst = IPv4Address.of("10.192.20.0");
190 + IPv4Address ipDstMask = IPv4Address.of("255.255.255.128");
191 + TransportPort tcpSrcMask = TransportPort.of(0x01F0);
192 + OFVersion version = factory.getVersion();
193 + boolean supportsAllMasks = (version != OFVersion.OF_10) &&
194 + (version != OFVersion.OF_11) && (version != OFVersion.OF_12);
195 + int matchFieldCount = 4;
196 + Match.Builder builder = factory.buildMatch()
197 + .setExact(MatchField.ETH_TYPE, EthType.IPv4)
198 + .setMasked(MatchField.IPV4_SRC, ipSrc, ipSrcMask)
199 + .setMasked(MatchField.IPV4_DST, ipDst, ipDstMask)
200 + .setExact(MatchField.IP_PROTO, IpProtocol.TCP);
201 + if (supportsAllMasks) {
202 + builder.setMasked(MatchField.ETH_SRC, macSrc, macSrcMask);
203 + builder.setMasked(MatchField.ETH_DST, macDst, macDstMask);
204 + builder.setMasked(MatchField.TCP_SRC, tcpSrcMask, tcpSrcMask);
205 + matchFieldCount += 3;
206 + }
207 + Match match = builder.build();
208 + assertThat(Iterables.size(match.getMatchFields()), is(matchFieldCount));
209 + for (MatchField<?> matchField: match.getMatchFields()) {
210 + switch (matchField.id) {
211 + case ETH_TYPE:
212 + EthType ethType = match.get((MatchField<EthType>) matchField);
213 + assertThat(ethType, is(EthType.IPv4));
214 + break;
215 + case ETH_SRC:
216 + Masked<MacAddress> mac = match.getMasked((MatchField<MacAddress>) matchField);
217 + assertThat(mac.getValue(), is(macSrc));
218 + assertThat(mac.getMask(), is(macSrcMask));
219 + break;
220 + case ETH_DST:
221 + mac = match.getMasked((MatchField<MacAddress>) matchField);
222 + assertThat(mac.getValue(), is(macDst));
223 + assertThat(mac.getMask(), is(macDstMask));
224 + break;
225 + case IP_PROTO:
226 + IpProtocol ipProtocol = match.get((MatchField<IpProtocol>) matchField);
227 + assertThat(ipProtocol, is(IpProtocol.TCP));
228 + break;
229 + case IPV4_SRC:
230 + Masked<IPv4Address> ip = match.getMasked((MatchField<IPv4Address>) matchField);
231 + assertThat(ip.getValue(), is(ipSrc));
232 + assertThat(ip.getMask(), is(ipSrcMask));
233 + break;
234 + case IPV4_DST:
235 + ip = match.getMasked((MatchField<IPv4Address>) matchField);
236 + assertThat(ip.getValue(), is(ipDst));
237 + assertThat(ip.getMask(), is(ipDstMask));
238 + break;
239 + case TCP_SRC:
240 + Masked<TransportPort> tcp = match.getMasked((MatchField<TransportPort>) matchField);
241 + assertThat(tcp.getValue(), is(tcpSrcMask));
242 + assertThat(tcp.getMask(), is(tcpSrcMask));
243 + break;
244 + default:
245 + fail("Unexpected match field returned from iterator");
246 + }
247 + }
248 + }
249 +}
1 +package org.projectfloodlight.test;
2 +
3 +import java.util.ArrayList;
4 +import java.util.List;
5 +
6 +import org.junit.Assert;
7 +
8 +import com.google.common.base.Function;
9 +import com.google.common.base.Joiner;
10 +import com.google.common.collect.Lists;
11 +import com.google.common.primitives.Bytes;
12 +
13 +public class TestUtils {
14 + private TestUtils() {}
15 +
16 + private static final int PER_LINE = 8;
17 +
18 + public static void betterAssertArrayEquals(byte[] expected, byte[] got) {
19 + int maxlen = Math.max(expected.length, got.length);
20 +
21 + List<String> expectedList = formatHex(Bytes.asList(expected));
22 + List<String> gotList = formatHex(Bytes.asList(got));
23 +
24 + boolean fail = false;
25 + for (int i = 0; i < maxlen;i+= PER_LINE) {
26 + int maxThisLine = Math.min(maxlen, PER_LINE);
27 + boolean print = false;
28 +
29 + ArrayList<String> changeMarkers = new ArrayList<String>();
30 +
31 + for (int j = i; j < maxThisLine; j++) {
32 + if (j >= expected.length || j >= got.length || expected[j] != got[j]) {
33 + print = true;
34 + fail = true;
35 + changeMarkers.add("==");
36 + break;
37 + } else {
38 + changeMarkers.add(" ");
39 + }
40 + }
41 + if(print) {
42 + System.out.println(String.format("%4x: %s", i, Joiner.on(" ").join(expectedList.subList(i, Math.min(expectedList.size(), i+PER_LINE)))));
43 + System.out.println(String.format("%4x: %s", i, Joiner.on(" ").join(gotList.subList(i, Math.min(gotList.size(), i+PER_LINE)))));
44 + System.out.println(String.format("%4s %s", "", Joiner.on(" ").join(changeMarkers)));
45 + System.out.println("\n");
46 + }
47 + }
48 + if(fail) {
49 + Assert.fail("Array comparison failed");
50 + }
51 +
52 + }
53 +
54 + private static List<String> formatHex(List<Byte> b) {
55 + return Lists.transform(b, new Function<Byte, String>() {
56 + @Override
57 + public String apply(Byte input) {
58 + return String.format("%02x", input);
59 + }
60 + });
61 + }
62 +}
...\ No newline at end of file ...\ No newline at end of file
1 +<configuration scan="true">
2 + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 + <encoder>
4 + <pattern>%d{HH:mm:ss.SSS} %level [%logger{20}:%thread] %msg%n</pattern>
5 + </encoder>
6 + </appender>
7 + <root level="INFO">
8 + <appender-ref ref="STDOUT" />
9 + </root>
10 + <logger name="org" level="WARN"/>
11 + <logger name="LogService" level="WARN"/> <!-- Restlet access logging -->
12 + <logger name="org.projectfloodlight.openflow" level="DEBUG"/>
13 +</configuration>
File mode changed
1 +<!--
2 + ~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
3 + ~
4 + ~ This program and the accompanying materials are made available under the
5 + ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 + ~ and is available at http://www.eclipse.org/legal/epl-v10.html
7 + -->
8 +
9 +<project xmlns="http://maven.apache.org/POM/4.0.0"
10 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
11 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
12 + <modelVersion>4.0.0</modelVersion>
13 +
14 + <groupId>net.onrc.onos</groupId>
15 + <artifactId>onos-features</artifactId>
16 + <packaging>jar</packaging>
17 + <version>1.0.0-SNAPSHOT</version>
18 +
19 + <name>onos-features</name>
20 + <description>Apache Karaf features repository</description>
21 +
22 + <dependencies>
23 + <!--<dependency>
24 + <groupId>commons-codec</groupId>
25 + <artifactId>commons-codec</artifactId>
26 + <version>1.7</version>
27 + </dependency>
28 + <dependency>
29 + <groupId>commons-io</groupId>
30 + <artifactId>commons-io</artifactId>
31 + <version>2.4</version>
32 + </dependency>
33 + <dependency>
34 + <groupId>commons-lang</groupId>
35 + <artifactId>commons-lang</artifactId>
36 + <version>2.6</version>
37 + </dependency>
38 + <dependency>
39 + <groupId>commons-configuration</groupId>
40 + <artifactId>commons-configuration</artifactId>
41 + <version>1.10</version>
42 + </dependency>-->
43 + </dependencies>
44 +
45 + <build>
46 + <plugins>
47 + <plugin>
48 + <groupId>org.codehaus.mojo</groupId>
49 + <artifactId>build-helper-maven-plugin</artifactId>
50 + <version>1.3</version>
51 + <executions>
52 + <execution>
53 + <id>attach-artifacts</id>
54 + <phase>package</phase>
55 + <goals>
56 + <goal>attach-artifact</goal>
57 + </goals>
58 + <configuration>
59 + <artifacts>
60 + <artifact>
61 + <file>features.xml</file>
62 + <type>xml</type>
63 + <classifier>features</classifier>
64 + </artifact>
65 + </artifacts>
66 + </configuration>
67 + </execution>
68 + </executions>
69 + </plugin>
70 + </plugins>
71 + </build>
72 +
73 +</project>