blob: ea10996114a32b18871fe8e816950db9db3c8d68 [file] [log] [blame]
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +05303 *
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 */
16package org.onosproject.ospf.controller.lsdb;
17
18import com.google.common.base.Objects;
19import org.jboss.netty.channel.Channel;
20import org.onosproject.ospf.controller.LsaBin;
21import org.onosproject.ospf.controller.LsaWrapper;
22import org.onosproject.ospf.controller.LsdbAge;
23import org.onosproject.ospf.controller.OspfArea;
24import org.onosproject.ospf.controller.area.OspfAreaImpl;
25import org.onosproject.ospf.protocol.util.OspfParameters;
26import org.slf4j.Logger;
27import org.slf4j.LoggerFactory;
28
29import java.util.Map;
30import java.util.concurrent.ArrayBlockingQueue;
31import java.util.concurrent.BlockingQueue;
32import java.util.concurrent.ConcurrentHashMap;
33import java.util.concurrent.Executors;
34import java.util.concurrent.ScheduledExecutorService;
35import java.util.concurrent.TimeUnit;
36
37/**
38 * Representation of LSDB Aging process.
39 */
40public class LsdbAgeImpl implements LsdbAge {
41
42 private static final Logger log =
43 LoggerFactory.getLogger(LsdbAgeImpl.class);
sunishvkf7c56552016-07-18 16:02:39 +053044 protected static int ageCounter = 0;
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +053045 private InternalAgeTimer dbAgeTimer;
46 private ScheduledExecutorService exServiceage;
47 // creating age bins of MAXAGE
48 private Map<Integer, LsaBin> ageBins = new ConcurrentHashMap<>(OspfParameters.MAXAGE);
49 private LsaBin maxAgeBin = new LsaBinImpl(OspfParameters.MAXAGE);
50 private int ageCounterRollOver = 0;
51 private Channel channel = null;
52 private LsaQueueConsumer queueConsumer = null;
53 private BlockingQueue<LsaWrapper> lsaQueue = new ArrayBlockingQueue(1024);
54 private OspfArea ospfArea = null;
55
56
57 /**
58 * Creates an instance of LSDB age.
59 *
60 * @param ospfArea OSPF area instance
61 */
62 public LsdbAgeImpl(OspfArea ospfArea) {
63 // create LSBin's in the HashMap.
64 for (int i = 0; i < OspfParameters.MAXAGE; i++) {
65 LsaBin lsaBin = new LsaBinImpl(i);
66 ageBins.put(i, lsaBin);
67 }
68 this.ospfArea = ospfArea;
69 }
70
71 @Override
72 public boolean equals(Object o) {
73 if (this == o) {
74 return true;
75 }
76 if (o == null || getClass() != o.getClass()) {
77 return false;
78 }
79 LsdbAgeImpl that = (LsdbAgeImpl) o;
80 return Objects.equal(ageBins, that.ageBins) &&
81 Objects.equal(ageCounter, that.ageCounter) &&
82 Objects.equal(ageCounterRollOver, that.ageCounterRollOver) &&
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -080083 Objects.equal(lsaQueue, that.lsaQueue);
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +053084 }
85
86 @Override
87 public int hashCode() {
88 return Objects.hashCode(ageBins, ageCounter, ageCounterRollOver, lsaQueue);
89 }
90
91 /**
92 * Adds LSA to bin.
93 *
94 * @param binKey key to store in bin
95 * @param lsaBin LSA bin instance
96 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -080097 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +053098 public void addLsaBin(Integer binKey, LsaBin lsaBin) {
99 if (!ageBins.containsKey(binKey)) {
100 ageBins.put(binKey, lsaBin);
101 }
102 }
103
104 /**
105 * Gets LSA from Bin.
106 *
107 * @param binKey key
108 * @return bin instance
109 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800110 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530111 public LsaBin getLsaBin(Integer binKey) {
112
113 return ageBins.get(binKey);
114 }
115
116 /**
117 * Adds the LSA to maxAge bin.
118 *
119 * @param key key
120 * @param wrapper wrapper instance
121 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800122 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530123 public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) {
124 maxAgeBin.addOspfLsa(key, wrapper);
125 }
126
127 /**
128 * Removes LSA from Bin.
129 *
130 * @param lsaWrapper wrapper instance
131 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800132 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530133 public void removeLsaFromBin(LsaWrapper lsaWrapper) {
134 if (ageBins.containsKey(lsaWrapper.binNumber())) {
135 LsaBin lsaBin = ageBins.get(lsaWrapper.binNumber());
136 lsaBin.removeOspfLsa(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
137 lsaWrapper).lsaHeader()), lsaWrapper);
138 }
139 }
140
141 /**
142 * Starts the aging timer and queue consumer.
143 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800144 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530145 public void startDbAging() {
146 startDbAgeTimer();
147 queueConsumer = new LsaQueueConsumer(lsaQueue, channel, ospfArea);
148 new Thread(queueConsumer).start();
149 }
150
151
152 /**
153 * Gets called every 1 second as part of the timer.
154 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800155 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530156 public void ageLsaAndFlood() {
157 //every 5 mins checksum validation
158 checkAges();
159 //every 30 mins - flood LSA
160 refreshLsa();
161 //every 60 mins - flood LSA
162 maxAgeLsa();
163
164 if (ageCounter == OspfParameters.MAXAGE) {
165 ageCounter = 0;
166 ageCounterRollOver++;
167 } else {
168 //increment age bin
169 ageCounter++;
170 }
171 }
172
173 /**
174 * If the LSA have completed the MaxAge - they are moved called stop aging and flooded.
175 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800176 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530177 public void maxAgeLsa() {
178 if (ageCounter == 0) {
179 return;
180 }
181 //Get from Age Bins
182 LsaBin lsaBin = ageBins.get(ageCounter - 1);
183 if (lsaBin == null) {
184 return;
185 }
186 Map lsaBinMap = lsaBin.listOfLsa();
187 for (Object key : lsaBinMap.keySet()) {
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800188 LsaWrapper lsa = (LsaWrapper) lsaBinMap.get(key);
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530189 if (lsa.currentAge() == OspfParameters.MAXAGE) {
190 lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
191 log.debug("Lsa picked for maxage flooding. Age Counter: {}, AgeCounterRollover: {}, " +
192 "AgeCounterRollover WhenAddedToDb: {}, LSA Type: {}, LSA Key: {}",
193 ageCounter, ageCounterRollOver, lsa.currentAge(), lsa.lsaType(), key);
194 //add it to lsaQueue for processing
195 try {
196 lsaQueue.put(lsa);
197 //remove from bin
198 lsaBin.removeOspfLsa((String) key, lsa);
199 } catch (InterruptedException e) {
Ray Milkey5c7d4882018-02-05 14:50:39 -0800200 Thread.currentThread().interrupt();
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530201 log.debug("Error::LSDBAge::maxAgeLsa::{}", e.getMessage());
202 }
203 }
204 }
205
206 //Get from maxAgeBin
207 Map lsaMaxAgeBinMap = maxAgeBin.listOfLsa();
208 for (Object key : lsaMaxAgeBinMap.keySet()) {
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800209 LsaWrapper lsa = (LsaWrapper) lsaMaxAgeBinMap.get(key);
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530210 lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
211 log.debug("Lsa picked for maxage flooding. Age Counter: {}, LSA Type: {}, LSA Key: {}",
212 ageCounter, lsa.lsaType(), key);
213 //add it to lsaQueue for processing
214 try {
215 lsaQueue.put(lsa);
216 //remove from bin
217 maxAgeBin.removeOspfLsa((String) key, lsa);
218 } catch (InterruptedException e) {
Ray Milkey5c7d4882018-02-05 14:50:39 -0800219 Thread.currentThread().interrupt();
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530220 log.debug("Error::LSDBAge::maxAgeLsa::{}", e.getMessage());
221 }
222 }
223 }
224
225
226 /*
227 * If the LSA is in age bin of 1800 - it's pushed into refresh list.
228 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800229 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530230 public void refreshLsa() {
231 int binNumber;
232 if (ageCounter < OspfParameters.LSREFRESHTIME) {
233 binNumber = ageCounter + OspfParameters.LSREFRESHTIME;
234 } else {
235 binNumber = ageCounter - OspfParameters.LSREFRESHTIME;
236 }
237 LsaBin lsaBin = ageBins.get(binNumber);
238 if (lsaBin == null) {
239 return;
240 }
241 Map lsaBinMap = lsaBin.listOfLsa();
242 for (Object key : lsaBinMap.keySet()) {
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800243 LsaWrapper lsa = (LsaWrapper) lsaBinMap.get(key);
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530244 try {
245 if (lsa.isSelfOriginated()) {
246 log.debug("Lsa picked for refreshLsa. binNumber: {}, LSA Type: {}, LSA Key: {}",
247 binNumber, lsa.lsaType(), key);
248 lsa.setLsaProcessing(OspfParameters.REFRESHLSA);
249 lsaQueue.put(lsa);
250 //remove from bin
251 lsaBin.removeOspfLsa((String) key, lsa);
252 }
253 } catch (InterruptedException e) {
Ray Milkey5c7d4882018-02-05 14:50:39 -0800254 Thread.currentThread().interrupt();
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530255 log.debug("Error::LSDBAge::refreshLsa::{}", e.getMessage());
256 }
257 }
258 }
259
260 /**
261 * Verify the checksum for the LSAs who are in bins of 300 and it's multiples.
262 */
263 public void checkAges() {
264 //evry 5 min age counter + multiples of 300
265 for (int age = OspfParameters.CHECKAGE; age < OspfParameters.MAXAGE;
266 age += OspfParameters.CHECKAGE) {
267 LsaBin lsaBin = ageBins.get(age2Bin(age));
268 if (lsaBin == null) {
269 continue;
270 }
271 Map lsaBinMap = lsaBin.listOfLsa();
272 for (Object key : lsaBinMap.keySet()) {
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800273 LsaWrapper lsa = (LsaWrapper) lsaBinMap.get(key);
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530274 lsa.setLsaProcessing(OspfParameters.VERIFYCHECKSUM);
275 try {
276 lsaQueue.put(lsa);
277 } catch (InterruptedException e) {
Ray Milkey5c7d4882018-02-05 14:50:39 -0800278 Thread.currentThread().interrupt();
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530279 log.debug("Error::LSDBAge::checkAges::{}", e.getMessage());
280 }
281 }
282 }
283 }
284
285
286 /**
287 * Starts DB age timer method start the aging task.
288 */
289 private void startDbAgeTimer() {
290 log.debug("OSPFNbr::startWaitTimer");
291 dbAgeTimer = new InternalAgeTimer();
292 //from 1 sec
293 exServiceage = Executors.newSingleThreadScheduledExecutor();
294 exServiceage.scheduleAtFixedRate(dbAgeTimer, OspfParameters.AGECOUNTER,
295 OspfParameters.AGECOUNTER, TimeUnit.SECONDS);
296 }
297
298 /**
299 * Stops the aging task.
300 */
301 private void stopDbAgeTimer() {
302 log.debug("OSPFNbr::stopWaitTimer ");
303 exServiceage.shutdown();
304 }
305
306
307 /**
308 * Gets the netty channel.
309 *
310 * @return netty channel
311 */
312 public Channel getChannel() {
313 return channel;
314 }
315
316 /**
317 * Sets the netty channel.
318 *
319 * @param channel netty channel
320 */
321 public void setChannel(Channel channel) {
322
323 this.channel = channel;
324 if (queueConsumer != null) {
325 queueConsumer.setChannel(channel);
326 }
327 }
328
329 /**
330 * Gets the age counter.
331 *
332 * @return ageCounter
333 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800334 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530335 public int getAgeCounter() {
336 return ageCounter;
337 }
338
339 /**
340 * Gets the age counter roll over value.
341 *
342 * @return the age counter roll over value
343 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800344 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530345 public int getAgeCounterRollOver() {
346 return ageCounterRollOver;
347 }
348
349 /**
350 * Gets the max age bin.
351 *
352 * @return lsa bin instance
353 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800354 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530355 public LsaBin getMaxAgeBin() {
356 return maxAgeBin;
357 }
358
359 /**
360 * Gets the bin number.
361 *
362 * @param x Can be either age or ageCounter
363 * @return bin number.
364 */
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800365 @Override
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530366 public int age2Bin(int x) {
367 if (x <= ageCounter) {
368 return (ageCounter - x);
369 } else {
370 return ((OspfParameters.MAXAGE - 1) + (ageCounter - x));
371 }
372 }
373
374 /**
375 * Runnable task which runs every second and calls aging process.
376 */
377 private class InternalAgeTimer implements Runnable {
378
379 /**
380 * Constructor.
381 */
382 InternalAgeTimer() {
383 log.debug("Starts::LsdbAge::AgeTimer...!!! ");
384 }
385
386 @Override
387 public void run() {
388 ageLsaAndFlood();
389 }
390 }
391}