blob: 790d3ae24c5fb5421b60557f4101f910d94305db [file] [log] [blame]
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301/*
2 * Copyright 2016-present 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.isis.controller.impl.lsdb;
17
18import org.onosproject.isis.controller.IsisLsdbAge;
19import org.onosproject.isis.controller.IsisLspBin;
20import org.onosproject.isis.controller.LspWrapper;
21import org.onosproject.isis.io.isispacket.pdu.LsPdu;
22import org.onosproject.isis.io.util.IsisConstants;
23import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
25
26import java.util.Map;
27import java.util.concurrent.ArrayBlockingQueue;
28import java.util.concurrent.BlockingQueue;
29import java.util.concurrent.ConcurrentHashMap;
30import java.util.concurrent.Executors;
31import java.util.concurrent.ScheduledExecutorService;
32import java.util.concurrent.TimeUnit;
33
34/**
35 * Representation of ISIS link state database ageing process.
36 */
37public class DefaultIsisLsdbAge implements IsisLsdbAge {
38 private static final Logger log = LoggerFactory.getLogger(DefaultIsisLsdbAge.class);
sunish vk4b5ce002016-05-09 20:18:35 +053039 protected int ageCounter = 0;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +053040 private InternalAgeTimer dbAgeTimer;
41 private ScheduledExecutorService exServiceage;
sunish vk4b5ce002016-05-09 20:18:35 +053042 private Integer maxBins = IsisConstants.LSPMAXAGE;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +053043 private Map<Integer, IsisLspBin> ageBins = new ConcurrentHashMap<>(maxBins);
44 private int ageCounterRollOver = 0;
45 private IsisLspQueueConsumer queueConsumer = null;
46 private BlockingQueue<LspWrapper> lsaQueue = new ArrayBlockingQueue<>(1024);
sunish vkc3824e82016-05-11 19:38:24 +053047 private boolean timerStarted = false;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +053048
49 /**
50 * Creates an instance of LSDB age.
51 */
52 public DefaultIsisLsdbAge() {
53 // create LSBin's in the HashMap.
54 for (int i = 0; i < maxBins; i++) {
55 IsisLspBin lspBin = new DefaultIsisLspBin(i);
56 ageBins.put(i, lspBin);
57 }
58 }
59
60 /**
61 * Returns age counter.
62 *
63 * @return age counter
64 */
65 public int ageCounter() {
66 return ageCounter;
67 }
68
69 /**
70 * Returns age counter roll over.
71 *
72 * @return age counter roll over
73 */
74 public int ageCounterRollOver() {
75
76 return ageCounterRollOver;
77 }
78
79 /**
80 * Adds LSP to LS bin for ageing.
81 *
82 * @param binNumber key to store in bin
83 * @param lspBin LSP bin instance
84 */
85 public void addLspBin(int binNumber, IsisLspBin lspBin) {
86 if (!ageBins.containsKey(binNumber)) {
87 ageBins.put(binNumber, lspBin);
88 }
89 }
90
91 /**
92 * Returns LSP from Bin.
93 *
94 * @param binKey key
95 * @return bin instance
96 */
97 public IsisLspBin getLspBin(int binKey) {
98
99 return ageBins.get(binKey);
100 }
101
102 /**
103 * Removes LSP from Bin.
104 *
105 * @param lspWrapper wrapper instance
106 */
107 public void removeLspFromBin(LspWrapper lspWrapper) {
108 if (ageBins.containsKey(lspWrapper.binNumber())) {
109 IsisLspBin lsaBin = ageBins.get(lspWrapper.binNumber());
110 lsaBin.removeIsisLsp(((LsPdu) lspWrapper.lsPdu()).lspId(), lspWrapper);
111 }
112 }
113
114 /**
115 * Returns the bin number.
116 *
117 * @param age Can be either age or ageCounter
118 * @return bin number.
119 */
120 public int age2Bin(int age) {
121 if (age <= ageCounter) {
122 return (ageCounter - age);
123 } else {
124 return ((IsisConstants.LSPMAXAGE - 1) + (ageCounter - age));
125 }
126 }
127
128 /**
129 * Starts the aging timer and queue consumer.
130 */
131 public void startDbAging() {
sunish vkc3824e82016-05-11 19:38:24 +0530132 if (!timerStarted) {
133 startDbAgeTimer();
134 queueConsumer = new IsisLspQueueConsumer(lsaQueue);
135 new Thread(queueConsumer).start();
136 timerStarted = true;
137 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530138 }
139
140 /**
141 * Starts DB aging task.
142 */
143 private void startDbAgeTimer() {
144 dbAgeTimer = new InternalAgeTimer();
145 //from 1 sec
146 exServiceage = Executors.newSingleThreadScheduledExecutor();
147 exServiceage.scheduleAtFixedRate(dbAgeTimer, 1, 1, TimeUnit.SECONDS);
148 }
149
150 /**
151 * Gets called every second as part of the aging process.
152 */
153 public void ageLsp() {
154 refreshLsa();
155 maxAgeLsa();
156
157 if (ageCounter == IsisConstants.LSPMAXAGE) {
158 ageCounter = 0;
159 ageCounterRollOver++;
160 } else {
161 ageCounter++;
162 }
163 }
164
165 /**
166 * If the LSP have completed the MaxAge - they are moved called stop aging.
167 */
168 public void maxAgeLsa() {
169 if (ageCounter == 0) {
170 return;
171 }
172 //Get from Age Bins
173 IsisLspBin lspBin = ageBins.get(ageCounter - 1);
174 if (lspBin == null) {
175 return;
176 }
177 Map lspBinMap = lspBin.listOfLsp();
178 for (Object key : lspBinMap.keySet()) {
179 LspWrapper lspWrapper = (LspWrapper) lspBinMap.get((String) key);
180 if (lspWrapper.currentAge() == IsisConstants.LSPMAXAGE) {
181 lspWrapper.setLspProcessing(IsisConstants.MAXAGELSP);
182 log.debug("Lsp picked for maxage removal. Age Counter: {}, AgeCounterRollover: {}, " +
183 "AgeCounterRollover WhenAddedToDb: {}, LSA Type: {}, LSA Key: {}",
184 ageCounter, ageCounterRollOver, lspWrapper.currentAge(),
185 lspWrapper.lsPdu().isisPduType(), key);
186 //add it to lspQueue for processing
187 try {
188 lsaQueue.put(lspWrapper);
189 //remove from bin
190 lspBin.removeIsisLsp((String) key, lspWrapper);
191 } catch (InterruptedException e) {
192 log.debug("Error::LSDBAge::maxAgeLsp::{}", e.getMessage());
193 }
194 }
195 }
196
197 }
198
199 /*
200 * If the LSP is in age bin of 900s- it's pushed into refresh list.
201 */
202 public void refreshLsa() {
203 int binNumber;
204 if (ageCounter < IsisConstants.LSPREFRESH) {
205 binNumber = ageCounter + IsisConstants.LSPREFRESH;
206 } else {
207 binNumber = ageCounter - IsisConstants.LSPREFRESH;
208 }
sunish vk4b5ce002016-05-09 20:18:35 +0530209 if (binNumber >= IsisConstants.LSPMAXAGE) {
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530210 binNumber = binNumber - IsisConstants.LSPMAXAGE;
211 }
212 IsisLspBin lspBin = ageBins.get(binNumber);
213 if (lspBin == null) {
214 return;
215 }
216 Map lspBinMap = lspBin.listOfLsp();
217 for (Object key : lspBinMap.keySet()) {
218 LspWrapper lsp = (LspWrapper) lspBinMap.get((String) key);
219 try {
220 if (lsp.isSelfOriginated()) {
221 log.debug("Lsp picked for refreshLsp. binNumber: {}, LSA Type: {}, LSA Key: {}",
222 binNumber, lsp.lspType(), key);
223 lsp.setLspProcessing(IsisConstants.REFRESHLSP);
224 lsaQueue.put(lsp);
225 //remove from bin
226 lspBin.removeIsisLsp((String) key, lsp);
227 }
228 } catch (InterruptedException e) {
229 log.debug("Error::LSDBAge::refreshLsp::{}", e.getMessage());
230 }
231 }
232 }
233
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530234 /**
235 * Runnable task which runs every second and calls aging process.
236 */
237 private class InternalAgeTimer implements Runnable {
238
239 /**
240 * Creates an instance of age timer task.
241 */
242 InternalAgeTimer() {
243 log.debug("Starts::IsisLsdbAge::AgeTimer...!!! ");
244 }
245
246 @Override
247 public void run() {
248 ageLsp();
249 }
250 }
251}