Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
60 changed files
with
1738 additions
and
191 deletions
... | @@ -3,8 +3,6 @@ package org.onlab.onos.config; | ... | @@ -3,8 +3,6 @@ package org.onlab.onos.config; |
3 | import java.util.List; | 3 | import java.util.List; |
4 | 4 | ||
5 | import org.codehaus.jackson.annotate.JsonProperty; | 5 | import org.codehaus.jackson.annotate.JsonProperty; |
6 | -import org.onlab.packet.IpPrefix; | ||
7 | -import org.onlab.packet.MacAddress; | ||
8 | 6 | ||
9 | /** | 7 | /** |
10 | * Represents a set of addresses bound to a port. | 8 | * Represents a set of addresses bound to a port. |
... | @@ -12,8 +10,8 @@ import org.onlab.packet.MacAddress; | ... | @@ -12,8 +10,8 @@ import org.onlab.packet.MacAddress; |
12 | public class AddressEntry { | 10 | public class AddressEntry { |
13 | private String dpid; | 11 | private String dpid; |
14 | private short portNumber; | 12 | private short portNumber; |
15 | - private List<IpPrefix> ipAddresses; | 13 | + private List<String> ipAddresses; |
16 | - private MacAddress macAddress; | 14 | + private String macAddress; |
17 | 15 | ||
18 | public String getDpid() { | 16 | public String getDpid() { |
19 | return dpid; | 17 | return dpid; |
... | @@ -33,21 +31,21 @@ public class AddressEntry { | ... | @@ -33,21 +31,21 @@ public class AddressEntry { |
33 | this.portNumber = portNumber; | 31 | this.portNumber = portNumber; |
34 | } | 32 | } |
35 | 33 | ||
36 | - public List<IpPrefix> getIpAddresses() { | 34 | + public List<String> getIpAddresses() { |
37 | return ipAddresses; | 35 | return ipAddresses; |
38 | } | 36 | } |
39 | 37 | ||
40 | @JsonProperty("ips") | 38 | @JsonProperty("ips") |
41 | - public void setIpAddresses(List<IpPrefix> ipAddresses) { | 39 | + public void setIpAddresses(List<String> strIps) { |
42 | - this.ipAddresses = ipAddresses; | 40 | + this.ipAddresses = strIps; |
43 | } | 41 | } |
44 | 42 | ||
45 | - public MacAddress getMacAddress() { | 43 | + public String getMacAddress() { |
46 | return macAddress; | 44 | return macAddress; |
47 | } | 45 | } |
48 | 46 | ||
49 | @JsonProperty("mac") | 47 | @JsonProperty("mac") |
50 | - public void setMacAddress(MacAddress macAddress) { | 48 | + public void setMacAddress(String macAddress) { |
51 | this.macAddress = macAddress; | 49 | this.macAddress = macAddress; |
52 | } | 50 | } |
53 | } | 51 | } | ... | ... |
... | @@ -5,6 +5,8 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -5,6 +5,8 @@ import static org.slf4j.LoggerFactory.getLogger; |
5 | import java.io.File; | 5 | import java.io.File; |
6 | import java.io.FileNotFoundException; | 6 | import java.io.FileNotFoundException; |
7 | import java.io.IOException; | 7 | import java.io.IOException; |
8 | +import java.util.HashSet; | ||
9 | +import java.util.Set; | ||
8 | 10 | ||
9 | import org.apache.felix.scr.annotations.Activate; | 11 | import org.apache.felix.scr.annotations.Activate; |
10 | import org.apache.felix.scr.annotations.Component; | 12 | import org.apache.felix.scr.annotations.Component; |
... | @@ -17,10 +19,10 @@ import org.onlab.onos.net.DeviceId; | ... | @@ -17,10 +19,10 @@ import org.onlab.onos.net.DeviceId; |
17 | import org.onlab.onos.net.PortNumber; | 19 | import org.onlab.onos.net.PortNumber; |
18 | import org.onlab.onos.net.host.HostAdminService; | 20 | import org.onlab.onos.net.host.HostAdminService; |
19 | import org.onlab.onos.net.host.PortAddresses; | 21 | import org.onlab.onos.net.host.PortAddresses; |
22 | +import org.onlab.packet.IpPrefix; | ||
23 | +import org.onlab.packet.MacAddress; | ||
20 | import org.slf4j.Logger; | 24 | import org.slf4j.Logger; |
21 | 25 | ||
22 | -import com.google.common.collect.Sets; | ||
23 | - | ||
24 | /** | 26 | /** |
25 | * Simple configuration module to read in supplementary network configuration | 27 | * Simple configuration module to read in supplementary network configuration |
26 | * from a file. | 28 | * from a file. |
... | @@ -51,9 +53,29 @@ public class NetworkConfigReader { | ... | @@ -51,9 +53,29 @@ public class NetworkConfigReader { |
51 | DeviceId.deviceId(dpidToUri(entry.getDpid())), | 53 | DeviceId.deviceId(dpidToUri(entry.getDpid())), |
52 | PortNumber.portNumber(entry.getPortNumber())); | 54 | PortNumber.portNumber(entry.getPortNumber())); |
53 | 55 | ||
54 | - PortAddresses addresses = new PortAddresses(cp, | 56 | + Set<IpPrefix> ipAddresses = new HashSet<IpPrefix>(); |
55 | - Sets.newHashSet(entry.getIpAddresses()), | 57 | + |
58 | + for (String strIp : entry.getIpAddresses()) { | ||
59 | + try { | ||
60 | + IpPrefix address = IpPrefix.valueOf(strIp); | ||
61 | + ipAddresses.add(address); | ||
62 | + } catch (IllegalArgumentException e) { | ||
63 | + log.warn("Bad format for IP address in config: {}", strIp); | ||
64 | + } | ||
65 | + } | ||
66 | + | ||
67 | + MacAddress macAddress = null; | ||
68 | + if (entry.getMacAddress() != null) { | ||
69 | + try { | ||
70 | + macAddress = MacAddress.valueOf(entry.getMacAddress()); | ||
71 | + } catch (IllegalArgumentException e) { | ||
72 | + log.warn("Bad format for MAC address in config: {}", | ||
56 | entry.getMacAddress()); | 73 | entry.getMacAddress()); |
74 | + } | ||
75 | + } | ||
76 | + | ||
77 | + PortAddresses addresses = new PortAddresses(cp, | ||
78 | + ipAddresses, macAddress); | ||
57 | 79 | ||
58 | hostAdminService.bindAddressesToPort(addresses); | 80 | hostAdminService.bindAddressesToPort(addresses); |
59 | } | 81 | } | ... | ... |
1 | +package org.onlab.onos.net.intent; | ||
2 | +//TODO is this the right package? | ||
3 | + | ||
4 | +/** | ||
5 | + * A generalized interface for ID generation | ||
6 | + * | ||
7 | + * {@link #getNewId()} generates a globally unique ID instance on | ||
8 | + * each invocation. | ||
9 | + * | ||
10 | + * @param <T> the type of ID | ||
11 | + */ | ||
12 | +// TODO: do we need to define a base marker interface for ID, | ||
13 | +// then changed the type parameter to <T extends BaseId> something | ||
14 | +// like that? | ||
15 | +public interface IdGenerator<T> { | ||
16 | + /** | ||
17 | + * Returns a globally unique ID instance. | ||
18 | + * | ||
19 | + * @return globally unique ID instance | ||
20 | + */ | ||
21 | + T getNewId(); | ||
22 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import java.util.Set; | ||
4 | + | ||
5 | +import org.onlab.onos.net.ConnectPoint; | ||
6 | +import org.onlab.onos.net.DeviceId; | ||
7 | +import org.onlab.onos.net.PortNumber; | ||
8 | +import org.onlab.onos.net.flow.DefaultTrafficSelector; | ||
9 | +import org.onlab.onos.net.flow.DefaultTrafficTreatment; | ||
10 | +import org.onlab.onos.net.flow.TrafficSelector; | ||
11 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
12 | + | ||
13 | +/** | ||
14 | + * Base facilities to test various connectivity tests. | ||
15 | + */ | ||
16 | +public abstract class ConnectivityIntentTest extends IntentTest { | ||
17 | + | ||
18 | + public static final IntentId IID = new IntentId(123); | ||
19 | + public static final TrafficSelector MATCH = (new DefaultTrafficSelector.Builder()).build(); | ||
20 | + public static final TrafficTreatment NOP = (new DefaultTrafficTreatment.Builder()).build(); | ||
21 | + | ||
22 | + public static final ConnectPoint P1 = new ConnectPoint(DeviceId.deviceId("111"), PortNumber.portNumber(0x1)); | ||
23 | + public static final ConnectPoint P2 = new ConnectPoint(DeviceId.deviceId("222"), PortNumber.portNumber(0x2)); | ||
24 | + public static final ConnectPoint P3 = new ConnectPoint(DeviceId.deviceId("333"), PortNumber.portNumber(0x3)); | ||
25 | + | ||
26 | + public static final Set<ConnectPoint> PS1 = itemSet(new ConnectPoint[]{P1, P3}); | ||
27 | + public static final Set<ConnectPoint> PS2 = itemSet(new ConnectPoint[]{P2, P3}); | ||
28 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import java.util.ArrayList; | ||
4 | +import java.util.Collections; | ||
5 | +import java.util.HashMap; | ||
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.ExecutorService; | ||
11 | +import java.util.concurrent.Executors; | ||
12 | + | ||
13 | +/** | ||
14 | + * Fake implementation of the intent service to assist in developing tests | ||
15 | + * of the interface contract. | ||
16 | + */ | ||
17 | +public class FakeIntentManager implements TestableIntentService { | ||
18 | + | ||
19 | + private final Map<IntentId, Intent> intents = new HashMap<>(); | ||
20 | + private final Map<IntentId, IntentState> intentStates = new HashMap<>(); | ||
21 | + private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>(); | ||
22 | + private final Set<IntentEventListener> listeners = new HashSet<>(); | ||
23 | + | ||
24 | + private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>(); | ||
25 | + private final Map<Class<? extends InstallableIntent>, | ||
26 | + IntentInstaller<? extends InstallableIntent>> installers = new HashMap<>(); | ||
27 | + | ||
28 | + private final ExecutorService executor = Executors.newSingleThreadExecutor(); | ||
29 | + private final List<IntentException> exceptions = new ArrayList<>(); | ||
30 | + | ||
31 | + @Override | ||
32 | + public List<IntentException> getExceptions() { | ||
33 | + return exceptions; | ||
34 | + } | ||
35 | + | ||
36 | + // Provides an out-of-thread simulation of intent submit life-cycle | ||
37 | + private void executeSubmit(final Intent intent) { | ||
38 | + registerSubclassCompilerIfNeeded(intent); | ||
39 | + executor.execute(new Runnable() { | ||
40 | + @Override | ||
41 | + public void run() { | ||
42 | + try { | ||
43 | + List<InstallableIntent> installable = compileIntent(intent); | ||
44 | + installIntents(intent, installable); | ||
45 | + } catch (IntentException e) { | ||
46 | + exceptions.add(e); | ||
47 | + } | ||
48 | + } | ||
49 | + }); | ||
50 | + } | ||
51 | + | ||
52 | + // Provides an out-of-thread simulation of intent withdraw life-cycle | ||
53 | + private void executeWithdraw(final Intent intent) { | ||
54 | + executor.execute(new Runnable() { | ||
55 | + @Override | ||
56 | + public void run() { | ||
57 | + try { | ||
58 | + List<InstallableIntent> installable = getInstallable(intent.getId()); | ||
59 | + uninstallIntents(intent, installable); | ||
60 | + } catch (IntentException e) { | ||
61 | + exceptions.add(e); | ||
62 | + } | ||
63 | + | ||
64 | + } | ||
65 | + }); | ||
66 | + } | ||
67 | + | ||
68 | + private <T extends Intent> IntentCompiler<T> getCompiler(T intent) { | ||
69 | + @SuppressWarnings("unchecked") | ||
70 | + IntentCompiler<T> compiler = (IntentCompiler<T>) compilers.get(intent.getClass()); | ||
71 | + if (compiler == null) { | ||
72 | + throw new IntentException("no compiler for class " + intent.getClass()); | ||
73 | + } | ||
74 | + return compiler; | ||
75 | + } | ||
76 | + | ||
77 | + private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) { | ||
78 | + @SuppressWarnings("unchecked") | ||
79 | + IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass()); | ||
80 | + if (installer == null) { | ||
81 | + throw new IntentException("no installer for class " + intent.getClass()); | ||
82 | + } | ||
83 | + return installer; | ||
84 | + } | ||
85 | + | ||
86 | + private <T extends Intent> List<InstallableIntent> compileIntent(T intent) { | ||
87 | + try { | ||
88 | + // For the fake, we compile using a single level pass | ||
89 | + List<InstallableIntent> installable = new ArrayList<>(); | ||
90 | + for (Intent compiled : getCompiler(intent).compile(intent)) { | ||
91 | + installable.add((InstallableIntent) compiled); | ||
92 | + } | ||
93 | + setState(intent, IntentState.COMPILED); | ||
94 | + return installable; | ||
95 | + } catch (IntentException e) { | ||
96 | + setState(intent, IntentState.FAILED); | ||
97 | + throw e; | ||
98 | + } | ||
99 | + } | ||
100 | + | ||
101 | + private void installIntents(Intent intent, List<InstallableIntent> installable) { | ||
102 | + try { | ||
103 | + for (InstallableIntent ii : installable) { | ||
104 | + registerSubclassInstallerIfNeeded(ii); | ||
105 | + getInstaller(ii).install(ii); | ||
106 | + } | ||
107 | + setState(intent, IntentState.INSTALLED); | ||
108 | + putInstallable(intent.getId(), installable); | ||
109 | + } catch (IntentException e) { | ||
110 | + setState(intent, IntentState.FAILED); | ||
111 | + throw e; | ||
112 | + } | ||
113 | + } | ||
114 | + | ||
115 | + private void uninstallIntents(Intent intent, List<InstallableIntent> installable) { | ||
116 | + try { | ||
117 | + for (InstallableIntent ii : installable) { | ||
118 | + getInstaller(ii).uninstall(ii); | ||
119 | + } | ||
120 | + setState(intent, IntentState.WITHDRAWN); | ||
121 | + removeInstallable(intent.getId()); | ||
122 | + } catch (IntentException e) { | ||
123 | + setState(intent, IntentState.FAILED); | ||
124 | + throw e; | ||
125 | + } | ||
126 | + } | ||
127 | + | ||
128 | + | ||
129 | + // Sets the internal state for the given intent and dispatches an event | ||
130 | + private void setState(Intent intent, IntentState state) { | ||
131 | + IntentState previous = intentStates.get(intent.getId()); | ||
132 | + intentStates.put(intent.getId(), state); | ||
133 | + dispatch(new IntentEvent(intent, state, previous, System.currentTimeMillis())); | ||
134 | + } | ||
135 | + | ||
136 | + private void putInstallable(IntentId id, List<InstallableIntent> installable) { | ||
137 | + installables.put(id, installable); | ||
138 | + } | ||
139 | + | ||
140 | + private void removeInstallable(IntentId id) { | ||
141 | + installables.remove(id); | ||
142 | + } | ||
143 | + | ||
144 | + private List<InstallableIntent> getInstallable(IntentId id) { | ||
145 | + List<InstallableIntent> installable = installables.get(id); | ||
146 | + if (installable != null) { | ||
147 | + return installable; | ||
148 | + } else { | ||
149 | + return Collections.emptyList(); | ||
150 | + } | ||
151 | + } | ||
152 | + | ||
153 | + @Override | ||
154 | + public void submit(Intent intent) { | ||
155 | + intents.put(intent.getId(), intent); | ||
156 | + setState(intent, IntentState.SUBMITTED); | ||
157 | + executeSubmit(intent); | ||
158 | + } | ||
159 | + | ||
160 | + @Override | ||
161 | + public void withdraw(Intent intent) { | ||
162 | + intents.remove(intent.getId()); | ||
163 | + setState(intent, IntentState.WITHDRAWING); | ||
164 | + executeWithdraw(intent); | ||
165 | + } | ||
166 | + | ||
167 | + @Override | ||
168 | + public void execute(IntentOperations operations) { | ||
169 | + // TODO: implement later | ||
170 | + } | ||
171 | + | ||
172 | + @Override | ||
173 | + public Set<Intent> getIntents() { | ||
174 | + return Collections.unmodifiableSet(new HashSet<>(intents.values())); | ||
175 | + } | ||
176 | + | ||
177 | + @Override | ||
178 | + public Intent getIntent(IntentId id) { | ||
179 | + return intents.get(id); | ||
180 | + } | ||
181 | + | ||
182 | + @Override | ||
183 | + public IntentState getIntentState(IntentId id) { | ||
184 | + return intentStates.get(id); | ||
185 | + } | ||
186 | + | ||
187 | + @Override | ||
188 | + public void addListener(IntentEventListener listener) { | ||
189 | + listeners.add(listener); | ||
190 | + } | ||
191 | + | ||
192 | + @Override | ||
193 | + public void removeListener(IntentEventListener listener) { | ||
194 | + listeners.remove(listener); | ||
195 | + } | ||
196 | + | ||
197 | + private void dispatch(IntentEvent event) { | ||
198 | + for (IntentEventListener listener : listeners) { | ||
199 | + listener.event(event); | ||
200 | + } | ||
201 | + } | ||
202 | + | ||
203 | + @Override | ||
204 | + public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) { | ||
205 | + compilers.put(cls, compiler); | ||
206 | + } | ||
207 | + | ||
208 | + @Override | ||
209 | + public <T extends Intent> void unregisterCompiler(Class<T> cls) { | ||
210 | + compilers.remove(cls); | ||
211 | + } | ||
212 | + | ||
213 | + @Override | ||
214 | + public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() { | ||
215 | + return Collections.unmodifiableMap(compilers); | ||
216 | + } | ||
217 | + | ||
218 | + @Override | ||
219 | + public <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) { | ||
220 | + installers.put(cls, installer); | ||
221 | + } | ||
222 | + | ||
223 | + @Override | ||
224 | + public <T extends InstallableIntent> void unregisterInstaller(Class<T> cls) { | ||
225 | + installers.remove(cls); | ||
226 | + } | ||
227 | + | ||
228 | + @Override | ||
229 | + public Map<Class<? extends InstallableIntent>, | ||
230 | + IntentInstaller<? extends InstallableIntent>> getInstallers() { | ||
231 | + return Collections.unmodifiableMap(installers); | ||
232 | + } | ||
233 | + | ||
234 | + private void registerSubclassCompilerIfNeeded(Intent intent) { | ||
235 | + if (!compilers.containsKey(intent.getClass())) { | ||
236 | + Class<?> cls = intent.getClass(); | ||
237 | + while (cls != Object.class) { | ||
238 | + // As long as we're within the Intent class descendants | ||
239 | + if (Intent.class.isAssignableFrom(cls)) { | ||
240 | + IntentCompiler<?> compiler = compilers.get(cls); | ||
241 | + if (compiler != null) { | ||
242 | + compilers.put(intent.getClass(), compiler); | ||
243 | + return; | ||
244 | + } | ||
245 | + } | ||
246 | + cls = cls.getSuperclass(); | ||
247 | + } | ||
248 | + } | ||
249 | + } | ||
250 | + | ||
251 | + private void registerSubclassInstallerIfNeeded(InstallableIntent intent) { | ||
252 | + if (!installers.containsKey(intent.getClass())) { | ||
253 | + Class<?> cls = intent.getClass(); | ||
254 | + while (cls != Object.class) { | ||
255 | + // As long as we're within the InstallableIntent class descendants | ||
256 | + if (InstallableIntent.class.isAssignableFrom(cls)) { | ||
257 | + IntentInstaller<?> installer = installers.get(cls); | ||
258 | + if (installer != null) { | ||
259 | + installers.put(intent.getClass(), installer); | ||
260 | + return; | ||
261 | + } | ||
262 | + } | ||
263 | + cls = cls.getSuperclass(); | ||
264 | + } | ||
265 | + } | ||
266 | + } | ||
267 | + | ||
268 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | +//TODO is this the right package? | ||
3 | + | ||
4 | +import org.hamcrest.Description; | ||
5 | +import org.hamcrest.StringDescription; | ||
6 | + | ||
7 | +import java.lang.reflect.Field; | ||
8 | +import java.lang.reflect.Method; | ||
9 | +import java.lang.reflect.Modifier; | ||
10 | + | ||
11 | +/** | ||
12 | + * Hamcrest style class for verifying that a class follows the | ||
13 | + * accepted rules for immutable classes. | ||
14 | + * | ||
15 | + * The rules that are enforced for immutable classes: | ||
16 | + * - the class must be declared final | ||
17 | + * - all data members of the class must be declared private and final | ||
18 | + * - the class must not define any setter methods | ||
19 | + */ | ||
20 | + | ||
21 | +public class ImmutableClassChecker { | ||
22 | + | ||
23 | + private String failureReason = ""; | ||
24 | + | ||
25 | + /** | ||
26 | + * Method to determine if a given class is a properly specified | ||
27 | + * immutable class. | ||
28 | + * | ||
29 | + * @param clazz the class to check | ||
30 | + * @return true if the given class is a properly specified immutable class. | ||
31 | + */ | ||
32 | + private boolean isImmutableClass(Class<?> clazz) { | ||
33 | + // class must be declared final | ||
34 | + if (!Modifier.isFinal(clazz.getModifiers())) { | ||
35 | + failureReason = "a class that is not final"; | ||
36 | + return false; | ||
37 | + } | ||
38 | + | ||
39 | + // class must have only final and private data members | ||
40 | + for (final Field field : clazz.getDeclaredFields()) { | ||
41 | + if (field.getName().startsWith("__cobertura")) { | ||
42 | + // cobertura sticks these fields into classes - ignore them | ||
43 | + continue; | ||
44 | + } | ||
45 | + if (!Modifier.isFinal(field.getModifiers())) { | ||
46 | + failureReason = "a field named '" + field.getName() + | ||
47 | + "' that is not final"; | ||
48 | + return false; | ||
49 | + } | ||
50 | + if (!Modifier.isPrivate(field.getModifiers())) { | ||
51 | + // | ||
52 | + // NOTE: We relax the recommended rules for defining immutable | ||
53 | + // objects and allow "static final" fields that are not | ||
54 | + // private. The "final" check was already done above so we | ||
55 | + // don't repeat it here. | ||
56 | + // | ||
57 | + if (!Modifier.isStatic(field.getModifiers())) { | ||
58 | + failureReason = "a field named '" + field.getName() + | ||
59 | + "' that is not private and is not static"; | ||
60 | + return false; | ||
61 | + } | ||
62 | + } | ||
63 | + } | ||
64 | + | ||
65 | + // class must not define any setters | ||
66 | + for (final Method method : clazz.getMethods()) { | ||
67 | + if (method.getDeclaringClass().equals(clazz)) { | ||
68 | + if (method.getName().startsWith("set")) { | ||
69 | + failureReason = "a class with a setter named '" + method.getName() + "'"; | ||
70 | + return false; | ||
71 | + } | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | + return true; | ||
76 | + } | ||
77 | + | ||
78 | + /** | ||
79 | + * Describe why an error was reported. Uses Hamcrest style Description | ||
80 | + * interfaces. | ||
81 | + * | ||
82 | + * @param description the Description object to use for reporting the | ||
83 | + * mismatch | ||
84 | + */ | ||
85 | + public void describeMismatch(Description description) { | ||
86 | + description.appendText(failureReason); | ||
87 | + } | ||
88 | + | ||
89 | + /** | ||
90 | + * Describe the source object that caused an error, using a Hamcrest | ||
91 | + * Matcher style interface. In this case, it always returns | ||
92 | + * that we are looking for a properly defined utility class. | ||
93 | + * | ||
94 | + * @param description the Description object to use to report the "to" | ||
95 | + * object | ||
96 | + */ | ||
97 | + public void describeTo(Description description) { | ||
98 | + description.appendText("a properly defined immutable class"); | ||
99 | + } | ||
100 | + | ||
101 | + /** | ||
102 | + * Assert that the given class adheres to the utility class rules. | ||
103 | + * | ||
104 | + * @param clazz the class to check | ||
105 | + * | ||
106 | + * @throws java.lang.AssertionError if the class is not a valid | ||
107 | + * utility class | ||
108 | + */ | ||
109 | + public static void assertThatClassIsImmutable(Class<?> clazz) { | ||
110 | + final ImmutableClassChecker checker = new ImmutableClassChecker(); | ||
111 | + if (!checker.isImmutableClass(clazz)) { | ||
112 | + final Description toDescription = new StringDescription(); | ||
113 | + final Description mismatchDescription = new StringDescription(); | ||
114 | + | ||
115 | + checker.describeTo(toDescription); | ||
116 | + checker.describeMismatch(mismatchDescription); | ||
117 | + final String reason = | ||
118 | + "\n" + | ||
119 | + "Expected: is \"" + toDescription.toString() + "\"\n" + | ||
120 | + " but : was \"" + mismatchDescription.toString() + "\""; | ||
121 | + | ||
122 | + throw new AssertionError(reason); | ||
123 | + } | ||
124 | + } | ||
125 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import org.junit.Test; | ||
4 | + | ||
5 | +import static org.junit.Assert.assertEquals; | ||
6 | + | ||
7 | +/** | ||
8 | + * Test of the intent exception. | ||
9 | + */ | ||
10 | +public class IntentExceptionTest { | ||
11 | + | ||
12 | + @Test | ||
13 | + public void basics() { | ||
14 | + validate(new IntentException(), null, null); | ||
15 | + validate(new IntentException("foo"), "foo", null); | ||
16 | + | ||
17 | + Throwable cause = new NullPointerException("bar"); | ||
18 | + validate(new IntentException("foo", cause), "foo", cause); | ||
19 | + } | ||
20 | + | ||
21 | + /** | ||
22 | + * Validates that the specified exception has the correct message and cause. | ||
23 | + * | ||
24 | + * @param e exception to test | ||
25 | + * @param message expected message | ||
26 | + * @param cause expected cause | ||
27 | + */ | ||
28 | + protected void validate(RuntimeException e, String message, Throwable cause) { | ||
29 | + assertEquals("incorrect message", message, e.getMessage()); | ||
30 | + assertEquals("incorrect cause", cause, e.getCause()); | ||
31 | + } | ||
32 | + | ||
33 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +/** | ||
4 | + * This interface is for generator of IntentId. It is defined only for | ||
5 | + * testing purpose to keep type safety on mock creation. | ||
6 | + * | ||
7 | + * <p> | ||
8 | + * {@link #getNewId()} generates a globally unique {@link IntentId} instance | ||
9 | + * on each invocation. Application developers should not generate IntentId | ||
10 | + * by themselves. Instead use an implementation of this interface. | ||
11 | + * </p> | ||
12 | + */ | ||
13 | +public interface IntentIdGenerator extends IdGenerator<IntentId> { | ||
14 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import org.junit.Test; | ||
4 | + | ||
5 | +import static org.hamcrest.Matchers.is; | ||
6 | +import static org.hamcrest.Matchers.not; | ||
7 | +import static org.junit.Assert.assertEquals; | ||
8 | +import static org.junit.Assert.assertThat; | ||
9 | + | ||
10 | +/** | ||
11 | + * This class tests the immutability, equality, and non-equality of | ||
12 | + * {@link IntentId}. | ||
13 | + */ | ||
14 | +public class IntentIdTest { | ||
15 | + /** | ||
16 | + * Tests the immutability of {@link IntentId}. | ||
17 | + */ | ||
18 | + @Test | ||
19 | + public void intentIdFollowsGuidelineForImmutableObject() { | ||
20 | + ImmutableClassChecker.assertThatClassIsImmutable(IntentId.class); | ||
21 | + } | ||
22 | + | ||
23 | + /** | ||
24 | + * Tests equality of {@link IntentId}. | ||
25 | + */ | ||
26 | + @Test | ||
27 | + public void testEquality() { | ||
28 | + IntentId id1 = new IntentId(1L); | ||
29 | + IntentId id2 = new IntentId(1L); | ||
30 | + | ||
31 | + assertThat(id1, is(id2)); | ||
32 | + } | ||
33 | + | ||
34 | + /** | ||
35 | + * Tests non-equality of {@link IntentId}. | ||
36 | + */ | ||
37 | + @Test | ||
38 | + public void testNonEquality() { | ||
39 | + IntentId id1 = new IntentId(1L); | ||
40 | + IntentId id2 = new IntentId(2L); | ||
41 | + | ||
42 | + assertThat(id1, is(not(id2))); | ||
43 | + } | ||
44 | + | ||
45 | + @Test | ||
46 | + public void valueOf() { | ||
47 | + IntentId id = new IntentId(12345); | ||
48 | + assertEquals("incorrect valueOf", id, IntentId.valueOf("12345")); | ||
49 | + } | ||
50 | + | ||
51 | + @Test | ||
52 | + public void valueOfHex() { | ||
53 | + IntentId id = new IntentId(0xdeadbeefL); | ||
54 | + assertEquals("incorrect valueOf", id, IntentId.valueOf(id.toString())); | ||
55 | + } | ||
56 | + | ||
57 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import org.junit.After; | ||
4 | +import org.junit.Before; | ||
5 | +import org.junit.Test; | ||
6 | + | ||
7 | +import java.util.ArrayList; | ||
8 | +import java.util.Arrays; | ||
9 | +import java.util.Collections; | ||
10 | +import java.util.Iterator; | ||
11 | +import java.util.List; | ||
12 | + | ||
13 | +import static org.onlab.onos.net.intent.IntentState.*; | ||
14 | +import static org.junit.Assert.*; | ||
15 | + | ||
16 | +// TODO: consider make it categorized as integration test when it become | ||
17 | +// slow test or fragile test | ||
18 | +/** | ||
19 | + * Suite of tests for the intent service contract. | ||
20 | + */ | ||
21 | +public class IntentServiceTest { | ||
22 | + | ||
23 | + public static final IntentId IID = new IntentId(123); | ||
24 | + public static final IntentId INSTALLABLE_IID = new IntentId(234); | ||
25 | + | ||
26 | + protected static final int GRACE_MS = 500; // millis | ||
27 | + | ||
28 | + protected TestableIntentService service; | ||
29 | + protected TestListener listener = new TestListener(); | ||
30 | + | ||
31 | + @Before | ||
32 | + public void setUp() { | ||
33 | + service = createIntentService(); | ||
34 | + service.addListener(listener); | ||
35 | + } | ||
36 | + | ||
37 | + @After | ||
38 | + public void tearDown() { | ||
39 | + service.removeListener(listener); | ||
40 | + } | ||
41 | + | ||
42 | + /** | ||
43 | + * Creates a service instance appropriately instrumented for testing. | ||
44 | + * | ||
45 | + * @return testable intent service | ||
46 | + */ | ||
47 | + protected TestableIntentService createIntentService() { | ||
48 | + return new FakeIntentManager(); | ||
49 | + } | ||
50 | + | ||
51 | + @Test | ||
52 | + public void basics() { | ||
53 | + // Make sure there are no intents | ||
54 | + assertEquals("incorrect intent count", 0, service.getIntents().size()); | ||
55 | + | ||
56 | + // Register a compiler and an installer both setup for success. | ||
57 | + service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID))); | ||
58 | + service.registerInstaller(TestInstallableIntent.class, new TestInstaller(false)); | ||
59 | + | ||
60 | + final Intent intent = new TestIntent(IID); | ||
61 | + service.submit(intent); | ||
62 | + | ||
63 | + // Allow a small window of time until the intent is in the expected state | ||
64 | + TestTools.assertAfter(GRACE_MS, new Runnable() { | ||
65 | + @Override | ||
66 | + public void run() { | ||
67 | + assertEquals("incorrect intent state", INSTALLED, | ||
68 | + service.getIntentState(intent.getId())); | ||
69 | + } | ||
70 | + }); | ||
71 | + | ||
72 | + // Make sure that all expected events have been emitted | ||
73 | + validateEvents(intent, SUBMITTED, COMPILED, INSTALLED); | ||
74 | + | ||
75 | + // Make sure there is just one intent (and is ours) | ||
76 | + assertEquals("incorrect intent count", 1, service.getIntents().size()); | ||
77 | + assertEquals("incorrect intent", intent, service.getIntent(intent.getId())); | ||
78 | + | ||
79 | + // Reset the listener events | ||
80 | + listener.events.clear(); | ||
81 | + | ||
82 | + // Now withdraw the intent | ||
83 | + service.withdraw(intent); | ||
84 | + | ||
85 | + // Allow a small window of time until the event is in the expected state | ||
86 | + TestTools.assertAfter(GRACE_MS, new Runnable() { | ||
87 | + @Override | ||
88 | + public void run() { | ||
89 | + assertEquals("incorrect intent state", WITHDRAWN, | ||
90 | + service.getIntentState(intent.getId())); | ||
91 | + } | ||
92 | + }); | ||
93 | + | ||
94 | + // Make sure that all expected events have been emitted | ||
95 | + validateEvents(intent, WITHDRAWING, WITHDRAWN); | ||
96 | + | ||
97 | + // TODO: discuss what is the fate of intents after they have been withdrawn | ||
98 | + // Make sure that the intent is no longer in the system | ||
99 | +// assertEquals("incorrect intent count", 0, service.getIntents().size()); | ||
100 | +// assertNull("intent should not be found", service.getIntent(intent.getId())); | ||
101 | +// assertNull("intent state should not be found", service.getIntentState(intent.getId())); | ||
102 | + } | ||
103 | + | ||
104 | + @Test | ||
105 | + public void failedCompilation() { | ||
106 | + // Register a compiler programmed for success | ||
107 | + service.registerCompiler(TestIntent.class, new TestCompiler(true)); | ||
108 | + | ||
109 | + // Submit an intent | ||
110 | + final Intent intent = new TestIntent(IID); | ||
111 | + service.submit(intent); | ||
112 | + | ||
113 | + // Allow a small window of time until the intent is in the expected state | ||
114 | + TestTools.assertAfter(GRACE_MS, new Runnable() { | ||
115 | + @Override | ||
116 | + public void run() { | ||
117 | + assertEquals("incorrect intent state", FAILED, | ||
118 | + service.getIntentState(intent.getId())); | ||
119 | + } | ||
120 | + }); | ||
121 | + | ||
122 | + // Make sure that all expected events have been emitted | ||
123 | + validateEvents(intent, SUBMITTED, FAILED); | ||
124 | + } | ||
125 | + | ||
126 | + @Test | ||
127 | + public void failedInstallation() { | ||
128 | + // Register a compiler programmed for success and installer for failure | ||
129 | + service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID))); | ||
130 | + service.registerInstaller(TestInstallableIntent.class, new TestInstaller(true)); | ||
131 | + | ||
132 | + // Submit an intent | ||
133 | + final Intent intent = new TestIntent(IID); | ||
134 | + service.submit(intent); | ||
135 | + | ||
136 | + // Allow a small window of time until the intent is in the expected state | ||
137 | + TestTools.assertAfter(GRACE_MS, new Runnable() { | ||
138 | + @Override | ||
139 | + public void run() { | ||
140 | + assertEquals("incorrect intent state", FAILED, | ||
141 | + service.getIntentState(intent.getId())); | ||
142 | + } | ||
143 | + }); | ||
144 | + | ||
145 | + // Make sure that all expected events have been emitted | ||
146 | + validateEvents(intent, SUBMITTED, COMPILED, FAILED); | ||
147 | + } | ||
148 | + | ||
149 | + /** | ||
150 | + * Validates that the test event listener has received the following events | ||
151 | + * for the specified intent. Events received for other intents will not be | ||
152 | + * considered. | ||
153 | + * | ||
154 | + * @param intent intent subject | ||
155 | + * @param states list of states for which events are expected | ||
156 | + */ | ||
157 | + protected void validateEvents(Intent intent, IntentState... states) { | ||
158 | + Iterator<IntentEvent> events = listener.events.iterator(); | ||
159 | + for (IntentState state : states) { | ||
160 | + IntentEvent event = events.hasNext() ? events.next() : null; | ||
161 | + if (event == null) { | ||
162 | + fail("expected event not found: " + state); | ||
163 | + } else if (intent.equals(event.getIntent())) { | ||
164 | + assertEquals("incorrect state", state, event.getState()); | ||
165 | + } | ||
166 | + } | ||
167 | + | ||
168 | + // Remainder of events should not apply to this intent; make sure. | ||
169 | + while (events.hasNext()) { | ||
170 | + assertFalse("unexpected event for intent", | ||
171 | + intent.equals(events.next().getIntent())); | ||
172 | + } | ||
173 | + } | ||
174 | + | ||
175 | + @Test | ||
176 | + public void compilerBasics() { | ||
177 | + // Make sure there are no compilers | ||
178 | + assertEquals("incorrect compiler count", 0, service.getCompilers().size()); | ||
179 | + | ||
180 | + // Add a compiler and make sure that it appears in the map | ||
181 | + IntentCompiler<TestIntent> compiler = new TestCompiler(false); | ||
182 | + service.registerCompiler(TestIntent.class, compiler); | ||
183 | + assertEquals("incorrect compiler", compiler, | ||
184 | + service.getCompilers().get(TestIntent.class)); | ||
185 | + | ||
186 | + // Remove the same and make sure that it no longer appears in the map | ||
187 | + service.unregisterCompiler(TestIntent.class); | ||
188 | + assertNull("compiler should not be registered", | ||
189 | + service.getCompilers().get(TestIntent.class)); | ||
190 | + } | ||
191 | + | ||
192 | + @Test | ||
193 | + public void installerBasics() { | ||
194 | + // Make sure there are no installers | ||
195 | + assertEquals("incorrect installer count", 0, service.getInstallers().size()); | ||
196 | + | ||
197 | + // Add an installer and make sure that it appears in the map | ||
198 | + IntentInstaller<TestInstallableIntent> installer = new TestInstaller(false); | ||
199 | + service.registerInstaller(TestInstallableIntent.class, installer); | ||
200 | + assertEquals("incorrect installer", installer, | ||
201 | + service.getInstallers().get(TestInstallableIntent.class)); | ||
202 | + | ||
203 | + // Remove the same and make sure that it no longer appears in the map | ||
204 | + service.unregisterInstaller(TestInstallableIntent.class); | ||
205 | + assertNull("installer should not be registered", | ||
206 | + service.getInstallers().get(TestInstallableIntent.class)); | ||
207 | + } | ||
208 | + | ||
209 | + @Test | ||
210 | + public void implicitRegistration() { | ||
211 | + // Add a compiler and make sure that it appears in the map | ||
212 | + IntentCompiler<TestIntent> compiler = new TestCompiler(new TestSubclassInstallableIntent(INSTALLABLE_IID)); | ||
213 | + service.registerCompiler(TestIntent.class, compiler); | ||
214 | + assertEquals("incorrect compiler", compiler, | ||
215 | + service.getCompilers().get(TestIntent.class)); | ||
216 | + | ||
217 | + // Add a installer and make sure that it appears in the map | ||
218 | + IntentInstaller<TestInstallableIntent> installer = new TestInstaller(false); | ||
219 | + service.registerInstaller(TestInstallableIntent.class, installer); | ||
220 | + assertEquals("incorrect installer", installer, | ||
221 | + service.getInstallers().get(TestInstallableIntent.class)); | ||
222 | + | ||
223 | + | ||
224 | + // Submit an intent which is a subclass of the one we registered | ||
225 | + final Intent intent = new TestSubclassIntent(IID); | ||
226 | + service.submit(intent); | ||
227 | + | ||
228 | + // Allow some time for the intent to be compiled and installed | ||
229 | + TestTools.assertAfter(GRACE_MS, new Runnable() { | ||
230 | + @Override | ||
231 | + public void run() { | ||
232 | + assertEquals("incorrect intent state", INSTALLED, | ||
233 | + service.getIntentState(intent.getId())); | ||
234 | + } | ||
235 | + }); | ||
236 | + | ||
237 | + // Make sure that now we have an implicit registration of the compiler | ||
238 | + // under the intent subclass | ||
239 | + assertEquals("incorrect compiler", compiler, | ||
240 | + service.getCompilers().get(TestSubclassIntent.class)); | ||
241 | + | ||
242 | + // Make sure that now we have an implicit registration of the installer | ||
243 | + // under the intent subclass | ||
244 | + assertEquals("incorrect installer", installer, | ||
245 | + service.getInstallers().get(TestSubclassInstallableIntent.class)); | ||
246 | + | ||
247 | + // TODO: discuss whether or if implicit registration should require implicit unregistration | ||
248 | + // perhaps unregister by compiler or installer itself, rather than by class would be better | ||
249 | + } | ||
250 | + | ||
251 | + | ||
252 | + // Fixture to track emitted intent events | ||
253 | + protected class TestListener implements IntentEventListener { | ||
254 | + final List<IntentEvent> events = new ArrayList<>(); | ||
255 | + | ||
256 | + @Override | ||
257 | + public void event(IntentEvent event) { | ||
258 | + events.add(event); | ||
259 | + } | ||
260 | + } | ||
261 | + | ||
262 | + // Controllable compiler | ||
263 | + private class TestCompiler implements IntentCompiler<TestIntent> { | ||
264 | + private final boolean fail; | ||
265 | + private final List<Intent> result; | ||
266 | + | ||
267 | + TestCompiler(boolean fail) { | ||
268 | + this.fail = fail; | ||
269 | + this.result = Collections.emptyList(); | ||
270 | + } | ||
271 | + | ||
272 | + TestCompiler(Intent... result) { | ||
273 | + this.fail = false; | ||
274 | + this.result = Arrays.asList(result); | ||
275 | + } | ||
276 | + | ||
277 | + @Override | ||
278 | + public List<Intent> compile(TestIntent intent) { | ||
279 | + if (fail) { | ||
280 | + throw new IntentException("compile failed by design"); | ||
281 | + } | ||
282 | + List<Intent> compiled = new ArrayList<>(result); | ||
283 | + return compiled; | ||
284 | + } | ||
285 | + } | ||
286 | + | ||
287 | + // Controllable installer | ||
288 | + private class TestInstaller implements IntentInstaller<TestInstallableIntent> { | ||
289 | + private final boolean fail; | ||
290 | + | ||
291 | + TestInstaller(boolean fail) { | ||
292 | + this.fail = fail; | ||
293 | + } | ||
294 | + | ||
295 | + @Override | ||
296 | + public void install(TestInstallableIntent intent) { | ||
297 | + if (fail) { | ||
298 | + throw new IntentException("install failed by design"); | ||
299 | + } | ||
300 | + } | ||
301 | + | ||
302 | + @Override | ||
303 | + public void uninstall(TestInstallableIntent intent) { | ||
304 | + if (fail) { | ||
305 | + throw new IntentException("remove failed by design"); | ||
306 | + } | ||
307 | + } | ||
308 | + } | ||
309 | + | ||
310 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import static org.junit.Assert.assertEquals; | ||
4 | +import static org.junit.Assert.assertFalse; | ||
5 | +import static org.junit.Assert.assertTrue; | ||
6 | + | ||
7 | +import java.util.Arrays; | ||
8 | +import java.util.HashSet; | ||
9 | +import java.util.Set; | ||
10 | + | ||
11 | +import org.junit.Test; | ||
12 | + | ||
13 | +/** | ||
14 | + * Base facilities to test various intent tests. | ||
15 | + */ | ||
16 | +public abstract class IntentTest { | ||
17 | + /** | ||
18 | + * Produces a set of items from the supplied items. | ||
19 | + * | ||
20 | + * @param items items to be placed in set | ||
21 | + * @param <T> item type | ||
22 | + * @return set of items | ||
23 | + */ | ||
24 | + protected static <T> Set<T> itemSet(T[] items) { | ||
25 | + return new HashSet<>(Arrays.asList(items)); | ||
26 | + } | ||
27 | + | ||
28 | + @Test | ||
29 | + public void equalsAndHashCode() { | ||
30 | + Intent one = createOne(); | ||
31 | + Intent like = createOne(); | ||
32 | + Intent another = createAnother(); | ||
33 | + | ||
34 | + assertTrue("should be equal", one.equals(like)); | ||
35 | + assertEquals("incorrect hashCode", one.hashCode(), like.hashCode()); | ||
36 | + | ||
37 | + assertFalse("should not be equal", one.equals(another)); | ||
38 | + | ||
39 | + assertFalse("should not be equal", one.equals(null)); | ||
40 | + assertFalse("should not be equal", one.equals("foo")); | ||
41 | + } | ||
42 | + | ||
43 | + @Test | ||
44 | + public void testToString() { | ||
45 | + Intent one = createOne(); | ||
46 | + Intent like = createOne(); | ||
47 | + assertEquals("incorrect toString", one.toString(), like.toString()); | ||
48 | + } | ||
49 | + | ||
50 | + /** | ||
51 | + * Creates a new intent, but always a like intent, i.e. all instances will | ||
52 | + * be equal, but should not be the same. | ||
53 | + * | ||
54 | + * @return intent | ||
55 | + */ | ||
56 | + protected abstract Intent createOne(); | ||
57 | + | ||
58 | + /** | ||
59 | + * Creates another intent, not equals to the one created by | ||
60 | + * {@link #createOne()} and with a different hash code. | ||
61 | + * | ||
62 | + * @return another intent | ||
63 | + */ | ||
64 | + protected abstract Intent createAnother(); | ||
65 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import org.junit.Test; | ||
4 | + | ||
5 | +import static org.junit.Assert.assertEquals; | ||
6 | + | ||
7 | +/** | ||
8 | + * Suite of tests of the multi-to-single point intent descriptor. | ||
9 | + */ | ||
10 | +public class MultiPointToSinglePointIntentTest extends ConnectivityIntentTest { | ||
11 | + | ||
12 | + @Test | ||
13 | + public void basics() { | ||
14 | + MultiPointToSinglePointIntent intent = createOne(); | ||
15 | + assertEquals("incorrect id", IID, intent.getId()); | ||
16 | + assertEquals("incorrect match", MATCH, intent.getTrafficSelector()); | ||
17 | + assertEquals("incorrect ingress", PS1, intent.getIngressPorts()); | ||
18 | + assertEquals("incorrect egress", P2, intent.getEgressPort()); | ||
19 | + } | ||
20 | + | ||
21 | + @Override | ||
22 | + protected MultiPointToSinglePointIntent createOne() { | ||
23 | + return new MultiPointToSinglePointIntent(IID, MATCH, NOP, PS1, P2); | ||
24 | + } | ||
25 | + | ||
26 | + @Override | ||
27 | + protected MultiPointToSinglePointIntent createAnother() { | ||
28 | + return new MultiPointToSinglePointIntent(IID, MATCH, NOP, PS2, P1); | ||
29 | + } | ||
30 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import static org.junit.Assert.assertEquals; | ||
4 | + | ||
5 | +import org.junit.Test; | ||
6 | +import org.onlab.onos.net.NetTestTools; | ||
7 | +import org.onlab.onos.net.Path; | ||
8 | + | ||
9 | +public class PathIntentTest extends ConnectivityIntentTest { | ||
10 | + // 111:11 --> 222:22 | ||
11 | + private static final Path PATH1 = NetTestTools.createPath("111", "222"); | ||
12 | + | ||
13 | + // 111:11 --> 333:33 | ||
14 | + private static final Path PATH2 = NetTestTools.createPath("222", "333"); | ||
15 | + | ||
16 | + @Test | ||
17 | + public void basics() { | ||
18 | + PathIntent intent = createOne(); | ||
19 | + assertEquals("incorrect id", IID, intent.getId()); | ||
20 | + assertEquals("incorrect match", MATCH, intent.getTrafficSelector()); | ||
21 | + assertEquals("incorrect action", NOP, intent.getTrafficTreatment()); | ||
22 | + assertEquals("incorrect ingress", P1, intent.getIngressPort()); | ||
23 | + assertEquals("incorrect egress", P2, intent.getEgressPort()); | ||
24 | + assertEquals("incorrect path", PATH1, intent.getPath()); | ||
25 | + } | ||
26 | + | ||
27 | + @Override | ||
28 | + protected PathIntent createOne() { | ||
29 | + return new PathIntent(IID, MATCH, NOP, P1, P2, PATH1); | ||
30 | + } | ||
31 | + | ||
32 | + @Override | ||
33 | + protected PathIntent createAnother() { | ||
34 | + return new PathIntent(IID, MATCH, NOP, P1, P3, PATH2); | ||
35 | + } | ||
36 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import org.junit.Test; | ||
4 | + | ||
5 | +import static org.junit.Assert.assertEquals; | ||
6 | + | ||
7 | +/** | ||
8 | + * Suite of tests of the point-to-point intent descriptor. | ||
9 | + */ | ||
10 | +public class PointToPointIntentTest extends ConnectivityIntentTest { | ||
11 | + | ||
12 | + @Test | ||
13 | + public void basics() { | ||
14 | + PointToPointIntent intent = createOne(); | ||
15 | + assertEquals("incorrect id", IID, intent.getId()); | ||
16 | + assertEquals("incorrect match", MATCH, intent.getTrafficSelector()); | ||
17 | + assertEquals("incorrect ingress", P1, intent.getIngressPort()); | ||
18 | + assertEquals("incorrect egress", P2, intent.getEgressPort()); | ||
19 | + } | ||
20 | + | ||
21 | + @Override | ||
22 | + protected PointToPointIntent createOne() { | ||
23 | + return new PointToPointIntent(IID, MATCH, NOP, P1, P2); | ||
24 | + } | ||
25 | + | ||
26 | + @Override | ||
27 | + protected PointToPointIntent createAnother() { | ||
28 | + return new PointToPointIntent(IID, MATCH, NOP, P2, P1); | ||
29 | + } | ||
30 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import org.junit.Test; | ||
4 | + | ||
5 | +import static org.junit.Assert.assertEquals; | ||
6 | + | ||
7 | +/** | ||
8 | + * Suite of tests of the single-to-multi point intent descriptor. | ||
9 | + */ | ||
10 | +public class SinglePointToMultiPointIntentTest extends ConnectivityIntentTest { | ||
11 | + | ||
12 | + @Test | ||
13 | + public void basics() { | ||
14 | + SinglePointToMultiPointIntent intent = createOne(); | ||
15 | + assertEquals("incorrect id", IID, intent.getId()); | ||
16 | + assertEquals("incorrect match", MATCH, intent.getTrafficSelector()); | ||
17 | + assertEquals("incorrect ingress", P1, intent.getIngressPort()); | ||
18 | + assertEquals("incorrect egress", PS2, intent.getEgressPorts()); | ||
19 | + } | ||
20 | + | ||
21 | + @Override | ||
22 | + protected SinglePointToMultiPointIntent createOne() { | ||
23 | + return new SinglePointToMultiPointIntent(IID, MATCH, NOP, P1, PS2); | ||
24 | + } | ||
25 | + | ||
26 | + @Override | ||
27 | + protected SinglePointToMultiPointIntent createAnother() { | ||
28 | + return new SinglePointToMultiPointIntent(IID, MATCH, NOP, P2, PS1); | ||
29 | + } | ||
30 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | +//TODO is this the right package? | ||
3 | + | ||
4 | +/** | ||
5 | + * An installable intent used in the unit test. | ||
6 | + * | ||
7 | + * FIXME: we don't want to expose this class publicly, but the current Kryo | ||
8 | + * serialization mechanism does not allow this class to be private and placed | ||
9 | + * on testing directory. | ||
10 | + */ | ||
11 | +public class TestInstallableIntent extends AbstractIntent implements InstallableIntent { | ||
12 | + /** | ||
13 | + * Constructs an instance with the specified intent ID. | ||
14 | + * | ||
15 | + * @param id intent ID | ||
16 | + */ | ||
17 | + public TestInstallableIntent(IntentId id) { | ||
18 | + super(id); | ||
19 | + } | ||
20 | + | ||
21 | + /** | ||
22 | + * Constructor for serializer. | ||
23 | + */ | ||
24 | + protected TestInstallableIntent() { | ||
25 | + super(); | ||
26 | + } | ||
27 | + | ||
28 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | +//TODO is this the right package? | ||
3 | + | ||
4 | +/** | ||
5 | + * An intent used in the unit test. | ||
6 | + * | ||
7 | + * FIXME: we don't want to expose this class publicly, but the current Kryo | ||
8 | + * serialization mechanism does not allow this class to be private and placed | ||
9 | + * on testing directory. | ||
10 | + */ | ||
11 | +public class TestIntent extends AbstractIntent { | ||
12 | + /** | ||
13 | + * Constructs an instance with the specified intent ID. | ||
14 | + * | ||
15 | + * @param id intent ID | ||
16 | + */ | ||
17 | + public TestIntent(IntentId id) { | ||
18 | + super(id); | ||
19 | + } | ||
20 | + | ||
21 | + /** | ||
22 | + * Constructor for serializer. | ||
23 | + */ | ||
24 | + protected TestIntent() { | ||
25 | + super(); | ||
26 | + } | ||
27 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | +//TODO is this the right package? | ||
3 | + | ||
4 | +/** | ||
5 | + * An intent used in the unit test. | ||
6 | + * | ||
7 | + * FIXME: we don't want to expose this class publicly, but the current Kryo | ||
8 | + * serialization mechanism does not allow this class to be private and placed | ||
9 | + * on testing directory. | ||
10 | + */ | ||
11 | +public class TestSubclassInstallableIntent extends TestInstallableIntent implements InstallableIntent { | ||
12 | + /** | ||
13 | + * Constructs an instance with the specified intent ID. | ||
14 | + * | ||
15 | + * @param id intent ID | ||
16 | + */ | ||
17 | + public TestSubclassInstallableIntent(IntentId id) { | ||
18 | + super(id); | ||
19 | + } | ||
20 | + | ||
21 | + /** | ||
22 | + * Constructor for serializer. | ||
23 | + */ | ||
24 | + protected TestSubclassInstallableIntent() { | ||
25 | + super(); | ||
26 | + } | ||
27 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | +//TODO is this the right package? | ||
3 | + | ||
4 | +/** | ||
5 | + * An intent used in the unit test. | ||
6 | + * | ||
7 | + * FIXME: we don't want to expose this class publicly, but the current Kryo | ||
8 | + * serialization mechanism does not allow this class to be private and placed | ||
9 | + * on testing directory. | ||
10 | + */ | ||
11 | +public class TestSubclassIntent extends TestIntent { | ||
12 | + /** | ||
13 | + * Constructs an instance with the specified intent ID. | ||
14 | + * | ||
15 | + * @param id intent ID | ||
16 | + */ | ||
17 | + public TestSubclassIntent(IntentId id) { | ||
18 | + super(id); | ||
19 | + } | ||
20 | + | ||
21 | + /** | ||
22 | + * Constructor for serializer. | ||
23 | + */ | ||
24 | + protected TestSubclassIntent() { | ||
25 | + super(); | ||
26 | + } | ||
27 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import static org.junit.Assert.fail; | ||
4 | + | ||
5 | +/** | ||
6 | + * Set of test tools. | ||
7 | + */ | ||
8 | +public final class TestTools { | ||
9 | + | ||
10 | + // Disallow construction | ||
11 | + private TestTools() { | ||
12 | + } | ||
13 | + | ||
14 | + /** | ||
15 | + * Utility method to pause the current thread for the specified number of | ||
16 | + * milliseconds. | ||
17 | + * | ||
18 | + * @param ms number of milliseconds to pause | ||
19 | + */ | ||
20 | + public static void delay(int ms) { | ||
21 | + try { | ||
22 | + Thread.sleep(ms); | ||
23 | + } catch (InterruptedException e) { | ||
24 | + fail("unexpected interrupt"); | ||
25 | + } | ||
26 | + } | ||
27 | + | ||
28 | + /** | ||
29 | + * Periodically runs the given runnable, which should contain a series of | ||
30 | + * test assertions until all the assertions succeed, in which case it will | ||
31 | + * return, or until the the time expires, in which case it will throw the | ||
32 | + * first failed assertion error. | ||
33 | + * | ||
34 | + * @param start start time, in millis since start of epoch from which the | ||
35 | + * duration will be measured | ||
36 | + * @param delay initial delay (in milliseconds) before the first assertion | ||
37 | + * attempt | ||
38 | + * @param step delay (in milliseconds) between successive assertion | ||
39 | + * attempts | ||
40 | + * @param duration number of milliseconds beyond the given start time, | ||
41 | + * after which the failed assertions will be propagated and allowed | ||
42 | + * to fail the test | ||
43 | + * @param assertions runnable housing the test assertions | ||
44 | + */ | ||
45 | + public static void assertAfter(long start, int delay, int step, | ||
46 | + int duration, Runnable assertions) { | ||
47 | + delay(delay); | ||
48 | + while (true) { | ||
49 | + try { | ||
50 | + assertions.run(); | ||
51 | + break; | ||
52 | + } catch (AssertionError e) { | ||
53 | + if (System.currentTimeMillis() - start > duration) { | ||
54 | + throw e; | ||
55 | + } | ||
56 | + } | ||
57 | + delay(step); | ||
58 | + } | ||
59 | + } | ||
60 | + | ||
61 | + /** | ||
62 | + * Periodically runs the given runnable, which should contain a series of | ||
63 | + * test assertions until all the assertions succeed, in which case it will | ||
64 | + * return, or until the the time expires, in which case it will throw the | ||
65 | + * first failed assertion error. | ||
66 | + * <p> | ||
67 | + * The start of the period is the current time. | ||
68 | + * | ||
69 | + * @param delay initial delay (in milliseconds) before the first assertion | ||
70 | + * attempt | ||
71 | + * @param step delay (in milliseconds) between successive assertion | ||
72 | + * attempts | ||
73 | + * @param duration number of milliseconds beyond the current time time, | ||
74 | + * after which the failed assertions will be propagated and allowed | ||
75 | + * to fail the test | ||
76 | + * @param assertions runnable housing the test assertions | ||
77 | + */ | ||
78 | + public static void assertAfter(int delay, int step, int duration, | ||
79 | + Runnable assertions) { | ||
80 | + assertAfter(System.currentTimeMillis(), delay, step, duration, | ||
81 | + assertions); | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * Periodically runs the given runnable, which should contain a series of | ||
86 | + * test assertions until all the assertions succeed, in which case it will | ||
87 | + * return, or until the the time expires, in which case it will throw the | ||
88 | + * first failed assertion error. | ||
89 | + * <p> | ||
90 | + * The start of the period is the current time and the first assertion | ||
91 | + * attempt is delayed by the value of {@code step} parameter. | ||
92 | + * | ||
93 | + * @param step delay (in milliseconds) between successive assertion | ||
94 | + * attempts | ||
95 | + * @param duration number of milliseconds beyond the current time time, | ||
96 | + * after which the failed assertions will be propagated and allowed | ||
97 | + * to fail the test | ||
98 | + * @param assertions runnable housing the test assertions | ||
99 | + */ | ||
100 | + public static void assertAfter(int step, int duration, | ||
101 | + Runnable assertions) { | ||
102 | + assertAfter(step, step, duration, assertions); | ||
103 | + } | ||
104 | + | ||
105 | + /** | ||
106 | + * Periodically runs the given runnable, which should contain a series of | ||
107 | + * test assertions until all the assertions succeed, in which case it will | ||
108 | + * return, or until the the time expires, in which case it will throw the | ||
109 | + * first failed assertion error. | ||
110 | + * <p> | ||
111 | + * The start of the period is the current time and each successive | ||
112 | + * assertion attempt is delayed by at least 10 milliseconds unless the | ||
113 | + * {@code duration} is less than that, in which case the one and only | ||
114 | + * assertion is made after that delay. | ||
115 | + * | ||
116 | + * @param duration number of milliseconds beyond the current time, | ||
117 | + * after which the failed assertions will be propagated and allowed | ||
118 | + * to fail the test | ||
119 | + * @param assertions runnable housing the test assertions | ||
120 | + */ | ||
121 | + public static void assertAfter(int duration, Runnable assertions) { | ||
122 | + int step = Math.min(duration, Math.max(10, duration / 10)); | ||
123 | + assertAfter(step, duration, assertions); | ||
124 | + } | ||
125 | + | ||
126 | +} |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import java.util.List; | ||
4 | + | ||
5 | +/** | ||
6 | + * Abstraction of an extensible intent service enabled for unit tests. | ||
7 | + */ | ||
8 | +public interface TestableIntentService extends IntentService, IntentExtensionService { | ||
9 | + | ||
10 | + List<IntentException> getExceptions(); | ||
11 | + | ||
12 | +} |
1 | package org.onlab.onos.net.host.impl; | 1 | package org.onlab.onos.net.host.impl; |
2 | 2 | ||
3 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
4 | +import static org.slf4j.LoggerFactory.getLogger; | ||
5 | + | ||
6 | +import java.util.Set; | ||
7 | + | ||
3 | import org.apache.felix.scr.annotations.Activate; | 8 | import org.apache.felix.scr.annotations.Activate; |
4 | import org.apache.felix.scr.annotations.Component; | 9 | import org.apache.felix.scr.annotations.Component; |
5 | import org.apache.felix.scr.annotations.Deactivate; | 10 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -12,6 +17,7 @@ import org.onlab.onos.net.ConnectPoint; | ... | @@ -12,6 +17,7 @@ import org.onlab.onos.net.ConnectPoint; |
12 | import org.onlab.onos.net.DeviceId; | 17 | import org.onlab.onos.net.DeviceId; |
13 | import org.onlab.onos.net.Host; | 18 | import org.onlab.onos.net.Host; |
14 | import org.onlab.onos.net.HostId; | 19 | import org.onlab.onos.net.HostId; |
20 | +import org.onlab.onos.net.device.DeviceService; | ||
15 | import org.onlab.onos.net.host.HostAdminService; | 21 | import org.onlab.onos.net.host.HostAdminService; |
16 | import org.onlab.onos.net.host.HostDescription; | 22 | import org.onlab.onos.net.host.HostDescription; |
17 | import org.onlab.onos.net.host.HostEvent; | 23 | import org.onlab.onos.net.host.HostEvent; |
... | @@ -23,6 +29,7 @@ import org.onlab.onos.net.host.HostService; | ... | @@ -23,6 +29,7 @@ import org.onlab.onos.net.host.HostService; |
23 | import org.onlab.onos.net.host.HostStore; | 29 | import org.onlab.onos.net.host.HostStore; |
24 | import org.onlab.onos.net.host.HostStoreDelegate; | 30 | import org.onlab.onos.net.host.HostStoreDelegate; |
25 | import org.onlab.onos.net.host.PortAddresses; | 31 | import org.onlab.onos.net.host.PortAddresses; |
32 | +import org.onlab.onos.net.packet.PacketService; | ||
26 | import org.onlab.onos.net.provider.AbstractProviderRegistry; | 33 | import org.onlab.onos.net.provider.AbstractProviderRegistry; |
27 | import org.onlab.onos.net.provider.AbstractProviderService; | 34 | import org.onlab.onos.net.provider.AbstractProviderService; |
28 | import org.onlab.packet.IpAddress; | 35 | import org.onlab.packet.IpAddress; |
... | @@ -31,11 +38,6 @@ import org.onlab.packet.MacAddress; | ... | @@ -31,11 +38,6 @@ import org.onlab.packet.MacAddress; |
31 | import org.onlab.packet.VlanId; | 38 | import org.onlab.packet.VlanId; |
32 | import org.slf4j.Logger; | 39 | import org.slf4j.Logger; |
33 | 40 | ||
34 | -import java.util.Set; | ||
35 | - | ||
36 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
37 | -import static org.slf4j.LoggerFactory.getLogger; | ||
38 | - | ||
39 | /** | 41 | /** |
40 | * Provides basic implementation of the host SB & NB APIs. | 42 | * Provides basic implementation of the host SB & NB APIs. |
41 | */ | 43 | */ |
... | @@ -59,12 +61,22 @@ public class HostManager | ... | @@ -59,12 +61,22 @@ public class HostManager |
59 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 61 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
60 | protected EventDeliveryService eventDispatcher; | 62 | protected EventDeliveryService eventDispatcher; |
61 | 63 | ||
64 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
65 | + protected DeviceService deviceService; | ||
66 | + | ||
67 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
68 | + protected PacketService packetService; | ||
69 | + | ||
70 | + private HostMonitor monitor; | ||
62 | 71 | ||
63 | @Activate | 72 | @Activate |
64 | public void activate() { | 73 | public void activate() { |
74 | + log.info("Started"); | ||
65 | store.setDelegate(delegate); | 75 | store.setDelegate(delegate); |
66 | eventDispatcher.addSink(HostEvent.class, listenerRegistry); | 76 | eventDispatcher.addSink(HostEvent.class, listenerRegistry); |
67 | - log.info("Started"); | 77 | + |
78 | + monitor = new HostMonitor(deviceService, packetService, this); | ||
79 | + | ||
68 | } | 80 | } |
69 | 81 | ||
70 | @Deactivate | 82 | @Deactivate |
... | @@ -76,6 +88,8 @@ public class HostManager | ... | @@ -76,6 +88,8 @@ public class HostManager |
76 | 88 | ||
77 | @Override | 89 | @Override |
78 | protected HostProviderService createProviderService(HostProvider provider) { | 90 | protected HostProviderService createProviderService(HostProvider provider) { |
91 | + monitor.registerHostProvider(provider); | ||
92 | + | ||
79 | return new InternalHostProviderService(provider); | 93 | return new InternalHostProviderService(provider); |
80 | } | 94 | } |
81 | 95 | ||
... | @@ -126,12 +140,12 @@ public class HostManager | ... | @@ -126,12 +140,12 @@ public class HostManager |
126 | 140 | ||
127 | @Override | 141 | @Override |
128 | public void startMonitoringIp(IpAddress ip) { | 142 | public void startMonitoringIp(IpAddress ip) { |
129 | - // TODO pass through to HostMonitor | 143 | + monitor.addMonitoringFor(ip); |
130 | } | 144 | } |
131 | 145 | ||
132 | @Override | 146 | @Override |
133 | public void stopMonitoringIp(IpAddress ip) { | 147 | public void stopMonitoringIp(IpAddress ip) { |
134 | - // TODO pass through to HostMonitor | 148 | + monitor.stopMonitoring(ip); |
135 | } | 149 | } |
136 | 150 | ||
137 | @Override | 151 | @Override | ... | ... |
... | @@ -2,10 +2,11 @@ package org.onlab.onos.net.host.impl; | ... | @@ -2,10 +2,11 @@ package org.onlab.onos.net.host.impl; |
2 | 2 | ||
3 | import java.nio.ByteBuffer; | 3 | import java.nio.ByteBuffer; |
4 | import java.util.ArrayList; | 4 | import java.util.ArrayList; |
5 | -import java.util.Collections; | ||
6 | import java.util.HashSet; | 5 | import java.util.HashSet; |
7 | import java.util.List; | 6 | import java.util.List; |
7 | +import java.util.Map; | ||
8 | import java.util.Set; | 8 | import java.util.Set; |
9 | +import java.util.concurrent.ConcurrentHashMap; | ||
9 | import java.util.concurrent.TimeUnit; | 10 | import java.util.concurrent.TimeUnit; |
10 | 11 | ||
11 | import org.jboss.netty.util.Timeout; | 12 | import org.jboss.netty.util.Timeout; |
... | @@ -21,19 +22,19 @@ import org.onlab.onos.net.flow.TrafficTreatment; | ... | @@ -21,19 +22,19 @@ import org.onlab.onos.net.flow.TrafficTreatment; |
21 | import org.onlab.onos.net.flow.instructions.Instruction; | 22 | import org.onlab.onos.net.flow.instructions.Instruction; |
22 | import org.onlab.onos.net.flow.instructions.Instructions; | 23 | import org.onlab.onos.net.flow.instructions.Instructions; |
23 | import org.onlab.onos.net.host.HostProvider; | 24 | import org.onlab.onos.net.host.HostProvider; |
24 | -import org.onlab.onos.net.host.HostService; | ||
25 | -import org.onlab.onos.net.host.HostStore; | ||
26 | import org.onlab.onos.net.host.PortAddresses; | 25 | import org.onlab.onos.net.host.PortAddresses; |
27 | import org.onlab.onos.net.packet.DefaultOutboundPacket; | 26 | import org.onlab.onos.net.packet.DefaultOutboundPacket; |
28 | import org.onlab.onos.net.packet.OutboundPacket; | 27 | import org.onlab.onos.net.packet.OutboundPacket; |
29 | import org.onlab.onos.net.packet.PacketService; | 28 | import org.onlab.onos.net.packet.PacketService; |
30 | -import org.onlab.onos.net.topology.TopologyService; | 29 | +import org.onlab.onos.net.provider.ProviderId; |
31 | import org.onlab.packet.ARP; | 30 | import org.onlab.packet.ARP; |
32 | import org.onlab.packet.Ethernet; | 31 | import org.onlab.packet.Ethernet; |
33 | import org.onlab.packet.IpAddress; | 32 | import org.onlab.packet.IpAddress; |
34 | import org.onlab.packet.IpPrefix; | 33 | import org.onlab.packet.IpPrefix; |
35 | import org.onlab.packet.MacAddress; | 34 | import org.onlab.packet.MacAddress; |
36 | import org.onlab.util.Timer; | 35 | import org.onlab.util.Timer; |
36 | +import org.slf4j.Logger; | ||
37 | +import org.slf4j.LoggerFactory; | ||
37 | 38 | ||
38 | /** | 39 | /** |
39 | * Monitors hosts on the dataplane to detect changes in host data. | 40 | * Monitors hosts on the dataplane to detect changes in host data. |
... | @@ -43,9 +44,7 @@ import org.onlab.util.Timer; | ... | @@ -43,9 +44,7 @@ import org.onlab.util.Timer; |
43 | * probe for hosts that have not yet been detected (specified by IP address). | 44 | * probe for hosts that have not yet been detected (specified by IP address). |
44 | */ | 45 | */ |
45 | public class HostMonitor implements TimerTask { | 46 | public class HostMonitor implements TimerTask { |
46 | - | 47 | + private static final Logger log = LoggerFactory.getLogger(HostMonitor.class); |
47 | - private static final byte[] DEFAULT_MAC_ADDRESS = | ||
48 | - MacAddress.valueOf("00:00:00:00:00:01").getAddress(); | ||
49 | 48 | ||
50 | private static final byte[] ZERO_MAC_ADDRESS = | 49 | private static final byte[] ZERO_MAC_ADDRESS = |
51 | MacAddress.valueOf("00:00:00:00:00:00").getAddress(); | 50 | MacAddress.valueOf("00:00:00:00:00:00").getAddress(); |
... | @@ -54,59 +53,77 @@ public class HostMonitor implements TimerTask { | ... | @@ -54,59 +53,77 @@ public class HostMonitor implements TimerTask { |
54 | private static final byte[] BROADCAST_MAC = | 53 | private static final byte[] BROADCAST_MAC = |
55 | MacAddress.valueOf("ff:ff:ff:ff:ff:ff").getAddress(); | 54 | MacAddress.valueOf("ff:ff:ff:ff:ff:ff").getAddress(); |
56 | 55 | ||
57 | - private final HostService hostService; | 56 | + private DeviceService deviceService; |
58 | - private final TopologyService topologyService; | 57 | + private PacketService packetService; |
59 | - private final DeviceService deviceService; | 58 | + private HostManager hostManager; |
60 | - private final HostProvider hostProvider; | ||
61 | - private final PacketService packetService; | ||
62 | - private final HostStore hostStore; | ||
63 | 59 | ||
64 | private final Set<IpAddress> monitoredAddresses; | 60 | private final Set<IpAddress> monitoredAddresses; |
65 | 61 | ||
62 | + private final Map<ProviderId, HostProvider> hostProviders; | ||
63 | + | ||
66 | private final long probeRate; | 64 | private final long probeRate; |
67 | 65 | ||
68 | private final Timeout timeout; | 66 | private final Timeout timeout; |
69 | 67 | ||
70 | - public HostMonitor(HostService hostService, TopologyService topologyService, | 68 | + public HostMonitor( |
71 | DeviceService deviceService, | 69 | DeviceService deviceService, |
72 | - HostProvider hostProvider, PacketService packetService, | 70 | + PacketService packetService, |
73 | - HostStore hostStore) { | 71 | + HostManager hostService) { |
74 | - this.hostService = hostService; | 72 | + |
75 | - this.topologyService = topologyService; | ||
76 | this.deviceService = deviceService; | 73 | this.deviceService = deviceService; |
77 | - this.hostProvider = hostProvider; | ||
78 | this.packetService = packetService; | 74 | this.packetService = packetService; |
79 | - this.hostStore = hostStore; | 75 | + this.hostManager = hostService; |
80 | 76 | ||
81 | monitoredAddresses = new HashSet<>(); | 77 | monitoredAddresses = new HashSet<>(); |
78 | + hostProviders = new ConcurrentHashMap<>(); | ||
82 | 79 | ||
83 | probeRate = 30000; // milliseconds | 80 | probeRate = 30000; // milliseconds |
84 | 81 | ||
85 | timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS); | 82 | timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS); |
83 | + | ||
84 | + addDefaultAddresses(); | ||
86 | } | 85 | } |
87 | 86 | ||
88 | - public void addMonitoringFor(IpAddress ip) { | 87 | + private void addDefaultAddresses() { |
88 | + //monitoredAddresses.add(IpAddress.valueOf("10.0.0.1")); | ||
89 | + } | ||
90 | + | ||
91 | + void addMonitoringFor(IpAddress ip) { | ||
89 | monitoredAddresses.add(ip); | 92 | monitoredAddresses.add(ip); |
90 | } | 93 | } |
91 | 94 | ||
92 | - public void stopMonitoring(IpAddress ip) { | 95 | + void stopMonitoring(IpAddress ip) { |
93 | monitoredAddresses.remove(ip); | 96 | monitoredAddresses.remove(ip); |
94 | } | 97 | } |
95 | 98 | ||
96 | - public void shutdown() { | 99 | + void shutdown() { |
97 | timeout.cancel(); | 100 | timeout.cancel(); |
98 | } | 101 | } |
99 | 102 | ||
103 | + void registerHostProvider(HostProvider provider) { | ||
104 | + hostProviders.put(provider.id(), provider); | ||
105 | + } | ||
106 | + | ||
107 | + void unregisterHostProvider(HostProvider provider) { | ||
108 | + // TODO find out how to call this | ||
109 | + } | ||
110 | + | ||
100 | @Override | 111 | @Override |
101 | public void run(Timeout timeout) throws Exception { | 112 | public void run(Timeout timeout) throws Exception { |
102 | for (IpAddress ip : monitoredAddresses) { | 113 | for (IpAddress ip : monitoredAddresses) { |
103 | - Set<Host> hosts = Collections.emptySet(); //TODO hostService.getHostsByIp(ip); | 114 | + // TODO have to convert right now because the HostService API uses IpPrefix |
115 | + IpPrefix prefix = IpPrefix.valueOf(ip.toOctets()); | ||
116 | + | ||
117 | + Set<Host> hosts = hostManager.getHostsByIp(prefix); | ||
104 | 118 | ||
105 | if (hosts.isEmpty()) { | 119 | if (hosts.isEmpty()) { |
106 | sendArpRequest(ip); | 120 | sendArpRequest(ip); |
107 | } else { | 121 | } else { |
108 | for (Host host : hosts) { | 122 | for (Host host : hosts) { |
109 | - hostProvider.triggerProbe(host); | 123 | + HostProvider provider = hostProviders.get(host.providerId()); |
124 | + if (provider != null) { | ||
125 | + provider.triggerProbe(host); | ||
126 | + } | ||
110 | } | 127 | } |
111 | } | 128 | } |
112 | } | 129 | } |
... | @@ -120,29 +137,26 @@ public class HostMonitor implements TimerTask { | ... | @@ -120,29 +137,26 @@ public class HostMonitor implements TimerTask { |
120 | * @param targetIp IP address to ARP for | 137 | * @param targetIp IP address to ARP for |
121 | */ | 138 | */ |
122 | private void sendArpRequest(IpAddress targetIp) { | 139 | private void sendArpRequest(IpAddress targetIp) { |
123 | - | ||
124 | // Find ports with an IP address in the target's subnet and sent ARP | 140 | // Find ports with an IP address in the target's subnet and sent ARP |
125 | // probes out those ports. | 141 | // probes out those ports. |
126 | for (Device device : deviceService.getDevices()) { | 142 | for (Device device : deviceService.getDevices()) { |
127 | for (Port port : deviceService.getPorts(device.id())) { | 143 | for (Port port : deviceService.getPorts(device.id())) { |
128 | ConnectPoint cp = new ConnectPoint(device.id(), port.number()); | 144 | ConnectPoint cp = new ConnectPoint(device.id(), port.number()); |
129 | - PortAddresses addresses = hostStore.getAddressBindingsForPort(cp); | 145 | + PortAddresses addresses = hostManager.getAddressBindingsForPort(cp); |
130 | 146 | ||
131 | - /*for (IpPrefix prefix : addresses.ips()) { | 147 | + for (IpPrefix prefix : addresses.ips()) { |
132 | if (prefix.contains(targetIp)) { | 148 | if (prefix.contains(targetIp)) { |
133 | - sendProbe(device.id(), port, addresses, targetIp); | 149 | + sendProbe(device.id(), port, targetIp, |
150 | + prefix.toIpAddress(), addresses.mac()); | ||
151 | + } | ||
134 | } | 152 | } |
135 | - }*/ | ||
136 | } | 153 | } |
137 | } | 154 | } |
138 | - | ||
139 | - // TODO case where no address was found. | ||
140 | - // Broadcast out internal edge ports? | ||
141 | } | 155 | } |
142 | 156 | ||
143 | - private void sendProbe(DeviceId deviceId, Port port, PortAddresses portAddresses, | 157 | + private void sendProbe(DeviceId deviceId, Port port, IpAddress targetIp, |
144 | - IpAddress targetIp) { | 158 | + IpAddress sourceIp, MacAddress sourceMac) { |
145 | - Ethernet arpPacket = createArpFor(targetIp, portAddresses); | 159 | + Ethernet arpPacket = buildArpRequest(targetIp, sourceIp, sourceMac); |
146 | 160 | ||
147 | List<Instruction> instructions = new ArrayList<>(); | 161 | List<Instruction> instructions = new ArrayList<>(); |
148 | instructions.add(Instructions.createOutput(port.number())); | 162 | instructions.add(Instructions.createOutput(port.number())); |
... | @@ -158,30 +172,25 @@ public class HostMonitor implements TimerTask { | ... | @@ -158,30 +172,25 @@ public class HostMonitor implements TimerTask { |
158 | packetService.emit(outboundPacket); | 172 | packetService.emit(outboundPacket); |
159 | } | 173 | } |
160 | 174 | ||
161 | - private Ethernet createArpFor(IpAddress targetIp, PortAddresses portAddresses) { | 175 | + private Ethernet buildArpRequest(IpAddress targetIp, IpAddress sourceIp, |
176 | + MacAddress sourceMac) { | ||
162 | 177 | ||
163 | ARP arp = new ARP(); | 178 | ARP arp = new ARP(); |
164 | arp.setHardwareType(ARP.HW_TYPE_ETHERNET) | 179 | arp.setHardwareType(ARP.HW_TYPE_ETHERNET) |
165 | .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH) | 180 | .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH) |
166 | .setProtocolType(ARP.PROTO_TYPE_IP) | 181 | .setProtocolType(ARP.PROTO_TYPE_IP) |
167 | - .setProtocolAddressLength((byte) IpPrefix.INET_LEN); | 182 | + .setProtocolAddressLength((byte) IpPrefix.INET_LEN) |
168 | - | 183 | + .setOpCode(ARP.OP_REQUEST); |
169 | - byte[] sourceMacAddress; | ||
170 | - if (portAddresses.mac() == null) { | ||
171 | - sourceMacAddress = DEFAULT_MAC_ADDRESS; | ||
172 | - } else { | ||
173 | - sourceMacAddress = portAddresses.mac().getAddress(); | ||
174 | - } | ||
175 | 184 | ||
176 | - arp.setSenderHardwareAddress(sourceMacAddress) | 185 | + arp.setSenderHardwareAddress(sourceMac.getAddress()) |
177 | - //TODO .setSenderProtocolAddress(portAddresses.ips().toOctets()) | 186 | + .setSenderProtocolAddress(sourceIp.toOctets()) |
178 | .setTargetHardwareAddress(ZERO_MAC_ADDRESS) | 187 | .setTargetHardwareAddress(ZERO_MAC_ADDRESS) |
179 | .setTargetProtocolAddress(targetIp.toOctets()); | 188 | .setTargetProtocolAddress(targetIp.toOctets()); |
180 | 189 | ||
181 | Ethernet ethernet = new Ethernet(); | 190 | Ethernet ethernet = new Ethernet(); |
182 | ethernet.setEtherType(Ethernet.TYPE_ARP) | 191 | ethernet.setEtherType(Ethernet.TYPE_ARP) |
183 | .setDestinationMACAddress(BROADCAST_MAC) | 192 | .setDestinationMACAddress(BROADCAST_MAC) |
184 | - .setSourceMACAddress(sourceMacAddress) | 193 | + .setSourceMACAddress(sourceMac.getAddress()) |
185 | .setPayload(arp); | 194 | .setPayload(arp); |
186 | 195 | ||
187 | return ethernet; | 196 | return ethernet; | ... | ... |
... | @@ -35,6 +35,12 @@ | ... | @@ -35,6 +35,12 @@ |
35 | </dependency> | 35 | </dependency> |
36 | 36 | ||
37 | <dependency> | 37 | <dependency> |
38 | + <groupId>org.onlab.onos</groupId> | ||
39 | + <artifactId>onlab-netty</artifactId> | ||
40 | + <version>${project.version}</version> | ||
41 | + </dependency> | ||
42 | + | ||
43 | + <dependency> | ||
38 | <groupId>com.fasterxml.jackson.core</groupId> | 44 | <groupId>com.fasterxml.jackson.core</groupId> |
39 | <artifactId>jackson-databind</artifactId> | 45 | <artifactId>jackson-databind</artifactId> |
40 | </dependency> | 46 | </dependency> |
... | @@ -51,15 +57,6 @@ | ... | @@ -51,15 +57,6 @@ |
51 | <groupId>de.javakaffee</groupId> | 57 | <groupId>de.javakaffee</groupId> |
52 | <artifactId>kryo-serializers</artifactId> | 58 | <artifactId>kryo-serializers</artifactId> |
53 | </dependency> | 59 | </dependency> |
54 | - <dependency> | ||
55 | - <groupId>io.netty</groupId> | ||
56 | - <artifactId>netty-all</artifactId> | ||
57 | - </dependency> | ||
58 | - <dependency> | ||
59 | - <groupId>commons-pool</groupId> | ||
60 | - <artifactId>commons-pool</artifactId> | ||
61 | - <version>1.6</version> | ||
62 | - </dependency> | ||
63 | </dependencies> | 60 | </dependencies> |
64 | 61 | ||
65 | <build> | 62 | <build> | ... | ... |
... | @@ -20,7 +20,7 @@ import org.onlab.onos.cluster.DefaultControllerNode; | ... | @@ -20,7 +20,7 @@ import org.onlab.onos.cluster.DefaultControllerNode; |
20 | import org.onlab.onos.cluster.NodeId; | 20 | import org.onlab.onos.cluster.NodeId; |
21 | import org.onlab.onos.store.AbstractStore; | 21 | import org.onlab.onos.store.AbstractStore; |
22 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationAdminService; | 22 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationAdminService; |
23 | -import org.onlab.onos.store.cluster.messaging.impl.OnosClusterCommunicationManager; | 23 | +import org.onlab.onos.store.cluster.messaging.impl.ClusterCommunicationManager; |
24 | import org.onlab.packet.IpPrefix; | 24 | import org.onlab.packet.IpPrefix; |
25 | import org.slf4j.Logger; | 25 | import org.slf4j.Logger; |
26 | import org.slf4j.LoggerFactory; | 26 | import org.slf4j.LoggerFactory; |
... | @@ -50,7 +50,7 @@ public class DistributedClusterStore | ... | @@ -50,7 +50,7 @@ public class DistributedClusterStore |
50 | private final Map<NodeId, State> states = new ConcurrentHashMap<>(); | 50 | private final Map<NodeId, State> states = new ConcurrentHashMap<>(); |
51 | private final Cache<NodeId, ControllerNode> livenessCache = CacheBuilder.newBuilder() | 51 | private final Cache<NodeId, ControllerNode> livenessCache = CacheBuilder.newBuilder() |
52 | .maximumSize(1000) | 52 | .maximumSize(1000) |
53 | - .expireAfterWrite(OnosClusterCommunicationManager.HEART_BEAT_INTERVAL_MILLIS * 3, TimeUnit.MILLISECONDS) | 53 | + .expireAfterWrite(ClusterCommunicationManager.HEART_BEAT_INTERVAL_MILLIS * 3, TimeUnit.MILLISECONDS) |
54 | .removalListener(new LivenessCacheRemovalListener()).build(); | 54 | .removalListener(new LivenessCacheRemovalListener()).build(); |
55 | 55 | ||
56 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 56 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ... | ... |
1 | package org.onlab.onos.store.cluster.messaging; | 1 | package org.onlab.onos.store.cluster.messaging; |
2 | 2 | ||
3 | +/** | ||
4 | + * Interface for handling cluster messages. | ||
5 | + */ | ||
3 | public interface ClusterMessageHandler { | 6 | public interface ClusterMessageHandler { |
7 | + | ||
8 | + /** | ||
9 | + * Handles/Processes the cluster message. | ||
10 | + * @param message cluster message. | ||
11 | + */ | ||
4 | public void handle(ClusterMessage message); | 12 | public void handle(ClusterMessage message); |
5 | } | 13 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -2,6 +2,8 @@ package org.onlab.onos.store.cluster.messaging; | ... | @@ -2,6 +2,8 @@ package org.onlab.onos.store.cluster.messaging; |
2 | 2 | ||
3 | /** | 3 | /** |
4 | * Representation of a message subject. | 4 | * Representation of a message subject. |
5 | + * Cluster messages have associated subjects that dictate how they get handled | ||
6 | + * on the receiving side. | ||
5 | */ | 7 | */ |
6 | public class MessageSubject { | 8 | public class MessageSubject { |
7 | 9 | ... | ... |
core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/MessageSubscriber.java
deleted
100644 → 0
1 | -package org.onlab.onos.store.cluster.messaging; | ||
2 | - | ||
3 | -import org.onlab.onos.cluster.NodeId; | ||
4 | - | ||
5 | -/** | ||
6 | - * Represents a message consumer. | ||
7 | - */ | ||
8 | -public interface MessageSubscriber { | ||
9 | - | ||
10 | - /** | ||
11 | - * Receives the specified cluster message. | ||
12 | - * | ||
13 | - * @param message message to be received | ||
14 | - * @param fromNodeId node from which the message was received | ||
15 | - */ | ||
16 | - void receive(Object messagePayload, NodeId fromNodeId); | ||
17 | - | ||
18 | -} |
... | @@ -23,16 +23,16 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | ... | @@ -23,16 +23,16 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; |
23 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 23 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
24 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; | 24 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; |
25 | import org.onlab.onos.store.cluster.messaging.MessageSubject; | 25 | import org.onlab.onos.store.cluster.messaging.MessageSubject; |
26 | -import org.onlab.onos.store.messaging.Endpoint; | 26 | +import org.onlab.netty.Endpoint; |
27 | -import org.onlab.onos.store.messaging.Message; | 27 | +import org.onlab.netty.Message; |
28 | -import org.onlab.onos.store.messaging.MessageHandler; | 28 | +import org.onlab.netty.MessageHandler; |
29 | -import org.onlab.onos.store.messaging.MessagingService; | 29 | +import org.onlab.netty.MessagingService; |
30 | import org.slf4j.Logger; | 30 | import org.slf4j.Logger; |
31 | import org.slf4j.LoggerFactory; | 31 | import org.slf4j.LoggerFactory; |
32 | 32 | ||
33 | @Component(immediate = true) | 33 | @Component(immediate = true) |
34 | @Service | 34 | @Service |
35 | -public class OnosClusterCommunicationManager | 35 | +public class ClusterCommunicationManager |
36 | implements ClusterCommunicationService, ClusterCommunicationAdminService { | 36 | implements ClusterCommunicationService, ClusterCommunicationAdminService { |
37 | 37 | ||
38 | private final Logger log = LoggerFactory.getLogger(getClass()); | 38 | private final Logger log = LoggerFactory.getLogger(getClass()); | ... | ... |
core/store/dist/src/test/java/org/onlab/onos/store/cluster/impl/ClusterCommunicationManagerTest.java
... | @@ -6,8 +6,8 @@ import org.junit.Ignore; | ... | @@ -6,8 +6,8 @@ import org.junit.Ignore; |
6 | import org.junit.Test; | 6 | import org.junit.Test; |
7 | import org.onlab.onos.cluster.DefaultControllerNode; | 7 | import org.onlab.onos.cluster.DefaultControllerNode; |
8 | import org.onlab.onos.cluster.NodeId; | 8 | import org.onlab.onos.cluster.NodeId; |
9 | -import org.onlab.onos.store.cluster.messaging.impl.OnosClusterCommunicationManager; | 9 | +import org.onlab.onos.store.cluster.messaging.impl.ClusterCommunicationManager; |
10 | -import org.onlab.onos.store.messaging.impl.NettyMessagingService; | 10 | +import org.onlab.netty.NettyMessagingService; |
11 | import org.onlab.packet.IpPrefix; | 11 | import org.onlab.packet.IpPrefix; |
12 | 12 | ||
13 | import java.util.concurrent.CountDownLatch; | 13 | import java.util.concurrent.CountDownLatch; |
... | @@ -29,8 +29,8 @@ public class ClusterCommunicationManagerTest { | ... | @@ -29,8 +29,8 @@ public class ClusterCommunicationManagerTest { |
29 | 29 | ||
30 | private static final IpPrefix IP = IpPrefix.valueOf("127.0.0.1"); | 30 | private static final IpPrefix IP = IpPrefix.valueOf("127.0.0.1"); |
31 | 31 | ||
32 | - private OnosClusterCommunicationManager ccm1; | 32 | + private ClusterCommunicationManager ccm1; |
33 | - private OnosClusterCommunicationManager ccm2; | 33 | + private ClusterCommunicationManager ccm2; |
34 | 34 | ||
35 | private TestDelegate cnd1 = new TestDelegate(); | 35 | private TestDelegate cnd1 = new TestDelegate(); |
36 | private TestDelegate cnd2 = new TestDelegate(); | 36 | private TestDelegate cnd2 = new TestDelegate(); |
... | @@ -46,11 +46,11 @@ public class ClusterCommunicationManagerTest { | ... | @@ -46,11 +46,11 @@ public class ClusterCommunicationManagerTest { |
46 | NettyMessagingService messagingService = new NettyMessagingService(); | 46 | NettyMessagingService messagingService = new NettyMessagingService(); |
47 | messagingService.activate(); | 47 | messagingService.activate(); |
48 | 48 | ||
49 | - ccm1 = new OnosClusterCommunicationManager(); | 49 | + ccm1 = new ClusterCommunicationManager(); |
50 | // ccm1.serializationService = messageSerializer; | 50 | // ccm1.serializationService = messageSerializer; |
51 | ccm1.activate(); | 51 | ccm1.activate(); |
52 | 52 | ||
53 | - ccm2 = new OnosClusterCommunicationManager(); | 53 | + ccm2 = new ClusterCommunicationManager(); |
54 | // ccm2.serializationService = messageSerializer; | 54 | // ccm2.serializationService = messageSerializer; |
55 | ccm2.activate(); | 55 | ccm2.activate(); |
56 | 56 | ... | ... |
... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
11 | <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> | 11 | <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> |
12 | 12 | ||
13 | <bundle>mvn:com.hazelcast/hazelcast/3.3</bundle> | 13 | <bundle>mvn:com.hazelcast/hazelcast/3.3</bundle> |
14 | - <bundle>mvn:com.codahale.metrics/metrics-core/3.0.2</bundle> | 14 | + <bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle> |
15 | <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle> | 15 | <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle> |
16 | 16 | ||
17 | <bundle>mvn:com.esotericsoftware.kryo/kryo/2.24.0</bundle> | 17 | <bundle>mvn:com.esotericsoftware.kryo/kryo/2.24.0</bundle> | ... | ... |
... | @@ -169,7 +169,12 @@ public class OpenFlowControllerImpl implements OpenFlowController { | ... | @@ -169,7 +169,12 @@ public class OpenFlowControllerImpl implements OpenFlowController { |
169 | 169 | ||
170 | @Override | 170 | @Override |
171 | public void setRole(Dpid dpid, RoleState role) { | 171 | public void setRole(Dpid dpid, RoleState role) { |
172 | - getSwitch(dpid).setRole(role); | 172 | + final OpenFlowSwitch sw = getSwitch(dpid); |
173 | + if (sw == null) { | ||
174 | + log.debug("Switch not connected. Ignoring setRole({}, {})", dpid, role); | ||
175 | + return; | ||
176 | + } | ||
177 | + sw.setRole(role); | ||
173 | } | 178 | } |
174 | 179 | ||
175 | /** | 180 | /** | ... | ... |
... | @@ -48,6 +48,19 @@ | ... | @@ -48,6 +48,19 @@ |
48 | </dependency> | 48 | </dependency> |
49 | 49 | ||
50 | <dependency> | 50 | <dependency> |
51 | + <groupId>org.hamcrest</groupId> | ||
52 | + <artifactId>hamcrest-core</artifactId> | ||
53 | + <version>1.3</version> | ||
54 | + <scope>test</scope> | ||
55 | + </dependency> | ||
56 | + <dependency> | ||
57 | + <groupId>org.hamcrest</groupId> | ||
58 | + <artifactId>hamcrest-library</artifactId> | ||
59 | + <version>1.3</version> | ||
60 | + <scope>test</scope> | ||
61 | + </dependency> | ||
62 | + | ||
63 | + <dependency> | ||
51 | <groupId>org.slf4j</groupId> | 64 | <groupId>org.slf4j</groupId> |
52 | <artifactId>slf4j-api</artifactId> | 65 | <artifactId>slf4j-api</artifactId> |
53 | <version>1.7.6</version> | 66 | <version>1.7.6</version> |
... | @@ -235,6 +248,11 @@ | ... | @@ -235,6 +248,11 @@ |
235 | <classifier>tests</classifier> | 248 | <classifier>tests</classifier> |
236 | <scope>test</scope> | 249 | <scope>test</scope> |
237 | </dependency> | 250 | </dependency> |
251 | + <dependency> | ||
252 | + <groupId>commons-pool</groupId> | ||
253 | + <artifactId>commons-pool</artifactId> | ||
254 | + <version>1.6</version> | ||
255 | + </dependency> | ||
238 | </dependencies> | 256 | </dependencies> |
239 | </dependencyManagement> | 257 | </dependencyManagement> |
240 | 258 | ||
... | @@ -244,6 +262,14 @@ | ... | @@ -244,6 +262,14 @@ |
244 | <artifactId>junit</artifactId> | 262 | <artifactId>junit</artifactId> |
245 | </dependency> | 263 | </dependency> |
246 | <dependency> | 264 | <dependency> |
265 | + <groupId>org.hamcrest</groupId> | ||
266 | + <artifactId>hamcrest-core</artifactId> | ||
267 | + </dependency> | ||
268 | + <dependency> | ||
269 | + <groupId>org.hamcrest</groupId> | ||
270 | + <artifactId>hamcrest-library</artifactId> | ||
271 | + </dependency> | ||
272 | + <dependency> | ||
247 | <groupId>org.slf4j</groupId> | 273 | <groupId>org.slf4j</groupId> |
248 | <artifactId>slf4j-jdk14</artifactId> | 274 | <artifactId>slf4j-jdk14</artifactId> |
249 | </dependency> | 275 | </dependency> |
... | @@ -320,6 +346,35 @@ | ... | @@ -320,6 +346,35 @@ |
320 | </plugin> | 346 | </plugin> |
321 | 347 | ||
322 | <!-- TODO: add findbugs plugin for static code analysis; for explicit invocation only --> | 348 | <!-- TODO: add findbugs plugin for static code analysis; for explicit invocation only --> |
349 | + <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.--> | ||
350 | + <plugin> | ||
351 | + <groupId>org.eclipse.m2e</groupId> | ||
352 | + <artifactId>lifecycle-mapping</artifactId> | ||
353 | + <version>1.0.0</version> | ||
354 | + <configuration> | ||
355 | + <lifecycleMappingMetadata> | ||
356 | + <pluginExecutions> | ||
357 | + <pluginExecution> | ||
358 | + <pluginExecutionFilter> | ||
359 | + <groupId>org.jacoco</groupId> | ||
360 | + <artifactId> | ||
361 | + jacoco-maven-plugin | ||
362 | + </artifactId> | ||
363 | + <versionRange> | ||
364 | + [0.7.1.201405082137,) | ||
365 | + </versionRange> | ||
366 | + <goals> | ||
367 | + <goal>prepare-agent</goal> | ||
368 | + </goals> | ||
369 | + </pluginExecutionFilter> | ||
370 | + <action> | ||
371 | + <ignore></ignore> | ||
372 | + </action> | ||
373 | + </pluginExecution> | ||
374 | + </pluginExecutions> | ||
375 | + </lifecycleMappingMetadata> | ||
376 | + </configuration> | ||
377 | + </plugin> | ||
323 | </plugins> | 378 | </plugins> |
324 | </pluginManagement> | 379 | </pluginManagement> |
325 | 380 | ... | ... |
... | @@ -6,5 +6,10 @@ | ... | @@ -6,5 +6,10 @@ |
6 | <groupId>org.onlab.tools</groupId> | 6 | <groupId>org.onlab.tools</groupId> |
7 | <artifactId>onos-build-conf</artifactId> | 7 | <artifactId>onos-build-conf</artifactId> |
8 | <version>1.0</version> | 8 | <version>1.0</version> |
9 | + | ||
10 | + <properties> | ||
11 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
12 | + </properties> | ||
13 | + | ||
9 | </project> | 14 | </project> |
10 | 15 | ... | ... |
... | @@ -56,9 +56,13 @@ | ... | @@ -56,9 +56,13 @@ |
56 | <artifactId>objenesis</artifactId> | 56 | <artifactId>objenesis</artifactId> |
57 | </dependency> | 57 | </dependency> |
58 | <dependency> | 58 | <dependency> |
59 | - <groupId>com.codahale.metrics</groupId> | 59 | + <groupId>io.dropwizard.metrics</groupId> |
60 | <artifactId>metrics-core</artifactId> | 60 | <artifactId>metrics-core</artifactId> |
61 | - <version>3.0.2</version> | 61 | + <version>3.1.0</version> |
62 | + </dependency> | ||
63 | + <dependency> | ||
64 | + <groupId>org.apache.felix</groupId> | ||
65 | + <artifactId>org.apache.felix.scr.annotations</artifactId> | ||
62 | </dependency> | 66 | </dependency> |
63 | </dependencies> | 67 | </dependencies> |
64 | 68 | ... | ... |
1 | package org.onlab.metrics; | 1 | package org.onlab.metrics; |
2 | 2 | ||
3 | +import java.io.File; | ||
4 | +import java.util.Locale; | ||
3 | import java.util.Map; | 5 | import java.util.Map; |
4 | import java.util.concurrent.ConcurrentHashMap; | 6 | import java.util.concurrent.ConcurrentHashMap; |
5 | import java.util.concurrent.ConcurrentMap; | 7 | import java.util.concurrent.ConcurrentMap; |
8 | +import java.util.concurrent.TimeUnit; | ||
9 | + | ||
10 | +import org.apache.felix.scr.annotations.Activate; | ||
11 | +import org.apache.felix.scr.annotations.Component; | ||
12 | +import org.apache.felix.scr.annotations.Deactivate; | ||
6 | 13 | ||
7 | import com.codahale.metrics.Counter; | 14 | import com.codahale.metrics.Counter; |
15 | +import com.codahale.metrics.CsvReporter; | ||
8 | import com.codahale.metrics.Gauge; | 16 | import com.codahale.metrics.Gauge; |
9 | import com.codahale.metrics.Histogram; | 17 | import com.codahale.metrics.Histogram; |
10 | import com.codahale.metrics.Meter; | 18 | import com.codahale.metrics.Meter; |
... | @@ -45,24 +53,44 @@ import com.codahale.metrics.Timer; | ... | @@ -45,24 +53,44 @@ import com.codahale.metrics.Timer; |
45 | * </code> | 53 | * </code> |
46 | * </pre> | 54 | * </pre> |
47 | */ | 55 | */ |
56 | +@Component(immediate = true) | ||
48 | public final class MetricsManager implements MetricsService { | 57 | public final class MetricsManager implements MetricsService { |
49 | 58 | ||
50 | /** | 59 | /** |
51 | * Registry to hold the Components defined in the system. | 60 | * Registry to hold the Components defined in the system. |
52 | */ | 61 | */ |
53 | - private ConcurrentMap<String, MetricsComponent> componentsRegistry = | 62 | + private ConcurrentMap<String, MetricsComponent> componentsRegistry; |
54 | - new ConcurrentHashMap<>(); | ||
55 | 63 | ||
56 | /** | 64 | /** |
57 | * Registry for the Metrics objects created in the system. | 65 | * Registry for the Metrics objects created in the system. |
58 | */ | 66 | */ |
59 | - private final MetricRegistry metricsRegistry = new MetricRegistry(); | 67 | + private final MetricRegistry metricsRegistry; |
60 | 68 | ||
61 | /** | 69 | /** |
62 | - * Hide constructor. The only way to get the registry is through the | 70 | + * Default Reporter for this metrics manager. |
63 | - * singleton getter. | ||
64 | */ | 71 | */ |
65 | - private MetricsManager() {} | 72 | + private final CsvReporter reporter; |
73 | + | ||
74 | + public MetricsManager() { | ||
75 | + this.componentsRegistry = new ConcurrentHashMap<>(); | ||
76 | + this.metricsRegistry = new MetricRegistry(); | ||
77 | + | ||
78 | + this.reporter = CsvReporter.forRegistry(metricsRegistry) | ||
79 | + .formatFor(Locale.US) | ||
80 | + .convertRatesTo(TimeUnit.SECONDS) | ||
81 | + .convertDurationsTo(TimeUnit.MICROSECONDS) | ||
82 | + .build(new File("/tmp/")); | ||
83 | + | ||
84 | + reporter.start(10, TimeUnit.SECONDS); | ||
85 | + } | ||
86 | + | ||
87 | + @Activate | ||
88 | + public void activate() { | ||
89 | + } | ||
90 | + | ||
91 | + @Deactivate | ||
92 | + public void deactivate() { | ||
93 | + } | ||
66 | 94 | ||
67 | /** | 95 | /** |
68 | * Registers a component. | 96 | * Registers a component. | ... | ... |
... | @@ -250,6 +250,17 @@ public final class IpPrefix { | ... | @@ -250,6 +250,17 @@ public final class IpPrefix { |
250 | return new IpPrefix(version, host, netmask); | 250 | return new IpPrefix(version, host, netmask); |
251 | } | 251 | } |
252 | 252 | ||
253 | + /** | ||
254 | + * Returns an IpAddress of the bytes contained in this prefix. | ||
255 | + * FIXME this is a hack for now and only works because IpPrefix doesn't | ||
256 | + * mask the input bytes on creation. | ||
257 | + * | ||
258 | + * @return the IpAddress | ||
259 | + */ | ||
260 | + public IpAddress toIpAddress() { | ||
261 | + return IpAddress.valueOf(octets); | ||
262 | + } | ||
263 | + | ||
253 | public boolean isMasked() { | 264 | public boolean isMasked() { |
254 | return mask() != 0; | 265 | return mask() != 0; |
255 | } | 266 | } |
... | @@ -278,6 +289,17 @@ public final class IpPrefix { | ... | @@ -278,6 +289,17 @@ public final class IpPrefix { |
278 | return false; | 289 | return false; |
279 | } | 290 | } |
280 | 291 | ||
292 | + public boolean contains(IpAddress address) { | ||
293 | + // Need to get the network address because prefixes aren't automatically | ||
294 | + // masked on creation | ||
295 | + IpPrefix meMasked = network(); | ||
296 | + | ||
297 | + IpPrefix otherMasked = | ||
298 | + IpPrefix.valueOf(address.octets, netmask).network(); | ||
299 | + | ||
300 | + return Arrays.equals(meMasked.octets, otherMasked.octets); | ||
301 | + } | ||
302 | + | ||
281 | @Override | 303 | @Override |
282 | public int hashCode() { | 304 | public int hashCode() { |
283 | final int prime = 31; | 305 | final int prime = 31; |
... | @@ -303,6 +325,7 @@ public final class IpPrefix { | ... | @@ -303,6 +325,7 @@ public final class IpPrefix { |
303 | if (netmask != other.netmask) { | 325 | if (netmask != other.netmask) { |
304 | return false; | 326 | return false; |
305 | } | 327 | } |
328 | + // TODO not quite right until we mask the input | ||
306 | if (!Arrays.equals(octets, other.octets)) { | 329 | if (!Arrays.equals(octets, other.octets)) { |
307 | return false; | 330 | return false; |
308 | } | 331 | } | ... | ... |
... | @@ -76,7 +76,7 @@ public class IpPrefixTest { | ... | @@ -76,7 +76,7 @@ public class IpPrefixTest { |
76 | } | 76 | } |
77 | 77 | ||
78 | @Test | 78 | @Test |
79 | - public void testContains() { | 79 | + public void testContainsIpPrefix() { |
80 | IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31); | 80 | IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31); |
81 | IpPrefix slash32 = IpPrefix.valueOf(BYTES1, 32); | 81 | IpPrefix slash32 = IpPrefix.valueOf(BYTES1, 32); |
82 | IpPrefix differentSlash32 = IpPrefix.valueOf(BYTES2, 32); | 82 | IpPrefix differentSlash32 = IpPrefix.valueOf(BYTES2, 32); |
... | @@ -96,4 +96,17 @@ public class IpPrefixTest { | ... | @@ -96,4 +96,17 @@ public class IpPrefixTest { |
96 | assertTrue(slash8.contains(slash31)); | 96 | assertTrue(slash8.contains(slash31)); |
97 | assertFalse(slash31.contains(slash8)); | 97 | assertFalse(slash31.contains(slash8)); |
98 | } | 98 | } |
99 | + | ||
100 | + @Test | ||
101 | + public void testContainsIpAddress() { | ||
102 | + IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31); | ||
103 | + IpAddress slash32 = IpAddress.valueOf(BYTES1, 32); | ||
104 | + | ||
105 | + assertTrue(slash31.contains(slash32)); | ||
106 | + | ||
107 | + IpPrefix intf = IpPrefix.valueOf("192.168.10.101/24"); | ||
108 | + IpAddress addr = IpAddress.valueOf("192.168.10.1"); | ||
109 | + | ||
110 | + assertTrue(intf.contains(addr)); | ||
111 | + } | ||
99 | } | 112 | } | ... | ... |
utils/netty/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
5 | + <modelVersion>4.0.0</modelVersion> | ||
6 | + | ||
7 | + <parent> | ||
8 | + <groupId>org.onlab.onos</groupId> | ||
9 | + <artifactId>onlab-utils</artifactId> | ||
10 | + <version>1.0.0-SNAPSHOT</version> | ||
11 | + <relativePath>../pom.xml</relativePath> | ||
12 | + </parent> | ||
13 | + | ||
14 | + <artifactId>onlab-netty</artifactId> | ||
15 | + <packaging>bundle</packaging> | ||
16 | + | ||
17 | + <description>Network I/O using Netty framework</description> | ||
18 | + | ||
19 | + <dependencies> | ||
20 | + <dependency> | ||
21 | + <groupId>com.google.guava</groupId> | ||
22 | + <artifactId>guava-testlib</artifactId> | ||
23 | + <scope>test</scope> | ||
24 | + </dependency> | ||
25 | + <dependency> | ||
26 | + <groupId>org.onlab.onos</groupId> | ||
27 | + <artifactId>onlab-misc</artifactId> | ||
28 | + </dependency> | ||
29 | + <dependency> | ||
30 | + <groupId>org.onlab.onos</groupId> | ||
31 | + <artifactId>onlab-junit</artifactId> | ||
32 | + <scope>test</scope> | ||
33 | + </dependency> | ||
34 | + <dependency> | ||
35 | + <groupId>de.javakaffee</groupId> | ||
36 | + <artifactId>kryo-serializers</artifactId> | ||
37 | + </dependency> | ||
38 | + <dependency> | ||
39 | + <groupId>io.netty</groupId> | ||
40 | + <artifactId>netty-all</artifactId> | ||
41 | + </dependency> | ||
42 | + <dependency> | ||
43 | + <groupId>commons-pool</groupId> | ||
44 | + <artifactId>commons-pool</artifactId> | ||
45 | + </dependency> | ||
46 | + </dependencies> | ||
47 | + | ||
48 | +</project> |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | 2 | ||
3 | import java.util.concurrent.TimeUnit; | 3 | import java.util.concurrent.TimeUnit; |
4 | import java.util.concurrent.TimeoutException; | 4 | import java.util.concurrent.TimeoutException; |
5 | 5 | ||
6 | -import org.onlab.onos.store.messaging.Response; | ||
7 | - | ||
8 | /** | 6 | /** |
9 | * An asynchronous response. | 7 | * An asynchronous response. |
10 | * This class provides a base implementation of Response, with methods to retrieve the | 8 | * This class provides a base implementation of Response, with methods to retrieve the | ... | ... |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | 2 | ||
3 | import java.io.IOException; | 3 | import java.io.IOException; |
4 | 4 | ||
5 | -import org.onlab.onos.store.messaging.Message; | ||
6 | -import org.onlab.onos.store.messaging.MessageHandler; | ||
7 | - | ||
8 | /** | 5 | /** |
9 | * Message handler that echos the message back to the sender. | 6 | * Message handler that echos the message back to the sender. |
10 | */ | 7 | */ | ... | ... |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | 2 | ||
3 | import java.io.IOException; | 3 | import java.io.IOException; |
4 | 4 | ||
5 | -import org.onlab.onos.store.messaging.Endpoint; | ||
6 | -import org.onlab.onos.store.messaging.Message; | ||
7 | - | ||
8 | /** | 5 | /** |
9 | * Internal message representation with additional attributes | 6 | * Internal message representation with additional attributes |
10 | * for supporting, synchronous request/reply behavior. | 7 | * for supporting, synchronous request/reply behavior. | ... | ... |
1 | +package org.onlab.netty; | ||
2 | + | ||
3 | +import org.onlab.util.KryoPool; | ||
4 | +import org.slf4j.Logger; | ||
5 | +import org.slf4j.LoggerFactory; | ||
6 | + | ||
7 | +import java.util.ArrayList; | ||
8 | +import java.util.HashMap; | ||
9 | + | ||
10 | +/** | ||
11 | + * Kryo Serializer. | ||
12 | + */ | ||
13 | +public class KryoSerializer implements Serializer { | ||
14 | + | ||
15 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
16 | + | ||
17 | + private KryoPool serializerPool; | ||
18 | + | ||
19 | + public KryoSerializer() { | ||
20 | + setupKryoPool(); | ||
21 | + } | ||
22 | + | ||
23 | + /** | ||
24 | + * Sets up the common serialzers pool. | ||
25 | + */ | ||
26 | + protected void setupKryoPool() { | ||
27 | + // FIXME Slice out types used in common to separate pool/namespace. | ||
28 | + serializerPool = KryoPool.newBuilder() | ||
29 | + .register(ArrayList.class, | ||
30 | + HashMap.class, | ||
31 | + ArrayList.class | ||
32 | + ) | ||
33 | + .build() | ||
34 | + .populate(1); | ||
35 | + } | ||
36 | + | ||
37 | + | ||
38 | + @Override | ||
39 | + public Object decode(byte[] data) { | ||
40 | + return serializerPool.deserialize(data); | ||
41 | + } | ||
42 | + | ||
43 | + @Override | ||
44 | + public byte[] encode(Object payload) { | ||
45 | + return serializerPool.serialize(payload); | ||
46 | + } | ||
47 | +} |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | - | ||
3 | -import org.onlab.onos.store.messaging.Message; | ||
4 | -import org.onlab.onos.store.messaging.MessageHandler; | ||
5 | 2 | ||
6 | /** | 3 | /** |
7 | * A MessageHandler that simply logs the information. | 4 | * A MessageHandler that simply logs the information. | ... | ... |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | 2 | ||
3 | import java.util.Arrays; | 3 | import java.util.Arrays; |
4 | import java.util.List; | 4 | import java.util.List; |
5 | 5 | ||
6 | import static com.google.common.base.Preconditions.checkState; | 6 | import static com.google.common.base.Preconditions.checkState; |
7 | 7 | ||
8 | -import org.onlab.onos.store.cluster.messaging.SerializationService; | ||
9 | -import org.onlab.onos.store.messaging.Endpoint; | ||
10 | - | ||
11 | import io.netty.buffer.ByteBuf; | 8 | import io.netty.buffer.ByteBuf; |
12 | import io.netty.channel.ChannelHandlerContext; | 9 | import io.netty.channel.ChannelHandlerContext; |
13 | import io.netty.handler.codec.ByteToMessageDecoder; | 10 | import io.netty.handler.codec.ByteToMessageDecoder; |
14 | 11 | ||
15 | /** | 12 | /** |
16 | - * Decode bytes into a InrenalMessage. | 13 | + * Decode bytes into a InternalMessage. |
17 | */ | 14 | */ |
18 | public class MessageDecoder extends ByteToMessageDecoder { | 15 | public class MessageDecoder extends ByteToMessageDecoder { |
19 | 16 | ||
20 | private final NettyMessagingService messagingService; | 17 | private final NettyMessagingService messagingService; |
21 | - private final SerializationService serializationService; | 18 | + private final Serializer serializer; |
22 | 19 | ||
23 | - public MessageDecoder(NettyMessagingService messagingService, SerializationService serializationService) { | 20 | + public MessageDecoder(NettyMessagingService messagingService, Serializer serializer) { |
24 | this.messagingService = messagingService; | 21 | this.messagingService = messagingService; |
25 | - this.serializationService = serializationService; | 22 | + this.serializer = serializer; |
26 | } | 23 | } |
27 | 24 | ||
28 | @Override | 25 | @Override |
... | @@ -47,7 +44,7 @@ public class MessageDecoder extends ByteToMessageDecoder { | ... | @@ -47,7 +44,7 @@ public class MessageDecoder extends ByteToMessageDecoder { |
47 | Endpoint sender = new Endpoint(host, port); | 44 | Endpoint sender = new Endpoint(host, port); |
48 | 45 | ||
49 | // read message payload; first read size and then bytes. | 46 | // read message payload; first read size and then bytes. |
50 | - Object payload = serializationService.decode(in.readBytes(in.readInt()).array()); | 47 | + Object payload = serializer.decode(in.readBytes(in.readInt()).array()); |
51 | 48 | ||
52 | InternalMessage message = new InternalMessage.Builder(messagingService) | 49 | InternalMessage message = new InternalMessage.Builder(messagingService) |
53 | .withId(id) | 50 | .withId(id) | ... | ... |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | - | ||
3 | -import org.onlab.onos.store.cluster.messaging.SerializationService; | ||
4 | 2 | ||
5 | import io.netty.buffer.ByteBuf; | 3 | import io.netty.buffer.ByteBuf; |
6 | import io.netty.channel.ChannelHandlerContext; | 4 | import io.netty.channel.ChannelHandlerContext; |
... | @@ -14,10 +12,10 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { | ... | @@ -14,10 +12,10 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { |
14 | // onosiscool in ascii | 12 | // onosiscool in ascii |
15 | public static final byte[] PREAMBLE = "onosiscool".getBytes(); | 13 | public static final byte[] PREAMBLE = "onosiscool".getBytes(); |
16 | 14 | ||
17 | - private final SerializationService serializationService; | 15 | + private final Serializer serializer; |
18 | 16 | ||
19 | - public MessageEncoder(SerializationService serializationService) { | 17 | + public MessageEncoder(Serializer serializer) { |
20 | - this.serializationService = serializationService; | 18 | + this.serializer = serializer; |
21 | } | 19 | } |
22 | 20 | ||
23 | @Override | 21 | @Override |
... | @@ -46,12 +44,12 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { | ... | @@ -46,12 +44,12 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { |
46 | out.writeInt(message.sender().port()); | 44 | out.writeInt(message.sender().port()); |
47 | 45 | ||
48 | try { | 46 | try { |
49 | - serializationService.encode(message.payload()); | 47 | + serializer.encode(message.payload()); |
50 | } catch (Exception e) { | 48 | } catch (Exception e) { |
51 | e.printStackTrace(); | 49 | e.printStackTrace(); |
52 | } | 50 | } |
53 | 51 | ||
54 | - byte[] payload = serializationService.encode(message.payload()); | 52 | + byte[] payload = serializer.encode(message.payload()); |
55 | 53 | ||
56 | // write payload length. | 54 | // write payload length. |
57 | out.writeInt(payload.length); | 55 | out.writeInt(payload.length); | ... | ... |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | 2 | ||
3 | import java.io.IOException; | 3 | import java.io.IOException; |
4 | import java.net.UnknownHostException; | 4 | import java.net.UnknownHostException; |
... | @@ -25,17 +25,6 @@ import org.apache.commons.lang.math.RandomUtils; | ... | @@ -25,17 +25,6 @@ import org.apache.commons.lang.math.RandomUtils; |
25 | import org.apache.commons.pool.KeyedObjectPool; | 25 | import org.apache.commons.pool.KeyedObjectPool; |
26 | import org.apache.commons.pool.KeyedPoolableObjectFactory; | 26 | import org.apache.commons.pool.KeyedPoolableObjectFactory; |
27 | import org.apache.commons.pool.impl.GenericKeyedObjectPool; | 27 | import org.apache.commons.pool.impl.GenericKeyedObjectPool; |
28 | -import org.apache.felix.scr.annotations.Activate; | ||
29 | -import org.apache.felix.scr.annotations.Component; | ||
30 | -import org.apache.felix.scr.annotations.Deactivate; | ||
31 | -import org.apache.felix.scr.annotations.Reference; | ||
32 | -import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
33 | -import org.apache.felix.scr.annotations.Service; | ||
34 | -import org.onlab.onos.store.cluster.messaging.SerializationService; | ||
35 | -import org.onlab.onos.store.messaging.Endpoint; | ||
36 | -import org.onlab.onos.store.messaging.MessageHandler; | ||
37 | -import org.onlab.onos.store.messaging.MessagingService; | ||
38 | -import org.onlab.onos.store.messaging.Response; | ||
39 | import org.slf4j.Logger; | 28 | import org.slf4j.Logger; |
40 | import org.slf4j.LoggerFactory; | 29 | import org.slf4j.LoggerFactory; |
41 | 30 | ||
... | @@ -45,8 +34,6 @@ import com.google.common.cache.CacheBuilder; | ... | @@ -45,8 +34,6 @@ import com.google.common.cache.CacheBuilder; |
45 | /** | 34 | /** |
46 | * A Netty based implementation of MessagingService. | 35 | * A Netty based implementation of MessagingService. |
47 | */ | 36 | */ |
48 | -@Component(immediate = true) | ||
49 | -@Service | ||
50 | public class NettyMessagingService implements MessagingService { | 37 | public class NettyMessagingService implements MessagingService { |
51 | 38 | ||
52 | private final Logger log = LoggerFactory.getLogger(getClass()); | 39 | private final Logger log = LoggerFactory.getLogger(getClass()); |
... | @@ -60,8 +47,7 @@ public class NettyMessagingService implements MessagingService { | ... | @@ -60,8 +47,7 @@ public class NettyMessagingService implements MessagingService { |
60 | private Cache<Long, AsyncResponse<?>> responseFutures; | 47 | private Cache<Long, AsyncResponse<?>> responseFutures; |
61 | private final Endpoint localEp; | 48 | private final Endpoint localEp; |
62 | 49 | ||
63 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 50 | + protected Serializer serializer; |
64 | - protected SerializationService serializationService; | ||
65 | 51 | ||
66 | public NettyMessagingService() { | 52 | public NettyMessagingService() { |
67 | // TODO: Default port should be configurable. | 53 | // TODO: Default port should be configurable. |
... | @@ -79,7 +65,6 @@ public class NettyMessagingService implements MessagingService { | ... | @@ -79,7 +65,6 @@ public class NettyMessagingService implements MessagingService { |
79 | } | 65 | } |
80 | } | 66 | } |
81 | 67 | ||
82 | - @Activate | ||
83 | public void activate() throws Exception { | 68 | public void activate() throws Exception { |
84 | responseFutures = CacheBuilder.newBuilder() | 69 | responseFutures = CacheBuilder.newBuilder() |
85 | .maximumSize(100000) | 70 | .maximumSize(100000) |
... | @@ -90,7 +75,6 @@ public class NettyMessagingService implements MessagingService { | ... | @@ -90,7 +75,6 @@ public class NettyMessagingService implements MessagingService { |
90 | startAcceptingConnections(); | 75 | startAcceptingConnections(); |
91 | } | 76 | } |
92 | 77 | ||
93 | - @Deactivate | ||
94 | public void deactivate() throws Exception { | 78 | public void deactivate() throws Exception { |
95 | channels.close(); | 79 | channels.close(); |
96 | bossGroup.shutdownGracefully(); | 80 | bossGroup.shutdownGracefully(); |
... | @@ -213,8 +197,8 @@ public class NettyMessagingService implements MessagingService { | ... | @@ -213,8 +197,8 @@ public class NettyMessagingService implements MessagingService { |
213 | @Override | 197 | @Override |
214 | protected void initChannel(SocketChannel channel) throws Exception { | 198 | protected void initChannel(SocketChannel channel) throws Exception { |
215 | channel.pipeline() | 199 | channel.pipeline() |
216 | - .addLast(new MessageEncoder(serializationService)) | 200 | + .addLast(new MessageEncoder(serializer)) |
217 | - .addLast(new MessageDecoder(NettyMessagingService.this, serializationService)) | 201 | + .addLast(new MessageDecoder(NettyMessagingService.this, serializer)) |
218 | .addLast(new NettyMessagingService.InboundMessageDispatcher()); | 202 | .addLast(new NettyMessagingService.InboundMessageDispatcher()); |
219 | } | 203 | } |
220 | } | 204 | } | ... | ... |
1 | +package org.onlab.netty; | ||
2 | + | ||
3 | +/** | ||
4 | + * Interface for encoding/decoding message payloads. | ||
5 | + */ | ||
6 | +public interface Serializer { | ||
7 | + | ||
8 | + /** | ||
9 | + * Decodes the specified byte array to a POJO. | ||
10 | + * | ||
11 | + * @param data byte array. | ||
12 | + * @return POJO | ||
13 | + */ | ||
14 | + Object decode(byte[] data); | ||
15 | + | ||
16 | + /** | ||
17 | + * Encodes the specified POJO into a byte array. | ||
18 | + * | ||
19 | + * @param data POJO to be encoded | ||
20 | + * @return byte array. | ||
21 | + */ | ||
22 | + byte[] encode(Object message); | ||
23 | + | ||
24 | +} |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | 2 | ||
3 | import java.util.concurrent.TimeUnit; | 3 | import java.util.concurrent.TimeUnit; |
4 | 4 | ||
5 | -import org.onlab.onos.store.cluster.impl.MessageSerializer; | ||
6 | -import org.onlab.onos.store.messaging.Endpoint; | ||
7 | -import org.onlab.onos.store.messaging.Response; | ||
8 | - | ||
9 | public final class SimpleClient { | 5 | public final class SimpleClient { |
10 | private SimpleClient() {} | 6 | private SimpleClient() {} |
11 | 7 | ||
... | @@ -21,9 +17,8 @@ public final class SimpleClient { | ... | @@ -21,9 +17,8 @@ public final class SimpleClient { |
21 | public static class TestNettyMessagingService extends NettyMessagingService { | 17 | public static class TestNettyMessagingService extends NettyMessagingService { |
22 | public TestNettyMessagingService(int port) throws Exception { | 18 | public TestNettyMessagingService(int port) throws Exception { |
23 | super(port); | 19 | super(port); |
24 | - MessageSerializer mgr = new MessageSerializer(); | 20 | + Serializer serializer = new KryoSerializer(); |
25 | - mgr.activate(); | 21 | + this.serializer = serializer; |
26 | - this.serializationService = mgr; | ||
27 | } | 22 | } |
28 | } | 23 | } |
29 | } | 24 | } | ... | ... |
1 | -package org.onlab.onos.store.messaging.impl; | 1 | +package org.onlab.netty; |
2 | - | ||
3 | -import org.onlab.onos.store.cluster.impl.MessageSerializer; | ||
4 | 2 | ||
5 | public final class SimpleServer { | 3 | public final class SimpleServer { |
6 | private SimpleServer() {} | 4 | private SimpleServer() {} |
... | @@ -14,9 +12,8 @@ public final class SimpleServer { | ... | @@ -14,9 +12,8 @@ public final class SimpleServer { |
14 | 12 | ||
15 | public static class TestNettyMessagingService extends NettyMessagingService { | 13 | public static class TestNettyMessagingService extends NettyMessagingService { |
16 | protected TestNettyMessagingService() { | 14 | protected TestNettyMessagingService() { |
17 | - MessageSerializer mgr = new MessageSerializer(); | 15 | + Serializer serializer = new KryoSerializer(); |
18 | - mgr.activate(); | 16 | + this.serializer = serializer; |
19 | - this.serializationService = mgr; | ||
20 | } | 17 | } |
21 | } | 18 | } |
22 | } | 19 | } | ... | ... |
... | @@ -19,6 +19,7 @@ | ... | @@ -19,6 +19,7 @@ |
19 | <modules> | 19 | <modules> |
20 | <module>junit</module> | 20 | <module>junit</module> |
21 | <module>misc</module> | 21 | <module>misc</module> |
22 | + <module>netty</module> | ||
22 | <module>nio</module> | 23 | <module>nio</module> |
23 | <module>osgi</module> | 24 | <module>osgi</module> |
24 | <module>rest</module> | 25 | <module>rest</module> | ... | ... |
-
Please register or login to post a comment