blob: a4fd63c139c64356d72976fd9e7fa5aeb863a132 [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
62 private long remoteHoldtime; // 2 octets
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080063 private Ip4Address remoteBgpId; // 4 octets -> IPv4 address
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -080064 private boolean remoteIpv4Unicast; // Peer IPv4/UNICAST AFI/SAFI
65 private boolean remoteIpv4Multicast; // Peer IPv4/MULTICAST AFI/SAFI
66 private boolean remoteIpv6Unicast; // Peer IPv6/UNICAST AFI/SAFI
67 private boolean remoteIpv6Multicast; // Peer IPv6/MULTICAST AFI/SAFI
Jonathan Hartab63aac2014-10-16 08:52:55 -070068 //
69 private SocketAddress localAddress; // Local IP addr/port
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080070 private Ip4Address localIp4Address; // Local IPv4 address
Jonathan Hartab63aac2014-10-16 08:52:55 -070071 private int localBgpVersion; // 1 octet
72 private long localAs; // 2 octets
73 private long localHoldtime; // 2 octets
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080074 private Ip4Address localBgpId; // 4 octets -> IPv4 address
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -080075 private boolean localIpv4Unicast; // Local IPv4/UNICAST AFI/SAFI
76 private boolean localIpv4Multicast; // Local IPv4/MULTICAST AFI/SAFI
77 private boolean localIpv6Unicast; // Local IPv6/UNICAST AFI/SAFI
78 private boolean localIpv6Multicast; // Local IPv6/MULTICAST AFI/SAFI
Jonathan Hartab63aac2014-10-16 08:52:55 -070079 //
80 private long localKeepaliveInterval; // Keepalive interval
81
82 // Timers state
83 private Timer timer = new HashedWheelTimer();
84 private volatile Timeout keepaliveTimeout; // Periodic KEEPALIVE
85 private volatile Timeout sessionTimeout; // Session timeout
86
87 // BGP RIB-IN routing entries from this peer
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080088 private ConcurrentMap<Ip4Prefix, BgpRouteEntry> bgpRibIn =
Jonathan Hartab63aac2014-10-16 08:52:55 -070089 new ConcurrentHashMap<>();
90
91 /**
92 * Constructor for a given BGP Session Manager.
93 *
94 * @param bgpSessionManager the BGP Session Manager to use
95 */
96 BgpSession(BgpSessionManager bgpSessionManager) {
97 this.bgpSessionManager = bgpSessionManager;
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080098
99 // NOTE: We support only BGP4
100 this.localBgpVersion = BgpConstants.BGP_VERSION;
101 }
102
103 /**
104 * Gets the BGP Session Manager.
105 *
106 * @return the BGP Session Manager
107 */
108 BgpSessionManager getBgpSessionManager() {
109 return bgpSessionManager;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700110 }
111
112 /**
113 * Gets the BGP RIB-IN routing entries.
114 *
115 * @return the BGP RIB-IN routing entries
116 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800117 public Map<Ip4Prefix, BgpRouteEntry> bgpRibIn() {
118 return bgpRibIn;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700119 }
120
121 /**
122 * Finds a BGP routing entry in the BGP RIB-IN.
123 *
124 * @param prefix the prefix of the route to search for
125 * @return the BGP routing entry if found, otherwise null
126 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800127 public BgpRouteEntry findBgpRouteEntry(Ip4Prefix prefix) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700128 return bgpRibIn.get(prefix);
129 }
130
131 /**
132 * Gets the BGP session remote address.
133 *
134 * @return the BGP session remote address
135 */
136 public SocketAddress getRemoteAddress() {
137 return remoteAddress;
138 }
139
140 /**
141 * Gets the BGP session remote IPv4 address.
142 *
143 * @return the BGP session remote IPv4 address
144 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800145 public Ip4Address getRemoteIp4Address() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700146 return remoteIp4Address;
147 }
148
149 /**
150 * Gets the BGP session remote BGP version.
151 *
152 * @return the BGP session remote BGP version
153 */
154 public int getRemoteBgpVersion() {
155 return remoteBgpVersion;
156 }
157
158 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800159 * Sets the BGP session remote BGP version.
160 *
161 * @param remoteBgpVersion the BGP session remote BGP version to set
162 */
163 void setRemoteBgpVersion(int remoteBgpVersion) {
164 this.remoteBgpVersion = remoteBgpVersion;
165 }
166
167 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700168 * Gets the BGP session remote AS number.
169 *
170 * @return the BGP session remote AS number
171 */
172 public long getRemoteAs() {
173 return remoteAs;
174 }
175
176 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800177 * Sets the BGP session remote AS number.
178 *
179 * @param remoteAs the BGP session remote AS number to set
180 */
181 void setRemoteAs(long remoteAs) {
182 this.remoteAs = remoteAs;
183
184 //
185 // NOTE: Currently, the local AS number is always set to the remote AS.
186 // This is done, because the peer setup is always iBGP.
187 // In the future the local AS number should be configured as part
188 // of an explicit BGP peering configuration.
189 //
190 this.localAs = remoteAs;
191 }
192
193 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700194 * Gets the BGP session remote Holdtime.
195 *
196 * @return the BGP session remote Holdtime
197 */
198 public long getRemoteHoldtime() {
199 return remoteHoldtime;
200 }
201
202 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800203 * Sets the BGP session remote Holdtime.
204 *
205 * @param remoteHoldtime the BGP session remote Holdtime to set
206 */
207 void setRemoteHoldtime(long remoteHoldtime) {
208 this.remoteHoldtime = remoteHoldtime;
209
210 //
211 // NOTE: Currently. the local BGP Holdtime is always set to the remote
212 // BGP holdtime.
213 // In the future, the local BGP Holdtime should be configured as part
214 // of an explicit BGP peering configuration.
215 //
216 this.localHoldtime = remoteHoldtime;
217
218 // Set the local Keepalive interval
219 if (localHoldtime == 0) {
220 localKeepaliveInterval = 0;
221 } else {
222 localKeepaliveInterval = Math.max(localHoldtime /
223 BgpConstants.BGP_KEEPALIVE_PER_HOLD_INTERVAL,
224 BgpConstants.BGP_KEEPALIVE_MIN_INTERVAL);
225 }
226 }
227
228 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700229 * Gets the BGP session remote BGP Identifier as an IPv4 address.
230 *
231 * @return the BGP session remote BGP Identifier as an IPv4 address
232 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800233 public Ip4Address getRemoteBgpId() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700234 return remoteBgpId;
235 }
236
237 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800238 * Sets the BGP session remote BGP Identifier as an IPv4 address.
239 *
240 * @param remoteBgpId the BGP session remote BGP Identifier to set
241 */
242 void setRemoteBgpId(Ip4Address remoteBgpId) {
243 this.remoteBgpId = remoteBgpId;
244 }
245
246 /**
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800247 * Gets the BGP session remote AFI/SAFI configuration for IPv4 unicast.
248 *
249 * @return the BGP session remote AFI/SAFI configuration for IPv4 unicast
250 */
251 public boolean getRemoteIpv4Unicast() {
252 return remoteIpv4Unicast;
253 }
254
255 /**
256 * Sets the BGP session remote AFI/SAFI configuration for IPv4 unicast.
257 */
258 void setRemoteIpv4Unicast() {
259 this.remoteIpv4Unicast = true;
260 // Copy the remote AFI/SAFI setting to the local configuration
261 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
262 // this.localIpv4Unicast = true;
263 }
264
265 /**
266 * Gets the BGP session remote AFI/SAFI configuration for IPv4 multicast.
267 *
268 * @return the BGP session remote AFI/SAFI configuration for IPv4 multicast
269 */
270 public boolean getRemoteIpv4Multicast() {
271 return remoteIpv4Multicast;
272 }
273
274 /**
275 * Sets the BGP session remote AFI/SAFI configuration for IPv4 multicast.
276 */
277 void setRemoteIpv4Multicast() {
278 this.remoteIpv4Multicast = true;
279 // Copy the remote AFI/SAFI setting to the local configuration
280 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
281 // this.localIpv4Multicast = true;
282 }
283
284 /**
285 * Gets the BGP session remote AFI/SAFI configuration for IPv6 unicast.
286 *
287 * @return the BGP session remote AFI/SAFI configuration for IPv6 unicast
288 */
289 public boolean getRemoteIpv6Unicast() {
290 return remoteIpv6Unicast;
291 }
292
293 /**
294 * Sets the BGP session remote AFI/SAFI configuration for IPv6 unicast.
295 */
296 void setRemoteIpv6Unicast() {
297 this.remoteIpv6Unicast = true;
298 // Copy the remote AFI/SAFI setting to the local configuration
299 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
300 // this.localIpv6Unicast = true;
301 }
302
303 /**
304 * Gets the BGP session remote AFI/SAFI configuration for IPv6 multicast.
305 *
306 * @return the BGP session remote AFI/SAFI configuration for IPv6 multicast
307 */
308 public boolean getRemoteIpv6Multicast() {
309 return remoteIpv6Multicast;
310 }
311
312 /**
313 * Sets the BGP session remote AFI/SAFI configuration for IPv6 multicast.
314 */
315 void setRemoteIpv6Multicast() {
316 this.remoteIpv6Multicast = true;
317 // Copy the remote AFI/SAFI setting to the local configuration
318 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
319 // this.localIpv6Multicast = true;
320 }
321
322 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700323 * Gets the BGP session local address.
324 *
325 * @return the BGP session local address
326 */
327 public SocketAddress getLocalAddress() {
328 return localAddress;
329 }
330
331 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800332 * Gets the BGP session local IPv4 address.
333 *
334 * @return the BGP session local IPv4 address
335 */
336 public Ip4Address getLocalIp4Address() {
337 return localIp4Address;
338 }
339
340 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700341 * Gets the BGP session local BGP version.
342 *
343 * @return the BGP session local BGP version
344 */
345 public int getLocalBgpVersion() {
346 return localBgpVersion;
347 }
348
349 /**
350 * Gets the BGP session local AS number.
351 *
352 * @return the BGP session local AS number
353 */
354 public long getLocalAs() {
355 return localAs;
356 }
357
358 /**
359 * Gets the BGP session local Holdtime.
360 *
361 * @return the BGP session local Holdtime
362 */
363 public long getLocalHoldtime() {
364 return localHoldtime;
365 }
366
367 /**
368 * Gets the BGP session local BGP Identifier as an IPv4 address.
369 *
370 * @return the BGP session local BGP Identifier as an IPv4 address
371 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800372 public Ip4Address getLocalBgpId() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700373 return localBgpId;
374 }
375
376 /**
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800377 * Gets the BGP session local AFI/SAFI configuration for IPv4 unicast.
378 *
379 * @return the BGP session local AFI/SAFI configuration for IPv4 unicast
380 */
381 public boolean getLocalIpv4Unicast() {
382 return localIpv4Unicast;
383 }
384
385 /**
386 * Gets the BGP session local AFI/SAFI configuration for IPv4 multicast.
387 *
388 * @return the BGP session local AFI/SAFI configuration for IPv4 multicast
389 */
390 public boolean getLocalIpv4Multicast() {
391 return localIpv4Multicast;
392 }
393
394 /**
395 * Gets the BGP session local AFI/SAFI configuration for IPv6 unicast.
396 *
397 * @return the BGP session local AFI/SAFI configuration for IPv6 unicast
398 */
399 public boolean getLocalIpv6Unicast() {
400 return localIpv6Unicast;
401 }
402
403 /**
404 * Gets the BGP session local AFI/SAFI configuration for IPv6 multicast.
405 *
406 * @return the BGP session local AFI/SAFI configuration for IPv6 multicast
407 */
408 public boolean getLocalIpv6Multicast() {
409 return localIpv6Multicast;
410 }
411
412 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700413 * Tests whether the session is closed.
Thomas Vachuska4b420772014-10-30 16:46:17 -0700414 * <p>
Jonathan Hartab63aac2014-10-16 08:52:55 -0700415 * NOTE: We use this method to avoid the Netty's asynchronous closing
416 * of a channel.
Thomas Vachuska4b420772014-10-30 16:46:17 -0700417 * </p>
418 * @return true if the session is closed
Jonathan Hartab63aac2014-10-16 08:52:55 -0700419 */
420 boolean isClosed() {
421 return isClosed;
422 }
423
424 /**
Jonathan Hartff071a22014-12-03 12:10:00 -0800425 * Closes the session.
426 *
427 * @param ctx the Channel Handler Context
428 */
429 void closeSession(ChannelHandlerContext ctx) {
430 timer.stop();
431 closeChannel(ctx);
432 }
433
434 /**
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800435 * Closes the Netty channel.
Jonathan Hartab63aac2014-10-16 08:52:55 -0700436 *
437 * @param ctx the Channel Handler Context
438 */
439 void closeChannel(ChannelHandlerContext ctx) {
440 isClosed = true;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700441 ctx.getChannel().close();
442 }
443
444 @Override
Pavlin Radoslavov7e190942014-11-13 18:50:59 -0800445 public void channelOpen(ChannelHandlerContext ctx,
446 ChannelStateEvent channelEvent) {
447 bgpSessionManager.addSessionChannel(channelEvent.getChannel());
448 }
449
450 @Override
451 public void channelClosed(ChannelHandlerContext ctx,
452 ChannelStateEvent channelEvent) {
453 bgpSessionManager.removeSessionChannel(channelEvent.getChannel());
454 }
455
456 @Override
Jonathan Hartab63aac2014-10-16 08:52:55 -0700457 public void channelConnected(ChannelHandlerContext ctx,
458 ChannelStateEvent channelEvent) {
459 localAddress = ctx.getChannel().getLocalAddress();
460 remoteAddress = ctx.getChannel().getRemoteAddress();
461
462 // Assign the local and remote IPv4 addresses
463 InetAddress inetAddr;
464 if (localAddress instanceof InetSocketAddress) {
465 inetAddr = ((InetSocketAddress) localAddress).getAddress();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800466 localIp4Address = Ip4Address.valueOf(inetAddr.getAddress());
Jonathan Hartab63aac2014-10-16 08:52:55 -0700467 }
468 if (remoteAddress instanceof InetSocketAddress) {
469 inetAddr = ((InetSocketAddress) remoteAddress).getAddress();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800470 remoteIp4Address = Ip4Address.valueOf(inetAddr.getAddress());
Jonathan Hartab63aac2014-10-16 08:52:55 -0700471 }
472
473 log.debug("BGP Session Connected from {} on {}",
474 remoteAddress, localAddress);
475 if (!bgpSessionManager.peerConnected(this)) {
476 log.debug("Cannot setup BGP Session Connection from {}. Closing...",
477 remoteAddress);
478 ctx.getChannel().close();
479 }
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800480
481 //
482 // Assign the local BGP ID
483 // NOTE: This should be configuration-based
484 //
485 localBgpId = bgpSessionManager.getMyBgpId();
Jonathan Hartab63aac2014-10-16 08:52:55 -0700486 }
487
488 @Override
489 public void channelDisconnected(ChannelHandlerContext ctx,
490 ChannelStateEvent channelEvent) {
491 log.debug("BGP Session Disconnected from {} on {}",
492 ctx.getChannel().getRemoteAddress(),
493 ctx.getChannel().getLocalAddress());
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800494 processChannelDisconnected();
495 }
Jonathan Hartab63aac2014-10-16 08:52:55 -0700496
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800497 @Override
498 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
499 log.debug("BGP Session Exception Caught from {} on {}: {}",
500 ctx.getChannel().getRemoteAddress(),
501 ctx.getChannel().getLocalAddress(),
502 e);
503 processChannelDisconnected();
504 }
505
506 /**
507 * Processes the channel being disconnected.
508 */
509 private void processChannelDisconnected() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700510 //
511 // Withdraw the routes advertised by this BGP peer
512 //
513 // NOTE: We must initialize the RIB-IN before propagating the withdraws
514 // for further processing. Otherwise, the BGP Decision Process
515 // will use those routes again.
516 //
517 Collection<BgpRouteEntry> deletedRoutes = bgpRibIn.values();
518 bgpRibIn = new ConcurrentHashMap<>();
519
520 // Push the updates to the BGP Merged RIB
521 BgpSessionManager.BgpRouteSelector bgpRouteSelector =
522 bgpSessionManager.getBgpRouteSelector();
523 Collection<BgpRouteEntry> addedRoutes = Collections.emptyList();
524 bgpRouteSelector.routeUpdates(this, addedRoutes, deletedRoutes);
525
526 bgpSessionManager.peerDisconnected(this);
527 }
528
529 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700530 * Restarts the BGP KeepaliveTimer.
531 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800532 void restartKeepaliveTimer(ChannelHandlerContext ctx) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700533 if (localKeepaliveInterval == 0) {
534 return; // Nothing to do
535 }
536 keepaliveTimeout = timer.newTimeout(new TransmitKeepaliveTask(ctx),
537 localKeepaliveInterval,
538 TimeUnit.SECONDS);
539 }
540
541 /**
542 * Task class for transmitting KEEPALIVE messages.
543 */
544 private final class TransmitKeepaliveTask implements TimerTask {
545 private final ChannelHandlerContext ctx;
546
547 /**
548 * Constructor for given Channel Handler Context.
549 *
550 * @param ctx the Channel Handler Context to use
551 */
552 TransmitKeepaliveTask(ChannelHandlerContext ctx) {
553 this.ctx = ctx;
554 }
555
556 @Override
557 public void run(Timeout timeout) throws Exception {
558 if (timeout.isCancelled()) {
559 return;
560 }
561 if (!ctx.getChannel().isOpen()) {
562 return;
563 }
564
565 // Transmit the KEEPALIVE
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800566 ChannelBuffer txMessage = BgpKeepalive.prepareBgpKeepalive();
Jonathan Hartab63aac2014-10-16 08:52:55 -0700567 ctx.getChannel().write(txMessage);
568
569 // Restart the KEEPALIVE timer
570 restartKeepaliveTimer(ctx);
571 }
572 }
573
574 /**
575 * Restarts the BGP Session Timeout Timer.
576 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800577 void restartSessionTimeoutTimer(ChannelHandlerContext ctx) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700578 if (remoteHoldtime == 0) {
579 return; // Nothing to do
580 }
581 if (sessionTimeout != null) {
582 sessionTimeout.cancel();
583 }
584 sessionTimeout = timer.newTimeout(new SessionTimeoutTask(ctx),
585 remoteHoldtime,
586 TimeUnit.SECONDS);
587 }
588
589 /**
590 * Task class for BGP Session timeout.
591 */
592 private final class SessionTimeoutTask implements TimerTask {
593 private final ChannelHandlerContext ctx;
594
595 /**
596 * Constructor for given Channel Handler Context.
597 *
598 * @param ctx the Channel Handler Context to use
599 */
600 SessionTimeoutTask(ChannelHandlerContext ctx) {
601 this.ctx = ctx;
602 }
603
604 @Override
605 public void run(Timeout timeout) throws Exception {
606 if (timeout.isCancelled()) {
607 return;
608 }
609 if (!ctx.getChannel().isOpen()) {
610 return;
611 }
612
613 log.debug("BGP Session Timeout: peer {}", remoteAddress);
614 //
615 // ERROR: Invalid Optional Parameter Length field: Unspecific
616 //
617 // Send NOTIFICATION and close the connection
618 int errorCode = HoldTimerExpired.ERROR_CODE;
619 int errorSubcode = Notifications.ERROR_SUBCODE_UNSPECIFIC;
620 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800621 BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
622 null);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700623 ctx.getChannel().write(txMessage);
624 closeChannel(ctx);
625 }
626 }
Jonathan Hartab63aac2014-10-16 08:52:55 -0700627}