blob: 49fc6a77bdd9b15f047791906188ddb4d9a51eab [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<>();
192 BgpValueType flowSpecComponent = null;
193
194 byte nextHopLen = tempCb.readByte();
195 if (nextHopLen > 0) {
196 InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
197 if (ipAddress.isMulticastAddress()) {
198 throw new BgpParseException("Multicast not supported");
199 }
200 ipNextHop = Ip4Address.valueOf(ipAddress);
201 }
202
203 byte reserved = tempCb.readByte();
204 short totNlriLen = tempCb.getByte(tempCb.readerIndex());
205 if (totNlriLen >= FLOW_SPEC_LEN) {
206 totNlriLen = tempCb.readShort();
207 } else {
208 totNlriLen = tempCb.readByte();
209 }
210 if (tempCb.readableBytes() < totNlriLen) {
211 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
212 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
213 }
214 tempBuf = tempCb.readBytes(totNlriLen);
215 while (tempBuf.readableBytes() > 0) {
216 short type = tempBuf.readByte();
217 switch (type) {
218 case Constants.BGP_FLOWSPEC_DST_PREFIX:
219 flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
220 break;
221 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
222 flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
223 break;
224 case Constants.BGP_FLOWSPEC_IP_PROTO:
225 flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
226 break;
227 case Constants.BGP_FLOWSPEC_PORT:
228 flowSpecComponent = BgpFsPortNum.read(tempBuf);
229 break;
230 case Constants.BGP_FLOWSPEC_DST_PORT:
231 flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
232 break;
233 case Constants.BGP_FLOWSPEC_SRC_PORT:
234 flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
235 break;
236 case Constants.BGP_FLOWSPEC_ICMP_TP:
237 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
238 break;
239 case Constants.BGP_FLOWSPEC_ICMP_CD:
240 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
241 break;
242 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
243 flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
244 break;
245 case Constants.BGP_FLOWSPEC_PCK_LEN:
246 flowSpecComponent = BgpFsPacketLength.read(tempBuf);
247 break;
248 case Constants.BGP_FLOWSPEC_DSCP:
249 flowSpecComponent = BgpFsDscpValue.read(tempBuf);
250 break;
251 case Constants.BGP_FLOWSPEC_FRAGMENT:
252 flowSpecComponent = BgpFsFragment.read(tempBuf);
253 break;
254 default:
255 log.debug("flow spec type not supported" + type);
256 break;
257 }
258 flowSpecComponents.add(flowSpecComponent);
259 }
260 return new MpReachNlri(new BgpFlowSpecDetails(flowSpecComponents), afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530261 } else {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530262 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
Priyanka B3b695542015-10-14 17:16:27 +0530263 }
264 }
265 return new MpReachNlri(mpReachNlri, afi, safi, ipNextHop, parseFlags.getLength());
266 }
267
268 @Override
269 public short getType() {
270 return MPREACHNLRI_TYPE;
271 }
272
273 /**
274 * Returns AFI.
275 *
276 * @return AFI
277 */
278 public short afi() {
279 return this.afi;
280 }
281
282 /**
283 * Returns Nexthop IpAddress.
284 *
285 * @return Nexthop IpAddress
286 */
287 public Ip4Address nexthop4() {
288 return this.ipNextHop;
289 }
290
291 /**
292 * Returns SAFI.
293 *
294 * @return SAFI
295 */
296 public byte safi() {
297 return this.safi;
298 }
299
300 @Override
301 public int write(ChannelBuffer cb) {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530302 int iLenStartIndex = cb.writerIndex();
303 if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
304 || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
305
306 cb.writeByte(FLAGS);
307 cb.writeByte(MPREACHNLRI_TYPE);
308
309 int mpReachDataIndx = cb.writerIndex();
310 cb.writeShort(0);
311
312 cb.writeShort(afi);
313 cb.writeByte(safi);
314 //next hop address
315 cb.writeByte(0);
316 //sub network points of attachment
317 cb.writeByte(0);
318
319 if (bgpFlowSpecInfo.routeDistinguisher() != null) {
320 cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
321 }
322
323 ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
324 int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
325
326 List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
327 ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
328
329 while (listIterator.hasNext()) {
330 BgpValueType tlv = listIterator.next();
331 switch (tlv.getType()) {
332 case Constants.BGP_FLOWSPEC_DST_PREFIX:
333 BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
334 fsDstPrefix.write(flowSpecTmpBuff);
335 break;
336 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
337 BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
338 fsSrcPrefix.write(flowSpecTmpBuff);
339 break;
340 case Constants.BGP_FLOWSPEC_IP_PROTO:
341 BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
342 fsIpProtocol.write(flowSpecTmpBuff);
343 break;
344 case Constants.BGP_FLOWSPEC_PORT:
345 BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
346 fsPortNum.write(flowSpecTmpBuff);
347 break;
348 case Constants.BGP_FLOWSPEC_DST_PORT:
349 BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
350 fsDstPortNum.write(flowSpecTmpBuff);
351 break;
352 case Constants.BGP_FLOWSPEC_SRC_PORT:
353 BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
354 fsSrcPortNum.write(flowSpecTmpBuff);
355 break;
356 case Constants.BGP_FLOWSPEC_ICMP_TP:
357 BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
358 fsIcmpType.write(flowSpecTmpBuff);
359 break;
360 case Constants.BGP_FLOWSPEC_ICMP_CD:
361 BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
362 fsIcmpCode.write(flowSpecTmpBuff);
363 break;
364 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
365 BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
366 fsTcpFlags.write(flowSpecTmpBuff);
367 break;
368 case Constants.BGP_FLOWSPEC_PCK_LEN:
369 BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
370 fsPacketLen.write(flowSpecTmpBuff);
371 break;
372 case Constants.BGP_FLOWSPEC_DSCP:
373 BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
374 fsDscpVal.write(flowSpecTmpBuff);
375 break;
376 case Constants.BGP_FLOWSPEC_FRAGMENT:
377 BgpFsFragment fsFragment = (BgpFsFragment) tlv;
378 fsFragment.write(flowSpecTmpBuff);
379 break;
380 default:
381 break;
382 }
383 }
384
385 /* RFC 5575: section 4, If the NLRI length value is smaller than 240 (0xf0 hex), the length
386 field can be encoded as a single octet. Otherwise, it is encoded as
387 an extended-length 2-octet values */
388 int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
389 if (len >= FLOW_SPEC_LEN) {
390 cb.writeShort(len);
391 } else {
392 cb.writeByte(len);
393 }
394 //Copy from bynamic buffer to channel buffer
395 cb.writeBytes(flowSpecTmpBuff);
396
397 int fsNlriLen = cb.writerIndex() - mpReachDataIndx;
398 cb.setShort(mpReachDataIndx, (short) (fsNlriLen - 2));
399
400 }
401
402 return cb.writerIndex() - iLenStartIndex;
Priyanka B3b695542015-10-14 17:16:27 +0530403 }
404
405 @Override
406 public String toString() {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530407 return MoreObjects.toStringHelper(getClass()).omitNullValues()
Priyanka B3b695542015-10-14 17:16:27 +0530408 .add("mpReachNlri", mpReachNlri)
Shashikanth VH510a8d82016-02-12 12:32:43 +0530409 .add("bgpFlowSpecInfo", bgpFlowSpecInfo)
Priyanka B3b695542015-10-14 17:16:27 +0530410 .add("afi", afi)
411 .add("safi", safi)
412 .add("ipNextHop", ipNextHop)
413 .add("length", length)
414 .toString();
415 }
Priyanka B02040732015-11-29 11:30:29 +0530416
417 @Override
418 public int compareTo(Object o) {
419 // TODO Auto-generated method stub
420 return 0;
421 }
Priyanka B3b695542015-10-14 17:16:27 +0530422}