blob: c769c9ed2d4021bb5b6728bcf78a48ca84365cd6 [file] [log] [blame]
Dhruv Dhody43f3ce62016-02-16 22:44:21 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Dhruv Dhody43f3ce62016-02-16 22:44: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.protocol.lsa.types;
17
18import com.google.common.base.MoreObjects;
19import com.google.common.base.Objects;
20import com.google.common.primitives.Bytes;
21import org.jboss.netty.buffer.ChannelBuffer;
22import org.onosproject.ospf.exceptions.OspfErrorType;
23import org.onosproject.ospf.exceptions.OspfParseException;
24import org.onosproject.ospf.protocol.lsa.LsaHeader;
25import org.onosproject.ospf.protocol.lsa.subtypes.OspfLsaLink;
26import org.onosproject.ospf.protocol.util.OspfUtil;
27import org.slf4j.Logger;
28import org.slf4j.LoggerFactory;
29
30import java.net.InetAddress;
31import java.util.ArrayList;
32import java.util.List;
33
34/**
35 * Representation of a Router LSA, and the fields and methods to access them.
36 */
37public class RouterLsa extends LsaHeader {
38 /*
39 0 1 2 3
40 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
41 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 | LS age | Options | 1 |
43 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 | Link State ID |
45 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 | Advertising Router |
47 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 | LS sequence number |
49 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 | LS checksum | length |
51 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 | 0 |V|E|B| 0 | # links |
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 | Link ID |
55 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 | Link Data |
57 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 | Type | # TOS | metric |
59 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 | ... |
61 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 | TOS | 0 | TOS metric |
63 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 | Link ID |
65 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 | Link Data |
67 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68 | ... |
69 */
70 private static final Logger log =
71 LoggerFactory.getLogger(RouterLsa.class);
72 private boolean isVirtualEndPoint;
73 private boolean isAsBoundaryRouter;
74 private boolean isAreaBorderRouter;
75 private int noLink;
76 private List<OspfLsaLink> routerLinks = new ArrayList<>();
77
78 /**
79 * Creates an instance of Router LSA.
80 */
81 public RouterLsa() {
82 }
83
84 /**
85 * Creates an instance of Router LSA.
86 *
87 * @param lsaHeader lsa header instance
88 */
89 public RouterLsa(LsaHeader lsaHeader) {
90 populateHeader(lsaHeader);
91 }
92
93 /**
94 * Sets virtual endpoint or not.
95 *
96 * @param isVirtualEndPoint true or false
97 */
98 public void setVirtualEndPoint(boolean isVirtualEndPoint) {
99 this.isVirtualEndPoint = isVirtualEndPoint;
100 }
101
102 /**
103 * Sets if it is an AS boundary router or not.
104 *
105 * @param isAsBoundaryRouter true if AS boundary router else false
106 */
107 public void setAsBoundaryRouter(boolean isAsBoundaryRouter) {
108 this.isAsBoundaryRouter = isAsBoundaryRouter;
109 }
110
111 /**
112 * Sets whether it is an ABR or not.
113 *
114 * @param isAreaBorderRouter true if ABR else false
115 */
116 public void setAreaBorderRouter(boolean isAreaBorderRouter) {
117 this.isAreaBorderRouter = isAreaBorderRouter;
118 }
119
120 /**
121 * Gets number of links.
122 *
123 * @return number of links
124 */
125 public int noLink() {
126 return noLink;
127 }
128
129 /**
130 * Sets number of links.
131 *
132 * @param noLink number of links
133 */
134 public void setNoLink(int noLink) {
135 this.noLink = noLink;
136 }
137
138
139 /**
140 * Adds router link.
141 *
142 * @param lsaLink LSA link
143 */
144 public void addRouterLink(OspfLsaLink lsaLink) {
145 if (!this.routerLinks.contains(lsaLink)) {
146 this.routerLinks.add(lsaLink);
147 }
148 }
149
150 /**
151 * Gets router link.
152 *
153 * @return routerLinks LSA link list
154 */
155 public List<OspfLsaLink> routerLink() {
156 return this.routerLinks;
157 }
158
159 /**
160 * Reads from channel buffer and populate this.
161 *
162 * @param channelBuffer channelBuffer instance.
163 * @throws OspfParseException might throws exception while parsing buffer
164 */
165 public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {
166
167 try {
168 int veb = channelBuffer.readByte();
169 int unUsed = channelBuffer.readByte();
170 //Convert the byte to veb bits
171 String strVeb = Integer.toBinaryString(veb);
172 if (strVeb.length() == 3) {
173 this.setVirtualEndPoint((Integer.parseInt(Character.toString(strVeb.charAt(0))) == 1) ? true : false);
174 this.setAsBoundaryRouter((Integer.parseInt(Character.toString(strVeb.charAt(1))) == 1) ? true : false);
175 this.setAreaBorderRouter((Integer.parseInt(Character.toString(strVeb.charAt(2))) == 1) ? true : false);
176 } else if (strVeb.length() == 2) {
177 this.setVirtualEndPoint(false);
178 this.setAsBoundaryRouter((Integer.parseInt(Character.toString(strVeb.charAt(0))) == 1) ? true : false);
179 this.setAreaBorderRouter((Integer.parseInt(Character.toString(strVeb.charAt(1))) == 1) ? true : false);
180 } else if (strVeb.length() == 1) {
181 this.setVirtualEndPoint(false);
182 this.setAsBoundaryRouter(false);
183 this.setAreaBorderRouter((Integer.parseInt(Character.toString(strVeb.charAt(0))) == 1) ? true : false);
184 }
185 this.setNoLink(channelBuffer.readUnsignedShort());
186 while (channelBuffer.readableBytes() >= OspfUtil.TWELVE_BYTES) {
187 OspfLsaLink ospfLsaLink = new OspfLsaLink();
188
189 byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
190 channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
191 ospfLsaLink.setLinkId(InetAddress.getByAddress(tempByteArray).getHostName());
192 tempByteArray = new byte[OspfUtil.FOUR_BYTES];
193 channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
194 ospfLsaLink.setLinkData(InetAddress.getByAddress(tempByteArray).getHostName());
195 ospfLsaLink.setLinkType(channelBuffer.readByte());
196 ospfLsaLink.setTos(channelBuffer.readByte());
197 ospfLsaLink.setMetric(channelBuffer.readUnsignedShort());
198 //add the link
199 this.addRouterLink(ospfLsaLink);
200 }
201 } catch (Exception e) {
202 log.debug("Error::RouterLsa:: {}", e.getMessage());
203 throw new OspfParseException(OspfErrorType.OSPF_MESSAGE_ERROR, OspfErrorType.BAD_MESSAGE);
204 }
205 }
206
207 /**
208 * Returns instance as bytes.
209 *
210 * @return instance as bytes
211 * @throws OspfParseException might throws exception while parsing packet
212 */
213 public byte[] asBytes() throws OspfParseException {
214 byte[] lsaMessage = null;
215
216 byte[] lsaHeader = getLsaHeaderAsByteArray();
217 byte[] lsaBody = getLsaBodyAsByteArray();
218 lsaMessage = Bytes.concat(lsaHeader, lsaBody);
219
220 return lsaMessage;
221 }
222
223 /**
224 * Gets the LSA body as bytes.
225 *
226 * @return LSA body as bytes
227 */
228 public byte[] getLsaBodyAsByteArray() {
229 List<Byte> bodyLst = new ArrayList<>();
230
231 try {
232 int isVirtualEndPointVal = this.isVirtualEndPoint ? 1 : 0;
233 int isASBoundaryRouterVal = this.isAsBoundaryRouter ? 1 : 0;
234 int isAreaBorderRouterVal = this.isAreaBorderRouter ? 1 : 0;
235
236 StringBuilder sb = new StringBuilder();
237 sb.append(Integer.toBinaryString(isVirtualEndPointVal));
238 sb.append(Integer.toBinaryString(isASBoundaryRouterVal));
239 sb.append(Integer.toBinaryString(isAreaBorderRouterVal));
240
241 //added VEB
242 bodyLst.add((byte) Integer.parseInt(sb.toString(), 2));
243 //second byte is 0.
244 bodyLst.add((byte) 0);
245 //Number of links
246 bodyLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.noLink())));
247
248 //add each link details
249 for (OspfLsaLink lsaLink : routerLinks) {
250 bodyLst.addAll(Bytes.asList(InetAddress.getByName(lsaLink.linkId()).getAddress()));
251 bodyLst.addAll(Bytes.asList(InetAddress.getByName(lsaLink.linkData()).getAddress()));
252 bodyLst.add((byte) lsaLink.linkType());
253 bodyLst.add((byte) lsaLink.tos());
254 bodyLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(lsaLink.metric())));
255 }
256 } catch (Exception e) {
257 log.debug("Error::getLsrBodyAsByteArray {}", e.getMessage());
258 return Bytes.toArray(bodyLst);
259 }
260
261 return Bytes.toArray(bodyLst);
262 }
263
264 /**
265 * Increment the link by 1.
266 */
267 public void incrementLinkNo() {
268 this.noLink++;
269 }
270
271 @Override
272 public String toString() {
273 return MoreObjects.toStringHelper(getClass())
274 .omitNullValues()
275 .add("isVirtualEndPoint", isVirtualEndPoint)
276 .add("isAsBoundaryRouter", isAsBoundaryRouter)
277 .add("isAreaBorderRouter", isAreaBorderRouter)
278 .add("noLink", noLink)
279 .add("routerLinks", routerLinks)
280 .toString();
281 }
282
283 @Override
284 public boolean equals(Object o) {
285 if (this == o) {
286 return true;
287 }
288 if (o == null || getClass() != o.getClass()) {
289 return false;
290 }
291 RouterLsa that = (RouterLsa) o;
292 return Objects.equal(isVirtualEndPoint, that.isVirtualEndPoint) &&
293 Objects.equal(isAsBoundaryRouter, that.isAsBoundaryRouter) &&
294 Objects.equal(isAreaBorderRouter, that.isAreaBorderRouter) &&
295 Objects.equal(noLink, that.noLink) &&
296 Objects.equal(routerLinks, that.routerLinks);
297 }
298
299 @Override
300 public int hashCode() {
301 return Objects.hashCode(isVirtualEndPoint, isAsBoundaryRouter, isAreaBorderRouter,
302 noLink, routerLinks);
303 }
304}