Committed by
Brian O'Connor
Adding experimental Flow Objective composition
Change-Id: I35e4414845ad5034145157ab83f933e40f75a1d9
Showing
12 changed files
with
2136 additions
and
0 deletions
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) { | ... | ... |
core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FilterTable.java
0 → 100644
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 | +} |
core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/ForwardTable.java
0 → 100644
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 | +} |
core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/ForwardUpdateTable.java
0 → 100644
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 | +} |
core/net/src/test/java/org/onosproject/net/flowobjective/impl/FlowObjectiveCompositionTreeTest.java
0 → 100644
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 | +} |
-
Please register or login to post a comment