blob: f21a6be8c285d84dd3c8d94ff5db94f81d54565c [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<>();
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530157 RouteDistinguisher routeDistinguisher = null;
Shashikanth VH58260662016-02-13 01:12:02 +0530158 if (tempCb.readableBytes() > 0) {
159 BgpValueType flowSpecComponent = null;
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530160
161 if (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE) {
162 routeDistinguisher = new RouteDistinguisher();
163 routeDistinguisher = RouteDistinguisher.read(tempCb);
164 }
Shashikanth VH58260662016-02-13 01:12:02 +0530165 short totNlriLen = tempCb.getByte(tempCb.readerIndex());
166 if (totNlriLen >= FLOW_SPEC_LEN) {
167 totNlriLen = tempCb.readShort();
168 } else {
169 totNlriLen = tempCb.readByte();
Shashikanth VH510a8d82016-02-12 12:32:43 +0530170 }
Shashikanth VH58260662016-02-13 01:12:02 +0530171 if (tempCb.readableBytes() < totNlriLen) {
172 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
173 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
174 }
175 tempBuf = tempCb.readBytes(totNlriLen);
176 while (tempBuf.readableBytes() > 0) {
177 short type = tempBuf.readByte();
178 switch (type) {
179 case Constants.BGP_FLOWSPEC_DST_PREFIX:
180 flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
181 break;
182 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
183 flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
184 break;
185 case Constants.BGP_FLOWSPEC_IP_PROTO:
186 flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
187 break;
188 case Constants.BGP_FLOWSPEC_PORT:
189 flowSpecComponent = BgpFsPortNum.read(tempBuf);
190 break;
191 case Constants.BGP_FLOWSPEC_DST_PORT:
192 flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
193 break;
194 case Constants.BGP_FLOWSPEC_SRC_PORT:
195 flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
196 break;
197 case Constants.BGP_FLOWSPEC_ICMP_TP:
198 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
199 break;
200 case Constants.BGP_FLOWSPEC_ICMP_CD:
201 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
202 break;
203 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
204 flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
205 break;
206 case Constants.BGP_FLOWSPEC_PCK_LEN:
207 flowSpecComponent = BgpFsPacketLength.read(tempBuf);
208 break;
209 case Constants.BGP_FLOWSPEC_DSCP:
210 flowSpecComponent = BgpFsDscpValue.read(tempBuf);
211 break;
212 case Constants.BGP_FLOWSPEC_FRAGMENT:
213 flowSpecComponent = BgpFsFragment.read(tempBuf);
214 break;
215 default:
216 log.debug("flow spec type not supported" + type);
217 break;
218 }
219 flowSpecComponents.add(flowSpecComponent);
220 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530221 }
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530222 BgpFlowSpecDetails flowSpecDetails = new BgpFlowSpecDetails(flowSpecComponents);
223 flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
224 return new MpUnReachNlri(flowSpecDetails, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530225 } else {
226 //TODO: check with the values got from capability
Shashikanth VH510a8d82016-02-12 12:32:43 +0530227 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
Priyanka B3b695542015-10-14 17:16:27 +0530228 }
229 }
230 return new MpUnReachNlri(mpUnReachNlri, afi, safi,
231 parseFlags.getLength());
232 }
233
234 @Override
235 public short getType() {
236 return MPUNREACHNLRI_TYPE;
237 }
238
239 /**
240 * Returns SAFI.
241 *
242 * @return SAFI
243 */
244 public byte safi() {
245 return this.safi;
246 }
247
248 /**
249 * Returns AFI.
250 *
251 * @return AFI
252 */
253 public short afi() {
254 return this.afi;
255 }
256
257 /**
258 * Returns list of MpUnReach Nlri.
259 *
260 * @return list of MpUnReach Nlri
261 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530262 public List<BgpLSNlri> mpUnReachNlri() {
Priyanka B3b695542015-10-14 17:16:27 +0530263 return this.mpUnReachNlri;
264 }
265
266 /**
267 * Returns whether MpReachNlri is present.
268 *
269 * @return whether MpReachNlri is present
270 */
271 public boolean isMpUnReachNlriSet() {
272 return this.isMpUnReachNlri;
273 }
274
275 /**
276 * Returns length of MpUnReach.
277 *
278 * @return length of MpUnReach
279 */
280 public int mpUnReachNlriLen() {
281 return this.length;
282 }
283
284 @Override
285 public int write(ChannelBuffer cb) {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530286 int iLenStartIndex = cb.writerIndex();
287 if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE) ||
288 (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
289
290 cb.writeByte(FLAGS);
291 cb.writeByte(MPUNREACHNLRI_TYPE);
292
293 int mpUnReachIndx = cb.writerIndex();
294 cb.writeShort(0);
295
296 cb.writeShort(afi);
297 cb.writeByte(safi);
298
299 if (bgpFlowSpecInfo.routeDistinguisher() != null) {
300 cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
301 }
302
303 ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
304 int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
305
306 List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
307 ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
308 while (listIterator.hasNext()) {
309 BgpValueType tlv = listIterator.next();
310 switch (tlv.getType()) {
311 case Constants.BGP_FLOWSPEC_DST_PREFIX:
312 BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
313 fsDstPrefix.write(flowSpecTmpBuff);
314 break;
315 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
316 BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
317 fsSrcPrefix.write(flowSpecTmpBuff);
318 break;
319 case Constants.BGP_FLOWSPEC_IP_PROTO:
320 BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
321 fsIpProtocol.write(flowSpecTmpBuff);
322 break;
323 case Constants.BGP_FLOWSPEC_PORT:
324 BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
325 fsPortNum.write(flowSpecTmpBuff);
326 break;
327 case Constants.BGP_FLOWSPEC_DST_PORT:
328 BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
329 fsDstPortNum.write(flowSpecTmpBuff);
330 break;
331 case Constants.BGP_FLOWSPEC_SRC_PORT:
332 BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
333 fsSrcPortNum.write(flowSpecTmpBuff);
334 break;
335 case Constants.BGP_FLOWSPEC_ICMP_TP:
336 BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
337 fsIcmpType.write(flowSpecTmpBuff);
338 break;
339 case Constants.BGP_FLOWSPEC_ICMP_CD:
340 BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
341 fsIcmpCode.write(flowSpecTmpBuff);
342 break;
343 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
344 BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
345 fsTcpFlags.write(flowSpecTmpBuff);
346 break;
347 case Constants.BGP_FLOWSPEC_PCK_LEN:
348 BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
349 fsPacketLen.write(flowSpecTmpBuff);
350 break;
351 case Constants.BGP_FLOWSPEC_DSCP:
352 BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
353 fsDscpVal.write(flowSpecTmpBuff);
354 break;
355 case Constants.BGP_FLOWSPEC_FRAGMENT:
356 BgpFsFragment fsFragment = (BgpFsFragment) tlv;
357 fsFragment.write(flowSpecTmpBuff);
358 break;
359 default:
360 }
361 }
362
363 int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
364 if (len >= FLOW_SPEC_LEN) {
365 cb.writeShort(len);
366 } else {
367 cb.writeByte(len);
368 }
369 //Copy from bynamic buffer to channel buffer
370 cb.writeBytes(flowSpecTmpBuff);
371
372 int fsNlriLen = cb.writerIndex() - mpUnReachIndx;
373 cb.setShort(mpUnReachIndx, (short) (fsNlriLen - 2));
374 }
375
376 return cb.writerIndex() - iLenStartIndex;
Priyanka B3b695542015-10-14 17:16:27 +0530377 }
378
379 @Override
Priyanka B02040732015-11-29 11:30:29 +0530380 public int compareTo(Object o) {
381 // TODO Auto-generated method stub
382 return 0;
383 }
384
385 @Override
Priyanka B3b695542015-10-14 17:16:27 +0530386 public String toString() {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530387 return MoreObjects.toStringHelper(getClass()).omitNullValues()
Priyanka B3b695542015-10-14 17:16:27 +0530388 .add("mpReachNlri", mpUnReachNlri)
Shashikanth VH510a8d82016-02-12 12:32:43 +0530389 .add("bgpFlowSpecInfo", bgpFlowSpecInfo)
Priyanka B3b695542015-10-14 17:16:27 +0530390 .add("afi", afi)
391 .add("safi", safi)
392 .add("length", length)
393 .toString();
394 }
395}