blob: 7c50998836720415ff55e3441a0abb5634f40655 [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;
Ankur Aggarwalbd6fc422020-03-25 09:00:18 +000033import org.onosproject.bgpio.types.RouteRefreshCapabilityTlv;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053034import org.onosproject.bgpio.util.Validation;
Shashikanth VH44967ec2016-02-04 19:46:16 +053035import org.onosproject.bgpio.util.Constants;
Shashikanth VHb58cfd52016-04-21 16:45:50 +053036import org.onosproject.bgpio.types.RpdCapabilityTlv;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import com.google.common.base.MoreObjects;
41
42/**
43 * Provides BGP open message.
44 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053045public class BgpOpenMsgVer4 implements BgpOpenMsg {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053046
47 /*
48 0 1 2 3
49 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
50 +-+-+-+-+-+-+-+-+
51 | Version |
52 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 | My Autonomous System |
54 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 | Hold Time |
56 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 | BGP Identifier |
58 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 | Opt Parm Len |
60 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 | Optional Parameters (variable) |
62 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 OPEN Message Format
64 REFERENCE : RFC 4271
65 */
66
Ray Milkey9c9cde42018-01-12 14:22:06 -080067 private static final Logger log = LoggerFactory.getLogger(BgpOpenMsgVer4.class);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053068
69 public static final byte PACKET_VERSION = 4;
70 public static final int OPEN_MSG_MINIMUM_LENGTH = 10;
71 public static final int MSG_HEADER_LENGTH = 19;
72 public static final int MARKER_LENGTH = 16;
73 public static final int DEFAULT_HOLD_TIME = 120;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053074 public static final short AS_TRANS = 23456;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053075 public static final int OPT_PARA_TYPE_CAPABILITY = 2;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053076 public static final BgpType MSG_TYPE = BgpType.OPEN;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053077 public static final short AFI = 16388;
78 public static final byte SAFI = 71;
79 public static final byte RES = 0;
80 public static final int FOUR_OCTET_AS_NUM_CAPA_TYPE = 65;
Ray Milkey2e27ec52018-01-31 17:21:40 -080081 private static final byte[] MARKER = new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053082 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
83 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053084 public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053085 (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053086 private BgpHeader bgpMsgHeader;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053087 private byte version;
Shashikanth VH09792f02016-05-10 16:59:57 +053088 private long asNumber;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053089 private short holdTime;
90 private int bgpId;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +053091 private boolean isLargeAsCapabilitySet;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053092 private LinkedList<BgpValueType> capabilityTlv;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053093
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053094 public static final BgpOpenMsgVer4.Reader READER = new Reader();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +053095
96 /**
97 * reset variables.
98 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053099 public BgpOpenMsgVer4() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530100 this.bgpMsgHeader = null;
101 this.version = 0;
102 this.holdTime = 0;
103 this.asNumber = 0;
104 this.bgpId = 0;
105 this.capabilityTlv = null;
106 }
107
108 /**
109 * Constructor to initialize all variables of BGP Open message.
110 *
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530111 * @param bgpMsgHeader BGP Header in open message
112 * @param version BGP version in open message
113 * @param holdTime hold time in open message
114 * @param asNumber AS number in open message
115 * @param bgpId BGP identifier in open message
116 * @param capabilityTlv capabilities in open message
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530117 */
Shashikanth VH09792f02016-05-10 16:59:57 +0530118 public BgpOpenMsgVer4(BgpHeader bgpMsgHeader, byte version, long asNumber, short holdTime,
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530119 int bgpId, LinkedList<BgpValueType> capabilityTlv) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530120 this.bgpMsgHeader = bgpMsgHeader;
121 this.version = version;
122 this.asNumber = asNumber;
123 this.holdTime = holdTime;
124 this.bgpId = bgpId;
125 this.capabilityTlv = capabilityTlv;
126 }
127
128 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530129 public BgpHeader getHeader() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530130 return this.bgpMsgHeader;
131 }
132
133 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530134 public BgpVersion getVersion() {
135 return BgpVersion.BGP_4;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530136 }
137
138 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530139 public BgpType getType() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530140 return MSG_TYPE;
141 }
142
143 @Override
144 public short getHoldTime() {
145 return this.holdTime;
146 }
147
148 @Override
Shashikanth VH09792f02016-05-10 16:59:57 +0530149 public long getAsNumber() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530150 return this.asNumber;
151 }
152
153 @Override
154 public int getBgpId() {
155 return this.bgpId;
156 }
157
158 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530159 public LinkedList<BgpValueType> getCapabilityTlv() {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530160 return this.capabilityTlv;
161 }
162
163 /**
164 * Reader class for reading BGP open message from channel buffer.
165 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530166 public static class Reader implements BgpMessageReader<BgpOpenMsg> {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530167
168 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530169 public BgpOpenMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530170
171 byte version;
172 short holdTime;
Shashikanth VH09792f02016-05-10 16:59:57 +0530173 long asNumber;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530174 int bgpId;
175 byte optParaLen = 0;
176 byte optParaType;
177 byte capParaLen = 0;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530178 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530179
180 if (cb.readableBytes() < OPEN_MSG_MINIMUM_LENGTH) {
181 log.error("[readFrom] Invalid length: Packet size is less than the minimum length ");
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530182 Validation.validateLen(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530183 cb.readableBytes());
184 }
185
186 // Read version
187 version = cb.readByte();
188 if (version != PACKET_VERSION) {
189 log.error("[readFrom] Invalid version: " + version);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530190 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR,
191 BgpErrorType.UNSUPPORTED_VERSION_NUMBER, null);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530192 }
193
194 // Read AS number
Shashikanth VH09792f02016-05-10 16:59:57 +0530195 asNumber = cb.getUnsignedShort(cb.readerIndex());
196 cb.readShort();
mohamedrahil00f6f262016-11-24 20:20:41 +0530197 log.debug("AS number read");
198
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530199 // Read Hold timer
200 holdTime = cb.readShort();
mohamedrahil00f6f262016-11-24 20:20:41 +0530201 log.debug("Holding time read");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530202
203 // Read BGP Identifier
204 bgpId = cb.readInt();
mohamedrahil00f6f262016-11-24 20:20:41 +0530205 log.debug("BGP identifier read");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530206
207 // Read optional parameter length
208 optParaLen = cb.readByte();
mohamedrahil00f6f262016-11-24 20:20:41 +0530209 log.debug("OPtional parameter length read");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530210
211 // Read Capabilities if optional parameter length is greater than 0
212 if (optParaLen != 0) {
Shashikanth VH3479fd42017-11-15 11:45:09 +0530213 while (cb.readableBytes() > 0) {
214 // Read optional parameter type
215 optParaType = cb.readByte();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530216
Shashikanth VH3479fd42017-11-15 11:45:09 +0530217 // Read optional parameter length
218 capParaLen = cb.readByte();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530219
Shashikanth VH3479fd42017-11-15 11:45:09 +0530220 if (cb.readableBytes() < capParaLen) {
221 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, (byte) 0, null);
222 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530223
Shashikanth VH3479fd42017-11-15 11:45:09 +0530224 ChannelBuffer capaCb = cb.readBytes(capParaLen);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530225
Shashikanth VH3479fd42017-11-15 11:45:09 +0530226 // Parse capabilities only if optional parameter type is 2
227 if ((optParaType == OPT_PARA_TYPE_CAPABILITY) && (capParaLen != 0)) {
Ankur Aggarwal32c96962020-02-25 13:35:25 +0530228 //Observed that some routers send a list of capabilities, while others send a list
229 //of optional parameters. This takes care of both
230 LinkedList<BgpValueType> currentCapabilityTlv = parseCapabilityTlv(capaCb);
231 capabilityTlv.addAll(currentCapabilityTlv);
Shashikanth VH3479fd42017-11-15 11:45:09 +0530232 } else {
233 throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR,
234 BgpErrorType.UNSUPPORTED_OPTIONAL_PARAMETER, null);
235 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530236 }
237 }
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530238 return new BgpOpenMsgVer4(bgpHeader, version, asNumber, holdTime, bgpId, capabilityTlv);
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530239 }
240 }
241
242 /**
243 * Parsing capabilities.
244 *
245 * @param cb of type channel buffer
246 * @return capabilityTlv of open message
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530247 * @throws BgpParseException while parsing capabilities
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530248 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530249 protected static LinkedList<BgpValueType> parseCapabilityTlv(ChannelBuffer cb) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530250
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530251 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530252
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530253 while (cb.readableBytes() > 0) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530254 BgpValueType tlv;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530255 short type = cb.readByte();
256 short length = cb.readByte();
257
258 switch (type) {
259 case FourOctetAsNumCapabilityTlv.TYPE:
260 log.debug("FourOctetAsNumCapabilityTlv");
261 if (FourOctetAsNumCapabilityTlv.LENGTH != length) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530262 throw new BgpParseException("Invalid length received for FourOctetAsNumCapabilityTlv.");
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530263 }
264 if (length > cb.readableBytes()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530265 throw new BgpParseException("Four octet as num tlv length"
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530266 + " is more than readableBytes.");
267 }
268 int as4Num = cb.readInt();
269 tlv = new FourOctetAsNumCapabilityTlv(as4Num);
270 break;
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530271 case RpdCapabilityTlv.TYPE:
272 log.debug("RpdCapability");
273 if (RpdCapabilityTlv.LENGTH != length) {
274 throw new BgpParseException("Invalid length received for RpdCapability.");
275 }
276 if (length > cb.readableBytes()) {
mohamedrahil00f6f262016-11-24 20:20:41 +0530277 throw new BgpParseException("Four octet as num TLV length"
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530278 + " is more than readableBytes.");
279 }
280 short rpdAfi = cb.readShort();
281 byte rpdAsafi = cb.readByte();
282 byte sendReceive = cb.readByte();
283 tlv = new RpdCapabilityTlv(sendReceive);
284 break;
285
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530286 case MultiProtocolExtnCapabilityTlv.TYPE:
287 log.debug("MultiProtocolExtnCapabilityTlv");
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530288
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530289 if (MultiProtocolExtnCapabilityTlv.LENGTH != length) {
290 throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
291 }
292
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530293 if (length > cb.readableBytes()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530294 throw new BgpParseException("BGP LS tlv length is more than readableBytes.");
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530295 }
296 short afi = cb.readShort();
297 byte res = cb.readByte();
298 byte safi = cb.readByte();
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530299 tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
300
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530301 break;
Ankur Aggarwalbd6fc422020-03-25 09:00:18 +0000302 case RouteRefreshCapabilityTlv.TYPE:
303 log.debug("RouteRefreshCapabilityTlv");
304
305 if (RouteRefreshCapabilityTlv.LENGTH != length) {
306 throw new BgpParseException("Invalid length received for RouteRefreshCapabilityTlv.");
307 }
308
309 tlv = new RouteRefreshCapabilityTlv(true);
310 break;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530311 default:
312 log.debug("Warning: Unsupported TLV: " + type);
313 cb.skipBytes(length);
314 continue;
315 }
316 capabilityTlv.add(tlv);
317 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530318 return capabilityTlv;
319 }
320
321 /**
322 * Builder class for BGP open message.
323 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530324 static class Builder implements BgpOpenMsg.Builder {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530325
326 private boolean isHeaderSet = false;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530327 private BgpHeader bgpMsgHeader;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530328 private boolean isHoldTimeSet = false;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530329 private short holdTime;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530330 private boolean isAsNumSet = false;
331 private short asNumber;
332 private boolean isBgpIdSet = false;
333 private int bgpId;
Shashikanth VHf04ab492016-02-10 11:35:11 +0530334 private boolean isIpV4UnicastCapabilityTlvSet = true;
Ankur Aggarwalf363d1a2019-11-11 14:56:18 +0530335 private boolean isIpV6UnicastCapabilityTlvSet = false;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530336 private boolean isLargeAsCapabilityTlvSet = false;
337 private boolean isLsCapabilityTlvSet = false;
Shashikanth VH44967ec2016-02-04 19:46:16 +0530338 private boolean isFlowSpecCapabilityTlvSet = false;
339 private boolean isVpnFlowSpecCapabilityTlvSet = false;
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530340 private boolean isFlowSpecRpdCapabilityTlvSet = false;
Mohammad Shahid30fedc52017-08-09 11:49:40 +0530341 private boolean isEvpnCapabilityTlvSet = false;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530342
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530343 LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530344
345 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530346 public BgpOpenMsg build() throws BgpParseException {
347 BgpHeader bgpMsgHeader = this.isHeaderSet ? this.bgpMsgHeader : DEFAULT_OPEN_HEADER;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530348 short holdTime = this.isHoldTimeSet ? this.holdTime : DEFAULT_HOLD_TIME;
349
350 if (!this.isAsNumSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530351 throw new BgpParseException("BGP AS number is not set (mandatory)");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530352 }
353
354 if (!this.isBgpIdSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530355 throw new BgpParseException("BGPID is not set (mandatory)");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530356 }
357
Shashikanth VHf04ab492016-02-10 11:35:11 +0530358 if (this.isIpV4UnicastCapabilityTlvSet) {
359 BgpValueType tlv;
360 tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV4_UNICAST, RES,
Ankur Aggarwalf363d1a2019-11-11 14:56:18 +0530361 (byte) Constants.SAFI_UNICAST);
362 this.capabilityTlv.add(tlv);
363 }
364
365 if (this.isIpV6UnicastCapabilityTlvSet) {
366 BgpValueType tlv;
367 tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV6_UNICAST, RES,
368 (byte) Constants.SAFI_UNICAST);
Shashikanth VHf04ab492016-02-10 11:35:11 +0530369 this.capabilityTlv.add(tlv);
370 }
371
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530372 if (this.isLargeAsCapabilityTlvSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530373 BgpValueType tlv;
Vidyashree Ramaafbbff92015-11-02 14:45:17 +0530374 int value = this.asNumber;
375 tlv = new FourOctetAsNumCapabilityTlv(value);
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530376 this.capabilityTlv.add(tlv);
377 }
378
379 if (this.isLsCapabilityTlvSet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530380 BgpValueType tlv;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530381 tlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI);
382 this.capabilityTlv.add(tlv);
383 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530384
Shashikanth VH44967ec2016-02-04 19:46:16 +0530385 if (this.isFlowSpecCapabilityTlvSet) {
386 BgpValueType tlv;
387 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
388 RES, Constants.SAFI_FLOWSPEC_VALUE);
389 this.capabilityTlv.add(tlv);
390 }
391
392 if (this.isVpnFlowSpecCapabilityTlvSet) {
393 BgpValueType tlv;
394 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
395 RES, Constants.VPN_SAFI_FLOWSPEC_VALUE);
396 this.capabilityTlv.add(tlv);
397 }
398
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530399 if (this.isFlowSpecRpdCapabilityTlvSet) {
400 BgpValueType tlv;
Shashikanth VHb58cfd52016-04-21 16:45:50 +0530401 tlv = new RpdCapabilityTlv(Constants.RPD_CAPABILITY_SEND_VALUE);
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530402 this.capabilityTlv.add(tlv);
403 }
404
Mohammad Shahid30fedc52017-08-09 11:49:40 +0530405 if (this.isEvpnCapabilityTlvSet) {
406 BgpValueType tlv;
407 tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_EVPN_VALUE,
408 RES, Constants.SAFI_EVPN_VALUE);
409 this.capabilityTlv.add(tlv);
410 }
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530411
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530412 return new BgpOpenMsgVer4(bgpMsgHeader, PACKET_VERSION, this.asNumber, holdTime, this.bgpId,
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530413 this.capabilityTlv);
414 }
415
416 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530417 public Builder setHeader(BgpHeader bgpMsgHeader) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530418 this.bgpMsgHeader = bgpMsgHeader;
419 return this;
420 }
421
422 @Override
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530423 public Builder setHoldTime(short holdTime) {
424 this.holdTime = holdTime;
425 this.isHoldTimeSet = true;
426 return this;
427 }
428
429 @Override
430 public Builder setAsNumber(short asNumber) {
431 this.asNumber = asNumber;
432 this.isAsNumSet = true;
433 return this;
434 }
435
436 @Override
437 public Builder setBgpId(int bgpId) {
438 this.bgpId = bgpId;
439 this.isBgpIdSet = true;
440 return this;
441 }
442
443 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530444 public Builder setCapabilityTlv(LinkedList<BgpValueType> capabilityTlv) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530445 this.capabilityTlv = capabilityTlv;
446 return this;
447 }
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530448
449 @Override
450 public Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet) {
451 this.isLargeAsCapabilityTlvSet = isLargeAsCapabilitySet;
452 return this;
453 }
454
455 @Override
456 public Builder setLsCapabilityTlv(boolean isLsCapabilitySet) {
457 this.isLsCapabilityTlvSet = isLsCapabilitySet;
458 return this;
459 }
Shashikanth VH44967ec2016-02-04 19:46:16 +0530460
461 @Override
462 public Builder setFlowSpecCapabilityTlv(boolean isFlowSpecCapabilitySet) {
463 this.isFlowSpecCapabilityTlvSet = isFlowSpecCapabilitySet;
464 return this;
465 }
466
467 @Override
468 public Builder setVpnFlowSpecCapabilityTlv(boolean isVpnFlowSpecCapabilitySet) {
469 this.isVpnFlowSpecCapabilityTlvSet = isVpnFlowSpecCapabilitySet;
470 return this;
471 }
Shashikanth VHb650bfa2016-04-18 12:54:03 +0530472
473 @Override
474 public Builder setFlowSpecRpdCapabilityTlv(boolean isFlowSpecRpdCapabilityTlvSet) {
475 this.isFlowSpecRpdCapabilityTlvSet = isFlowSpecRpdCapabilityTlvSet;
476 return this;
477 }
Mohammad Shahid30fedc52017-08-09 11:49:40 +0530478
479 @Override
480 public Builder setEvpnCapabilityTlv(boolean isEvpnCapabilitySet) {
481 this.isEvpnCapabilityTlvSet = isEvpnCapabilitySet;
482 return this;
483 }
Ankur Aggarwalf363d1a2019-11-11 14:56:18 +0530484
485 @Override
486 public Builder setIpV4UnicastCapabilityTlvSet(boolean isIpV4UnicastCapabilityTlvSet) {
487 this.isIpV4UnicastCapabilityTlvSet = isIpV4UnicastCapabilityTlvSet;
488 return this;
489 }
490
491 @Override
492 public Builder setIpV6UnicastCapabilityTlvSet(boolean isIpV6UnicastCapabilityTlvSet) {
493 this.isIpV6UnicastCapabilityTlvSet = isIpV6UnicastCapabilityTlvSet;
494 return this;
495 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530496 }
497
498 @Override
499 public void writeTo(ChannelBuffer cb) {
500 try {
501 WRITER.write(cb, this);
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530502 } catch (BgpParseException e) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530503 log.debug("[writeTo] Error: " + e.toString());
504 }
505 }
506
507 public static final Writer WRITER = new Writer();
508
509 /**
510 * Writer class for writing BGP open message to channel buffer.
511 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530512 public static class Writer implements BgpMessageWriter<BgpOpenMsgVer4> {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530513
514 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530515 public void write(ChannelBuffer cb, BgpOpenMsgVer4 message) throws BgpParseException {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530516
517 int optParaLen = 0;
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530518 int as4num = 0;
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530519
520 int startIndex = cb.writerIndex();
521
522 // write common header and get msg length index
523 int msgLenIndex = message.bgpMsgHeader.write(cb);
524
525 if (msgLenIndex <= 0) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530526 throw new BgpParseException("Unable to write message header.");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530527 }
528
529 // write version in 1-octet
530 cb.writeByte(message.version);
531
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530532 // get as4num if LS Capability is set
533 if (message.isLargeAsCapabilitySet) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530534 LinkedList<BgpValueType> capabilityTlv = message
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530535 .getCapabilityTlv();
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530536 ListIterator<BgpValueType> listIterator = capabilityTlv
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530537 .listIterator();
538
539 while (listIterator.hasNext()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530540 BgpValueType tlv = listIterator.next();
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530541 if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
542 as4num = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
543 break;
544 }
545 }
546 }
547
548 if ((message.isLargeAsCapabilitySet) && (as4num > 65535)) {
549 // write As number as AS_TRANS
550 cb.writeShort(AS_TRANS);
551 } else {
552 // write AS number in next 2-octet
Shashikanth VH09792f02016-05-10 16:59:57 +0530553 cb.writeShort((short) message.asNumber);
Vidyashree Ramaf49b22c2015-10-13 15:30:24 +0530554 }
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530555
556 // write HoldTime in next 2-octet
557 cb.writeShort(message.holdTime);
558
559 // write BGP Identifier in next 4-octet
560 cb.writeInt(message.bgpId);
561
562 // store the index of Optional parameter length
563 int optParaLenIndex = cb.writerIndex();
564
565 // set optional parameter length as 0
566 cb.writeByte(0);
567
568 // Pack capability TLV
569 optParaLen = message.packCapabilityTlv(cb, message);
570
571 if (optParaLen != 0) {
572 // Update optional parameter length
573 cb.setByte(optParaLenIndex, (byte) (optParaLen + 2)); //+2 for optional parameter type.
574 }
575
576 // write OPEN Object Length
577 int length = cb.writerIndex() - startIndex;
578 cb.setShort(msgLenIndex, (short) length);
579 message.bgpMsgHeader.setLength((short) length);
580 }
581 }
582
583 /**
584 * returns length of capability tlvs.
585 *
586 * @param cb of type channel buffer
587 * @param message of type BGPOpenMsgVer4
588 * @return capParaLen of open message
589 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530590 protected int packCapabilityTlv(ChannelBuffer cb, BgpOpenMsgVer4 message) {
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530591 int startIndex = cb.writerIndex();
592 int capParaLen = 0;
593 int capParaLenIndex = 0;
594
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530595 LinkedList<BgpValueType> capabilityTlv = message.capabilityTlv;
596 ListIterator<BgpValueType> listIterator = capabilityTlv.listIterator();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530597
598 if (listIterator.hasNext()) {
599 // Set optional parameter type as 2
600 cb.writeByte(OPT_PARA_TYPE_CAPABILITY);
601
602 // Store the index of capability parameter length and update length at the end
603 capParaLenIndex = cb.writerIndex();
604
605 // Set capability parameter length as 0
606 cb.writeByte(0);
607
608 // Update the startIndex to know the length of capability tlv
609 startIndex = cb.writerIndex();
610 }
611
612 while (listIterator.hasNext()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530613 BgpValueType tlv = listIterator.next();
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530614 if (tlv == null) {
mohamedrahil00f6f262016-11-24 20:20:41 +0530615 log.debug("Warning: TLV is null from CapabilityTlv list");
Vidyashree Rama6d4f84e2015-09-21 20:01:02 +0530616 continue;
617 }
618 tlv.write(cb);
619 }
620
621 capParaLen = cb.writerIndex() - startIndex;
622
623 if (capParaLen != 0) {
624 // Update capability parameter length
625 cb.setByte(capParaLenIndex, (byte) capParaLen);
626 }
627 return capParaLen;
628 }
629
630 @Override
631 public String toString() {
632 return MoreObjects.toStringHelper(getClass())
633 .add("bgpMsgHeader", bgpMsgHeader)
634 .add("version", version)
635 .add("holdTime", holdTime)
636 .add("asNumber", asNumber)
637 .add("bgpId", bgpId)
638 .add("capabilityTlv", capabilityTlv)
639 .toString();
640 }
641}