blob: c38b3835cf83187c83db07061c7347baeb687c19 [file] [log] [blame]
Manicdb26412016-02-16 19:44:34 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Manicdb26412016-02-16 19:44:34 +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.protocol.ospfpacket.types;
17
18import com.google.common.base.MoreObjects;
19import com.google.common.primitives.Bytes;
20import org.jboss.netty.buffer.ChannelBuffer;
21import org.onosproject.ospf.exceptions.OspfErrorType;
22import org.onosproject.ospf.exceptions.OspfParseException;
23import org.onosproject.ospf.protocol.lsa.LsaHeader;
24import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
25import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
sunishvkf7c56552016-07-18 16:02:39 +053026import org.onosproject.ospf.controller.OspfPacketType;
Manicdb26412016-02-16 19:44:34 +053027import org.onosproject.ospf.protocol.util.OspfParameters;
28import org.onosproject.ospf.protocol.util.OspfUtil;
29import org.slf4j.Logger;
30import org.slf4j.LoggerFactory;
31
32import java.util.ArrayList;
33import java.util.List;
34
35/**
36 * Representation of an OSPF Database Description packet.
37 * Database Description packets are OSPF packet type 2.
38 * These packets are exchanged when an adjacency is being initialized.
39 * They describe the contents of the link-state database.
40 */
41public class DdPacket extends OspfPacketHeader {
42
43 /*
44 0 1 2 3
45 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
46 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 | Version # | 2 | Packet length |
48 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 | Router ID |
50 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 | Area ID |
52 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 | Checksum | AuType |
54 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 | Authentication |
56 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 | Authentication |
58 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 | Interface MTU | Options |0|0|0|0|0|I|M|MS
60 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 | DD sequence number |
62 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 | |
64 +- -+
65 | |
66 +- An LSA Header -+
67 | |
68 +- -+
69 | |
70 +- -+
71 | |
72 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 | ... |
74 */
75 private static final Logger log = LoggerFactory.getLogger(DdPacket.class);
76 private int imtu;
77 private int options;
78 private int ims; // initialize , more but / master slave bit
79 private int isMaster;
80 private int isInitialize;
81 private int isMore;
82 private long sequenceNo;
83 private boolean isOpaqueCapable;
84 private List<LsaHeader> lsaHeaderList = new ArrayList<>();
85
86 /**
87 * Creates an instance of DD packet.
88 */
89 public DdPacket() {
90 }
91
92 /**
93 * Creates an instance of DD packet.
94 *
95 * @param ospfHeader OSPF header instance
96 */
97 public DdPacket(OspfPacketHeader ospfHeader) {
98 populateHeader(ospfHeader);
99 }
100
101 /**
102 * Gets is opaque capable or not.
103 *
104 * @return true if opaque capable else false
105 */
106 public boolean isOpaqueCapable() {
107 return isOpaqueCapable;
108 }
109
110 /**
111 * Sets is opaque capable or not.
112 *
113 * @param isOpaqueCapable true or false
114 */
115 public void setIsOpaqueCapable(boolean isOpaqueCapable) {
116 this.isOpaqueCapable = isOpaqueCapable;
117 }
118
119 /**
120 * Gets IMS value.
121 *
122 * @return IMS bits as an int value
123 */
124 public int ims() {
125 return ims;
126 }
127
128 /**
129 * Sets IMS value.
130 *
131 * @param ims IMS value
132 */
133 public void setIms(int ims) {
134 this.ims = ims;
135 }
136
137 /**
138 * Gets master bit value.
139 *
140 * @return 1 if master else 0
141 */
142 public int isMaster() {
143 return isMaster;
144 }
145
146 /**
147 * Sets master value.
148 *
149 * @param isMaster 1 represents master
150 */
151 public void setIsMaster(int isMaster) {
152 this.isMaster = isMaster;
153 }
154
155 /**
156 * Gets Initialize bit value.
157 *
158 * @return 1 if initialize else 0
159 */
160 public int isInitialize() {
161 return isInitialize;
162 }
163
164 /**
165 * Sets initialize value.
166 *
167 * @param isInitialize 1 is initialize else 0
168 */
169 public void setIsInitialize(int isInitialize) {
170 this.isInitialize = isInitialize;
171 }
172
173 /**
174 * Gets is more bit set or not.
175 *
176 * @return 1 if more set else 0
177 */
178 public int isMore() {
179 return isMore;
180 }
181
182 /**
183 * Sets more bit value to 0 or 1.
184 *
185 * @param isMore 1 if more set else 0
186 */
187 public void setIsMore(int isMore) {
188 this.isMore = isMore;
189 }
190
191
192 /**
193 * Gets IMTU value.
194 *
195 * @return IMTU value
196 */
197 public int imtu() {
198 return imtu;
199 }
200
201 /**
202 * Sets IMTU value.
203 *
204 * @param imtu value
205 */
206 public void setImtu(int imtu) {
207 this.imtu = imtu;
208 }
209
210 /**
211 * Gets options value.
212 *
213 * @return options
214 */
215 public int options() {
216 return options;
217 }
218
219 /**
220 * Sets options value.
221 *
222 * @param options options value
223 */
224 public void setOptions(int options) {
225 this.options = options;
226 }
227
228 /**
229 * Gets sequence number.
230 *
231 * @return sequenceNo
232 */
233 public long sequenceNo() {
234 return sequenceNo;
235 }
236
237 /**
238 * Sets Sequence number.
239 *
240 * @param sequenceNo sequence number
241 */
242 public void setSequenceNo(long sequenceNo) {
243 this.sequenceNo = sequenceNo;
244 }
245
246 /**
247 * Gets LSA header list.
248 *
249 * @return LSA header
250 */
251 public List<LsaHeader> getLsaHeaderList() {
252 return lsaHeaderList;
253 }
254
255 /**
256 * Adds LSA header to header list.
257 *
258 * @param lsaHeader lsa header instance
259 */
260 public void addLsaHeader(LsaHeader lsaHeader) {
261
262 if (!lsaHeaderList.contains(lsaHeader)) {
263 lsaHeaderList.add(lsaHeader);
264 }
265 }
266
267 @Override
268 public OspfPacketType ospfMessageType() {
269 return OspfPacketType.DD;
270 }
271
272 @Override
273 public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {
274
275 try {
276 this.setImtu(channelBuffer.readShort());
277
278 int options = channelBuffer.readByte();
279 String obit = Integer.toHexString(options);
280 if (obit.length() == 1) {
281 obit = "0" + obit;
282 }
283 String toBinary = Integer.toBinaryString(Integer.parseInt(new Character(obit.charAt(0)).toString()));
284 if (toBinary.length() == 1) {
285 toBinary = "000" + toBinary;
286 } else if (toBinary.length() == 2) {
287 toBinary = "00" + toBinary;
288 } else if (toBinary.length() == 3) {
289 toBinary = "0" + toBinary;
290 }
291 if (Integer.parseInt(new Character(toBinary.charAt(1)).toString()) == 1) {
292 this.setIsOpaqueCapable(true);
293 }
294 this.setOptions(options);
295 this.setIms(channelBuffer.readByte());
296 //Convert the byte to ims bits
297 String strIms = Integer.toBinaryString(this.ims());
298 if (strIms.length() == 3) {
299 this.setIsInitialize(Integer.parseInt(Character.toString(strIms.charAt(0))));
300 this.setIsMore(Integer.parseInt(Character.toString(strIms.charAt(1))));
301 this.setIsMaster(Integer.parseInt(Character.toString(strIms.charAt(2))));
302 } else if (strIms.length() == 2) {
303 this.setIsInitialize(0);
304 this.setIsMore(Integer.parseInt(Character.toString(strIms.charAt(0))));
305 this.setIsMaster(Integer.parseInt(Character.toString(strIms.charAt(1))));
306 } else if (strIms.length() == 1) {
307 this.setIsInitialize(0);
308 this.setIsMore(0);
309 this.setIsMaster(Integer.parseInt(Character.toString(strIms.charAt(0))));
310 }
311 this.setSequenceNo(channelBuffer.readInt());
312
313 //add all the LSA Headers - header is of 20 bytes
314 while (channelBuffer.readableBytes() >= OspfUtil.LSA_HEADER_LENGTH) {
315 LsaHeader header = OspfUtil.readLsaHeader(channelBuffer.readBytes(OspfUtil.LSA_HEADER_LENGTH));
316 //add the LSAHeader to DDPacket
317 addLsaHeader(header);
318 }
319
320 } catch (Exception e) {
321 log.debug("Error::DdPacket:: {}", e.getMessage());
322 throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH);
323 }
324 }
325
326 @Override
327 public byte[] asBytes() {
328
329 byte[] ddMessage = null;
330
331 byte[] ddHeader = getDdHeaderAsByteArray();
332 byte[] ddBody = getDdBodyAsByteArray();
333 ddMessage = Bytes.concat(ddHeader, ddBody);
334
335 return ddMessage;
336 }
337
338 /**
339 * Gets DD Header as byte array.
340 *
341 * @return dd header as byte array.
342 */
343 public byte[] getDdHeaderAsByteArray() {
344 List<Byte> headerLst = new ArrayList<>();
345
346 try {
347 headerLst.add((byte) this.ospfVersion());
348 headerLst.add((byte) this.ospfType());
349 headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.ospfPacLength())));
350 headerLst.addAll(Bytes.asList(this.routerId().toOctets()));
351 headerLst.addAll(Bytes.asList(this.areaId().toOctets()));
352 headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.checksum())));
353 headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.authType())));
354 //Authentication is 0 always. Total 8 bytes consist of zero
355 byte[] auth = new byte[OspfUtil.EIGHT_BYTES];
356 headerLst.addAll(Bytes.asList(auth));
357
358 } catch (Exception e) {
359 log.debug("Error");
360
361 }
362
363 return Bytes.toArray(headerLst);
364 }
365
366
367 /**
368 * Gets DD body as byte array.
369 *
370 * @return DD body
371 */
372 public byte[] getDdBodyAsByteArray() {
373 List<Byte> bodyLst = new ArrayList<>();
374
375 try {
376 bodyLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.imtu())));
377 bodyLst.add((byte) this.options());
378
379 StringBuilder sb = new StringBuilder();
380 sb.append(this.isInitialize());
381 sb.append(this.isMore());
382 sb.append(this.isMaster());
383
384 bodyLst.add((byte) Integer.parseInt(sb.toString(), 2));
385 bodyLst.addAll(Bytes.asList(OspfUtil.convertToFourBytes(this.sequenceNo()))); // passing long value
386
387 for (LsaHeader lsaHeader : lsaHeaderList) {
388 if (lsaHeader.lsType() == OspfParameters.LINK_LOCAL_OPAQUE_LSA ||
389 lsaHeader.lsType() == OspfParameters.AREA_LOCAL_OPAQUE_LSA ||
390 lsaHeader.lsType() == OspfParameters.AS_OPAQUE_LSA) {
391 OpaqueLsaHeader header = (OpaqueLsaHeader) lsaHeader;
392 bodyLst.addAll(Bytes.asList(header.getOpaqueLsaHeaderAsByteArray()));
393 } else {
394 bodyLst.addAll(Bytes.asList(lsaHeader.getLsaHeaderAsByteArray()));
395 }
396 }
397 } catch (Exception e) {
398 log.debug("Error::getLsrBodyAsByteArray {}", e.getMessage());
399 return Bytes.toArray(bodyLst);
400 }
401
402 return Bytes.toArray(bodyLst);
403 }
404
405 @Override
406 public String toString() {
407 return MoreObjects.toStringHelper(getClass())
408 .omitNullValues()
409 .add("imtu", imtu)
410 .add("options", options)
411 .add("ims", ims)
412 .add("isMaster", isMaster)
413 .add("isInitialize", isInitialize)
414 .add("isMore", isMore)
415 .add("sequenceNo", sequenceNo)
416 .add("isOpaqueCapable", isOpaqueCapable)
417 .add("lsaHeaderList", lsaHeaderList)
418 .toString();
419 }
420}