blob: 3a108e97bbe53c5986148e143f7d27f5d02cc494 [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.net.InetAddress;
20import java.util.LinkedList;
21import java.util.List;
Shashikanth VH510a8d82016-02-12 12:32:43 +053022import java.util.ListIterator;
Priyanka B3b695542015-10-14 17:16:27 +053023
24import org.jboss.netty.buffer.ChannelBuffer;
Shashikanth VH510a8d82016-02-12 12:32:43 +053025import org.jboss.netty.buffer.ChannelBuffers;
Priyanka B3b695542015-10-14 17:16:27 +053026import org.onlab.packet.Ip4Address;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053027import org.onosproject.bgpio.exceptions.BgpParseException;
28import org.onosproject.bgpio.protocol.BgpLSNlri;
Shashikanth VH510a8d82016-02-12 12:32:43 +053029import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053030import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
31import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
Priyanka Be07ea4d2015-11-21 21:28:10 +053032import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
Priyanka B3b695542015-10-14 17:16:27 +053033import org.onosproject.bgpio.util.Constants;
34import org.onosproject.bgpio.util.Validation;
35import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
38import com.google.common.base.MoreObjects;
39
40/*
41 * Provides Implementation of MpReach Nlri BGP Path Attribute.
42 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053043public class MpReachNlri implements BgpValueType {
Priyanka B3b695542015-10-14 17:16:27 +053044
45 private static final Logger log = LoggerFactory.getLogger(MpReachNlri.class);
Priyanka B3b695542015-10-14 17:16:27 +053046 public static final byte MPREACHNLRI_TYPE = 14;
47 public static final byte LINK_NLRITYPE = 2;
Shashikanth VH510a8d82016-02-12 12:32:43 +053048 public static final byte FLAGS = (byte) 0x90;
49 public static final short FLOW_SPEC_LEN = 240;
Priyanka B3b695542015-10-14 17:16:27 +053050 private boolean isMpReachNlri = false;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053051 private final List<BgpLSNlri> mpReachNlri;
Priyanka B3b695542015-10-14 17:16:27 +053052 private final int length;
53 private final short afi;
54 private final byte safi;
55 private final Ip4Address ipNextHop;
Shashikanth VH510a8d82016-02-12 12:32:43 +053056 private BgpFlowSpecDetails bgpFlowSpecInfo;
Priyanka B3b695542015-10-14 17:16:27 +053057
58 /**
59 * Constructor to initialize parameters.
60 *
61 * @param mpReachNlri MpReach Nlri attribute
62 * @param afi address family identifier
63 * @param safi subsequent address family identifier
64 * @param ipNextHop nexthop IpAddress
65 * @param length of MpReachNlri
66 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053067 public MpReachNlri(List<BgpLSNlri> mpReachNlri, short afi, byte safi, Ip4Address ipNextHop, int length) {
Priyanka B3b695542015-10-14 17:16:27 +053068 this.mpReachNlri = mpReachNlri;
69 this.isMpReachNlri = true;
70 this.ipNextHop = ipNextHop;
71 this.afi = afi;
72 this.safi = safi;
73 this.length = length;
74 }
75
Shashikanth VH510a8d82016-02-12 12:32:43 +053076 public MpReachNlri(BgpFlowSpecDetails bgpFlowSpecInfo, short afi, byte safi) {
77 this.mpReachNlri = null;
78 this.isMpReachNlri = true;
79 this.length = 0;
80 this.ipNextHop = null;
81 this.bgpFlowSpecInfo = bgpFlowSpecInfo;
82 this.afi = afi;
83 this.safi = safi;
84 }
85
Priyanka B3b695542015-10-14 17:16:27 +053086 /**
87 * Returns whether MpReachNlri is present.
88 *
89 * @return whether MpReachNlri is present
90 */
91 public boolean isMpReachNlriSet() {
92 return this.isMpReachNlri;
93 }
94
95 /**
96 * Returns list of MpReach Nlri.
97 *
98 * @return list of MpReach Nlri
99 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530100 public List<BgpLSNlri> mpReachNlri() {
Priyanka B3b695542015-10-14 17:16:27 +0530101 return this.mpReachNlri;
102 }
103
104 /**
105 * Returns length of MpReachNlri.
106 *
107 * @return length of MpReachNlri
108 */
109 public int mpReachNlriLen() {
110 return this.length;
111 }
112
113 /**
Shashikanth VH510a8d82016-02-12 12:32:43 +0530114 * Returns BGP flow specification info.
115 *
116 * @return BGP flow specification info
117 */
118 public BgpFlowSpecDetails bgpFlowSpecInfo() {
119 return this.bgpFlowSpecInfo;
120 }
121
122 /**
Priyanka B3b695542015-10-14 17:16:27 +0530123 * Reads from ChannelBuffer and parses MpReachNlri.
124 *
125 * @param cb channelBuffer
126 * @return object of MpReachNlri
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530127 * @throws BgpParseException while parsing MpReachNlri
Priyanka B3b695542015-10-14 17:16:27 +0530128 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530129 public static MpReachNlri read(ChannelBuffer cb) throws BgpParseException {
Priyanka B3b695542015-10-14 17:16:27 +0530130 ChannelBuffer tempBuf = cb.copy();
131 Validation parseFlags = Validation.parseAttributeHeader(cb);
132 int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT :
133 parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE;
134 ChannelBuffer data = tempBuf.readBytes(len);
135
136 if (cb.readableBytes() < parseFlags.getLength()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530137 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
Priyanka B3b695542015-10-14 17:16:27 +0530138 parseFlags.getLength());
139 }
140 if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() && parseFlags.getThirdBit()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530141 throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data);
Priyanka B3b695542015-10-14 17:16:27 +0530142 }
143
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530144 BgpLSNlri bgpLSNlri = null;
145 List<BgpLSNlri> mpReachNlri = new LinkedList<>();
Priyanka B3b695542015-10-14 17:16:27 +0530146 ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength());
147 short afi = 0;
148 byte safi = 0;
149 Ip4Address ipNextHop = null;
150 while (tempCb.readableBytes() > 0) {
151 afi = tempCb.readShort();
152 safi = tempCb.readByte();
153
154 //Supporting for AFI 16388 / SAFI 71 and VPN AFI 16388 / SAFI 128
155 if ((afi == Constants.AFI_VALUE) && (safi == Constants.SAFI_VALUE) || (afi == Constants.AFI_VALUE)
156 && (safi == Constants.VPN_SAFI_VALUE)) {
157 byte nextHopLen = tempCb.readByte();
Vidyashree Rama7ba6b4c2015-11-30 17:20:22 +0530158 InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
Priyanka B3b695542015-10-14 17:16:27 +0530159 if (ipAddress.isMulticastAddress()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530160 throw new BgpParseException("Multicast not supported");
Priyanka B3b695542015-10-14 17:16:27 +0530161 }
162 ipNextHop = Ip4Address.valueOf(ipAddress);
163 byte reserved = tempCb.readByte();
164
165 while (tempCb.readableBytes() > 0) {
166 short nlriType = tempCb.readShort();
167 short totNlriLen = tempCb.readShort();
168 if (tempCb.readableBytes() < totNlriLen) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530169 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
170 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
Priyanka B3b695542015-10-14 17:16:27 +0530171 }
172 tempBuf = tempCb.readBytes(totNlriLen);
173 switch (nlriType) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530174 case BgpNodeLSNlriVer4.NODE_NLRITYPE:
175 bgpLSNlri = BgpNodeLSNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530176 break;
Priyanka Be07ea4d2015-11-21 21:28:10 +0530177 case BgpLinkLsNlriVer4.LINK_NLRITYPE:
178 bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530179 break;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530180 case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE:
181 bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530182 break;
183 default:
184 log.debug("nlriType not supported" + nlriType);
185 }
186 mpReachNlri.add(bgpLSNlri);
187 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530188 } else if ((afi == Constants.AFI_FLOWSPEC_VALUE)
189 && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
190 || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
191 List<BgpValueType> flowSpecComponents = new LinkedList<>();
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530192 RouteDistinguisher routeDistinguisher = null;
Shashikanth VH58260662016-02-13 01:12:02 +0530193 if (tempCb.readableBytes() > 0) {
194 BgpValueType flowSpecComponent = null;
Shashikanth VH510a8d82016-02-12 12:32:43 +0530195
Shashikanth VH58260662016-02-13 01:12:02 +0530196 byte nextHopLen = tempCb.readByte();
197 if (nextHopLen > 0) {
198 InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
199 if (ipAddress.isMulticastAddress()) {
200 throw new BgpParseException("Multicast not supported");
201 }
202 ipNextHop = Ip4Address.valueOf(ipAddress);
Shashikanth VH510a8d82016-02-12 12:32:43 +0530203 }
Shashikanth VH58260662016-02-13 01:12:02 +0530204
205 byte reserved = tempCb.readByte();
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530206
207 if (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE) {
208 routeDistinguisher = new RouteDistinguisher();
209 routeDistinguisher = RouteDistinguisher.read(tempCb);
210 }
Shashikanth VH58260662016-02-13 01:12:02 +0530211 short totNlriLen = tempCb.getByte(tempCb.readerIndex());
212 if (totNlriLen >= FLOW_SPEC_LEN) {
213 totNlriLen = tempCb.readShort();
214 } else {
215 totNlriLen = tempCb.readByte();
216 }
217 if (tempCb.readableBytes() < totNlriLen) {
218 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
219 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
220 }
221 tempBuf = tempCb.readBytes(totNlriLen);
222 while (tempBuf.readableBytes() > 0) {
223 short type = tempBuf.readByte();
224 switch (type) {
225 case Constants.BGP_FLOWSPEC_DST_PREFIX:
226 flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
227 break;
228 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
229 flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
230 break;
231 case Constants.BGP_FLOWSPEC_IP_PROTO:
232 flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
233 break;
234 case Constants.BGP_FLOWSPEC_PORT:
235 flowSpecComponent = BgpFsPortNum.read(tempBuf);
236 break;
237 case Constants.BGP_FLOWSPEC_DST_PORT:
238 flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
239 break;
240 case Constants.BGP_FLOWSPEC_SRC_PORT:
241 flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
242 break;
243 case Constants.BGP_FLOWSPEC_ICMP_TP:
244 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
245 break;
246 case Constants.BGP_FLOWSPEC_ICMP_CD:
Shashikanth VH03205d22016-02-19 22:48:08 +0530247 flowSpecComponent = BgpFsIcmpCode.read(tempBuf);
Shashikanth VH58260662016-02-13 01:12:02 +0530248 break;
249 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
250 flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
251 break;
252 case Constants.BGP_FLOWSPEC_PCK_LEN:
253 flowSpecComponent = BgpFsPacketLength.read(tempBuf);
254 break;
255 case Constants.BGP_FLOWSPEC_DSCP:
256 flowSpecComponent = BgpFsDscpValue.read(tempBuf);
257 break;
258 case Constants.BGP_FLOWSPEC_FRAGMENT:
259 flowSpecComponent = BgpFsFragment.read(tempBuf);
260 break;
261 default:
262 log.debug("flow spec type not supported" + type);
263 break;
264 }
265 flowSpecComponents.add(flowSpecComponent);
266 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530267 }
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530268 BgpFlowSpecDetails flowSpecDetails = new BgpFlowSpecDetails(flowSpecComponents);
269 flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
270 return new MpReachNlri(flowSpecDetails, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530271 } else {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530272 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
Priyanka B3b695542015-10-14 17:16:27 +0530273 }
274 }
275 return new MpReachNlri(mpReachNlri, afi, safi, ipNextHop, parseFlags.getLength());
276 }
277
278 @Override
279 public short getType() {
280 return MPREACHNLRI_TYPE;
281 }
282
283 /**
284 * Returns AFI.
285 *
286 * @return AFI
287 */
288 public short afi() {
289 return this.afi;
290 }
291
292 /**
293 * Returns Nexthop IpAddress.
294 *
295 * @return Nexthop IpAddress
296 */
297 public Ip4Address nexthop4() {
298 return this.ipNextHop;
299 }
300
301 /**
302 * Returns SAFI.
303 *
304 * @return SAFI
305 */
306 public byte safi() {
307 return this.safi;
308 }
309
310 @Override
311 public int write(ChannelBuffer cb) {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530312 int iLenStartIndex = cb.writerIndex();
313 if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
314 || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
315
316 cb.writeByte(FLAGS);
317 cb.writeByte(MPREACHNLRI_TYPE);
318
319 int mpReachDataIndx = cb.writerIndex();
320 cb.writeShort(0);
321
322 cb.writeShort(afi);
323 cb.writeByte(safi);
324 //next hop address
325 cb.writeByte(0);
326 //sub network points of attachment
327 cb.writeByte(0);
328
329 if (bgpFlowSpecInfo.routeDistinguisher() != null) {
330 cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
331 }
332
333 ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
334 int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
335
336 List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
337 ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
338
339 while (listIterator.hasNext()) {
340 BgpValueType tlv = listIterator.next();
341 switch (tlv.getType()) {
342 case Constants.BGP_FLOWSPEC_DST_PREFIX:
343 BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
344 fsDstPrefix.write(flowSpecTmpBuff);
345 break;
346 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
347 BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
348 fsSrcPrefix.write(flowSpecTmpBuff);
349 break;
350 case Constants.BGP_FLOWSPEC_IP_PROTO:
351 BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
352 fsIpProtocol.write(flowSpecTmpBuff);
353 break;
354 case Constants.BGP_FLOWSPEC_PORT:
355 BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
356 fsPortNum.write(flowSpecTmpBuff);
357 break;
358 case Constants.BGP_FLOWSPEC_DST_PORT:
359 BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
360 fsDstPortNum.write(flowSpecTmpBuff);
361 break;
362 case Constants.BGP_FLOWSPEC_SRC_PORT:
363 BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
364 fsSrcPortNum.write(flowSpecTmpBuff);
365 break;
366 case Constants.BGP_FLOWSPEC_ICMP_TP:
367 BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
368 fsIcmpType.write(flowSpecTmpBuff);
369 break;
370 case Constants.BGP_FLOWSPEC_ICMP_CD:
371 BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
372 fsIcmpCode.write(flowSpecTmpBuff);
373 break;
374 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
375 BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
376 fsTcpFlags.write(flowSpecTmpBuff);
377 break;
378 case Constants.BGP_FLOWSPEC_PCK_LEN:
379 BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
380 fsPacketLen.write(flowSpecTmpBuff);
381 break;
382 case Constants.BGP_FLOWSPEC_DSCP:
383 BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
384 fsDscpVal.write(flowSpecTmpBuff);
385 break;
386 case Constants.BGP_FLOWSPEC_FRAGMENT:
387 BgpFsFragment fsFragment = (BgpFsFragment) tlv;
388 fsFragment.write(flowSpecTmpBuff);
389 break;
390 default:
391 break;
392 }
393 }
394
395 /* RFC 5575: section 4, If the NLRI length value is smaller than 240 (0xf0 hex), the length
396 field can be encoded as a single octet. Otherwise, it is encoded as
397 an extended-length 2-octet values */
398 int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
399 if (len >= FLOW_SPEC_LEN) {
400 cb.writeShort(len);
401 } else {
402 cb.writeByte(len);
403 }
404 //Copy from bynamic buffer to channel buffer
405 cb.writeBytes(flowSpecTmpBuff);
406
407 int fsNlriLen = cb.writerIndex() - mpReachDataIndx;
408 cb.setShort(mpReachDataIndx, (short) (fsNlriLen - 2));
409
410 }
411
412 return cb.writerIndex() - iLenStartIndex;
Priyanka B3b695542015-10-14 17:16:27 +0530413 }
414
415 @Override
416 public String toString() {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530417 return MoreObjects.toStringHelper(getClass()).omitNullValues()
Priyanka B3b695542015-10-14 17:16:27 +0530418 .add("mpReachNlri", mpReachNlri)
Shashikanth VH510a8d82016-02-12 12:32:43 +0530419 .add("bgpFlowSpecInfo", bgpFlowSpecInfo)
Priyanka B3b695542015-10-14 17:16:27 +0530420 .add("afi", afi)
421 .add("safi", safi)
422 .add("ipNextHop", ipNextHop)
423 .add("length", length)
424 .toString();
425 }
Priyanka B02040732015-11-29 11:30:29 +0530426
427 @Override
428 public int compareTo(Object o) {
429 // TODO Auto-generated method stub
430 return 0;
431 }
Priyanka B3b695542015-10-14 17:16:27 +0530432}