blob: 09317731dd21331dc4ceee84c6efa34141860b28 [file] [log] [blame]
Priyanka B3b695542015-10-14 17:16:27 +05301/*
2 * Copyright 2015 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 */
16
17package org.onosproject.bgpio.types;
18
19import java.util.LinkedList;
20import java.util.List;
Shashikanth VH510a8d82016-02-12 12:32:43 +053021import java.util.ListIterator;
Priyanka B3b695542015-10-14 17:16:27 +053022
23import org.jboss.netty.buffer.ChannelBuffer;
Shashikanth VH510a8d82016-02-12 12:32:43 +053024import org.jboss.netty.buffer.ChannelBuffers;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053025import org.onosproject.bgpio.exceptions.BgpParseException;
26import org.onosproject.bgpio.protocol.BgpLSNlri;
Shashikanth VH510a8d82016-02-12 12:32:43 +053027import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053028import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
29import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
Priyanka Be07ea4d2015-11-21 21:28:10 +053030import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
Priyanka B3b695542015-10-14 17:16:27 +053031import org.onosproject.bgpio.util.Constants;
32import org.onosproject.bgpio.util.Validation;
33import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
36import com.google.common.base.MoreObjects;
37
38/**
39 * Provides Implementation of MpUnReach Nlri BGP Path Attribute.
40 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053041public class MpUnReachNlri implements BgpValueType {
Priyanka B3b695542015-10-14 17:16:27 +053042
Priyanka Be07ea4d2015-11-21 21:28:10 +053043 private static final Logger log = LoggerFactory.getLogger(MpUnReachNlri.class);
Priyanka B3b695542015-10-14 17:16:27 +053044 public static final byte MPUNREACHNLRI_TYPE = 15;
45 public static final byte LINK_NLRITYPE = 2;
Shashikanth VH510a8d82016-02-12 12:32:43 +053046 public static final byte FLAGS = (byte) 0x90;
47 public static final short FLOW_SPEC_LEN = 240;
Priyanka B3b695542015-10-14 17:16:27 +053048 private boolean isMpUnReachNlri = false;
49 private final short afi;
50 private final byte safi;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053051 private final List<BgpLSNlri> mpUnReachNlri;
Priyanka B3b695542015-10-14 17:16:27 +053052 private final int length;
Shashikanth VH510a8d82016-02-12 12:32:43 +053053 private BgpFlowSpecDetails bgpFlowSpecInfo;
Priyanka B3b695542015-10-14 17:16:27 +053054
55 /**
56 * Constructor to initialize parameters.
57 *
58 * @param mpUnReachNlri MpUnReach Nlri attribute
59 * @param afi address family identifier
60 * @param safi subsequent address family identifier
61 * @param length of MpUnReachNlri
62 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053063 public MpUnReachNlri(List<BgpLSNlri> mpUnReachNlri, short afi, byte safi,
Priyanka B3b695542015-10-14 17:16:27 +053064 int length) {
65 this.mpUnReachNlri = mpUnReachNlri;
66 this.isMpUnReachNlri = true;
67 this.afi = afi;
68 this.safi = safi;
69 this.length = length;
70 }
71
Shashikanth VH510a8d82016-02-12 12:32:43 +053072 public MpUnReachNlri(BgpFlowSpecDetails bgpFlowSpecInfo, short afi, byte safi) {
73 this.mpUnReachNlri = null;
74 this.isMpUnReachNlri = true;
75 this.length = 0;
76 this.bgpFlowSpecInfo = bgpFlowSpecInfo;
77 this.afi = afi;
78 this.safi = safi;
79 }
80
81 /**
82 * Returns BGP flow specification info.
83 *
84 * @return BGP flow specification info
85 */
86 public BgpFlowSpecDetails bgpFlowSpecInfo() {
87 return this.bgpFlowSpecInfo;
88 }
89
Priyanka B3b695542015-10-14 17:16:27 +053090 /**
91 * Reads from ChannelBuffer and parses MpUnReachNlri.
92 *
93 * @param cb ChannelBuffer
94 * @return object of MpUnReachNlri
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053095 * @throws BgpParseException while parsing MpUnReachNlri
Priyanka B3b695542015-10-14 17:16:27 +053096 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053097 public static MpUnReachNlri read(ChannelBuffer cb) throws BgpParseException {
Priyanka B3b695542015-10-14 17:16:27 +053098 ChannelBuffer tempBuf = cb.copy();
99 Validation parseFlags = Validation.parseAttributeHeader(cb);
100 int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT
101 : parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE;
102 ChannelBuffer data = tempBuf.readBytes(len);
103
104 if (!parseFlags.getFirstBit() && parseFlags.getSecondBit()
105 && parseFlags.getThirdBit()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530106 throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
107 BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data);
Priyanka B3b695542015-10-14 17:16:27 +0530108 }
109
110 if (cb.readableBytes() < parseFlags.getLength()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530111 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
112 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, parseFlags.getLength());
Priyanka B3b695542015-10-14 17:16:27 +0530113 }
114
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530115 LinkedList<BgpLSNlri> mpUnReachNlri = new LinkedList<>();
116 BgpLSNlri bgpLSNlri = null;
Priyanka B3b695542015-10-14 17:16:27 +0530117 short afi = 0;
118 byte safi = 0;
119 ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength());
120 while (tempCb.readableBytes() > 0) {
121 afi = tempCb.readShort();
122 safi = tempCb.readByte();
123
124 //Supporting only for AFI 16388 / SAFI 71
125 if ((afi == Constants.AFI_VALUE) && (safi == Constants.SAFI_VALUE)
126 || (afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) {
127 while (tempCb.readableBytes() > 0) {
128 short nlriType = tempCb.readShort();
129 short totNlriLen = tempCb.readShort();
130 if (tempCb.readableBytes() < totNlriLen) {
131 Validation.validateLen(
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530132 BgpErrorType.UPDATE_MESSAGE_ERROR,
133 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
Priyanka B3b695542015-10-14 17:16:27 +0530134 }
135 tempBuf = tempCb.readBytes(totNlriLen);
136 switch (nlriType) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530137 case BgpNodeLSNlriVer4.NODE_NLRITYPE:
138 bgpLSNlri = BgpNodeLSNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530139 break;
Priyanka Be07ea4d2015-11-21 21:28:10 +0530140 case BgpLinkLsNlriVer4.LINK_NLRITYPE:
141 bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530142 break;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530143 case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE:
144 bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi,
Priyanka B3b695542015-10-14 17:16:27 +0530145 safi);
146 break;
147 default:
148 log.debug("nlriType not supported" + nlriType);
Shashikanth VH510a8d82016-02-12 12:32:43 +0530149 break;
Priyanka B3b695542015-10-14 17:16:27 +0530150 }
151 mpUnReachNlri.add(bgpLSNlri);
152 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530153 } else if ((afi == Constants.AFI_FLOWSPEC_VALUE)
154 && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
155 || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
156 List<BgpValueType> flowSpecComponents = new LinkedList<>();
157 BgpValueType flowSpecComponent = null;
158
159 short totNlriLen = tempCb.getByte(tempCb.readerIndex());
160 if (totNlriLen >= FLOW_SPEC_LEN) {
161 totNlriLen = tempCb.readShort();
162 } else {
163 totNlriLen = tempCb.readByte();
164 }
165 if (tempCb.readableBytes() < totNlriLen) {
166 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
167 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
168 }
169 tempBuf = tempCb.readBytes(totNlriLen);
170 while (tempBuf.readableBytes() > 0) {
171 short type = tempBuf.readByte();
172 switch (type) {
173 case Constants.BGP_FLOWSPEC_DST_PREFIX:
174 flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
175 break;
176 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
177 flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
178 break;
179 case Constants.BGP_FLOWSPEC_IP_PROTO:
180 flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
181 break;
182 case Constants.BGP_FLOWSPEC_PORT:
183 flowSpecComponent = BgpFsPortNum.read(tempBuf);
184 break;
185 case Constants.BGP_FLOWSPEC_DST_PORT:
186 flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
187 break;
188 case Constants.BGP_FLOWSPEC_SRC_PORT:
189 flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
190 break;
191 case Constants.BGP_FLOWSPEC_ICMP_TP:
192 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
193 break;
194 case Constants.BGP_FLOWSPEC_ICMP_CD:
195 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
196 break;
197 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
198 flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
199 break;
200 case Constants.BGP_FLOWSPEC_PCK_LEN:
201 flowSpecComponent = BgpFsPacketLength.read(tempBuf);
202 break;
203 case Constants.BGP_FLOWSPEC_DSCP:
204 flowSpecComponent = BgpFsDscpValue.read(tempBuf);
205 break;
206 case Constants.BGP_FLOWSPEC_FRAGMENT:
207 flowSpecComponent = BgpFsFragment.read(tempBuf);
208 break;
209 default:
210 log.debug("flow spec type not supported" + type);
211 break;
212 }
213 flowSpecComponents.add(flowSpecComponent);
214 }
215 return new MpUnReachNlri(new BgpFlowSpecDetails(flowSpecComponents), afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530216 } else {
217 //TODO: check with the values got from capability
Shashikanth VH510a8d82016-02-12 12:32:43 +0530218 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
Priyanka B3b695542015-10-14 17:16:27 +0530219 }
220 }
221 return new MpUnReachNlri(mpUnReachNlri, afi, safi,
222 parseFlags.getLength());
223 }
224
225 @Override
226 public short getType() {
227 return MPUNREACHNLRI_TYPE;
228 }
229
230 /**
231 * Returns SAFI.
232 *
233 * @return SAFI
234 */
235 public byte safi() {
236 return this.safi;
237 }
238
239 /**
240 * Returns AFI.
241 *
242 * @return AFI
243 */
244 public short afi() {
245 return this.afi;
246 }
247
248 /**
249 * Returns list of MpUnReach Nlri.
250 *
251 * @return list of MpUnReach Nlri
252 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530253 public List<BgpLSNlri> mpUnReachNlri() {
Priyanka B3b695542015-10-14 17:16:27 +0530254 return this.mpUnReachNlri;
255 }
256
257 /**
258 * Returns whether MpReachNlri is present.
259 *
260 * @return whether MpReachNlri is present
261 */
262 public boolean isMpUnReachNlriSet() {
263 return this.isMpUnReachNlri;
264 }
265
266 /**
267 * Returns length of MpUnReach.
268 *
269 * @return length of MpUnReach
270 */
271 public int mpUnReachNlriLen() {
272 return this.length;
273 }
274
275 @Override
276 public int write(ChannelBuffer cb) {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530277 int iLenStartIndex = cb.writerIndex();
278 if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE) ||
279 (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
280
281 cb.writeByte(FLAGS);
282 cb.writeByte(MPUNREACHNLRI_TYPE);
283
284 int mpUnReachIndx = cb.writerIndex();
285 cb.writeShort(0);
286
287 cb.writeShort(afi);
288 cb.writeByte(safi);
289
290 if (bgpFlowSpecInfo.routeDistinguisher() != null) {
291 cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
292 }
293
294 ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
295 int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
296
297 List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
298 ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
299 while (listIterator.hasNext()) {
300 BgpValueType tlv = listIterator.next();
301 switch (tlv.getType()) {
302 case Constants.BGP_FLOWSPEC_DST_PREFIX:
303 BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
304 fsDstPrefix.write(flowSpecTmpBuff);
305 break;
306 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
307 BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
308 fsSrcPrefix.write(flowSpecTmpBuff);
309 break;
310 case Constants.BGP_FLOWSPEC_IP_PROTO:
311 BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
312 fsIpProtocol.write(flowSpecTmpBuff);
313 break;
314 case Constants.BGP_FLOWSPEC_PORT:
315 BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
316 fsPortNum.write(flowSpecTmpBuff);
317 break;
318 case Constants.BGP_FLOWSPEC_DST_PORT:
319 BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
320 fsDstPortNum.write(flowSpecTmpBuff);
321 break;
322 case Constants.BGP_FLOWSPEC_SRC_PORT:
323 BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
324 fsSrcPortNum.write(flowSpecTmpBuff);
325 break;
326 case Constants.BGP_FLOWSPEC_ICMP_TP:
327 BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
328 fsIcmpType.write(flowSpecTmpBuff);
329 break;
330 case Constants.BGP_FLOWSPEC_ICMP_CD:
331 BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
332 fsIcmpCode.write(flowSpecTmpBuff);
333 break;
334 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
335 BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
336 fsTcpFlags.write(flowSpecTmpBuff);
337 break;
338 case Constants.BGP_FLOWSPEC_PCK_LEN:
339 BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
340 fsPacketLen.write(flowSpecTmpBuff);
341 break;
342 case Constants.BGP_FLOWSPEC_DSCP:
343 BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
344 fsDscpVal.write(flowSpecTmpBuff);
345 break;
346 case Constants.BGP_FLOWSPEC_FRAGMENT:
347 BgpFsFragment fsFragment = (BgpFsFragment) tlv;
348 fsFragment.write(flowSpecTmpBuff);
349 break;
350 default:
351 }
352 }
353
354 int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
355 if (len >= FLOW_SPEC_LEN) {
356 cb.writeShort(len);
357 } else {
358 cb.writeByte(len);
359 }
360 //Copy from bynamic buffer to channel buffer
361 cb.writeBytes(flowSpecTmpBuff);
362
363 int fsNlriLen = cb.writerIndex() - mpUnReachIndx;
364 cb.setShort(mpUnReachIndx, (short) (fsNlriLen - 2));
365 }
366
367 return cb.writerIndex() - iLenStartIndex;
Priyanka B3b695542015-10-14 17:16:27 +0530368 }
369
370 @Override
Priyanka B02040732015-11-29 11:30:29 +0530371 public int compareTo(Object o) {
372 // TODO Auto-generated method stub
373 return 0;
374 }
375
376 @Override
Priyanka B3b695542015-10-14 17:16:27 +0530377 public String toString() {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530378 return MoreObjects.toStringHelper(getClass()).omitNullValues()
Priyanka B3b695542015-10-14 17:16:27 +0530379 .add("mpReachNlri", mpUnReachNlri)
Shashikanth VH510a8d82016-02-12 12:32:43 +0530380 .add("bgpFlowSpecInfo", bgpFlowSpecInfo)
Priyanka B3b695542015-10-14 17:16:27 +0530381 .add("afi", afi)
382 .add("safi", safi)
383 .add("length", length)
384 .toString();
385 }
386}