blob: 29af7c37e939a55ac422eb5b3bd726c6087670be [file] [log] [blame]
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +05301/*
2 * Copyright 2016 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 */
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);
44 protected int ageCounter = 0;
45 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) &&
83 Objects.equal(lsaQueue, lsaQueue);
84 }
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 */
97 public void addLsaBin(Integer binKey, LsaBin lsaBin) {
98 if (!ageBins.containsKey(binKey)) {
99 ageBins.put(binKey, lsaBin);
100 }
101 }
102
103 /**
104 * Gets LSA from Bin.
105 *
106 * @param binKey key
107 * @return bin instance
108 */
109 public LsaBin getLsaBin(Integer binKey) {
110
111 return ageBins.get(binKey);
112 }
113
114 /**
115 * Adds the LSA to maxAge bin.
116 *
117 * @param key key
118 * @param wrapper wrapper instance
119 */
120 public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) {
121 maxAgeBin.addOspfLsa(key, wrapper);
122 }
123
124 /**
125 * Removes LSA from Bin.
126 *
127 * @param lsaWrapper wrapper instance
128 */
129 public void removeLsaFromBin(LsaWrapper lsaWrapper) {
130 if (ageBins.containsKey(lsaWrapper.binNumber())) {
131 LsaBin lsaBin = ageBins.get(lsaWrapper.binNumber());
132 lsaBin.removeOspfLsa(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
133 lsaWrapper).lsaHeader()), lsaWrapper);
134 }
135 }
136
137 /**
138 * Starts the aging timer and queue consumer.
139 */
140 public void startDbAging() {
141 startDbAgeTimer();
142 queueConsumer = new LsaQueueConsumer(lsaQueue, channel, ospfArea);
143 new Thread(queueConsumer).start();
144 }
145
146
147 /**
148 * Gets called every 1 second as part of the timer.
149 */
150 public void ageLsaAndFlood() {
151 //every 5 mins checksum validation
152 checkAges();
153 //every 30 mins - flood LSA
154 refreshLsa();
155 //every 60 mins - flood LSA
156 maxAgeLsa();
157
158 if (ageCounter == OspfParameters.MAXAGE) {
159 ageCounter = 0;
160 ageCounterRollOver++;
161 } else {
162 //increment age bin
163 ageCounter++;
164 }
165 }
166
167 /**
168 * If the LSA have completed the MaxAge - they are moved called stop aging and flooded.
169 */
170 public void maxAgeLsa() {
171 if (ageCounter == 0) {
172 return;
173 }
174 //Get from Age Bins
175 LsaBin lsaBin = ageBins.get(ageCounter - 1);
176 if (lsaBin == null) {
177 return;
178 }
179 Map lsaBinMap = lsaBin.listOfLsa();
180 for (Object key : lsaBinMap.keySet()) {
181 LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
182 if (lsa.currentAge() == OspfParameters.MAXAGE) {
183 lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
184 log.debug("Lsa picked for maxage flooding. Age Counter: {}, AgeCounterRollover: {}, " +
185 "AgeCounterRollover WhenAddedToDb: {}, LSA Type: {}, LSA Key: {}",
186 ageCounter, ageCounterRollOver, lsa.currentAge(), lsa.lsaType(), key);
187 //add it to lsaQueue for processing
188 try {
189 lsaQueue.put(lsa);
190 //remove from bin
191 lsaBin.removeOspfLsa((String) key, lsa);
192 } catch (InterruptedException e) {
193 log.debug("Error::LSDBAge::maxAgeLsa::{}", e.getMessage());
194 }
195 }
196 }
197
198 //Get from maxAgeBin
199 Map lsaMaxAgeBinMap = maxAgeBin.listOfLsa();
200 for (Object key : lsaMaxAgeBinMap.keySet()) {
201 LsaWrapper lsa = (LsaWrapper) lsaMaxAgeBinMap.get((String) key);
202 lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
203 log.debug("Lsa picked for maxage flooding. Age Counter: {}, LSA Type: {}, LSA Key: {}",
204 ageCounter, lsa.lsaType(), key);
205 //add it to lsaQueue for processing
206 try {
207 lsaQueue.put(lsa);
208 //remove from bin
209 maxAgeBin.removeOspfLsa((String) key, lsa);
210 } catch (InterruptedException e) {
211 log.debug("Error::LSDBAge::maxAgeLsa::{}", e.getMessage());
212 }
213 }
214 }
215
216
217 /*
218 * If the LSA is in age bin of 1800 - it's pushed into refresh list.
219 */
220 public void refreshLsa() {
221 int binNumber;
222 if (ageCounter < OspfParameters.LSREFRESHTIME) {
223 binNumber = ageCounter + OspfParameters.LSREFRESHTIME;
224 } else {
225 binNumber = ageCounter - OspfParameters.LSREFRESHTIME;
226 }
227 LsaBin lsaBin = ageBins.get(binNumber);
228 if (lsaBin == null) {
229 return;
230 }
231 Map lsaBinMap = lsaBin.listOfLsa();
232 for (Object key : lsaBinMap.keySet()) {
233 LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
234 try {
235 if (lsa.isSelfOriginated()) {
236 log.debug("Lsa picked for refreshLsa. binNumber: {}, LSA Type: {}, LSA Key: {}",
237 binNumber, lsa.lsaType(), key);
238 lsa.setLsaProcessing(OspfParameters.REFRESHLSA);
239 lsaQueue.put(lsa);
240 //remove from bin
241 lsaBin.removeOspfLsa((String) key, lsa);
242 }
243 } catch (InterruptedException e) {
244 log.debug("Error::LSDBAge::refreshLsa::{}", e.getMessage());
245 }
246 }
247 }
248
249 /**
250 * Verify the checksum for the LSAs who are in bins of 300 and it's multiples.
251 */
252 public void checkAges() {
253 //evry 5 min age counter + multiples of 300
254 for (int age = OspfParameters.CHECKAGE; age < OspfParameters.MAXAGE;
255 age += OspfParameters.CHECKAGE) {
256 LsaBin lsaBin = ageBins.get(age2Bin(age));
257 if (lsaBin == null) {
258 continue;
259 }
260 Map lsaBinMap = lsaBin.listOfLsa();
261 for (Object key : lsaBinMap.keySet()) {
262 LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
263 lsa.setLsaProcessing(OspfParameters.VERIFYCHECKSUM);
264 try {
265 lsaQueue.put(lsa);
266 } catch (InterruptedException e) {
267 log.debug("Error::LSDBAge::checkAges::{}", e.getMessage());
268 }
269 }
270 }
271 }
272
273
274 /**
275 * Starts DB age timer method start the aging task.
276 */
277 private void startDbAgeTimer() {
278 log.debug("OSPFNbr::startWaitTimer");
279 dbAgeTimer = new InternalAgeTimer();
280 //from 1 sec
281 exServiceage = Executors.newSingleThreadScheduledExecutor();
282 exServiceage.scheduleAtFixedRate(dbAgeTimer, OspfParameters.AGECOUNTER,
283 OspfParameters.AGECOUNTER, TimeUnit.SECONDS);
284 }
285
286 /**
287 * Stops the aging task.
288 */
289 private void stopDbAgeTimer() {
290 log.debug("OSPFNbr::stopWaitTimer ");
291 exServiceage.shutdown();
292 }
293
294
295 /**
296 * Gets the netty channel.
297 *
298 * @return netty channel
299 */
300 public Channel getChannel() {
301 return channel;
302 }
303
304 /**
305 * Sets the netty channel.
306 *
307 * @param channel netty channel
308 */
309 public void setChannel(Channel channel) {
310
311 this.channel = channel;
312 if (queueConsumer != null) {
313 queueConsumer.setChannel(channel);
314 }
315 }
316
317 /**
318 * Gets the age counter.
319 *
320 * @return ageCounter
321 */
322 public int getAgeCounter() {
323 return ageCounter;
324 }
325
326 /**
327 * Gets the age counter roll over value.
328 *
329 * @return the age counter roll over value
330 */
331 public int getAgeCounterRollOver() {
332 return ageCounterRollOver;
333 }
334
335 /**
336 * Gets the max age bin.
337 *
338 * @return lsa bin instance
339 */
340 public LsaBin getMaxAgeBin() {
341 return maxAgeBin;
342 }
343
344 /**
345 * Gets the bin number.
346 *
347 * @param x Can be either age or ageCounter
348 * @return bin number.
349 */
350 public int age2Bin(int x) {
351 if (x <= ageCounter) {
352 return (ageCounter - x);
353 } else {
354 return ((OspfParameters.MAXAGE - 1) + (ageCounter - x));
355 }
356 }
357
358 /**
359 * Runnable task which runs every second and calls aging process.
360 */
361 private class InternalAgeTimer implements Runnable {
362
363 /**
364 * Constructor.
365 */
366 InternalAgeTimer() {
367 log.debug("Starts::LsdbAge::AgeTimer...!!! ");
368 }
369
370 @Override
371 public void run() {
372 ageLsaAndFlood();
373 }
374 }
375}