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