blob: 12c3c6260cc01686af350e3f80d8c84988bcb065 [file] [log] [blame]
Priyanka B3b695542015-10-14 17:16:27 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Priyanka B3b695542015-10-14 17:16:27 +05303 *
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;
25import org.onlab.packet.Ip4Address;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053026import org.onosproject.bgpio.exceptions.BgpParseException;
27import org.onosproject.bgpio.protocol.BgpLSNlri;
Shashikanth VH26fd38a2016-04-26 18:11:37 +053028import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053029import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
30import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
Priyanka Be07ea4d2015-11-21 21:28:10 +053031import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
Priyanka B3b695542015-10-14 17:16:27 +053032import org.onosproject.bgpio.util.Constants;
33import org.onosproject.bgpio.util.Validation;
34import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
37import com.google.common.base.MoreObjects;
38
39/*
40 * Provides Implementation of MpReach Nlri BGP Path Attribute.
41 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053042public class MpReachNlri implements BgpValueType {
Priyanka B3b695542015-10-14 17:16:27 +053043
44 private static final Logger log = LoggerFactory.getLogger(MpReachNlri.class);
Priyanka B3b695542015-10-14 17:16:27 +053045 public static final byte MPREACHNLRI_TYPE = 14;
46 public static final byte LINK_NLRITYPE = 2;
Shashikanth VH510a8d82016-02-12 12:32:43 +053047 public static final byte FLAGS = (byte) 0x90;
Priyanka B3b695542015-10-14 17:16:27 +053048 private boolean isMpReachNlri = false;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053049 private final List<BgpLSNlri> mpReachNlri;
Priyanka B3b695542015-10-14 17:16:27 +053050 private final int length;
51 private final short afi;
52 private final byte safi;
53 private final Ip4Address ipNextHop;
Shashikanth VH26fd38a2016-04-26 18:11:37 +053054 private BgpFlowSpecNlri bgpFlowSpecNlri;
Priyanka B3b695542015-10-14 17:16:27 +053055
56 /**
57 * Constructor to initialize parameters.
58 *
59 * @param mpReachNlri MpReach Nlri attribute
60 * @param afi address family identifier
61 * @param safi subsequent address family identifier
62 * @param ipNextHop nexthop IpAddress
63 * @param length of MpReachNlri
64 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053065 public MpReachNlri(List<BgpLSNlri> mpReachNlri, short afi, byte safi, Ip4Address ipNextHop, int length) {
Priyanka B3b695542015-10-14 17:16:27 +053066 this.mpReachNlri = mpReachNlri;
67 this.isMpReachNlri = true;
68 this.ipNextHop = ipNextHop;
69 this.afi = afi;
70 this.safi = safi;
71 this.length = length;
72 }
73
Shashikanth VH26fd38a2016-04-26 18:11:37 +053074 public MpReachNlri(BgpFlowSpecNlri bgpFlowSpecNlri, short afi, byte safi) {
Shashikanth VH510a8d82016-02-12 12:32:43 +053075 this.mpReachNlri = null;
76 this.isMpReachNlri = true;
77 this.length = 0;
78 this.ipNextHop = null;
Shashikanth VH26fd38a2016-04-26 18:11:37 +053079 this.bgpFlowSpecNlri = bgpFlowSpecNlri;
Shashikanth VH510a8d82016-02-12 12:32:43 +053080 this.afi = afi;
81 this.safi = safi;
82 }
83
Priyanka B3b695542015-10-14 17:16:27 +053084 /**
85 * Returns whether MpReachNlri is present.
86 *
87 * @return whether MpReachNlri is present
88 */
89 public boolean isMpReachNlriSet() {
90 return this.isMpReachNlri;
91 }
92
93 /**
94 * Returns list of MpReach Nlri.
95 *
96 * @return list of MpReach Nlri
97 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053098 public List<BgpLSNlri> mpReachNlri() {
Priyanka B3b695542015-10-14 17:16:27 +053099 return this.mpReachNlri;
100 }
101
102 /**
103 * Returns length of MpReachNlri.
104 *
105 * @return length of MpReachNlri
106 */
107 public int mpReachNlriLen() {
108 return this.length;
109 }
110
111 /**
Shashikanth VH510a8d82016-02-12 12:32:43 +0530112 * Returns BGP flow specification info.
113 *
114 * @return BGP flow specification info
115 */
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530116 public BgpFlowSpecNlri bgpFlowSpecNlri() {
117 return this.bgpFlowSpecNlri;
Shashikanth VH510a8d82016-02-12 12:32:43 +0530118 }
119
120 /**
Priyanka B3b695542015-10-14 17:16:27 +0530121 * Reads from ChannelBuffer and parses MpReachNlri.
122 *
123 * @param cb channelBuffer
124 * @return object of MpReachNlri
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530125 * @throws BgpParseException while parsing MpReachNlri
Priyanka B3b695542015-10-14 17:16:27 +0530126 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530127 public static MpReachNlri read(ChannelBuffer cb) throws BgpParseException {
Priyanka B3b695542015-10-14 17:16:27 +0530128 ChannelBuffer tempBuf = cb.copy();
129 Validation parseFlags = Validation.parseAttributeHeader(cb);
130 int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT :
131 parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE;
132 ChannelBuffer data = tempBuf.readBytes(len);
133
134 if (cb.readableBytes() < parseFlags.getLength()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530135 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
Priyanka B3b695542015-10-14 17:16:27 +0530136 parseFlags.getLength());
137 }
138 if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() && parseFlags.getThirdBit()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530139 throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data);
Priyanka B3b695542015-10-14 17:16:27 +0530140 }
141
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530142 BgpLSNlri bgpLSNlri = null;
143 List<BgpLSNlri> mpReachNlri = new LinkedList<>();
Priyanka B3b695542015-10-14 17:16:27 +0530144 ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength());
145 short afi = 0;
146 byte safi = 0;
147 Ip4Address ipNextHop = null;
148 while (tempCb.readableBytes() > 0) {
149 afi = tempCb.readShort();
150 safi = tempCb.readByte();
151
152 //Supporting for AFI 16388 / SAFI 71 and VPN AFI 16388 / SAFI 128
153 if ((afi == Constants.AFI_VALUE) && (safi == Constants.SAFI_VALUE) || (afi == Constants.AFI_VALUE)
154 && (safi == Constants.VPN_SAFI_VALUE)) {
155 byte nextHopLen = tempCb.readByte();
Vidyashree Rama7ba6b4c2015-11-30 17:20:22 +0530156 InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
Priyanka B3b695542015-10-14 17:16:27 +0530157 if (ipAddress.isMulticastAddress()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530158 throw new BgpParseException("Multicast not supported");
Priyanka B3b695542015-10-14 17:16:27 +0530159 }
160 ipNextHop = Ip4Address.valueOf(ipAddress);
161 byte reserved = tempCb.readByte();
162
163 while (tempCb.readableBytes() > 0) {
164 short nlriType = tempCb.readShort();
165 short totNlriLen = tempCb.readShort();
166 if (tempCb.readableBytes() < totNlriLen) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530167 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
168 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
Priyanka B3b695542015-10-14 17:16:27 +0530169 }
170 tempBuf = tempCb.readBytes(totNlriLen);
171 switch (nlriType) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530172 case BgpNodeLSNlriVer4.NODE_NLRITYPE:
173 bgpLSNlri = BgpNodeLSNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530174 break;
Priyanka Be07ea4d2015-11-21 21:28:10 +0530175 case BgpLinkLsNlriVer4.LINK_NLRITYPE:
176 bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530177 break;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530178 case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE:
179 bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530180 break;
181 default:
182 log.debug("nlriType not supported" + nlriType);
183 }
184 mpReachNlri.add(bgpLSNlri);
185 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530186 } else if ((afi == Constants.AFI_FLOWSPEC_VALUE)
187 && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
188 || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
189 List<BgpValueType> flowSpecComponents = new LinkedList<>();
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530190 RouteDistinguisher routeDistinguisher = null;
Shashikanth VH58260662016-02-13 01:12:02 +0530191 if (tempCb.readableBytes() > 0) {
192 BgpValueType flowSpecComponent = null;
Shashikanth VH510a8d82016-02-12 12:32:43 +0530193
Shashikanth VH58260662016-02-13 01:12:02 +0530194 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);
Shashikanth VH510a8d82016-02-12 12:32:43 +0530201 }
Shashikanth VH58260662016-02-13 01:12:02 +0530202
203 byte reserved = tempCb.readByte();
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530204
205 if (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE) {
206 routeDistinguisher = new RouteDistinguisher();
207 routeDistinguisher = RouteDistinguisher.read(tempCb);
208 }
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530209 while (tempCb.readableBytes() > 0) {
210 short totNlriLen = tempCb.getByte(tempCb.readerIndex());
211 if (totNlriLen >= BgpFlowSpecNlri.FLOW_SPEC_LEN) {
212 if (tempCb.readableBytes() < 2) {
213 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
214 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
215 }
216 totNlriLen = tempCb.readShort();
217 } else {
218 totNlriLen = tempCb.readByte();
Shashikanth VH58260662016-02-13 01:12:02 +0530219 }
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530220 if (tempCb.readableBytes() < totNlriLen) {
221 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
222 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
223 }
224 tempBuf = tempCb.readBytes(totNlriLen);
225 while (tempBuf.readableBytes() > 0) {
226 short type = tempBuf.readByte();
227 switch (type) {
228 case Constants.BGP_FLOWSPEC_DST_PREFIX:
229 flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
230 break;
231 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
232 flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
233 break;
234 case Constants.BGP_FLOWSPEC_IP_PROTO:
235 flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
236 break;
237 case Constants.BGP_FLOWSPEC_PORT:
238 flowSpecComponent = BgpFsPortNum.read(tempBuf);
239 break;
240 case Constants.BGP_FLOWSPEC_DST_PORT:
241 flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
242 break;
243 case Constants.BGP_FLOWSPEC_SRC_PORT:
244 flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
245 break;
246 case Constants.BGP_FLOWSPEC_ICMP_TP:
247 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
248 break;
249 case Constants.BGP_FLOWSPEC_ICMP_CD:
250 flowSpecComponent = BgpFsIcmpCode.read(tempBuf);
251 break;
252 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
253 flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
254 break;
255 case Constants.BGP_FLOWSPEC_PCK_LEN:
256 flowSpecComponent = BgpFsPacketLength.read(tempBuf);
257 break;
258 case Constants.BGP_FLOWSPEC_DSCP:
259 flowSpecComponent = BgpFsDscpValue.read(tempBuf);
260 break;
261 case Constants.BGP_FLOWSPEC_FRAGMENT:
262 flowSpecComponent = BgpFsFragment.read(tempBuf);
263 break;
264 default:
265 log.debug("flow spec type not supported" + type);
266 break;
267 }
268 flowSpecComponents.add(flowSpecComponent);
269 }
Shashikanth VH58260662016-02-13 01:12:02 +0530270 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530271 }
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530272 BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530273 flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
274 return new MpReachNlri(flowSpecDetails, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530275 } else {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530276 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
Priyanka B3b695542015-10-14 17:16:27 +0530277 }
278 }
279 return new MpReachNlri(mpReachNlri, afi, safi, ipNextHop, parseFlags.getLength());
280 }
281
282 @Override
283 public short getType() {
284 return MPREACHNLRI_TYPE;
285 }
286
287 /**
288 * Returns AFI.
289 *
290 * @return AFI
291 */
292 public short afi() {
293 return this.afi;
294 }
295
296 /**
297 * Returns Nexthop IpAddress.
298 *
299 * @return Nexthop IpAddress
300 */
301 public Ip4Address nexthop4() {
302 return this.ipNextHop;
303 }
304
305 /**
306 * Returns SAFI.
307 *
308 * @return SAFI
309 */
310 public byte safi() {
311 return this.safi;
312 }
313
314 @Override
315 public int write(ChannelBuffer cb) {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530316 int iLenStartIndex = cb.writerIndex();
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530317
Shashikanth VH510a8d82016-02-12 12:32:43 +0530318 if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
319 || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530320 List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
321 ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
322 boolean isAllFlowTypesIdentical = true;
Shashikanth VH510a8d82016-02-12 12:32:43 +0530323
324 cb.writeByte(FLAGS);
325 cb.writeByte(MPREACHNLRI_TYPE);
326
327 int mpReachDataIndx = cb.writerIndex();
328 cb.writeShort(0);
329
330 cb.writeShort(afi);
331 cb.writeByte(safi);
332 //next hop address
333 cb.writeByte(0);
334 //sub network points of attachment
335 cb.writeByte(0);
336
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530337 if (bgpFlowSpecNlri.routeDistinguisher() != null) {
338 cb.writeLong(bgpFlowSpecNlri.routeDistinguisher().getRouteDistinguisher());
Shashikanth VH510a8d82016-02-12 12:32:43 +0530339 }
340
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530341 BgpValueType tlv1 = null;
342 if (listIterator.hasNext()) {
343 tlv1 = listIterator.next();
344 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530345 while (listIterator.hasNext()) {
346 BgpValueType tlv = listIterator.next();
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530347 if (tlv.getType() != tlv1.getType()) {
348 isAllFlowTypesIdentical = false;
Shashikanth VH510a8d82016-02-12 12:32:43 +0530349 break;
350 }
351 }
352
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530353 if (isAllFlowTypesIdentical) {
354 BgpFlowSpecNlri.updateBufferIdenticalFlowTypes(cb, bgpFlowSpecNlri());
Shashikanth VH510a8d82016-02-12 12:32:43 +0530355 } else {
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530356 BgpFlowSpecNlri.updateBufferNonIdenticalFlowTypes(cb, bgpFlowSpecNlri());
Shashikanth VH510a8d82016-02-12 12:32:43 +0530357 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530358 int fsNlriLen = cb.writerIndex() - mpReachDataIndx;
359 cb.setShort(mpReachDataIndx, (short) (fsNlriLen - 2));
360
361 }
362
363 return cb.writerIndex() - iLenStartIndex;
Priyanka B3b695542015-10-14 17:16:27 +0530364 }
365
366 @Override
367 public String toString() {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530368 return MoreObjects.toStringHelper(getClass()).omitNullValues()
Priyanka B3b695542015-10-14 17:16:27 +0530369 .add("mpReachNlri", mpReachNlri)
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530370 .add("bgpFlowSpecNlri", bgpFlowSpecNlri)
Priyanka B3b695542015-10-14 17:16:27 +0530371 .add("afi", afi)
372 .add("safi", safi)
373 .add("ipNextHop", ipNextHop)
374 .add("length", length)
375 .toString();
376 }
Priyanka B02040732015-11-29 11:30:29 +0530377
378 @Override
379 public int compareTo(Object o) {
380 // TODO Auto-generated method stub
381 return 0;
382 }
Priyanka B3b695542015-10-14 17:16:27 +0530383}