blob: 61486ed88ee44a8f25ba5ce31b13e75eabd15759 [file] [log] [blame]
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +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 */
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053016package org.onosproject.bgpio.protocol.ver4;
17
18import java.util.LinkedList;
19import java.util.ListIterator;
20
21import org.jboss.netty.buffer.ChannelBuffer;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053022import org.onosproject.bgpio.exceptions.BgpParseException;
23import org.onosproject.bgpio.protocol.BgpMessageReader;
24import org.onosproject.bgpio.protocol.BgpMessageWriter;
25import org.onosproject.bgpio.protocol.BgpOpenMsg;
26import org.onosproject.bgpio.protocol.BgpType;
27import org.onosproject.bgpio.protocol.BgpVersion;
28import org.onosproject.bgpio.types.BgpErrorType;
29import org.onosproject.bgpio.types.BgpHeader;
30import org.onosproject.bgpio.types.BgpValueType;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053031import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv;
32import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053033import org.onosproject.bgpio.util.Validation;
Shashikanth VH44967ec2016-02-04 19:46:16 +053034import org.onosproject.bgpio.util.Constants;
Shashikanth VHb58cfd52016-04-21 16:45:50 +053035import org.onosproject.bgpio.types.RpdCapabilityTlv;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
39import com.google.common.base.MoreObjects;
40
41/**
42 * Provides BGP open message.
43 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053044public class BgpOpenMsgVer4 implements BgpOpenMsg {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053045
46 /*
47 0 1 2 3
48 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
49 +-+-+-+-+-+-+-+-+
50 | Version |
51 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 | My Autonomous System |
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 | Hold Time |
55 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 | BGP Identifier |
57 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 | Opt Parm Len |
59 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 | Optional Parameters (variable) |
61 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 OPEN Message Format
63 REFERENCE : RFC 4271
64 */
65
Ray Milkey9c9cde42018-01-12 14:22:06 -080066 private static final Logger log = LoggerFactory.getLogger(BgpOpenMsgVer4.class);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053067
68 public static final byte PACKET_VERSION = 4;
69 public static final int OPEN_MSG_MINIMUM_LENGTH = 10;
70 public static final int MSG_HEADER_LENGTH = 19;
71 public static final int MARKER_LENGTH = 16;
72 public static final int DEFAULT_HOLD_TIME = 120;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053073 public static final short AS_TRANS = 23456;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053074 public static final int OPT_PARA_TYPE_CAPABILITY = 2;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053075 public static final BgpType MSG_TYPE = BgpType.OPEN;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053076 public static final short AFI = 16388;
77 public static final byte SAFI = 71;
78 public static final byte RES = 0;
79 public static final int FOUR_OCTET_AS_NUM_CAPA_TYPE = 65;
Ray Milkey2e27ec52018-01-31 17:21:40 -080080 private static final byte[] MARKER = new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053081 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
82 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053083 public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053084 (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053085 private BgpHeader bgpMsgHeader;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053086 private byte version;
Shashikanth VH09792f02016-05-10 16:59:57 +053087 private long asNumber;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053088 private short holdTime;
89 private int bgpId;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053090 private boolean isLargeAsCapabilitySet;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053091 private LinkedList<BgpValueType> capabilityTlv;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053092
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053093 public static final BgpOpenMsgVer4.Reader READER = new Reader();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053094
95 /**
96 * reset variables.
97 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053098 public BgpOpenMsgVer4() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053099 this.bgpMsgHeader = null;
100 this.version = 0;
101 this.holdTime = 0;
102 this.asNumber = 0;
103 this.bgpId = 0;
104 this.capabilityTlv = null;
105 }
106
107 /**
108 * Constructor to initialize all variables of BGP Open message.
109 *
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530110 * @param bgpMsgHeader BGP Header in open message
111 * @param version BGP version in open message
112 * @param holdTime hold time in open message
113 * @param asNumber AS number in open message
114 * @param bgpId BGP identifier in open message
115 * @param capabilityTlv capabilities in open message
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530116 */
Shashikanth VH09792f02016-05-10 16:59:57 +0530117 public BgpOpenMsgVer4(BgpHeader bgpMsgHeader, byte version, long asNumber, short holdTime,
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530118 int bgpId, LinkedList<BgpValueType> capabilityTlv) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530119 this.bgpMsgHeader = bgpMsgHeader;
120 this.version = version;
121 this.asNumber = asNumber;
122 this.holdTime = holdTime;
123 this.bgpId = bgpId;
124 this.capabilityTlv = capabilityTlv;
125 }
126
127 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530128 public BgpHeader getHeader() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530129 return this.bgpMsgHeader;
130 }
131
132 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530133 public BgpVersion getVersion() {
134 return BgpVersion.BGP_4;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530135 }
136
137 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530138 public BgpType getType() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530139 return MSG_TYPE;
140 }
141
142 @Override
143 public short getHoldTime() {
144 return this.holdTime;
145 }
146
147 @Override
Shashikanth VH09792f02016-05-10 16:59:57 +0530148 public long getAsNumber() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530149 return this.asNumber;
150 }
151
152 @Override
153 public int getBgpId() {
154 return this.bgpId;
155 }
156
157 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530158 public LinkedList<BgpValueType> getCapabilityTlv() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530159 return this.capabilityTlv;
160 }
161
162 /**
163 * Reader class for reading BGP open message from channel buffer.
164 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530165 public static class Reader implements BgpMessageReader<BgpOpenMsg> {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530166
167 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530168 public BgpOpenMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530169
170 byte version;
171 short holdTime;
Shashikanth VH09792f02016-05-10 16:59:57 +0530172 long asNumber;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530173 int bgpId;
174 byte optParaLen = 0;
175 byte optParaType;
176 byte capParaLen = 0;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530177 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530178
179 if (cb.readableBytes() < OPEN_MSG_MINIMUM_LENGTH) {
180 log.error("[readFrom] Invalid length: Packet size is less than the minimum length ");
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530181 Validation.validateLen(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530182 cb.readableBytes());
183 }
184
185 // Read version
186 version = cb.readByte();
187 if (version != PACKET_VERSION) {
188 log.error("[readFrom] Invalid version: " + version);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530189 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR,
190 BgpErrorType.UNSUPPORTED_VERSION_NUMBER, null);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530191 }
192
193 // Read AS number
Shashikanth VH09792f02016-05-10 16:59:57 +0530194 asNumber = cb.getUnsignedShort(cb.readerIndex());
195 cb.readShort();
mohamedrahil00f6f262016-11-24 20:20:41 +0530196 log.debug("AS number read");
197
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530198 // Read Hold timer
199 holdTime = cb.readShort();
mohamedrahil00f6f262016-11-24 20:20:41 +0530200 log.debug("Holding time read");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530201
202 // Read BGP Identifier
203 bgpId = cb.readInt();
mohamedrahil00f6f262016-11-24 20:20:41 +0530204 log.debug("BGP identifier read");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530205
206 // Read optional parameter length
207 optParaLen = cb.readByte();
mohamedrahil00f6f262016-11-24 20:20:41 +0530208 log.debug("OPtional parameter length read");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530209
210 // Read Capabilities if optional parameter length is greater than 0
211 if (optParaLen != 0) {
Shashikanth VH3479fd42017-11-15 11:45:09 +0530212 while (cb.readableBytes() > 0) {
213 // Read optional parameter type
214 optParaType = cb.readByte();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530215
Shashikanth VH3479fd42017-11-15 11:45:09 +0530216 // Read optional parameter length
217 capParaLen = cb.readByte();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530218
Shashikanth VH3479fd42017-11-15 11:45:09 +0530219 if (cb.readableBytes() < capParaLen) {
220 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, (byte) 0, null);
221 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530222
Shashikanth VH3479fd42017-11-15 11:45:09 +0530223 ChannelBuffer capaCb = cb.readBytes(capParaLen);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530224
Shashikanth VH3479fd42017-11-15 11:45:09 +0530225 // Parse capabilities only if optional parameter type is 2
226 if ((optParaType == OPT_PARA_TYPE_CAPABILITY) && (capParaLen != 0)) {
227 capabilityTlv = parseCapabilityTlv(capaCb);
228 } else {
229 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR,
230 BgpErrorType.UNSUPPORTED_OPTIONAL_PARAMETER, null);
231 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530232 }
233 }
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530234 return new BgpOpenMsgVer4(bgpHeader, version, asNumber, holdTime, bgpId, capabilityTlv);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530235 }
236 }
237
238 /**
239 * Parsing capabilities.
240 *
241 * @param cb of type channel buffer
242 * @return capabilityTlv of open message
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530243 * @throws BgpParseException while parsing capabilities
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530244 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530245 protected static LinkedList<BgpValueType> parseCapabilityTlv(ChannelBuffer cb) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530246
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530247 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530248
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530249 while (cb.readableBytes() > 0) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530250 BgpValueType tlv;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530251 short type = cb.readByte();
252 short length = cb.readByte();
253
254 switch (type) {
255 case FourOctetAsNumCapabilityTlv.TYPE:
256 log.debug("FourOctetAsNumCapabilityTlv");
257 if (FourOctetAsNumCapabilityTlv.LENGTH != length) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530258 throw new BgpParseException("Invalid length received for FourOctetAsNumCapabilityTlv.");
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530259 }
260 if (length > cb.readableBytes()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530261 throw new BgpParseException("Four octet as num tlv length"
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530262 + " is more than readableBytes.");
263 }
264 int as4Num = cb.readInt();
265 tlv = new FourOctetAsNumCapabilityTlv(as4Num);
266 break;
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530267 case RpdCapabilityTlv.TYPE:
268 log.debug("RpdCapability");
269 if (RpdCapabilityTlv.LENGTH != length) {
270 throw new BgpParseException("Invalid length received for RpdCapability.");
271 }
272 if (length > cb.readableBytes()) {
mohamedrahil00f6f262016-11-24 20:20:41 +0530273 throw new BgpParseException("Four octet as num TLV length"
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530274 + " is more than readableBytes.");
275 }
276 short rpdAfi = cb.readShort();
277 byte rpdAsafi = cb.readByte();
278 byte sendReceive = cb.readByte();
279 tlv = new RpdCapabilityTlv(sendReceive);
280 break;
281
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530282 case MultiProtocolExtnCapabilityTlv.TYPE:
283 log.debug("MultiProtocolExtnCapabilityTlv");
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530284
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530285 if (MultiProtocolExtnCapabilityTlv.LENGTH != length) {
286 throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
287 }
288
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530289 if (length > cb.readableBytes()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530290 throw new BgpParseException("BGP LS tlv length is more than readableBytes.");
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530291 }
292 short afi = cb.readShort();
293 byte res = cb.readByte();
294 byte safi = cb.readByte();
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530295 tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
296
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530297 break;
298 default:
299 log.debug("Warning: Unsupported TLV: " + type);
300 cb.skipBytes(length);
301 continue;
302 }
303 capabilityTlv.add(tlv);
304 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530305 return capabilityTlv;
306 }
307
308 /**
309 * Builder class for BGP open message.
310 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530311 static class Builder implements BgpOpenMsg.Builder {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530312
313 private boolean isHeaderSet = false;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530314 private BgpHeader bgpMsgHeader;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530315 private boolean isHoldTimeSet = false;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530316 private short holdTime;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530317 private boolean isAsNumSet = false;
318 private short asNumber;
319 private boolean isBgpIdSet = false;
320 private int bgpId;
Shashikanth VHf04ab492016-02-10 11:35:11 +0530321 private boolean isIpV4UnicastCapabilityTlvSet = true;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530322 private boolean isLargeAsCapabilityTlvSet = false;
323 private boolean isLsCapabilityTlvSet = false;
Shashikanth VH44967ec2016-02-04 19:46:16 +0530324 private boolean isFlowSpecCapabilityTlvSet = false;
325 private boolean isVpnFlowSpecCapabilityTlvSet = false;
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530326 private boolean isFlowSpecRpdCapabilityTlvSet = false;
Mohammad Shahid30fedc52017-08-09 11:49:40 +0530327 private boolean isEvpnCapabilityTlvSet = false;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530328
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530329 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530330
331 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530332 public BgpOpenMsg build() throws BgpParseException {
333 BgpHeader bgpMsgHeader = this.isHeaderSet ? this.bgpMsgHeader : DEFAULT_OPEN_HEADER;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530334 short holdTime = this.isHoldTimeSet ? this.holdTime : DEFAULT_HOLD_TIME;
335
336 if (!this.isAsNumSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530337 throw new BgpParseException("BGP AS number is not set (mandatory)");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530338 }
339
340 if (!this.isBgpIdSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530341 throw new BgpParseException("BGPID is not set (mandatory)");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530342 }
343
Shashikanth VHf04ab492016-02-10 11:35:11 +0530344 if (this.isIpV4UnicastCapabilityTlvSet) {
345 BgpValueType tlv;
346 tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV4_UNICAST, RES,
347 (byte) Constants.SAFI_IPV4_UNICAST);
348 this.capabilityTlv.add(tlv);
349 }
350
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530351 if (this.isLargeAsCapabilityTlvSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530352 BgpValueType tlv;
Vidyashree Ramaafbbff92015-11-02 14:45:17 +0530353 int value = this.asNumber;
354 tlv = new FourOctetAsNumCapabilityTlv(value);
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530355 this.capabilityTlv.add(tlv);
356 }
357
358 if (this.isLsCapabilityTlvSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530359 BgpValueType tlv;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530360 tlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI);
361 this.capabilityTlv.add(tlv);
362 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530363
Shashikanth VH44967ec2016-02-04 19:46:16 +0530364 if (this.isFlowSpecCapabilityTlvSet) {
365 BgpValueType tlv;
366 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
367 RES, Constants.SAFI_FLOWSPEC_VALUE);
368 this.capabilityTlv.add(tlv);
369 }
370
371 if (this.isVpnFlowSpecCapabilityTlvSet) {
372 BgpValueType tlv;
373 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
374 RES, Constants.VPN_SAFI_FLOWSPEC_VALUE);
375 this.capabilityTlv.add(tlv);
376 }
377
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530378 if (this.isFlowSpecRpdCapabilityTlvSet) {
379 BgpValueType tlv;
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530380 tlv = new RpdCapabilityTlv(Constants.RPD_CAPABILITY_SEND_VALUE);
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530381 this.capabilityTlv.add(tlv);
382 }
383
Mohammad Shahid30fedc52017-08-09 11:49:40 +0530384 if (this.isEvpnCapabilityTlvSet) {
385 BgpValueType tlv;
386 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_EVPN_VALUE,
387 RES, Constants.SAFI_EVPN_VALUE);
388 this.capabilityTlv.add(tlv);
389 }
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530390
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530391 return new BgpOpenMsgVer4(bgpMsgHeader, PACKET_VERSION, this.asNumber, holdTime, this.bgpId,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530392 this.capabilityTlv);
393 }
394
395 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530396 public Builder setHeader(BgpHeader bgpMsgHeader) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530397 this.bgpMsgHeader = bgpMsgHeader;
398 return this;
399 }
400
401 @Override
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530402 public Builder setHoldTime(short holdTime) {
403 this.holdTime = holdTime;
404 this.isHoldTimeSet = true;
405 return this;
406 }
407
408 @Override
409 public Builder setAsNumber(short asNumber) {
410 this.asNumber = asNumber;
411 this.isAsNumSet = true;
412 return this;
413 }
414
415 @Override
416 public Builder setBgpId(int bgpId) {
417 this.bgpId = bgpId;
418 this.isBgpIdSet = true;
419 return this;
420 }
421
422 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530423 public Builder setCapabilityTlv(LinkedList<BgpValueType> capabilityTlv) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530424 this.capabilityTlv = capabilityTlv;
425 return this;
426 }
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530427
428 @Override
429 public Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet) {
430 this.isLargeAsCapabilityTlvSet = isLargeAsCapabilitySet;
431 return this;
432 }
433
434 @Override
435 public Builder setLsCapabilityTlv(boolean isLsCapabilitySet) {
436 this.isLsCapabilityTlvSet = isLsCapabilitySet;
437 return this;
438 }
Shashikanth VH44967ec2016-02-04 19:46:16 +0530439
440 @Override
441 public Builder setFlowSpecCapabilityTlv(boolean isFlowSpecCapabilitySet) {
442 this.isFlowSpecCapabilityTlvSet = isFlowSpecCapabilitySet;
443 return this;
444 }
445
446 @Override
447 public Builder setVpnFlowSpecCapabilityTlv(boolean isVpnFlowSpecCapabilitySet) {
448 this.isVpnFlowSpecCapabilityTlvSet = isVpnFlowSpecCapabilitySet;
449 return this;
450 }
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530451
452 @Override
453 public Builder setFlowSpecRpdCapabilityTlv(boolean isFlowSpecRpdCapabilityTlvSet) {
454 this.isFlowSpecRpdCapabilityTlvSet = isFlowSpecRpdCapabilityTlvSet;
455 return this;
456 }
Mohammad Shahid30fedc52017-08-09 11:49:40 +0530457
458 @Override
459 public Builder setEvpnCapabilityTlv(boolean isEvpnCapabilitySet) {
460 this.isEvpnCapabilityTlvSet = isEvpnCapabilitySet;
461 return this;
462 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530463 }
464
465 @Override
466 public void writeTo(ChannelBuffer cb) {
467 try {
468 WRITER.write(cb, this);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530469 } catch (BgpParseException e) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530470 log.debug("[writeTo] Error: " + e.toString());
471 }
472 }
473
474 public static final Writer WRITER = new Writer();
475
476 /**
477 * Writer class for writing BGP open message to channel buffer.
478 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530479 public static class Writer implements BgpMessageWriter<BgpOpenMsgVer4> {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530480
481 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530482 public void write(ChannelBuffer cb, BgpOpenMsgVer4 message) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530483
484 int optParaLen = 0;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530485 int as4num = 0;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530486
487 int startIndex = cb.writerIndex();
488
489 // write common header and get msg length index
490 int msgLenIndex = message.bgpMsgHeader.write(cb);
491
492 if (msgLenIndex <= 0) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530493 throw new BgpParseException("Unable to write message header.");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530494 }
495
496 // write version in 1-octet
497 cb.writeByte(message.version);
498
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530499 // get as4num if LS Capability is set
500 if (message.isLargeAsCapabilitySet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530501 LinkedList<BgpValueType> capabilityTlv = message
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530502 .getCapabilityTlv();
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530503 ListIterator<BgpValueType> listIterator = capabilityTlv
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530504 .listIterator();
505
506 while (listIterator.hasNext()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530507 BgpValueType tlv = listIterator.next();
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530508 if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
509 as4num = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
510 break;
511 }
512 }
513 }
514
515 if ((message.isLargeAsCapabilitySet) && (as4num > 65535)) {
516 // write As number as AS_TRANS
517 cb.writeShort(AS_TRANS);
518 } else {
519 // write AS number in next 2-octet
Shashikanth VH09792f02016-05-10 16:59:57 +0530520 cb.writeShort((short) message.asNumber);
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530521 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530522
523 // write HoldTime in next 2-octet
524 cb.writeShort(message.holdTime);
525
526 // write BGP Identifier in next 4-octet
527 cb.writeInt(message.bgpId);
528
529 // store the index of Optional parameter length
530 int optParaLenIndex = cb.writerIndex();
531
532 // set optional parameter length as 0
533 cb.writeByte(0);
534
535 // Pack capability TLV
536 optParaLen = message.packCapabilityTlv(cb, message);
537
538 if (optParaLen != 0) {
539 // Update optional parameter length
540 cb.setByte(optParaLenIndex, (byte) (optParaLen + 2)); //+2 for optional parameter type.
541 }
542
543 // write OPEN Object Length
544 int length = cb.writerIndex() - startIndex;
545 cb.setShort(msgLenIndex, (short) length);
546 message.bgpMsgHeader.setLength((short) length);
547 }
548 }
549
550 /**
551 * returns length of capability tlvs.
552 *
553 * @param cb of type channel buffer
554 * @param message of type BGPOpenMsgVer4
555 * @return capParaLen of open message
556 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530557 protected int packCapabilityTlv(ChannelBuffer cb, BgpOpenMsgVer4 message) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530558 int startIndex = cb.writerIndex();
559 int capParaLen = 0;
560 int capParaLenIndex = 0;
561
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530562 LinkedList<BgpValueType> capabilityTlv = message.capabilityTlv;
563 ListIterator<BgpValueType> listIterator = capabilityTlv.listIterator();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530564
565 if (listIterator.hasNext()) {
566 // Set optional parameter type as 2
567 cb.writeByte(OPT_PARA_TYPE_CAPABILITY);
568
569 // Store the index of capability parameter length and update length at the end
570 capParaLenIndex = cb.writerIndex();
571
572 // Set capability parameter length as 0
573 cb.writeByte(0);
574
575 // Update the startIndex to know the length of capability tlv
576 startIndex = cb.writerIndex();
577 }
578
579 while (listIterator.hasNext()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530580 BgpValueType tlv = listIterator.next();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530581 if (tlv == null) {
mohamedrahil00f6f262016-11-24 20:20:41 +0530582 log.debug("Warning: TLV is null from CapabilityTlv list");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530583 continue;
584 }
585 tlv.write(cb);
586 }
587
588 capParaLen = cb.writerIndex() - startIndex;
589
590 if (capParaLen != 0) {
591 // Update capability parameter length
592 cb.setByte(capParaLenIndex, (byte) capParaLen);
593 }
594 return capParaLen;
595 }
596
597 @Override
598 public String toString() {
599 return MoreObjects.toStringHelper(getClass())
600 .add("bgpMsgHeader", bgpMsgHeader)
601 .add("version", version)
602 .add("holdTime", holdTime)
603 .add("asNumber", asNumber)
604 .add("bgpId", bgpId)
605 .add("capabilityTlv", capabilityTlv)
606 .toString();
607 }
608}