blob: 320d167be69c73f889029f0457f043fa28db9c7f [file] [log] [blame]
Yoonseon Hanc70b4e02016-10-20 15:24:33 -07001/*
2 * Copyright 2016-present 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
17package org.onosproject.incubator.net.virtual.impl.provider;
18
19import com.google.common.collect.HashBasedTable;
20import com.google.common.collect.ImmutableList;
21import com.google.common.collect.ImmutableSet;
22import com.google.common.collect.Maps;
23import com.google.common.collect.Sets;
24import com.google.common.collect.Table;
25import javafx.util.Pair;
26import org.apache.felix.scr.annotations.Activate;
27import org.apache.felix.scr.annotations.Component;
28import org.apache.felix.scr.annotations.Deactivate;
29import org.apache.felix.scr.annotations.Modified;
30import org.apache.felix.scr.annotations.Reference;
31import org.apache.felix.scr.annotations.ReferenceCardinality;
32import org.apache.felix.scr.annotations.Service;
33import org.onlab.packet.VlanId;
34import org.onosproject.core.ApplicationId;
35import org.onosproject.core.CoreService;
36import org.onosproject.incubator.net.virtual.NetworkId;
37import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
38import org.onosproject.incubator.net.virtual.VirtualPort;
39import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
40import org.onosproject.incubator.net.virtual.provider.InternalRoutingAlgorithm;
41import org.onosproject.incubator.net.virtual.provider.VirtualFlowRuleProvider;
42import org.onosproject.incubator.net.virtual.provider.VirtualFlowRuleProviderService;
43import org.onosproject.incubator.net.virtual.provider.VirtualProviderRegistryService;
44import org.onosproject.net.ConnectPoint;
45import org.onosproject.net.DeviceId;
46import org.onosproject.net.Link;
47import org.onosproject.net.Path;
48import org.onosproject.net.PortNumber;
49import org.onosproject.net.device.DeviceService;
50import org.onosproject.net.flow.DefaultFlowEntry;
51import org.onosproject.net.flow.DefaultFlowRule;
52import org.onosproject.net.flow.DefaultTrafficSelector;
53import org.onosproject.net.flow.DefaultTrafficTreatment;
54import org.onosproject.net.flow.FlowEntry;
55import org.onosproject.net.flow.FlowRule;
56import org.onosproject.net.flow.FlowRuleBatchOperation;
57import org.onosproject.net.flow.FlowRuleEvent;
58import org.onosproject.net.flow.FlowRuleListener;
59import org.onosproject.net.flow.FlowRuleService;
60import org.onosproject.net.flow.TrafficSelector;
61import org.onosproject.net.flow.TrafficTreatment;
62import org.onosproject.net.flow.criteria.Criterion;
63import org.onosproject.net.flow.criteria.PortCriterion;
64import org.onosproject.net.flow.instructions.Instruction;
65import org.onosproject.net.flow.instructions.Instructions;
66import org.onosproject.net.provider.ProviderId;
67import org.onosproject.net.topology.TopologyService;
68import org.osgi.service.component.ComponentContext;
69import org.slf4j.Logger;
70
71import java.util.Dictionary;
72import java.util.HashSet;
73import java.util.Map;
74import java.util.Optional;
75import java.util.Set;
76
77import static com.google.common.base.Preconditions.checkNotNull;
78import static org.slf4j.LoggerFactory.getLogger;
79
80/**
81 * Provider that translate virtual flow rules into physical rules.
82 * Current implementation is based on FlowRules.
83 * This virtualize and de-virtualize virtual flow rules into physical flow rules.
84 * {@link org.onosproject.net.flow.FlowRule}
85 */
86@Component(immediate = true)
87@Service
88public class DefaultVirtualFlowRuleProvider extends AbstractVirtualProvider
89 implements VirtualFlowRuleProvider {
90
91 private static final int FLOW_RULE_PRIORITY = 10;
92
93 private final Logger log = getLogger(getClass());
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected TopologyService topologyService;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected VirtualNetworkAdminService virtualNetworkAdminService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected CoreService coreService;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected FlowRuleService flowRuleService;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected DeviceService deviceService;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected VirtualProviderRegistryService providerRegistryService;
112
113 InternalRoutingAlgorithm internalRoutingAlgorithm;
114 InternalVirtualFlowRuleManager frm;
115 ApplicationId appId;
116 FlowRuleListener flowRuleListener;
117
118 /**
119 * Creates a provider with the supplied identifier.
120 */
121 public DefaultVirtualFlowRuleProvider() {
122 super(new ProviderId("vnet-flow", "org.onosproject.virtual.vnet-flow"));
123 }
124
125
126 @Activate
127 public void activate() {
128 appId = coreService.registerApplication(
129 "org.onosproject.virtual.vnet-flow");
130
131 providerRegistryService.registerProvider(this);
132
133 flowRuleListener = new InternalFlowRuleListener();
134 flowRuleService.addListener(flowRuleListener);
135
136 internalRoutingAlgorithm = new DefaultInternalRoutingAlgorithm();
137 frm = new InternalVirtualFlowRuleManager();
138
139 log.info("Started");
140 }
141
142 @Deactivate
143 public void deactivate() {
144 flowRuleService.removeListener(flowRuleListener);
145 providerRegistryService.unregisterProvider(this);
146 }
147
148 @Modified
149 protected void modified(ComponentContext context) {
150 Dictionary<?, ?> properties = context.getProperties();
151 }
152
153 @Override
154 public void applyFlowRule(NetworkId networkId, FlowRule... flowRules) {
155 for (FlowRule flowRule : flowRules) {
156 devirtualize(networkId, flowRule).forEach(
157 r -> {
158 flowRuleService.applyFlowRules(r);
159 }
160 );
161 }
162 }
163
164 @Override
165 public void removeFlowRule(NetworkId networkId, FlowRule... flowRules) {
166 for (FlowRule flowRule : flowRules) {
167 devirtualize(networkId, flowRule).forEach(
168 r -> {
169 flowRuleService.removeFlowRules(r);
170 }
171 );
172 }
173 }
174
175 @Override
176 public void executeBatch(NetworkId networkId, FlowRuleBatchOperation batch) {
177 checkNotNull(batch);
178
179 //TODO: execute batch mechanism
180 }
181
182 public void setEmbeddingAlgorithm(InternalRoutingAlgorithm
183 internalRoutingAlgorithm) {
184 this.internalRoutingAlgorithm = internalRoutingAlgorithm;
185 }
186
187 /**
188 * Translate the requested physical flow rules into virtual flow rules.
189 *
190 * @param flowRule A virtual flow rule to be translated
191 * @return A flow rule for a specific virtual network
192 */
193 private FlowRule virtualize(FlowRule flowRule) {
194 return frm.getVirtualRule(flowRule);
195 }
196
197 private FlowEntry virtualize(FlowEntry flowEntry) {
198 FlowRule vRule = virtualize(flowEntry);
199 FlowEntry vEntry = new DefaultFlowEntry(vRule, flowEntry.state(),
200 flowEntry.life(),
201 flowEntry.packets(),
202 flowEntry.bytes());
203
204 return vEntry;
205 }
206
207 /**
208 * Translate the requested virtual flow rules into physical flow rules.
209 * The translation could be one to many.
210 *
211 * @param flowRule A flow rule from underlying data plane to be translated
212 * @return A set of flow rules for physical network
213 */
214 private Set<FlowRule> devirtualize(NetworkId networkId, FlowRule flowRule) {
215
216 Set<FlowRule> outRules = new HashSet<>();
217
218 Set<VirtualPort> vPorts = virtualNetworkAdminService
219 .getVirtualPorts(networkId, flowRule.deviceId());
220
221 PortCriterion portCriterion = ((PortCriterion) flowRule.selector()
222 .getCriterion(Criterion.Type.IN_PORT));
223
224 Set<ConnectPoint> ingressPoints = new HashSet<>();
225 if (portCriterion != null) {
226 PortNumber vInPortNum = portCriterion.port();
227
228 Optional<ConnectPoint> optionalCp = vPorts.stream()
229 .filter(v -> v.number().equals(vInPortNum))
230 .map(v -> v.realizedBy()).findFirst();
231 if (!optionalCp.isPresent()) {
232 log.info("Port {} is not realized yet, in Network {}, Device {}",
233 vInPortNum, networkId, flowRule.deviceId());
234 return outRules;
235 }
236 ingressPoints.add(optionalCp.get());
237 } else {
238 for (VirtualPort vPort : vPorts) {
239 if (vPort.realizedBy() != null) {
240 ingressPoints.add(vPort.realizedBy());
241 } else {
242 log.info("Port {} is not realized yet, in Network {}, " +
243 "Device {}",
244 vPort, networkId, flowRule.deviceId());
245 return outRules;
246 }
247 }
248 }
249
250 PortNumber vOutPortNum = flowRule.treatment().allInstructions().stream()
251 .filter(i -> i.type() == Instruction.Type.OUTPUT)
252 .map(i -> ((Instructions.OutputInstruction) i).port())
253 .findFirst().get();
254
255 Optional<ConnectPoint> optionalCpOut = vPorts.stream()
256 .filter(v -> v.number().equals(vOutPortNum))
257 .map(v -> v.realizedBy())
258 .findFirst();
259 if (!optionalCpOut.isPresent()) {
260 log.info("Port {} is not realized yet, in Network {}, Device {}",
261 vOutPortNum, networkId, flowRule.deviceId());
262 return outRules;
263 }
264 ConnectPoint egressPoint = optionalCpOut.get();
265
266 TrafficSelector.Builder commonSelectorBuilder
267 = DefaultTrafficSelector.builder();
268 flowRule.selector().criteria().stream()
269 .filter(c -> c.type() != Criterion.Type.IN_PORT)
270 .forEach(c -> commonSelectorBuilder.add(c));
271 TrafficSelector commonSelector = commonSelectorBuilder.build();
272
273 TrafficTreatment.Builder commonTreatmentBuilder
274 = DefaultTrafficTreatment.builder();
275 flowRule.treatment().allInstructions().stream()
276 .filter(i -> i.type() != Instruction.Type.OUTPUT)
277 .forEach(i -> commonTreatmentBuilder.add(i));
278 TrafficTreatment commonTreatment = commonTreatmentBuilder.build();
279
280 for (ConnectPoint ingressPoint : ingressPoints) {
281 outRules.addAll(generateRules(networkId, ingressPoint, egressPoint,
282 commonSelector, commonTreatment, flowRule));
283 }
284
285 return outRules;
286 }
287
288 private Set<FlowRule> generateRules(NetworkId networkId,
289 ConnectPoint ingressPoint,
290 ConnectPoint egressPoint,
291 TrafficSelector commonSelector,
292 TrafficTreatment commonTreatment,
293 FlowRule flowRule) {
294
295 Set<FlowRule> outRules = new HashSet<>();
296
297 if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
298 //Traffic is handled inside a single physical switch
299 //No tunnel is needed.
300
301 TrafficSelector.Builder selectorBuilder =
302 DefaultTrafficSelector.builder(commonSelector);
303 selectorBuilder.matchInPort(ingressPoint.port());
304
305 TrafficTreatment.Builder treatmentBuilder =
306 DefaultTrafficTreatment.builder(commonTreatment);
307 treatmentBuilder.setOutput(egressPoint.port());
308
309 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder();
310 ruleBuilder.fromApp(appId);
311 ruleBuilder.forDevice(ingressPoint.deviceId());
312 ruleBuilder.withSelector(selectorBuilder.build());
313 ruleBuilder.withTreatment(treatmentBuilder.build());
314 ruleBuilder.withPriority(FLOW_RULE_PRIORITY);
315 if (flowRule.isPermanent()) {
316 ruleBuilder.makePermanent();
317 } else {
318 ruleBuilder.makeTemporary(flowRule.timeout());
319 }
320
321 FlowRule rule = ruleBuilder.build();
322 frm.addIngressRule(flowRule, rule, networkId);
323 outRules.add(ruleBuilder.build());
324 } else {
325 //Traffic is handled by multiple physical switches
326 //A tunnel is needed.
327
328 Path internalPath = internalRoutingAlgorithm
329 .findPath(ingressPoint, egressPoint);
330 checkNotNull(internalPath, "No path between " +
331 ingressPoint.toString() + " " + egressPoint.toString());
332 ConnectPoint inCp = ingressPoint;
333 ConnectPoint outCp = internalPath.links().get(0).src();
334
335 //ingress point of tunnel
336 TrafficSelector.Builder selectorBuilder =
337 DefaultTrafficSelector.builder(commonSelector);
338 selectorBuilder.matchInPort(ingressPoint.port());
339
340 TrafficTreatment.Builder treatmentBuilder =
341 DefaultTrafficTreatment.builder(commonTreatment);
342 treatmentBuilder.pushVlan()
343 .setVlanId(VlanId.vlanId(networkId.id().shortValue()));
344 treatmentBuilder.setOutput(outCp.port());
345
346 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder();
347 ruleBuilder.fromApp(appId);
348 ruleBuilder.forDevice(ingressPoint.deviceId());
349 ruleBuilder.withSelector(selectorBuilder.build());
350 ruleBuilder.withTreatment(treatmentBuilder.build());
351 ruleBuilder.withPriority(FLOW_RULE_PRIORITY);
352 if (flowRule.isPermanent()) {
353 ruleBuilder.makePermanent();
354 } else {
355 ruleBuilder.makeTemporary(flowRule.timeout());
356 }
357
358 FlowRule rule = ruleBuilder.build();
359 frm.addIngressRule(flowRule, rule, networkId);
360 outRules.add(ruleBuilder.build());
361
362 //routing inside tunnel
363 inCp = internalPath.links().get(0).dst();
364
365 if (internalPath.links().size() > 1) {
366 for (Link l : internalPath.links()
367 .subList(1, internalPath.links().size() - 1)) {
368
369 outCp = l.src();
370
371 selectorBuilder = DefaultTrafficSelector
372 .builder(commonSelector);
373 selectorBuilder.matchVlanId(
374 VlanId.vlanId(networkId.id().shortValue()));
375 selectorBuilder.matchInPort(inCp.port());
376
377 treatmentBuilder = DefaultTrafficTreatment
378 .builder(commonTreatment);
379 treatmentBuilder.setOutput(outCp.port());
380
381 ruleBuilder = DefaultFlowRule.builder();
382 ruleBuilder.fromApp(appId);
383 ruleBuilder.forDevice(inCp.deviceId());
384 ruleBuilder.withSelector(selectorBuilder.build());
385 ruleBuilder.withTreatment(treatmentBuilder.build());
386 if (flowRule.isPermanent()) {
387 ruleBuilder.makePermanent();
388 } else {
389 ruleBuilder.makeTemporary(flowRule.timeout());
390 }
391
392 outRules.add(ruleBuilder.build());
393 inCp = l.dst();
394 }
395 }
396
397 //egress point of tunnel
398 selectorBuilder = DefaultTrafficSelector.builder(commonSelector);
399 selectorBuilder.matchVlanId(
400 VlanId.vlanId(networkId.id().shortValue()));
401 selectorBuilder.matchInPort(ingressPoint.port());
402
403 treatmentBuilder = DefaultTrafficTreatment.builder(commonTreatment);
404 treatmentBuilder.popVlan();
405 treatmentBuilder.setOutput(egressPoint.port());
406
407 ruleBuilder = DefaultFlowRule.builder();
408 ruleBuilder.fromApp(appId);
409 ruleBuilder.forDevice(egressPoint.deviceId());
410 ruleBuilder.withSelector(selectorBuilder.build());
411 ruleBuilder.withTreatment(treatmentBuilder.build());
412 ruleBuilder.withPriority(FLOW_RULE_PRIORITY);
413 if (flowRule.isPermanent()) {
414 ruleBuilder.makePermanent();
415 } else {
416 ruleBuilder.makeTemporary(flowRule.timeout());
417 }
418
419 outRules.add(ruleBuilder.build());
420 }
421
422 return outRules;
423 }
424
425 private class InternalFlowRuleListener implements FlowRuleListener {
426 @Override
427 public void event(FlowRuleEvent event) {
428
429 if ((event.type() == FlowRuleEvent.Type.RULE_ADDED) ||
430 (event.type() == FlowRuleEvent.Type.RULE_UPDATED)) {
431 if (frm.isVirtualIngressRule(event.subject())) {
432 NetworkId networkId = frm.getVirtualNetworkId(event.subject());
433 FlowEntry vEntry = getVirtualFlowEntry(event.subject());
434 ImmutableList.Builder<FlowEntry> builder = ImmutableList.builder();
435 builder.add(vEntry);
436
437 VirtualFlowRuleProviderService providerService =
438 (VirtualFlowRuleProviderService) providerRegistryService
439 .getProviderService(networkId,
440 VirtualFlowRuleProvider.class);
441
442 providerService.pushFlowMetrics(vEntry.deviceId(), builder.build());
443 }
444 } else if (event.type() == FlowRuleEvent.Type.RULE_REMOVED) {
445 if (frm.isVirtualIngressRule(event.subject())) {
446 //FIXME confirm all physical rules are removed
447 NetworkId networkId = frm.getVirtualNetworkId(event.subject());
448 FlowEntry vEntry = getVirtualFlowEntry(event.subject());
449
450 VirtualFlowRuleProviderService providerService =
451 (VirtualFlowRuleProviderService) providerRegistryService
452 .getProviderService(networkId,
453 VirtualFlowRuleProvider.class);
454 providerService.flowRemoved(vEntry);
455
456 }
457 }
458 }
459
460 private FlowEntry getVirtualFlowEntry(FlowRule rule) {
461 FlowEntry entry = null;
462 for (FlowEntry fe :
463 flowRuleService.getFlowEntries(rule.deviceId())) {
464 if (rule.exactMatch(fe)) {
465 entry = fe;
466 }
467 }
468
469 FlowRule vRule = virtualize(entry);
470 FlowEntry vEntry = new DefaultFlowEntry(vRule, entry.state(),
471 entry.life(), entry.packets(),
472 entry.bytes());
473
474 return vEntry;
475 }
476 }
477
478 private class InternalVirtualFlowRuleManager {
479 /** <Virtual Network ID, Virtual Device ID, Virtual Flow Rules>.*/
480 final Table<NetworkId, DeviceId, Set<FlowRule>> flowRuleTable
481 = HashBasedTable.create();
482
483 /** <Virtual Network ID, Virtual Device ID, Virtual Flow Rules>.*/
484 final Table<NetworkId, DeviceId, Set<FlowRule>> missingFlowRuleTable
485 = HashBasedTable.create();
486
487 /** <Virtual Network ID, Virtual Device ID, Virtual Flow Entries>.*/
488 final Table<NetworkId, DeviceId, Set<FlowEntry>> flowEntryTable
489 = HashBasedTable.create();
490
491 /** <Physical Flow Rule, Virtual Network ID>.*/
492 final Map<FlowRule, NetworkId> ingressRuleMap = Maps.newConcurrentMap();
493
494 /** <Physical Flow Rule, Virtual Virtual Flow Rule>.*/
495 final Map<FlowRule, FlowRule> virtualizationMap = Maps.newConcurrentMap();
496
497 private int getFlowRuleCount(NetworkId networkId, DeviceId deviceId) {
498 return flowRuleTable.get(networkId, deviceId).size();
499 }
500
501 private int getMissingFlowCount(NetworkId networkId, DeviceId deviceId) {
502 return missingFlowRuleTable.get(networkId, deviceId).size();
503 }
504
505 private int getFlowEntryCount(NetworkId networkId, DeviceId deviceId) {
506 return flowEntryTable.get(networkId, deviceId).size();
507 }
508
509 private Iterable<FlowRule> getFlowRules(NetworkId networkId,
510 DeviceId deviceId) {
511 return flowRuleTable.get(networkId, deviceId);
512 }
513
514 private Iterable<FlowEntry> getFlowEntries(NetworkId networkId,
515 DeviceId deviceId) {
516 return flowEntryTable.get(networkId, deviceId);
517 }
518
519 private void addFlowRule(NetworkId networkId, DeviceId deviceId,
520 FlowRule flowRule) {
521 Set<FlowRule> set = flowRuleTable.get(networkId, deviceId);
522 if (set == null) {
523 set = Sets.newHashSet();
524 flowRuleTable.put(networkId, deviceId, set);
525 }
526 set.add(flowRule);
527 }
528
529 private void removeFlowRule(NetworkId networkId, DeviceId deviceId,
530 FlowRule flowRule) {
531 Set<FlowRule> set = flowRuleTable.get(networkId, deviceId);
532 if (set == null) {
533 return;
534 }
535 set.remove(flowRule);
536 }
537
538 private Set<FlowRule> getMissingRules(NetworkId networkId,
539 DeviceId deviceId) {
540 return missingFlowRuleTable.get(networkId, deviceId);
541 }
542
543 private void addMissingFlowRule(NetworkId networkId, DeviceId deviceId,
544 FlowRule flowRule) {
545 Set<FlowRule> set = missingFlowRuleTable.get(networkId, deviceId);
546 if (set == null) {
547 set = Sets.newHashSet();
548 missingFlowRuleTable.put(networkId, deviceId, set);
549 }
550 set.add(flowRule);
551 }
552
553 private void removeMissingFlowRule(NetworkId networkId, DeviceId deviceId,
554 FlowRule flowRule) {
555 Set<FlowRule> set = missingFlowRuleTable.get(networkId, deviceId);
556 if (set == null) {
557 return;
558 }
559 set.remove(flowRule);
560 }
561
562 private void addFlowEntry(NetworkId networkId, DeviceId deviceId,
563 FlowEntry flowEntry) {
564 Set<FlowEntry> set = flowEntryTable.get(networkId, deviceId);
565 if (set == null) {
566 set = Sets.newHashSet();
567 flowEntryTable.put(networkId, deviceId, set);
568 }
569
570 //Replace old entry with new one
571 set.stream().filter(fe -> fe.exactMatch(flowEntry))
572 .forEach(set::remove);
573 set.add(flowEntry);
574
575 //Remove old entry from missing flow
576 getMissingRules(networkId, deviceId).stream()
577 .filter(fr -> fr.exactMatch(flowEntry))
578 .forEach(fr -> removeMissingFlowRule(networkId, deviceId, fr));
579 }
580
581 private void removeFlowEntry(NetworkId networkId, DeviceId deviceId,
582 FlowEntry flowEntry) {
583 Set<FlowEntry> set = flowEntryTable.get(networkId, deviceId);
584 if (set == null) {
585 return;
586 }
587 set.remove(flowEntry);
588 }
589
590 private void addIngressRule(FlowRule virtualRule, FlowRule physicalRule,
591 NetworkId networkId) {
592 ingressRuleMap.put(physicalRule, networkId);
593 virtualizationMap.put(physicalRule, virtualRule);
594 }
595
596 private FlowRule getVirtualRule(FlowRule physicalRule) {
597 return virtualizationMap.get(physicalRule);
598 }
599
600 private Set<FlowRule> getAllPhysicalRule() {
601 return ImmutableSet.copyOf(virtualizationMap.keySet());
602 }
603
604 private NetworkId getVirtualNetworkId(FlowRule physicalRule) {
605 return ingressRuleMap.get(physicalRule);
606 }
607
608 /**
609 * Test the rule is the ingress rule for virtual rules.
610 *
611 * @param flowRule A flow rule from underlying data plane to be translated
612 * @return True when the rule is for ingress point for a virtual switch
613 */
614 private boolean isVirtualIngressRule(FlowRule flowRule) {
615 return ingressRuleMap.containsKey(flowRule);
616 }
617
618 private Set<Pair<NetworkId, DeviceId>> getCompletedDevice(boolean
619 withMissing) {
620
621 Set<Pair<NetworkId, DeviceId>> completed = new HashSet<>();
622
623 for (Table.Cell<NetworkId, DeviceId, Set<FlowRule>> cell
624 : flowRuleTable.cellSet()) {
625
626 int ruleCount = getFlowRuleCount(cell.getRowKey(),
627 cell.getColumnKey());
628 int missingFlowCount = getMissingFlowCount(cell.getRowKey(),
629 cell.getColumnKey());
630 int entryCount = getFlowEntryCount(cell.getRowKey(),
631 cell.getColumnKey());
632
633 if (withMissing && (ruleCount == missingFlowCount + entryCount)) {
634 if (ruleCount < entryCount) {
635 completed.add(new Pair<>(cell.getRowKey(),
636 cell.getColumnKey()));
637 }
638 } else if (ruleCount == entryCount) {
639 completed.add(new Pair<>(cell.getRowKey(),
640 cell.getColumnKey()));
641 }
642 }
643 return completed;
644 }
645 }
646
647 private class DefaultInternalRoutingAlgorithm
648 implements InternalRoutingAlgorithm {
649
650 @Override
651 public Path findPath(ConnectPoint src, ConnectPoint dst) {
652 Set<Path> paths =
653 topologyService.getPaths(topologyService.currentTopology(),
654 src.deviceId(),
655 dst.deviceId());
656
657 if (paths.isEmpty()) {
658 return null;
659 }
660
661 //TODO the logic find the best path
662 return (Path) paths.toArray()[0];
663 }
664 }
665}