Committed by
Gerrit Code Review
[ONOS-3831,ONOS-3836] Load balance algorithm for sfc
Change-Id: I48a428587420ce6d782c128b835b5bb90e0cacfe
Showing
5 changed files
with
238 additions
and
81 deletions
apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/NshSpiIdGenerators.java
deleted
100644 → 0
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.sfc.manager; | ||
17 | - | ||
18 | -import java.util.concurrent.atomic.AtomicInteger; | ||
19 | - | ||
20 | -/** | ||
21 | - * Unique NSH SPI Id generator for NSH header. | ||
22 | - */ | ||
23 | -public final class NshSpiIdGenerators { | ||
24 | - | ||
25 | - private static final AtomicInteger NSH_SPI_ID_GEN = new AtomicInteger(); | ||
26 | - private static final int MAX_NSH_SPI_ID = 0x7FFFFFFF; | ||
27 | - private static int nshSpiId; | ||
28 | - | ||
29 | - /** | ||
30 | - * Default constructor. | ||
31 | - */ | ||
32 | - private NshSpiIdGenerators() { | ||
33 | - } | ||
34 | - | ||
35 | - /** | ||
36 | - * Get the next NSH SPI id. | ||
37 | - * | ||
38 | - * @return NSH SPI id | ||
39 | - */ | ||
40 | - public static int create() { | ||
41 | - do { | ||
42 | - if (nshSpiId >= MAX_NSH_SPI_ID) { | ||
43 | - if (NSH_SPI_ID_GEN.get() >= MAX_NSH_SPI_ID) { | ||
44 | - NSH_SPI_ID_GEN.set(0); | ||
45 | - } | ||
46 | - } | ||
47 | - nshSpiId = NSH_SPI_ID_GEN.incrementAndGet(); | ||
48 | - } while (nshSpiId > MAX_NSH_SPI_ID); | ||
49 | - return nshSpiId; | ||
50 | - } | ||
51 | -} |
... | @@ -18,9 +18,10 @@ package org.onosproject.sfc.manager.impl; | ... | @@ -18,9 +18,10 @@ package org.onosproject.sfc.manager.impl; |
18 | import static org.slf4j.LoggerFactory.getLogger; | 18 | import static org.slf4j.LoggerFactory.getLogger; |
19 | 19 | ||
20 | import java.util.Collection; | 20 | import java.util.Collection; |
21 | +import java.util.Iterator; | ||
22 | +import java.util.List; | ||
23 | +import java.util.Optional; | ||
21 | import java.util.Set; | 24 | import java.util.Set; |
22 | -import java.util.concurrent.ConcurrentHashMap; | ||
23 | -import java.util.concurrent.ConcurrentMap; | ||
24 | 25 | ||
25 | import org.apache.felix.scr.annotations.Activate; | 26 | import org.apache.felix.scr.annotations.Activate; |
26 | import org.apache.felix.scr.annotations.Component; | 27 | import org.apache.felix.scr.annotations.Component; |
... | @@ -38,8 +39,14 @@ import org.onlab.util.ItemNotFoundException; | ... | @@ -38,8 +39,14 @@ import org.onlab.util.ItemNotFoundException; |
38 | import org.onlab.util.KryoNamespace; | 39 | import org.onlab.util.KryoNamespace; |
39 | import org.onosproject.core.ApplicationId; | 40 | import org.onosproject.core.ApplicationId; |
40 | import org.onosproject.core.CoreService; | 41 | import org.onosproject.core.CoreService; |
42 | +import org.onosproject.core.IdGenerator; | ||
43 | +import org.onosproject.net.ConnectPoint; | ||
41 | import org.onosproject.net.NshServicePathId; | 44 | import org.onosproject.net.NshServicePathId; |
42 | import org.onosproject.net.PortNumber; | 45 | import org.onosproject.net.PortNumber; |
46 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
47 | +import org.onosproject.net.flow.TrafficTreatment; | ||
48 | +import org.onosproject.net.packet.DefaultOutboundPacket; | ||
49 | +import org.onosproject.net.packet.OutboundPacket; | ||
43 | import org.onosproject.net.packet.PacketContext; | 50 | import org.onosproject.net.packet.PacketContext; |
44 | import org.onosproject.net.packet.PacketProcessor; | 51 | import org.onosproject.net.packet.PacketProcessor; |
45 | import org.onosproject.net.packet.PacketService; | 52 | import org.onosproject.net.packet.PacketService; |
... | @@ -47,13 +54,19 @@ import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService; | ... | @@ -47,13 +54,19 @@ import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService; |
47 | import org.onosproject.sfc.forwarder.impl.ServiceFunctionForwarderImpl; | 54 | import org.onosproject.sfc.forwarder.impl.ServiceFunctionForwarderImpl; |
48 | import org.onosproject.sfc.installer.FlowClassifierInstallerService; | 55 | import org.onosproject.sfc.installer.FlowClassifierInstallerService; |
49 | import org.onosproject.sfc.installer.impl.FlowClassifierInstallerImpl; | 56 | import org.onosproject.sfc.installer.impl.FlowClassifierInstallerImpl; |
50 | -import org.onosproject.sfc.manager.NshSpiIdGenerators; | ||
51 | import org.onosproject.sfc.manager.SfcService; | 57 | import org.onosproject.sfc.manager.SfcService; |
58 | +import org.onosproject.store.serializers.KryoNamespaces; | ||
59 | +import org.onosproject.store.service.DistributedSet; | ||
60 | +import org.onosproject.store.service.EventuallyConsistentMap; | ||
61 | +import org.onosproject.store.service.Serializer; | ||
62 | +import org.onosproject.store.service.StorageService; | ||
63 | +import org.onosproject.store.service.WallClockTimestamp; | ||
52 | import org.onosproject.vtnrsc.DefaultFiveTuple; | 64 | import org.onosproject.vtnrsc.DefaultFiveTuple; |
53 | import org.onosproject.vtnrsc.FiveTuple; | 65 | import org.onosproject.vtnrsc.FiveTuple; |
54 | import org.onosproject.vtnrsc.FixedIp; | 66 | import org.onosproject.vtnrsc.FixedIp; |
55 | import org.onosproject.vtnrsc.FlowClassifier; | 67 | import org.onosproject.vtnrsc.FlowClassifier; |
56 | import org.onosproject.vtnrsc.FlowClassifierId; | 68 | import org.onosproject.vtnrsc.FlowClassifierId; |
69 | +import org.onosproject.vtnrsc.LoadBalanceId; | ||
57 | import org.onosproject.vtnrsc.PortChain; | 70 | import org.onosproject.vtnrsc.PortChain; |
58 | import org.onosproject.vtnrsc.PortChainId; | 71 | import org.onosproject.vtnrsc.PortChainId; |
59 | import org.onosproject.vtnrsc.PortPair; | 72 | import org.onosproject.vtnrsc.PortPair; |
... | @@ -68,10 +81,13 @@ import org.onosproject.vtnrsc.event.VtnRscEventFeedback; | ... | @@ -68,10 +81,13 @@ import org.onosproject.vtnrsc.event.VtnRscEventFeedback; |
68 | import org.onosproject.vtnrsc.event.VtnRscListener; | 81 | import org.onosproject.vtnrsc.event.VtnRscListener; |
69 | import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService; | 82 | import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService; |
70 | import org.onosproject.vtnrsc.portchain.PortChainService; | 83 | import org.onosproject.vtnrsc.portchain.PortChainService; |
84 | +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService; | ||
71 | import org.onosproject.vtnrsc.service.VtnRscService; | 85 | import org.onosproject.vtnrsc.service.VtnRscService; |
72 | import org.onosproject.vtnrsc.virtualport.VirtualPortService; | 86 | import org.onosproject.vtnrsc.virtualport.VirtualPortService; |
73 | import org.slf4j.Logger; | 87 | import org.slf4j.Logger; |
74 | 88 | ||
89 | +import com.google.common.collect.Lists; | ||
90 | + | ||
75 | /** | 91 | /** |
76 | * Provides implementation of SFC Service. | 92 | * Provides implementation of SFC Service. |
77 | */ | 93 | */ |
... | @@ -80,9 +96,13 @@ import org.slf4j.Logger; | ... | @@ -80,9 +96,13 @@ import org.slf4j.Logger; |
80 | public class SfcManager implements SfcService { | 96 | public class SfcManager implements SfcService { |
81 | 97 | ||
82 | private final Logger log = getLogger(getClass()); | 98 | private final Logger log = getLogger(getClass()); |
99 | + | ||
100 | + private String nshSpiIdTopic = "nsh-spi-id"; | ||
83 | private static final String APP_ID = "org.onosproject.app.vtn"; | 101 | private static final String APP_ID = "org.onosproject.app.vtn"; |
84 | private static final int SFC_PRIORITY = 1000; | 102 | private static final int SFC_PRIORITY = 1000; |
85 | private static final int NULL_PORT = 0; | 103 | private static final int NULL_PORT = 0; |
104 | + private static final int MAX_NSH_SPI_ID = 0x7FFFF; | ||
105 | + private static final int MAX_LOAD_BALANCE_ID = 0x20; | ||
86 | 106 | ||
87 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 107 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
88 | protected VtnRscService vtnRscService; | 108 | protected VtnRscService vtnRscService; |
... | @@ -97,26 +117,34 @@ public class SfcManager implements SfcService { | ... | @@ -97,26 +117,34 @@ public class SfcManager implements SfcService { |
97 | protected PortChainService portChainService; | 117 | protected PortChainService portChainService; |
98 | 118 | ||
99 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 119 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
120 | + protected PortPairGroupService portPairGroupService; | ||
121 | + | ||
122 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
100 | protected FlowClassifierService flowClassifierService; | 123 | protected FlowClassifierService flowClassifierService; |
101 | 124 | ||
102 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 125 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
103 | protected VirtualPortService virtualPortService; | 126 | protected VirtualPortService virtualPortService; |
104 | 127 | ||
105 | - private SfcPacketProcessor processor = new SfcPacketProcessor(); | 128 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
129 | + protected StorageService storageService; | ||
130 | + | ||
131 | + protected SfcPacketProcessor processor = new SfcPacketProcessor(); | ||
106 | 132 | ||
107 | protected ApplicationId appId; | 133 | protected ApplicationId appId; |
108 | - private ServiceFunctionForwarderService serviceFunctionForwarderService; | 134 | + protected ServiceFunctionForwarderService serviceFunctionForwarder; |
109 | - private FlowClassifierInstallerService flowClassifierInstallerService; | 135 | + protected FlowClassifierInstallerService flowClassifierInstaller; |
136 | + protected IdGenerator nshSpiIdGenerator; | ||
137 | + protected EventuallyConsistentMap<PortChainId, Integer> nshSpiPortChainMap; | ||
138 | + protected DistributedSet<Integer> nshSpiIdFreeList; | ||
110 | 139 | ||
111 | private final VtnRscListener vtnRscListener = new InnerVtnRscListener(); | 140 | private final VtnRscListener vtnRscListener = new InnerVtnRscListener(); |
112 | 141 | ||
113 | - private ConcurrentMap<PortChainId, NshServicePathId> nshSpiPortChainMap = new ConcurrentHashMap<>(); | ||
114 | - | ||
115 | @Activate | 142 | @Activate |
116 | public void activate() { | 143 | public void activate() { |
117 | appId = coreService.registerApplication(APP_ID); | 144 | appId = coreService.registerApplication(APP_ID); |
118 | - serviceFunctionForwarderService = new ServiceFunctionForwarderImpl(appId); | 145 | + serviceFunctionForwarder = new ServiceFunctionForwarderImpl(appId); |
119 | - flowClassifierInstallerService = new FlowClassifierInstallerImpl(appId); | 146 | + flowClassifierInstaller = new FlowClassifierInstallerImpl(appId); |
147 | + nshSpiIdGenerator = coreService.getIdGenerator(nshSpiIdTopic); | ||
120 | 148 | ||
121 | vtnRscService.addListener(vtnRscListener); | 149 | vtnRscService.addListener(vtnRscListener); |
122 | 150 | ||
... | @@ -127,6 +155,18 @@ public class SfcManager implements SfcService { | ... | @@ -127,6 +155,18 @@ public class SfcManager implements SfcService { |
127 | .register(FlowClassifierId.class) | 155 | .register(FlowClassifierId.class) |
128 | .register(PortChainId.class); | 156 | .register(PortChainId.class); |
129 | 157 | ||
158 | + nshSpiPortChainMap = storageService.<PortChainId, Integer>eventuallyConsistentMapBuilder() | ||
159 | + .withName("nshSpiPortChainMap") | ||
160 | + .withSerializer(serializer) | ||
161 | + .withTimestampProvider((k, v) -> new WallClockTimestamp()) | ||
162 | + .build(); | ||
163 | + | ||
164 | + nshSpiIdFreeList = storageService.<Integer>setBuilder() | ||
165 | + .withName("nshSpiIdDeletedList") | ||
166 | + .withSerializer(Serializer.using(KryoNamespaces.API)) | ||
167 | + .build() | ||
168 | + .asDistributedSet(); | ||
169 | + | ||
130 | packetService.addProcessor(processor, PacketProcessor.director(SFC_PRIORITY)); | 170 | packetService.addProcessor(processor, PacketProcessor.director(SFC_PRIORITY)); |
131 | log.info("Started"); | 171 | log.info("Started"); |
132 | } | 172 | } |
... | @@ -230,15 +270,20 @@ public class SfcManager implements SfcService { | ... | @@ -230,15 +270,20 @@ public class SfcManager implements SfcService { |
230 | NshServicePathId nshSpi; | 270 | NshServicePathId nshSpi; |
231 | log.info("onPortChainCreated"); | 271 | log.info("onPortChainCreated"); |
232 | if (nshSpiPortChainMap.containsKey(portChain.portChainId())) { | 272 | if (nshSpiPortChainMap.containsKey(portChain.portChainId())) { |
233 | - nshSpi = nshSpiPortChainMap.get(portChain.portChainId()); | 273 | + nshSpi = NshServicePathId.of(nshSpiPortChainMap.get(portChain.portChainId())); |
234 | } else { | 274 | } else { |
235 | - nshSpi = NshServicePathId.of(NshSpiIdGenerators.create()); | 275 | + int id = getNextNshSpi(); |
236 | - nshSpiPortChainMap.put(portChain.portChainId(), nshSpi); | 276 | + if (id > MAX_NSH_SPI_ID) { |
277 | + log.error("Reached max limit of service path index." | ||
278 | + + "Failed to install SFC for port chain {}", portChain.portChainId().toString()); | ||
279 | + return; | ||
280 | + } | ||
281 | + nshSpi = NshServicePathId.of(id); | ||
282 | + nshSpiPortChainMap.put(portChain.portChainId(), new Integer(id)); | ||
237 | } | 283 | } |
238 | 284 | ||
239 | - // install in OVS. | 285 | + // Install classifier rule to send the packet to controller |
240 | - flowClassifierInstallerService.installFlowClassifier(portChain, nshSpi); | 286 | + flowClassifierInstaller.installFlowClassifier(portChain, nshSpi); |
241 | - serviceFunctionForwarderService.installForwardingRule(portChain, nshSpi); | ||
242 | } | 287 | } |
243 | 288 | ||
244 | @Override | 289 | @Override |
... | @@ -248,13 +293,47 @@ public class SfcManager implements SfcService { | ... | @@ -248,13 +293,47 @@ public class SfcManager implements SfcService { |
248 | throw new ItemNotFoundException("Unable to find NSH SPI"); | 293 | throw new ItemNotFoundException("Unable to find NSH SPI"); |
249 | } | 294 | } |
250 | 295 | ||
251 | - NshServicePathId nshSpi = nshSpiPortChainMap.get(portChain.portChainId()); | 296 | + int nshSpiId = nshSpiPortChainMap.get(portChain.portChainId()); |
252 | - // uninstall from OVS. | 297 | + // Uninstall classifier rules |
253 | - flowClassifierInstallerService.unInstallFlowClassifier(portChain, nshSpi); | 298 | + flowClassifierInstaller.unInstallFlowClassifier(portChain, NshServicePathId.of(nshSpiId)); |
254 | - serviceFunctionForwarderService.unInstallForwardingRule(portChain, nshSpi); | 299 | + // remove from nshSpiPortChainMap and add to nshSpiIdFreeList |
300 | + nshSpiPortChainMap.remove(portChain.portChainId()); | ||
301 | + nshSpiIdFreeList.add(nshSpiId); | ||
302 | + | ||
303 | + // Uninstall load balanced classifier and forwarding rules. | ||
304 | + NshServicePathId nshSpi; | ||
305 | + LoadBalanceId id; | ||
306 | + List<LoadBalanceId> processedIdList = Lists.newArrayList(); | ||
307 | + Set<FiveTuple> fiveTupleSet = portChain.getLoadBalanceIdMapKeys(); | ||
308 | + for (FiveTuple fiveTuple : fiveTupleSet) { | ||
309 | + id = portChain.getLoadBalanceId(fiveTuple); | ||
310 | + if (processedIdList.contains(id)) { | ||
311 | + // multiple five tuple can have single path. | ||
312 | + continue; | ||
313 | + } else { | ||
314 | + processedIdList.add(id); | ||
315 | + } | ||
316 | + nshSpi = NshServicePathId.of(getNshServicePathId(id, nshSpiId)); | ||
317 | + flowClassifierInstaller.unInstallLoadBalancedFlowClassifier(portChain, fiveTuple, nshSpi); | ||
318 | + serviceFunctionForwarder.unInstallLoadBalancedForwardingRule(portChain.getLoadBalancePath(fiveTuple), | ||
319 | + nshSpi); | ||
320 | + } | ||
321 | + } | ||
255 | 322 | ||
256 | - // remove SPI. No longer it will be used. | 323 | + /** |
257 | - nshSpiPortChainMap.remove(nshSpi); | 324 | + * Get next nsh service path identifier. |
325 | + * | ||
326 | + * @return value of service path identifier | ||
327 | + */ | ||
328 | + int getNextNshSpi() { | ||
329 | + // If there is any free id use it. Otherwise generate new id. | ||
330 | + if (nshSpiIdFreeList.isEmpty()) { | ||
331 | + return (int) nshSpiIdGenerator.getNewId(); | ||
332 | + } | ||
333 | + Iterator<Integer> it = nshSpiIdFreeList.iterator(); | ||
334 | + Integer value = it.next(); | ||
335 | + nshSpiIdFreeList.remove(value); | ||
336 | + return value; | ||
258 | } | 337 | } |
259 | 338 | ||
260 | private class SfcPacketProcessor implements PacketProcessor { | 339 | private class SfcPacketProcessor implements PacketProcessor { |
... | @@ -296,6 +375,10 @@ public class SfcManager implements SfcService { | ... | @@ -296,6 +375,10 @@ public class SfcManager implements SfcService { |
296 | // Identify the port chain to which the packet belongs | 375 | // Identify the port chain to which the packet belongs |
297 | for (final PortChain portChain : portChains) { | 376 | for (final PortChain portChain : portChains) { |
298 | 377 | ||
378 | + if (!portChain.tenantId().equals(fiveTuple.tenantId())) { | ||
379 | + continue; | ||
380 | + } | ||
381 | + | ||
299 | Iterable<FlowClassifierId> flowClassifiers = portChain.flowClassifiers(); | 382 | Iterable<FlowClassifierId> flowClassifiers = portChain.flowClassifiers(); |
300 | 383 | ||
301 | // One port chain can have multiple flow classifiers. | 384 | // One port chain can have multiple flow classifiers. |
... | @@ -375,6 +458,67 @@ public class SfcManager implements SfcService { | ... | @@ -375,6 +458,67 @@ public class SfcManager implements SfcService { |
375 | return portChainId; | 458 | return portChainId; |
376 | } | 459 | } |
377 | 460 | ||
461 | + /** | ||
462 | + * Find the load balanced path set it to port chain for the given five tuple. | ||
463 | + * | ||
464 | + * @param portChainId port chain id | ||
465 | + * @param fiveTuple five tuple info | ||
466 | + * @return load balance id | ||
467 | + */ | ||
468 | + private LoadBalanceId loadBalanceSfc(PortChainId portChainId, FiveTuple fiveTuple) { | ||
469 | + | ||
470 | + // Get the port chain | ||
471 | + PortChain portChain = portChainService.getPortChain(portChainId); | ||
472 | + List<PortPairId> loadBalancePath = Lists.newArrayList(); | ||
473 | + LoadBalanceId id; | ||
474 | + int paths = portChain.getLoadBalancePathSize(); | ||
475 | + if (paths >= MAX_LOAD_BALANCE_ID) { | ||
476 | + log.info("Max limit reached for load balance paths. " | ||
477 | + + "Reusing the created path for port chain {} with five tuple {}", | ||
478 | + portChainId, fiveTuple); | ||
479 | + id = LoadBalanceId.of((byte) ((paths + 1) % MAX_LOAD_BALANCE_ID)); | ||
480 | + portChain.addLoadBalancePath(fiveTuple, id, portChain.getLoadBalancePath(id)); | ||
481 | + } | ||
482 | + | ||
483 | + // Get the list of port pair groups from port chain | ||
484 | + Iterable<PortPairGroupId> portPairGroups = portChain.portPairGroups(); | ||
485 | + for (final PortPairGroupId portPairGroupId : portPairGroups) { | ||
486 | + PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId); | ||
487 | + | ||
488 | + // Get the list of port pair ids from port pair group. | ||
489 | + Iterable<PortPairId> portPairs = portPairGroup.portPairs(); | ||
490 | + int minLoad = 0xFFF; | ||
491 | + PortPairId minLoadPortPairId = null; | ||
492 | + for (final PortPairId portPairId : portPairs) { | ||
493 | + int load = portPairGroup.getLoad(portPairId); | ||
494 | + if (load == 0) { | ||
495 | + minLoadPortPairId = portPairId; | ||
496 | + break; | ||
497 | + } else { | ||
498 | + // Check the port pair which has min load. | ||
499 | + if (load < minLoad) { | ||
500 | + minLoad = load; | ||
501 | + minLoadPortPairId = portPairId; | ||
502 | + } | ||
503 | + } | ||
504 | + } | ||
505 | + if (minLoadPortPairId != null) { | ||
506 | + loadBalancePath.add(minLoadPortPairId); | ||
507 | + portPairGroup.addLoad(minLoadPortPairId); | ||
508 | + } | ||
509 | + } | ||
510 | + | ||
511 | + // Check if the path already exists, if not create a new id | ||
512 | + Optional<LoadBalanceId> output = portChain.matchPath(loadBalancePath); | ||
513 | + if (output.isPresent()) { | ||
514 | + id = output.get(); | ||
515 | + } else { | ||
516 | + id = LoadBalanceId.of((byte) (paths + 1)); | ||
517 | + } | ||
518 | + | ||
519 | + portChain.addLoadBalancePath(fiveTuple, id, loadBalancePath); | ||
520 | + return id; | ||
521 | + } | ||
378 | 522 | ||
379 | /** | 523 | /** |
380 | * Get the tenant id for the given mac address. | 524 | * Get the tenant id for the given mac address. |
... | @@ -443,9 +587,59 @@ public class SfcManager implements SfcService { | ... | @@ -443,9 +587,59 @@ public class SfcManager implements SfcService { |
443 | return; | 587 | return; |
444 | } | 588 | } |
445 | 589 | ||
446 | - // TODO | 590 | + // Once the 5 tuple and port chain are identified, give this input for load balancing |
591 | + LoadBalanceId id = loadBalanceSfc(portChainId, fiveTuple); | ||
592 | + // Get nsh service path index | ||
593 | + NshServicePathId nshSpi; | ||
594 | + PortChain portChain = portChainService.getPortChain(portChainId); | ||
595 | + if (nshSpiPortChainMap.containsKey(portChain.portChainId())) { | ||
596 | + int nshSpiId = nshSpiPortChainMap.get(portChain.portChainId()); | ||
597 | + nshSpi = NshServicePathId.of(getNshServicePathId(id, nshSpiId)); | ||
598 | + } else { | ||
599 | + int nshSpiId = getNextNshSpi(); | ||
600 | + if (nshSpiId > MAX_NSH_SPI_ID) { | ||
601 | + log.error("Reached max limit of service path index." | ||
602 | + + "Failed to install SFC for port chain {}", portChain.portChainId()); | ||
603 | + return; | ||
604 | + } | ||
605 | + nshSpi = NshServicePathId.of(getNshServicePathId(id, nshSpiId)); | ||
606 | + nshSpiPortChainMap.put(portChain.portChainId(), new Integer(nshSpiId)); | ||
607 | + } | ||
447 | // download the required flow rules for classifier and forwarding | 608 | // download the required flow rules for classifier and forwarding |
448 | - // resend the packet back to classifier | 609 | + // install in OVS. |
610 | + ConnectPoint connectPoint = flowClassifierInstaller.installLoadBalancedFlowClassifier(portChain, | ||
611 | + fiveTuple, nshSpi); | ||
612 | + serviceFunctionForwarder.installLoadBalancedForwardingRule(portChain.getLoadBalancePath(fiveTuple), | ||
613 | + nshSpi); | ||
614 | + sendPacket(context, connectPoint); | ||
449 | } | 615 | } |
616 | + | ||
617 | + /** | ||
618 | + * Send packet back to classifier. | ||
619 | + * | ||
620 | + * @param context packet context | ||
621 | + * @param connectPoint connect point of first service function | ||
622 | + */ | ||
623 | + private void sendPacket(PacketContext context, ConnectPoint connectPoint) { | ||
624 | + | ||
625 | + TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build(); | ||
626 | + OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(), treatment, | ||
627 | + context.inPacket().unparsed()); | ||
628 | + packetService.emit(packet); | ||
629 | + log.trace("Sending packet: {}", packet); | ||
630 | + } | ||
631 | + } | ||
632 | + | ||
633 | + /** | ||
634 | + * Encapsulate 5 bit load balance id to nsh spi. | ||
635 | + * | ||
636 | + * @param id load balance identifier | ||
637 | + * @param nshSpiId nsh service path index | ||
638 | + * @return updated service path index | ||
639 | + */ | ||
640 | + protected int getNshServicePathId(LoadBalanceId id, int nshSpiId) { | ||
641 | + int nshSpiNew = nshSpiId << 5; | ||
642 | + nshSpiNew = nshSpiNew | id.loadBalanceId(); | ||
643 | + return nshSpiNew; | ||
450 | } | 644 | } |
451 | } | 645 | } | ... | ... |
... | @@ -142,6 +142,14 @@ public final class DefaultPortChain implements PortChain { | ... | @@ -142,6 +142,14 @@ public final class DefaultPortChain implements PortChain { |
142 | } | 142 | } |
143 | 143 | ||
144 | @Override | 144 | @Override |
145 | + public int getLoadBalancePathSize() { | ||
146 | + if (sfcLoadBalanceIdMap.isEmpty()) { | ||
147 | + return 0; | ||
148 | + } | ||
149 | + return sfcLoadBalanceIdMap.size(); | ||
150 | + } | ||
151 | + | ||
152 | + @Override | ||
145 | public Optional<LoadBalanceId> matchPath(List<PortPairId> path) { | 153 | public Optional<LoadBalanceId> matchPath(List<PortPairId> path) { |
146 | 154 | ||
147 | LoadBalanceId id = null; | 155 | LoadBalanceId id = null; | ... | ... |
... | @@ -113,6 +113,13 @@ public interface PortChain { | ... | @@ -113,6 +113,13 @@ public interface PortChain { |
113 | List<PortPairId> getLoadBalancePath(FiveTuple fiveTuple); | 113 | List<PortPairId> getLoadBalancePath(FiveTuple fiveTuple); |
114 | 114 | ||
115 | /** | 115 | /** |
116 | + * Get the no of load balance paths created. | ||
117 | + * | ||
118 | + * @return size of load balanced paths | ||
119 | + */ | ||
120 | + int getLoadBalancePathSize(); | ||
121 | + | ||
122 | + /** | ||
116 | * Match the given path with existing load balanced paths. | 123 | * Match the given path with existing load balanced paths. |
117 | * | 124 | * |
118 | * @param path load balanced path | 125 | * @param path load balanced path | ... | ... |
... | @@ -142,38 +142,37 @@ public class PortChainResourceTest extends VtnResourceTest { | ... | @@ -142,38 +142,37 @@ public class PortChainResourceTest extends VtnResourceTest { |
142 | 142 | ||
143 | @Override | 143 | @Override |
144 | public void addLoadBalancePath(FiveTuple fiveTuple, LoadBalanceId id, List<PortPairId> path) { | 144 | public void addLoadBalancePath(FiveTuple fiveTuple, LoadBalanceId id, List<PortPairId> path) { |
145 | - // TODO Auto-generated method stub | ||
146 | } | 145 | } |
147 | 146 | ||
148 | @Override | 147 | @Override |
149 | public LoadBalanceId getLoadBalanceId(FiveTuple fiveTuple) { | 148 | public LoadBalanceId getLoadBalanceId(FiveTuple fiveTuple) { |
150 | - // TODO Auto-generated method stub | ||
151 | return null; | 149 | return null; |
152 | } | 150 | } |
153 | 151 | ||
154 | @Override | 152 | @Override |
155 | public Set<FiveTuple> getLoadBalanceIdMapKeys() { | 153 | public Set<FiveTuple> getLoadBalanceIdMapKeys() { |
156 | - // TODO Auto-generated method stub | ||
157 | return null; | 154 | return null; |
158 | } | 155 | } |
159 | 156 | ||
160 | @Override | 157 | @Override |
161 | public List<PortPairId> getLoadBalancePath(LoadBalanceId id) { | 158 | public List<PortPairId> getLoadBalancePath(LoadBalanceId id) { |
162 | - // TODO Auto-generated method stub | ||
163 | return null; | 159 | return null; |
164 | } | 160 | } |
165 | 161 | ||
166 | @Override | 162 | @Override |
167 | public List<PortPairId> getLoadBalancePath(FiveTuple fiveTuple) { | 163 | public List<PortPairId> getLoadBalancePath(FiveTuple fiveTuple) { |
168 | - // TODO Auto-generated method stub | ||
169 | return null; | 164 | return null; |
170 | } | 165 | } |
171 | 166 | ||
172 | @Override | 167 | @Override |
173 | public Optional<LoadBalanceId> matchPath(List<PortPairId> path) { | 168 | public Optional<LoadBalanceId> matchPath(List<PortPairId> path) { |
174 | - // TODO Auto-generated method stub | ||
175 | return null; | 169 | return null; |
176 | } | 170 | } |
171 | + | ||
172 | + @Override | ||
173 | + public int getLoadBalancePathSize() { | ||
174 | + return 0; | ||
175 | + } | ||
177 | } | 176 | } |
178 | 177 | ||
179 | /** | 178 | /** | ... | ... |
-
Please register or login to post a comment