blob: 494718bee14c9bd7c43c5cbfc88e7a6c1f1b2538 [file] [log] [blame]
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.onosproject.bgp.controller.impl;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.onosproject.bgp.controller.BgpCfg;
import org.onosproject.bgp.controller.BgpController;
import org.onosproject.bgp.controller.BgpPeerCfg;
import org.onosproject.bgp.controller.BgpConnectPeer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implements connection initiation to peer on peer configuration and manage channel using netty channel handler.
*/
public class BgpConnectPeerImpl implements BgpConnectPeer {
private static final Logger log = LoggerFactory.getLogger(BgpConnectPeerImpl.class);
private ScheduledExecutorService connectExecutor = null;
private final String peerHost;
private static final int RETRY_INTERVAL = 4;
private final int peerPort;
private int connectRetryCounter = 0;
private int connectRetryTime;
private ChannelPipelineFactory pfact;
private ClientBootstrap peerBootstrap;
private BgpCfg bgpconfig;
/**
* Initialize timer and initiate pipeline factory.
*
* @param bgpController parent BGP controller
* @param remoteHost remote host to connect
* @param remotePort remote port to connect
*/
public BgpConnectPeerImpl(BgpController bgpController, String remoteHost, int remotePort) {
this.bgpconfig = bgpController.getConfig();
this.pfact = new BgpPipelineFactory(bgpController, false);
this.peerBootstrap = Controller.peerBootstrap();
this.peerBootstrap.setPipelineFactory(pfact);
this.peerHost = remoteHost;
this.peerPort = remotePort;
this.connectRetryTime = 0;
}
@Override
public void disconnectPeer() {
if (connectExecutor != null) {
connectExecutor.shutdown();
connectExecutor = null;
}
}
@Override
public void connectPeer() {
scheduleConnectionRetry(this.connectRetryTime);
}
/**
* Retry connection with exponential back-off mechanism.
*
* @param retryDelay retry delay
*/
private void scheduleConnectionRetry(long retryDelay) {
if (this.connectExecutor == null) {
this.connectExecutor = Executors.newSingleThreadScheduledExecutor();
}
this.connectExecutor.schedule(new ConnectionRetry(), retryDelay, TimeUnit.MINUTES);
}
/**
* Implements BGP connection and manages connection to peer with back-off mechanism in case of failure.
*/
class ConnectionRetry implements Runnable {
@Override
public void run() {
log.debug("Connect to peer {}", peerHost);
InetSocketAddress connectToSocket = new InetSocketAddress(peerHost, peerPort);
try {
bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.CONNECT);
peerBootstrap.connect(connectToSocket).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.ACTIVE);
connectRetryCounter++;
log.error("Connection failed, ConnectRetryCounter {} remote host {}", connectRetryCounter,
peerHost);
/*
* Reconnect to peer on failure is exponential till 4 mins, later on retry after every 4
* mins.
*/
if (connectRetryTime < RETRY_INTERVAL) {
connectRetryTime = (connectRetryTime != 0) ? connectRetryTime * 2 : 1;
}
scheduleConnectionRetry(connectRetryTime);
} else {
connectRetryCounter++;
log.info("Connected to remote host {}, Connect Counter {}", peerHost, connectRetryCounter);
disconnectPeer();
return;
}
}
});
} catch (Exception e) {
log.info("Connect peer exception : " + e.toString());
disconnectPeer();
}
}
}
}