Showing
6 changed files
with
262 additions
and
49 deletions
| ... | @@ -34,7 +34,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); | ... | @@ -34,7 +34,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); |
| 34 | 34 | ||
| 35 | System.exit(0); | 35 | System.exit(0); |
| 36 | } | 36 | } |
| 37 | - public static void startStandalone(String... args) throws Exception { | 37 | + public static void startStandalone(String[] args) throws Exception { |
| 38 | String host = args.length > 0 ? args[0] : "localhost"; | 38 | String host = args.length > 0 ? args[0] : "localhost"; |
| 39 | int port = args.length > 1 ? Integer.parseInt(args[1]) : 8081; | 39 | int port = args.length > 1 ? Integer.parseInt(args[1]) : 8081; |
| 40 | int warmup = args.length > 2 ? Integer.parseInt(args[2]) : 1000; | 40 | int warmup = args.length > 2 ? Integer.parseInt(args[2]) : 1000; |
| ... | @@ -46,7 +46,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); | ... | @@ -46,7 +46,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); |
| 46 | metrics.activate(); | 46 | metrics.activate(); |
| 47 | MetricsFeature feature = new MetricsFeature("latency"); | 47 | MetricsFeature feature = new MetricsFeature("latency"); |
| 48 | MetricsComponent component = metrics.registerComponent("NettyMessaging"); | 48 | MetricsComponent component = metrics.registerComponent("NettyMessaging"); |
| 49 | - log.info("warmup...."); | 49 | + log.info("connecting " + host + ":" + port + " warmup:" + warmup + " iterations:" + iterations); |
| 50 | 50 | ||
| 51 | for (int i = 0; i < warmup; i++) { | 51 | for (int i = 0; i < warmup; i++) { |
| 52 | messaging.sendAsync(endpoint, "simple", "Hello World".getBytes()); | 52 | messaging.sendAsync(endpoint, "simple", "Hello World".getBytes()); |
| ... | @@ -73,6 +73,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); | ... | @@ -73,6 +73,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); |
| 73 | // System.out.println("Got back:" + new String(response.get(2, TimeUnit.SECONDS))); | 73 | // System.out.println("Got back:" + new String(response.get(2, TimeUnit.SECONDS))); |
| 74 | context.stop(); | 74 | context.stop(); |
| 75 | } | 75 | } |
| 76 | + metrics.deactivate(); | ||
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | public static class TestNettyMessagingService extends NettyMessagingService { | 79 | public static class TestNettyMessagingService extends NettyMessagingService { | ... | ... |
| ... | @@ -18,15 +18,15 @@ public class SimpleNettyClientCommand extends AbstractShellCommand { | ... | @@ -18,15 +18,15 @@ public class SimpleNettyClientCommand extends AbstractShellCommand { |
| 18 | required = false, multiValued = false) | 18 | required = false, multiValued = false) |
| 19 | String hostname = "localhost"; | 19 | String hostname = "localhost"; |
| 20 | 20 | ||
| 21 | - @Argument(index = 3, name = "port", description = "Port", | 21 | + @Argument(index = 1, name = "port", description = "Port", |
| 22 | required = false, multiValued = false) | 22 | required = false, multiValued = false) |
| 23 | String port = "8081"; | 23 | String port = "8081"; |
| 24 | 24 | ||
| 25 | - @Argument(index = 1, name = "warmupCount", description = "Warm-up count", | 25 | + @Argument(index = 2, name = "warmupCount", description = "Warm-up count", |
| 26 | required = false, multiValued = false) | 26 | required = false, multiValued = false) |
| 27 | String warmupCount = "1000"; | 27 | String warmupCount = "1000"; |
| 28 | 28 | ||
| 29 | - @Argument(index = 2, name = "messageCount", description = "Message count", | 29 | + @Argument(index = 3, name = "messageCount", description = "Message count", |
| 30 | required = false, multiValued = false) | 30 | required = false, multiValued = false) |
| 31 | String messageCount = "100000"; | 31 | String messageCount = "100000"; |
| 32 | 32 | ... | ... |
| 1 | package org.onlab.onos.net.intent; | 1 | package org.onlab.onos.net.intent; |
| 2 | 2 | ||
| 3 | +import java.util.concurrent.Future; | ||
| 4 | + | ||
| 5 | +import org.onlab.onos.net.flow.CompletedBatchOperation; | ||
| 6 | + | ||
| 3 | /** | 7 | /** |
| 4 | * Abstraction of entity capable of installing intents to the environment. | 8 | * Abstraction of entity capable of installing intents to the environment. |
| 5 | */ | 9 | */ |
| ... | @@ -10,7 +14,7 @@ public interface IntentInstaller<T extends InstallableIntent> { | ... | @@ -10,7 +14,7 @@ public interface IntentInstaller<T extends InstallableIntent> { |
| 10 | * @param intent intent to be installed | 14 | * @param intent intent to be installed |
| 11 | * @throws IntentException if issues are encountered while installing the intent | 15 | * @throws IntentException if issues are encountered while installing the intent |
| 12 | */ | 16 | */ |
| 13 | - void install(T intent); | 17 | + Future<CompletedBatchOperation> install(T intent); |
| 14 | 18 | ||
| 15 | /** | 19 | /** |
| 16 | * Uninstalls the specified intent from the environment. | 20 | * Uninstalls the specified intent from the environment. |
| ... | @@ -18,5 +22,5 @@ public interface IntentInstaller<T extends InstallableIntent> { | ... | @@ -18,5 +22,5 @@ public interface IntentInstaller<T extends InstallableIntent> { |
| 18 | * @param intent intent to be uninstalled | 22 | * @param intent intent to be uninstalled |
| 19 | * @throws IntentException if issues are encountered while uninstalling the intent | 23 | * @throws IntentException if issues are encountered while uninstalling the intent |
| 20 | */ | 24 | */ |
| 21 | - void uninstall(T intent); | 25 | + Future<CompletedBatchOperation> uninstall(T intent); |
| 22 | } | 26 | } | ... | ... |
| 1 | package org.onlab.onos.net.intent; | 1 | package org.onlab.onos.net.intent; |
| 2 | 2 | ||
| 3 | -import org.junit.After; | 3 | +import static org.junit.Assert.assertEquals; |
| 4 | -import org.junit.Before; | 4 | +import static org.junit.Assert.assertFalse; |
| 5 | -import org.junit.Test; | 5 | +import static org.junit.Assert.assertNull; |
| 6 | +import static org.junit.Assert.fail; | ||
| 7 | +import static org.onlab.onos.net.intent.IntentEvent.Type.FAILED; | ||
| 8 | +import static org.onlab.onos.net.intent.IntentEvent.Type.INSTALLED; | ||
| 9 | +import static org.onlab.onos.net.intent.IntentEvent.Type.SUBMITTED; | ||
| 10 | +import static org.onlab.onos.net.intent.IntentEvent.Type.WITHDRAWN; | ||
| 6 | 11 | ||
| 7 | import java.util.ArrayList; | 12 | import java.util.ArrayList; |
| 8 | import java.util.Arrays; | 13 | import java.util.Arrays; |
| 9 | import java.util.Collections; | 14 | import java.util.Collections; |
| 10 | import java.util.Iterator; | 15 | import java.util.Iterator; |
| 11 | import java.util.List; | 16 | import java.util.List; |
| 17 | +import java.util.concurrent.Future; | ||
| 12 | 18 | ||
| 13 | -import static org.junit.Assert.*; | 19 | +import org.junit.After; |
| 14 | -import static org.onlab.onos.net.intent.IntentEvent.Type.*; | 20 | +import org.junit.Before; |
| 21 | +import org.junit.Test; | ||
| 22 | +import org.onlab.onos.net.flow.CompletedBatchOperation; | ||
| 15 | 23 | ||
| 16 | /** | 24 | /** |
| 17 | * Suite of tests for the intent service contract. | 25 | * Suite of tests for the intent service contract. |
| ... | @@ -290,17 +298,19 @@ public class IntentServiceTest { | ... | @@ -290,17 +298,19 @@ public class IntentServiceTest { |
| 290 | } | 298 | } |
| 291 | 299 | ||
| 292 | @Override | 300 | @Override |
| 293 | - public void install(TestInstallableIntent intent) { | 301 | + public Future<CompletedBatchOperation> install(TestInstallableIntent intent) { |
| 294 | if (fail) { | 302 | if (fail) { |
| 295 | throw new IntentException("install failed by design"); | 303 | throw new IntentException("install failed by design"); |
| 296 | } | 304 | } |
| 305 | + return null; | ||
| 297 | } | 306 | } |
| 298 | 307 | ||
| 299 | @Override | 308 | @Override |
| 300 | - public void uninstall(TestInstallableIntent intent) { | 309 | + public Future<CompletedBatchOperation> uninstall(TestInstallableIntent intent) { |
| 301 | if (fail) { | 310 | if (fail) { |
| 302 | throw new IntentException("remove failed by design"); | 311 | throw new IntentException("remove failed by design"); |
| 303 | } | 312 | } |
| 313 | + return null; | ||
| 304 | } | 314 | } |
| 305 | } | 315 | } |
| 306 | 316 | ... | ... |
| ... | @@ -13,12 +13,14 @@ import static org.onlab.util.Tools.namedThreads; | ... | @@ -13,12 +13,14 @@ import static org.onlab.util.Tools.namedThreads; |
| 13 | import static org.slf4j.LoggerFactory.getLogger; | 13 | import static org.slf4j.LoggerFactory.getLogger; |
| 14 | 14 | ||
| 15 | import java.util.ArrayList; | 15 | import java.util.ArrayList; |
| 16 | +import java.util.Iterator; | ||
| 16 | import java.util.List; | 17 | import java.util.List; |
| 17 | import java.util.Map; | 18 | import java.util.Map; |
| 18 | import java.util.Objects; | 19 | import java.util.Objects; |
| 19 | import java.util.concurrent.ConcurrentHashMap; | 20 | import java.util.concurrent.ConcurrentHashMap; |
| 20 | import java.util.concurrent.ConcurrentMap; | 21 | import java.util.concurrent.ConcurrentMap; |
| 21 | import java.util.concurrent.ExecutorService; | 22 | import java.util.concurrent.ExecutorService; |
| 23 | +import java.util.concurrent.Future; | ||
| 22 | 24 | ||
| 23 | import org.apache.felix.scr.annotations.Activate; | 25 | import org.apache.felix.scr.annotations.Activate; |
| 24 | import org.apache.felix.scr.annotations.Component; | 26 | import org.apache.felix.scr.annotations.Component; |
| ... | @@ -28,6 +30,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -28,6 +30,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 28 | import org.apache.felix.scr.annotations.Service; | 30 | import org.apache.felix.scr.annotations.Service; |
| 29 | import org.onlab.onos.event.AbstractListenerRegistry; | 31 | import org.onlab.onos.event.AbstractListenerRegistry; |
| 30 | import org.onlab.onos.event.EventDeliveryService; | 32 | import org.onlab.onos.event.EventDeliveryService; |
| 33 | +import org.onlab.onos.net.flow.CompletedBatchOperation; | ||
| 31 | import org.onlab.onos.net.intent.InstallableIntent; | 34 | import org.onlab.onos.net.intent.InstallableIntent; |
| 32 | import org.onlab.onos.net.intent.Intent; | 35 | import org.onlab.onos.net.intent.Intent; |
| 33 | import org.onlab.onos.net.intent.IntentCompiler; | 36 | import org.onlab.onos.net.intent.IntentCompiler; |
| ... | @@ -44,7 +47,9 @@ import org.onlab.onos.net.intent.IntentStore; | ... | @@ -44,7 +47,9 @@ import org.onlab.onos.net.intent.IntentStore; |
| 44 | import org.onlab.onos.net.intent.IntentStoreDelegate; | 47 | import org.onlab.onos.net.intent.IntentStoreDelegate; |
| 45 | import org.slf4j.Logger; | 48 | import org.slf4j.Logger; |
| 46 | 49 | ||
| 50 | +import com.google.common.collect.ImmutableList; | ||
| 47 | import com.google.common.collect.ImmutableMap; | 51 | import com.google.common.collect.ImmutableMap; |
| 52 | +import com.google.common.collect.Lists; | ||
| 48 | 53 | ||
| 49 | /** | 54 | /** |
| 50 | * An implementation of Intent Manager. | 55 | * An implementation of Intent Manager. |
| ... | @@ -67,7 +72,8 @@ public class IntentManager | ... | @@ -67,7 +72,8 @@ public class IntentManager |
| 67 | private final AbstractListenerRegistry<IntentEvent, IntentListener> | 72 | private final AbstractListenerRegistry<IntentEvent, IntentListener> |
| 68 | listenerRegistry = new AbstractListenerRegistry<>(); | 73 | listenerRegistry = new AbstractListenerRegistry<>(); |
| 69 | 74 | ||
| 70 | - private final ExecutorService executor = newSingleThreadExecutor(namedThreads("onos-intents")); | 75 | + private ExecutorService executor; |
| 76 | + private ExecutorService monitorExecutor; | ||
| 71 | 77 | ||
| 72 | private final IntentStoreDelegate delegate = new InternalStoreDelegate(); | 78 | private final IntentStoreDelegate delegate = new InternalStoreDelegate(); |
| 73 | private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate(); | 79 | private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate(); |
| ... | @@ -86,6 +92,8 @@ public class IntentManager | ... | @@ -86,6 +92,8 @@ public class IntentManager |
| 86 | store.setDelegate(delegate); | 92 | store.setDelegate(delegate); |
| 87 | trackerService.setDelegate(topoDelegate); | 93 | trackerService.setDelegate(topoDelegate); |
| 88 | eventDispatcher.addSink(IntentEvent.class, listenerRegistry); | 94 | eventDispatcher.addSink(IntentEvent.class, listenerRegistry); |
| 95 | + executor = newSingleThreadExecutor(namedThreads("onos-intents")); | ||
| 96 | + monitorExecutor = newSingleThreadExecutor(namedThreads("onos-intent-monitor")); | ||
| 89 | log.info("Started"); | 97 | log.info("Started"); |
| 90 | } | 98 | } |
| 91 | 99 | ||
| ... | @@ -94,6 +102,8 @@ public class IntentManager | ... | @@ -94,6 +102,8 @@ public class IntentManager |
| 94 | store.unsetDelegate(delegate); | 102 | store.unsetDelegate(delegate); |
| 95 | trackerService.unsetDelegate(topoDelegate); | 103 | trackerService.unsetDelegate(topoDelegate); |
| 96 | eventDispatcher.removeSink(IntentEvent.class); | 104 | eventDispatcher.removeSink(IntentEvent.class); |
| 105 | + executor.shutdown(); | ||
| 106 | + monitorExecutor.shutdown(); | ||
| 97 | log.info("Stopped"); | 107 | log.info("Stopped"); |
| 98 | } | 108 | } |
| 99 | 109 | ||
| ... | @@ -240,14 +250,23 @@ public class IntentManager | ... | @@ -240,14 +250,23 @@ public class IntentManager |
| 240 | } | 250 | } |
| 241 | } | 251 | } |
| 242 | 252 | ||
| 243 | - // FIXME: To make SDN-IP workable ASAP, only single level compilation is implemented | 253 | + /** |
| 244 | - // TODO: implement compilation traversing tree structure | 254 | + * Compiles an intent recursively. |
| 255 | + * | ||
| 256 | + * @param intent intent | ||
| 257 | + * @return result of compilation | ||
| 258 | + */ | ||
| 245 | private List<InstallableIntent> compileIntent(Intent intent) { | 259 | private List<InstallableIntent> compileIntent(Intent intent) { |
| 260 | + if (intent instanceof InstallableIntent) { | ||
| 261 | + return ImmutableList.of((InstallableIntent) intent); | ||
| 262 | + } | ||
| 263 | + | ||
| 246 | List<InstallableIntent> installable = new ArrayList<>(); | 264 | List<InstallableIntent> installable = new ArrayList<>(); |
| 265 | + // TODO do we need to registerSubclassCompiler? | ||
| 247 | for (Intent compiled : getCompiler(intent).compile(intent)) { | 266 | for (Intent compiled : getCompiler(intent).compile(intent)) { |
| 248 | - InstallableIntent installableIntent = (InstallableIntent) compiled; | 267 | + installable.addAll(compileIntent(compiled)); |
| 249 | - installable.add(installableIntent); | ||
| 250 | } | 268 | } |
| 269 | + | ||
| 251 | return installable; | 270 | return installable; |
| 252 | } | 271 | } |
| 253 | 272 | ||
| ... | @@ -261,6 +280,7 @@ public class IntentManager | ... | @@ -261,6 +280,7 @@ public class IntentManager |
| 261 | // Indicate that the intent is entering the installing phase. | 280 | // Indicate that the intent is entering the installing phase. |
| 262 | store.setState(intent, INSTALLING); | 281 | store.setState(intent, INSTALLING); |
| 263 | 282 | ||
| 283 | + List<Future<CompletedBatchOperation>> installFutures = Lists.newArrayList(); | ||
| 264 | try { | 284 | try { |
| 265 | List<InstallableIntent> installables = store.getInstallableIntents(intent.id()); | 285 | List<InstallableIntent> installables = store.getInstallableIntents(intent.id()); |
| 266 | if (installables != null) { | 286 | if (installables != null) { |
| ... | @@ -268,17 +288,20 @@ public class IntentManager | ... | @@ -268,17 +288,20 @@ public class IntentManager |
| 268 | registerSubclassInstallerIfNeeded(installable); | 288 | registerSubclassInstallerIfNeeded(installable); |
| 269 | trackerService.addTrackedResources(intent.id(), | 289 | trackerService.addTrackedResources(intent.id(), |
| 270 | installable.requiredLinks()); | 290 | installable.requiredLinks()); |
| 271 | - getInstaller(installable).install(installable); | 291 | + Future<CompletedBatchOperation> future = getInstaller(installable).install(installable); |
| 292 | + installFutures.add(future); | ||
| 272 | } | 293 | } |
| 273 | } | 294 | } |
| 274 | - eventDispatcher.post(store.setState(intent, INSTALLED)); | 295 | + // FIXME we have to wait for the installable intents |
| 275 | - | 296 | + //eventDispatcher.post(store.setState(intent, INSTALLED)); |
| 297 | + monitorExecutor.execute(new IntentInstallMonitor(intent, installFutures, INSTALLED)); | ||
| 276 | } catch (Exception e) { | 298 | } catch (Exception e) { |
| 277 | log.warn("Unable to install intent {} due to: {}", intent.id(), e); | 299 | log.warn("Unable to install intent {} due to: {}", intent.id(), e); |
| 278 | - uninstallIntent(intent); | 300 | + uninstallIntent(intent, RECOMPILING); |
| 279 | 301 | ||
| 280 | // If compilation failed, kick off the recompiling phase. | 302 | // If compilation failed, kick off the recompiling phase. |
| 281 | - executeRecompilingPhase(intent); | 303 | + // FIXME |
| 304 | + //executeRecompilingPhase(intent); | ||
| 282 | } | 305 | } |
| 283 | } | 306 | } |
| 284 | 307 | ||
| ... | @@ -327,12 +350,14 @@ public class IntentManager | ... | @@ -327,12 +350,14 @@ public class IntentManager |
| 327 | private void executeWithdrawingPhase(Intent intent) { | 350 | private void executeWithdrawingPhase(Intent intent) { |
| 328 | // Indicate that the intent is being withdrawn. | 351 | // Indicate that the intent is being withdrawn. |
| 329 | store.setState(intent, WITHDRAWING); | 352 | store.setState(intent, WITHDRAWING); |
| 330 | - uninstallIntent(intent); | 353 | + uninstallIntent(intent, WITHDRAWN); |
| 331 | 354 | ||
| 332 | // If all went well, disassociate the top-level intent with its | 355 | // If all went well, disassociate the top-level intent with its |
| 333 | // installable derivatives and mark it as withdrawn. | 356 | // installable derivatives and mark it as withdrawn. |
| 334 | - store.removeInstalledIntents(intent.id()); | 357 | + // FIXME need to clean up |
| 335 | - eventDispatcher.post(store.setState(intent, WITHDRAWN)); | 358 | + //store.removeInstalledIntents(intent.id()); |
| 359 | + // FIXME | ||
| 360 | + //eventDispatcher.post(store.setState(intent, WITHDRAWN)); | ||
| 336 | } | 361 | } |
| 337 | 362 | ||
| 338 | /** | 363 | /** |
| ... | @@ -340,14 +365,17 @@ public class IntentManager | ... | @@ -340,14 +365,17 @@ public class IntentManager |
| 340 | * | 365 | * |
| 341 | * @param intent intent to be uninstalled | 366 | * @param intent intent to be uninstalled |
| 342 | */ | 367 | */ |
| 343 | - private void uninstallIntent(Intent intent) { | 368 | + private void uninstallIntent(Intent intent, IntentState nextState) { |
| 369 | + List<Future<CompletedBatchOperation>> uninstallFutures = Lists.newArrayList(); | ||
| 344 | try { | 370 | try { |
| 345 | List<InstallableIntent> installables = store.getInstallableIntents(intent.id()); | 371 | List<InstallableIntent> installables = store.getInstallableIntents(intent.id()); |
| 346 | if (installables != null) { | 372 | if (installables != null) { |
| 347 | for (InstallableIntent installable : installables) { | 373 | for (InstallableIntent installable : installables) { |
| 348 | - getInstaller(installable).uninstall(installable); | 374 | + Future<CompletedBatchOperation> future = getInstaller(installable).uninstall(installable); |
| 375 | + uninstallFutures.add(future); | ||
| 349 | } | 376 | } |
| 350 | } | 377 | } |
| 378 | + monitorExecutor.execute(new IntentInstallMonitor(intent, uninstallFutures, nextState)); | ||
| 351 | } catch (IntentException e) { | 379 | } catch (IntentException e) { |
| 352 | log.warn("Unable to uninstall intent {} due to: {}", intent.id(), e); | 380 | log.warn("Unable to uninstall intent {} due to: {}", intent.id(), e); |
| 353 | } | 381 | } |
| ... | @@ -422,9 +450,10 @@ public class IntentManager | ... | @@ -422,9 +450,10 @@ public class IntentManager |
| 422 | // Attempt recompilation of the specified intents first. | 450 | // Attempt recompilation of the specified intents first. |
| 423 | for (IntentId intentId : intentIds) { | 451 | for (IntentId intentId : intentIds) { |
| 424 | Intent intent = getIntent(intentId); | 452 | Intent intent = getIntent(intentId); |
| 425 | - uninstallIntent(intent); | 453 | + uninstallIntent(intent, RECOMPILING); |
| 426 | 454 | ||
| 427 | - executeRecompilingPhase(intent); | 455 | + //FIXME |
| 456 | + //executeRecompilingPhase(intent); | ||
| 428 | } | 457 | } |
| 429 | 458 | ||
| 430 | if (compileAllFailed) { | 459 | if (compileAllFailed) { |
| ... | @@ -460,4 +489,44 @@ public class IntentManager | ... | @@ -460,4 +489,44 @@ public class IntentManager |
| 460 | } | 489 | } |
| 461 | } | 490 | } |
| 462 | 491 | ||
| 492 | + private class IntentInstallMonitor implements Runnable { | ||
| 493 | + | ||
| 494 | + private final Intent intent; | ||
| 495 | + private final List<Future<CompletedBatchOperation>> futures; | ||
| 496 | + private final IntentState nextState; | ||
| 497 | + | ||
| 498 | + public IntentInstallMonitor(Intent intent, | ||
| 499 | + List<Future<CompletedBatchOperation>> futures, IntentState nextState) { | ||
| 500 | + this.intent = intent; | ||
| 501 | + this.futures = futures; | ||
| 502 | + this.nextState = nextState; | ||
| 503 | + } | ||
| 504 | + | ||
| 505 | + private void updateIntent(Intent intent) { | ||
| 506 | + if (nextState == RECOMPILING) { | ||
| 507 | + executor.execute(new IntentTask(nextState, intent)); | ||
| 508 | + } else if (nextState == INSTALLED || nextState == WITHDRAWN) { | ||
| 509 | + eventDispatcher.post(store.setState(intent, nextState)); | ||
| 510 | + } else { | ||
| 511 | + log.warn("Invalid next intent state {} for intent {}", nextState, intent); | ||
| 512 | + } | ||
| 513 | + } | ||
| 514 | + | ||
| 515 | + @Override | ||
| 516 | + public void run() { | ||
| 517 | + for (Iterator<Future<CompletedBatchOperation>> i = futures.iterator(); i.hasNext();) { | ||
| 518 | + Future<CompletedBatchOperation> future = i.next(); | ||
| 519 | + if (future.isDone()) { | ||
| 520 | + // TODO: we may want to get the future here | ||
| 521 | + i.remove(); | ||
| 522 | + } | ||
| 523 | + } | ||
| 524 | + if (futures.isEmpty()) { | ||
| 525 | + updateIntent(intent); | ||
| 526 | + } else { | ||
| 527 | + // resubmit ourselves if we are not done yet | ||
| 528 | + monitorExecutor.submit(this); | ||
| 529 | + } | ||
| 530 | + } | ||
| 531 | + } | ||
| 463 | } | 532 | } | ... | ... |
| ... | @@ -5,7 +5,7 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -5,7 +5,7 @@ import static org.slf4j.LoggerFactory.getLogger; |
| 5 | 5 | ||
| 6 | import java.util.Iterator; | 6 | import java.util.Iterator; |
| 7 | import java.util.List; | 7 | import java.util.List; |
| 8 | -import java.util.concurrent.ExecutionException; | 8 | +import java.util.concurrent.Future; |
| 9 | 9 | ||
| 10 | import org.apache.felix.scr.annotations.Activate; | 10 | import org.apache.felix.scr.annotations.Activate; |
| 11 | import org.apache.felix.scr.annotations.Component; | 11 | import org.apache.felix.scr.annotations.Component; |
| ... | @@ -15,6 +15,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -15,6 +15,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 15 | import org.onlab.onos.ApplicationId; | 15 | import org.onlab.onos.ApplicationId; |
| 16 | import org.onlab.onos.net.ConnectPoint; | 16 | import org.onlab.onos.net.ConnectPoint; |
| 17 | import org.onlab.onos.net.Link; | 17 | import org.onlab.onos.net.Link; |
| 18 | +import org.onlab.onos.net.flow.CompletedBatchOperation; | ||
| 18 | import org.onlab.onos.net.flow.DefaultFlowRule; | 19 | import org.onlab.onos.net.flow.DefaultFlowRule; |
| 19 | import org.onlab.onos.net.flow.DefaultTrafficSelector; | 20 | import org.onlab.onos.net.flow.DefaultTrafficSelector; |
| 20 | import org.onlab.onos.net.flow.FlowRule; | 21 | import org.onlab.onos.net.flow.FlowRule; |
| ... | @@ -57,8 +58,26 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { | ... | @@ -57,8 +58,26 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { |
| 57 | intentManager.unregisterInstaller(PathIntent.class); | 58 | intentManager.unregisterInstaller(PathIntent.class); |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 61 | + /** | ||
| 62 | + * Apply a list of FlowRules. | ||
| 63 | + * | ||
| 64 | + * @param rules rules to apply | ||
| 65 | + */ | ||
| 66 | + private Future<CompletedBatchOperation> applyBatch(List<FlowRuleBatchEntry> rules) { | ||
| 67 | + FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules); | ||
| 68 | + Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch); | ||
| 69 | + return future; | ||
| 70 | +// try { | ||
| 71 | +// //FIXME don't do this here | ||
| 72 | +// future.get(); | ||
| 73 | +// } catch (InterruptedException | ExecutionException e) { | ||
| 74 | +// // TODO Auto-generated catch block | ||
| 75 | +// e.printStackTrace(); | ||
| 76 | +// } | ||
| 77 | + } | ||
| 78 | + | ||
| 60 | @Override | 79 | @Override |
| 61 | - public void install(PathIntent intent) { | 80 | + public Future<CompletedBatchOperation> install(PathIntent intent) { |
| 62 | TrafficSelector.Builder builder = | 81 | TrafficSelector.Builder builder = |
| 63 | DefaultTrafficSelector.builder(intent.selector()); | 82 | DefaultTrafficSelector.builder(intent.selector()); |
| 64 | Iterator<Link> links = intent.path().links().iterator(); | 83 | Iterator<Link> links = intent.path().links().iterator(); |
| ... | @@ -74,20 +93,14 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { | ... | @@ -74,20 +93,14 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { |
| 74 | builder.build(), treatment, | 93 | builder.build(), treatment, |
| 75 | 123, appId, 600); | 94 | 123, appId, 600); |
| 76 | rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule)); | 95 | rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule)); |
| 77 | - //flowRuleService.applyFlowRules(rule); | ||
| 78 | prev = link.dst(); | 96 | prev = link.dst(); |
| 79 | } | 97 | } |
| 80 | - FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules); | 98 | + |
| 81 | - try { | 99 | + return applyBatch(rules); |
| 82 | - flowRuleService.applyBatch(batch).get(); | ||
| 83 | - } catch (InterruptedException | ExecutionException e) { | ||
| 84 | - // TODO Auto-generated catch block | ||
| 85 | - e.printStackTrace(); | ||
| 86 | - } | ||
| 87 | } | 100 | } |
| 88 | 101 | ||
| 89 | @Override | 102 | @Override |
| 90 | - public void uninstall(PathIntent intent) { | 103 | + public Future<CompletedBatchOperation> uninstall(PathIntent intent) { |
| 91 | TrafficSelector.Builder builder = | 104 | TrafficSelector.Builder builder = |
| 92 | DefaultTrafficSelector.builder(intent.selector()); | 105 | DefaultTrafficSelector.builder(intent.selector()); |
| 93 | Iterator<Link> links = intent.path().links().iterator(); | 106 | Iterator<Link> links = intent.path().links().iterator(); |
| ... | @@ -103,15 +116,131 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { | ... | @@ -103,15 +116,131 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { |
| 103 | builder.build(), treatment, | 116 | builder.build(), treatment, |
| 104 | 123, appId, 600); | 117 | 123, appId, 600); |
| 105 | rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule)); | 118 | rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule)); |
| 106 | - //flowRuleService.removeFlowRules(rule); | ||
| 107 | prev = link.dst(); | 119 | prev = link.dst(); |
| 108 | } | 120 | } |
| 109 | - FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules); | 121 | + return applyBatch(rules); |
| 110 | - try { | 122 | + } |
| 111 | - flowRuleService.applyBatch(batch).get(); | 123 | + |
| 112 | - } catch (InterruptedException | ExecutionException e) { | 124 | + // TODO refactor below this line... ---------------------------- |
| 113 | - // TODO Auto-generated catch block | 125 | + |
| 114 | - e.printStackTrace(); | 126 | + /** |
| 127 | + * Generates the series of MatchActionOperations from the | ||
| 128 | + * {@link FlowBatchOperation}. | ||
| 129 | + * <p> | ||
| 130 | + * FIXME: Currently supporting PacketPathFlow and SingleDstTreeFlow only. | ||
| 131 | + * <p> | ||
| 132 | + * FIXME: MatchActionOperations should have dependency field to the other | ||
| 133 | + * match action operations, and this method should use this. | ||
| 134 | + * | ||
| 135 | + * @param op the {@link FlowBatchOperation} object | ||
| 136 | + * @return the list of {@link MatchActionOperations} objects | ||
| 137 | + */ | ||
| 138 | + /* | ||
| 139 | + private List<MatchActionOperations> | ||
| 140 | + generateMatchActionOperationsList(FlowBatchOperation op) { | ||
| 141 | + | ||
| 142 | + // MatchAction operations at head (ingress) switches. | ||
| 143 | + MatchActionOperations headOps = matchActionService.createOperationsList(); | ||
| 144 | + | ||
| 145 | + // MatchAction operations at rest of the switches. | ||
| 146 | + MatchActionOperations tailOps = matchActionService.createOperationsList(); | ||
| 147 | + | ||
| 148 | + MatchActionOperations removeOps = matchActionService.createOperationsList(); | ||
| 149 | + | ||
| 150 | + for (BatchOperationEntry<Operator, ?> e : op.getOperations()) { | ||
| 151 | + | ||
| 152 | + if (e.getOperator() == FlowBatchOperation.Operator.ADD) { | ||
| 153 | + generateInstallMatchActionOperations(e, tailOps, headOps); | ||
| 154 | + } else if (e.getOperator() == FlowBatchOperation.Operator.REMOVE) { | ||
| 155 | + generateRemoveMatchActionOperations(e, removeOps); | ||
| 156 | + } else { | ||
| 157 | + throw new UnsupportedOperationException( | ||
| 158 | + "FlowManager supports ADD and REMOVE operations only."); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + return Arrays.asList(tailOps, headOps, removeOps); | ||
| 164 | + } | ||
| 165 | + */ | ||
| 166 | + | ||
| 167 | + /** | ||
| 168 | + * Generates MatchActionOperations for an INSTALL FlowBatchOperation. | ||
| 169 | + * <p/> | ||
| 170 | + * FIXME: Currently only supports flows that generate exactly two match | ||
| 171 | + * action operation sets. | ||
| 172 | + * | ||
| 173 | + * @param e Flow BatchOperationEntry | ||
| 174 | + * @param tailOps MatchActionOperation set that the tail | ||
| 175 | + * MatchActionOperations will be placed in | ||
| 176 | + * @param headOps MatchActionOperation set that the head | ||
| 177 | + * MatchActionOperations will be placed in | ||
| 178 | + */ | ||
| 179 | + /* | ||
| 180 | + private void generateInstallMatchActionOperations( | ||
| 181 | + BatchOperationEntry<Operator, ?> e, | ||
| 182 | + MatchActionOperations tailOps, | ||
| 183 | + MatchActionOperations headOps) { | ||
| 184 | + | ||
| 185 | + if (!(e.getTarget() instanceof Flow)) { | ||
| 186 | + throw new IllegalStateException( | ||
| 187 | + "The target is not Flow object: " + e.getTarget()); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + // Compile flows to match-actions | ||
| 191 | + Flow flow = (Flow) e.getTarget(); | ||
| 192 | + List<MatchActionOperations> maOps = flow.compile( | ||
| 193 | + e.getOperator(), matchActionService); | ||
| 194 | + verifyNotNull(maOps, "Could not compile the flow: " + flow); | ||
| 195 | + verify(maOps.size() == 2, | ||
| 196 | + "The flow generates unspported match-action operations."); | ||
| 197 | + | ||
| 198 | + // Map FlowId to MatchActionIds | ||
| 199 | + for (MatchActionOperations maOp : maOps) { | ||
| 200 | + for (MatchActionOperationEntry entry : maOp.getOperations()) { | ||
| 201 | + flowMatchActionsMap.put( | ||
| 202 | + KryoFactory.serialize(flow.getId()), | ||
| 203 | + KryoFactory.serialize(entry.getTarget())); | ||
| 204 | + } | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + // Merge match-action operations | ||
| 208 | + for (MatchActionOperationEntry mae : maOps.get(0).getOperations()) { | ||
| 209 | + verify(mae.getOperator() == MatchActionOperations.Operator.INSTALL); | ||
| 210 | + tailOps.addOperation(mae); | ||
| 211 | + } | ||
| 212 | + for (MatchActionOperationEntry mae : maOps.get(1).getOperations()) { | ||
| 213 | + verify(mae.getOperator() == MatchActionOperations.Operator.INSTALL); | ||
| 214 | + headOps.addOperation(mae); | ||
| 215 | + } | ||
| 216 | + } | ||
| 217 | + */ | ||
| 218 | + /** | ||
| 219 | + * Generates MatchActionOperations for a REMOVE FlowBatchOperation. | ||
| 220 | + * | ||
| 221 | + * @param e Flow BatchOperationEntry | ||
| 222 | + * @param removeOps MatchActionOperation set that the remove | ||
| 223 | + * MatchActionOperations will be placed in | ||
| 224 | + */ | ||
| 225 | + /* | ||
| 226 | + private void generateRemoveMatchActionOperations( | ||
| 227 | + BatchOperationEntry<Operator, ?> e, | ||
| 228 | + MatchActionOperations removeOps) { | ||
| 229 | + | ||
| 230 | + if (!(e.getTarget() instanceof FlowId)) { | ||
| 231 | + throw new IllegalStateException( | ||
| 232 | + "The target is not a FlowId object: " + e.getTarget()); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + // Compile flows to match-actions | ||
| 236 | + FlowId flowId = (FlowId) e.getTarget(); | ||
| 237 | + | ||
| 238 | + for (byte[] matchActionIdBytes : | ||
| 239 | + flowMatchActionsMap.remove(KryoFactory.serialize(flowId))) { | ||
| 240 | + MatchActionId matchActionId = KryoFactory.deserialize(matchActionIdBytes); | ||
| 241 | + removeOps.addOperation(new MatchActionOperationEntry( | ||
| 242 | + MatchActionOperations.Operator.REMOVE, matchActionId)); | ||
| 115 | } | 243 | } |
| 116 | } | 244 | } |
| 245 | + */ | ||
| 117 | } | 246 | } | ... | ... |
-
Please register or login to post a comment