27db618d4d26f89cbc36b03067cef9896cba63d5
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11  * specific language governing permissions and limitations under the License.
12  */
13 package org.onosproject.bgp.controller.impl;
14
15 import java.net.InetSocketAddress;
16 import java.util.concurrent.Executors;
17 import java.util.concurrent.ScheduledExecutorService;
18 import java.util.concurrent.TimeUnit;
19
20 import org.jboss.netty.bootstrap.ClientBootstrap;
21 import org.jboss.netty.channel.ChannelFuture;
22 import org.jboss.netty.channel.ChannelFutureListener;
23 import org.jboss.netty.channel.ChannelPipelineFactory;
24 import org.onosproject.bgp.controller.BgpCfg;
25 import org.onosproject.bgp.controller.BgpController;
26 import org.onosproject.bgp.controller.BgpPeerCfg;
27 import org.onosproject.bgp.controller.BgpConnectPeer;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Implements connection initiation to peer on peer configuration and manage channel using netty channel handler.
33  */
34 public class BgpConnectPeerImpl implements BgpConnectPeer {
35     private static final Logger log = LoggerFactory.getLogger(BgpConnectPeerImpl.class);
36
37     private ScheduledExecutorService connectExecutor = null;
38     private final String peerHost;
39     private static final int RETRY_INTERVAL = 4;
40     private final int peerPort;
41     private int connectRetryCounter = 0;
42     private int connectRetryTime;
43     private ChannelPipelineFactory pfact;
44     private ClientBootstrap peerBootstrap;
45     private BgpCfg bgpconfig;
46
47     /**
48      * Initialize timer and initiate pipeline factory.
49      *
50      * @param bgpController parent BGP controller
51      * @param remoteHost remote host to connect
52      * @param remotePort remote port to connect
53      */
54     public BgpConnectPeerImpl(BgpController bgpController, String remoteHost, int remotePort) {
55
56         this.bgpconfig = bgpController.getConfig();
57         this.pfact = new BgpPipelineFactory(bgpController, false);
58         this.peerBootstrap = Controller.peerBootstrap();
59         this.peerBootstrap.setPipelineFactory(pfact);
60         this.peerHost = remoteHost;
61         this.peerPort = remotePort;
62         this.connectRetryTime = 0;
63     }
64
65     @Override
66     public void disconnectPeer() {
67         if (connectExecutor != null) {
68             connectExecutor.shutdown();
69             connectExecutor = null;
70         }
71     }
72
73     @Override
74     public void connectPeer() {
75         scheduleConnectionRetry(this.connectRetryTime);
76     }
77
78     /**
79      * Retry connection with exponential back-off mechanism.
80      *
81      * @param retryDelay retry delay
82      */
83     private void scheduleConnectionRetry(long retryDelay) {
84         if (this.connectExecutor == null) {
85             this.connectExecutor = Executors.newSingleThreadScheduledExecutor();
86         }
87         this.connectExecutor.schedule(new ConnectionRetry(), retryDelay, TimeUnit.MINUTES);
88     }
89
90     /**
91      * Implements BGP connection and manages connection to peer with back-off mechanism in case of failure.
92      */
93     class ConnectionRetry implements Runnable {
94         @Override
95         public void run() {
96             log.debug("Connect to peer {}", peerHost);
97
98             InetSocketAddress connectToSocket = new InetSocketAddress(peerHost, peerPort);
99
100             try {
101                 bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.CONNECT);
102                 peerBootstrap.connect(connectToSocket).addListener(new ChannelFutureListener() {
103                     @Override
104                     public void operationComplete(ChannelFuture future) throws Exception {
105                         if (!future.isSuccess()) {
106                             bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.ACTIVE);
107                             connectRetryCounter++;
108                             log.error("Connection failed, ConnectRetryCounter {} remote host {}", connectRetryCounter,
109                                       peerHost);
110                             /*
111                              * Reconnect to peer on failure is exponential till 4 mins, later on retry after every 4
112                              * mins.
113                              */
114                             if (connectRetryTime < RETRY_INTERVAL) {
115                                 connectRetryTime = (connectRetryTime != 0) ? connectRetryTime * 2 : 1;
116                             }
117                             scheduleConnectionRetry(connectRetryTime);
118                         } else {
119
120                             connectRetryCounter++;
121                             log.info("Connected to remote host {}, Connect Counter {}", peerHost, connectRetryCounter);
122                             disconnectPeer();
123                             return;
124                         }
125                     }
126                 });
127             } catch (Exception e) {
128                 log.info("Connect peer exception : " + e.toString());
129                 disconnectPeer();
130             }
131         }
132     }
133 }