Committed by
Gerrit Code Review
Made OpticalPathProvisioner to store connectivity data in distributed store. (ONOS-4518)
Change-Id: I7f9ef02cab4aa1848c8926d2e88478e035076c99
Showing
8 changed files
with
686 additions
and
295 deletions
... | @@ -89,6 +89,12 @@ | ... | @@ -89,6 +89,12 @@ |
89 | </dependency> | 89 | </dependency> |
90 | 90 | ||
91 | <dependency> | 91 | <dependency> |
92 | + <groupId>org.onosproject</groupId> | ||
93 | + <artifactId>onos-core-serializers</artifactId> | ||
94 | + <version>${project.version}</version> | ||
95 | + </dependency> | ||
96 | + | ||
97 | + <dependency> | ||
92 | <groupId>com.google.guava</groupId> | 98 | <groupId>com.google.guava</groupId> |
93 | <artifactId>guava-testlib</artifactId> | 99 | <artifactId>guava-testlib</artifactId> |
94 | <scope>test</scope> | 100 | <scope>test</scope> | ... | ... |
... | @@ -22,14 +22,14 @@ import org.onlab.util.Bandwidth; | ... | @@ -22,14 +22,14 @@ import org.onlab.util.Bandwidth; |
22 | import org.onosproject.newoptical.api.OpticalConnectivityId; | 22 | import org.onosproject.newoptical.api.OpticalConnectivityId; |
23 | import org.onosproject.net.ConnectPoint; | 23 | import org.onosproject.net.ConnectPoint; |
24 | import org.onosproject.net.Link; | 24 | import org.onosproject.net.Link; |
25 | -import org.onosproject.net.Path; | ||
26 | 25 | ||
27 | import java.time.Duration; | 26 | import java.time.Duration; |
28 | -import java.util.HashSet; | ||
29 | import java.util.List; | 27 | import java.util.List; |
28 | +import java.util.Optional; | ||
30 | import java.util.Set; | 29 | import java.util.Set; |
30 | +import java.util.stream.Collectors; | ||
31 | 31 | ||
32 | -import static com.google.common.base.Preconditions.checkNotNull; | 32 | +import static com.google.common.base.Preconditions.checkState; |
33 | 33 | ||
34 | /** | 34 | /** |
35 | * Entity to store optical connectivity request and related information. | 35 | * Entity to store optical connectivity request and related information. |
... | @@ -42,48 +42,48 @@ public class OpticalConnectivity { | ... | @@ -42,48 +42,48 @@ public class OpticalConnectivity { |
42 | private final Bandwidth requestBandwidth; | 42 | private final Bandwidth requestBandwidth; |
43 | private final Duration requestLatency; | 43 | private final Duration requestLatency; |
44 | 44 | ||
45 | - // Bandwidth capacity of optical layer | 45 | + /** |
46 | - private Bandwidth opticalCapacity; | 46 | + * Set of packet link that is not yet established. |
47 | - | 47 | + * Packet links in this set are expected to be discovered after underlying (optical) path has been provisioned. |
48 | - private final Set<PacketLinkRealizedByOptical> realizingLinks = new HashSet<>(); | 48 | + */ |
49 | - | 49 | + private final ImmutableSet<PacketLinkRealizedByOptical> unestablishedLinks; |
50 | - private State state = State.CREATED; | 50 | + |
51 | - | 51 | + /** |
52 | - public enum State { | 52 | + * Set of packet link that is already established. |
53 | - CREATED, | 53 | + */ |
54 | - INSTALLING, | 54 | + private final ImmutableSet<PacketLinkRealizedByOptical> establishedLinks; |
55 | - INSTALLED, | 55 | + |
56 | - WITHDRAWING, | 56 | + public OpticalConnectivity(OpticalConnectivityId id, |
57 | - WITHDRAWN, | 57 | + List<Link> links, |
58 | - FAILED | 58 | + Bandwidth requestBandwidth, |
59 | - } | 59 | + Duration requestLatency, |
60 | - | 60 | + Set<PacketLinkRealizedByOptical> unestablishedLinks, |
61 | - public OpticalConnectivity(OpticalConnectivityId id, Path path, Bandwidth requestBandwidth, | 61 | + Set<PacketLinkRealizedByOptical> establishedLinks) { |
62 | - Duration requestLatency) { | ||
63 | this.id = id; | 62 | this.id = id; |
64 | - this.links = ImmutableList.copyOf(path.links()); | 63 | + this.links = ImmutableList.copyOf(links); |
65 | this.requestBandwidth = requestBandwidth; | 64 | this.requestBandwidth = requestBandwidth; |
66 | this.requestLatency = requestLatency; | 65 | this.requestLatency = requestLatency; |
66 | + this.unestablishedLinks = ImmutableSet.copyOf(unestablishedLinks); | ||
67 | + this.establishedLinks = ImmutableSet.copyOf(establishedLinks); | ||
67 | } | 68 | } |
68 | 69 | ||
69 | - public void setLinkEstablished(ConnectPoint src, ConnectPoint dst) { | 70 | + private OpticalConnectivity(OpticalConnectivity connectivity) { |
70 | - realizingLinks.stream().filter(l -> l.isBetween(src, dst)) | 71 | + this.id = connectivity.id; |
71 | - .findAny() | 72 | + this.links = ImmutableList.copyOf(connectivity.links); |
72 | - .ifPresent(l -> l.setEstablished(true)); | 73 | + this.requestBandwidth = connectivity.requestBandwidth; |
73 | - } | 74 | + this.requestLatency = connectivity.requestLatency; |
74 | - | 75 | + this.unestablishedLinks = ImmutableSet.copyOf(connectivity.unestablishedLinks); |
75 | - public void setLinkRemoved(ConnectPoint src, ConnectPoint dst) { | 76 | + this.establishedLinks = ImmutableSet.copyOf(connectivity.establishedLinks); |
76 | - realizingLinks.stream().filter(l -> l.isBetween(src, dst)) | ||
77 | - .findAny() | ||
78 | - .ifPresent(l -> l.setEstablished(false)); | ||
79 | } | 77 | } |
80 | 78 | ||
81 | public boolean isAllRealizingLinkEstablished() { | 79 | public boolean isAllRealizingLinkEstablished() { |
82 | - return realizingLinks.stream().allMatch(PacketLinkRealizedByOptical::isEstablished); | 80 | + // Check if all links are established |
81 | + return unestablishedLinks.isEmpty(); | ||
83 | } | 82 | } |
84 | 83 | ||
85 | public boolean isAllRealizingLinkNotEstablished() { | 84 | public boolean isAllRealizingLinkNotEstablished() { |
86 | - return !realizingLinks.stream().anyMatch(PacketLinkRealizedByOptical::isEstablished); | 85 | + // Check if any link is not established |
86 | + return establishedLinks.isEmpty(); | ||
87 | } | 87 | } |
88 | 88 | ||
89 | public OpticalConnectivityId id() { | 89 | public OpticalConnectivityId id() { |
... | @@ -102,59 +102,64 @@ public class OpticalConnectivity { | ... | @@ -102,59 +102,64 @@ public class OpticalConnectivity { |
102 | return requestLatency; | 102 | return requestLatency; |
103 | } | 103 | } |
104 | 104 | ||
105 | - public State state() { | 105 | + public Set<PacketLinkRealizedByOptical> getEstablishedLinks() { |
106 | - return state; | 106 | + return establishedLinks; |
107 | - } | 107 | + } |
108 | - | 108 | + |
109 | - public boolean state(State state) { | 109 | + public Set<PacketLinkRealizedByOptical> getUnestablishedLinks() { |
110 | - boolean valid = true; | 110 | + return unestablishedLinks; |
111 | - // reject invalid state transition | 111 | + } |
112 | - switch (this.state) { | 112 | + |
113 | - case CREATED: | 113 | + public OpticalConnectivity setLinkEstablished(ConnectPoint src, |
114 | - valid = (state == State.INSTALLING || state == State.FAILED); | 114 | + ConnectPoint dst, |
115 | - break; | 115 | + boolean established) { |
116 | - case INSTALLING: | 116 | + Set<PacketLinkRealizedByOptical> newEstablishedLinks; |
117 | - valid = (state == State.INSTALLED || state == State.FAILED); | 117 | + Set<PacketLinkRealizedByOptical> newUnestablishedLinks; |
118 | - break; | 118 | + |
119 | - case INSTALLED: | 119 | + if (established) { |
120 | - valid = (state == State.WITHDRAWING || state == State.FAILED); | 120 | + // move PacketLink from unestablished set to established set |
121 | - break; | 121 | + Optional<PacketLinkRealizedByOptical> link = this.unestablishedLinks.stream() |
122 | - case WITHDRAWING: | 122 | + .filter(l -> l.isBetween(src, dst)).findAny(); |
123 | - valid = (state == State.WITHDRAWN || state == State.FAILED); | 123 | + checkState(link.isPresent()); |
124 | - break; | 124 | + |
125 | - case FAILED: | 125 | + newUnestablishedLinks = this.unestablishedLinks.stream() |
126 | - valid = (state == State.INSTALLING || state == State.WITHDRAWING || state == State.FAILED); | 126 | + .filter(l -> !l.isBetween(src, dst)) |
127 | - break; | 127 | + .collect(Collectors.toSet()); |
128 | - default: | 128 | + newEstablishedLinks = ImmutableSet.<PacketLinkRealizedByOptical>builder() |
129 | - break; | 129 | + .addAll(this.establishedLinks) |
130 | + .add(link.get()) | ||
131 | + .build(); | ||
132 | + } else { | ||
133 | + // move PacketLink from established set to unestablished set | ||
134 | + Optional<PacketLinkRealizedByOptical> link = this.establishedLinks.stream() | ||
135 | + .filter(l -> l.isBetween(src, dst)).findAny(); | ||
136 | + checkState(link.isPresent()); | ||
137 | + | ||
138 | + newEstablishedLinks = this.establishedLinks.stream() | ||
139 | + .filter(l -> !l.isBetween(src, dst)) | ||
140 | + .collect(Collectors.toSet()); | ||
141 | + newUnestablishedLinks = ImmutableSet.<PacketLinkRealizedByOptical>builder() | ||
142 | + .addAll(this.unestablishedLinks) | ||
143 | + .add(link.get()) | ||
144 | + .build(); | ||
130 | } | 145 | } |
131 | 146 | ||
132 | - if (valid) { | 147 | + return new OpticalConnectivity(this.id, |
133 | - this.state = state; | 148 | + this.links, |
134 | - } | 149 | + this.requestBandwidth, |
135 | - | 150 | + this.requestLatency, |
136 | - return valid; | 151 | + newUnestablishedLinks, |
137 | - } | 152 | + newEstablishedLinks); |
138 | - | ||
139 | - public Bandwidth getOpticalCapacity() { | ||
140 | - return opticalCapacity; | ||
141 | - } | ||
142 | - | ||
143 | - public void setOpticalCapacity(Bandwidth opticalCapacity) { | ||
144 | - this.opticalCapacity = opticalCapacity; | ||
145 | } | 153 | } |
146 | 154 | ||
147 | - public void addRealizingLink(PacketLinkRealizedByOptical link) { | 155 | + public Set<PacketLinkRealizedByOptical> getRealizingLinks() { |
148 | - checkNotNull(link); | 156 | + return ImmutableSet.<PacketLinkRealizedByOptical>builder() |
149 | - realizingLinks.add(link); | 157 | + .addAll(unestablishedLinks) |
150 | - } | 158 | + .addAll(establishedLinks) |
151 | - | 159 | + .build(); |
152 | - public void removeRealizingLink(PacketLinkRealizedByOptical link) { | ||
153 | - checkNotNull(link); | ||
154 | - realizingLinks.remove(link); | ||
155 | } | 160 | } |
156 | 161 | ||
157 | - public Set<PacketLinkRealizedByOptical> getRealizingLinks() { | 162 | + public static OpticalConnectivity copyOf(OpticalConnectivity connectivity) { |
158 | - return ImmutableSet.copyOf(realizingLinks); | 163 | + return new OpticalConnectivity(connectivity); |
159 | } | 164 | } |
160 | } | 165 | } | ... | ... |
... | @@ -17,7 +17,6 @@ package org.onosproject.newoptical; | ... | @@ -17,7 +17,6 @@ package org.onosproject.newoptical; |
17 | 17 | ||
18 | import com.google.common.annotations.Beta; | 18 | import com.google.common.annotations.Beta; |
19 | import com.google.common.collect.ImmutableList; | 19 | import com.google.common.collect.ImmutableList; |
20 | -import com.google.common.collect.Sets; | ||
21 | 20 | ||
22 | import org.apache.commons.lang3.tuple.Pair; | 21 | import org.apache.commons.lang3.tuple.Pair; |
23 | import org.apache.felix.scr.annotations.Activate; | 22 | import org.apache.felix.scr.annotations.Activate; |
... | @@ -27,8 +26,8 @@ import org.apache.felix.scr.annotations.Reference; | ... | @@ -27,8 +26,8 @@ import org.apache.felix.scr.annotations.Reference; |
27 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 26 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
28 | import org.apache.felix.scr.annotations.Service; | 27 | import org.apache.felix.scr.annotations.Service; |
29 | import org.onlab.util.Bandwidth; | 28 | import org.onlab.util.Bandwidth; |
29 | +import org.onlab.util.KryoNamespace; | ||
30 | import org.onosproject.cluster.ClusterService; | 30 | import org.onosproject.cluster.ClusterService; |
31 | -import org.onosproject.cluster.NodeId; | ||
32 | import org.onosproject.core.ApplicationId; | 31 | import org.onosproject.core.ApplicationId; |
33 | import org.onosproject.core.CoreService; | 32 | import org.onosproject.core.CoreService; |
34 | import org.onosproject.event.ListenerTracker; | 33 | import org.onosproject.event.ListenerTracker; |
... | @@ -66,20 +65,29 @@ import org.onosproject.net.resource.Resources; | ... | @@ -66,20 +65,29 @@ import org.onosproject.net.resource.Resources; |
66 | import org.onosproject.net.topology.LinkWeight; | 65 | import org.onosproject.net.topology.LinkWeight; |
67 | import org.onosproject.net.topology.PathService; | 66 | import org.onosproject.net.topology.PathService; |
68 | import org.onosproject.net.topology.TopologyEdge; | 67 | import org.onosproject.net.topology.TopologyEdge; |
68 | +import org.onosproject.store.serializers.KryoNamespaces; | ||
69 | import org.onosproject.store.service.AtomicCounter; | 69 | import org.onosproject.store.service.AtomicCounter; |
70 | +import org.onosproject.store.service.ConsistentMap; | ||
71 | +import org.onosproject.store.service.DistributedSet; | ||
72 | +import org.onosproject.store.service.MapEvent; | ||
73 | +import org.onosproject.store.service.MapEventListener; | ||
74 | +import org.onosproject.store.service.Serializer; | ||
70 | import org.onosproject.store.service.StorageService; | 75 | import org.onosproject.store.service.StorageService; |
76 | +import org.onosproject.store.service.Versioned; | ||
71 | import org.slf4j.Logger; | 77 | import org.slf4j.Logger; |
72 | import org.slf4j.LoggerFactory; | 78 | import org.slf4j.LoggerFactory; |
73 | 79 | ||
74 | import java.time.Duration; | 80 | import java.time.Duration; |
81 | +import java.util.ArrayList; | ||
75 | import java.util.Collections; | 82 | import java.util.Collections; |
83 | +import java.util.HashMap; | ||
84 | +import java.util.HashSet; | ||
76 | import java.util.Iterator; | 85 | import java.util.Iterator; |
77 | import java.util.LinkedList; | 86 | import java.util.LinkedList; |
78 | import java.util.List; | 87 | import java.util.List; |
79 | import java.util.Map; | 88 | import java.util.Map; |
80 | import java.util.Optional; | 89 | import java.util.Optional; |
81 | import java.util.Set; | 90 | import java.util.Set; |
82 | -import java.util.concurrent.ConcurrentHashMap; | ||
83 | import java.util.stream.Collectors; | 91 | import java.util.stream.Collectors; |
84 | import java.util.stream.Stream; | 92 | import java.util.stream.Stream; |
85 | 93 | ||
... | @@ -99,6 +107,9 @@ public class OpticalPathProvisioner | ... | @@ -99,6 +107,9 @@ public class OpticalPathProvisioner |
99 | protected static final Logger log = LoggerFactory.getLogger(OpticalPathProvisioner.class); | 107 | protected static final Logger log = LoggerFactory.getLogger(OpticalPathProvisioner.class); |
100 | 108 | ||
101 | private static final String OPTICAL_CONNECTIVITY_ID_COUNTER = "optical-connectivity-id"; | 109 | private static final String OPTICAL_CONNECTIVITY_ID_COUNTER = "optical-connectivity-id"; |
110 | + private static final String LINKPATH_MAP_NAME = "newoptical-linkpath"; | ||
111 | + private static final String CONNECTIVITY_MAP_NAME = "newoptical-connectivity"; | ||
112 | + private static final String CROSSCONNECTLINK_SET_NAME = "newoptical-crossconnectlink"; | ||
102 | 113 | ||
103 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 114 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
104 | protected IntentService intentService; | 115 | protected IntentService intentService; |
... | @@ -137,14 +148,28 @@ public class OpticalPathProvisioner | ... | @@ -137,14 +148,28 @@ public class OpticalPathProvisioner |
137 | 148 | ||
138 | private ListenerTracker listeners; | 149 | private ListenerTracker listeners; |
139 | 150 | ||
140 | - private Map<PacketLinkRealizedByOptical, OpticalConnectivity> linkPathMap = new ConcurrentHashMap<>(); | 151 | + private InternalStoreListener storeListener = new InternalStoreListener(); |
141 | 152 | ||
142 | - // TODO this should be stored to distributed store | 153 | + private ConsistentMap<PacketLinkRealizedByOptical, OpticalConnectivity> linkPathMap; |
143 | - private Map<OpticalConnectivityId, OpticalConnectivity> connectivities = new ConcurrentHashMap<>(); | 154 | + |
155 | + private ConsistentMap<OpticalConnectivityId, OpticalConnectivity> connectivityMap; | ||
144 | 156 | ||
145 | - // TODO this should be stored to distributed store | ||
146 | // Map of cross connect link and installed path which uses the link | 157 | // Map of cross connect link and installed path which uses the link |
147 | - private Set<Link> usedCrossConnectLinks = Sets.newConcurrentHashSet(); | 158 | + private DistributedSet<Link> usedCrossConnectLinkSet; |
159 | + | ||
160 | + private static final KryoNamespace.Builder LINKPATH_SERIALIZER = KryoNamespace.newBuilder() | ||
161 | + .register(KryoNamespaces.API) | ||
162 | + .register(PacketLinkRealizedByOptical.class) | ||
163 | + .register(OpticalConnectivityId.class) | ||
164 | + .register(OpticalConnectivity.class); | ||
165 | + | ||
166 | + private static final KryoNamespace.Builder CONNECTIVITY_SERIALIZER = KryoNamespace.newBuilder() | ||
167 | + .register(KryoNamespaces.API) | ||
168 | + .register(OpticalConnectivityId.class) | ||
169 | + .register(OpticalConnectivity.class); | ||
170 | + | ||
171 | + private static final KryoNamespace.Builder CROSSCONNECTLINKS_SERIALIZER = KryoNamespace.newBuilder() | ||
172 | + .register(KryoNamespaces.API); | ||
148 | 173 | ||
149 | @Activate | 174 | @Activate |
150 | protected void activate() { | 175 | protected void activate() { |
... | @@ -153,17 +178,39 @@ public class OpticalPathProvisioner | ... | @@ -153,17 +178,39 @@ public class OpticalPathProvisioner |
153 | 178 | ||
154 | idCounter = storageService.getAtomicCounter(OPTICAL_CONNECTIVITY_ID_COUNTER); | 179 | idCounter = storageService.getAtomicCounter(OPTICAL_CONNECTIVITY_ID_COUNTER); |
155 | 180 | ||
181 | + linkPathMap = storageService.<PacketLinkRealizedByOptical, OpticalConnectivity>consistentMapBuilder() | ||
182 | + .withSerializer(Serializer.using(LINKPATH_SERIALIZER.build())) | ||
183 | + .withName(LINKPATH_MAP_NAME) | ||
184 | + .withApplicationId(appId) | ||
185 | + .build(); | ||
186 | + | ||
187 | + connectivityMap = storageService.<OpticalConnectivityId, OpticalConnectivity>consistentMapBuilder() | ||
188 | + .withSerializer(Serializer.using(CONNECTIVITY_SERIALIZER.build())) | ||
189 | + .withName(CONNECTIVITY_MAP_NAME) | ||
190 | + .withApplicationId(appId) | ||
191 | + .build(); | ||
192 | + | ||
193 | + usedCrossConnectLinkSet = storageService.<Link>setBuilder() | ||
194 | + .withSerializer(Serializer.using(CROSSCONNECTLINKS_SERIALIZER.build())) | ||
195 | + .withName(CROSSCONNECTLINK_SET_NAME) | ||
196 | + .withApplicationId(appId) | ||
197 | + .build() | ||
198 | + .asDistributedSet(); | ||
199 | + | ||
156 | eventDispatcher.addSink(OpticalPathEvent.class, listenerRegistry); | 200 | eventDispatcher.addSink(OpticalPathEvent.class, listenerRegistry); |
157 | 201 | ||
158 | listeners = new ListenerTracker(); | 202 | listeners = new ListenerTracker(); |
159 | listeners.addListener(linkService, new InternalLinkListener()) | 203 | listeners.addListener(linkService, new InternalLinkListener()) |
160 | .addListener(intentService, new InternalIntentListener()); | 204 | .addListener(intentService, new InternalIntentListener()); |
161 | 205 | ||
206 | + linkPathMap.addListener(storeListener); | ||
207 | + | ||
162 | log.info("Started"); | 208 | log.info("Started"); |
163 | } | 209 | } |
164 | 210 | ||
165 | @Deactivate | 211 | @Deactivate |
166 | protected void deactivate() { | 212 | protected void deactivate() { |
213 | + linkPathMap.removeListener(storeListener); | ||
167 | listeners.removeListeners(); | 214 | listeners.removeListeners(); |
168 | eventDispatcher.removeSink(OpticalPathEvent.class); | 215 | eventDispatcher.removeSink(OpticalPathEvent.class); |
169 | 216 | ||
... | @@ -205,22 +252,67 @@ public class OpticalPathProvisioner | ... | @@ -205,22 +252,67 @@ public class OpticalPathProvisioner |
205 | checkNotNull(path); | 252 | checkNotNull(path); |
206 | log.info("setupPath({}, {}, {})", path, bandwidth, latency); | 253 | log.info("setupPath({}, {}, {})", path, bandwidth, latency); |
207 | 254 | ||
208 | - // validate optical path | 255 | + // map of cross connect points (optical port -> packet port) |
209 | - List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs = getCrossConnectPoints(path); | 256 | + Map<ConnectPoint, ConnectPoint> crossConnectPointMap = new HashMap<>(); |
210 | - if (!checkXcPoints(xcPointPairs)) { | 257 | + |
211 | - // Can't setup path if cross connect points are mismatched | 258 | + // list of (src, dst) pair of optical ports between which optical path should be installed |
212 | - log.error("Failed to setup path because of mismatched cross connect points."); | 259 | + List<Pair<ConnectPoint, ConnectPoint>> crossConnectPoints = new ArrayList<>(); |
213 | - return null; | 260 | + |
261 | + // Scan path to find pairs of connect points between which optical intent is installed | ||
262 | + // opticalSrcPort works as a flag parameter to show scanning status | ||
263 | + ConnectPoint opticalSrcPort = null; | ||
264 | + for (Link link : path.links()) { | ||
265 | + if (!isCrossConnectLink(link)) { | ||
266 | + continue; | ||
267 | + } | ||
268 | + | ||
269 | + if (opticalSrcPort != null) { | ||
270 | + // opticalSrcPort!=null means src port was already found | ||
271 | + // in this case link.src() is optical layer, and link.dst() is packet layer | ||
272 | + | ||
273 | + // Check if types of src port and dst port matches | ||
274 | + Device srcDevice = checkNotNull(deviceService.getDevice(opticalSrcPort.deviceId()), | ||
275 | + "Unknown device ID"); | ||
276 | + Device dstDevice = checkNotNull(deviceService.getDevice(link.src().deviceId()), | ||
277 | + "Unknown device ID"); | ||
278 | + if (srcDevice.type() != dstDevice.type()) { | ||
279 | + log.error("Unsupported mix of cross connect points : {}, {}", | ||
280 | + srcDevice.type(), dstDevice.type()); | ||
281 | + return null; | ||
282 | + } | ||
283 | + | ||
284 | + // Update cross connect points map | ||
285 | + crossConnectPointMap.put(link.src(), link.dst()); | ||
286 | + | ||
287 | + // Add optical ports pair to list | ||
288 | + crossConnectPoints.add(Pair.of(opticalSrcPort, link.src())); | ||
289 | + | ||
290 | + // Reset flag parameter | ||
291 | + opticalSrcPort = null; | ||
292 | + } else { | ||
293 | + // opticalSrcPort==null means src port was not found yet | ||
294 | + // in this case link.src() is packet layer, and link.dst() is optical layer | ||
295 | + | ||
296 | + // Update cross connect points map | ||
297 | + crossConnectPointMap.put(link.dst(), link.src()); | ||
298 | + // Set opticalSrcPort to src of link (optical port) | ||
299 | + opticalSrcPort = link.dst(); | ||
300 | + } | ||
214 | } | 301 | } |
215 | 302 | ||
216 | - OpticalConnectivity connectivity = createConnectivity(path, bandwidth, latency); | 303 | + // create intents from cross connect points |
304 | + List<Intent> intents = createIntents(crossConnectPoints); | ||
217 | 305 | ||
218 | - // create intents from cross connect points and set connectivity information | 306 | + // create set of PacketLinkRealizedByOptical |
219 | - List<Intent> intents = createIntents(xcPointPairs, connectivity); | 307 | + Set<PacketLinkRealizedByOptical> packetLinks = createPacketLinkSet(crossConnectPoints, |
308 | + intents, crossConnectPointMap); | ||
309 | + | ||
310 | + // create OpticalConnectivity object and store information to distributed store | ||
311 | + OpticalConnectivity connectivity = createConnectivity(path, bandwidth, latency, packetLinks); | ||
220 | 312 | ||
221 | // store cross connect port usage | 313 | // store cross connect port usage |
222 | path.links().stream().filter(this::isCrossConnectLink) | 314 | path.links().stream().filter(this::isCrossConnectLink) |
223 | - .forEach(usedCrossConnectLinks::add); | 315 | + .forEach(usedCrossConnectLinkSet::add); |
224 | 316 | ||
225 | // Submit the intents | 317 | // Submit the intents |
226 | for (Intent i : intents) { | 318 | for (Intent i : intents) { |
... | @@ -231,12 +323,16 @@ public class OpticalPathProvisioner | ... | @@ -231,12 +323,16 @@ public class OpticalPathProvisioner |
231 | return connectivity.id(); | 323 | return connectivity.id(); |
232 | } | 324 | } |
233 | 325 | ||
234 | - private OpticalConnectivity createConnectivity(Path path, Bandwidth bandwidth, Duration latency) { | 326 | + private OpticalConnectivity createConnectivity(Path path, Bandwidth bandwidth, Duration latency, |
327 | + Set<PacketLinkRealizedByOptical> links) { | ||
235 | OpticalConnectivityId id = OpticalConnectivityId.of(idCounter.getAndIncrement()); | 328 | OpticalConnectivityId id = OpticalConnectivityId.of(idCounter.getAndIncrement()); |
236 | - OpticalConnectivity connectivity = new OpticalConnectivity(id, path, bandwidth, latency); | 329 | + OpticalConnectivity connectivity = new OpticalConnectivity(id, path.links(), bandwidth, latency, |
330 | + links, Collections.emptySet()); | ||
331 | + | ||
332 | + links.forEach(l -> linkPathMap.put(l, connectivity)); | ||
237 | 333 | ||
238 | // store connectivity information | 334 | // store connectivity information |
239 | - connectivities.put(connectivity.id(), connectivity); | 335 | + connectivityMap.put(connectivity.id(), connectivity); |
240 | 336 | ||
241 | return connectivity; | 337 | return connectivity; |
242 | } | 338 | } |
... | @@ -244,7 +340,7 @@ public class OpticalPathProvisioner | ... | @@ -244,7 +340,7 @@ public class OpticalPathProvisioner |
244 | @Override | 340 | @Override |
245 | public boolean removeConnectivity(OpticalConnectivityId id) { | 341 | public boolean removeConnectivity(OpticalConnectivityId id) { |
246 | log.info("removeConnectivity({})", id); | 342 | log.info("removeConnectivity({})", id); |
247 | - OpticalConnectivity connectivity = connectivities.remove(id); | 343 | + Versioned<OpticalConnectivity> connectivity = connectivityMap.remove(id); |
248 | 344 | ||
249 | if (connectivity == null) { | 345 | if (connectivity == null) { |
250 | log.info("OpticalConnectivity with id {} not found.", id); | 346 | log.info("OpticalConnectivity with id {} not found.", id); |
... | @@ -252,7 +348,7 @@ public class OpticalPathProvisioner | ... | @@ -252,7 +348,7 @@ public class OpticalPathProvisioner |
252 | } | 348 | } |
253 | 349 | ||
254 | // TODO withdraw intent only if all of connectivities that use the optical path are withdrawn | 350 | // TODO withdraw intent only if all of connectivities that use the optical path are withdrawn |
255 | - connectivity.getRealizingLinks().forEach(l -> { | 351 | + connectivity.value().getRealizingLinks().forEach(l -> { |
256 | Intent intent = intentService.getIntent(l.realizingIntentKey()); | 352 | Intent intent = intentService.getIntent(l.realizingIntentKey()); |
257 | intentService.withdraw(intent); | 353 | intentService.withdraw(intent); |
258 | }); | 354 | }); |
... | @@ -262,98 +358,34 @@ public class OpticalPathProvisioner | ... | @@ -262,98 +358,34 @@ public class OpticalPathProvisioner |
262 | 358 | ||
263 | @Override | 359 | @Override |
264 | public Optional<List<Link>> getPath(OpticalConnectivityId id) { | 360 | public Optional<List<Link>> getPath(OpticalConnectivityId id) { |
265 | - OpticalConnectivity connectivity = connectivities.get(id); | 361 | + Versioned<OpticalConnectivity> connectivity = connectivityMap.get(id); |
266 | if (connectivity == null) { | 362 | if (connectivity == null) { |
267 | log.info("OpticalConnectivity with id {} not found.", id); | 363 | log.info("OpticalConnectivity with id {} not found.", id); |
268 | return Optional.empty(); | 364 | return Optional.empty(); |
269 | } | 365 | } |
270 | 366 | ||
271 | - return Optional.of(ImmutableList.copyOf(connectivity.links())); | 367 | + return Optional.of(ImmutableList.copyOf(connectivity.value().links())); |
272 | - } | ||
273 | - | ||
274 | - /** | ||
275 | - * Returns list of (optical, packet) pairs of cross connection points of missing optical path sections. | ||
276 | - * | ||
277 | - * Scans the given multi-layer path and looks for sections that use cross connect links. | ||
278 | - * The ingress and egress points in the optical layer are combined to the packet layer ports, and | ||
279 | - * are returned in a list. | ||
280 | - * | ||
281 | - * @param path the multi-layer path | ||
282 | - * @return List of cross connect link's (packet port, optical port) pairs | ||
283 | - */ | ||
284 | - private List<Pair<ConnectPoint, ConnectPoint>> getCrossConnectPoints(Path path) { | ||
285 | - List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs = new LinkedList<>(); | ||
286 | - boolean scanning = false; | ||
287 | - | ||
288 | - for (Link link : path.links()) { | ||
289 | - if (!isCrossConnectLink(link)) { | ||
290 | - continue; | ||
291 | - } | ||
292 | - | ||
293 | - if (scanning) { | ||
294 | - // link.src() is packet, link.dst() is optical | ||
295 | - xcPointPairs.add(Pair.of(checkNotNull(link.src()), checkNotNull(link.dst()))); | ||
296 | - scanning = false; | ||
297 | - } else { | ||
298 | - // link.src() is optical, link.dst() is packet | ||
299 | - xcPointPairs.add(Pair.of(checkNotNull(link.dst()), checkNotNull(link.src()))); | ||
300 | - scanning = true; | ||
301 | - } | ||
302 | - } | ||
303 | - | ||
304 | - return xcPointPairs; | ||
305 | - } | ||
306 | - | ||
307 | - /** | ||
308 | - * Checks if optical cross connect points are of same type. | ||
309 | - * | ||
310 | - * @param xcPointPairs list of cross connection points | ||
311 | - * @return true if cross connect point pairs are of same type, false otherwise | ||
312 | - */ | ||
313 | - private boolean checkXcPoints(List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs) { | ||
314 | - checkArgument(xcPointPairs.size() % 2 == 0); | ||
315 | - | ||
316 | - Iterator<Pair<ConnectPoint, ConnectPoint>> itr = xcPointPairs.iterator(); | ||
317 | - | ||
318 | - while (itr.hasNext()) { | ||
319 | - // checkArgument at start ensures we'll always have pairs of connect points | ||
320 | - Pair<ConnectPoint, ConnectPoint> src = itr.next(); | ||
321 | - Pair<ConnectPoint, ConnectPoint> dst = itr.next(); | ||
322 | - | ||
323 | - Device.Type srcType = deviceService.getDevice(src.getKey().deviceId()).type(); | ||
324 | - Device.Type dstType = deviceService.getDevice(dst.getKey().deviceId()).type(); | ||
325 | - | ||
326 | - // Only support connections between identical port types | ||
327 | - if (srcType != dstType) { | ||
328 | - log.warn("Unsupported mix of cross connect points : {}, {}", srcType, dstType); | ||
329 | - return false; | ||
330 | - } | ||
331 | - } | ||
332 | - | ||
333 | - return true; | ||
334 | } | 368 | } |
335 | 369 | ||
336 | /** | 370 | /** |
337 | * Scans the list of cross connection points and returns a list of optical connectivity intents. | 371 | * Scans the list of cross connection points and returns a list of optical connectivity intents. |
338 | - * During the process, store intent ID and its realizing link information to given connectivity object. | 372 | + * During the process, save information about packet links to given set. |
339 | * | 373 | * |
340 | - * @param xcPointPairs list of cross connection points | 374 | + * @param crossConnectPoints list of (src, dst) pair between which optical path will be set up |
341 | * @return list of optical connectivity intents | 375 | * @return list of optical connectivity intents |
342 | */ | 376 | */ |
343 | - private List<Intent> createIntents(List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs, | 377 | + private List<Intent> createIntents(List<Pair<ConnectPoint, ConnectPoint>> crossConnectPoints) { |
344 | - OpticalConnectivity connectivity) { | ||
345 | - checkArgument(xcPointPairs.size() % 2 == 0); | ||
346 | - | ||
347 | List<Intent> intents = new LinkedList<>(); | 378 | List<Intent> intents = new LinkedList<>(); |
348 | - Iterator<Pair<ConnectPoint, ConnectPoint>> itr = xcPointPairs.iterator(); | 379 | + Iterator<Pair<ConnectPoint, ConnectPoint>> itr = crossConnectPoints.iterator(); |
349 | 380 | ||
350 | while (itr.hasNext()) { | 381 | while (itr.hasNext()) { |
351 | // checkArgument at start ensures we'll always have pairs of connect points | 382 | // checkArgument at start ensures we'll always have pairs of connect points |
352 | - Pair<ConnectPoint, ConnectPoint> src = itr.next(); | 383 | + Pair<ConnectPoint, ConnectPoint> next = itr.next(); |
353 | - Pair<ConnectPoint, ConnectPoint> dst = itr.next(); | 384 | + ConnectPoint src = next.getLeft(); |
385 | + ConnectPoint dst = next.getRight(); | ||
354 | 386 | ||
355 | - Port srcPort = deviceService.getPort(src.getKey().deviceId(), src.getKey().port()); | 387 | + Port srcPort = deviceService.getPort(src.deviceId(), src.port()); |
356 | - Port dstPort = deviceService.getPort(dst.getKey().deviceId(), dst.getKey().port()); | 388 | + Port dstPort = deviceService.getPort(dst.deviceId(), dst.port()); |
357 | 389 | ||
358 | if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) { | 390 | if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) { |
359 | OduCltPort srcOCPort = (OduCltPort) srcPort; | 391 | OduCltPort srcOCPort = (OduCltPort) srcPort; |
... | @@ -365,16 +397,12 @@ public class OpticalPathProvisioner | ... | @@ -365,16 +397,12 @@ public class OpticalPathProvisioner |
365 | // Create OTN circuit | 397 | // Create OTN circuit |
366 | OpticalCircuitIntent circuitIntent = OpticalCircuitIntent.builder() | 398 | OpticalCircuitIntent circuitIntent = OpticalCircuitIntent.builder() |
367 | .appId(appId) | 399 | .appId(appId) |
368 | - .src(src.getKey()) | 400 | + .src(src) |
369 | - .dst(dst.getKey()) | 401 | + .dst(dst) |
370 | .signalType(srcOCPort.signalType()) | 402 | .signalType(srcOCPort.signalType()) |
371 | .bidirectional(true) | 403 | .bidirectional(true) |
372 | .build(); | 404 | .build(); |
373 | intents.add(circuitIntent); | 405 | intents.add(circuitIntent); |
374 | - PacketLinkRealizedByOptical pLink = PacketLinkRealizedByOptical.create(src.getValue(), dst.getValue(), | ||
375 | - circuitIntent); | ||
376 | - connectivity.addRealizingLink(pLink); | ||
377 | - linkPathMap.put(pLink, connectivity); | ||
378 | } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) { | 406 | } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) { |
379 | OchPort srcOchPort = (OchPort) srcPort; | 407 | OchPort srcOchPort = (OchPort) srcPort; |
380 | OchPort dstOchPort = (OchPort) dstPort; | 408 | OchPort dstOchPort = (OchPort) dstPort; |
... | @@ -385,16 +413,12 @@ public class OpticalPathProvisioner | ... | @@ -385,16 +413,12 @@ public class OpticalPathProvisioner |
385 | // Create lightpath | 413 | // Create lightpath |
386 | OpticalConnectivityIntent opticalIntent = OpticalConnectivityIntent.builder() | 414 | OpticalConnectivityIntent opticalIntent = OpticalConnectivityIntent.builder() |
387 | .appId(appId) | 415 | .appId(appId) |
388 | - .src(src.getKey()) | 416 | + .src(src) |
389 | - .dst(dst.getKey()) | 417 | + .dst(dst) |
390 | .signalType(srcOchPort.signalType()) | 418 | .signalType(srcOchPort.signalType()) |
391 | .bidirectional(true) | 419 | .bidirectional(true) |
392 | .build(); | 420 | .build(); |
393 | intents.add(opticalIntent); | 421 | intents.add(opticalIntent); |
394 | - PacketLinkRealizedByOptical pLink = PacketLinkRealizedByOptical.create(src.getValue(), dst.getValue(), | ||
395 | - opticalIntent); | ||
396 | - connectivity.addRealizingLink(pLink); | ||
397 | - linkPathMap.put(pLink, connectivity); | ||
398 | } else { | 422 | } else { |
399 | log.warn("Unsupported cross connect point types {} {}", srcPort.type(), dstPort.type()); | 423 | log.warn("Unsupported cross connect point types {} {}", srcPort.type(), dstPort.type()); |
400 | return Collections.emptyList(); | 424 | return Collections.emptyList(); |
... | @@ -404,6 +428,36 @@ public class OpticalPathProvisioner | ... | @@ -404,6 +428,36 @@ public class OpticalPathProvisioner |
404 | return intents; | 428 | return intents; |
405 | } | 429 | } |
406 | 430 | ||
431 | + private Set<PacketLinkRealizedByOptical> createPacketLinkSet(List<Pair<ConnectPoint, ConnectPoint>> connectPoints, | ||
432 | + List<Intent> intents, | ||
433 | + Map<ConnectPoint, ConnectPoint> crossConnectPoints) { | ||
434 | + checkArgument(connectPoints.size() == intents.size()); | ||
435 | + | ||
436 | + Set<PacketLinkRealizedByOptical> pLinks = new HashSet<>(); | ||
437 | + | ||
438 | + Iterator<Pair<ConnectPoint, ConnectPoint>> xcPointsItr = connectPoints.iterator(); | ||
439 | + Iterator<Intent> intentItr = intents.iterator(); | ||
440 | + while (xcPointsItr.hasNext()) { | ||
441 | + Pair<ConnectPoint, ConnectPoint> xcPoints = xcPointsItr.next(); | ||
442 | + Intent intent = intentItr.next(); | ||
443 | + | ||
444 | + ConnectPoint packetSrc = checkNotNull(crossConnectPoints.get(xcPoints.getLeft())); | ||
445 | + ConnectPoint packetDst = checkNotNull(crossConnectPoints.get(xcPoints.getRight())); | ||
446 | + | ||
447 | + if (intent instanceof OpticalConnectivityIntent) { | ||
448 | + pLinks.add(PacketLinkRealizedByOptical.create(packetSrc, packetDst, | ||
449 | + (OpticalConnectivityIntent) intent)); | ||
450 | + } else if (intent instanceof OpticalCircuitIntent) { | ||
451 | + pLinks.add(PacketLinkRealizedByOptical.create(packetSrc, packetDst, | ||
452 | + (OpticalCircuitIntent) intent)); | ||
453 | + } else { | ||
454 | + log.warn("Unexpected intent type: {}", intent.getClass()); | ||
455 | + } | ||
456 | + } | ||
457 | + | ||
458 | + return pLinks; | ||
459 | + } | ||
460 | + | ||
407 | /** | 461 | /** |
408 | * Verifies if given device type is in packet layer, i.e., ROADM, OTN or ROADM_OTN device. | 462 | * Verifies if given device type is in packet layer, i.e., ROADM, OTN or ROADM_OTN device. |
409 | * | 463 | * |
... | @@ -444,17 +498,14 @@ public class OpticalPathProvisioner | ... | @@ -444,17 +498,14 @@ public class OpticalPathProvisioner |
444 | 498 | ||
445 | /** | 499 | /** |
446 | * Updates bandwidth resource of given connect point. | 500 | * Updates bandwidth resource of given connect point. |
501 | + * | ||
447 | * @param cp Connect point | 502 | * @param cp Connect point |
448 | * @param bandwidth New bandwidth | 503 | * @param bandwidth New bandwidth |
449 | */ | 504 | */ |
450 | private void updatePortBandwidth(ConnectPoint cp, Bandwidth bandwidth) { | 505 | private void updatePortBandwidth(ConnectPoint cp, Bandwidth bandwidth) { |
451 | - NodeId localNode = clusterService.getLocalNode().id(); | 506 | + log.debug("update Port {} Bandwidth {}", cp, bandwidth); |
452 | - NodeId sourceMaster = mastershipService.getMasterFor(cp.deviceId()); | 507 | + BandwidthCapacity bwCapacity = networkConfigService.addConfig(cp, BandwidthCapacity.class); |
453 | - if (localNode.equals(sourceMaster)) { | 508 | + bwCapacity.capacity(bandwidth).apply(); |
454 | - log.debug("update Port {} Bandwidth {}", cp, bandwidth); | ||
455 | - BandwidthCapacity bwCapacity = networkConfigService.addConfig(cp, BandwidthCapacity.class); | ||
456 | - bwCapacity.capacity(bandwidth).apply(); | ||
457 | - } | ||
458 | } | 509 | } |
459 | 510 | ||
460 | /** | 511 | /** |
... | @@ -487,15 +538,22 @@ public class OpticalPathProvisioner | ... | @@ -487,15 +538,22 @@ public class OpticalPathProvisioner |
487 | * @param connectivity Optical connectivity | 538 | * @param connectivity Optical connectivity |
488 | */ | 539 | */ |
489 | private void releaseBandwidthUsage(OpticalConnectivity connectivity) { | 540 | private void releaseBandwidthUsage(OpticalConnectivity connectivity) { |
490 | - OpticalConnectivityId connectivityId = connectivity.id(); | 541 | + if (connectivity.links().isEmpty()) { |
542 | + return; | ||
543 | + } | ||
491 | 544 | ||
492 | - log.debug("releasing bandwidth allocated to {}", connectivityId); | 545 | + // release resource only if this node is the master for link head device |
493 | - if (!resourceService.release(connectivityId)) { | 546 | + if (mastershipService.isLocalMaster(connectivity.links().get(0).src().deviceId())) { |
494 | - log.warn("Failed to release bandwidth allocated to {}", | 547 | + OpticalConnectivityId connectivityId = connectivity.id(); |
495 | - connectivityId); | 548 | + |
496 | - // TODO any recovery? | 549 | + log.debug("releasing bandwidth allocated to {}", connectivityId); |
550 | + if (!resourceService.release(connectivityId)) { | ||
551 | + log.warn("Failed to release bandwidth allocated to {}", | ||
552 | + connectivityId); | ||
553 | + // TODO any recovery? | ||
554 | + } | ||
555 | + log.debug("DONE releasing bandwidth for {}", connectivityId); | ||
497 | } | 556 | } |
498 | - log.debug("DONE releasing bandwidth for {}", connectivityId); | ||
499 | } | 557 | } |
500 | 558 | ||
501 | private class BandwidthLinkWeight implements LinkWeight { | 559 | private class BandwidthLinkWeight implements LinkWeight { |
... | @@ -515,7 +573,7 @@ public class OpticalPathProvisioner | ... | @@ -515,7 +573,7 @@ public class OpticalPathProvisioner |
515 | } | 573 | } |
516 | 574 | ||
517 | // Avoid cross connect links with used ports | 575 | // Avoid cross connect links with used ports |
518 | - if (isCrossConnectLink(l) && usedCrossConnectLinks.contains(l)) { | 576 | + if (isCrossConnectLink(l) && usedCrossConnectLinkSet.contains(l)) { |
519 | return -1.0; | 577 | return -1.0; |
520 | } | 578 | } |
521 | 579 | ||
... | @@ -592,18 +650,16 @@ public class OpticalPathProvisioner | ... | @@ -592,18 +650,16 @@ public class OpticalPathProvisioner |
592 | ConnectPoint packetSrc = e.getKey().src(); | 650 | ConnectPoint packetSrc = e.getKey().src(); |
593 | ConnectPoint packetDst = e.getKey().dst(); | 651 | ConnectPoint packetDst = e.getKey().dst(); |
594 | Bandwidth bw = e.getKey().bandwidth(); | 652 | Bandwidth bw = e.getKey().bandwidth(); |
595 | - // Updates bandwidth of packet ports | ||
596 | - updatePortBandwidth(packetSrc, bw); | ||
597 | - updatePortBandwidth(packetDst, bw); | ||
598 | - | ||
599 | - OpticalConnectivity connectivity = e.getValue(); | ||
600 | - connectivity.setLinkEstablished(packetSrc, packetDst); | ||
601 | 653 | ||
602 | - if (e.getValue().isAllRealizingLinkEstablished()) { | 654 | + // reflect modification only if packetSrc is local_ |
603 | - updateBandwidthUsage(connectivity); | 655 | + if (mastershipService.isLocalMaster(packetSrc.deviceId())) { |
656 | + // Updates bandwidth of packet ports | ||
657 | + updatePortBandwidth(packetSrc, bw); | ||
658 | + updatePortBandwidth(packetDst, bw); | ||
604 | 659 | ||
605 | - // Notifies listeners if all links are established | 660 | + // Updates link status in distributed map |
606 | - post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_INSTALLED, e.getValue().id())); | 661 | + linkPathMap.computeIfPresent(e.getKey(), (link, connectivity) -> |
662 | + e.getValue().value().setLinkEstablished(packetSrc, packetDst, true)); | ||
607 | } | 663 | } |
608 | }); | 664 | }); |
609 | } | 665 | } |
... | @@ -633,23 +689,23 @@ public class OpticalPathProvisioner | ... | @@ -633,23 +689,23 @@ public class OpticalPathProvisioner |
633 | .forEach(e -> { | 689 | .forEach(e -> { |
634 | ConnectPoint packetSrc = e.getKey().src(); | 690 | ConnectPoint packetSrc = e.getKey().src(); |
635 | ConnectPoint packetDst = e.getKey().dst(); | 691 | ConnectPoint packetDst = e.getKey().dst(); |
636 | - // Updates bandwidth of packet ports | ||
637 | - updatePortBandwidth(packetSrc, bw); | ||
638 | - updatePortBandwidth(packetDst, bw); | ||
639 | - OpticalConnectivity connectivity = e.getValue(); | ||
640 | - connectivity.setLinkRemoved(packetSrc, packetDst); | ||
641 | 692 | ||
642 | - // Notifies listeners if all links are gone | 693 | + // reflect modification only if packetSrc is local_ |
643 | - if (e.getValue().isAllRealizingLinkNotEstablished()) { | 694 | + if (mastershipService.isLocalMaster(packetSrc.deviceId())) { |
644 | - releaseBandwidthUsage(connectivity); | 695 | + // Updates bandwidth of packet ports |
645 | - post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, e.getValue().id())); | 696 | + updatePortBandwidth(packetSrc, bw); |
697 | + updatePortBandwidth(packetDst, bw); | ||
698 | + | ||
699 | + // Updates link status in distributed map | ||
700 | + linkPathMap.computeIfPresent(e.getKey(), (link, connectivity) -> | ||
701 | + e.getValue().value().setLinkEstablished(packetSrc, packetDst, false)); | ||
646 | } | 702 | } |
647 | }); | 703 | }); |
648 | } | 704 | } |
649 | 705 | ||
650 | private void removeXcLinkUsage(ConnectPoint cp) { | 706 | private void removeXcLinkUsage(ConnectPoint cp) { |
651 | Optional<Link> link = linkService.getLinks(cp).stream() | 707 | Optional<Link> link = linkService.getLinks(cp).stream() |
652 | - .filter(usedCrossConnectLinks::contains) | 708 | + .filter(usedCrossConnectLinkSet::contains) |
653 | .findAny(); | 709 | .findAny(); |
654 | 710 | ||
655 | if (!link.isPresent()) { | 711 | if (!link.isPresent()) { |
... | @@ -657,7 +713,7 @@ public class OpticalPathProvisioner | ... | @@ -657,7 +713,7 @@ public class OpticalPathProvisioner |
657 | return; | 713 | return; |
658 | } | 714 | } |
659 | 715 | ||
660 | - usedCrossConnectLinks.remove(link.get()); | 716 | + usedCrossConnectLinkSet.remove(link.get()); |
661 | } | 717 | } |
662 | } | 718 | } |
663 | 719 | ||
... | @@ -669,22 +725,60 @@ public class OpticalPathProvisioner | ... | @@ -669,22 +725,60 @@ public class OpticalPathProvisioner |
669 | switch (event.type()) { | 725 | switch (event.type()) { |
670 | case LINK_REMOVED: | 726 | case LINK_REMOVED: |
671 | Link link = event.subject(); | 727 | Link link = event.subject(); |
728 | + // updates linkPathMap only if src device of link is local | ||
729 | + if (!mastershipService.isLocalMaster(link.src().deviceId())) { | ||
730 | + return; | ||
731 | + } | ||
732 | + | ||
733 | + // find all packet links that correspond to removed link | ||
672 | Set<PacketLinkRealizedByOptical> pLinks = linkPathMap.keySet().stream() | 734 | Set<PacketLinkRealizedByOptical> pLinks = linkPathMap.keySet().stream() |
673 | .filter(l -> l.isBetween(link.src(), link.dst()) || l.isBetween(link.dst(), link.src())) | 735 | .filter(l -> l.isBetween(link.src(), link.dst()) || l.isBetween(link.dst(), link.src())) |
674 | .collect(Collectors.toSet()); | 736 | .collect(Collectors.toSet()); |
675 | 737 | ||
676 | pLinks.forEach(l -> { | 738 | pLinks.forEach(l -> { |
677 | - OpticalConnectivity c = linkPathMap.get(l); | 739 | + // remove found packet links from distributed store |
678 | - // Notifies listeners if all links are gone | 740 | + linkPathMap.computeIfPresent(l, (plink, conn) -> { |
679 | - if (c.isAllRealizingLinkNotEstablished()) { | 741 | + // Notifies listeners if all packet links are gone |
680 | - post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, c.id())); | 742 | + if (conn.isAllRealizingLinkNotEstablished()) { |
681 | - } | 743 | + post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, conn.id())); |
682 | - linkPathMap.remove(l); | 744 | + } |
745 | + return null; | ||
746 | + }); | ||
683 | }); | 747 | }); |
684 | default: | 748 | default: |
685 | break; | 749 | break; |
686 | } | 750 | } |
687 | } | 751 | } |
688 | } | 752 | } |
753 | + | ||
754 | + private class InternalStoreListener | ||
755 | + implements MapEventListener<PacketLinkRealizedByOptical, OpticalConnectivity> { | ||
756 | + | ||
757 | + @Override | ||
758 | + public void event(MapEvent<PacketLinkRealizedByOptical, OpticalConnectivity> event) { | ||
759 | + switch (event.type()) { | ||
760 | + case UPDATE: | ||
761 | + OpticalConnectivity oldConnectivity = event.oldValue().value(); | ||
762 | + OpticalConnectivity newConnectivity = event.newValue().value(); | ||
763 | + | ||
764 | + if (!oldConnectivity.isAllRealizingLinkEstablished() && | ||
765 | + newConnectivity.isAllRealizingLinkEstablished()) { | ||
766 | + // Notifies listeners if all links are established | ||
767 | + updateBandwidthUsage(newConnectivity); | ||
768 | + post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_INSTALLED, newConnectivity.id())); | ||
769 | + } else if (!oldConnectivity.isAllRealizingLinkNotEstablished() && | ||
770 | + newConnectivity.isAllRealizingLinkNotEstablished()) { | ||
771 | + // Notifies listeners if all links are gone | ||
772 | + releaseBandwidthUsage(newConnectivity); | ||
773 | + post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, newConnectivity.id())); | ||
774 | + } | ||
775 | + | ||
776 | + break; | ||
777 | + default: | ||
778 | + break; | ||
779 | + } | ||
780 | + } | ||
781 | + | ||
782 | + } | ||
689 | } | 783 | } |
690 | 784 | ... | ... |
... | @@ -33,9 +33,6 @@ public class PacketLinkRealizedByOptical { | ... | @@ -33,9 +33,6 @@ public class PacketLinkRealizedByOptical { |
33 | private final Bandwidth bandwidth; | 33 | private final Bandwidth bandwidth; |
34 | // TODO should be list of Intent Key? | 34 | // TODO should be list of Intent Key? |
35 | private final Key realizingIntentKey; | 35 | private final Key realizingIntentKey; |
36 | - // established=false represents that this (packet) link is expected to be | ||
37 | - // discovered after underlying (optical) path has been provisioned. | ||
38 | - private boolean established; | ||
39 | 36 | ||
40 | /** | 37 | /** |
41 | * Creates instance with specified parameters. | 38 | * Creates instance with specified parameters. |
... | @@ -51,7 +48,6 @@ public class PacketLinkRealizedByOptical { | ... | @@ -51,7 +48,6 @@ public class PacketLinkRealizedByOptical { |
51 | this.dst = dst; | 48 | this.dst = dst; |
52 | this.realizingIntentKey = realizingIntentKey; | 49 | this.realizingIntentKey = realizingIntentKey; |
53 | this.bandwidth = bandwidth; | 50 | this.bandwidth = bandwidth; |
54 | - this.established = false; | ||
55 | } | 51 | } |
56 | 52 | ||
57 | /** | 53 | /** |
... | @@ -129,24 +125,6 @@ public class PacketLinkRealizedByOptical { | ... | @@ -129,24 +125,6 @@ public class PacketLinkRealizedByOptical { |
129 | } | 125 | } |
130 | 126 | ||
131 | /** | 127 | /** |
132 | - * Returns whether packet link is realized or not. | ||
133 | - * | ||
134 | - * @return true if packet link is realized. false if not. | ||
135 | - */ | ||
136 | - public boolean isEstablished() { | ||
137 | - return established; | ||
138 | - } | ||
139 | - | ||
140 | - /** | ||
141 | - * Sets packet link to be established. | ||
142 | - * | ||
143 | - * @param established status of packet link | ||
144 | - */ | ||
145 | - public void setEstablished(boolean established) { | ||
146 | - this.established = established; | ||
147 | - } | ||
148 | - | ||
149 | - /** | ||
150 | * Check if packet link is between specified two connect points. | 128 | * Check if packet link is between specified two connect points. |
151 | * | 129 | * |
152 | * @param src source connect point | 130 | * @param src source connect point |
... | @@ -157,4 +135,36 @@ public class PacketLinkRealizedByOptical { | ... | @@ -157,4 +135,36 @@ public class PacketLinkRealizedByOptical { |
157 | return (this.src.equals(src) && this.dst.equals(dst)); | 135 | return (this.src.equals(src) && this.dst.equals(dst)); |
158 | } | 136 | } |
159 | 137 | ||
138 | + @Override | ||
139 | + public boolean equals(Object o) { | ||
140 | + if (this == o) { | ||
141 | + return true; | ||
142 | + } | ||
143 | + if (o == null || getClass() != o.getClass()) { | ||
144 | + return false; | ||
145 | + } | ||
146 | + | ||
147 | + PacketLinkRealizedByOptical that = (PacketLinkRealizedByOptical) o; | ||
148 | + | ||
149 | + if (!src.equals(that.src)) { | ||
150 | + return false; | ||
151 | + } | ||
152 | + if (!dst.equals(that.dst)) { | ||
153 | + return false; | ||
154 | + } | ||
155 | + if (!bandwidth.equals(that.bandwidth)) { | ||
156 | + return false; | ||
157 | + } | ||
158 | + return realizingIntentKey.equals(that.realizingIntentKey); | ||
159 | + | ||
160 | + } | ||
161 | + | ||
162 | + @Override | ||
163 | + public int hashCode() { | ||
164 | + int result = src.hashCode(); | ||
165 | + result = 31 * result + dst.hashCode(); | ||
166 | + result = 31 * result + bandwidth.hashCode(); | ||
167 | + result = 31 * result + realizingIntentKey.hashCode(); | ||
168 | + return result; | ||
169 | + } | ||
160 | } | 170 | } | ... | ... |
... | @@ -33,7 +33,7 @@ import java.util.Optional; | ... | @@ -33,7 +33,7 @@ import java.util.Optional; |
33 | public interface OpticalPathService extends ListenerService<OpticalPathEvent, OpticalPathListener> { | 33 | public interface OpticalPathService extends ListenerService<OpticalPathEvent, OpticalPathListener> { |
34 | 34 | ||
35 | /** | 35 | /** |
36 | - * Calculates optical path between connect points and sets up connectivity. | 36 | + * Calculates multi-layer path between connect points and sets up connectivity. |
37 | * | 37 | * |
38 | * @param ingress ingress port | 38 | * @param ingress ingress port |
39 | * @param egress egress port | 39 | * @param egress egress port |
... | @@ -45,9 +45,9 @@ public interface OpticalPathService extends ListenerService<OpticalPathEvent, Op | ... | @@ -45,9 +45,9 @@ public interface OpticalPathService extends ListenerService<OpticalPathEvent, Op |
45 | Bandwidth bandwidth, Duration latency); | 45 | Bandwidth bandwidth, Duration latency); |
46 | 46 | ||
47 | /** | 47 | /** |
48 | - * Sets up connectivity along given optical path. | 48 | + * Sets up connectivity along given multi-layer path including cross-connect links. |
49 | * | 49 | * |
50 | - * @param path path along which connectivity will be set up | 50 | + * @param path multi-layer path along which connectivity will be set up |
51 | * @param bandwidth required bandwidth. No bandwidth is assured if null. | 51 | * @param bandwidth required bandwidth. No bandwidth is assured if null. |
52 | * @param latency required latency. No latency is assured if null. | 52 | * @param latency required latency. No latency is assured if null. |
53 | * @return true if successful. false otherwise. | 53 | * @return true if successful. false otherwise. | ... | ... |
... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
16 | 16 | ||
17 | package org.onosproject.newoptical; | 17 | package org.onosproject.newoptical; |
18 | 18 | ||
19 | +import com.google.common.collect.ImmutableSet; | ||
19 | import org.junit.After; | 20 | import org.junit.After; |
20 | import org.junit.Before; | 21 | import org.junit.Before; |
21 | import org.junit.Test; | 22 | import org.junit.Test; |
... | @@ -39,7 +40,9 @@ import org.onosproject.net.provider.ProviderId; | ... | @@ -39,7 +40,9 @@ import org.onosproject.net.provider.ProviderId; |
39 | import org.onosproject.newoptical.api.OpticalConnectivityId; | 40 | import org.onosproject.newoptical.api.OpticalConnectivityId; |
40 | 41 | ||
41 | import java.time.Duration; | 42 | import java.time.Duration; |
43 | +import java.util.Collections; | ||
42 | import java.util.List; | 44 | import java.util.List; |
45 | +import java.util.Set; | ||
43 | import java.util.stream.Collectors; | 46 | import java.util.stream.Collectors; |
44 | import java.util.stream.Stream; | 47 | import java.util.stream.Stream; |
45 | 48 | ||
... | @@ -94,10 +97,9 @@ public class OpticalConnectivityTest { | ... | @@ -94,10 +97,9 @@ public class OpticalConnectivityTest { |
94 | Link link2 = createLink(cp22, cp31); | 97 | Link link2 = createLink(cp22, cp31); |
95 | List<Link> links = Stream.of(link1, link2).collect(Collectors.toList()); | 98 | List<Link> links = Stream.of(link1, link2).collect(Collectors.toList()); |
96 | 99 | ||
97 | - Path path = new MockPath(cp12, cp31, links); | ||
98 | - | ||
99 | OpticalConnectivityId cid = OpticalConnectivityId.of(1L); | 100 | OpticalConnectivityId cid = OpticalConnectivityId.of(1L); |
100 | - OpticalConnectivity oc = new OpticalConnectivity(cid, path, bandwidth, latency); | 101 | + OpticalConnectivity oc = new OpticalConnectivity(cid, links, bandwidth, latency, |
102 | + Collections.emptySet(), Collections.emptySet()); | ||
101 | 103 | ||
102 | assertNotNull(oc); | 104 | assertNotNull(oc); |
103 | assertEquals(oc.id(), cid); | 105 | assertEquals(oc.id(), cid); |
... | @@ -133,8 +135,6 @@ public class OpticalConnectivityTest { | ... | @@ -133,8 +135,6 @@ public class OpticalConnectivityTest { |
133 | Link link6 = createLink(cp62, cp71); | 135 | Link link6 = createLink(cp62, cp71); |
134 | List<Link> links = Stream.of(link1, link2, link3, link4, link5, link6).collect(Collectors.toList()); | 136 | List<Link> links = Stream.of(link1, link2, link3, link4, link5, link6).collect(Collectors.toList()); |
135 | 137 | ||
136 | - Path path = new MockPath(cp12, cp71, links); | ||
137 | - | ||
138 | // Mocks 2 intents to create OduCtl connectivity | 138 | // Mocks 2 intents to create OduCtl connectivity |
139 | OpticalConnectivityIntent connIntent1 = createConnectivityIntent(cp21, cp32); | 139 | OpticalConnectivityIntent connIntent1 = createConnectivityIntent(cp21, cp32); |
140 | PacketLinkRealizedByOptical oduLink1 = PacketLinkRealizedByOptical.create(cp12, cp41, | 140 | PacketLinkRealizedByOptical oduLink1 = PacketLinkRealizedByOptical.create(cp12, cp41, |
... | @@ -144,29 +144,29 @@ public class OpticalConnectivityTest { | ... | @@ -144,29 +144,29 @@ public class OpticalConnectivityTest { |
144 | PacketLinkRealizedByOptical oduLink2 = PacketLinkRealizedByOptical.create(cp42, cp71, | 144 | PacketLinkRealizedByOptical oduLink2 = PacketLinkRealizedByOptical.create(cp42, cp71, |
145 | connIntent2); | 145 | connIntent2); |
146 | 146 | ||
147 | + Set<PacketLinkRealizedByOptical> plinks = ImmutableSet.of(oduLink1, oduLink2); | ||
148 | + | ||
147 | Bandwidth bandwidth = Bandwidth.bps(100); | 149 | Bandwidth bandwidth = Bandwidth.bps(100); |
148 | Duration latency = Duration.ofMillis(10); | 150 | Duration latency = Duration.ofMillis(10); |
149 | 151 | ||
150 | OpticalConnectivityId cid = OpticalConnectivityId.of(1L); | 152 | OpticalConnectivityId cid = OpticalConnectivityId.of(1L); |
151 | - OpticalConnectivity oc = new OpticalConnectivity(cid, path, bandwidth, latency); | 153 | + OpticalConnectivity oc1 = new OpticalConnectivity(cid, links, bandwidth, latency, |
152 | - | 154 | + plinks, Collections.emptySet()); |
153 | - oc.addRealizingLink(oduLink1); | ||
154 | - oc.addRealizingLink(oduLink2); | ||
155 | 155 | ||
156 | - assertTrue(oc.isAllRealizingLinkNotEstablished()); | 156 | + assertTrue(oc1.isAllRealizingLinkNotEstablished()); |
157 | - assertFalse(oc.isAllRealizingLinkEstablished()); | 157 | + assertFalse(oc1.isAllRealizingLinkEstablished()); |
158 | 158 | ||
159 | // Sets link realized by connIntent1 to be established | 159 | // Sets link realized by connIntent1 to be established |
160 | - oc.setLinkEstablished(cp12, cp41); | 160 | + OpticalConnectivity oc2 = oc1.setLinkEstablished(cp12, cp41, true); |
161 | 161 | ||
162 | - assertFalse(oc.isAllRealizingLinkNotEstablished()); | 162 | + assertFalse(oc2.isAllRealizingLinkNotEstablished()); |
163 | - assertFalse(oc.isAllRealizingLinkEstablished()); | 163 | + assertFalse(oc2.isAllRealizingLinkEstablished()); |
164 | 164 | ||
165 | // Sets link realized by connIntent2 to be established | 165 | // Sets link realized by connIntent2 to be established |
166 | - oc.setLinkEstablished(cp42, cp71); | 166 | + OpticalConnectivity oc3 = oc2.setLinkEstablished(cp42, cp71, true); |
167 | 167 | ||
168 | - assertFalse(oc.isAllRealizingLinkNotEstablished()); | 168 | + assertFalse(oc3.isAllRealizingLinkNotEstablished()); |
169 | - assertTrue(oc.isAllRealizingLinkEstablished()); | 169 | + assertTrue(oc3.isAllRealizingLinkEstablished()); |
170 | } | 170 | } |
171 | 171 | ||
172 | /** | 172 | /** |
... | @@ -196,8 +196,6 @@ public class OpticalConnectivityTest { | ... | @@ -196,8 +196,6 @@ public class OpticalConnectivityTest { |
196 | Link link6 = createLink(cp62, cp71); | 196 | Link link6 = createLink(cp62, cp71); |
197 | List<Link> links = Stream.of(link1, link2, link3, link4, link5, link6).collect(Collectors.toList()); | 197 | List<Link> links = Stream.of(link1, link2, link3, link4, link5, link6).collect(Collectors.toList()); |
198 | 198 | ||
199 | - Path path = new MockPath(cp12, cp71, links); | ||
200 | - | ||
201 | // Mocks 2 intents to create Och connectivity | 199 | // Mocks 2 intents to create Och connectivity |
202 | OpticalCircuitIntent circuitIntent1 = createCircuitIntent(cp21, cp32); | 200 | OpticalCircuitIntent circuitIntent1 = createCircuitIntent(cp21, cp32); |
203 | PacketLinkRealizedByOptical ochLink1 = PacketLinkRealizedByOptical.create(cp12, cp41, | 201 | PacketLinkRealizedByOptical ochLink1 = PacketLinkRealizedByOptical.create(cp12, cp41, |
... | @@ -207,29 +205,29 @@ public class OpticalConnectivityTest { | ... | @@ -207,29 +205,29 @@ public class OpticalConnectivityTest { |
207 | PacketLinkRealizedByOptical ochLink2 = PacketLinkRealizedByOptical.create(cp42, cp71, | 205 | PacketLinkRealizedByOptical ochLink2 = PacketLinkRealizedByOptical.create(cp42, cp71, |
208 | circuitIntent2); | 206 | circuitIntent2); |
209 | 207 | ||
208 | + Set<PacketLinkRealizedByOptical> plinks = ImmutableSet.of(ochLink1, ochLink2); | ||
209 | + | ||
210 | Bandwidth bandwidth = Bandwidth.bps(100); | 210 | Bandwidth bandwidth = Bandwidth.bps(100); |
211 | Duration latency = Duration.ofMillis(10); | 211 | Duration latency = Duration.ofMillis(10); |
212 | 212 | ||
213 | OpticalConnectivityId cid = OpticalConnectivityId.of(1L); | 213 | OpticalConnectivityId cid = OpticalConnectivityId.of(1L); |
214 | - OpticalConnectivity oc = new OpticalConnectivity(cid, path, bandwidth, latency); | 214 | + OpticalConnectivity oc1 = new OpticalConnectivity(cid, links, bandwidth, latency, |
215 | - | 215 | + plinks, Collections.emptySet()); |
216 | - oc.addRealizingLink(ochLink1); | ||
217 | - oc.addRealizingLink(ochLink2); | ||
218 | 216 | ||
219 | - assertTrue(oc.isAllRealizingLinkNotEstablished()); | 217 | + assertTrue(oc1.isAllRealizingLinkNotEstablished()); |
220 | - assertFalse(oc.isAllRealizingLinkEstablished()); | 218 | + assertFalse(oc1.isAllRealizingLinkEstablished()); |
221 | 219 | ||
222 | // Sets link realized by circuitIntent1 to be established | 220 | // Sets link realized by circuitIntent1 to be established |
223 | - oc.setLinkEstablished(cp12, cp41); | 221 | + OpticalConnectivity oc2 = oc1.setLinkEstablished(cp12, cp41, true); |
224 | 222 | ||
225 | - assertFalse(oc.isAllRealizingLinkNotEstablished()); | 223 | + assertFalse(oc2.isAllRealizingLinkNotEstablished()); |
226 | - assertFalse(oc.isAllRealizingLinkEstablished()); | 224 | + assertFalse(oc2.isAllRealizingLinkEstablished()); |
227 | 225 | ||
228 | // Sets link realized by circuitIntent2 to be established | 226 | // Sets link realized by circuitIntent2 to be established |
229 | - oc.setLinkEstablished(cp42, cp71); | 227 | + OpticalConnectivity oc3 = oc2.setLinkEstablished(cp42, cp71, true); |
230 | 228 | ||
231 | - assertFalse(oc.isAllRealizingLinkNotEstablished()); | 229 | + assertFalse(oc3.isAllRealizingLinkNotEstablished()); |
232 | - assertTrue(oc.isAllRealizingLinkEstablished()); | 230 | + assertTrue(oc3.isAllRealizingLinkEstablished()); |
233 | } | 231 | } |
234 | 232 | ||
235 | private ConnectPoint createConnectPoint(long devIdNum, long portIdNum) { | 233 | private ConnectPoint createConnectPoint(long devIdNum, long portIdNum) { | ... | ... |
... | @@ -21,9 +21,12 @@ import org.junit.After; | ... | @@ -21,9 +21,12 @@ import org.junit.After; |
21 | import org.junit.Before; | 21 | import org.junit.Before; |
22 | import org.junit.Test; | 22 | import org.junit.Test; |
23 | import org.onlab.packet.ChassisId; | 23 | import org.onlab.packet.ChassisId; |
24 | +import org.onlab.packet.IpAddress; | ||
24 | import org.onlab.util.Bandwidth; | 25 | import org.onlab.util.Bandwidth; |
25 | import org.onlab.util.Frequency; | 26 | import org.onlab.util.Frequency; |
26 | import org.onosproject.cluster.ClusterServiceAdapter; | 27 | import org.onosproject.cluster.ClusterServiceAdapter; |
28 | +import org.onosproject.cluster.ControllerNode; | ||
29 | +import org.onosproject.cluster.NodeId; | ||
27 | import org.onosproject.core.ApplicationId; | 30 | import org.onosproject.core.ApplicationId; |
28 | import org.onosproject.core.CoreServiceAdapter; | 31 | import org.onosproject.core.CoreServiceAdapter; |
29 | import org.onosproject.core.DefaultApplicationId; | 32 | import org.onosproject.core.DefaultApplicationId; |
... | @@ -44,12 +47,15 @@ import org.onosproject.net.Device; | ... | @@ -44,12 +47,15 @@ import org.onosproject.net.Device; |
44 | import org.onosproject.net.DeviceId; | 47 | import org.onosproject.net.DeviceId; |
45 | import org.onosproject.net.ElementId; | 48 | import org.onosproject.net.ElementId; |
46 | import org.onosproject.net.Link; | 49 | import org.onosproject.net.Link; |
50 | +import org.onosproject.net.MastershipRole; | ||
47 | import org.onosproject.net.OchSignal; | 51 | import org.onosproject.net.OchSignal; |
48 | import org.onosproject.net.OduSignalType; | 52 | import org.onosproject.net.OduSignalType; |
49 | import org.onosproject.net.Path; | 53 | import org.onosproject.net.Path; |
50 | import org.onosproject.net.Port; | 54 | import org.onosproject.net.Port; |
51 | import org.onosproject.net.PortNumber; | 55 | import org.onosproject.net.PortNumber; |
56 | +import org.onosproject.net.config.Config; | ||
52 | import org.onosproject.net.config.NetworkConfigServiceAdapter; | 57 | import org.onosproject.net.config.NetworkConfigServiceAdapter; |
58 | +import org.onosproject.net.config.basics.BandwidthCapacity; | ||
53 | import org.onosproject.net.device.DeviceServiceAdapter; | 59 | import org.onosproject.net.device.DeviceServiceAdapter; |
54 | import org.onosproject.net.intent.Intent; | 60 | import org.onosproject.net.intent.Intent; |
55 | import org.onosproject.net.intent.IntentEvent; | 61 | import org.onosproject.net.intent.IntentEvent; |
... | @@ -74,8 +80,20 @@ import org.onosproject.net.topology.PathServiceAdapter; | ... | @@ -74,8 +80,20 @@ import org.onosproject.net.topology.PathServiceAdapter; |
74 | import org.onosproject.newoptical.api.OpticalConnectivityId; | 80 | import org.onosproject.newoptical.api.OpticalConnectivityId; |
75 | import org.onosproject.newoptical.api.OpticalPathEvent; | 81 | import org.onosproject.newoptical.api.OpticalPathEvent; |
76 | import org.onosproject.newoptical.api.OpticalPathListener; | 82 | import org.onosproject.newoptical.api.OpticalPathListener; |
83 | +import org.onosproject.store.service.AsyncConsistentMap; | ||
84 | +import org.onosproject.store.service.AsyncDistributedSet; | ||
77 | import org.onosproject.store.service.AtomicCounter; | 85 | import org.onosproject.store.service.AtomicCounter; |
86 | +import org.onosproject.store.service.ConsistentMap; | ||
87 | +import org.onosproject.store.service.ConsistentMapAdapter; | ||
88 | +import org.onosproject.store.service.ConsistentMapBuilder; | ||
89 | +import org.onosproject.store.service.DistributedSet; | ||
90 | +import org.onosproject.store.service.DistributedSetAdapter; | ||
91 | +import org.onosproject.store.service.DistributedSetBuilder; | ||
92 | +import org.onosproject.store.service.MapEvent; | ||
93 | +import org.onosproject.store.service.MapEventListener; | ||
94 | +import org.onosproject.store.service.SetEventListener; | ||
78 | import org.onosproject.store.service.StorageServiceAdapter; | 95 | import org.onosproject.store.service.StorageServiceAdapter; |
96 | +import org.onosproject.store.service.Versioned; | ||
79 | 97 | ||
80 | import java.time.Duration; | 98 | import java.time.Duration; |
81 | import java.util.ArrayList; | 99 | import java.util.ArrayList; |
... | @@ -87,6 +105,8 @@ import java.util.List; | ... | @@ -87,6 +105,8 @@ import java.util.List; |
87 | import java.util.Map; | 105 | import java.util.Map; |
88 | import java.util.Optional; | 106 | import java.util.Optional; |
89 | import java.util.Set; | 107 | import java.util.Set; |
108 | +import java.util.concurrent.Executor; | ||
109 | +import java.util.function.BiFunction; | ||
90 | import java.util.stream.Collectors; | 110 | import java.util.stream.Collectors; |
91 | import java.util.stream.Stream; | 111 | import java.util.stream.Stream; |
92 | 112 | ||
... | @@ -155,6 +175,8 @@ public class OpticalPathProvisionerTest { | ... | @@ -155,6 +175,8 @@ public class OpticalPathProvisionerTest { |
155 | protected TestLinkService linkService; | 175 | protected TestLinkService linkService; |
156 | protected TestPathService pathService; | 176 | protected TestPathService pathService; |
157 | protected TestIntentService intentService; | 177 | protected TestIntentService intentService; |
178 | + protected TestMastershipService mastershipService; | ||
179 | + protected TestClusterService clusterService; | ||
158 | protected IdGenerator idGenerator; | 180 | protected IdGenerator idGenerator; |
159 | 181 | ||
160 | @Before | 182 | @Before |
... | @@ -188,14 +210,24 @@ public class OpticalPathProvisionerTest { | ... | @@ -188,14 +210,24 @@ public class OpticalPathProvisionerTest { |
188 | 210 | ||
189 | this.pathService = new TestPathService(); | 211 | this.pathService = new TestPathService(); |
190 | this.intentService = new TestIntentService(); | 212 | this.intentService = new TestIntentService(); |
213 | + this.mastershipService = new TestMastershipService(); | ||
214 | + this.clusterService = new TestClusterService(); | ||
215 | + | ||
216 | + mastershipService.setMastership(DEVICE1.id(), MastershipRole.MASTER); | ||
217 | + mastershipService.setMastership(DEVICE2.id(), MastershipRole.MASTER); | ||
218 | + mastershipService.setMastership(DEVICE3.id(), MastershipRole.MASTER); | ||
219 | + mastershipService.setMastership(DEVICE4.id(), MastershipRole.MASTER); | ||
220 | + mastershipService.setMastership(DEVICE5.id(), MastershipRole.MASTER); | ||
221 | + mastershipService.setMastership(DEVICE6.id(), MastershipRole.MASTER); | ||
222 | + mastershipService.setMastership(DEVICE7.id(), MastershipRole.MASTER); | ||
191 | 223 | ||
192 | this.target = new OpticalPathProvisioner(); | 224 | this.target = new OpticalPathProvisioner(); |
193 | target.coreService = new TestCoreService(); | 225 | target.coreService = new TestCoreService(); |
194 | target.intentService = this.intentService; | 226 | target.intentService = this.intentService; |
195 | target.pathService = this.pathService; | 227 | target.pathService = this.pathService; |
196 | target.linkService = this.linkService; | 228 | target.linkService = this.linkService; |
197 | - target.mastershipService = new TestMastershipService(); | 229 | + target.mastershipService = this.mastershipService; |
198 | - target.clusterService = new TestClusterService(); | 230 | + target.clusterService = this.clusterService; |
199 | target.storageService = new TestStorageService(); | 231 | target.storageService = new TestStorageService(); |
200 | target.deviceService = this.deviceService; | 232 | target.deviceService = this.deviceService; |
201 | target.networkConfigService = new TestNetworkConfigService(); | 233 | target.networkConfigService = new TestNetworkConfigService(); |
... | @@ -310,15 +342,16 @@ public class OpticalPathProvisionerTest { | ... | @@ -310,15 +342,16 @@ public class OpticalPathProvisionerTest { |
310 | } | 342 | } |
311 | 343 | ||
312 | /** | 344 | /** |
313 | - * Checks if PATH_INSTALLED event comes up after intent is installed. | 345 | + * Checks if PATH_INSTALLED event comes up after intent whose master is this node is installed. |
314 | */ | 346 | */ |
315 | @Test | 347 | @Test |
316 | - public void testInstalledEvent() { | 348 | + public void testInstalledEventLocal() { |
317 | Bandwidth bandwidth = Bandwidth.bps(100); | 349 | Bandwidth bandwidth = Bandwidth.bps(100); |
318 | Duration latency = Duration.ofMillis(10); | 350 | Duration latency = Duration.ofMillis(10); |
319 | 351 | ||
320 | OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency); | 352 | OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency); |
321 | 353 | ||
354 | + // notify all intents are installed | ||
322 | intentService.notifyInstalled(); | 355 | intentService.notifyInstalled(); |
323 | 356 | ||
324 | assertEquals(1, listener.events.size()); | 357 | assertEquals(1, listener.events.size()); |
... | @@ -327,26 +360,77 @@ public class OpticalPathProvisionerTest { | ... | @@ -327,26 +360,77 @@ public class OpticalPathProvisionerTest { |
327 | } | 360 | } |
328 | 361 | ||
329 | /** | 362 | /** |
363 | + * Checks if PATH_INSTALLED event comes up after intent whose master is remote node is installed. | ||
364 | + */ | ||
365 | + @Test | ||
366 | + public void testInstalledEventRemote() { | ||
367 | + // set the master for ingress device of intent to remote node | ||
368 | + mastershipService.setMastership(DEVICE2.id(), MastershipRole.NONE); | ||
369 | + | ||
370 | + Bandwidth bandwidth = Bandwidth.bps(100); | ||
371 | + Duration latency = Duration.ofMillis(10); | ||
372 | + | ||
373 | + OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency); | ||
374 | + | ||
375 | + // notify all intents are installed | ||
376 | + intentService.notifyInstalled(); | ||
377 | + | ||
378 | + // remote nodes must not receive event before distributed map is updated | ||
379 | + assertEquals(0, listener.events.size()); | ||
380 | + } | ||
381 | + | ||
382 | + /** | ||
330 | * Checks if PATH_REMOVED event comes up after packet link is removed. | 383 | * Checks if PATH_REMOVED event comes up after packet link is removed. |
331 | */ | 384 | */ |
332 | @Test | 385 | @Test |
333 | - public void testRemovedEvent() { | 386 | + public void testRemovedEventLocal() { |
334 | Bandwidth bandwidth = Bandwidth.bps(100); | 387 | Bandwidth bandwidth = Bandwidth.bps(100); |
335 | Duration latency = Duration.ofMillis(10); | 388 | Duration latency = Duration.ofMillis(10); |
336 | 389 | ||
337 | OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency); | 390 | OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency); |
338 | 391 | ||
392 | + // notify all intents are installed | ||
339 | intentService.notifyInstalled(); | 393 | intentService.notifyInstalled(); |
340 | 394 | ||
341 | target.removeConnectivity(cid); | 395 | target.removeConnectivity(cid); |
342 | 396 | ||
397 | + // notify all intents are withdrawn | ||
343 | intentService.notifyWithdrawn(); | 398 | intentService.notifyWithdrawn(); |
344 | 399 | ||
400 | + // must have received "INSTALLED" and "REMOVED" events | ||
345 | assertEquals(2, listener.events.size()); | 401 | assertEquals(2, listener.events.size()); |
402 | + assertEquals(OpticalPathEvent.Type.PATH_INSTALLED, listener.events.get(0).type()); | ||
403 | + assertEquals(cid, listener.events.get(0).subject()); | ||
346 | assertEquals(OpticalPathEvent.Type.PATH_REMOVED, listener.events.get(1).type()); | 404 | assertEquals(OpticalPathEvent.Type.PATH_REMOVED, listener.events.get(1).type()); |
347 | assertEquals(cid, listener.events.get(1).subject()); | 405 | assertEquals(cid, listener.events.get(1).subject()); |
348 | } | 406 | } |
349 | 407 | ||
408 | + | ||
409 | + /** | ||
410 | + * Checks if PATH_REMOVED event comes up after packet link is removed. | ||
411 | + */ | ||
412 | + @Test | ||
413 | + public void testRemovedEventRemote() { | ||
414 | + // set the master for ingress device of intent to remote node | ||
415 | + mastershipService.setMastership(DEVICE2.id(), MastershipRole.NONE); | ||
416 | + | ||
417 | + Bandwidth bandwidth = Bandwidth.bps(100); | ||
418 | + Duration latency = Duration.ofMillis(10); | ||
419 | + | ||
420 | + OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency); | ||
421 | + | ||
422 | + // notify all intents are installed | ||
423 | + intentService.notifyInstalled(); | ||
424 | + | ||
425 | + target.removeConnectivity(cid); | ||
426 | + | ||
427 | + // notify all intents are withdrawn | ||
428 | + intentService.notifyWithdrawn(); | ||
429 | + | ||
430 | + // remote nodes must not receive event before distributed map is updated | ||
431 | + assertEquals(0, listener.events.size()); | ||
432 | + } | ||
433 | + | ||
350 | private static ConnectPoint createConnectPoint(long devIdNum, long portIdNum) { | 434 | private static ConnectPoint createConnectPoint(long devIdNum, long portIdNum) { |
351 | return new ConnectPoint( | 435 | return new ConnectPoint( |
352 | deviceIdOf(devIdNum), | 436 | deviceIdOf(devIdNum), |
... | @@ -495,18 +579,192 @@ public class OpticalPathProvisionerTest { | ... | @@ -495,18 +579,192 @@ public class OpticalPathProvisionerTest { |
495 | } | 579 | } |
496 | 580 | ||
497 | private static class TestMastershipService extends MastershipServiceAdapter { | 581 | private static class TestMastershipService extends MastershipServiceAdapter { |
582 | + private Map<DeviceId, MastershipRole> mastershipMap = new HashMap<>(); | ||
583 | + | ||
584 | + public void setMastership(DeviceId deviceId, MastershipRole role) { | ||
585 | + mastershipMap.put(deviceId, role); | ||
586 | + } | ||
587 | + | ||
588 | + public void clear() { | ||
589 | + mastershipMap.clear(); | ||
590 | + } | ||
591 | + | ||
592 | + @Override | ||
593 | + public MastershipRole getLocalRole(DeviceId deviceId) { | ||
594 | + return mastershipMap.get(deviceId); | ||
595 | + } | ||
498 | 596 | ||
499 | } | 597 | } |
500 | 598 | ||
501 | private static class TestClusterService extends ClusterServiceAdapter { | 599 | private static class TestClusterService extends ClusterServiceAdapter { |
600 | + private NodeId nodeId; | ||
601 | + | ||
602 | + public void setLocalNode(String nodeIdStr) { | ||
603 | + nodeId = NodeId.nodeId(nodeIdStr); | ||
604 | + } | ||
502 | 605 | ||
606 | + @Override | ||
607 | + public ControllerNode getLocalNode() { | ||
608 | + return new ControllerNode() { | ||
609 | + @Override | ||
610 | + public NodeId id() { | ||
611 | + return nodeId; | ||
612 | + } | ||
613 | + | ||
614 | + @Override | ||
615 | + public IpAddress ip() { | ||
616 | + return null; | ||
617 | + } | ||
618 | + | ||
619 | + @Override | ||
620 | + public int tcpPort() { | ||
621 | + return 0; | ||
622 | + } | ||
623 | + }; | ||
624 | + } | ||
503 | } | 625 | } |
504 | 626 | ||
505 | private static class TestStorageService extends StorageServiceAdapter { | 627 | private static class TestStorageService extends StorageServiceAdapter { |
628 | + | ||
629 | + @Override | ||
630 | + public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() { | ||
631 | + ConsistentMapBuilder<K, V> builder = new ConsistentMapBuilder<K, V>() { | ||
632 | + @Override | ||
633 | + public AsyncConsistentMap<K, V> buildAsyncMap() { | ||
634 | + return null; | ||
635 | + } | ||
636 | + | ||
637 | + @Override | ||
638 | + public ConsistentMap<K, V> build() { | ||
639 | + return new TestConsistentMap<K, V>(); | ||
640 | + } | ||
641 | + }; | ||
642 | + | ||
643 | + return builder; | ||
644 | + } | ||
645 | + | ||
646 | + @Override | ||
647 | + public <E> DistributedSetBuilder<E> setBuilder() { | ||
648 | + DistributedSetBuilder<E> builder = new DistributedSetBuilder<E>() { | ||
649 | + @Override | ||
650 | + public AsyncDistributedSet<E> build() { | ||
651 | + return new DistributedSetAdapter<E>() { | ||
652 | + @Override | ||
653 | + public DistributedSet<E> asDistributedSet() { | ||
654 | + return new TestDistributedSet<E>(); | ||
655 | + } | ||
656 | + }; | ||
657 | + } | ||
658 | + }; | ||
659 | + | ||
660 | + return builder; | ||
661 | + } | ||
662 | + | ||
506 | @Override | 663 | @Override |
507 | public AtomicCounter getAtomicCounter(String name) { | 664 | public AtomicCounter getAtomicCounter(String name) { |
508 | return new MockAtomicCounter(); | 665 | return new MockAtomicCounter(); |
509 | } | 666 | } |
667 | + | ||
668 | + // Mock ConsistentMap that behaves as a HashMap | ||
669 | + class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> { | ||
670 | + private Map<K, Versioned<V>> map = new HashMap<>(); | ||
671 | + private Map<MapEventListener<K, V>, Executor> listeners = new HashMap<>(); | ||
672 | + | ||
673 | + public void notifyListeners(MapEvent<K, V> event) { | ||
674 | + listeners.forEach((c, e) -> e.execute(() -> c.event(event))); | ||
675 | + } | ||
676 | + | ||
677 | + @Override | ||
678 | + public int size() { | ||
679 | + return map.size(); | ||
680 | + } | ||
681 | + | ||
682 | + @Override | ||
683 | + public Versioned<V> put(K key, V value) { | ||
684 | + Versioned<V> oldValue = map.get(key); | ||
685 | + Versioned<V> newValue = new Versioned<>(value, oldValue == null ? 0 : oldValue.version() + 1); | ||
686 | + map.put(key, newValue); | ||
687 | + notifyListeners(new MapEvent<>(name(), key, newValue, oldValue)); | ||
688 | + return newValue; | ||
689 | + } | ||
690 | + | ||
691 | + @Override | ||
692 | + public Versioned<V> get(K key) { | ||
693 | + return map.get(key); | ||
694 | + } | ||
695 | + | ||
696 | + @Override | ||
697 | + public Versioned<V> remove(K key) { | ||
698 | + Versioned<V> oldValue = map.remove(key); | ||
699 | + notifyListeners(new MapEvent<>(name(), key, oldValue, null)); | ||
700 | + return oldValue; | ||
701 | + } | ||
702 | + | ||
703 | + @Override | ||
704 | + public Versioned<V> computeIfPresent(K key, | ||
705 | + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { | ||
706 | + Versioned<V> oldValue = map.get(key); | ||
707 | + Versioned<V> newValue = new Versioned<>(remappingFunction.apply(key, oldValue.value()), | ||
708 | + oldValue == null ? 0 : oldValue.version() + 1); | ||
709 | + map.put(key, newValue); | ||
710 | + notifyListeners(new MapEvent<>(name(), key, newValue, oldValue)); | ||
711 | + return newValue; | ||
712 | + } | ||
713 | + | ||
714 | + | ||
715 | + @Override | ||
716 | + public Set<Map.Entry<K, Versioned<V>>> entrySet() { | ||
717 | + return map.entrySet(); | ||
718 | + } | ||
719 | + | ||
720 | + @Override | ||
721 | + public Set<K> keySet() { | ||
722 | + return map.keySet(); | ||
723 | + } | ||
724 | + | ||
725 | + @Override | ||
726 | + public Collection<Versioned<V>> values() { | ||
727 | + return map.values(); | ||
728 | + } | ||
729 | + | ||
730 | + @Override | ||
731 | + public void clear() { | ||
732 | + map.clear(); | ||
733 | + } | ||
734 | + | ||
735 | + @Override | ||
736 | + public void addListener(MapEventListener<K, V> listener, Executor executor) { | ||
737 | + listeners.put(listener, executor); | ||
738 | + } | ||
739 | + | ||
740 | + @Override | ||
741 | + public void removeListener(MapEventListener<K, V> listener) { | ||
742 | + listeners.remove(listener); | ||
743 | + } | ||
744 | + } | ||
745 | + | ||
746 | + // Mock DistributedSet that behaves as a HashSet | ||
747 | + class TestDistributedSet<E> extends HashSet<E> implements DistributedSet<E> { | ||
748 | + | ||
749 | + @Override | ||
750 | + public void addListener(SetEventListener<E> listener) { | ||
751 | + } | ||
752 | + | ||
753 | + @Override | ||
754 | + public void removeListener(SetEventListener<E> listener) { | ||
755 | + } | ||
756 | + | ||
757 | + @Override | ||
758 | + public String name() { | ||
759 | + return null; | ||
760 | + } | ||
761 | + | ||
762 | + @Override | ||
763 | + public Type primitiveType() { | ||
764 | + return null; | ||
765 | + } | ||
766 | + } | ||
767 | + | ||
510 | } | 768 | } |
511 | 769 | ||
512 | private static class TestDeviceService extends DeviceServiceAdapter { | 770 | private static class TestDeviceService extends DeviceServiceAdapter { |
... | @@ -525,6 +783,25 @@ public class OpticalPathProvisionerTest { | ... | @@ -525,6 +783,25 @@ public class OpticalPathProvisionerTest { |
525 | } | 783 | } |
526 | 784 | ||
527 | private static class TestNetworkConfigService extends NetworkConfigServiceAdapter { | 785 | private static class TestNetworkConfigService extends NetworkConfigServiceAdapter { |
786 | + @Override | ||
787 | + @SuppressWarnings("unchecked") | ||
788 | + public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) { | ||
789 | + if (BandwidthCapacity.class.equals(configClass)) { | ||
790 | + return (C) new BandwidthCapacity() { | ||
791 | + @Override | ||
792 | + public void apply() { | ||
793 | + // do nothing | ||
794 | + } | ||
795 | + | ||
796 | + @Override | ||
797 | + public BandwidthCapacity capacity(Bandwidth bandwidth) { | ||
798 | + // do nothing | ||
799 | + return this; | ||
800 | + } | ||
801 | + }; | ||
802 | + } | ||
803 | + return null; | ||
804 | + } | ||
528 | 805 | ||
529 | } | 806 | } |
530 | 807 | ... | ... |
-
Please register or login to post a comment