Xin Jin
Committed by Brian O'Connor

Adding experimental Flow Objective composition

Change-Id: I35e4414845ad5034145157ab83f933e40f75a1d9
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.cli.net;
17 +
18 +import org.apache.karaf.shell.commands.Argument;
19 +import org.apache.karaf.shell.commands.Command;
20 +import org.onosproject.cli.AbstractShellCommand;
21 +import org.onosproject.net.flowobjective.FlowObjectiveService;
22 +
23 +/**
24 + * Manages FlowObjectiveComposition policy.
25 + */
26 +@Command(scope = "onos", name = "policy",
27 + description = "Manages FlowObjectiveComposition policy")
28 +public class FlowObjectiveCompositionCommand extends AbstractShellCommand {
29 +
30 + @Argument(index = 0, name = "command",
31 + description = "Command name (install)",
32 + required = true, multiValued = false)
33 + String command = null;
34 +
35 + @Argument(index = 1, name = "names", description = "policy string",
36 + required = true, multiValued = true)
37 + String[] policies = null;
38 +
39 + @Override
40 + protected void execute() {
41 + FlowObjectiveService service = get(FlowObjectiveService.class);
42 + service.initPolicy(policies[0]);
43 + print("Policy %s installed", policies[0]);
44 + }
45 +}
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
30 </command> 30 </command>
31 31
32 <command> 32 <command>
33 + <action class="org.onosproject.cli.net.FlowObjectiveCompositionCommand"/>
34 + </command>
35 +
36 + <command>
33 <action class="org.onosproject.cli.app.ApplicationsListCommand"/> 37 <action class="org.onosproject.cli.app.ApplicationsListCommand"/>
34 </command> 38 </command>
35 39
......
...@@ -56,4 +56,10 @@ public interface FlowObjectiveService { ...@@ -56,4 +56,10 @@ public interface FlowObjectiveService {
56 */ 56 */
57 int allocateNextId(); 57 int allocateNextId();
58 58
59 + /**
60 + * Installs the filtering rules onto the specified device.
61 + *
62 + * @param policy policy expression
63 + */
64 + void initPolicy(String policy);
59 } 65 }
......
...@@ -218,6 +218,9 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -218,6 +218,9 @@ public class FlowObjectiveManager implements FlowObjectiveService {
218 return flowObjectiveStore.allocateNextId(); 218 return flowObjectiveStore.allocateNextId();
219 } 219 }
220 220
221 + @Override
222 + public void initPolicy(String policy) {}
223 +
221 private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) { 224 private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) {
222 if (fwd.nextId() != null && 225 if (fwd.nextId() != null &&
223 flowObjectiveStore.getNextGroup(fwd.nextId()) == null) { 226 flowObjectiveStore.getNextGroup(fwd.nextId()) == null) {
......
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.flowobjective.impl.composition;
17 +
18 +import org.onosproject.net.flowobjective.FilteringObjective;
19 +
20 +import java.util.ArrayList;
21 +import java.util.HashMap;
22 +import java.util.List;
23 +import java.util.Map;
24 +
25 +/**
26 + * Provides a table to store Fitler.
27 + */
28 +public class FilterTable {
29 +
30 + protected Map<Integer, FilteringObjective> filterMap;
31 +
32 + public FilterTable() {
33 + this.filterMap = new HashMap<>();
34 + }
35 +
36 + public List<FilteringObjective> updateFilter(FilteringObjective filteringObjective) {
37 + List<FilteringObjective> updates = new ArrayList<>();
38 + switch (filteringObjective.op()) {
39 + case ADD:
40 + this.filterMap.put(filteringObjective.id(), filteringObjective);
41 + updates.add(filteringObjective);
42 + break;
43 + case REMOVE:
44 + this.filterMap.remove(filteringObjective.id());
45 + updates.add(filteringObjective);
46 + break;
47 + default:
48 + break;
49 + }
50 + return updates;
51 + }
52 +
53 + public List<FilteringObjective> updateFilter(List<FilteringObjective> filteringObjectives) {
54 + List<FilteringObjective> updates = new ArrayList<>();
55 + for (FilteringObjective filteringObjective : filteringObjectives) {
56 + updates.addAll(this.updateFilter(filteringObjective));
57 + }
58 + return updates;
59 + }
60 +
61 +}
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.flowobjective.impl.composition;
17 +
18 +import com.google.common.collect.Maps;
19 +import com.google.common.collect.Sets;
20 +import org.apache.felix.scr.annotations.Activate;
21 +import org.apache.felix.scr.annotations.Component;
22 +import org.apache.felix.scr.annotations.Deactivate;
23 +import org.apache.felix.scr.annotations.Reference;
24 +import org.apache.felix.scr.annotations.ReferenceCardinality;
25 +import org.apache.felix.scr.annotations.Service;
26 +import org.onlab.osgi.DefaultServiceDirectory;
27 +import org.onlab.osgi.ServiceDirectory;
28 +import org.onlab.util.ItemNotFoundException;
29 +import org.onosproject.cluster.ClusterService;
30 +import org.onosproject.core.Permission;
31 +import org.onosproject.mastership.MastershipEvent;
32 +import org.onosproject.mastership.MastershipListener;
33 +import org.onosproject.mastership.MastershipService;
34 +import org.onosproject.net.DeviceId;
35 +import org.onosproject.net.behaviour.Pipeliner;
36 +import org.onosproject.net.behaviour.PipelinerContext;
37 +import org.onosproject.net.device.DeviceEvent;
38 +import org.onosproject.net.device.DeviceListener;
39 +import org.onosproject.net.device.DeviceService;
40 +import org.onosproject.net.driver.DefaultDriverProviderService;
41 +import org.onosproject.net.driver.DriverHandler;
42 +import org.onosproject.net.driver.DriverService;
43 +import org.onosproject.net.flow.FlowRuleService;
44 +import org.onosproject.net.flow.criteria.Criterion;
45 +import org.onosproject.net.flow.instructions.Instruction;
46 +import org.onosproject.net.flowobjective.FilteringObjective;
47 +import org.onosproject.net.flowobjective.FlowObjectiveService;
48 +import org.onosproject.net.flowobjective.FlowObjectiveStore;
49 +import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
50 +import org.onosproject.net.flowobjective.ForwardingObjective;
51 +import org.onosproject.net.flowobjective.NextObjective;
52 +import org.onosproject.net.flowobjective.Objective;
53 +import org.onosproject.net.flowobjective.ObjectiveError;
54 +import org.onosproject.net.flowobjective.ObjectiveEvent;
55 +import org.onosproject.net.group.GroupService;
56 +import org.slf4j.Logger;
57 +import org.slf4j.LoggerFactory;
58 +
59 +import java.util.List;
60 +import java.util.Map;
61 +import java.util.Set;
62 +import java.util.concurrent.ExecutorService;
63 +
64 +import static com.google.common.base.Preconditions.checkNotNull;
65 +import static java.util.concurrent.Executors.newFixedThreadPool;
66 +import static org.onlab.util.Tools.groupedThreads;
67 +import static org.onosproject.security.AppGuard.checkPermission;
68 +
69 +
70 +/**
71 + * Provides implementation of the flow objective programming service with composition feature.
72 + *
73 + * Note: This is an experimental, alternative implementation of the FlowObjectiveManager
74 + * that supports composition. It can be enabled by setting the enable flag below to true,
75 + * and you should also add "enabled = false" to the FlowObjectiveManager.
76 + *
77 + * The implementation relies a FlowObjectiveCompositionTree that is not yet distributed,
78 + * so it will not have high availability and may break if device mastership changes.
79 + * Therefore, it is safest to use this component in a single instance scenario.
80 + * This comment will be removed when a distributed implementation is available.
81 + */
82 +@Component(immediate = true, enabled = false)
83 +@Service
84 +public class FlowObjectiveCompositionManager implements FlowObjectiveService {
85 +
86 + public enum PolicyOperator {
87 + Parallel,
88 + Sequential,
89 + Override,
90 + Application
91 + }
92 +
93 + public static final int INSTALL_RETRY_ATTEMPTS = 5;
94 + public static final long INSTALL_RETRY_INTERVAL = 1000; // ms
95 +
96 + private final Logger log = LoggerFactory.getLogger(getClass());
97 +
98 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 + protected DriverService driverService;
100 +
101 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 + protected DeviceService deviceService;
103 +
104 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 + protected MastershipService mastershipService;
106 +
107 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 + protected ClusterService clusterService;
109 +
110 + // Note: The following dependencies are added on behalf of the pipeline
111 + // driver behaviours to assure these services are available for their
112 + // initialization.
113 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 + protected FlowRuleService flowRuleService;
115 +
116 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 + protected GroupService groupService;
118 +
119 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 + protected FlowObjectiveStore flowObjectiveStore;
121 +
122 + // Note: This must remain an optional dependency to allow re-install of default drivers.
123 + // Note: For now disabled until we can move to OPTIONAL_UNARY dependency
124 + // @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
125 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 + protected DefaultDriverProviderService defaultDriverService;
127 +
128 + private final FlowObjectiveStoreDelegate delegate = new InternalStoreDelegate();
129 +
130 + private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap();
131 + private final Map<DeviceId, Pipeliner> pipeliners = Maps.newConcurrentMap();
132 +
133 + private final PipelinerContext context = new InnerPipelineContext();
134 + private final MastershipListener mastershipListener = new InnerMastershipListener();
135 + private final DeviceListener deviceListener = new InnerDeviceListener();
136 +
137 + protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
138 +
139 + private Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap();
140 +
141 + private ExecutorService executorService;
142 +
143 + private String policy;
144 + private Map<DeviceId, FlowObjectiveCompositionTree> deviceCompositionTreeMap;
145 +
146 + @Activate
147 + protected void activate() {
148 + executorService = newFixedThreadPool(4, groupedThreads("onos/objective-installer", "%d"));
149 + flowObjectiveStore.setDelegate(delegate);
150 + mastershipService.addListener(mastershipListener);
151 + deviceService.addListener(deviceListener);
152 + deviceService.getDevices().forEach(device -> setupPipelineHandler(device.id()));
153 + deviceCompositionTreeMap = Maps.newConcurrentMap();
154 + log.info("Started");
155 + }
156 +
157 + @Deactivate
158 + protected void deactivate() {
159 + flowObjectiveStore.unsetDelegate(delegate);
160 + mastershipService.removeListener(mastershipListener);
161 + deviceService.removeListener(deviceListener);
162 + executorService.shutdown();
163 + pipeliners.clear();
164 + driverHandlers.clear();
165 + deviceCompositionTreeMap.clear();
166 + log.info("Stopped");
167 + }
168 +
169 + /**
170 + * Task that passes the flow objective down to the driver. The task will
171 + * make a few attempts to find the appropriate driver, then eventually give
172 + * up and report an error if no suitable driver could be found.
173 + */
174 + private class ObjectiveInstaller implements Runnable {
175 + private final DeviceId deviceId;
176 + private final Objective objective;
177 +
178 + private final int numAttempts;
179 +
180 + public ObjectiveInstaller(DeviceId deviceId, Objective objective) {
181 + this(deviceId, objective, 1);
182 + }
183 +
184 + public ObjectiveInstaller(DeviceId deviceId, Objective objective, int attemps) {
185 + this.deviceId = checkNotNull(deviceId);
186 + this.objective = checkNotNull(objective);
187 + this.numAttempts = checkNotNull(attemps);
188 + }
189 +
190 + @Override
191 + public void run() {
192 + try {
193 + Pipeliner pipeliner = getDevicePipeliner(deviceId);
194 +
195 + if (pipeliner != null) {
196 + if (objective instanceof NextObjective) {
197 + pipeliner.next((NextObjective) objective);
198 + } else if (objective instanceof ForwardingObjective) {
199 + pipeliner.forward((ForwardingObjective) objective);
200 + } else {
201 + pipeliner.filter((FilteringObjective) objective);
202 + }
203 + } else if (numAttempts < INSTALL_RETRY_ATTEMPTS) {
204 + Thread.sleep(INSTALL_RETRY_INTERVAL);
205 + executorService.submit(new ObjectiveInstaller(deviceId, objective, numAttempts + 1));
206 + } else {
207 + // Otherwise we've tried a few times and failed, report an
208 + // error back to the user.
209 + objective.context().ifPresent(
210 + c -> c.onError(objective, ObjectiveError.DEVICEMISSING));
211 + }
212 + } catch (Exception e) {
213 + log.warn("Exception while installing flow objective", e);
214 + }
215 + }
216 + }
217 +
218 + @Override
219 + public void filter(DeviceId deviceId, FilteringObjective filteringObjective) {
220 + checkPermission(Permission.FLOWRULE_WRITE);
221 +
222 + List<FilteringObjective> filteringObjectives
223 + = this.deviceCompositionTreeMap.get(deviceId).updateFilter(filteringObjective);
224 + for (FilteringObjective tmp : filteringObjectives) {
225 + executorService.submit(new ObjectiveInstaller(deviceId, tmp));
226 + }
227 + }
228 +
229 + @Override
230 + public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
231 + checkPermission(Permission.FLOWRULE_WRITE);
232 +
233 + if (queueObjective(deviceId, forwardingObjective)) {
234 + return;
235 + }
236 + List<ForwardingObjective> forwardingObjectives
237 + = this.deviceCompositionTreeMap.get(deviceId).updateForward(forwardingObjective);
238 + for (ForwardingObjective tmp : forwardingObjectives) {
239 + executorService.submit(new ObjectiveInstaller(deviceId, tmp));
240 + }
241 + }
242 +
243 + @Override
244 + public void next(DeviceId deviceId, NextObjective nextObjective) {
245 + checkPermission(Permission.FLOWRULE_WRITE);
246 +
247 + List<NextObjective> nextObjectives = this.deviceCompositionTreeMap.get(deviceId).updateNext(nextObjective);
248 + for (NextObjective tmp : nextObjectives) {
249 + executorService.submit(new ObjectiveInstaller(deviceId, tmp));
250 + }
251 + }
252 +
253 + @Override
254 + public int allocateNextId() {
255 + checkPermission(Permission.FLOWRULE_WRITE);
256 +
257 + return flowObjectiveStore.allocateNextId();
258 + }
259 +
260 + private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) {
261 + if (fwd.nextId() != null &&
262 + flowObjectiveStore.getNextGroup(fwd.nextId()) == null) {
263 + log.trace("Queuing forwarding objective for nextId {}", fwd.nextId());
264 + if (pendingForwards.putIfAbsent(fwd.nextId(),
265 + Sets.newHashSet(new PendingNext(deviceId, fwd))) != null) {
266 + Set<PendingNext> pending = pendingForwards.get(fwd.nextId());
267 + pending.add(new PendingNext(deviceId, fwd));
268 + }
269 + return true;
270 + }
271 + return false;
272 + }
273 +
274 + @Override
275 + public void initPolicy(String policy) {
276 + this.policy = policy;
277 + deviceService.getDevices().forEach(device ->
278 + this.deviceCompositionTreeMap.put(device.id(), FlowObjectiveCompositionUtil.parsePolicyString(policy)));
279 + log.info("Initialize policy {}", policy);
280 + }
281 +
282 + // Retrieves the device pipeline behaviour from the cache.
283 + private Pipeliner getDevicePipeliner(DeviceId deviceId) {
284 + Pipeliner pipeliner = pipeliners.get(deviceId);
285 + return pipeliner;
286 + }
287 +
288 + private void setupPipelineHandler(DeviceId deviceId) {
289 + if (defaultDriverService == null) {
290 + // We're not ready to go to work yet.
291 + return;
292 + }
293 +
294 + // Attempt to lookup the handler in the cache
295 + DriverHandler handler = driverHandlers.get(deviceId);
296 + if (handler == null) {
297 + try {
298 + // Otherwise create it and if it has pipeline behaviour, cache it
299 + handler = driverService.createHandler(deviceId);
300 + if (!handler.driver().hasBehaviour(Pipeliner.class)) {
301 + log.warn("Pipeline behaviour not supported for device {}",
302 + deviceId);
303 + return;
304 + }
305 + } catch (ItemNotFoundException e) {
306 + log.warn("No applicable driver for device {}", deviceId);
307 + return;
308 + }
309 +
310 + driverHandlers.put(deviceId, handler);
311 + }
312 +
313 + // Always (re)initialize the pipeline behaviour
314 + log.info("Driver {} bound to device {} ... initializing driver",
315 + handler.driver().name(), deviceId);
316 + Pipeliner pipeliner = handler.behaviour(Pipeliner.class);
317 + pipeliner.init(deviceId, context);
318 + pipeliners.putIfAbsent(deviceId, pipeliner);
319 + }
320 +
321 + // Triggers driver setup when the local node becomes a device master.
322 + private class InnerMastershipListener implements MastershipListener {
323 + @Override
324 + public void event(MastershipEvent event) {
325 + switch (event.type()) {
326 + case MASTER_CHANGED:
327 + log.debug("mastership changed on device {}", event.subject());
328 + if (deviceService.isAvailable(event.subject())) {
329 + setupPipelineHandler(event.subject());
330 + }
331 + break;
332 + case BACKUPS_CHANGED:
333 + break;
334 + default:
335 + break;
336 + }
337 + }
338 + }
339 +
340 + // Triggers driver setup when a device is (re)detected.
341 + private class InnerDeviceListener implements DeviceListener {
342 + @Override
343 + public void event(DeviceEvent event) {
344 + switch (event.type()) {
345 + case DEVICE_ADDED:
346 + case DEVICE_AVAILABILITY_CHANGED:
347 + log.debug("Device either added or availability changed {}",
348 + event.subject().id());
349 + if (deviceService.isAvailable(event.subject().id())) {
350 + log.debug("Device is now available {}", event.subject().id());
351 + setupPipelineHandler(event.subject().id());
352 + }
353 + break;
354 + case DEVICE_UPDATED:
355 + break;
356 + case DEVICE_REMOVED:
357 + break;
358 + case DEVICE_SUSPENDED:
359 + break;
360 + case PORT_ADDED:
361 + break;
362 + case PORT_UPDATED:
363 + break;
364 + case PORT_REMOVED:
365 + break;
366 + default:
367 + break;
368 + }
369 + }
370 + }
371 +
372 + // Processing context for initializing pipeline driver behaviours.
373 + private class InnerPipelineContext implements PipelinerContext {
374 + @Override
375 + public ServiceDirectory directory() {
376 + return serviceDirectory;
377 + }
378 +
379 + @Override
380 + public FlowObjectiveStore store() {
381 + return flowObjectiveStore;
382 + }
383 + }
384 +
385 + private class InternalStoreDelegate implements FlowObjectiveStoreDelegate {
386 + @Override
387 + public void notify(ObjectiveEvent event) {
388 + log.debug("Received notification of obj event {}", event);
389 + Set<PendingNext> pending = pendingForwards.remove(event.subject());
390 +
391 + if (pending == null) {
392 + log.debug("Nothing pending for this obj event");
393 + return;
394 + }
395 +
396 + log.debug("Processing pending forwarding objectives {}", pending.size());
397 +
398 + pending.forEach(p -> getDevicePipeliner(p.deviceId())
399 + .forward(p.forwardingObjective()));
400 +
401 + }
402 + }
403 +
404 + /**
405 + * Data class used to hold a pending forwarding objective that could not
406 + * be processed because the associated next object was not present.
407 + */
408 + private class PendingNext {
409 + private final DeviceId deviceId;
410 + private final ForwardingObjective fwd;
411 +
412 + public PendingNext(DeviceId deviceId, ForwardingObjective fwd) {
413 + this.deviceId = deviceId;
414 + this.fwd = fwd;
415 + }
416 +
417 + public DeviceId deviceId() {
418 + return deviceId;
419 + }
420 +
421 + public ForwardingObjective forwardingObjective() {
422 + return fwd;
423 + }
424 + }
425 +
426 + public static String forwardingObjectiveToString(ForwardingObjective forwardingObjective) {
427 + String str = forwardingObjective.priority() + " ";
428 + str += "selector( ";
429 + for (Criterion criterion : forwardingObjective.selector().criteria()) {
430 + str += criterion + " ";
431 + }
432 + str += ") treatment( ";
433 + for (Instruction instruction : forwardingObjective.treatment().allInstructions()) {
434 + str += instruction + " ";
435 + }
436 + str += ")";
437 + return str;
438 + }
439 +}
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.flowobjective.impl.composition;
17 +
18 +import org.onosproject.net.flowobjective.FilteringObjective;
19 +import org.onosproject.net.flowobjective.ForwardingObjective;
20 +import org.onosproject.net.flowobjective.NextObjective;
21 +
22 +import java.util.ArrayList;
23 +import java.util.Collection;
24 +import java.util.List;
25 +
26 +/**
27 + * Provides a policy tree to store all flow tables for each device.
28 + *
29 + * Note: This class uses in-memory structures and is not yet distributed.
30 + */
31 +public class FlowObjectiveCompositionTree {
32 +
33 + public FlowObjectiveCompositionManager.PolicyOperator operator;
34 + public FlowObjectiveCompositionTree leftChild;
35 + public FlowObjectiveCompositionTree rightChild;
36 + public short applicationId;
37 + protected FilterTable filterTable;
38 + protected ForwardTable forwardTable;
39 + protected NextTable nextTable;
40 +
41 + protected int priorityMultiplier;
42 + protected int priorityAddend;
43 +
44 + public FlowObjectiveCompositionTree(short applicationId) {
45 + this.operator = FlowObjectiveCompositionManager.PolicyOperator.Application;
46 + this.leftChild = null;
47 + this.rightChild = null;
48 + this.applicationId = applicationId;
49 + this.filterTable = new FilterTable();
50 + this.forwardTable = new ForwardTable();
51 + this.nextTable = new NextTable();
52 + this.priorityMultiplier = 10;
53 + this.priorityAddend = 10;
54 + }
55 +
56 + public FlowObjectiveCompositionTree(Character ch) {
57 + switch (ch) {
58 + case '+':
59 + this.operator = FlowObjectiveCompositionManager.PolicyOperator.Parallel;
60 + break;
61 + case '>':
62 + this.operator = FlowObjectiveCompositionManager.PolicyOperator.Sequential;
63 + break;
64 + case '/':
65 + this.operator = FlowObjectiveCompositionManager.PolicyOperator.Override;
66 + break;
67 + default:
68 + this.operator = FlowObjectiveCompositionManager.PolicyOperator.Application;
69 + break;
70 + }
71 + this.leftChild = null;
72 + this.rightChild = null;
73 + this.applicationId = (short) -1;
74 + this.filterTable = new FilterTable();
75 + this.forwardTable = new ForwardTable();
76 + this.nextTable = new NextTable();
77 + this.priorityMultiplier = 10;
78 + this.priorityAddend = 10;
79 + }
80 +
81 + protected List<FilteringObjective> updateFilter(FilteringObjective filteringObjective) {
82 + switch (this.operator) {
83 + case Parallel:
84 + return updateFilterParallel(filteringObjective);
85 + case Sequential:
86 + return updateFilterSequential(filteringObjective);
87 + case Override:
88 + return updateFilterOverride(filteringObjective);
89 + case Application:
90 + if (filteringObjective.appId().id() == this.applicationId) {
91 + return this.filterTable.updateFilter(filteringObjective);
92 + } else {
93 + return new ArrayList<>();
94 + }
95 + default:
96 + return new ArrayList<>();
97 + }
98 + }
99 +
100 + // Parallel composition: the filter set is the union of the children
101 + protected List<FilteringObjective> updateFilterParallel(FilteringObjective filteringObjective) {
102 + List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective);
103 + List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective);
104 +
105 + List<FilteringObjective> updates = new ArrayList<>();
106 + updates.addAll(leftUpdates);
107 + updates.addAll(rightUpdates);
108 +
109 + return this.filterTable.updateFilter(updates);
110 + }
111 +
112 + // Sequential composition: the filter set is the filter set of the left child
113 + protected List<FilteringObjective> updateFilterSequential(FilteringObjective filteringObjective) {
114 + List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective);
115 + List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective);
116 + return this.filterTable.updateFilter(leftUpdates);
117 + }
118 +
119 + // Override composition: the filter set is the filter set of the left child
120 + protected List<FilteringObjective> updateFilterOverride(FilteringObjective filteringObjective) {
121 + List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective);
122 + List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective);
123 + return this.filterTable.updateFilter(leftUpdates);
124 + }
125 +
126 + public List<ForwardingObjective> updateForward(ForwardingObjective forwardingObjective) {
127 + return this.updateForwardNode(forwardingObjective).toForwardingObjectiveList();
128 + }
129 +
130 + public ForwardUpdateTable updateForwardNode(ForwardingObjective forwardingObjective) {
131 + switch (this.operator) {
132 + case Parallel:
133 + case Sequential:
134 + case Override:
135 + return updateForwardComposition(forwardingObjective);
136 + case Application:
137 + if (forwardingObjective.appId().id() == this.applicationId) {
138 + return this.forwardTable.updateForward(forwardingObjective);
139 + } else {
140 + return (new ForwardUpdateTable());
141 + }
142 + default:
143 + return (new ForwardUpdateTable());
144 + }
145 + }
146 +
147 + protected ForwardUpdateTable updateForwardComposition(ForwardingObjective forwardingObjective) {
148 + ForwardUpdateTable leftUpdates = this.leftChild.updateForwardNode(forwardingObjective);
149 + ForwardUpdateTable rightUpdates = this.rightChild.updateForwardNode(forwardingObjective);
150 +
151 + List<ForwardingObjective> addUpdates = new ArrayList<>();
152 + List<ForwardingObjective> removeUpdates = new ArrayList<>();
153 + // Handle ADD
154 + if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel
155 + || this.operator == FlowObjectiveCompositionManager.PolicyOperator.Sequential) {
156 + for (ForwardingObjective fo1 : leftUpdates.addObjectives) {
157 + for (ForwardingObjective fo2 : this.rightChild.forwardTable.getForwardingObjectives()) {
158 + ForwardingObjective composedFo = null;
159 + if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel) {
160 + composedFo = FlowObjectiveCompositionUtil.composeParallel(fo1, fo2);
161 + } else {
162 + composedFo = FlowObjectiveCompositionUtil.composeSequential(fo1, fo2, this.priorityMultiplier);
163 + }
164 + if (composedFo != null) {
165 + addUpdates.add(composedFo);
166 + this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo1, composedFo);
167 + this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo2, composedFo);
168 + }
169 + }
170 + }
171 + Collection<ForwardingObjective> leftTableWithoutAdd = FlowObjectiveCompositionUtil
172 + .minusForwardingObjectives(this.leftChild.forwardTable.getForwardingObjectives(),
173 + leftUpdates.addObjectives);
174 + for (ForwardingObjective fo1 : leftTableWithoutAdd) {
175 + for (ForwardingObjective fo2 : rightUpdates.addObjectives) {
176 + ForwardingObjective composedFo = null;
177 + if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel) {
178 + composedFo = FlowObjectiveCompositionUtil.composeParallel(fo1, fo2);
179 + } else {
180 + composedFo = FlowObjectiveCompositionUtil.composeSequential(fo1, fo2, this.priorityMultiplier);
181 + }
182 + if (composedFo != null) {
183 + addUpdates.add(composedFo);
184 + this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo1, composedFo);
185 + this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo2, composedFo);
186 + }
187 + }
188 + }
189 + } else {
190 + for (ForwardingObjective fo : leftUpdates.addObjectives) {
191 + ForwardingObjective composedFo = FlowObjectiveCompositionUtil.composeOverride(fo, this.priorityAddend);
192 + addUpdates.add(composedFo);
193 + this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo, composedFo);
194 + }
195 + for (ForwardingObjective fo : rightUpdates.addObjectives) {
196 + ForwardingObjective composedFo = FlowObjectiveCompositionUtil.composeOverride(fo, 0);
197 + addUpdates.add(composedFo);
198 + this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo, composedFo);
199 + }
200 + }
201 +
202 + // Handle REMOVE
203 + for (ForwardingObjective fo : leftUpdates.removeObjectives) {
204 + List<ForwardingObjective> fos = this.leftChild.forwardTable
205 + .getGeneratedParentForwardingObjectiveForRemove(fo);
206 + removeUpdates.addAll(fos);
207 + }
208 + this.leftChild.forwardTable.deleteGeneratedParentForwardingObjective(leftUpdates.removeObjectives);
209 + for (ForwardingObjective fo : rightUpdates.removeObjectives) {
210 + List<ForwardingObjective> fos = this.rightChild.forwardTable
211 + .getGeneratedParentForwardingObjectiveForRemove(fo);
212 + removeUpdates.addAll(fos);
213 + }
214 + this.rightChild.forwardTable.deleteGeneratedParentForwardingObjective(rightUpdates.removeObjectives);
215 +
216 + ForwardUpdateTable updates = new ForwardUpdateTable();
217 + updates.addUpdateTable(this.forwardTable.updateForward(addUpdates));
218 + updates.addUpdateTable(this.forwardTable.updateForward(removeUpdates));
219 + return updates;
220 + }
221 +
222 + public List<NextObjective> updateNext(NextObjective nextObjective) {
223 + switch (this.operator) {
224 + case Parallel:
225 + case Sequential:
226 + case Override:
227 + return updateNextComposition(nextObjective);
228 + case Application:
229 + if (nextObjective.appId().id() == this.applicationId) {
230 + return this.nextTable.updateNext(nextObjective);
231 + } else {
232 + return new ArrayList<>();
233 + }
234 + default:
235 + return new ArrayList<>();
236 + }
237 + }
238 +
239 + // Next: the union of the children
240 + protected List<NextObjective> updateNextComposition(NextObjective nextObjective) {
241 + List<NextObjective> leftUpdates = this.leftChild.updateNext(nextObjective);
242 + List<NextObjective> rightUpdates = this.rightChild.updateNext(nextObjective);
243 +
244 + List<NextObjective> updates = new ArrayList<>();
245 + updates.addAll(leftUpdates);
246 + updates.addAll(rightUpdates);
247 +
248 + return this.nextTable.updateNext(updates);
249 + }
250 +
251 + @Override
252 + public String toString() {
253 + String str = null;
254 + switch (this.operator) {
255 + case Parallel:
256 + str = "(" + this.leftChild + "+" + this.rightChild + ")";
257 + break;
258 + case Sequential:
259 + str = "(" + this.leftChild + ">" + this.rightChild + ")";
260 + break;
261 + case Override:
262 + str = "(" + this.leftChild + "/" + this.rightChild + ")";
263 + break;
264 + default:
265 + str = " " + applicationId + " ";
266 + break;
267 + }
268 + return str;
269 + }
270 +
271 +}
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.flowobjective.impl.composition;
17 +
18 +import org.onlab.packet.IpPrefix;
19 +import org.onosproject.net.flow.DefaultTrafficSelector;
20 +import org.onosproject.net.flow.DefaultTrafficTreatment;
21 +import org.onosproject.net.flow.TrafficSelector;
22 +import org.onosproject.net.flow.TrafficTreatment;
23 +import org.onosproject.net.flow.criteria.Criterion;
24 +import org.onosproject.net.flow.criteria.LambdaCriterion;
25 +import org.onosproject.net.flow.criteria.OchSignalCriterion;
26 +import org.onosproject.net.flow.criteria.EthCriterion;
27 +import org.onosproject.net.flow.criteria.VlanIdCriterion;
28 +import org.onosproject.net.flow.criteria.VlanPcpCriterion;
29 +import org.onosproject.net.flow.criteria.MplsCriterion;
30 +import org.onosproject.net.flow.criteria.IPCriterion;
31 +import org.onosproject.net.flow.criteria.Criteria;
32 +import org.onosproject.net.flow.instructions.Instruction;
33 +import org.onosproject.net.flow.instructions.L0ModificationInstruction;
34 +import org.onosproject.net.flow.instructions.L2ModificationInstruction;
35 +import org.onosproject.net.flow.instructions.L3ModificationInstruction;
36 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
37 +import org.onosproject.net.flowobjective.ForwardingObjective;
38 +
39 +import java.util.ArrayList;
40 +import java.util.Collection;
41 +import java.util.HashMap;
42 +import java.util.HashSet;
43 +import java.util.List;
44 +import java.util.Map;
45 +import java.util.Set;
46 +import java.util.Stack;
47 +
48 +/**
49 + * Provide util functions for FlowObjectiveComposition.
50 + */
51 +public final class FlowObjectiveCompositionUtil {
52 +
53 + private FlowObjectiveCompositionUtil() {}
54 +
55 + // only work with VERSATILE
56 + public static ForwardingObjective composeParallel(ForwardingObjective fo1, ForwardingObjective fo2) {
57 +
58 + TrafficSelector trafficSelector = intersectTrafficSelector(fo1.selector(), fo2.selector());
59 + if (trafficSelector == null) {
60 + return null;
61 + }
62 +
63 + TrafficTreatment trafficTreatment = unionTrafficTreatment(fo1.treatment(), fo2.treatment());
64 +
65 + return DefaultForwardingObjective.builder()
66 + .fromApp(fo1.appId())
67 + .makePermanent()
68 + .withFlag(ForwardingObjective.Flag.VERSATILE)
69 + .withPriority(fo1.priority() + fo2.priority())
70 + .withSelector(trafficSelector)
71 + .withTreatment(trafficTreatment)
72 + .add();
73 + }
74 +
75 + public static ForwardingObjective composeSequential(ForwardingObjective fo1,
76 + ForwardingObjective fo2,
77 + int priorityMultiplier) {
78 +
79 + TrafficSelector revertTrafficSelector = revertTreatmentSelector(fo1.treatment(), fo2.selector());
80 + if (revertTrafficSelector == null) {
81 + return null;
82 + }
83 +
84 + TrafficSelector trafficSelector = intersectTrafficSelector(fo1.selector(), revertTrafficSelector);
85 + if (trafficSelector == null) {
86 + return null;
87 + }
88 +
89 + TrafficTreatment trafficTreatment = unionTrafficTreatment(fo1.treatment(), fo2.treatment());
90 +
91 + return DefaultForwardingObjective.builder()
92 + .fromApp(fo1.appId())
93 + .makePermanent()
94 + .withFlag(ForwardingObjective.Flag.VERSATILE)
95 + .withPriority(fo1.priority() * priorityMultiplier + fo2.priority())
96 + .withSelector(trafficSelector)
97 + .withTreatment(trafficTreatment)
98 + .add();
99 + }
100 +
101 + public static ForwardingObjective composeOverride(ForwardingObjective fo, int priorityAddend) {
102 + return DefaultForwardingObjective.builder()
103 + .fromApp(fo.appId())
104 + .makePermanent()
105 + .withFlag(fo.flag())
106 + .withPriority(fo.priority() + priorityAddend)
107 + .withSelector(fo.selector())
108 + .withTreatment(fo.treatment())
109 + .add();
110 + }
111 +
112 + public static TrafficSelector intersectTrafficSelector(TrafficSelector ts1, TrafficSelector ts2) {
113 +
114 + TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
115 +
116 + Set<Criterion.Type> ts1IntersectTs2 = getTypeSet(ts1);
117 + ts1IntersectTs2.retainAll(getTypeSet(ts2));
118 + for (Criterion.Type type : ts1IntersectTs2) {
119 + Criterion criterion = intersectCriterion(ts1.getCriterion(type), ts2.getCriterion(type));
120 + if (criterion == null) {
121 + return null;
122 + } else {
123 + selectorBuilder.add(criterion);
124 + }
125 + }
126 +
127 + Set<Criterion.Type> ts1MinusTs2 = getTypeSet(ts1);
128 + ts1MinusTs2.removeAll(getTypeSet(ts2));
129 + for (Criterion.Type type : ts1MinusTs2) {
130 + selectorBuilder.add(ts1.getCriterion(type));
131 + }
132 +
133 + Set<Criterion.Type> ts2MinusTs1 = getTypeSet(ts2);
134 + ts2MinusTs1.removeAll(getTypeSet(ts1));
135 + for (Criterion.Type type : ts2MinusTs1) {
136 + selectorBuilder.add(ts2.getCriterion(type));
137 + }
138 +
139 + return selectorBuilder.build();
140 + }
141 +
142 + public static TrafficTreatment unionTrafficTreatment(TrafficTreatment tt1, TrafficTreatment tt2) {
143 +
144 + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
145 +
146 + for (Instruction instruction : tt1.allInstructions()) {
147 + treatmentBuilder.add(instruction);
148 + }
149 +
150 + for (Instruction instruction : tt2.allInstructions()) {
151 + treatmentBuilder.add(instruction);
152 + }
153 +
154 + return treatmentBuilder.build();
155 + }
156 +
157 + public static TrafficSelector revertTreatmentSelector(TrafficTreatment trafficTreatment,
158 + TrafficSelector trafficSelector) {
159 +
160 + TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
161 +
162 + Map<Criterion.Type, Criterion> criterionMap = new HashMap<>();
163 + for (Criterion criterion : trafficSelector.criteria()) {
164 + criterionMap.put(criterion.type(), criterion);
165 + }
166 +
167 + for (Instruction instruction : trafficTreatment.allInstructions()) {
168 + switch (instruction.type()) {
169 + case DROP:
170 + return null;
171 + case OUTPUT:
172 + break;
173 + case GROUP:
174 + break;
175 + case L0MODIFICATION: {
176 + L0ModificationInstruction l0 = (L0ModificationInstruction) instruction;
177 + switch (l0.subtype()) {
178 + case LAMBDA:
179 + if (criterionMap.containsKey(Criterion.Type.OCH_SIGID)) {
180 + if (((LambdaCriterion) criterionMap.get((Criterion.Type.OCH_SIGID))).lambda()
181 + == ((L0ModificationInstruction.ModLambdaInstruction) l0).lambda()) {
182 + criterionMap.remove(Criterion.Type.OCH_SIGID);
183 + } else {
184 + return null;
185 + }
186 + } else {
187 + break;
188 + }
189 + case OCH:
190 + if (criterionMap.containsKey(Criterion.Type.OCH_SIGID)) {
191 + if (((OchSignalCriterion) criterionMap.get((Criterion.Type.OCH_SIGID))).lambda()
192 + .equals(((L0ModificationInstruction.ModOchSignalInstruction) l0).lambda())) {
193 + criterionMap.remove(Criterion.Type.OCH_SIGID);
194 + } else {
195 + return null;
196 + }
197 + } else {
198 + break;
199 + }
200 + default:
201 + break;
202 + }
203 + break;
204 + }
205 + case L2MODIFICATION: {
206 + L2ModificationInstruction l2 = (L2ModificationInstruction) instruction;
207 + switch (l2.subtype()) {
208 + case ETH_SRC:
209 + if (criterionMap.containsKey(Criterion.Type.ETH_SRC)) {
210 + if (((EthCriterion) criterionMap.get((Criterion.Type.ETH_SRC))).mac()
211 + .equals(((L2ModificationInstruction.ModEtherInstruction) l2).mac())) {
212 + criterionMap.remove(Criterion.Type.ETH_SRC);
213 + } else {
214 + return null;
215 + }
216 + } else {
217 + break;
218 + }
219 + case ETH_DST:
220 + if (criterionMap.containsKey(Criterion.Type.ETH_DST)) {
221 + if (((EthCriterion) criterionMap.get((Criterion.Type.ETH_DST))).mac()
222 + .equals(((L2ModificationInstruction.ModEtherInstruction) l2).mac())) {
223 + criterionMap.remove(Criterion.Type.ETH_DST);
224 + } else {
225 + return null;
226 + }
227 + } else {
228 + break;
229 + }
230 + case VLAN_ID:
231 + if (criterionMap.containsKey(Criterion.Type.VLAN_VID)) {
232 + if (((VlanIdCriterion) criterionMap.get((Criterion.Type.VLAN_VID))).vlanId()
233 + .equals(((L2ModificationInstruction.ModVlanIdInstruction) l2).vlanId())) {
234 + criterionMap.remove(Criterion.Type.VLAN_VID);
235 + } else {
236 + return null;
237 + }
238 + } else {
239 + break;
240 + }
241 + case VLAN_PCP:
242 + if (criterionMap.containsKey(Criterion.Type.VLAN_PCP)) {
243 + if (((VlanPcpCriterion) criterionMap.get((Criterion.Type.VLAN_PCP))).priority()
244 + == ((L2ModificationInstruction.ModVlanPcpInstruction) l2).vlanPcp()) {
245 + criterionMap.remove(Criterion.Type.VLAN_PCP);
246 + } else {
247 + return null;
248 + }
249 + } else {
250 + break;
251 + }
252 + case MPLS_LABEL:
253 + if (criterionMap.containsKey(Criterion.Type.MPLS_LABEL)) {
254 + if (((MplsCriterion) criterionMap.get((Criterion.Type.MPLS_LABEL))).label()
255 + .equals(((L2ModificationInstruction.ModMplsLabelInstruction) l2).label())) {
256 + criterionMap.remove(Criterion.Type.ETH_DST);
257 + } else {
258 + return null;
259 + }
260 + } else {
261 + break;
262 + }
263 + default:
264 + break;
265 + }
266 + break;
267 + }
268 + case TABLE:
269 + break;
270 + case L3MODIFICATION: {
271 + L3ModificationInstruction l3 = (L3ModificationInstruction) instruction;
272 + switch (l3.subtype()) {
273 + case IPV4_SRC:
274 + if (criterionMap.containsKey(Criterion.Type.IPV4_SRC)) {
275 + if (((IPCriterion) criterionMap.get(Criterion.Type.IPV4_SRC)).ip()
276 + .contains(((L3ModificationInstruction.ModIPInstruction) l3).ip())) {
277 + criterionMap.remove(Criterion.Type.IPV4_SRC);
278 + } else {
279 + return null;
280 + }
281 + } else {
282 + break;
283 + }
284 + case IPV4_DST:
285 + if (criterionMap.containsKey(Criterion.Type.IPV4_DST)) {
286 + if (((IPCriterion) criterionMap.get(Criterion.Type.IPV4_DST)).ip()
287 + .contains(((L3ModificationInstruction.ModIPInstruction) l3).ip())) {
288 + criterionMap.remove(Criterion.Type.IPV4_DST);
289 + } else {
290 + return null;
291 + }
292 + } else {
293 + break;
294 + }
295 + case IPV6_SRC:
296 + if (criterionMap.containsKey(Criterion.Type.IPV6_SRC)) {
297 + if (((IPCriterion) criterionMap.get(Criterion.Type.IPV6_SRC)).ip()
298 + .contains(((L3ModificationInstruction.ModIPInstruction) l3).ip())) {
299 + criterionMap.remove(Criterion.Type.IPV6_SRC);
300 + } else {
301 + return null;
302 + }
303 + } else {
304 + break;
305 + }
306 + case IPV6_DST:
307 + if (criterionMap.containsKey(Criterion.Type.IPV6_DST)) {
308 + if (((IPCriterion) criterionMap.get(Criterion.Type.IPV6_DST)).ip()
309 + .contains(((L3ModificationInstruction.ModIPInstruction) l3).ip())) {
310 + criterionMap.remove(Criterion.Type.IPV6_DST);
311 + } else {
312 + return null;
313 + }
314 + } else {
315 + break;
316 + }
317 + case IPV6_FLABEL:
318 + if (criterionMap.containsKey(Criterion.Type.IPV6_FLABEL)) {
319 + if (((IPCriterion) criterionMap.get(Criterion.Type.IPV6_FLABEL)).ip()
320 + .equals(((L3ModificationInstruction.ModIPv6FlowLabelInstruction) l3)
321 + .flowLabel())) {
322 + criterionMap.remove(Criterion.Type.IPV4_SRC);
323 + } else {
324 + return null;
325 + }
326 + } else {
327 + break;
328 + }
329 + default:
330 + break;
331 + }
332 + break;
333 + }
334 + case METADATA:
335 + break;
336 + default:
337 + break;
338 + }
339 + }
340 +
341 + for (Criterion criterion : criterionMap.values()) {
342 + selectorBuilder.add(criterion);
343 + }
344 +
345 + return selectorBuilder.build();
346 + }
347 +
348 + public static Set<Criterion.Type> getTypeSet(TrafficSelector trafficSelector) {
349 + Set<Criterion.Type> typeSet = new HashSet<>();
350 + for (Criterion criterion : trafficSelector.criteria()) {
351 + typeSet.add(criterion.type());
352 + }
353 + return typeSet;
354 + }
355 +
356 + public static Criterion intersectCriterion(Criterion c1, Criterion c2) {
357 + switch (c1.type()) {
358 + case IPV4_SRC: {
359 + IpPrefix ipPrefix = intersectIpPrefix(((IPCriterion) c1).ip(), ((IPCriterion) c2).ip());
360 + if (ipPrefix == null) {
361 + return null;
362 + } else {
363 + return Criteria.matchIPSrc(ipPrefix);
364 + }
365 + }
366 + case IPV4_DST: {
367 + IpPrefix ipPrefix = intersectIpPrefix(((IPCriterion) c1).ip(), ((IPCriterion) c2).ip());
368 + if (ipPrefix == null) {
369 + return null;
370 + } else {
371 + return Criteria.matchIPDst(ipPrefix);
372 + }
373 + }
374 + case IPV6_SRC: {
375 + IpPrefix ipPrefix = intersectIpPrefix(((IPCriterion) c1).ip(), ((IPCriterion) c2).ip());
376 + if (ipPrefix == null) {
377 + return null;
378 + } else {
379 + return Criteria.matchIPv6Src(ipPrefix);
380 + }
381 + }
382 + case IPV6_DST: {
383 + IpPrefix ipPrefix = intersectIpPrefix(((IPCriterion) c1).ip(), ((IPCriterion) c2).ip());
384 + if (ipPrefix == null) {
385 + return null;
386 + } else {
387 + return Criteria.matchIPv6Dst(ipPrefix);
388 + }
389 + }
390 + default:
391 + if (!c1.equals(c2)) {
392 + return null;
393 + } else {
394 + return c1;
395 + }
396 + }
397 + }
398 +
399 + public static IpPrefix intersectIpPrefix(IpPrefix ip1, IpPrefix ip2) {
400 + if (ip1.contains(ip2)) {
401 + return ip1;
402 + } else if (ip2.contains(ip1)) {
403 + return ip2;
404 + } else {
405 + return null;
406 + }
407 + }
408 +
409 + public static FlowObjectiveCompositionTree parsePolicyString(String policy) {
410 + List<FlowObjectiveCompositionTree> postfix = transformToPostfixForm(policy);
411 + return buildPolicyTree(postfix);
412 + }
413 +
414 + private static List<FlowObjectiveCompositionTree> transformToPostfixForm(String policy) {
415 + Stack<Character> stack = new Stack<>();
416 + List<FlowObjectiveCompositionTree> postfix = new ArrayList<>();
417 +
418 + for (int i = 0; i < policy.length(); i++) {
419 + Character ch = policy.charAt(i);
420 + if (Character.isDigit(ch)) {
421 +
422 + int applicationId = ch - '0';
423 + while (i + 1 < policy.length() && Character.isDigit(policy.charAt(i + 1))) {
424 + i++;
425 + applicationId = applicationId * 10 + policy.charAt(i) - '0';
426 + }
427 +
428 + postfix.add(new FlowObjectiveCompositionTree((short) applicationId));
429 + } else if (ch == '(') {
430 + stack.push(ch);
431 + } else if (ch == ')') {
432 + while (stack.peek() != '(') {
433 + postfix.add(new FlowObjectiveCompositionTree(stack.pop()));
434 + }
435 + stack.pop();
436 + } else {
437 + while (!stack.isEmpty() && compareOperatorPriority(stack.peek(), ch)) {
438 + postfix.add(new FlowObjectiveCompositionTree(stack.pop()));
439 + }
440 + stack.push(ch);
441 + }
442 + }
443 + while (!stack.isEmpty()) {
444 + postfix.add(new FlowObjectiveCompositionTree(stack.pop()));
445 + }
446 +
447 + return postfix;
448 + }
449 +
450 + private static boolean compareOperatorPriority(char peek, char cur) {
451 + if (peek == '/' && (cur == '+' || cur == '>' || cur == '/')) {
452 + return true;
453 + } else if (peek == '>' && (cur == '+' || cur == '>')) {
454 + return true;
455 + } else if (peek == '+' && cur == '+') {
456 + return true;
457 + }
458 + return false;
459 + }
460 +
461 + private static FlowObjectiveCompositionTree buildPolicyTree(List<FlowObjectiveCompositionTree> postfix) {
462 + Stack<FlowObjectiveCompositionTree> stack = new Stack<>();
463 + for (FlowObjectiveCompositionTree node : postfix) {
464 + if (node.operator == FlowObjectiveCompositionManager.PolicyOperator.Application) {
465 + stack.push(node);
466 + } else {
467 + node.rightChild = stack.pop();
468 + node.leftChild = stack.pop();
469 + stack.push(node);
470 + }
471 + }
472 + return stack.pop();
473 + }
474 +
475 + public static Collection<ForwardingObjective> minusForwardingObjectives(Collection<ForwardingObjective> fo1,
476 + Collection<ForwardingObjective> fo2) {
477 + Map<Integer, ForwardingObjective> map = new HashMap<>();
478 + for (ForwardingObjective fo : fo1) {
479 + map.put(fo.id(), fo);
480 + }
481 + for (ForwardingObjective fo : fo2) {
482 + map.remove(fo.id());
483 + }
484 + return map.values();
485 + }
486 +
487 +
488 +}
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.flowobjective.impl.composition;
17 +
18 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
19 +import org.onosproject.net.flowobjective.ForwardingObjective;
20 +
21 +import java.util.ArrayList;
22 +import java.util.Collection;
23 +import java.util.HashMap;
24 +import java.util.List;
25 +import java.util.Map;
26 +import java.util.Objects;
27 +
28 +/**
29 + * Provides a table to store Forward.
30 + */
31 +public class ForwardTable {
32 +
33 + protected Map<Integer, ForwardingObjective> forwardMap;
34 + protected Map<Integer, List<ForwardingObjective>> generatedParentForwardingObjectiveMap;
35 +
36 + public ForwardTable() {
37 + this.forwardMap = new HashMap<>();
38 + this.generatedParentForwardingObjectiveMap = new HashMap<>();
39 + }
40 +
41 + public ForwardUpdateTable updateForward(ForwardingObjective forwardingObjective) {
42 + ForwardUpdateTable updates = new ForwardUpdateTable();
43 + switch (forwardingObjective.op()) {
44 + case ADD:
45 + this.forwardMap.put(forwardingObjectiveHash(forwardingObjective), forwardingObjective);
46 + this.generatedParentForwardingObjectiveMap
47 + .put(forwardingObjectiveHash(forwardingObjective), new ArrayList<>());
48 + updates.addObjectives.add(forwardingObjective);
49 + break;
50 + case REMOVE:
51 + if (this.forwardMap.remove(forwardingObjectiveHash(forwardingObjective)) != null) {
52 + updates.removeObjectives.add(forwardingObjective);
53 + }
54 + break;
55 + default:
56 + break;
57 + }
58 + return updates;
59 + }
60 +
61 + public ForwardUpdateTable updateForward(List<ForwardingObjective> forwardingObjectives) {
62 + ForwardUpdateTable updates = new ForwardUpdateTable();
63 + for (ForwardingObjective forwardingObjective : forwardingObjectives) {
64 + updates.addUpdateTable(this.updateForward(forwardingObjective));
65 + }
66 + return updates;
67 + }
68 +
69 + public void addGeneratedParentForwardingObjective(ForwardingObjective child, ForwardingObjective parent) {
70 + this.generatedParentForwardingObjectiveMap.get(forwardingObjectiveHash(child)).add(parent);
71 + }
72 +
73 + public void deleteGeneratedParentForwardingObjective(List<ForwardingObjective> children) {
74 + for (ForwardingObjective fo : children) {
75 + this.generatedParentForwardingObjectiveMap.remove(forwardingObjectiveHash(fo));
76 + }
77 + }
78 +
79 + private List<ForwardingObjective> getGeneratedParentForwardingObjective(ForwardingObjective child) {
80 + return this.generatedParentForwardingObjectiveMap.get(forwardingObjectiveHash(child));
81 + }
82 +
83 + public List<ForwardingObjective> getGeneratedParentForwardingObjectiveForRemove(ForwardingObjective child) {
84 + List<ForwardingObjective> fos = this.generatedParentForwardingObjectiveMap.get(forwardingObjectiveHash(child));
85 + List<ForwardingObjective> removeFos = new ArrayList<>();
86 + for (ForwardingObjective fo : fos) {
87 + removeFos.add(DefaultForwardingObjective.builder()
88 + .fromApp(fo.appId())
89 + .makePermanent()
90 + .withFlag(fo.flag())
91 + .withPriority(fo.priority())
92 + .withSelector(fo.selector())
93 + .withTreatment(fo.treatment())
94 + .remove());
95 + }
96 + return removeFos;
97 + }
98 +
99 + public Collection<ForwardingObjective> getForwardingObjectives() {
100 + return this.forwardMap.values();
101 + }
102 +
103 + public static int forwardingObjectiveHash(ForwardingObjective forwardingObjective) {
104 + return Objects.hash(forwardingObjective.selector(), forwardingObjective.flag(),
105 + forwardingObjective.permanent(), forwardingObjective.timeout(),
106 + forwardingObjective.appId(), forwardingObjective.priority(),
107 + forwardingObjective.nextId(), forwardingObjective.treatment());
108 + }
109 +}
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.flowobjective.impl.composition;
17 +
18 +import org.onosproject.net.flowobjective.ForwardingObjective;
19 +
20 +import java.util.ArrayList;
21 +import java.util.List;
22 +
23 +/**
24 + * Provides an update table for Forward.
25 + */
26 +public class ForwardUpdateTable {
27 + public List<ForwardingObjective> addObjectives;
28 + public List<ForwardingObjective> removeObjectives;
29 +
30 + public ForwardUpdateTable() {
31 + this.addObjectives = new ArrayList<>();
32 + this.removeObjectives = new ArrayList<>();
33 + }
34 +
35 + public void addUpdateTable(ForwardUpdateTable updateTable) {
36 + this.addObjectives.addAll(updateTable.addObjectives);
37 + this.removeObjectives.addAll(updateTable.removeObjectives);
38 + }
39 +
40 + public List<ForwardingObjective> toForwardingObjectiveList() {
41 + List<ForwardingObjective> forwardingObjectives = new ArrayList<>();
42 + forwardingObjectives.addAll(this.addObjectives);
43 + forwardingObjectives.addAll(this.removeObjectives);
44 + return forwardingObjectives;
45 + }
46 +}
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.flowobjective.impl.composition;
17 +
18 +import org.onosproject.net.flowobjective.NextObjective;
19 +
20 +import java.util.ArrayList;
21 +import java.util.HashMap;
22 +import java.util.List;
23 +import java.util.Map;
24 +
25 +/**
26 + * Provides a table to store Next.
27 + */
28 +public class NextTable {
29 +
30 + protected Map<Integer, NextObjective> nextMap;
31 +
32 + public NextTable() {
33 + this.nextMap = new HashMap<>();
34 + }
35 +
36 + public List<NextObjective> updateNext(NextObjective nextObjective) {
37 + List<NextObjective> updates = new ArrayList<>();
38 + switch (nextObjective.op()) {
39 + case ADD:
40 + this.nextMap.put(nextObjective.id(), nextObjective);
41 + updates.add(nextObjective);
42 + break;
43 + case REMOVE:
44 + this.nextMap.remove(nextObjective.id());
45 + updates.add(nextObjective);
46 + break;
47 + default:
48 + break;
49 + }
50 + return updates;
51 + }
52 +
53 + public List<NextObjective> updateNext(List<NextObjective> nextObjectives) {
54 + List<NextObjective> updates = new ArrayList<>();
55 + for (NextObjective nextObjective : nextObjectives) {
56 + updates.addAll(this.updateNext(nextObjective));
57 + }
58 + return updates;
59 + }
60 +
61 +}
1 +/*
2 + * Copyright 2014-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.flowobjective.impl;
17 +
18 +import org.junit.After;
19 +import org.junit.Before;
20 +import org.junit.Ignore;
21 +import org.slf4j.Logger;
22 +import org.slf4j.LoggerFactory;
23 +
24 +/**
25 + * Test FlowObjectiveCompositionTree.
26 + */
27 +@Ignore
28 +public class FlowObjectiveCompositionTreeTest {
29 +
30 + private final Logger log = LoggerFactory.getLogger(getClass());
31 +
32 + @Before
33 + public void setUp() {}
34 +
35 + @After
36 + public void tearDown() {}
37 +
38 + /*@Test
39 + public void testParallelComposition() {
40 + FlowObjectiveCompositionTree policyTree = FlowObjectiveCompositionUtil.parsePolicyString("31+32");
41 +
42 + {
43 + TrafficSelector selector = DefaultTrafficSelector.builder()
44 + .matchIPSrc(IpPrefix.valueOf("1.0.0.0/24"))
45 + .build();
46 +
47 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
48 +
49 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
50 + .fromApp(new DefaultApplicationId(31, "a"))
51 + .makePermanent()
52 + .withFlag(ForwardingObjective.Flag.VERSATILE)
53 + .withPriority(1)
54 + .withSelector(selector)
55 + .withTreatment(treatment)
56 + .add();
57 +
58 + helper(policyTree, forwardingObjective);
59 + }
60 +
61 + {
62 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
63 +
64 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
65 +
66 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
67 + .fromApp(new DefaultApplicationId(31, "a"))
68 + .makePermanent()
69 + .withFlag(ForwardingObjective.Flag.VERSATILE)
70 + .withPriority(0)
71 + .withSelector(selector)
72 + .withTreatment(treatment)
73 + .add();
74 +
75 + helper(policyTree, forwardingObjective);
76 + }
77 +
78 +
79 + {
80 + TrafficSelector selector = DefaultTrafficSelector.builder()
81 + .matchIPDst(IpPrefix.valueOf("2.0.0.1/32"))
82 + .build();
83 +
84 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
85 + .setOutput(PortNumber.portNumber(1))
86 + .build();
87 +
88 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
89 + .fromApp(new DefaultApplicationId(32, "b"))
90 + .makePermanent()
91 + .withFlag(ForwardingObjective.Flag.VERSATILE)
92 + .withPriority(1)
93 + .withSelector(selector)
94 + .withTreatment(treatment)
95 + .add();
96 +
97 + helper(policyTree, forwardingObjective);
98 + }
99 +
100 + {
101 + TrafficSelector selector = DefaultTrafficSelector.builder()
102 + .matchIPDst(IpPrefix.valueOf("2.0.0.2/32"))
103 + .build();
104 +
105 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
106 + .setOutput(PortNumber.portNumber(2))
107 + .build();
108 +
109 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
110 + .fromApp(new DefaultApplicationId(32, "b"))
111 + .makePermanent()
112 + .withFlag(ForwardingObjective.Flag.VERSATILE)
113 + .withPriority(1)
114 + .withSelector(selector)
115 + .withTreatment(treatment)
116 + .add();
117 + helper(policyTree, forwardingObjective);
118 + }
119 +
120 + {
121 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
122 +
123 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
124 +
125 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
126 + .fromApp(new DefaultApplicationId(32, "b"))
127 + .makePermanent()
128 + .withFlag(ForwardingObjective.Flag.VERSATILE)
129 + .withPriority(0)
130 + .withSelector(selector)
131 + .withTreatment(treatment)
132 + .add();
133 +
134 + helper(policyTree, forwardingObjective);
135 + }
136 +
137 + System.out.println("---------- Parallel ----------");
138 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
139 + System.out.println(forwardingObjectiveToString(fo));
140 + }
141 +
142 + {
143 + TrafficSelector selector = DefaultTrafficSelector.builder()
144 + .matchIPDst(IpPrefix.valueOf("2.0.0.3/32"))
145 + .build();
146 +
147 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
148 + .setOutput(PortNumber.portNumber(3))
149 + .build();
150 +
151 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
152 + .fromApp(new DefaultApplicationId(32, "b"))
153 + .makePermanent()
154 + .withFlag(ForwardingObjective.Flag.VERSATILE)
155 + .withPriority(1)
156 + .withSelector(selector)
157 + .withTreatment(treatment)
158 + .add();
159 + helper(policyTree, forwardingObjective);
160 + }
161 +
162 + System.out.println("---------- Parallel ----------");
163 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
164 + System.out.println(forwardingObjectiveToString(fo));
165 + }
166 +
167 + {
168 + TrafficSelector selector = DefaultTrafficSelector.builder()
169 + .matchIPDst(IpPrefix.valueOf("2.0.0.3/32"))
170 + .build();
171 +
172 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
173 + .setOutput(PortNumber.portNumber(3))
174 + .build();
175 +
176 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
177 + .fromApp(new DefaultApplicationId(32, "b"))
178 + .makePermanent()
179 + .withFlag(ForwardingObjective.Flag.VERSATILE)
180 + .withPriority(1)
181 + .withSelector(selector)
182 + .withTreatment(treatment)
183 + .remove();
184 + helper(policyTree, forwardingObjective);
185 + }
186 +
187 + {
188 + TrafficSelector selector = DefaultTrafficSelector.builder()
189 + .matchIPSrc(IpPrefix.valueOf("1.0.0.0/24"))
190 + .build();
191 +
192 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
193 +
194 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
195 + .fromApp(new DefaultApplicationId(31, "a"))
196 + .makePermanent()
197 + .withFlag(ForwardingObjective.Flag.VERSATILE)
198 + .withPriority(1)
199 + .withSelector(selector)
200 + .withTreatment(treatment)
201 + .remove();
202 +
203 + helper(policyTree, forwardingObjective);
204 + }
205 +
206 + {
207 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
208 +
209 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
210 +
211 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
212 + .fromApp(new DefaultApplicationId(31, "a"))
213 + .makePermanent()
214 + .withFlag(ForwardingObjective.Flag.VERSATILE)
215 + .withPriority(0)
216 + .withSelector(selector)
217 + .withTreatment(treatment)
218 + .remove();
219 +
220 + helper(policyTree, forwardingObjective);
221 + }
222 +
223 + System.out.println("---------- Parallel ----------");
224 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
225 + System.out.println(forwardingObjectiveToString(fo));
226 + }
227 + }
228 +
229 + @Test
230 + public void testSequentialComposition() {
231 + FlowObjectiveCompositionTree policyTree = FlowObjectiveCompositionUtil.parsePolicyString("31>32");
232 +
233 + {
234 + TrafficSelector selector = DefaultTrafficSelector.builder()
235 + .matchIPSrc(IpPrefix.valueOf("0.0.0.0/2"))
236 + .matchIPDst(IpPrefix.valueOf("3.0.0.0/32"))
237 + .build();
238 +
239 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
240 + .setIpDst(IpAddress.valueOf("2.0.0.1"))
241 + .build();
242 +
243 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
244 + .fromApp(new DefaultApplicationId(31, "a"))
245 + .makePermanent()
246 + .withFlag(ForwardingObjective.Flag.VERSATILE)
247 + .withPriority(3)
248 + .withSelector(selector)
249 + .withTreatment(treatment)
250 + .add();
251 +
252 + helper(policyTree, forwardingObjective);
253 + }
254 +
255 + {
256 + TrafficSelector selector = DefaultTrafficSelector.builder()
257 + .matchIPDst(IpPrefix.valueOf("3.0.0.0/32"))
258 + .build();
259 +
260 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
261 + .setIpDst(IpAddress.valueOf("2.0.0.2"))
262 + .build();
263 +
264 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
265 + .fromApp(new DefaultApplicationId(31, "a"))
266 + .makePermanent()
267 + .withFlag(ForwardingObjective.Flag.VERSATILE)
268 + .withPriority(1)
269 + .withSelector(selector)
270 + .withTreatment(treatment)
271 + .add();
272 +
273 + helper(policyTree, forwardingObjective);
274 + }
275 +
276 + {
277 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
278 +
279 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
280 +
281 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
282 + .fromApp(new DefaultApplicationId(31, "a"))
283 + .makePermanent()
284 + .withFlag(ForwardingObjective.Flag.VERSATILE)
285 + .withPriority(0)
286 + .withSelector(selector)
287 + .withTreatment(treatment)
288 + .add();
289 +
290 + helper(policyTree, forwardingObjective);
291 + }
292 +
293 + {
294 + TrafficSelector selector = DefaultTrafficSelector.builder()
295 + .matchIPDst(IpPrefix.valueOf("2.0.0.1/32"))
296 + .build();
297 +
298 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
299 + .setOutput(PortNumber.portNumber(1))
300 + .build();
301 +
302 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
303 + .fromApp(new DefaultApplicationId(32, "b"))
304 + .makePermanent()
305 + .withFlag(ForwardingObjective.Flag.VERSATILE)
306 + .withPriority(1)
307 + .withSelector(selector)
308 + .withTreatment(treatment)
309 + .add();
310 +
311 + helper(policyTree, forwardingObjective);
312 + }
313 +
314 + {
315 + TrafficSelector selector = DefaultTrafficSelector.builder()
316 + .matchIPDst(IpPrefix.valueOf("2.0.0.2/32"))
317 + .build();
318 +
319 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
320 + .setOutput(PortNumber.portNumber(2))
321 + .build();
322 +
323 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
324 + .fromApp(new DefaultApplicationId(32, "b"))
325 + .makePermanent()
326 + .withFlag(ForwardingObjective.Flag.VERSATILE)
327 + .withPriority(1)
328 + .withSelector(selector)
329 + .withTreatment(treatment)
330 + .add();
331 + helper(policyTree, forwardingObjective);
332 + }
333 +
334 + {
335 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
336 +
337 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
338 +
339 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
340 + .fromApp(new DefaultApplicationId(32, "b"))
341 + .makePermanent()
342 + .withFlag(ForwardingObjective.Flag.VERSATILE)
343 + .withPriority(0)
344 + .withSelector(selector)
345 + .withTreatment(treatment)
346 + .add();
347 +
348 + helper(policyTree, forwardingObjective);
349 + }
350 +
351 + System.out.println("---------- Sequential ----------");
352 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
353 + System.out.println(forwardingObjectiveToString(fo));
354 + }
355 +
356 + {
357 + TrafficSelector selector = DefaultTrafficSelector.builder()
358 + .matchIPDst(IpPrefix.valueOf("2.0.0.3/32"))
359 + .build();
360 +
361 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
362 + .setOutput(PortNumber.portNumber(3))
363 + .build();
364 +
365 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
366 + .fromApp(new DefaultApplicationId(32, "b"))
367 + .makePermanent()
368 + .withFlag(ForwardingObjective.Flag.VERSATILE)
369 + .withPriority(1)
370 + .withSelector(selector)
371 + .withTreatment(treatment)
372 + .add();
373 +
374 + helper(policyTree, forwardingObjective);
375 + }
376 +
377 + {
378 + TrafficSelector selector = DefaultTrafficSelector.builder()
379 + .matchIPSrc(IpPrefix.valueOf("0.0.0.0/1"))
380 + .matchIPDst(IpPrefix.valueOf("3.0.0.0/32"))
381 + .build();
382 +
383 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
384 + .setIpDst(IpAddress.valueOf("2.0.0.3"))
385 + .build();
386 +
387 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
388 + .fromApp(new DefaultApplicationId(31, "a"))
389 + .makePermanent()
390 + .withFlag(ForwardingObjective.Flag.VERSATILE)
391 + .withPriority(3)
392 + .withSelector(selector)
393 + .withTreatment(treatment)
394 + .add();
395 +
396 + helper(policyTree, forwardingObjective);
397 + }
398 +
399 + System.out.println("---------- Sequential ----------");
400 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
401 + System.out.println(forwardingObjectiveToString(fo));
402 + }
403 +
404 + {
405 + TrafficSelector selector = DefaultTrafficSelector.builder()
406 + .matchIPDst(IpPrefix.valueOf("2.0.0.3/32"))
407 + .build();
408 +
409 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
410 + .setOutput(PortNumber.portNumber(3))
411 + .build();
412 +
413 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
414 + .fromApp(new DefaultApplicationId(32, "b"))
415 + .makePermanent()
416 + .withFlag(ForwardingObjective.Flag.VERSATILE)
417 + .withPriority(1)
418 + .withSelector(selector)
419 + .withTreatment(treatment)
420 + .remove();
421 +
422 + helper(policyTree, forwardingObjective);
423 + }
424 +
425 + {
426 + TrafficSelector selector = DefaultTrafficSelector.builder()
427 + .matchIPSrc(IpPrefix.valueOf("0.0.0.0/1"))
428 + .matchIPDst(IpPrefix.valueOf("3.0.0.0/32"))
429 + .build();
430 +
431 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
432 + .setIpDst(IpAddress.valueOf("2.0.0.3"))
433 + .build();
434 +
435 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
436 + .fromApp(new DefaultApplicationId(31, "a"))
437 + .makePermanent()
438 + .withFlag(ForwardingObjective.Flag.VERSATILE)
439 + .withPriority(3)
440 + .withSelector(selector)
441 + .withTreatment(treatment)
442 + .remove();
443 +
444 + helper(policyTree, forwardingObjective);
445 + }
446 +
447 + System.out.println("---------- Sequential ----------");
448 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
449 + System.out.println(forwardingObjectiveToString(fo));
450 + }
451 + }
452 +
453 + @Test
454 + public void testOverrideComposition() {
455 + FlowObjectiveCompositionTree policyTree = FlowObjectiveCompositionUtil.parsePolicyString("31/32");
456 +
457 + {
458 + TrafficSelector selector = DefaultTrafficSelector.builder()
459 + .matchIPSrc(IpPrefix.valueOf("1.0.0.0/32"))
460 + .matchIPDst(IpPrefix.valueOf("2.0.0.1/32"))
461 + .build();
462 +
463 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
464 + .setOutput(PortNumber.portNumber(3))
465 + .build();
466 +
467 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
468 + .fromApp(new DefaultApplicationId(31, "a"))
469 + .makePermanent()
470 + .withFlag(ForwardingObjective.Flag.VERSATILE)
471 + .withPriority(1)
472 + .withSelector(selector)
473 + .withTreatment(treatment)
474 + .add();
475 +
476 + helper(policyTree, forwardingObjective);
477 + }
478 +
479 + {
480 + TrafficSelector selector = DefaultTrafficSelector.builder()
481 + .matchIPDst(IpPrefix.valueOf("2.0.0.1/32"))
482 + .build();
483 +
484 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
485 + .setOutput(PortNumber.portNumber(1))
486 + .build();
487 +
488 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
489 + .fromApp(new DefaultApplicationId(32, "b"))
490 + .makePermanent()
491 + .withFlag(ForwardingObjective.Flag.VERSATILE)
492 + .withPriority(1)
493 + .withSelector(selector)
494 + .withTreatment(treatment)
495 + .add();
496 +
497 + helper(policyTree, forwardingObjective);
498 + }
499 +
500 + {
501 + TrafficSelector selector = DefaultTrafficSelector.builder()
502 + .matchIPDst(IpPrefix.valueOf("2.0.0.2/32"))
503 + .build();
504 +
505 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
506 + .setOutput(PortNumber.portNumber(2))
507 + .build();
508 +
509 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
510 + .fromApp(new DefaultApplicationId(32, "b"))
511 + .makePermanent()
512 + .withFlag(ForwardingObjective.Flag.VERSATILE)
513 + .withPriority(1)
514 + .withSelector(selector)
515 + .withTreatment(treatment)
516 + .add();
517 + helper(policyTree, forwardingObjective);
518 + }
519 +
520 + {
521 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
522 +
523 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
524 +
525 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
526 + .fromApp(new DefaultApplicationId(32, "b"))
527 + .makePermanent()
528 + .withFlag(ForwardingObjective.Flag.VERSATILE)
529 + .withPriority(0)
530 + .withSelector(selector)
531 + .withTreatment(treatment)
532 + .add();
533 +
534 + helper(policyTree, forwardingObjective);
535 + }
536 +
537 + System.out.println("---------- Override ----------");
538 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
539 + System.out.println(forwardingObjectiveToString(fo));
540 + }
541 +
542 + {
543 + TrafficSelector selector = DefaultTrafficSelector.builder()
544 + .matchIPDst(IpPrefix.valueOf("2.0.0.3/32"))
545 + .build();
546 +
547 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
548 + .setOutput(PortNumber.portNumber(3))
549 + .build();
550 +
551 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
552 + .fromApp(new DefaultApplicationId(32, "b"))
553 + .makePermanent()
554 + .withFlag(ForwardingObjective.Flag.VERSATILE)
555 + .withPriority(1)
556 + .withSelector(selector)
557 + .withTreatment(treatment)
558 + .add();
559 + helper(policyTree, forwardingObjective);
560 + }
561 +
562 + System.out.println("---------- Override ----------");
563 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
564 + System.out.println(forwardingObjectiveToString(fo));
565 + }
566 +
567 + {
568 + TrafficSelector selector = DefaultTrafficSelector.builder()
569 + .matchIPDst(IpPrefix.valueOf("2.0.0.3/32"))
570 + .build();
571 +
572 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
573 + .setOutput(PortNumber.portNumber(3))
574 + .build();
575 +
576 + ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
577 + .fromApp(new DefaultApplicationId(32, "b"))
578 + .makePermanent()
579 + .withFlag(ForwardingObjective.Flag.VERSATILE)
580 + .withPriority(1)
581 + .withSelector(selector)
582 + .withTreatment(treatment)
583 + .remove();
584 + helper(policyTree, forwardingObjective);
585 + }
586 +
587 + System.out.println("---------- Override ----------");
588 + for (ForwardingObjective fo : policyTree.forwardTable.getForwardingObjectives()) {
589 + System.out.println(forwardingObjectiveToString(fo));
590 + }
591 + }
592 +
593 + private void helper(FlowObjectiveCompositionTree policyTree, ForwardingObjective forwardingObjective) {
594 + log.info("before composition");
595 + log.info("\t{}", forwardingObjectiveToString(forwardingObjective));
596 + List<ForwardingObjective> forwardingObjectives
597 + = policyTree.updateForward(forwardingObjective);
598 + log.info("after composition");
599 + for (ForwardingObjective fo : forwardingObjectives) {
600 + log.info("\t{}", forwardingObjectiveToString(fo));
601 + }
602 + }*/
603 +}