blob: b55b178353b82dd72025169c2638f9527df2cd8d [file] [log] [blame]
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
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;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053035import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
38import com.google.common.base.MoreObjects;
39
40/**
41 * Provides BGP open message.
42 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053043public class BgpOpenMsgVer4 implements BgpOpenMsg {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053044
45 /*
46 0 1 2 3
47 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
48 +-+-+-+-+-+-+-+-+
49 | Version |
50 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 | My Autonomous System |
52 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 | Hold Time |
54 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 | BGP Identifier |
56 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 | Opt Parm Len |
58 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 | Optional Parameters (variable) |
60 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 OPEN Message Format
62 REFERENCE : RFC 4271
63 */
64
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053065 protected static final Logger log = LoggerFactory.getLogger(BgpOpenMsgVer4.class);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053066
67 public static final byte PACKET_VERSION = 4;
68 public static final int OPEN_MSG_MINIMUM_LENGTH = 10;
69 public static final int MSG_HEADER_LENGTH = 19;
70 public static final int MARKER_LENGTH = 16;
71 public static final int DEFAULT_HOLD_TIME = 120;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053072 public static final short AS_TRANS = 23456;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053073 public static final int OPT_PARA_TYPE_CAPABILITY = 2;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053074 public static final BgpType MSG_TYPE = BgpType.OPEN;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053075 public static final short AFI = 16388;
76 public static final byte SAFI = 71;
77 public static final byte RES = 0;
78 public static final int FOUR_OCTET_AS_NUM_CAPA_TYPE = 65;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053079 public static final byte[] MARKER = new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
80 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
81 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053082 public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053083 (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053084 private BgpHeader bgpMsgHeader;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053085 private byte version;
86 private short asNumber;
87 private short holdTime;
88 private int bgpId;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053089 private boolean isLargeAsCapabilitySet;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053090 private LinkedList<BgpValueType> capabilityTlv;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053091
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053092 public static final BgpOpenMsgVer4.Reader READER = new Reader();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053093
94 /**
95 * reset variables.
96 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053097 public BgpOpenMsgVer4() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053098 this.bgpMsgHeader = null;
99 this.version = 0;
100 this.holdTime = 0;
101 this.asNumber = 0;
102 this.bgpId = 0;
103 this.capabilityTlv = null;
104 }
105
106 /**
107 * Constructor to initialize all variables of BGP Open message.
108 *
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530109 * @param bgpMsgHeader BGP Header in open message
110 * @param version BGP version in open message
111 * @param holdTime hold time in open message
112 * @param asNumber AS number in open message
113 * @param bgpId BGP identifier in open message
114 * @param capabilityTlv capabilities in open message
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530115 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530116 public BgpOpenMsgVer4(BgpHeader bgpMsgHeader, byte version, short asNumber, short holdTime,
117 int bgpId, LinkedList<BgpValueType> capabilityTlv) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530118 this.bgpMsgHeader = bgpMsgHeader;
119 this.version = version;
120 this.asNumber = asNumber;
121 this.holdTime = holdTime;
122 this.bgpId = bgpId;
123 this.capabilityTlv = capabilityTlv;
124 }
125
126 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530127 public BgpHeader getHeader() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530128 return this.bgpMsgHeader;
129 }
130
131 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530132 public BgpVersion getVersion() {
133 return BgpVersion.BGP_4;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530134 }
135
136 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530137 public BgpType getType() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530138 return MSG_TYPE;
139 }
140
141 @Override
142 public short getHoldTime() {
143 return this.holdTime;
144 }
145
146 @Override
147 public short getAsNumber() {
148 return this.asNumber;
149 }
150
151 @Override
152 public int getBgpId() {
153 return this.bgpId;
154 }
155
156 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530157 public LinkedList<BgpValueType> getCapabilityTlv() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530158 return this.capabilityTlv;
159 }
160
161 /**
162 * Reader class for reading BGP open message from channel buffer.
163 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530164 public static class Reader implements BgpMessageReader<BgpOpenMsg> {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530165
166 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530167 public BgpOpenMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530168
169 byte version;
170 short holdTime;
171 short asNumber;
172 int bgpId;
173 byte optParaLen = 0;
174 byte optParaType;
175 byte capParaLen = 0;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530176 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530177
178 if (cb.readableBytes() < OPEN_MSG_MINIMUM_LENGTH) {
179 log.error("[readFrom] Invalid length: Packet size is less than the minimum length ");
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530180 Validation.validateLen(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530181 cb.readableBytes());
182 }
183
184 // Read version
185 version = cb.readByte();
186 if (version != PACKET_VERSION) {
187 log.error("[readFrom] Invalid version: " + version);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530188 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR,
189 BgpErrorType.UNSUPPORTED_VERSION_NUMBER, null);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530190 }
191
192 // Read AS number
193 asNumber = cb.readShort();
194
195 // Read Hold timer
196 holdTime = cb.readShort();
197
198 // Read BGP Identifier
199 bgpId = cb.readInt();
200
201 // Read optional parameter length
202 optParaLen = cb.readByte();
203
204 // Read Capabilities if optional parameter length is greater than 0
205 if (optParaLen != 0) {
206 // Read optional parameter type
207 optParaType = cb.readByte();
208
209 // Read optional parameter length
210 capParaLen = cb.readByte();
211
212 if (cb.readableBytes() < capParaLen) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530213 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, (byte) 0, null);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530214 }
215
216 ChannelBuffer capaCb = cb.readBytes(capParaLen);
217
218 // Parse capabilities only if optional parameter type is 2
219 if ((optParaType == OPT_PARA_TYPE_CAPABILITY) && (capParaLen != 0)) {
220 capabilityTlv = parseCapabilityTlv(capaCb);
221 } else {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530222 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR,
223 BgpErrorType.UNSUPPORTED_OPTIONAL_PARAMETER, null);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530224 }
225 }
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530226 return new BgpOpenMsgVer4(bgpHeader, version, asNumber, holdTime, bgpId, capabilityTlv);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530227 }
228 }
229
230 /**
231 * Parsing capabilities.
232 *
233 * @param cb of type channel buffer
234 * @return capabilityTlv of open message
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530235 * @throws BgpParseException while parsing capabilities
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530236 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530237 protected static LinkedList<BgpValueType> parseCapabilityTlv(ChannelBuffer cb) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530238
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530239 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530240
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530241 while (cb.readableBytes() > 0) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530242 BgpValueType tlv;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530243 short type = cb.readByte();
244 short length = cb.readByte();
245
246 switch (type) {
247 case FourOctetAsNumCapabilityTlv.TYPE:
248 log.debug("FourOctetAsNumCapabilityTlv");
249 if (FourOctetAsNumCapabilityTlv.LENGTH != length) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530250 throw new BgpParseException("Invalid length received for FourOctetAsNumCapabilityTlv.");
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530251 }
252 if (length > cb.readableBytes()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530253 throw new BgpParseException("Four octet as num tlv length"
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530254 + " is more than readableBytes.");
255 }
256 int as4Num = cb.readInt();
257 tlv = new FourOctetAsNumCapabilityTlv(as4Num);
258 break;
259 case MultiProtocolExtnCapabilityTlv.TYPE:
260 log.debug("MultiProtocolExtnCapabilityTlv");
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530261
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530262 if (length > cb.readableBytes()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530263 throw new BgpParseException("BGP LS tlv length is more than readableBytes.");
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530264 }
265 short afi = cb.readShort();
266 byte res = cb.readByte();
267 byte safi = cb.readByte();
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530268 if ((afi == Constants.AFI_FLOWSPEC_RPD_VALUE) && (safi == Constants.SAFI_FLOWSPEC_RPD_VALUE)) {
269 if ((MultiProtocolExtnCapabilityTlv.LENGTH + 1) != length) {
270 throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
271 }
272 tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi, cb.readByte());
273 } else {
274 if (MultiProtocolExtnCapabilityTlv.LENGTH != length) {
275 throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
276 }
277 tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
278 }
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530279 break;
280 default:
281 log.debug("Warning: Unsupported TLV: " + type);
282 cb.skipBytes(length);
283 continue;
284 }
285 capabilityTlv.add(tlv);
286 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530287 return capabilityTlv;
288 }
289
290 /**
291 * Builder class for BGP open message.
292 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530293 static class Builder implements BgpOpenMsg.Builder {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530294
295 private boolean isHeaderSet = false;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530296 private BgpHeader bgpMsgHeader;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530297 private boolean isHoldTimeSet = false;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530298 private short holdTime;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530299 private boolean isAsNumSet = false;
300 private short asNumber;
301 private boolean isBgpIdSet = false;
302 private int bgpId;
Shashikanth VHf04ab492016-02-10 11:35:11 +0530303 private boolean isIpV4UnicastCapabilityTlvSet = true;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530304 private boolean isLargeAsCapabilityTlvSet = false;
305 private boolean isLsCapabilityTlvSet = false;
Shashikanth VH44967ec2016-02-04 19:46:16 +0530306 private boolean isFlowSpecCapabilityTlvSet = false;
307 private boolean isVpnFlowSpecCapabilityTlvSet = false;
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530308 private boolean isFlowSpecRpdCapabilityTlvSet = false;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530309
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530310 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530311
312 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530313 public BgpOpenMsg build() throws BgpParseException {
314 BgpHeader bgpMsgHeader = this.isHeaderSet ? this.bgpMsgHeader : DEFAULT_OPEN_HEADER;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530315 short holdTime = this.isHoldTimeSet ? this.holdTime : DEFAULT_HOLD_TIME;
316
317 if (!this.isAsNumSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530318 throw new BgpParseException("BGP AS number is not set (mandatory)");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530319 }
320
321 if (!this.isBgpIdSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530322 throw new BgpParseException("BGPID is not set (mandatory)");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530323 }
324
Shashikanth VHf04ab492016-02-10 11:35:11 +0530325 if (this.isIpV4UnicastCapabilityTlvSet) {
326 BgpValueType tlv;
327 tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV4_UNICAST, RES,
328 (byte) Constants.SAFI_IPV4_UNICAST);
329 this.capabilityTlv.add(tlv);
330 }
331
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530332 if (this.isLargeAsCapabilityTlvSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530333 BgpValueType tlv;
Vidyashree Ramaafbbff92015-11-02 14:45:17 +0530334 int value = this.asNumber;
335 tlv = new FourOctetAsNumCapabilityTlv(value);
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530336 this.capabilityTlv.add(tlv);
337 }
338
339 if (this.isLsCapabilityTlvSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530340 BgpValueType tlv;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530341 tlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI);
342 this.capabilityTlv.add(tlv);
343 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530344
Shashikanth VH44967ec2016-02-04 19:46:16 +0530345 if (this.isFlowSpecCapabilityTlvSet) {
346 BgpValueType tlv;
347 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
348 RES, Constants.SAFI_FLOWSPEC_VALUE);
349 this.capabilityTlv.add(tlv);
350 }
351
352 if (this.isVpnFlowSpecCapabilityTlvSet) {
353 BgpValueType tlv;
354 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
355 RES, Constants.VPN_SAFI_FLOWSPEC_VALUE);
356 this.capabilityTlv.add(tlv);
357 }
358
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530359 if (this.isFlowSpecRpdCapabilityTlvSet) {
360 BgpValueType tlv;
361 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_RPD_VALUE,
362 RES, Constants.SAFI_FLOWSPEC_RPD_VALUE,
363 Constants.RPD_CAPABILITY_SEND_VALUE);
364 this.capabilityTlv.add(tlv);
365 }
366
367
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530368 return new BgpOpenMsgVer4(bgpMsgHeader, PACKET_VERSION, this.asNumber, holdTime, this.bgpId,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530369 this.capabilityTlv);
370 }
371
372 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530373 public Builder setHeader(BgpHeader bgpMsgHeader) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530374 this.bgpMsgHeader = bgpMsgHeader;
375 return this;
376 }
377
378 @Override
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530379 public Builder setHoldTime(short holdTime) {
380 this.holdTime = holdTime;
381 this.isHoldTimeSet = true;
382 return this;
383 }
384
385 @Override
386 public Builder setAsNumber(short asNumber) {
387 this.asNumber = asNumber;
388 this.isAsNumSet = true;
389 return this;
390 }
391
392 @Override
393 public Builder setBgpId(int bgpId) {
394 this.bgpId = bgpId;
395 this.isBgpIdSet = true;
396 return this;
397 }
398
399 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530400 public Builder setCapabilityTlv(LinkedList<BgpValueType> capabilityTlv) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530401 this.capabilityTlv = capabilityTlv;
402 return this;
403 }
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530404
405 @Override
406 public Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet) {
407 this.isLargeAsCapabilityTlvSet = isLargeAsCapabilitySet;
408 return this;
409 }
410
411 @Override
412 public Builder setLsCapabilityTlv(boolean isLsCapabilitySet) {
413 this.isLsCapabilityTlvSet = isLsCapabilitySet;
414 return this;
415 }
Shashikanth VH44967ec2016-02-04 19:46:16 +0530416
417 @Override
418 public Builder setFlowSpecCapabilityTlv(boolean isFlowSpecCapabilitySet) {
419 this.isFlowSpecCapabilityTlvSet = isFlowSpecCapabilitySet;
420 return this;
421 }
422
423 @Override
424 public Builder setVpnFlowSpecCapabilityTlv(boolean isVpnFlowSpecCapabilitySet) {
425 this.isVpnFlowSpecCapabilityTlvSet = isVpnFlowSpecCapabilitySet;
426 return this;
427 }
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530428
429 @Override
430 public Builder setFlowSpecRpdCapabilityTlv(boolean isFlowSpecRpdCapabilityTlvSet) {
431 this.isFlowSpecRpdCapabilityTlvSet = isFlowSpecRpdCapabilityTlvSet;
432 return this;
433 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530434 }
435
436 @Override
437 public void writeTo(ChannelBuffer cb) {
438 try {
439 WRITER.write(cb, this);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530440 } catch (BgpParseException e) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530441 log.debug("[writeTo] Error: " + e.toString());
442 }
443 }
444
445 public static final Writer WRITER = new Writer();
446
447 /**
448 * Writer class for writing BGP open message to channel buffer.
449 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530450 public static class Writer implements BgpMessageWriter<BgpOpenMsgVer4> {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530451
452 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530453 public void write(ChannelBuffer cb, BgpOpenMsgVer4 message) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530454
455 int optParaLen = 0;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530456 int as4num = 0;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530457
458 int startIndex = cb.writerIndex();
459
460 // write common header and get msg length index
461 int msgLenIndex = message.bgpMsgHeader.write(cb);
462
463 if (msgLenIndex <= 0) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530464 throw new BgpParseException("Unable to write message header.");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530465 }
466
467 // write version in 1-octet
468 cb.writeByte(message.version);
469
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530470 // get as4num if LS Capability is set
471 if (message.isLargeAsCapabilitySet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530472 LinkedList<BgpValueType> capabilityTlv = message
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530473 .getCapabilityTlv();
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530474 ListIterator<BgpValueType> listIterator = capabilityTlv
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530475 .listIterator();
476
477 while (listIterator.hasNext()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530478 BgpValueType tlv = listIterator.next();
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530479 if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
480 as4num = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
481 break;
482 }
483 }
484 }
485
486 if ((message.isLargeAsCapabilitySet) && (as4num > 65535)) {
487 // write As number as AS_TRANS
488 cb.writeShort(AS_TRANS);
489 } else {
490 // write AS number in next 2-octet
491 cb.writeShort(message.asNumber);
492 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530493
494 // write HoldTime in next 2-octet
495 cb.writeShort(message.holdTime);
496
497 // write BGP Identifier in next 4-octet
498 cb.writeInt(message.bgpId);
499
500 // store the index of Optional parameter length
501 int optParaLenIndex = cb.writerIndex();
502
503 // set optional parameter length as 0
504 cb.writeByte(0);
505
506 // Pack capability TLV
507 optParaLen = message.packCapabilityTlv(cb, message);
508
509 if (optParaLen != 0) {
510 // Update optional parameter length
511 cb.setByte(optParaLenIndex, (byte) (optParaLen + 2)); //+2 for optional parameter type.
512 }
513
514 // write OPEN Object Length
515 int length = cb.writerIndex() - startIndex;
516 cb.setShort(msgLenIndex, (short) length);
517 message.bgpMsgHeader.setLength((short) length);
518 }
519 }
520
521 /**
522 * returns length of capability tlvs.
523 *
524 * @param cb of type channel buffer
525 * @param message of type BGPOpenMsgVer4
526 * @return capParaLen of open message
527 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530528 protected int packCapabilityTlv(ChannelBuffer cb, BgpOpenMsgVer4 message) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530529 int startIndex = cb.writerIndex();
530 int capParaLen = 0;
531 int capParaLenIndex = 0;
532
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530533 LinkedList<BgpValueType> capabilityTlv = message.capabilityTlv;
534 ListIterator<BgpValueType> listIterator = capabilityTlv.listIterator();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530535
536 if (listIterator.hasNext()) {
537 // Set optional parameter type as 2
538 cb.writeByte(OPT_PARA_TYPE_CAPABILITY);
539
540 // Store the index of capability parameter length and update length at the end
541 capParaLenIndex = cb.writerIndex();
542
543 // Set capability parameter length as 0
544 cb.writeByte(0);
545
546 // Update the startIndex to know the length of capability tlv
547 startIndex = cb.writerIndex();
548 }
549
550 while (listIterator.hasNext()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530551 BgpValueType tlv = listIterator.next();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530552 if (tlv == null) {
553 log.debug("Warning: tlv is null from CapabilityTlv list");
554 continue;
555 }
556 tlv.write(cb);
557 }
558
559 capParaLen = cb.writerIndex() - startIndex;
560
561 if (capParaLen != 0) {
562 // Update capability parameter length
563 cb.setByte(capParaLenIndex, (byte) capParaLen);
564 }
565 return capParaLen;
566 }
567
568 @Override
569 public String toString() {
570 return MoreObjects.toStringHelper(getClass())
571 .add("bgpMsgHeader", bgpMsgHeader)
572 .add("version", version)
573 .add("holdTime", holdTime)
574 .add("asNumber", asNumber)
575 .add("bgpId", bgpId)
576 .add("capabilityTlv", capabilityTlv)
577 .toString();
578 }
579}