blob: 52c6827831908c8cd4753f3753eeec999e43e98f [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.sdnip.bgp;
Jonathan Hartab63aac2014-10-16 08:52:55 -070017
18import java.net.InetAddress;
19import java.net.InetSocketAddress;
20import java.net.SocketAddress;
Jonathan Hartab63aac2014-10-16 08:52:55 -070021import java.util.Collection;
22import java.util.Collections;
Jonathan Hartab63aac2014-10-16 08:52:55 -070023import java.util.Map;
24import java.util.concurrent.ConcurrentHashMap;
25import java.util.concurrent.ConcurrentMap;
26import java.util.concurrent.TimeUnit;
27
Jonathan Hartab63aac2014-10-16 08:52:55 -070028import org.jboss.netty.buffer.ChannelBuffer;
Jonathan Hartab63aac2014-10-16 08:52:55 -070029import org.jboss.netty.channel.ChannelHandlerContext;
30import org.jboss.netty.channel.ChannelStateEvent;
Pavlin Radoslavov0a714722014-12-03 13:44:08 -080031import org.jboss.netty.channel.ExceptionEvent;
Jonathan Hartab63aac2014-10-16 08:52:55 -070032import org.jboss.netty.channel.SimpleChannelHandler;
33import org.jboss.netty.util.HashedWheelTimer;
34import org.jboss.netty.util.Timeout;
35import org.jboss.netty.util.Timer;
36import org.jboss.netty.util.TimerTask;
Jonathan Harte9ef4f32014-12-04 17:49:22 -080037import org.onlab.packet.Ip4Address;
38import org.onlab.packet.Ip4Prefix;
Brian O'Connorabafb502014-12-02 22:26:20 -080039import org.onosproject.sdnip.bgp.BgpConstants.Notifications;
40import org.onosproject.sdnip.bgp.BgpConstants.Notifications.HoldTimerExpired;
Jonathan Hartab63aac2014-10-16 08:52:55 -070041import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
44/**
45 * Class for handling the BGP peer sessions.
46 * There is one instance per each BGP peer session.
47 */
48public class BgpSession extends SimpleChannelHandler {
49 private static final Logger log =
50 LoggerFactory.getLogger(BgpSession.class);
51
52 private final BgpSessionManager bgpSessionManager;
53
54 // Local flag to indicate the session is closed.
55 // It is used to avoid the Netty's asynchronous closing of a channel.
56 private boolean isClosed = false;
57
58 private SocketAddress remoteAddress; // Peer IP addr/port
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080059 private Ip4Address remoteIp4Address; // Peer IPv4 address
Jonathan Hartab63aac2014-10-16 08:52:55 -070060 private int remoteBgpVersion; // 1 octet
61 private long remoteAs; // 2 octets
Kunihiro Ishiguro828245c2014-12-18 17:54:18 +090062 private long remoteAs4Octet; // 4 octets
Jonathan Hartab63aac2014-10-16 08:52:55 -070063 private long remoteHoldtime; // 2 octets
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080064 private Ip4Address remoteBgpId; // 4 octets -> IPv4 address
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -080065 private boolean remoteIpv4Unicast; // Peer IPv4/UNICAST AFI/SAFI
66 private boolean remoteIpv4Multicast; // Peer IPv4/MULTICAST AFI/SAFI
67 private boolean remoteIpv6Unicast; // Peer IPv6/UNICAST AFI/SAFI
68 private boolean remoteIpv6Multicast; // Peer IPv6/MULTICAST AFI/SAFI
Kunihiro Ishiguro923d9d82014-12-21 15:47:28 +090069 private boolean remoteAs4OctetCapability; // Peer 4 octet AS path capability
Jonathan Hartab63aac2014-10-16 08:52:55 -070070 //
71 private SocketAddress localAddress; // Local IP addr/port
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080072 private Ip4Address localIp4Address; // Local IPv4 address
Jonathan Hartab63aac2014-10-16 08:52:55 -070073 private int localBgpVersion; // 1 octet
74 private long localAs; // 2 octets
75 private long localHoldtime; // 2 octets
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080076 private Ip4Address localBgpId; // 4 octets -> IPv4 address
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -080077 private boolean localIpv4Unicast; // Local IPv4/UNICAST AFI/SAFI
78 private boolean localIpv4Multicast; // Local IPv4/MULTICAST AFI/SAFI
79 private boolean localIpv6Unicast; // Local IPv6/UNICAST AFI/SAFI
80 private boolean localIpv6Multicast; // Local IPv6/MULTICAST AFI/SAFI
Kunihiro Ishiguro923d9d82014-12-21 15:47:28 +090081 private boolean localAs4OctetCapability; // Local 4 octet AS path capability
Jonathan Hartab63aac2014-10-16 08:52:55 -070082 //
83 private long localKeepaliveInterval; // Keepalive interval
84
85 // Timers state
86 private Timer timer = new HashedWheelTimer();
87 private volatile Timeout keepaliveTimeout; // Periodic KEEPALIVE
88 private volatile Timeout sessionTimeout; // Session timeout
89
90 // BGP RIB-IN routing entries from this peer
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080091 private ConcurrentMap<Ip4Prefix, BgpRouteEntry> bgpRibIn =
Jonathan Hartab63aac2014-10-16 08:52:55 -070092 new ConcurrentHashMap<>();
93
94 /**
95 * Constructor for a given BGP Session Manager.
96 *
97 * @param bgpSessionManager the BGP Session Manager to use
98 */
99 BgpSession(BgpSessionManager bgpSessionManager) {
100 this.bgpSessionManager = bgpSessionManager;
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800101
102 // NOTE: We support only BGP4
103 this.localBgpVersion = BgpConstants.BGP_VERSION;
104 }
105
106 /**
107 * Gets the BGP Session Manager.
108 *
109 * @return the BGP Session Manager
110 */
111 BgpSessionManager getBgpSessionManager() {
112 return bgpSessionManager;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700113 }
114
115 /**
116 * Gets the BGP RIB-IN routing entries.
117 *
118 * @return the BGP RIB-IN routing entries
119 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800120 public Map<Ip4Prefix, BgpRouteEntry> bgpRibIn() {
121 return bgpRibIn;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700122 }
123
124 /**
125 * Finds a BGP routing entry in the BGP RIB-IN.
126 *
127 * @param prefix the prefix of the route to search for
128 * @return the BGP routing entry if found, otherwise null
129 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800130 public BgpRouteEntry findBgpRouteEntry(Ip4Prefix prefix) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700131 return bgpRibIn.get(prefix);
132 }
133
134 /**
135 * Gets the BGP session remote address.
136 *
137 * @return the BGP session remote address
138 */
139 public SocketAddress getRemoteAddress() {
140 return remoteAddress;
141 }
142
143 /**
144 * Gets the BGP session remote IPv4 address.
145 *
146 * @return the BGP session remote IPv4 address
147 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800148 public Ip4Address getRemoteIp4Address() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700149 return remoteIp4Address;
150 }
151
152 /**
153 * Gets the BGP session remote BGP version.
154 *
155 * @return the BGP session remote BGP version
156 */
157 public int getRemoteBgpVersion() {
158 return remoteBgpVersion;
159 }
160
161 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800162 * Sets the BGP session remote BGP version.
163 *
164 * @param remoteBgpVersion the BGP session remote BGP version to set
165 */
166 void setRemoteBgpVersion(int remoteBgpVersion) {
167 this.remoteBgpVersion = remoteBgpVersion;
168 }
169
170 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700171 * Gets the BGP session remote AS number.
172 *
173 * @return the BGP session remote AS number
174 */
175 public long getRemoteAs() {
176 return remoteAs;
177 }
178
179 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800180 * Sets the BGP session remote AS number.
181 *
182 * @param remoteAs the BGP session remote AS number to set
183 */
184 void setRemoteAs(long remoteAs) {
185 this.remoteAs = remoteAs;
186
187 //
188 // NOTE: Currently, the local AS number is always set to the remote AS.
189 // This is done, because the peer setup is always iBGP.
190 // In the future the local AS number should be configured as part
191 // of an explicit BGP peering configuration.
192 //
Kunihiro Ishiguro923d9d82014-12-21 15:47:28 +0900193 setLocalAs(remoteAs);
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800194 }
195
196 /**
Kunihiro Ishiguro828245c2014-12-18 17:54:18 +0900197 * Sets the BGP session remote 4 octet AS number.
198 *
199 * @param remoteAs4Octet the BGP session remote 4 octet AS number to set
200 */
201 void setRemoteAs4Octet(long remoteAs4Octet) {
202 this.remoteAs4Octet = remoteAs4Octet;
203 }
204
205 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700206 * Gets the BGP session remote Holdtime.
207 *
208 * @return the BGP session remote Holdtime
209 */
210 public long getRemoteHoldtime() {
211 return remoteHoldtime;
212 }
213
214 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800215 * Sets the BGP session remote Holdtime.
216 *
217 * @param remoteHoldtime the BGP session remote Holdtime to set
218 */
219 void setRemoteHoldtime(long remoteHoldtime) {
220 this.remoteHoldtime = remoteHoldtime;
221
222 //
223 // NOTE: Currently. the local BGP Holdtime is always set to the remote
224 // BGP holdtime.
225 // In the future, the local BGP Holdtime should be configured as part
226 // of an explicit BGP peering configuration.
227 //
228 this.localHoldtime = remoteHoldtime;
229
230 // Set the local Keepalive interval
231 if (localHoldtime == 0) {
232 localKeepaliveInterval = 0;
233 } else {
234 localKeepaliveInterval = Math.max(localHoldtime /
235 BgpConstants.BGP_KEEPALIVE_PER_HOLD_INTERVAL,
236 BgpConstants.BGP_KEEPALIVE_MIN_INTERVAL);
237 }
238 }
239
240 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700241 * Gets the BGP session remote BGP Identifier as an IPv4 address.
242 *
243 * @return the BGP session remote BGP Identifier as an IPv4 address
244 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800245 public Ip4Address getRemoteBgpId() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700246 return remoteBgpId;
247 }
248
249 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800250 * Sets the BGP session remote BGP Identifier as an IPv4 address.
251 *
252 * @param remoteBgpId the BGP session remote BGP Identifier to set
253 */
254 void setRemoteBgpId(Ip4Address remoteBgpId) {
255 this.remoteBgpId = remoteBgpId;
256 }
257
258 /**
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800259 * Gets the BGP session remote AFI/SAFI configuration for IPv4 unicast.
260 *
261 * @return the BGP session remote AFI/SAFI configuration for IPv4 unicast
262 */
263 public boolean getRemoteIpv4Unicast() {
264 return remoteIpv4Unicast;
265 }
266
267 /**
268 * Sets the BGP session remote AFI/SAFI configuration for IPv4 unicast.
269 */
270 void setRemoteIpv4Unicast() {
271 this.remoteIpv4Unicast = true;
272 // Copy the remote AFI/SAFI setting to the local configuration
273 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
274 // this.localIpv4Unicast = true;
275 }
276
277 /**
278 * Gets the BGP session remote AFI/SAFI configuration for IPv4 multicast.
279 *
280 * @return the BGP session remote AFI/SAFI configuration for IPv4 multicast
281 */
282 public boolean getRemoteIpv4Multicast() {
283 return remoteIpv4Multicast;
284 }
285
286 /**
287 * Sets the BGP session remote AFI/SAFI configuration for IPv4 multicast.
288 */
289 void setRemoteIpv4Multicast() {
290 this.remoteIpv4Multicast = true;
291 // Copy the remote AFI/SAFI setting to the local configuration
292 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
293 // this.localIpv4Multicast = true;
294 }
295
296 /**
297 * Gets the BGP session remote AFI/SAFI configuration for IPv6 unicast.
298 *
299 * @return the BGP session remote AFI/SAFI configuration for IPv6 unicast
300 */
301 public boolean getRemoteIpv6Unicast() {
302 return remoteIpv6Unicast;
303 }
304
305 /**
306 * Sets the BGP session remote AFI/SAFI configuration for IPv6 unicast.
307 */
308 void setRemoteIpv6Unicast() {
309 this.remoteIpv6Unicast = true;
310 // Copy the remote AFI/SAFI setting to the local configuration
311 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
312 // this.localIpv6Unicast = true;
313 }
314
315 /**
316 * Gets the BGP session remote AFI/SAFI configuration for IPv6 multicast.
317 *
318 * @return the BGP session remote AFI/SAFI configuration for IPv6 multicast
319 */
320 public boolean getRemoteIpv6Multicast() {
321 return remoteIpv6Multicast;
322 }
323
324 /**
325 * Sets the BGP session remote AFI/SAFI configuration for IPv6 multicast.
326 */
327 void setRemoteIpv6Multicast() {
328 this.remoteIpv6Multicast = true;
329 // Copy the remote AFI/SAFI setting to the local configuration
330 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
331 // this.localIpv6Multicast = true;
332 }
333
334 /**
Kunihiro Ishiguro923d9d82014-12-21 15:47:28 +0900335 * Gets the BGP session remote 4 octet AS path capability.
336 *
337 * @return true when the BGP session remote has 4 octet AS path capability
338 */
339 public boolean getRemoteAs4OctetCapability() {
340 return remoteAs4OctetCapability;
341 }
342
343 /**
344 * Sets the BGP session remote 4 octet AS path capability.
345 */
346 void setRemoteAs4OctetCapability() {
347 this.remoteAs4OctetCapability = true;
348 }
349
350 /**
351 * Gets the BGP session local 4 octet AS path capability.
352 *
353 * @return true when the BGP session local has 4 octet AS path capability
354 */
355 public boolean getLocalAs4OctetCapability() {
356 return localAs4OctetCapability;
357 }
358
359 /**
360 * Sets the BGP session local 4 octet AS path capability.
361 */
362 void setLocalAs4OctetCapability() {
363 this.localAs4OctetCapability = true;
364 }
365
366 /**
367 * Gets the BGP session 4 octet AS path capability.
368 *
369 * @return true when the BGP session is 4 octet AS path capable
370 */
371 public boolean isAs4OctetCapable() {
372 return getRemoteAs4OctetCapability() && getLocalAs4OctetCapability();
373 }
374
375 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700376 * Gets the BGP session local address.
377 *
378 * @return the BGP session local address
379 */
380 public SocketAddress getLocalAddress() {
381 return localAddress;
382 }
383
384 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800385 * Gets the BGP session local IPv4 address.
386 *
387 * @return the BGP session local IPv4 address
388 */
389 public Ip4Address getLocalIp4Address() {
390 return localIp4Address;
391 }
392
393 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700394 * Gets the BGP session local BGP version.
395 *
396 * @return the BGP session local BGP version
397 */
398 public int getLocalBgpVersion() {
399 return localBgpVersion;
400 }
401
402 /**
403 * Gets the BGP session local AS number.
404 *
405 * @return the BGP session local AS number
406 */
407 public long getLocalAs() {
408 return localAs;
409 }
410
411 /**
Kunihiro Ishiguro923d9d82014-12-21 15:47:28 +0900412 * Sets the BGP session local AS number.
413 *
414 * @param localAs the BGP session local AS number to set
415 */
416 public void setLocalAs(long localAs) {
417 this.localAs = localAs;
418 }
419
420 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700421 * Gets the BGP session local Holdtime.
422 *
423 * @return the BGP session local Holdtime
424 */
425 public long getLocalHoldtime() {
426 return localHoldtime;
427 }
428
429 /**
430 * Gets the BGP session local BGP Identifier as an IPv4 address.
431 *
432 * @return the BGP session local BGP Identifier as an IPv4 address
433 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800434 public Ip4Address getLocalBgpId() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700435 return localBgpId;
436 }
437
438 /**
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800439 * Gets the BGP session local AFI/SAFI configuration for IPv4 unicast.
440 *
441 * @return the BGP session local AFI/SAFI configuration for IPv4 unicast
442 */
443 public boolean getLocalIpv4Unicast() {
444 return localIpv4Unicast;
445 }
446
447 /**
448 * Gets the BGP session local AFI/SAFI configuration for IPv4 multicast.
449 *
450 * @return the BGP session local AFI/SAFI configuration for IPv4 multicast
451 */
452 public boolean getLocalIpv4Multicast() {
453 return localIpv4Multicast;
454 }
455
456 /**
457 * Gets the BGP session local AFI/SAFI configuration for IPv6 unicast.
458 *
459 * @return the BGP session local AFI/SAFI configuration for IPv6 unicast
460 */
461 public boolean getLocalIpv6Unicast() {
462 return localIpv6Unicast;
463 }
464
465 /**
466 * Gets the BGP session local AFI/SAFI configuration for IPv6 multicast.
467 *
468 * @return the BGP session local AFI/SAFI configuration for IPv6 multicast
469 */
470 public boolean getLocalIpv6Multicast() {
471 return localIpv6Multicast;
472 }
473
474 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700475 * Tests whether the session is closed.
Thomas Vachuska4b420772014-10-30 16:46:17 -0700476 * <p>
Jonathan Hartab63aac2014-10-16 08:52:55 -0700477 * NOTE: We use this method to avoid the Netty's asynchronous closing
478 * of a channel.
Thomas Vachuska4b420772014-10-30 16:46:17 -0700479 * </p>
480 * @return true if the session is closed
Jonathan Hartab63aac2014-10-16 08:52:55 -0700481 */
482 boolean isClosed() {
483 return isClosed;
484 }
485
486 /**
Jonathan Hartff071a22014-12-03 12:10:00 -0800487 * Closes the session.
488 *
489 * @param ctx the Channel Handler Context
490 */
491 void closeSession(ChannelHandlerContext ctx) {
492 timer.stop();
493 closeChannel(ctx);
494 }
495
496 /**
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800497 * Closes the Netty channel.
Jonathan Hartab63aac2014-10-16 08:52:55 -0700498 *
499 * @param ctx the Channel Handler Context
500 */
501 void closeChannel(ChannelHandlerContext ctx) {
502 isClosed = true;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700503 ctx.getChannel().close();
504 }
505
506 @Override
Pavlin Radoslavov7e190942014-11-13 18:50:59 -0800507 public void channelOpen(ChannelHandlerContext ctx,
508 ChannelStateEvent channelEvent) {
509 bgpSessionManager.addSessionChannel(channelEvent.getChannel());
510 }
511
512 @Override
513 public void channelClosed(ChannelHandlerContext ctx,
514 ChannelStateEvent channelEvent) {
515 bgpSessionManager.removeSessionChannel(channelEvent.getChannel());
516 }
517
518 @Override
Jonathan Hartab63aac2014-10-16 08:52:55 -0700519 public void channelConnected(ChannelHandlerContext ctx,
520 ChannelStateEvent channelEvent) {
521 localAddress = ctx.getChannel().getLocalAddress();
522 remoteAddress = ctx.getChannel().getRemoteAddress();
523
524 // Assign the local and remote IPv4 addresses
525 InetAddress inetAddr;
526 if (localAddress instanceof InetSocketAddress) {
527 inetAddr = ((InetSocketAddress) localAddress).getAddress();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800528 localIp4Address = Ip4Address.valueOf(inetAddr.getAddress());
Jonathan Hartab63aac2014-10-16 08:52:55 -0700529 }
530 if (remoteAddress instanceof InetSocketAddress) {
531 inetAddr = ((InetSocketAddress) remoteAddress).getAddress();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800532 remoteIp4Address = Ip4Address.valueOf(inetAddr.getAddress());
Jonathan Hartab63aac2014-10-16 08:52:55 -0700533 }
534
535 log.debug("BGP Session Connected from {} on {}",
536 remoteAddress, localAddress);
537 if (!bgpSessionManager.peerConnected(this)) {
538 log.debug("Cannot setup BGP Session Connection from {}. Closing...",
539 remoteAddress);
540 ctx.getChannel().close();
541 }
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800542
543 //
544 // Assign the local BGP ID
545 // NOTE: This should be configuration-based
546 //
547 localBgpId = bgpSessionManager.getMyBgpId();
Jonathan Hartab63aac2014-10-16 08:52:55 -0700548 }
549
550 @Override
551 public void channelDisconnected(ChannelHandlerContext ctx,
552 ChannelStateEvent channelEvent) {
553 log.debug("BGP Session Disconnected from {} on {}",
554 ctx.getChannel().getRemoteAddress(),
555 ctx.getChannel().getLocalAddress());
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800556 processChannelDisconnected();
557 }
Jonathan Hartab63aac2014-10-16 08:52:55 -0700558
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800559 @Override
560 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
561 log.debug("BGP Session Exception Caught from {} on {}: {}",
562 ctx.getChannel().getRemoteAddress(),
563 ctx.getChannel().getLocalAddress(),
564 e);
565 processChannelDisconnected();
566 }
567
568 /**
569 * Processes the channel being disconnected.
570 */
571 private void processChannelDisconnected() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700572 //
573 // Withdraw the routes advertised by this BGP peer
574 //
575 // NOTE: We must initialize the RIB-IN before propagating the withdraws
576 // for further processing. Otherwise, the BGP Decision Process
577 // will use those routes again.
578 //
579 Collection<BgpRouteEntry> deletedRoutes = bgpRibIn.values();
580 bgpRibIn = new ConcurrentHashMap<>();
581
582 // Push the updates to the BGP Merged RIB
583 BgpSessionManager.BgpRouteSelector bgpRouteSelector =
584 bgpSessionManager.getBgpRouteSelector();
585 Collection<BgpRouteEntry> addedRoutes = Collections.emptyList();
586 bgpRouteSelector.routeUpdates(this, addedRoutes, deletedRoutes);
587
588 bgpSessionManager.peerDisconnected(this);
589 }
590
591 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700592 * Restarts the BGP KeepaliveTimer.
593 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800594 void restartKeepaliveTimer(ChannelHandlerContext ctx) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700595 if (localKeepaliveInterval == 0) {
596 return; // Nothing to do
597 }
598 keepaliveTimeout = timer.newTimeout(new TransmitKeepaliveTask(ctx),
599 localKeepaliveInterval,
600 TimeUnit.SECONDS);
601 }
602
603 /**
604 * Task class for transmitting KEEPALIVE messages.
605 */
606 private final class TransmitKeepaliveTask implements TimerTask {
607 private final ChannelHandlerContext ctx;
608
609 /**
610 * Constructor for given Channel Handler Context.
611 *
612 * @param ctx the Channel Handler Context to use
613 */
614 TransmitKeepaliveTask(ChannelHandlerContext ctx) {
615 this.ctx = ctx;
616 }
617
618 @Override
619 public void run(Timeout timeout) throws Exception {
620 if (timeout.isCancelled()) {
621 return;
622 }
623 if (!ctx.getChannel().isOpen()) {
624 return;
625 }
626
627 // Transmit the KEEPALIVE
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800628 ChannelBuffer txMessage = BgpKeepalive.prepareBgpKeepalive();
Jonathan Hartab63aac2014-10-16 08:52:55 -0700629 ctx.getChannel().write(txMessage);
630
631 // Restart the KEEPALIVE timer
632 restartKeepaliveTimer(ctx);
633 }
634 }
635
636 /**
637 * Restarts the BGP Session Timeout Timer.
638 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800639 void restartSessionTimeoutTimer(ChannelHandlerContext ctx) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700640 if (remoteHoldtime == 0) {
641 return; // Nothing to do
642 }
643 if (sessionTimeout != null) {
644 sessionTimeout.cancel();
645 }
646 sessionTimeout = timer.newTimeout(new SessionTimeoutTask(ctx),
647 remoteHoldtime,
648 TimeUnit.SECONDS);
649 }
650
651 /**
652 * Task class for BGP Session timeout.
653 */
654 private final class SessionTimeoutTask implements TimerTask {
655 private final ChannelHandlerContext ctx;
656
657 /**
658 * Constructor for given Channel Handler Context.
659 *
660 * @param ctx the Channel Handler Context to use
661 */
662 SessionTimeoutTask(ChannelHandlerContext ctx) {
663 this.ctx = ctx;
664 }
665
666 @Override
667 public void run(Timeout timeout) throws Exception {
668 if (timeout.isCancelled()) {
669 return;
670 }
671 if (!ctx.getChannel().isOpen()) {
672 return;
673 }
674
675 log.debug("BGP Session Timeout: peer {}", remoteAddress);
676 //
677 // ERROR: Invalid Optional Parameter Length field: Unspecific
678 //
679 // Send NOTIFICATION and close the connection
680 int errorCode = HoldTimerExpired.ERROR_CODE;
681 int errorSubcode = Notifications.ERROR_SUBCODE_UNSPECIFIC;
682 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800683 BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
684 null);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700685 ctx.getChannel().write(txMessage);
686 closeChannel(ctx);
687 }
688 }
Jonathan Hartab63aac2014-10-16 08:52:55 -0700689}