blob: e5d4821e41b6e6b8abc2727f962b97ba9367eed1 [file] [log] [blame]
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -08001/*
Jonathan Hartf4bd0482017-01-27 15:11:18 -08002 * Copyright 2017-present Open Networking Laboratory
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -08003 *
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 */
Jonathan Hartf4bd0482017-01-27 15:11:18 -080016
Jonathan Hart41349e92015-02-09 14:14:02 -080017package org.onosproject.routing.bgp;
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080018
19import org.jboss.netty.buffer.ChannelBuffer;
20import org.jboss.netty.buffer.ChannelBuffers;
21import org.jboss.netty.channel.ChannelHandlerContext;
22import org.onlab.packet.Ip4Address;
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080023import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
25
26/**
27 * A class for handling BGP OPEN messages.
28 */
29final class BgpOpen {
30 private static final Logger log = LoggerFactory.getLogger(BgpOpen.class);
31
32 /**
33 * Default constructor.
34 * <p>
35 * The constructor is private to prevent creating an instance of
36 * this utility class.
37 */
38 private BgpOpen() {
39 }
40
41 /**
42 * Processes BGP OPEN message.
43 *
44 * @param bgpSession the BGP Session to use
45 * @param ctx the Channel Handler Context
46 * @param message the message to process
47 */
48 static void processBgpOpen(BgpSession bgpSession,
49 ChannelHandlerContext ctx,
50 ChannelBuffer message) {
51 int minLength =
52 BgpConstants.BGP_OPEN_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH;
53 if (message.readableBytes() < minLength) {
54 log.debug("BGP RX OPEN Error from {}: " +
55 "Message length {} too short. Must be at least {}",
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -080056 bgpSession.remoteInfo().address(),
57 message.readableBytes(), minLength);
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080058 //
59 // ERROR: Bad Message Length
60 //
61 // Send NOTIFICATION and close the connection
62 ChannelBuffer txMessage =
63 BgpNotification.prepareBgpNotificationBadMessageLength(
64 message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH);
65 ctx.getChannel().write(txMessage);
66 bgpSession.closeSession(ctx);
67 return;
68 }
69
70 //
71 // Parse the OPEN message
72 //
73 // Remote BGP version
74 int remoteBgpVersion = message.readUnsignedByte();
75 if (remoteBgpVersion != BgpConstants.BGP_VERSION) {
76 log.debug("BGP RX OPEN Error from {}: " +
77 "Unsupported BGP version {}. Should be {}",
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -080078 bgpSession.remoteInfo().address(), remoteBgpVersion,
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080079 BgpConstants.BGP_VERSION);
80 //
81 // ERROR: Unsupported Version Number
82 //
83 // Send NOTIFICATION and close the connection
Jonathan Hart41349e92015-02-09 14:14:02 -080084 int errorCode = BgpConstants.Notifications.OpenMessageError.ERROR_CODE;
85 int errorSubcode = BgpConstants.Notifications.OpenMessageError.UNSUPPORTED_VERSION_NUMBER;
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080086 ChannelBuffer data = ChannelBuffers.buffer(2);
87 data.writeShort(BgpConstants.BGP_VERSION);
88 ChannelBuffer txMessage =
89 BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
90 data);
91 ctx.getChannel().write(txMessage);
92 bgpSession.closeSession(ctx);
93 return;
94 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -080095 bgpSession.remoteInfo().setBgpVersion(remoteBgpVersion);
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080096
97 // Remote AS number
98 long remoteAs = message.readUnsignedShort();
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -080099 bgpSession.remoteInfo().setAsNumber(remoteAs);
100 //
101 // NOTE: Currently, the local AS number is always set to the remote AS.
102 // This is done, because the peer setup is always iBGP.
103 // In the future, the local AS number should be configured as part
104 // of an explicit BGP peering configuration.
105 //
106 bgpSession.localInfo().setAsNumber(remoteAs);
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800107
108 // Remote Hold Time
109 long remoteHoldtime = message.readUnsignedShort();
110 if ((remoteHoldtime != 0) &&
111 (remoteHoldtime < BgpConstants.BGP_KEEPALIVE_MIN_HOLDTIME)) {
112 log.debug("BGP RX OPEN Error from {}: " +
113 "Unacceptable Hold Time field {}. " +
114 "Should be 0 or at least {}",
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800115 bgpSession.remoteInfo().address(), remoteHoldtime,
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800116 BgpConstants.BGP_KEEPALIVE_MIN_HOLDTIME);
117 //
118 // ERROR: Unacceptable Hold Time
119 //
120 // Send NOTIFICATION and close the connection
Jonathan Hart41349e92015-02-09 14:14:02 -0800121 int errorCode = BgpConstants.Notifications.OpenMessageError.ERROR_CODE;
122 int errorSubcode = BgpConstants.Notifications.OpenMessageError.UNACCEPTABLE_HOLD_TIME;
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800123 ChannelBuffer txMessage =
124 BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
125 null);
126 ctx.getChannel().write(txMessage);
127 bgpSession.closeSession(ctx);
128 return;
129 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800130 bgpSession.remoteInfo().setHoldtime(remoteHoldtime);
131 //
132 // NOTE: Currently. the local BGP Holdtime is always set to the remote
133 // BGP holdtime.
134 // In the future, the local BGP Holdtime should be configured as part
135 // of an explicit BGP peering configuration.
136 //
137 bgpSession.localInfo().setHoldtime(remoteHoldtime);
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800138
139 // Remote BGP Identifier
140 Ip4Address remoteBgpId =
141 Ip4Address.valueOf((int) message.readUnsignedInt());
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800142 bgpSession.remoteInfo().setBgpId(remoteBgpId);
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800143
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800144 // Parse the Optional Parameters
145 try {
146 parseOptionalParameters(bgpSession, ctx, message);
Jonathan Hart41349e92015-02-09 14:14:02 -0800147 } catch (BgpMessage.BgpParseException e) {
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800148 // ERROR: Error parsing optional parameters
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800149 log.debug("BGP RX OPEN Error from {}: " +
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800150 "Exception parsing Optional Parameters: {}",
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800151 bgpSession.remoteInfo().address(), e);
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800152 //
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800153 // ERROR: Invalid Optional Parameters: Unspecific
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800154 //
155 // Send NOTIFICATION and close the connection
Jonathan Hart41349e92015-02-09 14:14:02 -0800156 int errorCode = BgpConstants.Notifications.OpenMessageError.ERROR_CODE;
157 int errorSubcode = BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC;
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800158 ChannelBuffer txMessage =
159 BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
160 null);
161 ctx.getChannel().write(txMessage);
162 bgpSession.closeSession(ctx);
163 return;
164 }
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800165
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800166 //
167 // NOTE: Prepare the BGP OPEN message before the original local AS
168 // is overwritten by the 4-octet AS number
169 //
170 ChannelBuffer txOpenMessage = prepareBgpOpen(bgpSession.localInfo());
171
172 //
173 // Use the 4-octet AS number in lieu of the "My AS" field
174 // See RFC 6793, Section 4.1, second paragraph.
175 //
176 if (bgpSession.remoteInfo().as4OctetCapability()) {
177 long as4Number = bgpSession.remoteInfo().as4Number();
178 bgpSession.remoteInfo().setAsNumber(as4Number);
179 bgpSession.localInfo().setAsNumber(as4Number);
180 }
181
182 //
183 // Verify that the AS number is same for all other BGP Sessions
184 // NOTE: This check applies only for our use-case where all BGP
185 // sessions are iBGP.
186 //
187 for (BgpSession bs : bgpSession.getBgpSessionManager().getBgpSessions()) {
188 if ((bs.remoteInfo().asNumber() != 0) &&
189 (bgpSession.remoteInfo().asNumber() !=
190 bs.remoteInfo().asNumber())) {
191 log.debug("BGP RX OPEN Error from {}: Bad Peer AS {}. " +
192 "Expected {}",
193 bgpSession.remoteInfo().address(),
194 bgpSession.remoteInfo().asNumber(),
195 bs.remoteInfo().asNumber());
196 //
197 // ERROR: Bad Peer AS
198 //
199 // Send NOTIFICATION and close the connection
Jonathan Hart41349e92015-02-09 14:14:02 -0800200 int errorCode = BgpConstants.Notifications.OpenMessageError.ERROR_CODE;
201 int errorSubcode = BgpConstants.Notifications.OpenMessageError.BAD_PEER_AS;
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800202 ChannelBuffer txMessage =
203 BgpNotification.prepareBgpNotification(errorCode,
204 errorSubcode, null);
205 ctx.getChannel().write(txMessage);
206 bgpSession.closeSession(ctx);
207 return;
208 }
209 }
210
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800211 log.debug("BGP RX OPEN message from {}: " +
212 "BGPv{} AS {} BGP-ID {} Holdtime {}",
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800213 bgpSession.remoteInfo().address(),
214 bgpSession.remoteInfo().bgpVersion(),
215 bgpSession.remoteInfo().asNumber(),
216 bgpSession.remoteInfo().bgpId(),
217 bgpSession.remoteInfo().holdtime());
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800218
219 // Send my OPEN followed by KEEPALIVE
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800220 ctx.getChannel().write(txOpenMessage);
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800221 //
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800222 ChannelBuffer txMessage = BgpKeepalive.prepareBgpKeepalive();
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800223 ctx.getChannel().write(txMessage);
224
225 // Start the KEEPALIVE timer
226 bgpSession.restartKeepaliveTimer(ctx);
227
228 // Start the Session Timeout timer
229 bgpSession.restartSessionTimeoutTimer(ctx);
230 }
231
232 /**
233 * Prepares BGP OPEN message.
234 *
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800235 * @param localInfo the BGP Session local information to use
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800236 * @return the message to transmit (BGP header included)
237 */
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800238 static ChannelBuffer prepareBgpOpen(BgpSessionInfo localInfo) {
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800239 ChannelBuffer message =
240 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
241
242 //
243 // Prepare the OPEN message payload
244 //
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800245 message.writeByte(localInfo.bgpVersion());
246 message.writeShort((int) localInfo.asNumber());
247 message.writeShort((int) localInfo.holdtime());
248 message.writeInt(localInfo.bgpId().toInt());
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800249
250 // Prepare the optional BGP Capabilities
251 ChannelBuffer capabilitiesMessage =
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800252 prepareBgpOpenCapabilities(localInfo);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800253 message.writeByte(capabilitiesMessage.readableBytes());
254 message.writeBytes(capabilitiesMessage);
255
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800256 return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_OPEN,
257 message);
258 }
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800259
260 /**
261 * Parses BGP OPEN Optional Parameters.
262 *
263 * @param bgpSession the BGP Session to use
264 * @param ctx the Channel Handler Context
265 * @param message the message to process
Jonathan Hart41349e92015-02-09 14:14:02 -0800266 * @throws BgpMessage.BgpParseException
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800267 */
268 private static void parseOptionalParameters(BgpSession bgpSession,
269 ChannelHandlerContext ctx,
270 ChannelBuffer message)
Jonathan Hart41349e92015-02-09 14:14:02 -0800271 throws BgpMessage.BgpParseException {
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800272
273 //
274 // Get and verify the Optional Parameters Length
275 //
276 int optParamLength = message.readUnsignedByte();
277 if (optParamLength > message.readableBytes()) {
278 // ERROR: Invalid Optional Parameter Length
279 String errorMsg = "Invalid Optional Parameter Length field " +
280 optParamLength + ". Remaining Optional Parameters " +
281 message.readableBytes();
Jonathan Hart41349e92015-02-09 14:14:02 -0800282 throw new BgpMessage.BgpParseException(errorMsg);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800283 }
284 if (optParamLength == 0) {
285 return; // No Optional Parameters
286 }
287
288 //
289 // Parse the Optional Parameters
290 //
291 int optParamEnd = message.readerIndex() + optParamLength;
292 while (message.readerIndex() < optParamEnd) {
293 int paramType = message.readUnsignedByte();
294 if (message.readerIndex() >= optParamEnd) {
295 // ERROR: Malformed Optional Parameters
296 String errorMsg = "Malformed Optional Parameters";
Jonathan Hart41349e92015-02-09 14:14:02 -0800297 throw new BgpMessage.BgpParseException(errorMsg);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800298 }
299 int paramLen = message.readUnsignedByte();
300 if (message.readerIndex() + paramLen > optParamEnd) {
301 // ERROR: Malformed Optional Parameters
302 String errorMsg = "Malformed Optional Parameters";
Jonathan Hart41349e92015-02-09 14:14:02 -0800303 throw new BgpMessage.BgpParseException(errorMsg);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800304 }
305
306 //
307 // Extract the Optional Parameter Value based on the Parameter Type
308 //
309 switch (paramType) {
Jonathan Hart41349e92015-02-09 14:14:02 -0800310 case BgpConstants.Open.Capabilities.TYPE:
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800311 // Optional Parameter Type: Capabilities
Jonathan Hart41349e92015-02-09 14:14:02 -0800312 if (paramLen < BgpConstants.Open.Capabilities.MIN_LENGTH) {
Pingping Lin816c4802015-11-10 15:28:54 -0800313 // ERROR: Malformed Param Type
314 String errorMsg = "Malformed Capabilities Optional "
315 + "Parameter Type " + paramType;
Jonathan Hart41349e92015-02-09 14:14:02 -0800316 throw new BgpMessage.BgpParseException(errorMsg);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800317 }
Pingping Lin816c4802015-11-10 15:28:54 -0800318 int paramEnd = message.readerIndex() + paramLen;
319 // Parse Capabilities
320 while (message.readerIndex() < paramEnd) {
321 if (paramEnd - message.readerIndex() <
322 BgpConstants.Open.Capabilities.MIN_LENGTH) {
323 String errorMsg = "Malformed Capabilities";
Jonathan Hart41349e92015-02-09 14:14:02 -0800324 throw new BgpMessage.BgpParseException(errorMsg);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800325 }
Pingping Lin816c4802015-11-10 15:28:54 -0800326 int capabCode = message.readUnsignedByte();
327 int capabLen = message.readUnsignedByte();
328 if (message.readerIndex() + capabLen > paramEnd) {
329 // ERROR: Malformed Capability
330 String errorMsg = "Malformed Capability instance with "
331 + "code " + capabCode;
332 throw new BgpMessage.BgpParseException(errorMsg);
333 }
334
335 switch (capabCode) {
336 case BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE:
337 // Multiprotocol Extensions Capabilities (RFC 4760)
338 if (capabLen != BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH) {
339 // ERROR: Multiprotocol Extension Length Error
340 String errorMsg = "Multiprotocol Extension Length Error";
341 throw new BgpMessage.BgpParseException(errorMsg);
342 }
343 // Decode the AFI (2 octets) and SAFI (1 octet)
344 int afi = message.readUnsignedShort();
345 int reserved = message.readUnsignedByte();
346 int safi = message.readUnsignedByte();
347 log.debug("BGP RX OPEN Capability: AFI = {} SAFI = {}",
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800348 afi, safi);
Pingping Lin816c4802015-11-10 15:28:54 -0800349 //
350 // Setup the AFI/SAFI in the BgpSession
351 //
352 // NOTE: For now we just copy the remote AFI/SAFI setting
353 // to the local configuration.
354 //
355 if (afi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4 &&
356 safi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST) {
357 bgpSession.remoteInfo().setIpv4Unicast();
358 bgpSession.localInfo().setIpv4Unicast();
359 } else if (afi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4 &&
360 safi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_MULTICAST) {
361 bgpSession.remoteInfo().setIpv4Multicast();
362 bgpSession.localInfo().setIpv4Multicast();
363 } else if (afi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6 &&
364 safi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST) {
365 bgpSession.remoteInfo().setIpv6Unicast();
366 bgpSession.localInfo().setIpv6Unicast();
367 } else if (afi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6 &&
368 safi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_MULTICAST) {
369 bgpSession.remoteInfo().setIpv6Multicast();
370 bgpSession.localInfo().setIpv6Multicast();
371 } else {
372 log.debug("BGP RX OPEN Capability: Unknown AFI = {} SAFI = {}",
373 afi, safi);
374 }
375 break;
376
377 case BgpConstants.Open.Capabilities.As4Octet.CODE:
378 // Support for 4-octet AS Number Capabilities (RFC 6793)
379 if (capabLen != BgpConstants.Open.Capabilities.As4Octet.LENGTH) {
380 // ERROR: 4-octet AS Number Capability Length Error
381 String errorMsg = "4-octet AS Number Capability Length Error";
382 throw new BgpMessage.BgpParseException(errorMsg);
383 }
384 long as4Number = message.readUnsignedInt();
385
386 bgpSession.remoteInfo().setAs4OctetCapability();
387 bgpSession.remoteInfo().setAs4Number(as4Number);
388
389 //
390 // Copy remote 4-octet AS Number Capabilities and AS
391 // Number. This is a temporary setting until local AS
392 // number configuration is supported.
393 //
394 bgpSession.localInfo().setAs4OctetCapability();
395 bgpSession.localInfo().setAs4Number(as4Number);
396 log.debug("BGP RX OPEN Capability: AS4 Number = {}",
397 as4Number);
398 break;
399
400 default:
401 // Unknown Capability: ignore it
402 log.debug("BGP RX OPEN Capability Code = {} Length = {}",
403 capabCode, capabLen);
404 message.readBytes(capabLen);
405 break;
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800406 }
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800407
Kunihiro Ishiguro923d9d82014-12-21 15:47:28 +0900408
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800409 }
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800410 break;
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800411 default:
412 // Unknown Parameter Type: ignore it
413 log.debug("BGP RX OPEN Parameter Type = {} Length = {}",
414 paramType, paramLen);
415 message.readBytes(paramLen);
416 break;
417 }
418 }
419 }
420
421 /**
422 * Prepares the Capabilities for the BGP OPEN message.
423 *
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800424 * @param localInfo the BGP Session local information to use
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800425 * @return the buffer with the BGP Capabilities to transmit
426 */
427 private static ChannelBuffer prepareBgpOpenCapabilities(
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800428 BgpSessionInfo localInfo) {
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800429 ChannelBuffer message =
430 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
431
432 //
433 // Write the Multiprotocol Extensions Capabilities
434 //
435
436 // IPv4 unicast
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800437 if (localInfo.ipv4Unicast()) {
Jonathan Hart41349e92015-02-09 14:14:02 -0800438 message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
439 message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
440 BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Param len
441 message.writeByte(
442 BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE); // Capab. code
443 message.writeByte(
444 BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Capab. len
445 message.writeShort(
446 BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800447 message.writeByte(0); // Reserved field
Jonathan Hart41349e92015-02-09 14:14:02 -0800448 message.writeByte(
449 BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800450 }
451 // IPv4 multicast
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800452 if (localInfo.ipv4Multicast()) {
Jonathan Hart41349e92015-02-09 14:14:02 -0800453 message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
454 message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
455 BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Param len
456 message.writeByte(
457 BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE); // Capab. code
458 message.writeByte(
459 BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Capab. len
460 message.writeShort(
461 BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800462 message.writeByte(0); // Reserved field
Jonathan Hart41349e92015-02-09 14:14:02 -0800463 message.writeByte(
464 BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_MULTICAST);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800465 }
466 // IPv6 unicast
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800467 if (localInfo.ipv6Unicast()) {
Jonathan Hart41349e92015-02-09 14:14:02 -0800468 message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
469 message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
470 BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Param len
471 message.writeByte(
472 BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE); // Capab. code
473 message.writeByte(
474 BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Capab. len
475 message.writeShort(
476 BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800477 message.writeByte(0); // Reserved field
Jonathan Hart41349e92015-02-09 14:14:02 -0800478 message.writeByte(
479 BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800480 }
481 // IPv6 multicast
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800482 if (localInfo.ipv6Multicast()) {
Jonathan Hart41349e92015-02-09 14:14:02 -0800483 message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
484 message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
485 BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Param len
486 message.writeByte(
487 BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE); // Capab. code
488 message.writeByte(
489 BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Capab. len
490 message.writeShort(
491 BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800492 message.writeByte(0); // Reserved field
Jonathan Hart41349e92015-02-09 14:14:02 -0800493 message.writeByte(
494 BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_MULTICAST);
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800495 }
496
Kunihiro Ishiguro923d9d82014-12-21 15:47:28 +0900497 // 4 octet AS path capability
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800498 if (localInfo.as4OctetCapability()) {
Jonathan Hart41349e92015-02-09 14:14:02 -0800499 message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
500 message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
501 BgpConstants.Open.Capabilities.As4Octet.LENGTH); // Param len
502 message.writeByte(BgpConstants.Open.Capabilities.As4Octet.CODE); // Capab. code
503 message.writeByte(BgpConstants.Open.Capabilities.As4Octet.LENGTH); // Capab. len
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800504 message.writeInt((int) localInfo.as4Number());
Kunihiro Ishiguro923d9d82014-12-21 15:47:28 +0900505 }
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800506 return message;
507 }
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800508}