blob: cdd334c12e2295b391499e18c545ef48abfb8350 [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.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 VH5dd8dbe2015-11-26 13:22:18 +053024import org.onosproject.bgpio.exceptions.BgpParseException;
25import org.onosproject.bgpio.protocol.BgpLSNlri;
Shashikanth VH26fd38a2016-04-26 18:11:37 +053026import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053027import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
28import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
Priyanka Be07ea4d2015-11-21 21:28:10 +053029import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
Priyanka B3b695542015-10-14 17:16:27 +053030import org.onosproject.bgpio.util.Constants;
31import org.onosproject.bgpio.util.Validation;
32import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
34
35import com.google.common.base.MoreObjects;
36
37/**
38 * Provides Implementation of MpUnReach Nlri BGP Path Attribute.
39 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053040public class MpUnReachNlri implements BgpValueType {
Priyanka B3b695542015-10-14 17:16:27 +053041
Priyanka Be07ea4d2015-11-21 21:28:10 +053042 private static final Logger log = LoggerFactory.getLogger(MpUnReachNlri.class);
Priyanka B3b695542015-10-14 17:16:27 +053043 public static final byte MPUNREACHNLRI_TYPE = 15;
44 public static final byte LINK_NLRITYPE = 2;
Shashikanth VH510a8d82016-02-12 12:32:43 +053045 public static final byte FLAGS = (byte) 0x90;
Priyanka B3b695542015-10-14 17:16:27 +053046 private boolean isMpUnReachNlri = false;
47 private final short afi;
48 private final byte safi;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053049 private final List<BgpLSNlri> mpUnReachNlri;
Priyanka B3b695542015-10-14 17:16:27 +053050 private final int length;
Shashikanth VH26fd38a2016-04-26 18:11:37 +053051 private BgpFlowSpecNlri bgpFlowSpecNlri;
Priyanka B3b695542015-10-14 17:16:27 +053052
53 /**
54 * Constructor to initialize parameters.
55 *
56 * @param mpUnReachNlri MpUnReach Nlri attribute
57 * @param afi address family identifier
58 * @param safi subsequent address family identifier
59 * @param length of MpUnReachNlri
60 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053061 public MpUnReachNlri(List<BgpLSNlri> mpUnReachNlri, short afi, byte safi,
Priyanka B3b695542015-10-14 17:16:27 +053062 int length) {
63 this.mpUnReachNlri = mpUnReachNlri;
64 this.isMpUnReachNlri = true;
65 this.afi = afi;
66 this.safi = safi;
67 this.length = length;
68 }
69
Shashikanth VH26fd38a2016-04-26 18:11:37 +053070 public MpUnReachNlri(BgpFlowSpecNlri bgpFlowSpecNlri, short afi, byte safi) {
Shashikanth VH510a8d82016-02-12 12:32:43 +053071 this.mpUnReachNlri = null;
72 this.isMpUnReachNlri = true;
73 this.length = 0;
Shashikanth VH26fd38a2016-04-26 18:11:37 +053074 this.bgpFlowSpecNlri = bgpFlowSpecNlri;
Shashikanth VH510a8d82016-02-12 12:32:43 +053075 this.afi = afi;
76 this.safi = safi;
77 }
78
79 /**
80 * Returns BGP flow specification info.
81 *
82 * @return BGP flow specification info
83 */
Shashikanth VH26fd38a2016-04-26 18:11:37 +053084 public BgpFlowSpecNlri bgpFlowSpecNlri() {
85 return this.bgpFlowSpecNlri;
Shashikanth VH510a8d82016-02-12 12:32:43 +053086 }
87
Priyanka B3b695542015-10-14 17:16:27 +053088 /**
89 * Reads from ChannelBuffer and parses MpUnReachNlri.
90 *
91 * @param cb ChannelBuffer
92 * @return object of MpUnReachNlri
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053093 * @throws BgpParseException while parsing MpUnReachNlri
Priyanka B3b695542015-10-14 17:16:27 +053094 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053095 public static MpUnReachNlri read(ChannelBuffer cb) throws BgpParseException {
Priyanka B3b695542015-10-14 17:16:27 +053096 ChannelBuffer tempBuf = cb.copy();
97 Validation parseFlags = Validation.parseAttributeHeader(cb);
98 int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT
99 : parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE;
100 ChannelBuffer data = tempBuf.readBytes(len);
101
102 if (!parseFlags.getFirstBit() && parseFlags.getSecondBit()
103 && parseFlags.getThirdBit()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530104 throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
105 BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data);
Priyanka B3b695542015-10-14 17:16:27 +0530106 }
107
108 if (cb.readableBytes() < parseFlags.getLength()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530109 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
110 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, parseFlags.getLength());
Priyanka B3b695542015-10-14 17:16:27 +0530111 }
112
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530113 LinkedList<BgpLSNlri> mpUnReachNlri = new LinkedList<>();
114 BgpLSNlri bgpLSNlri = null;
Priyanka B3b695542015-10-14 17:16:27 +0530115 short afi = 0;
116 byte safi = 0;
117 ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength());
118 while (tempCb.readableBytes() > 0) {
119 afi = tempCb.readShort();
120 safi = tempCb.readByte();
121
122 //Supporting only for AFI 16388 / SAFI 71
123 if ((afi == Constants.AFI_VALUE) && (safi == Constants.SAFI_VALUE)
124 || (afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) {
125 while (tempCb.readableBytes() > 0) {
126 short nlriType = tempCb.readShort();
127 short totNlriLen = tempCb.readShort();
128 if (tempCb.readableBytes() < totNlriLen) {
129 Validation.validateLen(
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530130 BgpErrorType.UPDATE_MESSAGE_ERROR,
131 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
Priyanka B3b695542015-10-14 17:16:27 +0530132 }
133 tempBuf = tempCb.readBytes(totNlriLen);
134 switch (nlriType) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530135 case BgpNodeLSNlriVer4.NODE_NLRITYPE:
136 bgpLSNlri = BgpNodeLSNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530137 break;
Priyanka Be07ea4d2015-11-21 21:28:10 +0530138 case BgpLinkLsNlriVer4.LINK_NLRITYPE:
139 bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530140 break;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530141 case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE:
142 bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi,
Priyanka B3b695542015-10-14 17:16:27 +0530143 safi);
144 break;
145 default:
146 log.debug("nlriType not supported" + nlriType);
Shashikanth VH510a8d82016-02-12 12:32:43 +0530147 break;
Priyanka B3b695542015-10-14 17:16:27 +0530148 }
149 mpUnReachNlri.add(bgpLSNlri);
150 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530151 } else if ((afi == Constants.AFI_FLOWSPEC_VALUE)
152 && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
153 || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
154 List<BgpValueType> flowSpecComponents = new LinkedList<>();
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530155 RouteDistinguisher routeDistinguisher = null;
Shashikanth VH58260662016-02-13 01:12:02 +0530156 if (tempCb.readableBytes() > 0) {
157 BgpValueType flowSpecComponent = null;
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530158
159 if (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE) {
160 routeDistinguisher = new RouteDistinguisher();
161 routeDistinguisher = RouteDistinguisher.read(tempCb);
162 }
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530163 while (tempCb.readableBytes() > 0) {
subhasis77755e43a82017-02-12 07:46:09 +0530164 short totNlriLen = tempCb.getUnsignedByte(tempCb.readerIndex());
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530165 if (totNlriLen >= BgpFlowSpecNlri.FLOW_SPEC_LEN) {
166 if (tempCb.readableBytes() < 2) {
167 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
168 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
169 }
170 totNlriLen = tempCb.readShort();
171 } else {
172 totNlriLen = tempCb.readByte();
Shashikanth VH58260662016-02-13 01:12:02 +0530173 }
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530174 if (tempCb.readableBytes() < totNlriLen) {
175 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
176 BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
177 }
178 tempBuf = tempCb.readBytes(totNlriLen);
179 while (tempBuf.readableBytes() > 0) {
180 short type = tempBuf.readByte();
181 switch (type) {
182 case Constants.BGP_FLOWSPEC_DST_PREFIX:
183 flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
184 break;
185 case Constants.BGP_FLOWSPEC_SRC_PREFIX:
186 flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
187 break;
188 case Constants.BGP_FLOWSPEC_IP_PROTO:
189 flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
190 break;
191 case Constants.BGP_FLOWSPEC_PORT:
192 flowSpecComponent = BgpFsPortNum.read(tempBuf);
193 break;
194 case Constants.BGP_FLOWSPEC_DST_PORT:
195 flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
196 break;
197 case Constants.BGP_FLOWSPEC_SRC_PORT:
198 flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
199 break;
200 case Constants.BGP_FLOWSPEC_ICMP_TP:
201 flowSpecComponent = BgpFsIcmpType.read(tempBuf);
202 break;
203 case Constants.BGP_FLOWSPEC_ICMP_CD:
204 flowSpecComponent = BgpFsIcmpCode.read(tempBuf);
205 break;
206 case Constants.BGP_FLOWSPEC_TCP_FLAGS:
207 flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
208 break;
209 case Constants.BGP_FLOWSPEC_PCK_LEN:
210 flowSpecComponent = BgpFsPacketLength.read(tempBuf);
211 break;
212 case Constants.BGP_FLOWSPEC_DSCP:
213 flowSpecComponent = BgpFsDscpValue.read(tempBuf);
214 break;
215 case Constants.BGP_FLOWSPEC_FRAGMENT:
216 flowSpecComponent = BgpFsFragment.read(tempBuf);
217 break;
218 default:
219 log.debug("flow spec type not supported" + type);
220 break;
221 }
222 flowSpecComponents.add(flowSpecComponent);
223 }
Shashikanth VH58260662016-02-13 01:12:02 +0530224 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530225 }
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530226 BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
Shashikanth VHe3a73bc2016-02-22 20:11:31 +0530227 flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
228 return new MpUnReachNlri(flowSpecDetails, afi, safi);
Priyanka B3b695542015-10-14 17:16:27 +0530229 } else {
230 //TODO: check with the values got from capability
Shashikanth VH510a8d82016-02-12 12:32:43 +0530231 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
Priyanka B3b695542015-10-14 17:16:27 +0530232 }
233 }
234 return new MpUnReachNlri(mpUnReachNlri, afi, safi,
235 parseFlags.getLength());
236 }
237
238 @Override
239 public short getType() {
240 return MPUNREACHNLRI_TYPE;
241 }
242
243 /**
244 * Returns SAFI.
245 *
246 * @return SAFI
247 */
248 public byte safi() {
249 return this.safi;
250 }
251
252 /**
253 * Returns AFI.
254 *
255 * @return AFI
256 */
257 public short afi() {
258 return this.afi;
259 }
260
261 /**
262 * Returns list of MpUnReach Nlri.
263 *
264 * @return list of MpUnReach Nlri
265 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530266 public List<BgpLSNlri> mpUnReachNlri() {
Priyanka B3b695542015-10-14 17:16:27 +0530267 return this.mpUnReachNlri;
268 }
269
270 /**
271 * Returns whether MpReachNlri is present.
272 *
273 * @return whether MpReachNlri is present
274 */
275 public boolean isMpUnReachNlriSet() {
276 return this.isMpUnReachNlri;
277 }
278
279 /**
280 * Returns length of MpUnReach.
281 *
282 * @return length of MpUnReach
283 */
284 public int mpUnReachNlriLen() {
285 return this.length;
286 }
287
288 @Override
289 public int write(ChannelBuffer cb) {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530290 int iLenStartIndex = cb.writerIndex();
291 if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE) ||
292 (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530293 List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
294 ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
295 boolean isAllFlowTypesIdentical = true;
Shashikanth VH510a8d82016-02-12 12:32:43 +0530296
297 cb.writeByte(FLAGS);
298 cb.writeByte(MPUNREACHNLRI_TYPE);
299
300 int mpUnReachIndx = cb.writerIndex();
301 cb.writeShort(0);
302
303 cb.writeShort(afi);
304 cb.writeByte(safi);
305
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530306 if (bgpFlowSpecNlri.routeDistinguisher() != null) {
307 cb.writeLong(bgpFlowSpecNlri.routeDistinguisher().getRouteDistinguisher());
Shashikanth VH510a8d82016-02-12 12:32:43 +0530308 }
309
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530310 BgpValueType tlv1 = null;
311 if (listIterator.hasNext()) {
312 tlv1 = listIterator.next();
313 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530314 while (listIterator.hasNext()) {
315 BgpValueType tlv = listIterator.next();
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530316 if (tlv.getType() != tlv1.getType()) {
317 isAllFlowTypesIdentical = false;
Shashikanth VH510a8d82016-02-12 12:32:43 +0530318 break;
Shashikanth VH510a8d82016-02-12 12:32:43 +0530319 }
320 }
321
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530322 if (isAllFlowTypesIdentical) {
323 BgpFlowSpecNlri.updateBufferIdenticalFlowTypes(cb, bgpFlowSpecNlri());
Shashikanth VH510a8d82016-02-12 12:32:43 +0530324 } else {
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530325 BgpFlowSpecNlri.updateBufferNonIdenticalFlowTypes(cb, bgpFlowSpecNlri());
Shashikanth VH510a8d82016-02-12 12:32:43 +0530326 }
Shashikanth VH510a8d82016-02-12 12:32:43 +0530327 int fsNlriLen = cb.writerIndex() - mpUnReachIndx;
328 cb.setShort(mpUnReachIndx, (short) (fsNlriLen - 2));
329 }
330
331 return cb.writerIndex() - iLenStartIndex;
Priyanka B3b695542015-10-14 17:16:27 +0530332 }
333
334 @Override
Priyanka B02040732015-11-29 11:30:29 +0530335 public int compareTo(Object o) {
336 // TODO Auto-generated method stub
337 return 0;
338 }
339
340 @Override
Priyanka B3b695542015-10-14 17:16:27 +0530341 public String toString() {
Shashikanth VH510a8d82016-02-12 12:32:43 +0530342 return MoreObjects.toStringHelper(getClass()).omitNullValues()
Priyanka B3b695542015-10-14 17:16:27 +0530343 .add("mpReachNlri", mpUnReachNlri)
Shashikanth VH26fd38a2016-04-26 18:11:37 +0530344 .add("bgpFlowSpecNlri", bgpFlowSpecNlri)
Priyanka B3b695542015-10-14 17:16:27 +0530345 .add("afi", afi)
346 .add("safi", safi)
347 .add("length", length)
348 .toString();
349 }
350}