Moved the BGP Route Intent synchronization mechanism from the Router class
to the new class IntentSynchronizer. Also, minor cleanup in some of the method names and access scope. Change-Id: I38257cd1d9516ef3b3dd50f23c28015054c73d70
Showing
10 changed files
with
523 additions
and
418 deletions
1 | +/* | ||
2 | + * Copyright 2014 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.onlab.onos.sdnip; | ||
17 | + | ||
18 | +import java.util.Collection; | ||
19 | +import java.util.HashMap; | ||
20 | +import java.util.LinkedList; | ||
21 | +import java.util.List; | ||
22 | +import java.util.Map; | ||
23 | +import java.util.concurrent.ConcurrentHashMap; | ||
24 | +import java.util.concurrent.ExecutorService; | ||
25 | +import java.util.concurrent.Executors; | ||
26 | +import java.util.concurrent.Semaphore; | ||
27 | + | ||
28 | +import org.apache.commons.lang3.tuple.Pair; | ||
29 | +import org.onlab.onos.core.ApplicationId; | ||
30 | +import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion; | ||
31 | +import org.onlab.onos.net.flow.criteria.Criterion; | ||
32 | +import org.onlab.onos.net.intent.Intent; | ||
33 | +import org.onlab.onos.net.intent.IntentService; | ||
34 | +import org.onlab.onos.net.intent.IntentState; | ||
35 | +import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; | ||
36 | +import org.onlab.packet.Ip4Prefix; | ||
37 | +import org.slf4j.Logger; | ||
38 | +import org.slf4j.LoggerFactory; | ||
39 | + | ||
40 | +import com.google.common.base.Objects; | ||
41 | +import com.google.common.util.concurrent.ThreadFactoryBuilder; | ||
42 | + | ||
43 | +public class IntentSynchronizer { | ||
44 | + private static final Logger log = | ||
45 | + LoggerFactory.getLogger(IntentSynchronizer.class); | ||
46 | + | ||
47 | + private final ApplicationId appId; | ||
48 | + private final IntentService intentService; | ||
49 | + private final Map<Ip4Prefix, MultiPointToSinglePointIntent> pushedRouteIntents; | ||
50 | + | ||
51 | + // | ||
52 | + // State to deal with SDN-IP Leader election and pushing Intents | ||
53 | + // | ||
54 | + private final ExecutorService bgpIntentsSynchronizerExecutor; | ||
55 | + private final Semaphore intentsSynchronizerSemaphore = new Semaphore(0); | ||
56 | + private volatile boolean isElectedLeader = false; | ||
57 | + private volatile boolean isActivatedLeader = false; | ||
58 | + | ||
59 | + /** | ||
60 | + * Class constructor. | ||
61 | + * | ||
62 | + * @param appId the Application ID | ||
63 | + * @param intentService the intent service | ||
64 | + */ | ||
65 | + IntentSynchronizer(ApplicationId appId, IntentService intentService) { | ||
66 | + this.appId = appId; | ||
67 | + this.intentService = intentService; | ||
68 | + pushedRouteIntents = new ConcurrentHashMap<>(); | ||
69 | + | ||
70 | + bgpIntentsSynchronizerExecutor = Executors.newSingleThreadExecutor( | ||
71 | + new ThreadFactoryBuilder() | ||
72 | + .setNameFormat("bgp-intents-synchronizer-%d").build()); | ||
73 | + } | ||
74 | + | ||
75 | + /** | ||
76 | + * Starts the synchronizer. | ||
77 | + */ | ||
78 | + public void start() { | ||
79 | + bgpIntentsSynchronizerExecutor.execute(new Runnable() { | ||
80 | + @Override | ||
81 | + public void run() { | ||
82 | + doIntentSynchronizationThread(); | ||
83 | + } | ||
84 | + }); | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * Stops the synchronizer. | ||
89 | + */ | ||
90 | + public void stop() { | ||
91 | + // Stop the thread(s) | ||
92 | + bgpIntentsSynchronizerExecutor.shutdownNow(); | ||
93 | + | ||
94 | + // | ||
95 | + // Withdraw all SDN-IP intents | ||
96 | + // | ||
97 | + if (!isElectedLeader) { | ||
98 | + return; // Nothing to do: not the leader anymore | ||
99 | + } | ||
100 | + log.debug("Withdrawing all SDN-IP Route Intents..."); | ||
101 | + for (Intent intent : intentService.getIntents()) { | ||
102 | + if (!(intent instanceof MultiPointToSinglePointIntent) | ||
103 | + || !intent.appId().equals(appId)) { | ||
104 | + continue; | ||
105 | + } | ||
106 | + intentService.withdraw(intent); | ||
107 | + } | ||
108 | + | ||
109 | + pushedRouteIntents.clear(); | ||
110 | + } | ||
111 | + | ||
112 | + //@Override TODO hook this up to something | ||
113 | + public void leaderChanged(boolean isLeader) { | ||
114 | + log.debug("Leader changed: {}", isLeader); | ||
115 | + | ||
116 | + if (!isLeader) { | ||
117 | + this.isElectedLeader = false; | ||
118 | + this.isActivatedLeader = false; | ||
119 | + return; // Nothing to do | ||
120 | + } | ||
121 | + this.isActivatedLeader = false; | ||
122 | + this.isElectedLeader = true; | ||
123 | + | ||
124 | + // | ||
125 | + // Tell the Intents Synchronizer thread to start the synchronization | ||
126 | + // | ||
127 | + intentsSynchronizerSemaphore.release(); | ||
128 | + } | ||
129 | + | ||
130 | + /** | ||
131 | + * Gets the pushed route intents. | ||
132 | + * | ||
133 | + * @return the pushed route intents | ||
134 | + */ | ||
135 | + public Collection<MultiPointToSinglePointIntent> getPushedRouteIntents() { | ||
136 | + List<MultiPointToSinglePointIntent> pushedIntents = new LinkedList<>(); | ||
137 | + | ||
138 | + for (Map.Entry<Ip4Prefix, MultiPointToSinglePointIntent> entry : | ||
139 | + pushedRouteIntents.entrySet()) { | ||
140 | + pushedIntents.add(entry.getValue()); | ||
141 | + } | ||
142 | + return pushedIntents; | ||
143 | + } | ||
144 | + | ||
145 | + /** | ||
146 | + * Thread for Intent Synchronization. | ||
147 | + */ | ||
148 | + private void doIntentSynchronizationThread() { | ||
149 | + boolean interrupted = false; | ||
150 | + try { | ||
151 | + while (!interrupted) { | ||
152 | + try { | ||
153 | + intentsSynchronizerSemaphore.acquire(); | ||
154 | + // | ||
155 | + // Drain all permits, because a single synchronization is | ||
156 | + // sufficient. | ||
157 | + // | ||
158 | + intentsSynchronizerSemaphore.drainPermits(); | ||
159 | + } catch (InterruptedException e) { | ||
160 | + log.debug("Interrupted while waiting to become " + | ||
161 | + "Intent Synchronization leader"); | ||
162 | + interrupted = true; | ||
163 | + break; | ||
164 | + } | ||
165 | + syncIntents(); | ||
166 | + } | ||
167 | + } finally { | ||
168 | + if (interrupted) { | ||
169 | + Thread.currentThread().interrupt(); | ||
170 | + } | ||
171 | + } | ||
172 | + } | ||
173 | + | ||
174 | + /** | ||
175 | + * Submits a multi-point-to-single-point intent. | ||
176 | + * | ||
177 | + * @param prefix the IPv4 matching prefix for the intent to submit | ||
178 | + * @param intent the intent to submit | ||
179 | + */ | ||
180 | + void submitRouteIntent(Ip4Prefix prefix, | ||
181 | + MultiPointToSinglePointIntent intent) { | ||
182 | + synchronized (this) { | ||
183 | + if (isElectedLeader && isActivatedLeader) { | ||
184 | + log.debug("Intent installation: adding Intent for prefix: {}", | ||
185 | + prefix); | ||
186 | + intentService.submit(intent); | ||
187 | + } | ||
188 | + | ||
189 | + // Maintain the Intent | ||
190 | + pushedRouteIntents.put(prefix, intent); | ||
191 | + } | ||
192 | + } | ||
193 | + | ||
194 | + /** | ||
195 | + * Withdraws a multi-point-to-single-point intent. | ||
196 | + * | ||
197 | + * @param prefix the IPv4 matching prefix for the intent to withdraw. | ||
198 | + */ | ||
199 | + void withdrawRouteIntent(Ip4Prefix prefix) { | ||
200 | + synchronized (this) { | ||
201 | + MultiPointToSinglePointIntent intent = | ||
202 | + pushedRouteIntents.remove(prefix); | ||
203 | + | ||
204 | + if (intent == null) { | ||
205 | + log.debug("There is no intent in pushedRouteIntents to delete " + | ||
206 | + "for prefix: {}", prefix); | ||
207 | + return; | ||
208 | + } | ||
209 | + | ||
210 | + if (isElectedLeader && isActivatedLeader) { | ||
211 | + log.debug("Intent installation: deleting Intent for prefix: {}", | ||
212 | + prefix); | ||
213 | + intentService.withdraw(intent); | ||
214 | + } | ||
215 | + } | ||
216 | + } | ||
217 | + | ||
218 | + /** | ||
219 | + * Performs Intents Synchronization between the internally stored Route | ||
220 | + * Intents and the installed Route Intents. | ||
221 | + */ | ||
222 | + private void syncIntents() { | ||
223 | + synchronized (this) { | ||
224 | + if (!isElectedLeader) { | ||
225 | + return; // Nothing to do: not the leader anymore | ||
226 | + } | ||
227 | + log.debug("Syncing SDN-IP Route Intents..."); | ||
228 | + | ||
229 | + Map<Ip4Prefix, MultiPointToSinglePointIntent> fetchedIntents = | ||
230 | + new HashMap<>(); | ||
231 | + | ||
232 | + // | ||
233 | + // Fetch all intents, and classify the Multi-Point-to-Point Intents | ||
234 | + // based on the matching prefix. | ||
235 | + // | ||
236 | + for (Intent intent : intentService.getIntents()) { | ||
237 | + | ||
238 | + if (!(intent instanceof MultiPointToSinglePointIntent) | ||
239 | + || !intent.appId().equals(appId)) { | ||
240 | + continue; | ||
241 | + } | ||
242 | + MultiPointToSinglePointIntent mp2pIntent = | ||
243 | + (MultiPointToSinglePointIntent) intent; | ||
244 | + | ||
245 | + Criterion c = | ||
246 | + mp2pIntent.selector().getCriterion(Criterion.Type.IPV4_DST); | ||
247 | + if (c != null && c instanceof IPCriterion) { | ||
248 | + IPCriterion ipCriterion = (IPCriterion) c; | ||
249 | + Ip4Prefix ip4Prefix = ipCriterion.ip().getIp4Prefix(); | ||
250 | + if (ip4Prefix == null) { | ||
251 | + // TODO: For now we support only IPv4 | ||
252 | + continue; | ||
253 | + } | ||
254 | + fetchedIntents.put(ip4Prefix, mp2pIntent); | ||
255 | + } else { | ||
256 | + log.warn("No IPV4_DST criterion found for intent {}", | ||
257 | + mp2pIntent.id()); | ||
258 | + } | ||
259 | + | ||
260 | + } | ||
261 | + | ||
262 | + // | ||
263 | + // Compare for each prefix the local IN-MEMORY Intents with the | ||
264 | + // FETCHED Intents: | ||
265 | + // - If the IN-MEMORY Intent is same as the FETCHED Intent, store | ||
266 | + // the FETCHED Intent in the local memory (i.e., override the | ||
267 | + // IN-MEMORY Intent) to preserve the original Intent ID | ||
268 | + // - if the IN-MEMORY Intent is not same as the FETCHED Intent, | ||
269 | + // delete the FETCHED Intent, and push/install the IN-MEMORY | ||
270 | + // Intent. | ||
271 | + // - If there is an IN-MEMORY Intent for a prefix, but no FETCHED | ||
272 | + // Intent for same prefix, then push/install the IN-MEMORY | ||
273 | + // Intent. | ||
274 | + // - If there is a FETCHED Intent for a prefix, but no IN-MEMORY | ||
275 | + // Intent for same prefix, then delete/withdraw the FETCHED | ||
276 | + // Intent. | ||
277 | + // | ||
278 | + Collection<Pair<Ip4Prefix, MultiPointToSinglePointIntent>> | ||
279 | + storeInMemoryIntents = new LinkedList<>(); | ||
280 | + Collection<Pair<Ip4Prefix, MultiPointToSinglePointIntent>> | ||
281 | + addIntents = new LinkedList<>(); | ||
282 | + Collection<Pair<Ip4Prefix, MultiPointToSinglePointIntent>> | ||
283 | + deleteIntents = new LinkedList<>(); | ||
284 | + for (Map.Entry<Ip4Prefix, MultiPointToSinglePointIntent> entry : | ||
285 | + pushedRouteIntents.entrySet()) { | ||
286 | + Ip4Prefix prefix = entry.getKey(); | ||
287 | + MultiPointToSinglePointIntent inMemoryIntent = | ||
288 | + entry.getValue(); | ||
289 | + MultiPointToSinglePointIntent fetchedIntent = | ||
290 | + fetchedIntents.get(prefix); | ||
291 | + | ||
292 | + if (fetchedIntent == null) { | ||
293 | + // | ||
294 | + // No FETCHED Intent for same prefix: push the IN-MEMORY | ||
295 | + // Intent. | ||
296 | + // | ||
297 | + addIntents.add(Pair.of(prefix, inMemoryIntent)); | ||
298 | + continue; | ||
299 | + } | ||
300 | + | ||
301 | + IntentState state = intentService.getIntentState(fetchedIntent.id()); | ||
302 | + if (state == IntentState.WITHDRAWING || | ||
303 | + state == IntentState.WITHDRAWN) { | ||
304 | + // The intent has been withdrawn but according to our route | ||
305 | + // table it should be installed. We'll reinstall it. | ||
306 | + addIntents.add(Pair.of(prefix, inMemoryIntent)); | ||
307 | + } | ||
308 | + | ||
309 | + // | ||
310 | + // If IN-MEMORY Intent is same as the FETCHED Intent, | ||
311 | + // store the FETCHED Intent in the local memory. | ||
312 | + // | ||
313 | + if (compareMultiPointToSinglePointIntents(inMemoryIntent, | ||
314 | + fetchedIntent)) { | ||
315 | + storeInMemoryIntents.add(Pair.of(prefix, fetchedIntent)); | ||
316 | + } else { | ||
317 | + // | ||
318 | + // The IN-MEMORY Intent is not same as the FETCHED Intent, | ||
319 | + // hence delete the FETCHED Intent, and install the | ||
320 | + // IN-MEMORY Intent. | ||
321 | + // | ||
322 | + deleteIntents.add(Pair.of(prefix, fetchedIntent)); | ||
323 | + addIntents.add(Pair.of(prefix, inMemoryIntent)); | ||
324 | + } | ||
325 | + fetchedIntents.remove(prefix); | ||
326 | + } | ||
327 | + | ||
328 | + // | ||
329 | + // Any remaining FETCHED Intents have to be deleted/withdrawn | ||
330 | + // | ||
331 | + for (Map.Entry<Ip4Prefix, MultiPointToSinglePointIntent> entry : | ||
332 | + fetchedIntents.entrySet()) { | ||
333 | + Ip4Prefix prefix = entry.getKey(); | ||
334 | + MultiPointToSinglePointIntent fetchedIntent = entry.getValue(); | ||
335 | + deleteIntents.add(Pair.of(prefix, fetchedIntent)); | ||
336 | + } | ||
337 | + | ||
338 | + // | ||
339 | + // Perform the actions: | ||
340 | + // 1. Store in memory fetched intents that are same. Can be done | ||
341 | + // even if we are not the leader anymore | ||
342 | + // 2. Delete intents: check if the leader before each operation | ||
343 | + // 3. Add intents: check if the leader before each operation | ||
344 | + // | ||
345 | + for (Pair<Ip4Prefix, MultiPointToSinglePointIntent> pair : | ||
346 | + storeInMemoryIntents) { | ||
347 | + Ip4Prefix prefix = pair.getLeft(); | ||
348 | + MultiPointToSinglePointIntent intent = pair.getRight(); | ||
349 | + log.debug("Intent synchronization: updating in-memory " + | ||
350 | + "Intent for prefix: {}", prefix); | ||
351 | + pushedRouteIntents.put(prefix, intent); | ||
352 | + } | ||
353 | + // | ||
354 | + isActivatedLeader = true; // Allow push of Intents | ||
355 | + for (Pair<Ip4Prefix, MultiPointToSinglePointIntent> pair : | ||
356 | + deleteIntents) { | ||
357 | + Ip4Prefix prefix = pair.getLeft(); | ||
358 | + MultiPointToSinglePointIntent intent = pair.getRight(); | ||
359 | + if (!isElectedLeader) { | ||
360 | + isActivatedLeader = false; | ||
361 | + return; | ||
362 | + } | ||
363 | + log.debug("Intent synchronization: deleting Intent for " + | ||
364 | + "prefix: {}", prefix); | ||
365 | + intentService.withdraw(intent); | ||
366 | + } | ||
367 | + // | ||
368 | + for (Pair<Ip4Prefix, MultiPointToSinglePointIntent> pair : | ||
369 | + addIntents) { | ||
370 | + Ip4Prefix prefix = pair.getLeft(); | ||
371 | + MultiPointToSinglePointIntent intent = pair.getRight(); | ||
372 | + if (!isElectedLeader) { | ||
373 | + isActivatedLeader = false; | ||
374 | + return; | ||
375 | + } | ||
376 | + log.debug("Intent synchronization: adding Intent for " + | ||
377 | + "prefix: {}", prefix); | ||
378 | + intentService.submit(intent); | ||
379 | + } | ||
380 | + if (!isElectedLeader) { | ||
381 | + isActivatedLeader = false; | ||
382 | + } | ||
383 | + log.debug("Syncing SDN-IP routes completed."); | ||
384 | + } | ||
385 | + } | ||
386 | + | ||
387 | + /** | ||
388 | + * Compares two Multi-point to Single Point Intents whether they represent | ||
389 | + * same logical intention. | ||
390 | + * | ||
391 | + * @param intent1 the first Intent to compare | ||
392 | + * @param intent2 the second Intent to compare | ||
393 | + * @return true if both Intents represent same logical intention, otherwise | ||
394 | + * false | ||
395 | + */ | ||
396 | + private boolean compareMultiPointToSinglePointIntents( | ||
397 | + MultiPointToSinglePointIntent intent1, | ||
398 | + MultiPointToSinglePointIntent intent2) { | ||
399 | + | ||
400 | + return Objects.equal(intent1.appId(), intent2.appId()) && | ||
401 | + Objects.equal(intent1.selector(), intent2.selector()) && | ||
402 | + Objects.equal(intent1.treatment(), intent2.treatment()) && | ||
403 | + Objects.equal(intent1.ingressPoints(), intent2.ingressPoints()) && | ||
404 | + Objects.equal(intent1.egressPoint(), intent2.egressPoint()); | ||
405 | + } | ||
406 | +} |
... | @@ -96,6 +96,13 @@ public class PeerConnectivityManager { | ... | @@ -96,6 +96,13 @@ public class PeerConnectivityManager { |
96 | } | 96 | } |
97 | 97 | ||
98 | /** | 98 | /** |
99 | + * Stops the peer connectivity manager. | ||
100 | + */ | ||
101 | + public void stop() { | ||
102 | + // TODO: Implement it | ||
103 | + } | ||
104 | + | ||
105 | + /** | ||
99 | * Sets up paths to establish connectivity between all internal | 106 | * Sets up paths to establish connectivity between all internal |
100 | * {@link BgpSpeaker}s and all external {@link BgpPeer}s. | 107 | * {@link BgpSpeaker}s and all external {@link BgpPeer}s. |
101 | */ | 108 | */ | ... | ... |
... | @@ -16,21 +16,16 @@ | ... | @@ -16,21 +16,16 @@ |
16 | package org.onlab.onos.sdnip; | 16 | package org.onlab.onos.sdnip; |
17 | 17 | ||
18 | import java.util.Collection; | 18 | import java.util.Collection; |
19 | -import java.util.HashMap; | ||
20 | import java.util.HashSet; | 19 | import java.util.HashSet; |
21 | import java.util.Iterator; | 20 | import java.util.Iterator; |
22 | import java.util.LinkedList; | 21 | import java.util.LinkedList; |
23 | import java.util.List; | 22 | import java.util.List; |
24 | -import java.util.Map; | ||
25 | import java.util.Set; | 23 | import java.util.Set; |
26 | import java.util.concurrent.BlockingQueue; | 24 | import java.util.concurrent.BlockingQueue; |
27 | -import java.util.concurrent.ConcurrentHashMap; | ||
28 | import java.util.concurrent.ExecutorService; | 25 | import java.util.concurrent.ExecutorService; |
29 | import java.util.concurrent.Executors; | 26 | import java.util.concurrent.Executors; |
30 | import java.util.concurrent.LinkedBlockingQueue; | 27 | import java.util.concurrent.LinkedBlockingQueue; |
31 | -import java.util.concurrent.Semaphore; | ||
32 | 28 | ||
33 | -import org.apache.commons.lang3.tuple.Pair; | ||
34 | import org.onlab.onos.core.ApplicationId; | 29 | import org.onlab.onos.core.ApplicationId; |
35 | import org.onlab.onos.net.ConnectPoint; | 30 | import org.onlab.onos.net.ConnectPoint; |
36 | import org.onlab.onos.net.Host; | 31 | import org.onlab.onos.net.Host; |
... | @@ -38,15 +33,9 @@ import org.onlab.onos.net.flow.DefaultTrafficSelector; | ... | @@ -38,15 +33,9 @@ import org.onlab.onos.net.flow.DefaultTrafficSelector; |
38 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; | 33 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; |
39 | import org.onlab.onos.net.flow.TrafficSelector; | 34 | import org.onlab.onos.net.flow.TrafficSelector; |
40 | import org.onlab.onos.net.flow.TrafficTreatment; | 35 | import org.onlab.onos.net.flow.TrafficTreatment; |
41 | -import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion; | ||
42 | -import org.onlab.onos.net.flow.criteria.Criterion; | ||
43 | -import org.onlab.onos.net.flow.criteria.Criterion.Type; | ||
44 | import org.onlab.onos.net.host.HostEvent; | 36 | import org.onlab.onos.net.host.HostEvent; |
45 | import org.onlab.onos.net.host.HostListener; | 37 | import org.onlab.onos.net.host.HostListener; |
46 | import org.onlab.onos.net.host.HostService; | 38 | import org.onlab.onos.net.host.HostService; |
47 | -import org.onlab.onos.net.intent.Intent; | ||
48 | -import org.onlab.onos.net.intent.IntentService; | ||
49 | -import org.onlab.onos.net.intent.IntentState; | ||
50 | import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; | 39 | import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; |
51 | import org.onlab.onos.sdnip.config.BgpPeer; | 40 | import org.onlab.onos.sdnip.config.BgpPeer; |
52 | import org.onlab.onos.sdnip.config.Interface; | 41 | import org.onlab.onos.sdnip.config.Interface; |
... | @@ -59,7 +48,6 @@ import org.onlab.packet.MacAddress; | ... | @@ -59,7 +48,6 @@ import org.onlab.packet.MacAddress; |
59 | import org.slf4j.Logger; | 48 | import org.slf4j.Logger; |
60 | import org.slf4j.LoggerFactory; | 49 | import org.slf4j.LoggerFactory; |
61 | 50 | ||
62 | -import com.google.common.base.Objects; | ||
63 | import com.google.common.collect.HashMultimap; | 51 | import com.google.common.collect.HashMultimap; |
64 | import com.google.common.collect.Multimaps; | 52 | import com.google.common.collect.Multimaps; |
65 | import com.google.common.collect.SetMultimap; | 53 | import com.google.common.collect.SetMultimap; |
... | @@ -76,100 +64,81 @@ import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree; | ... | @@ -76,100 +64,81 @@ import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree; |
76 | public class Router implements RouteListener { | 64 | public class Router implements RouteListener { |
77 | 65 | ||
78 | private static final Logger log = LoggerFactory.getLogger(Router.class); | 66 | private static final Logger log = LoggerFactory.getLogger(Router.class); |
67 | + // For routes announced by local BGP daemon in SDN network, | ||
68 | + // the next hop will be 0.0.0.0. | ||
69 | + private static final Ip4Address LOCAL_NEXT_HOP = | ||
70 | + Ip4Address.valueOf("0.0.0.0"); | ||
79 | 71 | ||
80 | // Store all route updates in a radix tree. | 72 | // Store all route updates in a radix tree. |
81 | // The key in this tree is the binary string of prefix of the route. | 73 | // The key in this tree is the binary string of prefix of the route. |
82 | private InvertedRadixTree<RouteEntry> bgpRoutes; | 74 | private InvertedRadixTree<RouteEntry> bgpRoutes; |
83 | 75 | ||
84 | // Stores all incoming route updates in a queue. | 76 | // Stores all incoming route updates in a queue. |
85 | - private BlockingQueue<RouteUpdate> routeUpdates; | 77 | + private final BlockingQueue<RouteUpdate> routeUpdates; |
86 | 78 | ||
87 | // The Ip4Address is the next hop address of each route update. | 79 | // The Ip4Address is the next hop address of each route update. |
88 | - private SetMultimap<Ip4Address, RouteEntry> routesWaitingOnArp; | 80 | + private final SetMultimap<Ip4Address, RouteEntry> routesWaitingOnArp; |
89 | - private ConcurrentHashMap<Ip4Prefix, MultiPointToSinglePointIntent> pushedRouteIntents; | ||
90 | - | ||
91 | - private IntentService intentService; | ||
92 | - private HostService hostService; | ||
93 | - private SdnIpConfigService configService; | ||
94 | - private InterfaceService interfaceService; | ||
95 | - | ||
96 | - private ExecutorService bgpUpdatesExecutor; | ||
97 | - private ExecutorService bgpIntentsSynchronizerExecutor; | ||
98 | 81 | ||
99 | private final ApplicationId appId; | 82 | private final ApplicationId appId; |
100 | - | 83 | + private final IntentSynchronizer intentSynchronizer; |
101 | - // | 84 | + private final HostService hostService; |
102 | - // State to deal with SDN-IP Leader election and pushing Intents | 85 | + private final SdnIpConfigService configService; |
103 | - // | 86 | + private final InterfaceService interfaceService; |
104 | - private Semaphore intentsSynchronizerSemaphore = new Semaphore(0); | 87 | + private final ExecutorService bgpUpdatesExecutor; |
105 | - private volatile boolean isElectedLeader = false; | 88 | + private final HostListener hostListener; |
106 | - private volatile boolean isActivatedLeader = false; | ||
107 | - | ||
108 | - // For routes announced by local BGP daemon in SDN network, | ||
109 | - // the next hop will be 0.0.0.0. | ||
110 | - public static final Ip4Address LOCAL_NEXT_HOP = | ||
111 | - Ip4Address.valueOf("0.0.0.0"); | ||
112 | 89 | ||
113 | /** | 90 | /** |
114 | * Class constructor. | 91 | * Class constructor. |
115 | * | 92 | * |
116 | * @param appId the application ID | 93 | * @param appId the application ID |
117 | - * @param intentService the intent service | 94 | + * @param intentSynchronizer the intent synchronizer |
118 | * @param hostService the host service | 95 | * @param hostService the host service |
119 | * @param configService the configuration service | 96 | * @param configService the configuration service |
120 | * @param interfaceService the interface service | 97 | * @param interfaceService the interface service |
121 | */ | 98 | */ |
122 | - public Router(ApplicationId appId, IntentService intentService, | 99 | + public Router(ApplicationId appId, IntentSynchronizer intentSynchronizer, |
123 | HostService hostService, SdnIpConfigService configService, | 100 | HostService hostService, SdnIpConfigService configService, |
124 | InterfaceService interfaceService) { | 101 | InterfaceService interfaceService) { |
125 | this.appId = appId; | 102 | this.appId = appId; |
126 | - this.intentService = intentService; | 103 | + this.intentSynchronizer = intentSynchronizer; |
127 | this.hostService = hostService; | 104 | this.hostService = hostService; |
128 | this.configService = configService; | 105 | this.configService = configService; |
129 | this.interfaceService = interfaceService; | 106 | this.interfaceService = interfaceService; |
130 | 107 | ||
108 | + this.hostListener = new InternalHostListener(); | ||
109 | + | ||
131 | bgpRoutes = new ConcurrentInvertedRadixTree<>( | 110 | bgpRoutes = new ConcurrentInvertedRadixTree<>( |
132 | new DefaultByteArrayNodeFactory()); | 111 | new DefaultByteArrayNodeFactory()); |
133 | routeUpdates = new LinkedBlockingQueue<>(); | 112 | routeUpdates = new LinkedBlockingQueue<>(); |
134 | routesWaitingOnArp = Multimaps.synchronizedSetMultimap( | 113 | routesWaitingOnArp = Multimaps.synchronizedSetMultimap( |
135 | HashMultimap.<Ip4Address, RouteEntry>create()); | 114 | HashMultimap.<Ip4Address, RouteEntry>create()); |
136 | - pushedRouteIntents = new ConcurrentHashMap<>(); | ||
137 | 115 | ||
138 | bgpUpdatesExecutor = Executors.newSingleThreadExecutor( | 116 | bgpUpdatesExecutor = Executors.newSingleThreadExecutor( |
139 | new ThreadFactoryBuilder().setNameFormat("bgp-updates-%d").build()); | 117 | new ThreadFactoryBuilder().setNameFormat("bgp-updates-%d").build()); |
140 | - bgpIntentsSynchronizerExecutor = Executors.newSingleThreadExecutor( | ||
141 | - new ThreadFactoryBuilder() | ||
142 | - .setNameFormat("bgp-intents-synchronizer-%d").build()); | ||
143 | - | ||
144 | - this.hostService.addListener(new InternalHostListener()); | ||
145 | } | 118 | } |
146 | 119 | ||
147 | /** | 120 | /** |
148 | * Starts the router. | 121 | * Starts the router. |
149 | */ | 122 | */ |
150 | public void start() { | 123 | public void start() { |
124 | + this.hostService.addListener(hostListener); | ||
125 | + | ||
151 | bgpUpdatesExecutor.execute(new Runnable() { | 126 | bgpUpdatesExecutor.execute(new Runnable() { |
152 | @Override | 127 | @Override |
153 | public void run() { | 128 | public void run() { |
154 | doUpdatesThread(); | 129 | doUpdatesThread(); |
155 | } | 130 | } |
156 | }); | 131 | }); |
157 | - | ||
158 | - bgpIntentsSynchronizerExecutor.execute(new Runnable() { | ||
159 | - @Override | ||
160 | - public void run() { | ||
161 | - doIntentSynchronizationThread(); | ||
162 | - } | ||
163 | - }); | ||
164 | } | 132 | } |
165 | 133 | ||
166 | /** | 134 | /** |
167 | - * Shuts the router down. | 135 | + * Stops the router. |
168 | */ | 136 | */ |
169 | - public void shutdown() { | 137 | + public void stop() { |
170 | - // Stop all threads | 138 | + this.hostService.removeListener(hostListener); |
139 | + | ||
140 | + // Stop the thread(s) | ||
171 | bgpUpdatesExecutor.shutdownNow(); | 141 | bgpUpdatesExecutor.shutdownNow(); |
172 | - bgpIntentsSynchronizerExecutor.shutdownNow(); | ||
173 | 142 | ||
174 | synchronized (this) { | 143 | synchronized (this) { |
175 | // Cleanup all local state | 144 | // Cleanup all local state |
... | @@ -177,42 +146,8 @@ public class Router implements RouteListener { | ... | @@ -177,42 +146,8 @@ public class Router implements RouteListener { |
177 | new DefaultByteArrayNodeFactory()); | 146 | new DefaultByteArrayNodeFactory()); |
178 | routeUpdates.clear(); | 147 | routeUpdates.clear(); |
179 | routesWaitingOnArp.clear(); | 148 | routesWaitingOnArp.clear(); |
180 | - pushedRouteIntents.clear(); | ||
181 | - | ||
182 | - // | ||
183 | - // Withdraw all SDN-IP intents | ||
184 | - // | ||
185 | - if (!isElectedLeader) { | ||
186 | - return; // Nothing to do: not the leader anymore | ||
187 | - } | ||
188 | - log.debug("Withdrawing all SDN-IP Route Intents..."); | ||
189 | - for (Intent intent : intentService.getIntents()) { | ||
190 | - if (!(intent instanceof MultiPointToSinglePointIntent) | ||
191 | - || !intent.appId().equals(appId)) { | ||
192 | - continue; | ||
193 | - } | ||
194 | - intentService.withdraw(intent); | ||
195 | } | 149 | } |
196 | } | 150 | } |
197 | - } | ||
198 | - | ||
199 | - //@Override TODO hook this up to something | ||
200 | - public void leaderChanged(boolean isLeader) { | ||
201 | - log.debug("Leader changed: {}", isLeader); | ||
202 | - | ||
203 | - if (!isLeader) { | ||
204 | - this.isElectedLeader = false; | ||
205 | - this.isActivatedLeader = false; | ||
206 | - return; // Nothing to do | ||
207 | - } | ||
208 | - this.isActivatedLeader = false; | ||
209 | - this.isElectedLeader = true; | ||
210 | - | ||
211 | - // | ||
212 | - // Tell the Intents Synchronizer thread to start the synchronization | ||
213 | - // | ||
214 | - intentsSynchronizerSemaphore.release(); | ||
215 | - } | ||
216 | 151 | ||
217 | @Override | 152 | @Override |
218 | public void update(RouteUpdate routeUpdate) { | 153 | public void update(RouteUpdate routeUpdate) { |
... | @@ -227,35 +162,6 @@ public class Router implements RouteListener { | ... | @@ -227,35 +162,6 @@ public class Router implements RouteListener { |
227 | } | 162 | } |
228 | 163 | ||
229 | /** | 164 | /** |
230 | - * Thread for Intent Synchronization. | ||
231 | - */ | ||
232 | - private void doIntentSynchronizationThread() { | ||
233 | - boolean interrupted = false; | ||
234 | - try { | ||
235 | - while (!interrupted) { | ||
236 | - try { | ||
237 | - intentsSynchronizerSemaphore.acquire(); | ||
238 | - // | ||
239 | - // Drain all permits, because a single synchronization is | ||
240 | - // sufficient. | ||
241 | - // | ||
242 | - intentsSynchronizerSemaphore.drainPermits(); | ||
243 | - } catch (InterruptedException e) { | ||
244 | - log.debug("Interrupted while waiting to become " + | ||
245 | - "Intent Synchronization leader"); | ||
246 | - interrupted = true; | ||
247 | - break; | ||
248 | - } | ||
249 | - syncIntents(); | ||
250 | - } | ||
251 | - } finally { | ||
252 | - if (interrupted) { | ||
253 | - Thread.currentThread().interrupt(); | ||
254 | - } | ||
255 | - } | ||
256 | - } | ||
257 | - | ||
258 | - /** | ||
259 | * Thread for handling route updates. | 165 | * Thread for handling route updates. |
260 | */ | 166 | */ |
261 | private void doUpdatesThread() { | 167 | private void doUpdatesThread() { |
... | @@ -290,194 +196,6 @@ public class Router implements RouteListener { | ... | @@ -290,194 +196,6 @@ public class Router implements RouteListener { |
290 | } | 196 | } |
291 | 197 | ||
292 | /** | 198 | /** |
293 | - * Performs Intents Synchronization between the internally stored Route | ||
294 | - * Intents and the installed Route Intents. | ||
295 | - */ | ||
296 | - private void syncIntents() { | ||
297 | - synchronized (this) { | ||
298 | - if (!isElectedLeader) { | ||
299 | - return; // Nothing to do: not the leader anymore | ||
300 | - } | ||
301 | - log.debug("Syncing SDN-IP Route Intents..."); | ||
302 | - | ||
303 | - Map<Ip4Prefix, MultiPointToSinglePointIntent> fetchedIntents = | ||
304 | - new HashMap<>(); | ||
305 | - | ||
306 | - // | ||
307 | - // Fetch all intents, and classify the Multi-Point-to-Point Intents | ||
308 | - // based on the matching prefix. | ||
309 | - // | ||
310 | - for (Intent intent : intentService.getIntents()) { | ||
311 | - | ||
312 | - if (!(intent instanceof MultiPointToSinglePointIntent) | ||
313 | - || !intent.appId().equals(appId)) { | ||
314 | - continue; | ||
315 | - } | ||
316 | - MultiPointToSinglePointIntent mp2pIntent = | ||
317 | - (MultiPointToSinglePointIntent) intent; | ||
318 | - | ||
319 | - Criterion c = mp2pIntent.selector().getCriterion(Type.IPV4_DST); | ||
320 | - if (c != null && c instanceof IPCriterion) { | ||
321 | - IPCriterion ipCriterion = (IPCriterion) c; | ||
322 | - Ip4Prefix ip4Prefix = ipCriterion.ip().getIp4Prefix(); | ||
323 | - if (ip4Prefix == null) { | ||
324 | - // TODO: For now we support only IPv4 | ||
325 | - continue; | ||
326 | - } | ||
327 | - fetchedIntents.put(ip4Prefix, mp2pIntent); | ||
328 | - } else { | ||
329 | - log.warn("No IPV4_DST criterion found for intent {}", | ||
330 | - mp2pIntent.id()); | ||
331 | - } | ||
332 | - | ||
333 | - } | ||
334 | - | ||
335 | - // | ||
336 | - // Compare for each prefix the local IN-MEMORY Intents with the | ||
337 | - // FETCHED Intents: | ||
338 | - // - If the IN-MEMORY Intent is same as the FETCHED Intent, store | ||
339 | - // the FETCHED Intent in the local memory (i.e., override the | ||
340 | - // IN-MEMORY Intent) to preserve the original Intent ID | ||
341 | - // - if the IN-MEMORY Intent is not same as the FETCHED Intent, | ||
342 | - // delete the FETCHED Intent, and push/install the IN-MEMORY | ||
343 | - // Intent. | ||
344 | - // - If there is an IN-MEMORY Intent for a prefix, but no FETCHED | ||
345 | - // Intent for same prefix, then push/install the IN-MEMORY | ||
346 | - // Intent. | ||
347 | - // - If there is a FETCHED Intent for a prefix, but no IN-MEMORY | ||
348 | - // Intent for same prefix, then delete/withdraw the FETCHED | ||
349 | - // Intent. | ||
350 | - // | ||
351 | - Collection<Pair<Ip4Prefix, MultiPointToSinglePointIntent>> | ||
352 | - storeInMemoryIntents = new LinkedList<>(); | ||
353 | - Collection<Pair<Ip4Prefix, MultiPointToSinglePointIntent>> | ||
354 | - addIntents = new LinkedList<>(); | ||
355 | - Collection<Pair<Ip4Prefix, MultiPointToSinglePointIntent>> | ||
356 | - deleteIntents = new LinkedList<>(); | ||
357 | - for (Map.Entry<Ip4Prefix, MultiPointToSinglePointIntent> entry : | ||
358 | - pushedRouteIntents.entrySet()) { | ||
359 | - Ip4Prefix prefix = entry.getKey(); | ||
360 | - MultiPointToSinglePointIntent inMemoryIntent = | ||
361 | - entry.getValue(); | ||
362 | - MultiPointToSinglePointIntent fetchedIntent = | ||
363 | - fetchedIntents.get(prefix); | ||
364 | - | ||
365 | - if (fetchedIntent == null) { | ||
366 | - // | ||
367 | - // No FETCHED Intent for same prefix: push the IN-MEMORY | ||
368 | - // Intent. | ||
369 | - // | ||
370 | - addIntents.add(Pair.of(prefix, inMemoryIntent)); | ||
371 | - continue; | ||
372 | - } | ||
373 | - | ||
374 | - IntentState state = intentService.getIntentState(fetchedIntent.id()); | ||
375 | - if (state == IntentState.WITHDRAWING || | ||
376 | - state == IntentState.WITHDRAWN) { | ||
377 | - // The intent has been withdrawn but according to our route | ||
378 | - // table it should be installed. We'll reinstall it. | ||
379 | - addIntents.add(Pair.of(prefix, inMemoryIntent)); | ||
380 | - } | ||
381 | - | ||
382 | - // | ||
383 | - // If IN-MEMORY Intent is same as the FETCHED Intent, | ||
384 | - // store the FETCHED Intent in the local memory. | ||
385 | - // | ||
386 | - if (compareMultiPointToSinglePointIntents(inMemoryIntent, | ||
387 | - fetchedIntent)) { | ||
388 | - storeInMemoryIntents.add(Pair.of(prefix, fetchedIntent)); | ||
389 | - } else { | ||
390 | - // | ||
391 | - // The IN-MEMORY Intent is not same as the FETCHED Intent, | ||
392 | - // hence delete the FETCHED Intent, and install the | ||
393 | - // IN-MEMORY Intent. | ||
394 | - // | ||
395 | - deleteIntents.add(Pair.of(prefix, fetchedIntent)); | ||
396 | - addIntents.add(Pair.of(prefix, inMemoryIntent)); | ||
397 | - } | ||
398 | - fetchedIntents.remove(prefix); | ||
399 | - } | ||
400 | - | ||
401 | - // | ||
402 | - // Any remaining FETCHED Intents have to be deleted/withdrawn | ||
403 | - // | ||
404 | - for (Map.Entry<Ip4Prefix, MultiPointToSinglePointIntent> entry : | ||
405 | - fetchedIntents.entrySet()) { | ||
406 | - Ip4Prefix prefix = entry.getKey(); | ||
407 | - MultiPointToSinglePointIntent fetchedIntent = entry.getValue(); | ||
408 | - deleteIntents.add(Pair.of(prefix, fetchedIntent)); | ||
409 | - } | ||
410 | - | ||
411 | - // | ||
412 | - // Perform the actions: | ||
413 | - // 1. Store in memory fetched intents that are same. Can be done | ||
414 | - // even if we are not the leader anymore | ||
415 | - // 2. Delete intents: check if the leader before each operation | ||
416 | - // 3. Add intents: check if the leader before each operation | ||
417 | - // | ||
418 | - for (Pair<Ip4Prefix, MultiPointToSinglePointIntent> pair : | ||
419 | - storeInMemoryIntents) { | ||
420 | - Ip4Prefix prefix = pair.getLeft(); | ||
421 | - MultiPointToSinglePointIntent intent = pair.getRight(); | ||
422 | - log.debug("Intent synchronization: updating in-memory " + | ||
423 | - "Intent for prefix: {}", prefix); | ||
424 | - pushedRouteIntents.put(prefix, intent); | ||
425 | - } | ||
426 | - // | ||
427 | - isActivatedLeader = true; // Allow push of Intents | ||
428 | - for (Pair<Ip4Prefix, MultiPointToSinglePointIntent> pair : | ||
429 | - deleteIntents) { | ||
430 | - Ip4Prefix prefix = pair.getLeft(); | ||
431 | - MultiPointToSinglePointIntent intent = pair.getRight(); | ||
432 | - if (!isElectedLeader) { | ||
433 | - isActivatedLeader = false; | ||
434 | - return; | ||
435 | - } | ||
436 | - log.debug("Intent synchronization: deleting Intent for " + | ||
437 | - "prefix: {}", prefix); | ||
438 | - intentService.withdraw(intent); | ||
439 | - } | ||
440 | - // | ||
441 | - for (Pair<Ip4Prefix, MultiPointToSinglePointIntent> pair : | ||
442 | - addIntents) { | ||
443 | - Ip4Prefix prefix = pair.getLeft(); | ||
444 | - MultiPointToSinglePointIntent intent = pair.getRight(); | ||
445 | - if (!isElectedLeader) { | ||
446 | - isActivatedLeader = false; | ||
447 | - return; | ||
448 | - } | ||
449 | - log.debug("Intent synchronization: adding Intent for " + | ||
450 | - "prefix: {}", prefix); | ||
451 | - intentService.submit(intent); | ||
452 | - } | ||
453 | - if (!isElectedLeader) { | ||
454 | - isActivatedLeader = false; | ||
455 | - } | ||
456 | - log.debug("Syncing SDN-IP routes completed."); | ||
457 | - } | ||
458 | - } | ||
459 | - | ||
460 | - /** | ||
461 | - * Compares two Multi-point to Single Point Intents whether they represent | ||
462 | - * same logical intention. | ||
463 | - * | ||
464 | - * @param intent1 the first Intent to compare | ||
465 | - * @param intent2 the second Intent to compare | ||
466 | - * @return true if both Intents represent same logical intention, otherwise | ||
467 | - * false | ||
468 | - */ | ||
469 | - private boolean compareMultiPointToSinglePointIntents( | ||
470 | - MultiPointToSinglePointIntent intent1, | ||
471 | - MultiPointToSinglePointIntent intent2) { | ||
472 | - | ||
473 | - return Objects.equal(intent1.appId(), intent2.appId()) && | ||
474 | - Objects.equal(intent1.selector(), intent2.selector()) && | ||
475 | - Objects.equal(intent1.treatment(), intent2.treatment()) && | ||
476 | - Objects.equal(intent1.ingressPoints(), intent2.ingressPoints()) && | ||
477 | - Objects.equal(intent1.egressPoint(), intent2.egressPoint()); | ||
478 | - } | ||
479 | - | ||
480 | - /** | ||
481 | * Processes adding a route entry. | 199 | * Processes adding a route entry. |
482 | * <p> | 200 | * <p> |
483 | * Put new route entry into the radix tree. If there was an existing | 201 | * Put new route entry into the radix tree. If there was an existing |
... | @@ -488,7 +206,7 @@ public class Router implements RouteListener { | ... | @@ -488,7 +206,7 @@ public class Router implements RouteListener { |
488 | * | 206 | * |
489 | * @param routeEntry the route entry to add | 207 | * @param routeEntry the route entry to add |
490 | */ | 208 | */ |
491 | - protected void processRouteAdd(RouteEntry routeEntry) { | 209 | + void processRouteAdd(RouteEntry routeEntry) { |
492 | synchronized (this) { | 210 | synchronized (this) { |
493 | log.debug("Processing route add: {}", routeEntry); | 211 | log.debug("Processing route add: {}", routeEntry); |
494 | 212 | ||
... | @@ -610,17 +328,8 @@ public class Router implements RouteListener { | ... | @@ -610,17 +328,8 @@ public class Router implements RouteListener { |
610 | log.debug("Adding intent for prefix {}, next hop mac {}", | 328 | log.debug("Adding intent for prefix {}, next hop mac {}", |
611 | prefix, nextHopMacAddress); | 329 | prefix, nextHopMacAddress); |
612 | 330 | ||
613 | - MultiPointToSinglePointIntent pushedIntent = | ||
614 | - pushedRouteIntents.get(prefix); | ||
615 | - | ||
616 | - // Just for testing. | ||
617 | - if (pushedIntent != null) { | ||
618 | - log.error("There should not be a pushed intent: {}", pushedIntent); | ||
619 | - } | ||
620 | - | ||
621 | - ConnectPoint egressPort = egressInterface.connectPoint(); | ||
622 | - | ||
623 | Set<ConnectPoint> ingressPorts = new HashSet<>(); | 331 | Set<ConnectPoint> ingressPorts = new HashSet<>(); |
332 | + ConnectPoint egressPort = egressInterface.connectPoint(); | ||
624 | 333 | ||
625 | for (Interface intf : interfaceService.getInterfaces()) { | 334 | for (Interface intf : interfaceService.getInterfaces()) { |
626 | if (!intf.connectPoint().equals(egressInterface.connectPoint())) { | 335 | if (!intf.connectPoint().equals(egressInterface.connectPoint())) { |
... | @@ -644,14 +353,7 @@ public class Router implements RouteListener { | ... | @@ -644,14 +353,7 @@ public class Router implements RouteListener { |
644 | new MultiPointToSinglePointIntent(appId, selector, treatment, | 353 | new MultiPointToSinglePointIntent(appId, selector, treatment, |
645 | ingressPorts, egressPort); | 354 | ingressPorts, egressPort); |
646 | 355 | ||
647 | - if (isElectedLeader && isActivatedLeader) { | 356 | + intentSynchronizer.submitRouteIntent(prefix, intent); |
648 | - log.debug("Intent installation: adding Intent for prefix: {}", | ||
649 | - prefix); | ||
650 | - intentService.submit(intent); | ||
651 | - } | ||
652 | - | ||
653 | - // Maintain the Intent | ||
654 | - pushedRouteIntents.put(prefix, intent); | ||
655 | } | 357 | } |
656 | 358 | ||
657 | /** | 359 | /** |
... | @@ -663,7 +365,7 @@ public class Router implements RouteListener { | ... | @@ -663,7 +365,7 @@ public class Router implements RouteListener { |
663 | * | 365 | * |
664 | * @param routeEntry the route entry to delete | 366 | * @param routeEntry the route entry to delete |
665 | */ | 367 | */ |
666 | - protected void processRouteDelete(RouteEntry routeEntry) { | 368 | + void processRouteDelete(RouteEntry routeEntry) { |
667 | synchronized (this) { | 369 | synchronized (this) { |
668 | log.debug("Processing route delete: {}", routeEntry); | 370 | log.debug("Processing route delete: {}", routeEntry); |
669 | Ip4Prefix prefix = routeEntry.prefix(); | 371 | Ip4Prefix prefix = routeEntry.prefix(); |
... | @@ -691,21 +393,7 @@ public class Router implements RouteListener { | ... | @@ -691,21 +393,7 @@ public class Router implements RouteListener { |
691 | private void executeRouteDelete(RouteEntry routeEntry) { | 393 | private void executeRouteDelete(RouteEntry routeEntry) { |
692 | log.debug("Executing route delete: {}", routeEntry); | 394 | log.debug("Executing route delete: {}", routeEntry); |
693 | 395 | ||
694 | - Ip4Prefix prefix = routeEntry.prefix(); | 396 | + intentSynchronizer.withdrawRouteIntent(routeEntry.prefix()); |
695 | - | ||
696 | - MultiPointToSinglePointIntent intent = | ||
697 | - pushedRouteIntents.remove(prefix); | ||
698 | - | ||
699 | - if (intent == null) { | ||
700 | - log.debug("There is no intent in pushedRouteIntents to delete " + | ||
701 | - "for prefix: {}", prefix); | ||
702 | - } else { | ||
703 | - if (isElectedLeader && isActivatedLeader) { | ||
704 | - log.debug("Intent installation: deleting Intent for prefix: {}", | ||
705 | - prefix); | ||
706 | - intentService.withdraw(intent); | ||
707 | - } | ||
708 | - } | ||
709 | } | 397 | } |
710 | 398 | ||
711 | /** | 399 | /** |
... | @@ -774,21 +462,6 @@ public class Router implements RouteListener { | ... | @@ -774,21 +462,6 @@ public class Router implements RouteListener { |
774 | } | 462 | } |
775 | 463 | ||
776 | /** | 464 | /** |
777 | - * Gets the pushed route intents. | ||
778 | - * | ||
779 | - * @return the pushed route intents | ||
780 | - */ | ||
781 | - public Collection<MultiPointToSinglePointIntent> getPushedRouteIntents() { | ||
782 | - List<MultiPointToSinglePointIntent> pushedIntents = new LinkedList<>(); | ||
783 | - | ||
784 | - for (Map.Entry<Ip4Prefix, MultiPointToSinglePointIntent> entry : | ||
785 | - pushedRouteIntents.entrySet()) { | ||
786 | - pushedIntents.add(entry.getValue()); | ||
787 | - } | ||
788 | - return pushedIntents; | ||
789 | - } | ||
790 | - | ||
791 | - /** | ||
792 | * Listener for host events. | 465 | * Listener for host events. |
793 | */ | 466 | */ |
794 | class InternalHostListener implements HostListener { | 467 | class InternalHostListener implements HostListener { | ... | ... |
... | @@ -55,6 +55,7 @@ public class SdnIp implements SdnIpService { | ... | @@ -55,6 +55,7 @@ public class SdnIp implements SdnIpService { |
55 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 55 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
56 | protected HostService hostService; | 56 | protected HostService hostService; |
57 | 57 | ||
58 | + private IntentSynchronizer intentSynchronizer; | ||
58 | private SdnIpConfigReader config; | 59 | private SdnIpConfigReader config; |
59 | private PeerConnectivityManager peerConnectivity; | 60 | private PeerConnectivityManager peerConnectivity; |
60 | private Router router; | 61 | private Router router; |
... | @@ -64,35 +65,41 @@ public class SdnIp implements SdnIpService { | ... | @@ -64,35 +65,41 @@ public class SdnIp implements SdnIpService { |
64 | protected void activate() { | 65 | protected void activate() { |
65 | log.debug("SDN-IP started"); | 66 | log.debug("SDN-IP started"); |
66 | 67 | ||
68 | + ApplicationId appId = coreService.registerApplication(SDN_IP_APP); | ||
67 | config = new SdnIpConfigReader(); | 69 | config = new SdnIpConfigReader(); |
68 | config.init(); | 70 | config.init(); |
69 | 71 | ||
70 | - InterfaceService interfaceService = new HostToInterfaceAdaptor(hostService); | 72 | + InterfaceService interfaceService = |
73 | + new HostToInterfaceAdaptor(hostService); | ||
71 | 74 | ||
72 | - ApplicationId appId = coreService.registerApplication(SDN_IP_APP); | 75 | + intentSynchronizer = new IntentSynchronizer(appId, intentService); |
76 | + intentSynchronizer.start(); | ||
73 | 77 | ||
74 | peerConnectivity = new PeerConnectivityManager(appId, config, | 78 | peerConnectivity = new PeerConnectivityManager(appId, config, |
75 | interfaceService, intentService); | 79 | interfaceService, intentService); |
76 | peerConnectivity.start(); | 80 | peerConnectivity.start(); |
77 | 81 | ||
78 | - router = new Router(appId, intentService, hostService, config, interfaceService); | 82 | + router = new Router(appId, intentSynchronizer, hostService, config, |
83 | + interfaceService); | ||
79 | router.start(); | 84 | router.start(); |
80 | 85 | ||
81 | - // Manually set the router as the leader to allow testing | 86 | + // Manually set the instance as the leader to allow testing |
82 | // TODO change this when we get a leader election | 87 | // TODO change this when we get a leader election |
83 | - router.leaderChanged(true); | 88 | + intentSynchronizer.leaderChanged(true); |
84 | 89 | ||
85 | bgpSessionManager = new BgpSessionManager(router); | 90 | bgpSessionManager = new BgpSessionManager(router); |
86 | - bgpSessionManager.startUp(2000); // TODO | 91 | + // TODO: the local BGP listen port number should be configurable |
92 | + bgpSessionManager.start(2000); | ||
87 | 93 | ||
88 | // TODO need to disable link discovery on external ports | 94 | // TODO need to disable link discovery on external ports |
89 | - | ||
90 | } | 95 | } |
91 | 96 | ||
92 | @Deactivate | 97 | @Deactivate |
93 | protected void deactivate() { | 98 | protected void deactivate() { |
94 | - bgpSessionManager.shutDown(); | 99 | + bgpSessionManager.stop(); |
95 | - router.shutdown(); | 100 | + router.stop(); |
101 | + peerConnectivity.stop(); | ||
102 | + intentSynchronizer.stop(); | ||
96 | 103 | ||
97 | log.info("Stopped"); | 104 | log.info("Stopped"); |
98 | } | 105 | } |
... | @@ -114,7 +121,7 @@ public class SdnIp implements SdnIpService { | ... | @@ -114,7 +121,7 @@ public class SdnIp implements SdnIpService { |
114 | 121 | ||
115 | @Override | 122 | @Override |
116 | public void modifyPrimary(boolean isPrimary) { | 123 | public void modifyPrimary(boolean isPrimary) { |
117 | - router.leaderChanged(isPrimary); | 124 | + intentSynchronizer.leaderChanged(isPrimary); |
118 | } | 125 | } |
119 | 126 | ||
120 | static String dpidToUri(String dpid) { | 127 | static String dpidToUri(String dpid) { | ... | ... |
... | @@ -181,8 +181,8 @@ public class BgpSessionManager { | ... | @@ -181,8 +181,8 @@ public class BgpSessionManager { |
181 | * @param listenPortNumber the port number to listen on. By default | 181 | * @param listenPortNumber the port number to listen on. By default |
182 | * it should be BgpConstants.BGP_PORT (179) | 182 | * it should be BgpConstants.BGP_PORT (179) |
183 | */ | 183 | */ |
184 | - public void startUp(int listenPortNumber) { | 184 | + public void start(int listenPortNumber) { |
185 | - log.debug("BGP Session Manager startUp()"); | 185 | + log.debug("BGP Session Manager start."); |
186 | isShutdown = false; | 186 | isShutdown = false; |
187 | 187 | ||
188 | ChannelFactory channelFactory = | 188 | ChannelFactory channelFactory = |
... | @@ -222,9 +222,9 @@ public class BgpSessionManager { | ... | @@ -222,9 +222,9 @@ public class BgpSessionManager { |
222 | } | 222 | } |
223 | 223 | ||
224 | /** | 224 | /** |
225 | - * Shuts down the BGP Session Manager operation. | 225 | + * Stops the BGP Session Manager operation. |
226 | */ | 226 | */ |
227 | - public void shutDown() { | 227 | + public void stop() { |
228 | isShutdown = true; | 228 | isShutdown = true; |
229 | allChannels.close().awaitUninterruptibly(); | 229 | allChannels.close().awaitUninterruptibly(); |
230 | serverBootstrap.releaseExternalResources(); | 230 | serverBootstrap.releaseExternalResources(); | ... | ... |
... | @@ -54,7 +54,8 @@ import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree; | ... | @@ -54,7 +54,8 @@ import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree; |
54 | import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree; | 54 | import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree; |
55 | 55 | ||
56 | /** | 56 | /** |
57 | - * This class tests the intent synchronization function in Router class. | 57 | + * This class tests the intent synchronization function in the |
58 | + * IntentSynchronizer class. | ||
58 | */ | 59 | */ |
59 | public class IntentSyncTest { | 60 | public class IntentSyncTest { |
60 | 61 | ||
... | @@ -74,6 +75,7 @@ public class IntentSyncTest { | ... | @@ -74,6 +75,7 @@ public class IntentSyncTest { |
74 | DeviceId.deviceId("of:0000000000000003"), | 75 | DeviceId.deviceId("of:0000000000000003"), |
75 | PortNumber.portNumber(1)); | 76 | PortNumber.portNumber(1)); |
76 | 77 | ||
78 | + private IntentSynchronizer intentSynchronizer; | ||
77 | private Router router; | 79 | private Router router; |
78 | 80 | ||
79 | private static final ApplicationId APPID = new ApplicationId() { | 81 | private static final ApplicationId APPID = new ApplicationId() { |
... | @@ -94,7 +96,8 @@ public class IntentSyncTest { | ... | @@ -94,7 +96,8 @@ public class IntentSyncTest { |
94 | setUpHostService(); | 96 | setUpHostService(); |
95 | intentService = createMock(IntentService.class); | 97 | intentService = createMock(IntentService.class); |
96 | 98 | ||
97 | - router = new Router(APPID, intentService, | 99 | + intentSynchronizer = new IntentSynchronizer(APPID, intentService); |
100 | + router = new Router(APPID, intentSynchronizer, | ||
98 | hostService, null, interfaceService); | 101 | hostService, null, interfaceService); |
99 | } | 102 | } |
100 | 103 | ||
... | @@ -260,7 +263,7 @@ public class IntentSyncTest { | ... | @@ -260,7 +263,7 @@ public class IntentSyncTest { |
260 | // Compose a intent, which is equal to intent5 but the id is different. | 263 | // Compose a intent, which is equal to intent5 but the id is different. |
261 | MultiPointToSinglePointIntent intent5New = | 264 | MultiPointToSinglePointIntent intent5New = |
262 | staticIntentBuilder(intent5, routeEntry5, "00:00:00:00:00:01"); | 265 | staticIntentBuilder(intent5, routeEntry5, "00:00:00:00:00:01"); |
263 | - assertTrue(TestUtils.callMethod(router, | 266 | + assertTrue(TestUtils.callMethod(intentSynchronizer, |
264 | "compareMultiPointToSinglePointIntents", | 267 | "compareMultiPointToSinglePointIntents", |
265 | new Class<?>[] {MultiPointToSinglePointIntent.class, | 268 | new Class<?>[] {MultiPointToSinglePointIntent.class, |
266 | MultiPointToSinglePointIntent.class}, | 269 | MultiPointToSinglePointIntent.class}, |
... | @@ -296,7 +299,8 @@ public class IntentSyncTest { | ... | @@ -296,7 +299,8 @@ public class IntentSyncTest { |
296 | pushedRouteIntents.put(routeEntry5.prefix(), intent5New); | 299 | pushedRouteIntents.put(routeEntry5.prefix(), intent5New); |
297 | pushedRouteIntents.put(routeEntry6.prefix(), intent6); | 300 | pushedRouteIntents.put(routeEntry6.prefix(), intent6); |
298 | pushedRouteIntents.put(routeEntry7.prefix(), intent7); | 301 | pushedRouteIntents.put(routeEntry7.prefix(), intent7); |
299 | - TestUtils.setField(router, "pushedRouteIntents", pushedRouteIntents); | 302 | + TestUtils.setField(intentSynchronizer, "pushedRouteIntents", |
303 | + pushedRouteIntents); | ||
300 | 304 | ||
301 | // Set up expectation | 305 | // Set up expectation |
302 | reset(intentService); | 306 | reset(intentService); |
... | @@ -327,8 +331,9 @@ public class IntentSyncTest { | ... | @@ -327,8 +331,9 @@ public class IntentSyncTest { |
327 | replay(intentService); | 331 | replay(intentService); |
328 | 332 | ||
329 | // Start the test | 333 | // Start the test |
330 | - router.leaderChanged(true); | 334 | + intentSynchronizer.leaderChanged(true); |
331 | - TestUtils.callMethod(router, "syncIntents", new Class<?>[] {}); | 335 | + TestUtils.callMethod(intentSynchronizer, "syncIntents", |
336 | + new Class<?>[] {}); | ||
332 | 337 | ||
333 | // Verify | 338 | // Verify |
334 | assertEquals(router.getRoutes().size(), 6); | 339 | assertEquals(router.getRoutes().size(), 6); |
... | @@ -338,12 +343,12 @@ public class IntentSyncTest { | ... | @@ -338,12 +343,12 @@ public class IntentSyncTest { |
338 | assertTrue(router.getRoutes().contains(routeEntry5)); | 343 | assertTrue(router.getRoutes().contains(routeEntry5)); |
339 | assertTrue(router.getRoutes().contains(routeEntry6)); | 344 | assertTrue(router.getRoutes().contains(routeEntry6)); |
340 | 345 | ||
341 | - assertEquals(router.getPushedRouteIntents().size(), 6); | 346 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 6); |
342 | - assertTrue(router.getPushedRouteIntents().contains(intent1)); | 347 | + assertTrue(intentSynchronizer.getPushedRouteIntents().contains(intent1)); |
343 | - assertTrue(router.getPushedRouteIntents().contains(intent3)); | 348 | + assertTrue(intentSynchronizer.getPushedRouteIntents().contains(intent3)); |
344 | - assertTrue(router.getPushedRouteIntents().contains(intent4Update)); | 349 | + assertTrue(intentSynchronizer.getPushedRouteIntents().contains(intent4Update)); |
345 | - assertTrue(router.getPushedRouteIntents().contains(intent5)); | 350 | + assertTrue(intentSynchronizer.getPushedRouteIntents().contains(intent5)); |
346 | - assertTrue(router.getPushedRouteIntents().contains(intent6)); | 351 | + assertTrue(intentSynchronizer.getPushedRouteIntents().contains(intent6)); |
347 | 352 | ||
348 | verify(intentService); | 353 | verify(intentService); |
349 | } | 354 | } | ... | ... |
... | @@ -102,6 +102,7 @@ public class RouterTest { | ... | @@ -102,6 +102,7 @@ public class RouterTest { |
102 | } | 102 | } |
103 | }; | 103 | }; |
104 | 104 | ||
105 | + private IntentSynchronizer intentSynchronizer; | ||
105 | private Router router; | 106 | private Router router; |
106 | 107 | ||
107 | @Before | 108 | @Before |
... | @@ -113,7 +114,8 @@ public class RouterTest { | ... | @@ -113,7 +114,8 @@ public class RouterTest { |
113 | 114 | ||
114 | intentService = createMock(IntentService.class); | 115 | intentService = createMock(IntentService.class); |
115 | 116 | ||
116 | - router = new Router(APPID, intentService, | 117 | + intentSynchronizer = new IntentSynchronizer(APPID, intentService); |
118 | + router = new Router(APPID, intentSynchronizer, | ||
117 | hostService, sdnIpConfigService, interfaceService); | 119 | hostService, sdnIpConfigService, interfaceService); |
118 | } | 120 | } |
119 | 121 | ||
... | @@ -258,15 +260,15 @@ public class RouterTest { | ... | @@ -258,15 +260,15 @@ public class RouterTest { |
258 | replay(intentService); | 260 | replay(intentService); |
259 | 261 | ||
260 | // Call the processRouteAdd() method in Router class | 262 | // Call the processRouteAdd() method in Router class |
261 | - router.leaderChanged(true); | 263 | + intentSynchronizer.leaderChanged(true); |
262 | - TestUtils.setField(router, "isActivatedLeader", true); | 264 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
263 | router.processRouteAdd(routeEntry); | 265 | router.processRouteAdd(routeEntry); |
264 | 266 | ||
265 | // Verify | 267 | // Verify |
266 | assertEquals(router.getRoutes().size(), 1); | 268 | assertEquals(router.getRoutes().size(), 1); |
267 | assertTrue(router.getRoutes().contains(routeEntry)); | 269 | assertTrue(router.getRoutes().contains(routeEntry)); |
268 | - assertEquals(router.getPushedRouteIntents().size(), 1); | 270 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 1); |
269 | - assertEquals(router.getPushedRouteIntents().iterator().next(), | 271 | + assertEquals(intentSynchronizer.getPushedRouteIntents().iterator().next(), |
270 | intent); | 272 | intent); |
271 | verify(intentService); | 273 | verify(intentService); |
272 | } | 274 | } |
... | @@ -338,15 +340,15 @@ public class RouterTest { | ... | @@ -338,15 +340,15 @@ public class RouterTest { |
338 | replay(intentService); | 340 | replay(intentService); |
339 | 341 | ||
340 | // Call the processRouteAdd() method in Router class | 342 | // Call the processRouteAdd() method in Router class |
341 | - router.leaderChanged(true); | 343 | + intentSynchronizer.leaderChanged(true); |
342 | - TestUtils.setField(router, "isActivatedLeader", true); | 344 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
343 | router.processRouteAdd(routeEntryUpdate); | 345 | router.processRouteAdd(routeEntryUpdate); |
344 | 346 | ||
345 | // Verify | 347 | // Verify |
346 | assertEquals(router.getRoutes().size(), 1); | 348 | assertEquals(router.getRoutes().size(), 1); |
347 | assertTrue(router.getRoutes().contains(routeEntryUpdate)); | 349 | assertTrue(router.getRoutes().contains(routeEntryUpdate)); |
348 | - assertEquals(router.getPushedRouteIntents().size(), 1); | 350 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 1); |
349 | - assertEquals(router.getPushedRouteIntents().iterator().next(), | 351 | + assertEquals(intentSynchronizer.getPushedRouteIntents().iterator().next(), |
350 | intentNew); | 352 | intentNew); |
351 | verify(intentService); | 353 | verify(intentService); |
352 | } | 354 | } |
... | @@ -389,13 +391,13 @@ public class RouterTest { | ... | @@ -389,13 +391,13 @@ public class RouterTest { |
389 | replay(intentService); | 391 | replay(intentService); |
390 | 392 | ||
391 | // Call route deleting method in Router class | 393 | // Call route deleting method in Router class |
392 | - router.leaderChanged(true); | 394 | + intentSynchronizer.leaderChanged(true); |
393 | - TestUtils.setField(router, "isActivatedLeader", true); | 395 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
394 | router.processRouteDelete(routeEntry); | 396 | router.processRouteDelete(routeEntry); |
395 | 397 | ||
396 | // Verify | 398 | // Verify |
397 | assertEquals(router.getRoutes().size(), 0); | 399 | assertEquals(router.getRoutes().size(), 0); |
398 | - assertEquals(router.getPushedRouteIntents().size(), 0); | 400 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 0); |
399 | verify(intentService); | 401 | verify(intentService); |
400 | } | 402 | } |
401 | 403 | ||
... | @@ -416,14 +418,14 @@ public class RouterTest { | ... | @@ -416,14 +418,14 @@ public class RouterTest { |
416 | replay(intentService); | 418 | replay(intentService); |
417 | 419 | ||
418 | // Call the processRouteAdd() method in Router class | 420 | // Call the processRouteAdd() method in Router class |
419 | - router.leaderChanged(true); | 421 | + intentSynchronizer.leaderChanged(true); |
420 | - TestUtils.setField(router, "isActivatedLeader", true); | 422 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
421 | router.processRouteAdd(routeEntry); | 423 | router.processRouteAdd(routeEntry); |
422 | 424 | ||
423 | // Verify | 425 | // Verify |
424 | assertEquals(router.getRoutes().size(), 1); | 426 | assertEquals(router.getRoutes().size(), 1); |
425 | assertTrue(router.getRoutes().contains(routeEntry)); | 427 | assertTrue(router.getRoutes().contains(routeEntry)); |
426 | - assertEquals(router.getPushedRouteIntents().size(), 0); | 428 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 0); |
427 | verify(intentService); | 429 | verify(intentService); |
428 | } | 430 | } |
429 | } | 431 | } | ... | ... |
... | @@ -92,6 +92,7 @@ public class RouterTestWithAsyncArp { | ... | @@ -92,6 +92,7 @@ public class RouterTestWithAsyncArp { |
92 | DeviceId.deviceId("of:0000000000000003"), | 92 | DeviceId.deviceId("of:0000000000000003"), |
93 | PortNumber.portNumber(1)); | 93 | PortNumber.portNumber(1)); |
94 | 94 | ||
95 | + private IntentSynchronizer intentSynchronizer; | ||
95 | private Router router; | 96 | private Router router; |
96 | private InternalHostListener internalHostListener; | 97 | private InternalHostListener internalHostListener; |
97 | 98 | ||
... | @@ -114,7 +115,8 @@ public class RouterTestWithAsyncArp { | ... | @@ -114,7 +115,8 @@ public class RouterTestWithAsyncArp { |
114 | hostService = createMock(HostService.class); | 115 | hostService = createMock(HostService.class); |
115 | intentService = createMock(IntentService.class); | 116 | intentService = createMock(IntentService.class); |
116 | 117 | ||
117 | - router = new Router(APPID, intentService, | 118 | + intentSynchronizer = new IntentSynchronizer(APPID, intentService); |
119 | + router = new Router(APPID, intentSynchronizer, | ||
118 | hostService, sdnIpConfigService, interfaceService); | 120 | hostService, sdnIpConfigService, interfaceService); |
119 | internalHostListener = router.new InternalHostListener(); | 121 | internalHostListener = router.new InternalHostListener(); |
120 | } | 122 | } |
... | @@ -211,8 +213,8 @@ public class RouterTestWithAsyncArp { | ... | @@ -211,8 +213,8 @@ public class RouterTestWithAsyncArp { |
211 | replay(intentService); | 213 | replay(intentService); |
212 | 214 | ||
213 | // Call the processRouteAdd() method in Router class | 215 | // Call the processRouteAdd() method in Router class |
214 | - router.leaderChanged(true); | 216 | + intentSynchronizer.leaderChanged(true); |
215 | - TestUtils.setField(router, "isActivatedLeader", true); | 217 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
216 | router.processRouteAdd(routeEntry); | 218 | router.processRouteAdd(routeEntry); |
217 | 219 | ||
218 | Host host = new DefaultHost(ProviderId.NONE, HostId.NONE, | 220 | Host host = new DefaultHost(ProviderId.NONE, HostId.NONE, |
... | @@ -227,8 +229,8 @@ public class RouterTestWithAsyncArp { | ... | @@ -227,8 +229,8 @@ public class RouterTestWithAsyncArp { |
227 | // Verify | 229 | // Verify |
228 | assertEquals(router.getRoutes().size(), 1); | 230 | assertEquals(router.getRoutes().size(), 1); |
229 | assertTrue(router.getRoutes().contains(routeEntry)); | 231 | assertTrue(router.getRoutes().contains(routeEntry)); |
230 | - assertEquals(router.getPushedRouteIntents().size(), 1); | 232 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 1); |
231 | - assertEquals(router.getPushedRouteIntents().iterator().next(), | 233 | + assertEquals(intentSynchronizer.getPushedRouteIntents().iterator().next(), |
232 | intent); | 234 | intent); |
233 | verify(intentService); | 235 | verify(intentService); |
234 | verify(hostService); | 236 | verify(hostService); |
... | @@ -294,8 +296,8 @@ public class RouterTestWithAsyncArp { | ... | @@ -294,8 +296,8 @@ public class RouterTestWithAsyncArp { |
294 | replay(intentService); | 296 | replay(intentService); |
295 | 297 | ||
296 | // Call the processRouteAdd() method in Router class | 298 | // Call the processRouteAdd() method in Router class |
297 | - router.leaderChanged(true); | 299 | + intentSynchronizer.leaderChanged(true); |
298 | - TestUtils.setField(router, "isActivatedLeader", true); | 300 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
299 | router.processRouteAdd(routeEntryUpdate); | 301 | router.processRouteAdd(routeEntryUpdate); |
300 | 302 | ||
301 | Host host = new DefaultHost(ProviderId.NONE, HostId.NONE, | 303 | Host host = new DefaultHost(ProviderId.NONE, HostId.NONE, |
... | @@ -310,8 +312,8 @@ public class RouterTestWithAsyncArp { | ... | @@ -310,8 +312,8 @@ public class RouterTestWithAsyncArp { |
310 | // Verify | 312 | // Verify |
311 | assertEquals(router.getRoutes().size(), 1); | 313 | assertEquals(router.getRoutes().size(), 1); |
312 | assertTrue(router.getRoutes().contains(routeEntryUpdate)); | 314 | assertTrue(router.getRoutes().contains(routeEntryUpdate)); |
313 | - assertEquals(router.getPushedRouteIntents().size(), 1); | 315 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 1); |
314 | - assertEquals(router.getPushedRouteIntents().iterator().next(), | 316 | + assertEquals(intentSynchronizer.getPushedRouteIntents().iterator().next(), |
315 | intentNew); | 317 | intentNew); |
316 | verify(intentService); | 318 | verify(intentService); |
317 | verify(hostService); | 319 | verify(hostService); |
... | @@ -342,13 +344,13 @@ public class RouterTestWithAsyncArp { | ... | @@ -342,13 +344,13 @@ public class RouterTestWithAsyncArp { |
342 | replay(intentService); | 344 | replay(intentService); |
343 | 345 | ||
344 | // Call route deleting method in Router class | 346 | // Call route deleting method in Router class |
345 | - router.leaderChanged(true); | 347 | + intentSynchronizer.leaderChanged(true); |
346 | - TestUtils.setField(router, "isActivatedLeader", true); | 348 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
347 | router.processRouteDelete(routeEntry); | 349 | router.processRouteDelete(routeEntry); |
348 | 350 | ||
349 | // Verify | 351 | // Verify |
350 | assertEquals(router.getRoutes().size(), 0); | 352 | assertEquals(router.getRoutes().size(), 0); |
351 | - assertEquals(router.getPushedRouteIntents().size(), 0); | 353 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 0); |
352 | verify(intentService); | 354 | verify(intentService); |
353 | } | 355 | } |
354 | 356 | ... | ... |
... | @@ -66,6 +66,7 @@ public class SdnIpTest { | ... | @@ -66,6 +66,7 @@ public class SdnIpTest { |
66 | private static final int MIN_PREFIX_LENGTH = 1; | 66 | private static final int MIN_PREFIX_LENGTH = 1; |
67 | private static final int MAX_PREFIX_LENGTH = 32; | 67 | private static final int MAX_PREFIX_LENGTH = 32; |
68 | 68 | ||
69 | + private IntentSynchronizer intentSynchronizer; | ||
69 | static Router router; | 70 | static Router router; |
70 | 71 | ||
71 | private SdnIpConfigService sdnIpConfigService; | 72 | private SdnIpConfigService sdnIpConfigService; |
... | @@ -111,7 +112,8 @@ public class SdnIpTest { | ... | @@ -111,7 +112,8 @@ public class SdnIpTest { |
111 | intentService = createMock(IntentService.class); | 112 | intentService = createMock(IntentService.class); |
112 | random = new Random(); | 113 | random = new Random(); |
113 | 114 | ||
114 | - router = new Router(APPID, intentService, hostService, | 115 | + intentSynchronizer = new IntentSynchronizer(APPID, intentService); |
116 | + router = new Router(APPID, intentSynchronizer, hostService, | ||
115 | sdnIpConfigService, interfaceService); | 117 | sdnIpConfigService, interfaceService); |
116 | } | 118 | } |
117 | 119 | ||
... | @@ -228,8 +230,8 @@ public class SdnIpTest { | ... | @@ -228,8 +230,8 @@ public class SdnIpTest { |
228 | 230 | ||
229 | replay(intentService); | 231 | replay(intentService); |
230 | 232 | ||
231 | - router.leaderChanged(true); | 233 | + intentSynchronizer.leaderChanged(true); |
232 | - TestUtils.setField(router, "isActivatedLeader", true); | 234 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
233 | 235 | ||
234 | // Add route updates | 236 | // Add route updates |
235 | for (RouteUpdate update : routeUpdates) { | 237 | for (RouteUpdate update : routeUpdates) { |
... | @@ -239,7 +241,8 @@ public class SdnIpTest { | ... | @@ -239,7 +241,8 @@ public class SdnIpTest { |
239 | latch.await(5000, TimeUnit.MILLISECONDS); | 241 | latch.await(5000, TimeUnit.MILLISECONDS); |
240 | 242 | ||
241 | assertEquals(router.getRoutes().size(), numRoutes); | 243 | assertEquals(router.getRoutes().size(), numRoutes); |
242 | - assertEquals(router.getPushedRouteIntents().size(), numRoutes); | 244 | + assertEquals(intentSynchronizer.getPushedRouteIntents().size(), |
245 | + numRoutes); | ||
243 | 246 | ||
244 | verify(intentService); | 247 | verify(intentService); |
245 | } | 248 | } |
... | @@ -295,8 +298,8 @@ public class SdnIpTest { | ... | @@ -295,8 +298,8 @@ public class SdnIpTest { |
295 | 298 | ||
296 | replay(intentService); | 299 | replay(intentService); |
297 | 300 | ||
298 | - router.leaderChanged(true); | 301 | + intentSynchronizer.leaderChanged(true); |
299 | - TestUtils.setField(router, "isActivatedLeader", true); | 302 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); |
300 | 303 | ||
301 | // Send the add updates first | 304 | // Send the add updates first |
302 | for (RouteUpdate update : routeUpdates) { | 305 | for (RouteUpdate update : routeUpdates) { |
... | @@ -314,7 +317,7 @@ public class SdnIpTest { | ... | @@ -314,7 +317,7 @@ public class SdnIpTest { |
314 | deleteCount.await(5000, TimeUnit.MILLISECONDS); | 317 | deleteCount.await(5000, TimeUnit.MILLISECONDS); |
315 | 318 | ||
316 | assertEquals(0, router.getRoutes().size()); | 319 | assertEquals(0, router.getRoutes().size()); |
317 | - assertEquals(0, router.getPushedRouteIntents().size()); | 320 | + assertEquals(0, intentSynchronizer.getPushedRouteIntents().size()); |
318 | verify(intentService); | 321 | verify(intentService); |
319 | } | 322 | } |
320 | 323 | ... | ... |
... | @@ -95,7 +95,7 @@ public class BgpSessionManagerTest { | ... | @@ -95,7 +95,7 @@ public class BgpSessionManagerTest { |
95 | // | 95 | // |
96 | bgpSessionManager = new BgpSessionManager(dummyRouteListener); | 96 | bgpSessionManager = new BgpSessionManager(dummyRouteListener); |
97 | // NOTE: We use port 0 to bind on any available port | 97 | // NOTE: We use port 0 to bind on any available port |
98 | - bgpSessionManager.startUp(0); | 98 | + bgpSessionManager.start(0); |
99 | 99 | ||
100 | // Get the port number the BGP Session Manager is listening on | 100 | // Get the port number the BGP Session Manager is listening on |
101 | Channel serverChannel = TestUtils.getField(bgpSessionManager, | 101 | Channel serverChannel = TestUtils.getField(bgpSessionManager, |
... | @@ -136,7 +136,7 @@ public class BgpSessionManagerTest { | ... | @@ -136,7 +136,7 @@ public class BgpSessionManagerTest { |
136 | 136 | ||
137 | @After | 137 | @After |
138 | public void tearDown() throws Exception { | 138 | public void tearDown() throws Exception { |
139 | - bgpSessionManager.shutDown(); | 139 | + bgpSessionManager.stop(); |
140 | bgpSessionManager = null; | 140 | bgpSessionManager = null; |
141 | } | 141 | } |
142 | 142 | ... | ... |
-
Please register or login to post a comment