blob: 59d0385784b06ebe815506f62a57c2d7777361be [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
Jonathan Hartab63aac2014-10-16 08:52:55 -070069 //
70 private SocketAddress localAddress; // Local IP addr/port
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080071 private Ip4Address localIp4Address; // Local IPv4 address
Jonathan Hartab63aac2014-10-16 08:52:55 -070072 private int localBgpVersion; // 1 octet
73 private long localAs; // 2 octets
74 private long localHoldtime; // 2 octets
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080075 private Ip4Address localBgpId; // 4 octets -> IPv4 address
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -080076 private boolean localIpv4Unicast; // Local IPv4/UNICAST AFI/SAFI
77 private boolean localIpv4Multicast; // Local IPv4/MULTICAST AFI/SAFI
78 private boolean localIpv6Unicast; // Local IPv6/UNICAST AFI/SAFI
79 private boolean localIpv6Multicast; // Local IPv6/MULTICAST AFI/SAFI
Jonathan Hartab63aac2014-10-16 08:52:55 -070080 //
81 private long localKeepaliveInterval; // Keepalive interval
82
83 // Timers state
84 private Timer timer = new HashedWheelTimer();
85 private volatile Timeout keepaliveTimeout; // Periodic KEEPALIVE
86 private volatile Timeout sessionTimeout; // Session timeout
87
88 // BGP RIB-IN routing entries from this peer
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080089 private ConcurrentMap<Ip4Prefix, BgpRouteEntry> bgpRibIn =
Jonathan Hartab63aac2014-10-16 08:52:55 -070090 new ConcurrentHashMap<>();
91
92 /**
93 * Constructor for a given BGP Session Manager.
94 *
95 * @param bgpSessionManager the BGP Session Manager to use
96 */
97 BgpSession(BgpSessionManager bgpSessionManager) {
98 this.bgpSessionManager = bgpSessionManager;
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080099
100 // NOTE: We support only BGP4
101 this.localBgpVersion = BgpConstants.BGP_VERSION;
102 }
103
104 /**
105 * Gets the BGP Session Manager.
106 *
107 * @return the BGP Session Manager
108 */
109 BgpSessionManager getBgpSessionManager() {
110 return bgpSessionManager;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700111 }
112
113 /**
114 * Gets the BGP RIB-IN routing entries.
115 *
116 * @return the BGP RIB-IN routing entries
117 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800118 public Map<Ip4Prefix, BgpRouteEntry> bgpRibIn() {
119 return bgpRibIn;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700120 }
121
122 /**
123 * Finds a BGP routing entry in the BGP RIB-IN.
124 *
125 * @param prefix the prefix of the route to search for
126 * @return the BGP routing entry if found, otherwise null
127 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800128 public BgpRouteEntry findBgpRouteEntry(Ip4Prefix prefix) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700129 return bgpRibIn.get(prefix);
130 }
131
132 /**
133 * Gets the BGP session remote address.
134 *
135 * @return the BGP session remote address
136 */
137 public SocketAddress getRemoteAddress() {
138 return remoteAddress;
139 }
140
141 /**
142 * Gets the BGP session remote IPv4 address.
143 *
144 * @return the BGP session remote IPv4 address
145 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800146 public Ip4Address getRemoteIp4Address() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700147 return remoteIp4Address;
148 }
149
150 /**
151 * Gets the BGP session remote BGP version.
152 *
153 * @return the BGP session remote BGP version
154 */
155 public int getRemoteBgpVersion() {
156 return remoteBgpVersion;
157 }
158
159 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800160 * Sets the BGP session remote BGP version.
161 *
162 * @param remoteBgpVersion the BGP session remote BGP version to set
163 */
164 void setRemoteBgpVersion(int remoteBgpVersion) {
165 this.remoteBgpVersion = remoteBgpVersion;
166 }
167
168 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700169 * Gets the BGP session remote AS number.
170 *
171 * @return the BGP session remote AS number
172 */
173 public long getRemoteAs() {
174 return remoteAs;
175 }
176
177 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800178 * Sets the BGP session remote AS number.
179 *
180 * @param remoteAs the BGP session remote AS number to set
181 */
182 void setRemoteAs(long remoteAs) {
183 this.remoteAs = remoteAs;
184
185 //
186 // NOTE: Currently, the local AS number is always set to the remote AS.
187 // This is done, because the peer setup is always iBGP.
188 // In the future the local AS number should be configured as part
189 // of an explicit BGP peering configuration.
190 //
191 this.localAs = remoteAs;
192 }
193
194 /**
Kunihiro Ishiguro828245c2014-12-18 17:54:18 +0900195 * Sets the BGP session remote 4 octet AS number.
196 *
197 * @param remoteAs4Octet the BGP session remote 4 octet AS number to set
198 */
199 void setRemoteAs4Octet(long remoteAs4Octet) {
200 this.remoteAs4Octet = remoteAs4Octet;
201 }
202
203 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700204 * Gets the BGP session remote Holdtime.
205 *
206 * @return the BGP session remote Holdtime
207 */
208 public long getRemoteHoldtime() {
209 return remoteHoldtime;
210 }
211
212 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800213 * Sets the BGP session remote Holdtime.
214 *
215 * @param remoteHoldtime the BGP session remote Holdtime to set
216 */
217 void setRemoteHoldtime(long remoteHoldtime) {
218 this.remoteHoldtime = remoteHoldtime;
219
220 //
221 // NOTE: Currently. the local BGP Holdtime is always set to the remote
222 // BGP holdtime.
223 // In the future, the local BGP Holdtime should be configured as part
224 // of an explicit BGP peering configuration.
225 //
226 this.localHoldtime = remoteHoldtime;
227
228 // Set the local Keepalive interval
229 if (localHoldtime == 0) {
230 localKeepaliveInterval = 0;
231 } else {
232 localKeepaliveInterval = Math.max(localHoldtime /
233 BgpConstants.BGP_KEEPALIVE_PER_HOLD_INTERVAL,
234 BgpConstants.BGP_KEEPALIVE_MIN_INTERVAL);
235 }
236 }
237
238 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700239 * Gets the BGP session remote BGP Identifier as an IPv4 address.
240 *
241 * @return the BGP session remote BGP Identifier as an IPv4 address
242 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800243 public Ip4Address getRemoteBgpId() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700244 return remoteBgpId;
245 }
246
247 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800248 * Sets the BGP session remote BGP Identifier as an IPv4 address.
249 *
250 * @param remoteBgpId the BGP session remote BGP Identifier to set
251 */
252 void setRemoteBgpId(Ip4Address remoteBgpId) {
253 this.remoteBgpId = remoteBgpId;
254 }
255
256 /**
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800257 * Gets the BGP session remote AFI/SAFI configuration for IPv4 unicast.
258 *
259 * @return the BGP session remote AFI/SAFI configuration for IPv4 unicast
260 */
261 public boolean getRemoteIpv4Unicast() {
262 return remoteIpv4Unicast;
263 }
264
265 /**
266 * Sets the BGP session remote AFI/SAFI configuration for IPv4 unicast.
267 */
268 void setRemoteIpv4Unicast() {
269 this.remoteIpv4Unicast = true;
270 // Copy the remote AFI/SAFI setting to the local configuration
271 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
272 // this.localIpv4Unicast = true;
273 }
274
275 /**
276 * Gets the BGP session remote AFI/SAFI configuration for IPv4 multicast.
277 *
278 * @return the BGP session remote AFI/SAFI configuration for IPv4 multicast
279 */
280 public boolean getRemoteIpv4Multicast() {
281 return remoteIpv4Multicast;
282 }
283
284 /**
285 * Sets the BGP session remote AFI/SAFI configuration for IPv4 multicast.
286 */
287 void setRemoteIpv4Multicast() {
288 this.remoteIpv4Multicast = true;
289 // Copy the remote AFI/SAFI setting to the local configuration
290 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
291 // this.localIpv4Multicast = true;
292 }
293
294 /**
295 * Gets the BGP session remote AFI/SAFI configuration for IPv6 unicast.
296 *
297 * @return the BGP session remote AFI/SAFI configuration for IPv6 unicast
298 */
299 public boolean getRemoteIpv6Unicast() {
300 return remoteIpv6Unicast;
301 }
302
303 /**
304 * Sets the BGP session remote AFI/SAFI configuration for IPv6 unicast.
305 */
306 void setRemoteIpv6Unicast() {
307 this.remoteIpv6Unicast = true;
308 // Copy the remote AFI/SAFI setting to the local configuration
309 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
310 // this.localIpv6Unicast = true;
311 }
312
313 /**
314 * Gets the BGP session remote AFI/SAFI configuration for IPv6 multicast.
315 *
316 * @return the BGP session remote AFI/SAFI configuration for IPv6 multicast
317 */
318 public boolean getRemoteIpv6Multicast() {
319 return remoteIpv6Multicast;
320 }
321
322 /**
323 * Sets the BGP session remote AFI/SAFI configuration for IPv6 multicast.
324 */
325 void setRemoteIpv6Multicast() {
326 this.remoteIpv6Multicast = true;
327 // Copy the remote AFI/SAFI setting to the local configuration
328 // NOTE: Uncomment the line below if the AFI/SAFI is supported locally
329 // this.localIpv6Multicast = true;
330 }
331
332 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700333 * Gets the BGP session local address.
334 *
335 * @return the BGP session local address
336 */
337 public SocketAddress getLocalAddress() {
338 return localAddress;
339 }
340
341 /**
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800342 * Gets the BGP session local IPv4 address.
343 *
344 * @return the BGP session local IPv4 address
345 */
346 public Ip4Address getLocalIp4Address() {
347 return localIp4Address;
348 }
349
350 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700351 * Gets the BGP session local BGP version.
352 *
353 * @return the BGP session local BGP version
354 */
355 public int getLocalBgpVersion() {
356 return localBgpVersion;
357 }
358
359 /**
360 * Gets the BGP session local AS number.
361 *
362 * @return the BGP session local AS number
363 */
364 public long getLocalAs() {
365 return localAs;
366 }
367
368 /**
369 * Gets the BGP session local Holdtime.
370 *
371 * @return the BGP session local Holdtime
372 */
373 public long getLocalHoldtime() {
374 return localHoldtime;
375 }
376
377 /**
378 * Gets the BGP session local BGP Identifier as an IPv4 address.
379 *
380 * @return the BGP session local BGP Identifier as an IPv4 address
381 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800382 public Ip4Address getLocalBgpId() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700383 return localBgpId;
384 }
385
386 /**
Pavlin Radoslavov278cdde2014-12-16 14:09:31 -0800387 * Gets the BGP session local AFI/SAFI configuration for IPv4 unicast.
388 *
389 * @return the BGP session local AFI/SAFI configuration for IPv4 unicast
390 */
391 public boolean getLocalIpv4Unicast() {
392 return localIpv4Unicast;
393 }
394
395 /**
396 * Gets the BGP session local AFI/SAFI configuration for IPv4 multicast.
397 *
398 * @return the BGP session local AFI/SAFI configuration for IPv4 multicast
399 */
400 public boolean getLocalIpv4Multicast() {
401 return localIpv4Multicast;
402 }
403
404 /**
405 * Gets the BGP session local AFI/SAFI configuration for IPv6 unicast.
406 *
407 * @return the BGP session local AFI/SAFI configuration for IPv6 unicast
408 */
409 public boolean getLocalIpv6Unicast() {
410 return localIpv6Unicast;
411 }
412
413 /**
414 * Gets the BGP session local AFI/SAFI configuration for IPv6 multicast.
415 *
416 * @return the BGP session local AFI/SAFI configuration for IPv6 multicast
417 */
418 public boolean getLocalIpv6Multicast() {
419 return localIpv6Multicast;
420 }
421
422 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700423 * Tests whether the session is closed.
Thomas Vachuska4b420772014-10-30 16:46:17 -0700424 * <p>
Jonathan Hartab63aac2014-10-16 08:52:55 -0700425 * NOTE: We use this method to avoid the Netty's asynchronous closing
426 * of a channel.
Thomas Vachuska4b420772014-10-30 16:46:17 -0700427 * </p>
428 * @return true if the session is closed
Jonathan Hartab63aac2014-10-16 08:52:55 -0700429 */
430 boolean isClosed() {
431 return isClosed;
432 }
433
434 /**
Jonathan Hartff071a22014-12-03 12:10:00 -0800435 * Closes the session.
436 *
437 * @param ctx the Channel Handler Context
438 */
439 void closeSession(ChannelHandlerContext ctx) {
440 timer.stop();
441 closeChannel(ctx);
442 }
443
444 /**
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800445 * Closes the Netty channel.
Jonathan Hartab63aac2014-10-16 08:52:55 -0700446 *
447 * @param ctx the Channel Handler Context
448 */
449 void closeChannel(ChannelHandlerContext ctx) {
450 isClosed = true;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700451 ctx.getChannel().close();
452 }
453
454 @Override
Pavlin Radoslavov7e190942014-11-13 18:50:59 -0800455 public void channelOpen(ChannelHandlerContext ctx,
456 ChannelStateEvent channelEvent) {
457 bgpSessionManager.addSessionChannel(channelEvent.getChannel());
458 }
459
460 @Override
461 public void channelClosed(ChannelHandlerContext ctx,
462 ChannelStateEvent channelEvent) {
463 bgpSessionManager.removeSessionChannel(channelEvent.getChannel());
464 }
465
466 @Override
Jonathan Hartab63aac2014-10-16 08:52:55 -0700467 public void channelConnected(ChannelHandlerContext ctx,
468 ChannelStateEvent channelEvent) {
469 localAddress = ctx.getChannel().getLocalAddress();
470 remoteAddress = ctx.getChannel().getRemoteAddress();
471
472 // Assign the local and remote IPv4 addresses
473 InetAddress inetAddr;
474 if (localAddress instanceof InetSocketAddress) {
475 inetAddr = ((InetSocketAddress) localAddress).getAddress();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800476 localIp4Address = Ip4Address.valueOf(inetAddr.getAddress());
Jonathan Hartab63aac2014-10-16 08:52:55 -0700477 }
478 if (remoteAddress instanceof InetSocketAddress) {
479 inetAddr = ((InetSocketAddress) remoteAddress).getAddress();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800480 remoteIp4Address = Ip4Address.valueOf(inetAddr.getAddress());
Jonathan Hartab63aac2014-10-16 08:52:55 -0700481 }
482
483 log.debug("BGP Session Connected from {} on {}",
484 remoteAddress, localAddress);
485 if (!bgpSessionManager.peerConnected(this)) {
486 log.debug("Cannot setup BGP Session Connection from {}. Closing...",
487 remoteAddress);
488 ctx.getChannel().close();
489 }
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800490
491 //
492 // Assign the local BGP ID
493 // NOTE: This should be configuration-based
494 //
495 localBgpId = bgpSessionManager.getMyBgpId();
Jonathan Hartab63aac2014-10-16 08:52:55 -0700496 }
497
498 @Override
499 public void channelDisconnected(ChannelHandlerContext ctx,
500 ChannelStateEvent channelEvent) {
501 log.debug("BGP Session Disconnected from {} on {}",
502 ctx.getChannel().getRemoteAddress(),
503 ctx.getChannel().getLocalAddress());
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800504 processChannelDisconnected();
505 }
Jonathan Hartab63aac2014-10-16 08:52:55 -0700506
Pavlin Radoslavov0a714722014-12-03 13:44:08 -0800507 @Override
508 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
509 log.debug("BGP Session Exception Caught from {} on {}: {}",
510 ctx.getChannel().getRemoteAddress(),
511 ctx.getChannel().getLocalAddress(),
512 e);
513 processChannelDisconnected();
514 }
515
516 /**
517 * Processes the channel being disconnected.
518 */
519 private void processChannelDisconnected() {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700520 //
521 // Withdraw the routes advertised by this BGP peer
522 //
523 // NOTE: We must initialize the RIB-IN before propagating the withdraws
524 // for further processing. Otherwise, the BGP Decision Process
525 // will use those routes again.
526 //
527 Collection<BgpRouteEntry> deletedRoutes = bgpRibIn.values();
528 bgpRibIn = new ConcurrentHashMap<>();
529
530 // Push the updates to the BGP Merged RIB
531 BgpSessionManager.BgpRouteSelector bgpRouteSelector =
532 bgpSessionManager.getBgpRouteSelector();
533 Collection<BgpRouteEntry> addedRoutes = Collections.emptyList();
534 bgpRouteSelector.routeUpdates(this, addedRoutes, deletedRoutes);
535
536 bgpSessionManager.peerDisconnected(this);
537 }
538
539 /**
Jonathan Hartab63aac2014-10-16 08:52:55 -0700540 * Restarts the BGP KeepaliveTimer.
541 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800542 void restartKeepaliveTimer(ChannelHandlerContext ctx) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700543 if (localKeepaliveInterval == 0) {
544 return; // Nothing to do
545 }
546 keepaliveTimeout = timer.newTimeout(new TransmitKeepaliveTask(ctx),
547 localKeepaliveInterval,
548 TimeUnit.SECONDS);
549 }
550
551 /**
552 * Task class for transmitting KEEPALIVE messages.
553 */
554 private final class TransmitKeepaliveTask implements TimerTask {
555 private final ChannelHandlerContext ctx;
556
557 /**
558 * Constructor for given Channel Handler Context.
559 *
560 * @param ctx the Channel Handler Context to use
561 */
562 TransmitKeepaliveTask(ChannelHandlerContext ctx) {
563 this.ctx = ctx;
564 }
565
566 @Override
567 public void run(Timeout timeout) throws Exception {
568 if (timeout.isCancelled()) {
569 return;
570 }
571 if (!ctx.getChannel().isOpen()) {
572 return;
573 }
574
575 // Transmit the KEEPALIVE
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800576 ChannelBuffer txMessage = BgpKeepalive.prepareBgpKeepalive();
Jonathan Hartab63aac2014-10-16 08:52:55 -0700577 ctx.getChannel().write(txMessage);
578
579 // Restart the KEEPALIVE timer
580 restartKeepaliveTimer(ctx);
581 }
582 }
583
584 /**
585 * Restarts the BGP Session Timeout Timer.
586 */
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800587 void restartSessionTimeoutTimer(ChannelHandlerContext ctx) {
Jonathan Hartab63aac2014-10-16 08:52:55 -0700588 if (remoteHoldtime == 0) {
589 return; // Nothing to do
590 }
591 if (sessionTimeout != null) {
592 sessionTimeout.cancel();
593 }
594 sessionTimeout = timer.newTimeout(new SessionTimeoutTask(ctx),
595 remoteHoldtime,
596 TimeUnit.SECONDS);
597 }
598
599 /**
600 * Task class for BGP Session timeout.
601 */
602 private final class SessionTimeoutTask implements TimerTask {
603 private final ChannelHandlerContext ctx;
604
605 /**
606 * Constructor for given Channel Handler Context.
607 *
608 * @param ctx the Channel Handler Context to use
609 */
610 SessionTimeoutTask(ChannelHandlerContext ctx) {
611 this.ctx = ctx;
612 }
613
614 @Override
615 public void run(Timeout timeout) throws Exception {
616 if (timeout.isCancelled()) {
617 return;
618 }
619 if (!ctx.getChannel().isOpen()) {
620 return;
621 }
622
623 log.debug("BGP Session Timeout: peer {}", remoteAddress);
624 //
625 // ERROR: Invalid Optional Parameter Length field: Unspecific
626 //
627 // Send NOTIFICATION and close the connection
628 int errorCode = HoldTimerExpired.ERROR_CODE;
629 int errorSubcode = Notifications.ERROR_SUBCODE_UNSPECIFIC;
630 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800631 BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
632 null);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700633 ctx.getChannel().write(txMessage);
634 closeChannel(ctx);
635 }
636 }
Jonathan Hartab63aac2014-10-16 08:52:55 -0700637}