Brian O'Connor
Committed by Gerrit Code Review

Implementation of new Flow Subsystem:

The subsystem no longer returns futures for tracking completion of work.
Notifications are explicitely returned via a call back mechanism. Also, the
subsystem is now asynchronous.

Change-Id: I1a4cef931c24820f9ae9ed9a5398f163f05dfbc9

more flowservice improvements

Change-Id: I5c9c1b6be4b2ebfa523b64f6f52e7634b7d3e05f

more flowservice impl

Change-Id: I05f6774460effb53ced8c36844bcda2f8f6c096f

Manager to store functional (at least i believe it)

Change-Id: I09b04989bd1004c98fe0bafed4c76714b9155d53

flow subsystem functional: need to fix unit tests

Change-Id: I1667f25b91320f625a03e5e1d5e92823184d9de0

flow subsystem functional

Change-Id: I429b3335c16d4fc16f5d55f233dd37c4d1d6111d

finished refactor of flow subsystem

Change-Id: I1899abc6ff6a974a2018d936cc555049c70a6804

fix for null flow provider to use new api

Change-Id: If2fd9bd5baf74d9c61c5c8085cef8bc2d204cbdc
Showing 34 changed files with 648 additions and 228 deletions
...@@ -19,29 +19,30 @@ package org.onosproject.cli.net; ...@@ -19,29 +19,30 @@ package org.onosproject.cli.net;
19 import com.fasterxml.jackson.databind.ObjectMapper; 19 import com.fasterxml.jackson.databind.ObjectMapper;
20 import com.fasterxml.jackson.databind.node.ArrayNode; 20 import com.fasterxml.jackson.databind.node.ArrayNode;
21 import com.fasterxml.jackson.databind.node.ObjectNode; 21 import com.fasterxml.jackson.databind.node.ObjectNode;
22 +import com.google.common.base.Stopwatch;
22 import com.google.common.collect.Lists; 23 import com.google.common.collect.Lists;
23 -import com.google.common.collect.Sets; 24 +import org.apache.commons.lang.math.RandomUtils;
24 import org.apache.karaf.shell.commands.Argument; 25 import org.apache.karaf.shell.commands.Argument;
25 import org.apache.karaf.shell.commands.Command; 26 import org.apache.karaf.shell.commands.Command;
27 +import org.onlab.packet.MacAddress;
26 import org.onosproject.cli.AbstractShellCommand; 28 import org.onosproject.cli.AbstractShellCommand;
29 +import org.onosproject.core.ApplicationId;
30 +import org.onosproject.core.CoreService;
27 import org.onosproject.net.Device; 31 import org.onosproject.net.Device;
28 import org.onosproject.net.PortNumber; 32 import org.onosproject.net.PortNumber;
29 import org.onosproject.net.device.DeviceService; 33 import org.onosproject.net.device.DeviceService;
30 -import org.onosproject.net.flow.CompletedBatchOperation;
31 import org.onosproject.net.flow.DefaultFlowRule; 34 import org.onosproject.net.flow.DefaultFlowRule;
32 import org.onosproject.net.flow.DefaultTrafficSelector; 35 import org.onosproject.net.flow.DefaultTrafficSelector;
33 import org.onosproject.net.flow.DefaultTrafficTreatment; 36 import org.onosproject.net.flow.DefaultTrafficTreatment;
34 -import org.onosproject.net.flow.FlowRuleBatchEntry; 37 +import org.onosproject.net.flow.FlowRuleOperations;
35 -import org.onosproject.net.flow.FlowRuleBatchOperation; 38 +import org.onosproject.net.flow.FlowRuleOperationsContext;
36 import org.onosproject.net.flow.FlowRuleService; 39 import org.onosproject.net.flow.FlowRuleService;
37 import org.onosproject.net.flow.TrafficSelector; 40 import org.onosproject.net.flow.TrafficSelector;
38 import org.onosproject.net.flow.TrafficTreatment; 41 import org.onosproject.net.flow.TrafficTreatment;
39 -import org.onlab.packet.MacAddress;
40 42
41 import java.util.ArrayList; 43 import java.util.ArrayList;
42 -import java.util.Set; 44 +import java.util.concurrent.CountDownLatch;
43 -import java.util.concurrent.ExecutionException; 45 +import java.util.concurrent.TimeUnit;
44 -import java.util.concurrent.Future;
45 46
46 /** 47 /**
47 * Installs many many flows. 48 * Installs many many flows.
...@@ -50,6 +51,8 @@ import java.util.concurrent.Future; ...@@ -50,6 +51,8 @@ import java.util.concurrent.Future;
50 description = "Installs a number of test flow rules - for testing only") 51 description = "Installs a number of test flow rules - for testing only")
51 public class AddFlowsCommand extends AbstractShellCommand { 52 public class AddFlowsCommand extends AbstractShellCommand {
52 53
54 + private CountDownLatch latch;
55 +
53 @Argument(index = 0, name = "flowPerDevice", description = "Number of flows to add per device", 56 @Argument(index = 0, name = "flowPerDevice", description = "Number of flows to add per device",
54 required = true, multiValued = false) 57 required = true, multiValued = false)
55 String flows = null; 58 String flows = null;
...@@ -63,6 +66,9 @@ public class AddFlowsCommand extends AbstractShellCommand { ...@@ -63,6 +66,9 @@ public class AddFlowsCommand extends AbstractShellCommand {
63 66
64 FlowRuleService flowService = get(FlowRuleService.class); 67 FlowRuleService flowService = get(FlowRuleService.class);
65 DeviceService deviceService = get(DeviceService.class); 68 DeviceService deviceService = get(DeviceService.class);
69 + CoreService coreService = get(CoreService.class);
70 +
71 + ApplicationId appId = coreService.registerApplication("onos.test.flow.installer");
66 72
67 int flowsPerDevice = Integer.parseInt(flows); 73 int flowsPerDevice = Integer.parseInt(flows);
68 int num = Integer.parseInt(numOfRuns); 74 int num = Integer.parseInt(numOfRuns);
...@@ -70,49 +76,73 @@ public class AddFlowsCommand extends AbstractShellCommand { ...@@ -70,49 +76,73 @@ public class AddFlowsCommand extends AbstractShellCommand {
70 ArrayList<Long> results = Lists.newArrayList(); 76 ArrayList<Long> results = Lists.newArrayList();
71 Iterable<Device> devices = deviceService.getDevices(); 77 Iterable<Device> devices = deviceService.getDevices();
72 TrafficTreatment treatment = DefaultTrafficTreatment.builder() 78 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
73 - .setOutput(PortNumber.portNumber(1)).build(); 79 + .setOutput(PortNumber.portNumber(RandomUtils.nextInt())).build();
74 TrafficSelector.Builder sbuilder; 80 TrafficSelector.Builder sbuilder;
75 - Set<FlowRuleBatchEntry> rules = Sets.newHashSet(); 81 + FlowRuleOperations.Builder rules = FlowRuleOperations.builder();
76 - Set<FlowRuleBatchEntry> remove = Sets.newHashSet(); 82 + FlowRuleOperations.Builder remove = FlowRuleOperations.builder();
83 +
77 for (Device d : devices) { 84 for (Device d : devices) {
78 for (int i = 0; i < flowsPerDevice; i++) { 85 for (int i = 0; i < flowsPerDevice; i++) {
79 sbuilder = DefaultTrafficSelector.builder(); 86 sbuilder = DefaultTrafficSelector.builder();
80 - sbuilder.matchEthSrc(MacAddress.valueOf(i)) 87 +
81 - .matchEthDst(MacAddress.valueOf(Integer.MAX_VALUE - i)); 88 + sbuilder.matchEthSrc(MacAddress.valueOf(RandomUtils.nextInt() * i))
82 - rules.add(new FlowRuleBatchEntry(FlowRuleBatchEntry.FlowRuleOperation.ADD, 89 + .matchEthDst(MacAddress.valueOf((Integer.MAX_VALUE - i) * RandomUtils.nextInt()));
83 - new DefaultFlowRule(d.id(), sbuilder.build(), treatment, 90 +
84 - 100, (long) 0, 10, false))); 91 +
85 - remove.add(new FlowRuleBatchEntry(FlowRuleBatchEntry.FlowRuleOperation.REMOVE, 92 + int randomPriority = RandomUtils.nextInt();
86 - new DefaultFlowRule(d.id(), sbuilder.build(), treatment, 93 + rules.add(new DefaultFlowRule(d.id(), sbuilder.build(), treatment,
87 - 100, (long) 0, 10, false))); 94 + randomPriority, appId, 10, false));
95 + remove.remove(new DefaultFlowRule(d.id(), sbuilder.build(), treatment,
96 + randomPriority, appId, 10, false));
88 97
89 } 98 }
90 } 99 }
91 - boolean isSuccess = true; 100 +
92 for (int i = 0; i < num; i++) { 101 for (int i = 0; i < num; i++) {
93 - long startTime = System.currentTimeMillis(); 102 +
94 - Future<CompletedBatchOperation> op = flowService.applyBatch( 103 + latch = new CountDownLatch(2);
95 - new FlowRuleBatchOperation(rules)); 104 + flowService.apply(rules.build(new FlowRuleOperationsContext() {
105 +
106 + private final Stopwatch timer = Stopwatch.createStarted();
107 +
108 + @Override
109 + public void onSuccess(FlowRuleOperations ops) {
110 +
111 + timer.stop();
112 + results.add(timer.elapsed(TimeUnit.MILLISECONDS));
113 + if (results.size() == num) {
114 + if (outputJson()) {
115 + print("%s", json(new ObjectMapper(), true, results));
116 + } else {
117 + printTime(true, results);
118 + }
119 + }
120 + latch.countDown();
121 + }
122 + }));
123 +
124 +
125 + flowService.apply(remove.build(new FlowRuleOperationsContext() {
126 + @Override
127 + public void onSuccess(FlowRuleOperations ops) {
128 + latch.countDown();
129 + }
130 + }));
96 try { 131 try {
97 - isSuccess &= op.get().isSuccess(); 132 + latch.await();
98 - } catch (InterruptedException | ExecutionException e) { 133 + } catch (InterruptedException e) {
99 e.printStackTrace(); 134 e.printStackTrace();
100 } 135 }
101 - long endTime = System.currentTimeMillis(); 136 +
102 - results.add(endTime - startTime);
103 - flowService.applyBatch(
104 - new FlowRuleBatchOperation(remove));
105 - }
106 - if (outputJson()) {
107 - print("%s", json(new ObjectMapper(), isSuccess, results));
108 - } else {
109 - printTime(isSuccess, results);
110 } 137 }
111 138
112 139
113 140
141 +
114 } 142 }
115 143
144 +
145 +
116 private Object json(ObjectMapper mapper, boolean isSuccess, ArrayList<Long> elapsed) { 146 private Object json(ObjectMapper mapper, boolean isSuccess, ArrayList<Long> elapsed) {
117 ObjectNode result = mapper.createObjectNode(); 147 ObjectNode result = mapper.createObjectNode();
118 result.put("Success", isSuccess); 148 result.put("Success", isSuccess);
......
...@@ -21,6 +21,7 @@ import java.util.Set; ...@@ -21,6 +21,7 @@ import java.util.Set;
21 21
22 import com.google.common.base.MoreObjects; 22 import com.google.common.base.MoreObjects;
23 import com.google.common.collect.ImmutableSet; 23 import com.google.common.collect.ImmutableSet;
24 +import org.onosproject.net.DeviceId;
24 25
25 /** 26 /**
26 * Representation of a completed flow rule batch operation. 27 * Representation of a completed flow rule batch operation.
...@@ -30,19 +31,22 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { ...@@ -30,19 +31,22 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
30 private final boolean success; 31 private final boolean success;
31 private final Set<FlowRule> failures; 32 private final Set<FlowRule> failures;
32 private final Set<Long> failedIds; 33 private final Set<Long> failedIds;
34 + private final DeviceId deviceId;
33 35
34 /** 36 /**
35 * Creates a new batch completion result. 37 * Creates a new batch completion result.
36 * 38 *
37 - * @param success indicates whether the completion is successful. 39 + * @param success indicates whether the completion is successful
38 * @param failures set of any failures encountered 40 * @param failures set of any failures encountered
39 * @param failedIds (optional) set of failed operation ids 41 * @param failedIds (optional) set of failed operation ids
42 + * @param deviceId the device this operation completed for
40 */ 43 */
41 public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures, 44 public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures,
42 - Set<Long> failedIds) { 45 + Set<Long> failedIds, DeviceId deviceId) {
43 this.success = success; 46 this.success = success;
44 this.failures = ImmutableSet.copyOf(failures); 47 this.failures = ImmutableSet.copyOf(failures);
45 this.failedIds = ImmutableSet.copyOf(failedIds); 48 this.failedIds = ImmutableSet.copyOf(failedIds);
49 + this.deviceId = deviceId;
46 } 50 }
47 51
48 /** 52 /**
...@@ -51,10 +55,12 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { ...@@ -51,10 +55,12 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
51 * @param success indicates whether the completion is successful. 55 * @param success indicates whether the completion is successful.
52 * @param failures set of any failures encountered 56 * @param failures set of any failures encountered
53 */ 57 */
54 - public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures) { 58 + public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures,
59 + DeviceId deviceId) {
55 this.success = success; 60 this.success = success;
56 this.failures = ImmutableSet.copyOf(failures); 61 this.failures = ImmutableSet.copyOf(failures);
57 this.failedIds = Collections.emptySet(); 62 this.failedIds = Collections.emptySet();
63 + this.deviceId = deviceId;
58 } 64 }
59 65
60 66
...@@ -73,12 +79,17 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { ...@@ -73,12 +79,17 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
73 return failedIds; 79 return failedIds;
74 } 80 }
75 81
82 + public DeviceId deviceId() {
83 + return this.deviceId;
84 + }
85 +
76 @Override 86 @Override
77 public String toString() { 87 public String toString() {
78 return MoreObjects.toStringHelper(getClass()) 88 return MoreObjects.toStringHelper(getClass())
79 .add("success?", success) 89 .add("success?", success)
80 .add("failedItems", failures) 90 .add("failedItems", failures)
81 .add("failedIds", failedIds) 91 .add("failedIds", failedIds)
92 + .add("deviceId", deviceId)
82 .toString(); 93 .toString();
83 } 94 }
84 } 95 }
......
...@@ -16,12 +16,14 @@ ...@@ -16,12 +16,14 @@
16 package org.onosproject.net.flow; 16 package org.onosproject.net.flow;
17 17
18 import org.onosproject.event.AbstractEvent; 18 import org.onosproject.event.AbstractEvent;
19 +import org.onosproject.net.DeviceId;
19 20
20 /** 21 /**
21 * Describes flow rule batch event. 22 * Describes flow rule batch event.
22 */ 23 */
23 public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.Type, FlowRuleBatchRequest> { 24 public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.Type, FlowRuleBatchRequest> {
24 25
26 +
25 /** 27 /**
26 * Type of flow rule events. 28 * Type of flow rule events.
27 */ 29 */
...@@ -42,14 +44,17 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T ...@@ -42,14 +44,17 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T
42 } 44 }
43 45
44 private final CompletedBatchOperation result; 46 private final CompletedBatchOperation result;
47 + private final DeviceId deviceId;
45 48
46 /** 49 /**
47 * Constructs a new FlowRuleBatchEvent. 50 * Constructs a new FlowRuleBatchEvent.
48 - * @param request batch operation request. 51 + *
52 + * @param request batch operation request
53 + * @param deviceId the device this batch will be processed on
49 * @return event. 54 * @return event.
50 */ 55 */
51 - public static FlowRuleBatchEvent requested(FlowRuleBatchRequest request) { 56 + public static FlowRuleBatchEvent requested(FlowRuleBatchRequest request, DeviceId deviceId) {
52 - FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_REQUESTED, request, null); 57 + FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_REQUESTED, request, deviceId);
53 return event; 58 return event;
54 } 59 }
55 60
...@@ -73,13 +78,36 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T ...@@ -73,13 +78,36 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T
73 } 78 }
74 79
75 /** 80 /**
81 + * Returns the deviceId for this batch.
82 + * @return device id
83 + */
84 + public DeviceId deviceId() {
85 + return deviceId;
86 + }
87 +
88 + /**
76 * Creates an event of a given type and for the specified flow rule batch. 89 * Creates an event of a given type and for the specified flow rule batch.
77 * 90 *
78 * @param type flow rule batch event type 91 * @param type flow rule batch event type
79 - * @param batch event flow rule batch subject 92 + * @param request event flow rule batch subject
93 + * @param result the result of the batch operation
80 */ 94 */
81 private FlowRuleBatchEvent(Type type, FlowRuleBatchRequest request, CompletedBatchOperation result) { 95 private FlowRuleBatchEvent(Type type, FlowRuleBatchRequest request, CompletedBatchOperation result) {
82 super(type, request); 96 super(type, request);
83 this.result = result; 97 this.result = result;
98 + this.deviceId = result.deviceId();
99 + }
100 +
101 + /**
102 + * Creates an event of a given type and for the specified flow rule batch.
103 + *
104 + * @param type flow rule batch event type
105 + * @param request event flow rule batch subject
106 + * @param deviceId the device id for this batch
107 + */
108 + private FlowRuleBatchEvent(Type type, FlowRuleBatchRequest request, DeviceId deviceId) {
109 + super(type, request);
110 + this.result = null;
111 + this.deviceId = deviceId;
84 } 112 }
85 } 113 }
......
...@@ -15,12 +15,37 @@ ...@@ -15,12 +15,37 @@
15 */ 15 */
16 package org.onosproject.net.flow; 16 package org.onosproject.net.flow;
17 17
18 +import org.onosproject.net.DeviceId;
19 +
18 import java.util.Collection; 20 import java.util.Collection;
19 21
22 +/**
23 + * Class used with the flow subsystem to process per device
24 + * batches.
25 + */
20 public class FlowRuleBatchOperation 26 public class FlowRuleBatchOperation
21 extends BatchOperation<FlowRuleBatchEntry> { 27 extends BatchOperation<FlowRuleBatchEntry> {
22 28
23 - public FlowRuleBatchOperation(Collection<FlowRuleBatchEntry> operations) { 29 + /**
30 + * This id is used to cary to id of the original
31 + * FlowOperations and track where this batch operation
32 + * came from. The id is unique cluster wide.
33 + */
34 + private final long id;
35 + private final DeviceId deviceId;
36 +
37 + public FlowRuleBatchOperation(Collection<FlowRuleBatchEntry> operations,
38 + DeviceId deviceId, long flowOperationId) {
24 super(operations); 39 super(operations);
40 + this.id = flowOperationId;
41 + this.deviceId = deviceId;
42 + }
43 +
44 + public DeviceId deviceId() {
45 + return this.deviceId;
46 + }
47 +
48 + public long id() {
49 + return id;
25 } 50 }
26 } 51 }
......
...@@ -15,59 +15,43 @@ ...@@ -15,59 +15,43 @@
15 */ 15 */
16 package org.onosproject.net.flow; 16 package org.onosproject.net.flow;
17 17
18 +import com.google.common.collect.Lists;
19 +import org.onosproject.net.DeviceId;
20 +
18 import java.util.Collections; 21 import java.util.Collections;
19 import java.util.List; 22 import java.util.List;
23 +import java.util.Set;
20 24
21 -import com.google.common.base.Function; 25 +public class FlowRuleBatchRequest {
22 -import com.google.common.collect.FluentIterable;
23 -
24 -
25 26
26 -import com.google.common.collect.Lists; 27 + /**
28 + * This id is used to cary to id of the original
29 + * FlowOperations and track where this batch operation
30 + * came from. The id is unique cluster wide.
31 + */
32 + private final long batchId;
27 33
28 -public class FlowRuleBatchRequest { 34 + private final Set<FlowRuleBatchEntry> ops;
29 35
30 - private final int batchId;
31 - private final List<FlowRuleBatchEntry> toAdd;
32 - private final List<FlowRuleBatchEntry> toRemove;
33 36
34 - public FlowRuleBatchRequest(int batchId, List<FlowRuleBatchEntry> toAdd, 37 + public FlowRuleBatchRequest(long batchId, Set<FlowRuleBatchEntry> ops) {
35 - List<FlowRuleBatchEntry> toRemove) {
36 this.batchId = batchId; 38 this.batchId = batchId;
37 - this.toAdd = Collections.unmodifiableList(toAdd); 39 + this.ops = Collections.unmodifiableSet(ops);
38 - this.toRemove = Collections.unmodifiableList(toRemove);
39 - }
40 40
41 - public List<FlowRule> toAdd() {
42 - return FluentIterable.from(toAdd).transform(
43 - new Function<FlowRuleBatchEntry, FlowRule>() {
44 41
45 - @Override
46 - public FlowRule apply(FlowRuleBatchEntry input) {
47 - return input.target();
48 } 42 }
49 - }).toList();
50 - }
51 -
52 - public List<FlowRule> toRemove() {
53 - return FluentIterable.from(toRemove).transform(
54 - new Function<FlowRuleBatchEntry, FlowRule>() {
55 43
56 - @Override 44 + public Set<FlowRuleBatchEntry> ops() {
57 - public FlowRule apply(FlowRuleBatchEntry input) { 45 + return ops;
58 - return input.target();
59 - }
60 - }).toList();
61 } 46 }
62 47
63 - public FlowRuleBatchOperation asBatchOperation() { 48 + public FlowRuleBatchOperation asBatchOperation(DeviceId deviceId) {
64 List<FlowRuleBatchEntry> entries = Lists.newArrayList(); 49 List<FlowRuleBatchEntry> entries = Lists.newArrayList();
65 - entries.addAll(toAdd); 50 + entries.addAll(ops);
66 - entries.addAll(toRemove); 51 + return new FlowRuleBatchOperation(entries, deviceId, batchId);
67 - return new FlowRuleBatchOperation(entries);
68 } 52 }
69 53
70 - public int batchId() { 54 + public long batchId() {
71 return batchId; 55 return batchId;
72 } 56 }
73 } 57 }
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.flow;
17 +
18 +import com.google.common.base.MoreObjects;
19 +
20 +/**
21 + * Representation of an operation on a flow rule table.
22 + */
23 +public class FlowRuleOperation {
24 +
25 + /**
26 + * Type of flow table operations.
27 + */
28 + public enum Type {
29 + ADD,
30 + MODIFY,
31 + REMOVE
32 + }
33 +
34 + private final FlowRule rule;
35 + private final Type type;
36 +
37 + public FlowRuleOperation(FlowRule rule, Type type) {
38 + this.rule = rule;
39 + this.type = type;
40 + }
41 +
42 + /**
43 + * Returns the type of operation.
44 + *
45 + * @return type
46 + */
47 + public Type type() {
48 + return type;
49 + }
50 +
51 + /**
52 + * Returns the flow rule.
53 + *
54 + * @return flow rule
55 + */
56 + public FlowRule rule() {
57 + return rule;
58 + }
59 +
60 + @Override
61 + public String toString() {
62 + return MoreObjects.toStringHelper(this)
63 + .add("rule", rule)
64 + .add("type", type)
65 + .toString();
66 + }
67 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.flow;
17 +
18 +import com.google.common.base.MoreObjects;
19 +import com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.ImmutableSet;
21 +import com.google.common.collect.Lists;
22 +
23 +import java.util.List;
24 +import java.util.Set;
25 +
26 +import static org.onosproject.net.flow.FlowRuleOperation.Type.*;
27 +
28 +/**
29 + * A batch of flow rule operations that are broken into stages.
30 + * TODO move this up to parent's package
31 + */
32 +public class FlowRuleOperations {
33 +
34 + private final List<Set<FlowRuleOperation>> stages;
35 + private final FlowRuleOperationsContext callback; // TODO consider Optional
36 +
37 + private FlowRuleOperations(List<Set<FlowRuleOperation>> stages,
38 + FlowRuleOperationsContext cb) {
39 + this.stages = stages;
40 + this.callback = cb;
41 + }
42 +
43 + // kryo-constructor
44 + protected FlowRuleOperations() {
45 + this.stages = Lists.newArrayList();
46 + this.callback = null;
47 + }
48 +
49 + /**
50 + * Returns the flow rule operations as sets of stages that should be
51 + * executed sequentially.
52 + *
53 + * @return flow rule stages
54 + */
55 + public List<Set<FlowRuleOperation>> stages() {
56 + return stages;
57 + }
58 +
59 + /**
60 + * Returns the callback for this batch of operations.
61 + *
62 + * @return callback
63 + */
64 + public FlowRuleOperationsContext callback() {
65 + return callback;
66 + }
67 +
68 + /**
69 + * Returns a new builder.
70 + *
71 + * @return new builder
72 + */
73 + public static Builder builder() {
74 + return new Builder();
75 + }
76 +
77 + @Override
78 + public String toString() {
79 + return MoreObjects.toStringHelper(this)
80 + .add("stages", stages)
81 + .toString();
82 + }
83 +
84 + /**
85 + * A builder for constructing flow rule operations.
86 + */
87 + public static final class Builder {
88 +
89 + private final ImmutableList.Builder<Set<FlowRuleOperation>> listBuilder = ImmutableList.builder();
90 + private ImmutableSet.Builder<FlowRuleOperation> currentStage = ImmutableSet.builder();
91 +
92 + // prevent use of the default constructor outside of this file; use the above method
93 + private Builder() {}
94 +
95 + /**
96 + * Appends a flow rule add to the current stage.
97 + *
98 + * @param flowRule flow rule
99 + * @return this
100 + */
101 + public Builder add(FlowRule flowRule) {
102 + currentStage.add(new FlowRuleOperation(flowRule, ADD));
103 + return this;
104 + }
105 +
106 + /**
107 + * Appends a flow rule modify to the current stage.
108 + *
109 + * @param flowRule flow rule
110 + * @return this
111 + */
112 + public Builder modify(FlowRule flowRule) {
113 + currentStage.add(new FlowRuleOperation(flowRule, MODIFY));
114 + return this;
115 + }
116 +
117 + /**
118 + * Appends a flow rule remove to the current stage.
119 + *
120 + * @param flowRule flow rule
121 + * @return this
122 + */
123 + // FIXME this is confusing, consider renaming
124 + public Builder remove(FlowRule flowRule) {
125 + currentStage.add(new FlowRuleOperation(flowRule, REMOVE));
126 + return this;
127 + }
128 +
129 + /**
130 + * Closes the current stage.
131 + */
132 + private void closeStage() {
133 + ImmutableSet<FlowRuleOperation> stage = currentStage.build();
134 + if (!stage.isEmpty()) {
135 + listBuilder.add(stage);
136 + }
137 + }
138 +
139 + /**
140 + * Closes the current stage and starts a new one.
141 + *
142 + * @return this
143 + */
144 + public Builder newStage() {
145 + closeStage();
146 + currentStage = ImmutableSet.builder();
147 + return this;
148 + }
149 +
150 + /**
151 + * Builds the immutable flow rule operations.
152 + *
153 + * @return flow rule operations
154 + */
155 + public FlowRuleOperations build() {
156 + return build(null);
157 + }
158 +
159 + /**
160 + * Builds the immutable flow rule operations.
161 + *
162 + * @param cb the callback to call when this operation completes
163 + * @return flow rule operations
164 + */
165 + public FlowRuleOperations build(FlowRuleOperationsContext cb) {
166 + closeStage();
167 + return new FlowRuleOperations(listBuilder.build(), cb);
168 + }
169 + }
170 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.flow;
17 +
18 +/**
19 + * The context of a flow rule operations that will become the subject of
20 + * the notification.
21 + *
22 + * Implementations of this class must be serializable.
23 + */
24 +public interface FlowRuleOperationsContext {
25 + // TODO we might also want to execute a method on behalf of the app
26 + default void onSuccess(FlowRuleOperations ops){}
27 + default void onError(FlowRuleOperations ops){}
28 +}
...@@ -18,8 +18,6 @@ package org.onosproject.net.flow; ...@@ -18,8 +18,6 @@ package org.onosproject.net.flow;
18 import org.onosproject.core.ApplicationId; 18 import org.onosproject.core.ApplicationId;
19 import org.onosproject.net.provider.Provider; 19 import org.onosproject.net.provider.Provider;
20 20
21 -import java.util.concurrent.Future;
22 -
23 /** 21 /**
24 * Abstraction of a flow rule provider. 22 * Abstraction of a flow rule provider.
25 */ 23 */
...@@ -56,8 +54,7 @@ public interface FlowRuleProvider extends Provider { ...@@ -56,8 +54,7 @@ public interface FlowRuleProvider extends Provider {
56 * Installs a batch of flow rules. Each flowrule is associated to an 54 * Installs a batch of flow rules. Each flowrule is associated to an
57 * operation which results in either addition, removal or modification. 55 * operation which results in either addition, removal or modification.
58 * @param batch a batch of flow rules 56 * @param batch a batch of flow rules
59 - * @return a future indicating the status of this execution
60 */ 57 */
61 - Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch); 58 + void executeBatch(FlowRuleBatchOperation batch);
62 59
63 } 60 }
......
...@@ -40,4 +40,13 @@ public interface FlowRuleProviderService extends ProviderService<FlowRuleProvide ...@@ -40,4 +40,13 @@ public interface FlowRuleProviderService extends ProviderService<FlowRuleProvide
40 */ 40 */
41 void pushFlowMetrics(DeviceId deviceId, Iterable<FlowEntry> flowEntries); 41 void pushFlowMetrics(DeviceId deviceId, Iterable<FlowEntry> flowEntries);
42 42
43 + /**
44 + * Indicates to the core that the requested batch operation has
45 + * been completed.
46 + *
47 + * @param batchId the batch which was processed
48 + * @param operation the resulting outcome of the operation
49 + */
50 + void batchOperationCompleted(long batchId, CompletedBatchOperation operation);
51 +
43 } 52 }
......
...@@ -15,11 +15,11 @@ ...@@ -15,11 +15,11 @@
15 */ 15 */
16 package org.onosproject.net.flow; 16 package org.onosproject.net.flow;
17 17
18 -import java.util.concurrent.Future;
19 -
20 import org.onosproject.core.ApplicationId; 18 import org.onosproject.core.ApplicationId;
21 import org.onosproject.net.DeviceId; 19 import org.onosproject.net.DeviceId;
22 20
21 +import java.util.concurrent.Future;
22 +
23 /** 23 /**
24 * Service for injecting flow rules into the environment and for obtaining 24 * Service for injecting flow rules into the environment and for obtaining
25 * information about flow rules already in the environment. This implements 25 * information about flow rules already in the environment. This implements
...@@ -30,6 +30,11 @@ import org.onosproject.net.DeviceId; ...@@ -30,6 +30,11 @@ import org.onosproject.net.DeviceId;
30 public interface FlowRuleService { 30 public interface FlowRuleService {
31 31
32 /** 32 /**
33 + * The topic used for obtaining globally unique ids.
34 + */
35 + static String FLOW_OP_TOPIC = "flow-ops-ids";
36 +
37 + /**
33 * Returns the number of flow rules in the system. 38 * Returns the number of flow rules in the system.
34 * 39 *
35 * @return flow rule count 40 * @return flow rule count
...@@ -96,11 +101,20 @@ public interface FlowRuleService { ...@@ -96,11 +101,20 @@ public interface FlowRuleService {
96 * Applies a batch operation of FlowRules. 101 * Applies a batch operation of FlowRules.
97 * 102 *
98 * @param batch batch operation to apply 103 * @param batch batch operation to apply
99 - * @return future indicating the state of the batch operation 104 + * @return future indicating the state of the batch operation, due to the
105 + * deprecation of this api the future will immediately return
100 */ 106 */
107 + @Deprecated
101 Future<CompletedBatchOperation> applyBatch(FlowRuleBatchOperation batch); 108 Future<CompletedBatchOperation> applyBatch(FlowRuleBatchOperation batch);
102 109
103 /** 110 /**
111 + * Applies a batch operation of FlowRules.
112 + *
113 + * @param ops batch operation to apply
114 + */
115 + void apply(FlowRuleOperations ops);
116 +
117 + /**
104 * Adds the specified flow rule listener. 118 * Adds the specified flow rule listener.
105 * 119 *
106 * @param listener flow rule listener 120 * @param listener flow rule listener
......
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
15 */ 15 */
16 package org.onosproject.net.flow; 16 package org.onosproject.net.flow;
17 17
18 -import java.util.concurrent.Future;
19 -
20 import org.onosproject.net.DeviceId; 18 import org.onosproject.net.DeviceId;
21 import org.onosproject.store.Store; 19 import org.onosproject.store.Store;
22 20
...@@ -54,6 +52,7 @@ public interface FlowRuleStore extends Store<FlowRuleBatchEvent, FlowRuleStoreDe ...@@ -54,6 +52,7 @@ public interface FlowRuleStore extends Store<FlowRuleBatchEvent, FlowRuleStoreDe
54 * 52 *
55 * @param rule the flow rule to add 53 * @param rule the flow rule to add
56 */ 54 */
55 + @Deprecated
57 void storeFlowRule(FlowRule rule); 56 void storeFlowRule(FlowRule rule);
58 57
59 /** 58 /**
...@@ -61,10 +60,9 @@ public interface FlowRuleStore extends Store<FlowRuleBatchEvent, FlowRuleStoreDe ...@@ -61,10 +60,9 @@ public interface FlowRuleStore extends Store<FlowRuleBatchEvent, FlowRuleStoreDe
61 * 60 *
62 * @param batchOperation batch of flow rules. 61 * @param batchOperation batch of flow rules.
63 * A batch can contain flow rules for a single device only. 62 * A batch can contain flow rules for a single device only.
64 - * @return Future response indicating success/failure of the batch operation 63 + *
65 - * all the way down to the device.
66 */ 64 */
67 - Future<CompletedBatchOperation> storeBatch(FlowRuleBatchOperation batchOperation); 65 + void storeBatch(FlowRuleBatchOperation batchOperation);
68 66
69 /** 67 /**
70 * Invoked on the completion of a storeBatch operation. 68 * Invoked on the completion of a storeBatch operation.
......
...@@ -46,10 +46,10 @@ public class FlowRuleBatchOperationTest { ...@@ -46,10 +46,10 @@ public class FlowRuleBatchOperationTest {
46 final LinkedList<FlowRuleBatchEntry> ops3 = new LinkedList<>(); 46 final LinkedList<FlowRuleBatchEntry> ops3 = new LinkedList<>();
47 ops3.add(entry3); 47 ops3.add(entry3);
48 48
49 - final FlowRuleBatchOperation operation1 = new FlowRuleBatchOperation(ops1); 49 + final FlowRuleBatchOperation operation1 = new FlowRuleBatchOperation(ops1, null, 0);
50 - final FlowRuleBatchOperation sameAsOperation1 = new FlowRuleBatchOperation(ops1); 50 + final FlowRuleBatchOperation sameAsOperation1 = new FlowRuleBatchOperation(ops1, null, 0);
51 - final FlowRuleBatchOperation operation2 = new FlowRuleBatchOperation(ops2); 51 + final FlowRuleBatchOperation operation2 = new FlowRuleBatchOperation(ops2, null, 0);
52 - final FlowRuleBatchOperation operation3 = new FlowRuleBatchOperation(ops3); 52 + final FlowRuleBatchOperation operation3 = new FlowRuleBatchOperation(ops3, null, 0);
53 53
54 new EqualsTester() 54 new EqualsTester()
55 .addEqualityGroup(operation1, sameAsOperation1) 55 .addEqualityGroup(operation1, sameAsOperation1)
......
...@@ -15,17 +15,18 @@ ...@@ -15,17 +15,18 @@
15 */ 15 */
16 package org.onosproject.net.flow; 16 package org.onosproject.net.flow;
17 17
18 -import java.util.LinkedList;
19 -import java.util.List;
20 -
21 import org.junit.Test; 18 import org.junit.Test;
22 import org.onosproject.net.intent.IntentTestsMocks; 19 import org.onosproject.net.intent.IntentTestsMocks;
23 20
24 -import static org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation.*; 21 +import java.util.HashSet;
22 +import java.util.List;
23 +import java.util.Set;
25 24
26 import static org.hamcrest.MatcherAssert.assertThat; 25 import static org.hamcrest.MatcherAssert.assertThat;
27 import static org.hamcrest.Matchers.hasSize; 26 import static org.hamcrest.Matchers.hasSize;
28 import static org.hamcrest.Matchers.is; 27 import static org.hamcrest.Matchers.is;
28 +import static org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation.ADD;
29 +import static org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation.REMOVE;
29 30
30 /** 31 /**
31 * Unit tests for the FlowRuleBatchRequest class. 32 * Unit tests for the FlowRuleBatchRequest class.
...@@ -40,22 +41,19 @@ public class FlowRuleBatchRequestTest { ...@@ -40,22 +41,19 @@ public class FlowRuleBatchRequestTest {
40 public void testConstruction() { 41 public void testConstruction() {
41 final FlowRule rule1 = new IntentTestsMocks.MockFlowRule(1); 42 final FlowRule rule1 = new IntentTestsMocks.MockFlowRule(1);
42 final FlowRule rule2 = new IntentTestsMocks.MockFlowRule(2); 43 final FlowRule rule2 = new IntentTestsMocks.MockFlowRule(2);
43 - final List<FlowRuleBatchEntry> toAdd = new LinkedList<>(); 44 + final Set<FlowRuleBatchEntry> batch = new HashSet<>();
44 - toAdd.add(new FlowRuleBatchEntry(ADD, rule1)); 45 + batch.add(new FlowRuleBatchEntry(ADD, rule1));
45 - final List<FlowRuleBatchEntry> toRemove = new LinkedList<>(); 46 +
46 - toRemove.add(new FlowRuleBatchEntry(REMOVE, rule2)); 47 + batch.add(new FlowRuleBatchEntry(REMOVE, rule2));
47 48
48 49
49 final FlowRuleBatchRequest request = 50 final FlowRuleBatchRequest request =
50 - new FlowRuleBatchRequest(1, toAdd, toRemove); 51 + new FlowRuleBatchRequest(1, batch);
51 52
52 - assertThat(request.toAdd(), hasSize(1)); 53 + assertThat(request.ops(), hasSize(2));
53 - assertThat(request.toAdd().get(0), is(rule1)); 54 + assertThat(request.batchId(), is(1L));
54 - assertThat(request.toRemove(), hasSize(1));
55 - assertThat(request.toRemove().get(0), is(rule2));
56 - assertThat(request.batchId(), is(1));
57 55
58 - final FlowRuleBatchOperation op = request.asBatchOperation(); 56 + final FlowRuleBatchOperation op = request.asBatchOperation(rule1.deviceId());
59 assertThat(op.size(), is(2)); 57 assertThat(op.size(), is(2));
60 58
61 final List<FlowRuleBatchEntry> ops = op.getOperations(); 59 final List<FlowRuleBatchEntry> ops = op.getOperations();
......
...@@ -66,6 +66,11 @@ public class FlowRuleServiceAdapter implements FlowRuleService { ...@@ -66,6 +66,11 @@ public class FlowRuleServiceAdapter implements FlowRuleService {
66 } 66 }
67 67
68 @Override 68 @Override
69 + public void apply(FlowRuleOperations ops) {
70 +
71 + }
72 +
73 + @Override
69 public void addListener(FlowRuleListener listener) { 74 public void addListener(FlowRuleListener listener) {
70 75
71 } 76 }
......
...@@ -1151,6 +1151,7 @@ public class IntentManager ...@@ -1151,6 +1151,7 @@ public class IntentManager
1151 */ 1151 */
1152 protected Future<CompletedBatchOperation> applyNextBatch(List<CompletedIntentUpdate> updates) { 1152 protected Future<CompletedBatchOperation> applyNextBatch(List<CompletedIntentUpdate> updates) {
1153 //TODO test this. (also, maybe save this batch) 1153 //TODO test this. (also, maybe save this batch)
1154 +
1154 FlowRuleBatchOperation batch = createFlowRuleBatchOperation(updates); 1155 FlowRuleBatchOperation batch = createFlowRuleBatchOperation(updates);
1155 if (batch.size() > 0) { 1156 if (batch.size() > 0) {
1156 //FIXME apply batch might throw an exception 1157 //FIXME apply batch might throw an exception
...@@ -1165,7 +1166,7 @@ public class IntentManager ...@@ -1165,7 +1166,7 @@ public class IntentManager
1165 } 1166 }
1166 1167
1167 private FlowRuleBatchOperation createFlowRuleBatchOperation(List<CompletedIntentUpdate> intentUpdates) { 1168 private FlowRuleBatchOperation createFlowRuleBatchOperation(List<CompletedIntentUpdate> intentUpdates) {
1168 - FlowRuleBatchOperation batch = new FlowRuleBatchOperation(Collections.emptyList()); 1169 + FlowRuleBatchOperation batch = new FlowRuleBatchOperation(Collections.emptyList(), null, 0);
1169 for (CompletedIntentUpdate update : intentUpdates) { 1170 for (CompletedIntentUpdate update : intentUpdates) {
1170 FlowRuleBatchOperation currentBatch = update.currentBatch(); 1171 FlowRuleBatchOperation currentBatch = update.currentBatch();
1171 if (currentBatch != null) { 1172 if (currentBatch != null) {
......
...@@ -98,6 +98,7 @@ public class LinkCollectionIntentInstaller ...@@ -98,6 +98,7 @@ public class LinkCollectionIntentInstaller
98 outputPorts.put(egressPoint.deviceId(), egressPoint.port()); 98 outputPorts.put(egressPoint.deviceId(), egressPoint.port());
99 } 99 }
100 100
101 + //FIXME change to new api
101 FlowRuleBatchOperation batchOperation = 102 FlowRuleBatchOperation batchOperation =
102 new FlowRuleBatchOperation(outputPorts 103 new FlowRuleBatchOperation(outputPorts
103 .keys() 104 .keys()
...@@ -105,7 +106,7 @@ public class LinkCollectionIntentInstaller ...@@ -105,7 +106,7 @@ public class LinkCollectionIntentInstaller
105 .map(deviceId -> createBatchEntry(operation, 106 .map(deviceId -> createBatchEntry(operation,
106 intent, deviceId, 107 intent, deviceId,
107 outputPorts.get(deviceId))) 108 outputPorts.get(deviceId)))
108 - .collect(Collectors.toList())); 109 + .collect(Collectors.toList()), null, 0);
109 110
110 return Collections.singletonList(batchOperation); 111 return Collections.singletonList(batchOperation);
111 } 112 }
......
...@@ -181,6 +181,7 @@ public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIn ...@@ -181,6 +181,7 @@ public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIn
181 true); 181 true);
182 rules.add(new FlowRuleBatchEntry(operation, rule)); 182 rules.add(new FlowRuleBatchEntry(operation, rule));
183 183
184 - return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 184 + //FIXME change to new api
185 + return Lists.newArrayList(new FlowRuleBatchOperation(rules, null, 0));
185 } 186 }
186 } 187 }
......
...@@ -108,7 +108,8 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -108,7 +108,8 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
108 intent.id().fingerprint())); 108 intent.id().fingerprint()));
109 prev = link.dst(); 109 prev = link.dst();
110 } 110 }
111 - return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 111 + //FIXME this should change to new api.
112 + return Lists.newArrayList(new FlowRuleBatchOperation(rules, null, 0));
112 } 113 }
113 114
114 @Override 115 @Override
...@@ -138,7 +139,8 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -138,7 +139,8 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
138 intent.id().fingerprint())); 139 intent.id().fingerprint()));
139 prev = link.dst(); 140 prev = link.dst();
140 } 141 }
141 - return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 142 + // FIXME this should change to new api
143 + return Lists.newArrayList(new FlowRuleBatchOperation(rules, null, 0));
142 } 144 }
143 145
144 @Override 146 @Override
......
...@@ -31,7 +31,7 @@ public class TestEventDispatcher extends DefaultEventSinkRegistry ...@@ -31,7 +31,7 @@ public class TestEventDispatcher extends DefaultEventSinkRegistry
31 31
32 @Override 32 @Override
33 @SuppressWarnings("unchecked") 33 @SuppressWarnings("unchecked")
34 - public void post(Event event) { 34 + public synchronized void post(Event event) {
35 EventSink sink = getSink(event.getClass()); 35 EventSink sink = getSink(event.getClass());
36 checkState(sink != null, "No sink for event %s", event); 36 checkState(sink != null, "No sink for event %s", event);
37 sink.process(event); 37 sink.process(event);
......
...@@ -20,12 +20,15 @@ import com.google.common.collect.ImmutableMap; ...@@ -20,12 +20,15 @@ import com.google.common.collect.ImmutableMap;
20 import com.google.common.collect.Lists; 20 import com.google.common.collect.Lists;
21 import com.google.common.collect.Sets; 21 import com.google.common.collect.Sets;
22 import com.google.common.util.concurrent.ListenableFuture; 22 import com.google.common.util.concurrent.ListenableFuture;
23 - 23 +import com.google.common.util.concurrent.MoreExecutors;
24 import org.junit.After; 24 import org.junit.After;
25 import org.junit.Before; 25 import org.junit.Before;
26 import org.junit.Test; 26 import org.junit.Test;
27 import org.onosproject.core.ApplicationId; 27 import org.onosproject.core.ApplicationId;
28 +import org.onosproject.core.CoreService;
28 import org.onosproject.core.DefaultApplicationId; 29 import org.onosproject.core.DefaultApplicationId;
30 +import org.onosproject.core.IdGenerator;
31 +import org.onosproject.core.Version;
29 import org.onosproject.event.impl.TestEventDispatcher; 32 import org.onosproject.event.impl.TestEventDispatcher;
30 import org.onosproject.net.DefaultDevice; 33 import org.onosproject.net.DefaultDevice;
31 import org.onosproject.net.Device; 34 import org.onosproject.net.Device;
...@@ -36,7 +39,6 @@ import org.onosproject.net.Port; ...@@ -36,7 +39,6 @@ import org.onosproject.net.Port;
36 import org.onosproject.net.PortNumber; 39 import org.onosproject.net.PortNumber;
37 import org.onosproject.net.device.DeviceListener; 40 import org.onosproject.net.device.DeviceListener;
38 import org.onosproject.net.device.DeviceServiceAdapter; 41 import org.onosproject.net.device.DeviceServiceAdapter;
39 -import org.onosproject.net.flow.BatchOperation;
40 import org.onosproject.net.flow.CompletedBatchOperation; 42 import org.onosproject.net.flow.CompletedBatchOperation;
41 import org.onosproject.net.flow.DefaultFlowEntry; 43 import org.onosproject.net.flow.DefaultFlowEntry;
42 import org.onosproject.net.flow.DefaultFlowRule; 44 import org.onosproject.net.flow.DefaultFlowRule;
...@@ -72,6 +74,7 @@ import java.util.concurrent.Executor; ...@@ -72,6 +74,7 @@ import java.util.concurrent.Executor;
72 import java.util.concurrent.Future; 74 import java.util.concurrent.Future;
73 import java.util.concurrent.TimeUnit; 75 import java.util.concurrent.TimeUnit;
74 import java.util.concurrent.TimeoutException; 76 import java.util.concurrent.TimeoutException;
77 +import java.util.concurrent.atomic.AtomicLong;
75 78
76 import static org.junit.Assert.*; 79 import static org.junit.Assert.*;
77 import static org.onosproject.net.flow.FlowRuleEvent.Type.*; 80 import static org.onosproject.net.flow.FlowRuleEvent.Type.*;
...@@ -97,12 +100,16 @@ public class FlowRuleManagerTest { ...@@ -97,12 +100,16 @@ public class FlowRuleManagerTest {
97 protected TestListener listener = new TestListener(); 100 protected TestListener listener = new TestListener();
98 private ApplicationId appId; 101 private ApplicationId appId;
99 102
103 +
100 @Before 104 @Before
101 public void setUp() { 105 public void setUp() {
102 mgr = new FlowRuleManager(); 106 mgr = new FlowRuleManager();
103 mgr.store = new SimpleFlowRuleStore(); 107 mgr.store = new SimpleFlowRuleStore();
104 mgr.eventDispatcher = new TestEventDispatcher(); 108 mgr.eventDispatcher = new TestEventDispatcher();
105 mgr.deviceService = new TestDeviceService(); 109 mgr.deviceService = new TestDeviceService();
110 + mgr.coreService = new TestCoreService();
111 + mgr.operationsService = MoreExecutors.newDirectExecutorService();
112 + mgr.deviceInstallers = MoreExecutors.newDirectExecutorService();
106 service = mgr; 113 service = mgr;
107 registry = mgr; 114 registry = mgr;
108 115
...@@ -246,14 +253,23 @@ public class FlowRuleManagerTest { ...@@ -246,14 +253,23 @@ public class FlowRuleManagerTest {
246 253
247 @Test 254 @Test
248 public void flowRemoved() { 255 public void flowRemoved() {
256 +
249 FlowRule f1 = addFlowRule(1); 257 FlowRule f1 = addFlowRule(1);
250 FlowRule f2 = addFlowRule(2); 258 FlowRule f2 = addFlowRule(2);
251 StoredFlowEntry fe1 = new DefaultFlowEntry(f1); 259 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
252 FlowEntry fe2 = new DefaultFlowEntry(f2); 260 FlowEntry fe2 = new DefaultFlowEntry(f2);
261 +
262 +
253 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2)); 263 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
254 service.removeFlowRules(f1); 264 service.removeFlowRules(f1);
265 +
255 fe1.setState(FlowEntryState.REMOVED); 266 fe1.setState(FlowEntryState.REMOVED);
267 +
268 +
269 +
256 providerService.flowRemoved(fe1); 270 providerService.flowRemoved(fe1);
271 +
272 +
257 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, 273 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
258 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED); 274 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
259 275
...@@ -263,11 +279,13 @@ public class FlowRuleManagerTest { ...@@ -263,11 +279,13 @@ public class FlowRuleManagerTest {
263 FlowRule f3 = flowRule(3, 3); 279 FlowRule f3 = flowRule(3, 3);
264 FlowEntry fe3 = new DefaultFlowEntry(f3); 280 FlowEntry fe3 = new DefaultFlowEntry(f3);
265 service.applyFlowRules(f3); 281 service.applyFlowRules(f3);
282 +
266 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3)); 283 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
267 validateEvents(RULE_ADD_REQUESTED, RULE_ADDED); 284 validateEvents(RULE_ADD_REQUESTED, RULE_ADDED);
268 285
269 providerService.flowRemoved(fe3); 286 providerService.flowRemoved(fe3);
270 validateEvents(); 287 validateEvents();
288 +
271 } 289 }
272 290
273 @Test 291 @Test
...@@ -281,7 +299,6 @@ public class FlowRuleManagerTest { ...@@ -281,7 +299,6 @@ public class FlowRuleManagerTest {
281 FlowEntry fe1 = new DefaultFlowEntry(f1); 299 FlowEntry fe1 = new DefaultFlowEntry(f1);
282 FlowEntry fe2 = new DefaultFlowEntry(f2); 300 FlowEntry fe2 = new DefaultFlowEntry(f2);
283 301
284 -
285 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED); 302 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
286 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED); 303 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
287 304
...@@ -388,7 +405,7 @@ public class FlowRuleManagerTest { ...@@ -388,7 +405,7 @@ public class FlowRuleManagerTest {
388 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2); 405 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
389 406
390 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation( 407 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
391 - Lists.newArrayList(fbe1, fbe2)); 408 + Lists.newArrayList(fbe1, fbe2), null, 0);
392 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo); 409 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
393 assertTrue("Entries in wrong state", 410 assertTrue("Entries in wrong state",
394 validateState(ImmutableMap.of( 411 validateState(ImmutableMap.of(
...@@ -406,53 +423,6 @@ public class FlowRuleManagerTest { ...@@ -406,53 +423,6 @@ public class FlowRuleManagerTest {
406 423
407 } 424 }
408 425
409 - @Test
410 - public void cancelBatch() {
411 - FlowRule f1 = flowRule(1, 1);
412 - FlowRule f2 = flowRule(2, 2);
413 -
414 -
415 - mgr.applyFlowRules(f1);
416 -
417 - assertTrue("Entries in wrong state",
418 - validateState(ImmutableMap.of(
419 - f1, FlowEntryState.PENDING_ADD)));
420 -
421 - FlowEntry fe1 = new DefaultFlowEntry(f1);
422 - providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
423 -
424 - assertTrue("Entries in wrong state",
425 - validateState(ImmutableMap.of(
426 - f1, FlowEntryState.ADDED)));
427 -
428 -
429 - FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
430 - FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
431 -
432 - FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
433 - FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
434 -
435 - FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
436 - Lists.newArrayList(fbe1, fbe2));
437 - Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
438 -
439 - future.cancel(true);
440 -
441 - assertTrue(flowCount() == 2);
442 -
443 - /*
444 - * Rule f1 should be re-added to the list and therefore be in a pending add
445 - * state.
446 - */
447 - assertTrue("Entries in wrong state",
448 - validateState(ImmutableMap.of(
449 - f2, FlowEntryState.PENDING_REMOVE,
450 - f1, FlowEntryState.PENDING_ADD)));
451 -
452 -
453 - }
454 -
455 -
456 private static class TestListener implements FlowRuleListener { 426 private static class TestListener implements FlowRuleListener {
457 final List<FlowRuleEvent> events = new ArrayList<>(); 427 final List<FlowRuleEvent> events = new ArrayList<>();
458 428
...@@ -528,9 +498,8 @@ public class FlowRuleManagerTest { ...@@ -528,9 +498,8 @@ public class FlowRuleManagerTest {
528 } 498 }
529 499
530 @Override 500 @Override
531 - public ListenableFuture<CompletedBatchOperation> executeBatch( 501 + public void executeBatch(FlowRuleBatchOperation batch) {
532 - BatchOperation<FlowRuleBatchEntry> batch) { 502 + // TODO: need to call batchOperationComplete
533 - return new TestInstallationFuture();
534 } 503 }
535 504
536 private class TestInstallationFuture 505 private class TestInstallationFuture
...@@ -554,14 +523,14 @@ public class FlowRuleManagerTest { ...@@ -554,14 +523,14 @@ public class FlowRuleManagerTest {
554 @Override 523 @Override
555 public CompletedBatchOperation get() 524 public CompletedBatchOperation get()
556 throws InterruptedException, ExecutionException { 525 throws InterruptedException, ExecutionException {
557 - return new CompletedBatchOperation(true, Collections.<FlowRule>emptySet()); 526 + return new CompletedBatchOperation(true, Collections.<FlowRule>emptySet(), null);
558 } 527 }
559 528
560 @Override 529 @Override
561 public CompletedBatchOperation get(long timeout, TimeUnit unit) 530 public CompletedBatchOperation get(long timeout, TimeUnit unit)
562 throws InterruptedException, 531 throws InterruptedException,
563 ExecutionException, TimeoutException { 532 ExecutionException, TimeoutException {
564 - return new CompletedBatchOperation(true, Collections.<FlowRule>emptySet()); 533 + return new CompletedBatchOperation(true, Collections.<FlowRule>emptySet(), null);
565 } 534 }
566 535
567 @Override 536 @Override
...@@ -644,4 +613,37 @@ public class FlowRuleManagerTest { ...@@ -644,4 +613,37 @@ public class FlowRuleManagerTest {
644 } 613 }
645 } 614 }
646 615
616 + private class TestCoreService implements CoreService {
617 + @Override
618 + public Version version() {
619 + return null;
620 + }
621 +
622 + @Override
623 + public Set<ApplicationId> getAppIds() {
624 + return null;
625 + }
626 +
627 + @Override
628 + public ApplicationId getAppId(Short id) {
629 + return null;
630 + }
631 +
632 + @Override
633 + public ApplicationId registerApplication(String identifier) {
634 + return null;
635 + }
636 +
637 + @Override
638 + public IdGenerator getIdGenerator(String topic) {
639 + return new IdGenerator() {
640 + private AtomicLong counter = new AtomicLong(0);
641 + @Override
642 + public long getNewId() {
643 + return counter.getAndIncrement();
644 + }
645 + };
646 + }
647 + }
648 +
647 } 649 }
......
...@@ -201,7 +201,7 @@ public class IntentManagerTest { ...@@ -201,7 +201,7 @@ public class IntentManagerTest {
201 FlowRule fr = new IntentTestsMocks.MockFlowRule(intent.number().intValue()); 201 FlowRule fr = new IntentTestsMocks.MockFlowRule(intent.number().intValue());
202 List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); 202 List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
203 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, fr)); 203 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, fr));
204 - return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 204 + return Lists.newArrayList(new FlowRuleBatchOperation(rules, fr.deviceId(), 0));
205 } 205 }
206 206
207 @Override 207 @Override
...@@ -209,7 +209,7 @@ public class IntentManagerTest { ...@@ -209,7 +209,7 @@ public class IntentManagerTest {
209 FlowRule fr = new IntentTestsMocks.MockFlowRule(intent.number().intValue()); 209 FlowRule fr = new IntentTestsMocks.MockFlowRule(intent.number().intValue());
210 List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); 210 List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
211 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, fr)); 211 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, fr));
212 - return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 212 + return Lists.newArrayList(new FlowRuleBatchOperation(rules, fr.deviceId(), 0));
213 } 213 }
214 214
215 @Override 215 @Override
...@@ -219,7 +219,7 @@ public class IntentManagerTest { ...@@ -219,7 +219,7 @@ public class IntentManagerTest {
219 List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); 219 List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
220 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, fr)); 220 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, fr));
221 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, fr2)); 221 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, fr2));
222 - return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 222 + return Lists.newArrayList(new FlowRuleBatchOperation(rules, fr.deviceId(), 0));
223 } 223 }
224 } 224 }
225 225
......
...@@ -27,6 +27,7 @@ import org.onosproject.net.flow.FlowRule; ...@@ -27,6 +27,7 @@ import org.onosproject.net.flow.FlowRule;
27 import org.onosproject.net.flow.FlowRuleBatchEntry; 27 import org.onosproject.net.flow.FlowRuleBatchEntry;
28 import org.onosproject.net.flow.FlowRuleBatchOperation; 28 import org.onosproject.net.flow.FlowRuleBatchOperation;
29 import org.onosproject.net.flow.FlowRuleListener; 29 import org.onosproject.net.flow.FlowRuleListener;
30 +import org.onosproject.net.flow.FlowRuleOperations;
30 import org.onosproject.net.flow.FlowRuleService; 31 import org.onosproject.net.flow.FlowRuleService;
31 32
32 import com.google.common.collect.ImmutableSet; 33 import com.google.common.collect.ImmutableSet;
...@@ -45,11 +46,11 @@ public class MockFlowRuleService implements FlowRuleService { ...@@ -45,11 +46,11 @@ public class MockFlowRuleService implements FlowRuleService {
45 46
46 public void setFuture(boolean success, long intentId) { 47 public void setFuture(boolean success, long intentId) {
47 if (success) { 48 if (success) {
48 - future = Futures.immediateFuture(new CompletedBatchOperation(true, Collections.emptySet())); 49 + future = Futures.immediateFuture(new CompletedBatchOperation(true, Collections.emptySet(), null));
49 } else { 50 } else {
50 final Set<Long> failedIds = ImmutableSet.of(intentId); 51 final Set<Long> failedIds = ImmutableSet.of(intentId);
51 future = Futures.immediateFuture( 52 future = Futures.immediateFuture(
52 - new CompletedBatchOperation(false, flows, failedIds)); 53 + new CompletedBatchOperation(false, flows, failedIds, null));
53 } 54 }
54 } 55 }
55 56
...@@ -74,6 +75,11 @@ public class MockFlowRuleService implements FlowRuleService { ...@@ -74,6 +75,11 @@ public class MockFlowRuleService implements FlowRuleService {
74 } 75 }
75 76
76 @Override 77 @Override
78 + public void apply(FlowRuleOperations ops) {
79 +
80 + }
81 +
82 + @Override
77 public int getFlowRuleCount() { 83 public int getFlowRuleCount() {
78 return flows.size(); 84 return flows.size();
79 } 85 }
......
...@@ -34,4 +34,7 @@ public final class FlowStoreMessageSubjects { ...@@ -34,4 +34,7 @@ public final class FlowStoreMessageSubjects {
34 34
35 public static final MessageSubject REMOVE_FLOW_ENTRY 35 public static final MessageSubject REMOVE_FLOW_ENTRY
36 = new MessageSubject("peer-forward-remove-flow-entry"); 36 = new MessageSubject("peer-forward-remove-flow-entry");
37 +
38 + public static final MessageSubject REMOTE_APPLY_COMPLETED
39 + = new MessageSubject("peer-apply-completed");
37 } 40 }
......
...@@ -59,15 +59,17 @@ import org.onosproject.net.PortNumber; ...@@ -59,15 +59,17 @@ import org.onosproject.net.PortNumber;
59 import org.onosproject.net.device.DefaultDeviceDescription; 59 import org.onosproject.net.device.DefaultDeviceDescription;
60 import org.onosproject.net.device.DefaultPortDescription; 60 import org.onosproject.net.device.DefaultPortDescription;
61 import org.onosproject.net.flow.CompletedBatchOperation; 61 import org.onosproject.net.flow.CompletedBatchOperation;
62 -import org.onosproject.net.flow.FlowRule;
63 import org.onosproject.net.flow.DefaultFlowEntry; 62 import org.onosproject.net.flow.DefaultFlowEntry;
64 import org.onosproject.net.flow.DefaultFlowRule; 63 import org.onosproject.net.flow.DefaultFlowRule;
65 import org.onosproject.net.flow.DefaultTrafficSelector; 64 import org.onosproject.net.flow.DefaultTrafficSelector;
66 import org.onosproject.net.flow.DefaultTrafficTreatment; 65 import org.onosproject.net.flow.DefaultTrafficTreatment;
67 import org.onosproject.net.flow.FlowEntry; 66 import org.onosproject.net.flow.FlowEntry;
68 import org.onosproject.net.flow.FlowId; 67 import org.onosproject.net.flow.FlowId;
68 +import org.onosproject.net.flow.FlowRule;
69 import org.onosproject.net.flow.FlowRuleBatchEntry; 69 import org.onosproject.net.flow.FlowRuleBatchEntry;
70 +import org.onosproject.net.flow.FlowRuleBatchEvent;
70 import org.onosproject.net.flow.FlowRuleBatchOperation; 71 import org.onosproject.net.flow.FlowRuleBatchOperation;
72 +import org.onosproject.net.flow.FlowRuleBatchRequest;
71 import org.onosproject.net.flow.StoredFlowEntry; 73 import org.onosproject.net.flow.StoredFlowEntry;
72 import org.onosproject.net.flow.criteria.Criteria; 74 import org.onosproject.net.flow.criteria.Criteria;
73 import org.onosproject.net.flow.criteria.Criterion; 75 import org.onosproject.net.flow.criteria.Criterion;
...@@ -162,6 +164,7 @@ public final class KryoNamespaces { ...@@ -162,6 +164,7 @@ public final class KryoNamespaces {
162 .register(Collections.emptySet().getClass()) 164 .register(Collections.emptySet().getClass())
163 .register(Optional.class) 165 .register(Optional.class)
164 .register(Collections.emptyList().getClass()) 166 .register(Collections.emptyList().getClass())
167 + .register(Collections.unmodifiableSet(Collections.emptySet()).getClass())
165 .build(); 168 .build();
166 169
167 /** 170 /**
...@@ -255,6 +258,9 @@ public final class KryoNamespaces { ...@@ -255,6 +258,9 @@ public final class KryoNamespaces {
255 L3ModificationInstruction.L3SubType.class, 258 L3ModificationInstruction.L3SubType.class,
256 L3ModificationInstruction.ModIPInstruction.class, 259 L3ModificationInstruction.ModIPInstruction.class,
257 RoleInfo.class, 260 RoleInfo.class,
261 + FlowRuleBatchEvent.class,
262 + FlowRuleBatchEvent.Type.class,
263 + FlowRuleBatchRequest.class,
258 FlowRuleBatchOperation.class, 264 FlowRuleBatchOperation.class,
259 CompletedBatchOperation.class, 265 CompletedBatchOperation.class,
260 FlowRuleBatchEntry.class, 266 FlowRuleBatchEntry.class,
......
...@@ -21,13 +21,13 @@ import com.google.common.cache.CacheBuilder; ...@@ -21,13 +21,13 @@ import com.google.common.cache.CacheBuilder;
21 import com.google.common.cache.RemovalListener; 21 import com.google.common.cache.RemovalListener;
22 import com.google.common.cache.RemovalNotification; 22 import com.google.common.cache.RemovalNotification;
23 import com.google.common.collect.FluentIterable; 23 import com.google.common.collect.FluentIterable;
24 -import com.google.common.util.concurrent.Futures; 24 +import com.google.common.collect.Sets;
25 import com.google.common.util.concurrent.SettableFuture; 25 import com.google.common.util.concurrent.SettableFuture;
26 -
27 import org.apache.felix.scr.annotations.Activate; 26 import org.apache.felix.scr.annotations.Activate;
28 import org.apache.felix.scr.annotations.Component; 27 import org.apache.felix.scr.annotations.Component;
29 import org.apache.felix.scr.annotations.Deactivate; 28 import org.apache.felix.scr.annotations.Deactivate;
30 import org.apache.felix.scr.annotations.Service; 29 import org.apache.felix.scr.annotations.Service;
30 +import org.onlab.util.NewConcurrentHashMap;
31 import org.onosproject.net.DeviceId; 31 import org.onosproject.net.DeviceId;
32 import org.onosproject.net.flow.CompletedBatchOperation; 32 import org.onosproject.net.flow.CompletedBatchOperation;
33 import org.onosproject.net.flow.DefaultFlowEntry; 33 import org.onosproject.net.flow.DefaultFlowEntry;
...@@ -46,7 +46,6 @@ import org.onosproject.net.flow.FlowRuleStore; ...@@ -46,7 +46,6 @@ import org.onosproject.net.flow.FlowRuleStore;
46 import org.onosproject.net.flow.FlowRuleStoreDelegate; 46 import org.onosproject.net.flow.FlowRuleStoreDelegate;
47 import org.onosproject.net.flow.StoredFlowEntry; 47 import org.onosproject.net.flow.StoredFlowEntry;
48 import org.onosproject.store.AbstractStore; 48 import org.onosproject.store.AbstractStore;
49 -import org.onlab.util.NewConcurrentHashMap;
50 import org.slf4j.Logger; 49 import org.slf4j.Logger;
51 50
52 import java.util.ArrayList; 51 import java.util.ArrayList;
...@@ -56,7 +55,6 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -56,7 +55,6 @@ import java.util.concurrent.ConcurrentHashMap;
56 import java.util.concurrent.ConcurrentMap; 55 import java.util.concurrent.ConcurrentMap;
57 import java.util.concurrent.CopyOnWriteArrayList; 56 import java.util.concurrent.CopyOnWriteArrayList;
58 import java.util.concurrent.ExecutionException; 57 import java.util.concurrent.ExecutionException;
59 -import java.util.concurrent.Future;
60 import java.util.concurrent.TimeUnit; 58 import java.util.concurrent.TimeUnit;
61 import java.util.concurrent.TimeoutException; 59 import java.util.concurrent.TimeoutException;
62 import java.util.concurrent.atomic.AtomicInteger; 60 import java.util.concurrent.atomic.AtomicInteger;
...@@ -261,13 +259,14 @@ public class SimpleFlowRuleStore ...@@ -261,13 +259,14 @@ public class SimpleFlowRuleStore
261 } 259 }
262 260
263 @Override 261 @Override
264 - public Future<CompletedBatchOperation> storeBatch( 262 + public void storeBatch(
265 - FlowRuleBatchOperation batchOperation) { 263 + FlowRuleBatchOperation operation) {
266 List<FlowRuleBatchEntry> toAdd = new ArrayList<>(); 264 List<FlowRuleBatchEntry> toAdd = new ArrayList<>();
267 List<FlowRuleBatchEntry> toRemove = new ArrayList<>(); 265 List<FlowRuleBatchEntry> toRemove = new ArrayList<>();
268 - for (FlowRuleBatchEntry entry : batchOperation.getOperations()) { 266 +
269 - final FlowRule flowRule = entry.target(); 267 + for (FlowRuleBatchEntry entry : operation.getOperations()) {
270 - if (entry.operator().equals(FlowRuleOperation.ADD)) { 268 + final FlowRule flowRule = entry.getTarget();
269 + if (entry.getOperator().equals(FlowRuleOperation.ADD)) {
271 if (!getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) { 270 if (!getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) {
272 storeFlowRule(flowRule); 271 storeFlowRule(flowRule);
273 toAdd.add(entry); 272 toAdd.add(entry);
...@@ -283,21 +282,27 @@ public class SimpleFlowRuleStore ...@@ -283,21 +282,27 @@ public class SimpleFlowRuleStore
283 } 282 }
284 283
285 if (toAdd.isEmpty() && toRemove.isEmpty()) { 284 if (toAdd.isEmpty() && toRemove.isEmpty()) {
286 - return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowRule>emptySet())); 285 + notifyDelegate(FlowRuleBatchEvent.completed(
286 + new FlowRuleBatchRequest(operation.id(), Collections.emptySet()),
287 + new CompletedBatchOperation(true, Collections.emptySet(),
288 + operation.deviceId())));
289 + return;
287 } 290 }
288 291
289 SettableFuture<CompletedBatchOperation> r = SettableFuture.create(); 292 SettableFuture<CompletedBatchOperation> r = SettableFuture.create();
290 final int batchId = localBatchIdGen.incrementAndGet(); 293 final int batchId = localBatchIdGen.incrementAndGet();
291 294
292 pendingFutures.put(batchId, r); 295 pendingFutures.put(batchId, r);
293 - notifyDelegate(FlowRuleBatchEvent.requested(new FlowRuleBatchRequest(batchId, toAdd, toRemove)));
294 296
295 - return r; 297 + toAdd.addAll(toRemove);
298 + notifyDelegate(FlowRuleBatchEvent.requested(
299 + new FlowRuleBatchRequest(batchId, Sets.newHashSet(toAdd)), operation.deviceId()));
300 +
296 } 301 }
297 302
298 @Override 303 @Override
299 public void batchOperationComplete(FlowRuleBatchEvent event) { 304 public void batchOperationComplete(FlowRuleBatchEvent event) {
300 - final Integer batchId = event.subject().batchId(); 305 + final Long batchId = event.subject().batchId();
301 SettableFuture<CompletedBatchOperation> future 306 SettableFuture<CompletedBatchOperation> future
302 = pendingFutures.getIfPresent(batchId); 307 = pendingFutures.getIfPresent(batchId);
303 if (future != null) { 308 if (future != null) {
......
...@@ -116,7 +116,7 @@ public class NullDeviceProvider extends AbstractProvider implements DeviceProvid ...@@ -116,7 +116,7 @@ public class NullDeviceProvider extends AbstractProvider implements DeviceProvid
116 @Activate 116 @Activate
117 public void activate(ComponentContext context) { 117 public void activate(ComponentContext context) {
118 providerService = providerRegistry.register(this); 118 providerService = providerRegistry.register(this);
119 - if (modified(context)) { 119 + if (!modified(context)) {
120 deviceBuilder.submit(new DeviceCreator(true)); 120 deviceBuilder.submit(new DeviceCreator(true));
121 } 121 }
122 log.info("Started"); 122 log.info("Started");
...@@ -173,6 +173,9 @@ public class NullDeviceProvider extends AbstractProvider implements DeviceProvid ...@@ -173,6 +173,9 @@ public class NullDeviceProvider extends AbstractProvider implements DeviceProvid
173 chgd |= true; 173 chgd |= true;
174 } 174 }
175 log.info("Using settings numDevices={}, numPorts={}", numDevices, numPorts); 175 log.info("Using settings numDevices={}, numPorts={}", numDevices, numPorts);
176 + if (chgd) {
177 + deviceBuilder.submit(new DeviceCreator(true));
178 + }
176 return chgd; 179 return chgd;
177 } 180 }
178 181
......
...@@ -15,9 +15,7 @@ ...@@ -15,9 +15,7 @@
15 */ 15 */
16 package org.onosproject.provider.nil.flow.impl; 16 package org.onosproject.provider.nil.flow.impl;
17 17
18 -import com.google.common.collect.HashMultimap; 18 +import com.google.common.collect.Sets;
19 -import com.google.common.collect.Multimap;
20 -import com.google.common.util.concurrent.Futures;
21 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 21 import org.apache.felix.scr.annotations.Deactivate;
...@@ -29,12 +27,12 @@ import org.jboss.netty.util.TimerTask; ...@@ -29,12 +27,12 @@ import org.jboss.netty.util.TimerTask;
29 import org.onlab.util.Timer; 27 import org.onlab.util.Timer;
30 import org.onosproject.core.ApplicationId; 28 import org.onosproject.core.ApplicationId;
31 import org.onosproject.net.DeviceId; 29 import org.onosproject.net.DeviceId;
32 -import org.onosproject.net.flow.BatchOperation;
33 import org.onosproject.net.flow.CompletedBatchOperation; 30 import org.onosproject.net.flow.CompletedBatchOperation;
34 import org.onosproject.net.flow.DefaultFlowEntry; 31 import org.onosproject.net.flow.DefaultFlowEntry;
35 import org.onosproject.net.flow.FlowEntry; 32 import org.onosproject.net.flow.FlowEntry;
36 import org.onosproject.net.flow.FlowRule; 33 import org.onosproject.net.flow.FlowRule;
37 import org.onosproject.net.flow.FlowRuleBatchEntry; 34 import org.onosproject.net.flow.FlowRuleBatchEntry;
35 +import org.onosproject.net.flow.FlowRuleBatchOperation;
38 import org.onosproject.net.flow.FlowRuleProvider; 36 import org.onosproject.net.flow.FlowRuleProvider;
39 import org.onosproject.net.flow.FlowRuleProviderRegistry; 37 import org.onosproject.net.flow.FlowRuleProviderRegistry;
40 import org.onosproject.net.flow.FlowRuleProviderService; 38 import org.onosproject.net.flow.FlowRuleProviderService;
...@@ -43,7 +41,9 @@ import org.onosproject.net.provider.ProviderId; ...@@ -43,7 +41,9 @@ import org.onosproject.net.provider.ProviderId;
43 import org.slf4j.Logger; 41 import org.slf4j.Logger;
44 42
45 import java.util.Collections; 43 import java.util.Collections;
46 -import java.util.concurrent.Future; 44 +import java.util.Set;
45 +import java.util.concurrent.ConcurrentHashMap;
46 +import java.util.concurrent.ConcurrentMap;
47 import java.util.concurrent.TimeUnit; 47 import java.util.concurrent.TimeUnit;
48 48
49 import static org.slf4j.LoggerFactory.getLogger; 49 import static org.slf4j.LoggerFactory.getLogger;
...@@ -59,7 +59,7 @@ public class NullFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -59,7 +59,7 @@ public class NullFlowRuleProvider extends AbstractProvider implements FlowRulePr
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected FlowRuleProviderRegistry providerRegistry; 60 protected FlowRuleProviderRegistry providerRegistry;
61 61
62 - private Multimap<DeviceId, FlowEntry> flowTable = HashMultimap.create(); 62 + private ConcurrentMap<DeviceId, Set<FlowEntry>> flowTable = new ConcurrentHashMap<>();
63 63
64 private FlowRuleProviderService providerService; 64 private FlowRuleProviderService providerService;
65 65
...@@ -88,18 +88,10 @@ public class NullFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -88,18 +88,10 @@ public class NullFlowRuleProvider extends AbstractProvider implements FlowRulePr
88 } 88 }
89 89
90 @Override 90 @Override
91 - public void applyFlowRule(FlowRule... flowRules) { 91 + public void applyFlowRule(FlowRule... flowRules) {}
92 - for (int i = 0; i < flowRules.length; i++) {
93 - flowTable.put(flowRules[i].deviceId(), new DefaultFlowEntry(flowRules[i]));
94 - }
95 - }
96 92
97 @Override 93 @Override
98 - public void removeFlowRule(FlowRule... flowRules) { 94 + public void removeFlowRule(FlowRule... flowRules) {}
99 - for (int i = 0; i < flowRules.length; i++) {
100 - flowTable.remove(flowRules[i].deviceId(), flowRules[i]);
101 - }
102 - }
103 95
104 @Override 96 @Override
105 public void removeRulesById(ApplicationId id, FlowRule... flowRules) { 97 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
...@@ -107,26 +99,32 @@ public class NullFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -107,26 +99,32 @@ public class NullFlowRuleProvider extends AbstractProvider implements FlowRulePr
107 } 99 }
108 100
109 @Override 101 @Override
110 - public Future<CompletedBatchOperation> executeBatch( 102 + public void executeBatch(
111 - BatchOperation<FlowRuleBatchEntry> batch) { 103 + FlowRuleBatchOperation batch) {
104 + Set<FlowEntry> flowRules = flowTable.getOrDefault(batch.deviceId(), Sets.newConcurrentHashSet());
112 for (FlowRuleBatchEntry fbe : batch.getOperations()) { 105 for (FlowRuleBatchEntry fbe : batch.getOperations()) {
113 switch (fbe.operator()) { 106 switch (fbe.operator()) {
114 case ADD: 107 case ADD:
115 - applyFlowRule(fbe.target()); 108 + flowRules.add(new DefaultFlowEntry(fbe.target()));
116 break; 109 break;
117 case REMOVE: 110 case REMOVE:
118 - removeFlowRule(fbe.target()); 111 + flowRules.remove(new DefaultFlowEntry(fbe.target()));
119 break; 112 break;
120 case MODIFY: 113 case MODIFY:
121 - removeFlowRule(fbe.target()); 114 + FlowEntry entry = new DefaultFlowEntry(fbe.target());
122 - applyFlowRule(fbe.target()); 115 + flowRules.remove(entry);
116 + flowRules.add(entry);
123 break; 117 break;
124 default: 118 default:
125 log.error("Unknown flow operation: {}", fbe); 119 log.error("Unknown flow operation: {}", fbe);
126 } 120 }
127 } 121 }
128 - return Futures.immediateFuture( 122 + flowTable.put(batch.deviceId(), flowRules);
129 - new CompletedBatchOperation(true, Collections.emptySet())); 123 + providerService.batchOperationCompleted(batch.id(),
124 + new CompletedBatchOperation(
125 + true,
126 + Collections.emptySet(),
127 + batch.deviceId()));
130 } 128 }
131 129
132 private class StatisticTask implements TimerTask { 130 private class StatisticTask implements TimerTask {
...@@ -134,10 +132,11 @@ public class NullFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -134,10 +132,11 @@ public class NullFlowRuleProvider extends AbstractProvider implements FlowRulePr
134 @Override 132 @Override
135 public void run(Timeout to) throws Exception { 133 public void run(Timeout to) throws Exception {
136 for (DeviceId devId : flowTable.keySet()) { 134 for (DeviceId devId : flowTable.keySet()) {
137 - providerService.pushFlowMetrics(devId, flowTable.get(devId)); 135 + providerService.pushFlowMetrics(devId,
136 + flowTable.getOrDefault(devId, Collections.emptySet()));
138 } 137 }
139 -
140 timeout = timer.newTimeout(to.getTask(), 5, TimeUnit.SECONDS); 138 timeout = timer.newTimeout(to.getTask(), 5, TimeUnit.SECONDS);
139 +
141 } 140 }
142 } 141 }
143 } 142 }
......
...@@ -35,6 +35,7 @@ import org.onosproject.net.flow.FlowRule; ...@@ -35,6 +35,7 @@ import org.onosproject.net.flow.FlowRule;
35 import org.onosproject.net.flow.TrafficSelector; 35 import org.onosproject.net.flow.TrafficSelector;
36 import org.onosproject.net.flow.TrafficTreatment; 36 import org.onosproject.net.flow.TrafficTreatment;
37 import org.onosproject.openflow.controller.Dpid; 37 import org.onosproject.openflow.controller.Dpid;
38 +import org.projectfloodlight.openflow.protocol.OFFlowMod;
38 import org.projectfloodlight.openflow.protocol.OFFlowRemoved; 39 import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
39 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; 40 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
40 import org.projectfloodlight.openflow.protocol.OFInstructionType; 41 import org.projectfloodlight.openflow.protocol.OFInstructionType;
...@@ -74,13 +75,16 @@ public class FlowEntryBuilder { ...@@ -74,13 +75,16 @@ public class FlowEntryBuilder {
74 75
75 private final OFFlowStatsEntry stat; 76 private final OFFlowStatsEntry stat;
76 private final OFFlowRemoved removed; 77 private final OFFlowRemoved removed;
78 + private final OFFlowMod flowMod;
77 79
78 private final Match match; 80 private final Match match;
79 private final List<OFAction> actions; 81 private final List<OFAction> actions;
80 82
81 private final Dpid dpid; 83 private final Dpid dpid;
82 84
83 - private final boolean addedRule; 85 + public enum FlowType { STAT, REMOVED, MOD }
86 +
87 + private final FlowType type;
84 88
85 89
86 public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) { 90 public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
...@@ -89,7 +93,8 @@ public class FlowEntryBuilder { ...@@ -89,7 +93,8 @@ public class FlowEntryBuilder {
89 this.actions = getActions(entry); 93 this.actions = getActions(entry);
90 this.dpid = dpid; 94 this.dpid = dpid;
91 this.removed = null; 95 this.removed = null;
92 - this.addedRule = true; 96 + this.flowMod = null;
97 + this.type = FlowType.STAT;
93 } 98 }
94 99
95 public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) { 100 public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
...@@ -99,26 +104,48 @@ public class FlowEntryBuilder { ...@@ -99,26 +104,48 @@ public class FlowEntryBuilder {
99 this.dpid = dpid; 104 this.dpid = dpid;
100 this.actions = null; 105 this.actions = null;
101 this.stat = null; 106 this.stat = null;
102 - this.addedRule = false; 107 + this.flowMod = null;
108 + this.type = FlowType.REMOVED;
109 +
110 + }
103 111
112 + public FlowEntryBuilder(Dpid dpid, OFFlowMod fm) {
113 + this.match = fm.getMatch();
114 + this.dpid = dpid;
115 + this.actions = fm.getActions();
116 + this.type = FlowType.MOD;
117 + this.flowMod = fm;
118 + this.stat = null;
119 + this.removed = null;
104 } 120 }
105 121
106 - public FlowEntry build() { 122 + public FlowEntry build(FlowEntryState... state) {
107 - if (addedRule) { 123 + FlowRule rule;
108 - FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)), 124 + switch (this.type) {
125 + case STAT:
126 + rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
109 buildSelector(), buildTreatment(), stat.getPriority(), 127 buildSelector(), buildTreatment(), stat.getPriority(),
110 stat.getCookie().getValue(), stat.getIdleTimeout(), false); 128 stat.getCookie().getValue(), stat.getIdleTimeout(), false);
111 return new DefaultFlowEntry(rule, FlowEntryState.ADDED, 129 return new DefaultFlowEntry(rule, FlowEntryState.ADDED,
112 stat.getDurationSec(), stat.getPacketCount().getValue(), 130 stat.getDurationSec(), stat.getPacketCount().getValue(),
113 stat.getByteCount().getValue()); 131 stat.getByteCount().getValue());
114 - 132 + case REMOVED:
115 - } else { 133 + rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
116 - FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
117 buildSelector(), null, removed.getPriority(), 134 buildSelector(), null, removed.getPriority(),
118 removed.getCookie().getValue(), removed.getIdleTimeout(), false); 135 removed.getCookie().getValue(), removed.getIdleTimeout(), false);
119 return new DefaultFlowEntry(rule, FlowEntryState.REMOVED, removed.getDurationSec(), 136 return new DefaultFlowEntry(rule, FlowEntryState.REMOVED, removed.getDurationSec(),
120 removed.getPacketCount().getValue(), removed.getByteCount().getValue()); 137 removed.getPacketCount().getValue(), removed.getByteCount().getValue());
138 + case MOD:
139 + FlowEntryState flowState = state.length > 0 ? state[0] : FlowEntryState.FAILED;
140 + rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
141 + buildSelector(), buildTreatment(), flowMod.getPriority(),
142 + flowMod.getCookie().getValue(), flowMod.getIdleTimeout(), false);
143 + return new DefaultFlowEntry(rule, flowState, 0, 0, 0);
144 + default:
145 + log.error("Unknown flow type : {}", this.type);
146 + return null;
121 } 147 }
148 +
122 } 149 }
123 150
124 private List<OFAction> getActions(OFFlowStatsEntry entry) { 151 private List<OFAction> getActions(OFFlowStatsEntry entry) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 # Instance-specific configurations, in this case, the number of 2 # Instance-specific configurations, in this case, the number of
3 # devices per node. 3 # devices per node.
4 # 4 #
5 -devConfigs = 192.168.56.30:5,192.168.56.40:7 5 +devConfigs = 192.168.97.132:5,192.168.97.131:5
6 6
7 # 7 #
8 # Number of ports per device. This is global to all devices 8 # Number of ports per device. This is global to all devices
......
...@@ -9,4 +9,4 @@ ...@@ -9,4 +9,4 @@
9 # 9 #
10 # Set order of islands to chain together, in a line. 10 # Set order of islands to chain together, in a line.
11 # 11 #
12 -neighbors = 192.168.56.20,192.168.56.30,192.168.56.40 12 +neighbors = 192.168.97.132,192.168.97.131
......