blob: c6d164239ebce6ca01d580c548769b7d3391215c [file] [log] [blame]
Mohamed Rahila3b9e992016-02-16 20:26:49 +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.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.onlab.packet.Ip4Address;
23import org.onosproject.ospf.controller.OspfLsaType;
24import org.onosproject.ospf.exceptions.OspfErrorType;
25import org.onosproject.ospf.exceptions.OspfParseException;
26import org.onosproject.ospf.protocol.lsa.LsaHeader;
27import org.onosproject.ospf.protocol.lsa.subtypes.OspfExternalDestination;
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 External LSA and the fields and methods to access them.
37 */
38public class ExternalLsa extends LsaHeader {
39
40 /*
41 0 1 2 3
42 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
43 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 | LS age | Options | 5 |
45 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 | Link State ID |
47 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 | Advertising Router |
49 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 | LS sequence number |
51 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 | LS checksum | length |
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 | Network Mask |
55 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 |E| 0 | metric |
57 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 | Forwarding address |
59 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 | External Route Tag |
61 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 |E| TOS | TOS metric |
63 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 | Forwarding address |
65 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 | External Route Tag |
67 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68 | ... |
69
70 External LSA format
71 REFERENCE : RFC 2328
72 */
73 private static final Logger log =
74 LoggerFactory.getLogger(ExternalLsa.class);
75 private Ip4Address networkMask;
76 private List<OspfExternalDestination> externalDestinations = new ArrayList<>();
77
78 /**
79 * Creates an instance of External LSA.
80 *
81 * @param lsaHeader lsa header instance.
82 */
83 public ExternalLsa(LsaHeader lsaHeader) {
84 populateHeader(lsaHeader);
85 }
86
87
88 /**
89 * Gets the network mask.
90 *
91 * @return networkMask
92 */
93 public Ip4Address networkMask() {
94 return networkMask;
95 }
96
97 /**
98 * Sets network mask.
99 *
100 * @param networkMask network mask
101 */
102 public void setNetworkMask(Ip4Address networkMask) {
103 this.networkMask = networkMask;
104 }
105
106 /**
107 * Adds the external destination details to the list.
108 *
109 * @param externalDestination external destination details
110 */
111 public void addExternalDestination(OspfExternalDestination externalDestination) {
112 if (!externalDestinations.contains(externalDestination)) {
113 externalDestinations.add(externalDestination);
114 }
115 }
116
117 /**
118 * Reads from channel buffer and populate instance.
119 *
120 * @param channelBuffer channelBuffer instance
121 * @throws OspfParseException might throws exception while parsing buffer
122 */
123 public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {
124
125 try {
126 byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
127 channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
128 this.setNetworkMask(Ip4Address.valueOf(tempByteArray));
129
130 while (channelBuffer.readableBytes() >= OspfUtil.EXTERNAL_DESTINATION_LENGTH) {
131 OspfExternalDestination externalDestination = new OspfExternalDestination();
132
133 //E Bit - use to find type1 or type2
134 int eIsSet = channelBuffer.readByte();
135 if (eIsSet != 0) {
136 externalDestination.setType1orType2Metric(true);
137 } else {
138 externalDestination.setType1orType2Metric(false);
139 }
140 externalDestination.setMetric(channelBuffer.readUnsignedMedium());
141 tempByteArray = new byte[OspfUtil.FOUR_BYTES];
142 channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
143 externalDestination.setForwardingAddress(Ip4Address.valueOf(tempByteArray));
144 externalDestination.setExternalRouterTag(channelBuffer.readInt());
145
146 this.addExternalDestination(externalDestination);
147 }
148 } catch (Exception e) {
149 log.debug("Error::ExternalLSA:: {}", e.getMessage());
150 throw new OspfParseException(OspfErrorType.OSPF_MESSAGE_ERROR, OspfErrorType.BAD_MESSAGE);
151 }
152 }
153
154 /**
155 * Gets LSA as bytes.
156 *
157 * @return LSA as bytes.
158 * @throws OspfParseException might throws exception while parsing packet
159 */
160 public byte[] asBytes() throws OspfParseException {
161 byte[] lsaMessage = null;
162
163 byte[] lsaHeader = getLsaHeaderAsByteArray();
164 byte[] lsaBody = getLsaBodyAsByteArray();
165 lsaMessage = Bytes.concat(lsaHeader, lsaBody);
166
167 return lsaMessage;
168 }
169
170 /**
171 * Gets LSA body as byte array.
172 *
173 * @return byte array contains LSA body
174 * @throws OspfParseException might throws exception while parsing buffer
175 */
176 public byte[] getLsaBodyAsByteArray() throws OspfParseException {
177 List<Byte> bodyLst = new ArrayList<>();
178
179 try {
180 bodyLst.addAll(Bytes.asList(this.networkMask().toOctets()));
181
182 //add each OSPFExternalDestination details
183 for (OspfExternalDestination externalDest : externalDestinations) {
184 if (externalDest.isType1orType2Metric()) {
185 //add 1 followed by 7 zeros equals to decimal 128
186 bodyLst.add((byte) 128);
187 } else {
188 bodyLst.add((byte) 0);
189 }
190
191 bodyLst.addAll(Bytes.asList(OspfUtil.convertToThreeBytes(externalDest.metric())));
192 bodyLst.addAll(Bytes.asList(externalDest.forwardingAddress().toOctets()));
193 bodyLst.addAll(Bytes.asList(OspfUtil.convertToFourBytes(externalDest.externalRouterTag())));
194 }
195 } catch (Exception e) {
196 log.debug("Error::getLsrBodyAsByteArray {}", e.getMessage());
197 return Bytes.toArray(bodyLst);
198 }
199
200 return Bytes.toArray(bodyLst);
201 }
202
203 @Override
204 public OspfLsaType getOspfLsaType() {
205 return OspfLsaType.EXTERNAL_LSA;
206 }
207
208 @Override
209 public boolean equals(Object other) {
210 if (this == other) {
211 return true;
212 }
213 if (other == null || getClass() != other.getClass()) {
214 return false;
215 }
216 ExternalLsa that = (ExternalLsa) other;
217 return Objects.equal(networkMask, that.networkMask) &&
218 Objects.equal(externalDestinations, that.externalDestinations);
219 }
220
221 @Override
222 public int hashCode() {
223 return Objects.hashCode(networkMask, externalDestinations);
224 }
225
226 @Override
227 public String toString() {
228 return MoreObjects.toStringHelper(getClass())
229 .omitNullValues()
230 .add("networkMask", networkMask)
231 .add("externalDestinations", externalDestinations)
232 .toString();
233 }
234}