3311f0350ed45d700f3426b46f370772198ceee4
[netvirt.git] / vpnservice / bgpmanager / bgpmanager-impl / src / main / java / org / opendaylight / netvirt / bgpmanager / thrift / client / BgpRouter.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.bgpmanager.thrift.client;
10
11 import java.util.*;
12 import org.apache.thrift.protocol.TBinaryProtocol;
13 import org.apache.thrift.protocol.TProtocol;
14 import org.apache.thrift.TException;
15 import org.apache.thrift.transport.TSocket;
16 import org.apache.thrift.transport.TTransport;
17 import org.apache.thrift.transport.TTransportException;
18 import org.opendaylight.netvirt.bgpmanager.thrift.gen.*;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 public class BgpRouter {
23     private static TTransport transport;
24     private static TProtocol protocol;
25     private static BgpConfigurator.Client bgpClient=null;
26     boolean isConnected = false;
27     private static final Logger LOGGER = LoggerFactory.getLogger(BgpRouter.class);
28     public int startBGPresult = Integer.MIN_VALUE;
29     public String bgpHost = null;
30     public int bgpHostPort = 0;
31     private long startTS = 0;
32     private long connectTS = 0;
33     private long lastConnectedTS = 0;
34
35     public long getLastConnectedTS() {
36         return lastConnectedTS;
37     }
38
39     public void setLastConnectedTS(long lastConnectedTS) {
40         this.lastConnectedTS = lastConnectedTS;
41     }
42
43     public long getConnectTS() {
44         return connectTS;
45     }
46
47     public void setConnectTS(long connectTS) {
48         this.connectTS = connectTS;
49     }
50
51     public long getStartTS() {
52         return startTS;
53     }
54
55     public void setStartTS(long startTS) {
56         this.startTS = startTS;
57     }
58
59
60     private enum Optype {
61         START, STOP, NBR, VRF, PFX, SRC, MHOP, LOG, AF, GR
62     };
63
64     private final static int GET_RTS_INIT = 0;
65     private final static int GET_RTS_NEXT = 1;
66     private final static int CONNECTION_TIMEOUT = 60000;
67
68
69     private class BgpOp {
70         public Optype type;
71         public boolean add;
72         public String[] strs;
73         public int[] ints;
74         public List<String> irts;
75         public List<String> erts;
76         public static final int ignore = 0;
77         public BgpOp() {
78             strs = new String[3];
79             ints = new int[2];
80         }
81     }
82
83     private static BgpOp bop;
84
85     public synchronized void disconnect() {
86         bgpClient = null;
87         isConnected = false;
88         if (transport != null) {
89             transport.close();
90         }
91     }
92
93     public synchronized boolean connect(String bgpHost, int bgpPort) {
94         String msgPiece = "BGP config server at "+bgpHost+":"+bgpPort;
95
96         this.bgpHost = bgpHost;
97         this.bgpHostPort = bgpPort;
98
99         disconnect();
100         setConnectTS(System.currentTimeMillis());
101         try {
102             TSocket ts = new TSocket(bgpHost, bgpPort, CONNECTION_TIMEOUT);
103             transport = ts;
104             transport.open();
105             ts.setTimeout(0);
106             isConnected = true;
107             setLastConnectedTS(System.currentTimeMillis());
108         } catch (TTransportException tte) {
109             LOGGER.error("Failed connecting to " + msgPiece + "; Exception: " + tte);
110             isConnected = false;
111             return false;
112         }
113         protocol = new TBinaryProtocol(transport);
114         bgpClient = new BgpConfigurator.Client(protocol);
115         LOGGER.info("Connected to "+msgPiece);
116         return true;
117     }
118
119     public boolean isBgpConnected() {
120         return isConnected;
121     }
122
123     private BgpRouter() {
124         bop = new BgpOp();
125     }
126
127     private static BgpRouter br = null;
128
129     public static synchronized BgpRouter getInstance() {
130         return (br == null ? br = new BgpRouter() : br);
131     }
132
133     private void dispatch(BgpOp op) throws TException, BgpRouterException {
134         int result = 1;
135
136         if (bgpClient == null) {
137             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
138         }
139
140         switch (op.type) {
141             case START:
142                 setStartTS(System.currentTimeMillis());
143                 result = bgpClient.startBgp(op.ints[0], op.strs[0],
144                         op.ignore, op.ignore, op.ignore, op.ints[1], op.add);
145                 startBGPresult = result;
146                 break;
147             case STOP:
148                 result = bgpClient.stopBgp(op.ints[0]);
149                 break;
150             case NBR:
151                 result = bop.add ?
152                         bgpClient.createPeer(op.strs[0], op.ints[0])
153                         : bgpClient.deletePeer(op.strs[0]);
154                 break;
155             case VRF:
156                 result = bop.add ?
157                         bgpClient.addVrf(op.strs[0], op.irts, op.erts)
158                         : bgpClient.delVrf(op.strs[0]);
159                 break;
160             case PFX:
161                 // order of args is different in addPrefix(), hence the
162                 // seeming out-of-order-ness of string indices
163                 result = bop.add ?
164                         bgpClient.pushRoute(op.strs[1], op.strs[2],
165                                 op.strs[0], op.ints[0])
166                         : bgpClient.withdrawRoute(op.strs[1], op.strs[0]);
167                 break;
168             case LOG:
169                 result = bgpClient.setLogConfig(op.strs[0], op.strs[1]);
170                 break;
171             case MHOP:
172                 result = bop.add ?
173                         bgpClient.setEbgpMultihop(op.strs[0], op.ints[0])
174                         : bgpClient.unsetEbgpMultihop(op.strs[0]);
175                 break;
176             case SRC:
177                 result = bop.add ?
178                         bgpClient.setUpdateSource(op.strs[0], op.strs[1])
179                         : bgpClient.unsetUpdateSource(op.strs[0]);
180                 break;
181             default: break;
182             case AF:
183                 af_afi afi = af_afi.findByValue(op.ints[0]);
184                 af_safi safi = af_safi.findByValue(op.ints[1]);
185                 result = bop.add ?
186                         bgpClient.enableAddressFamily(op.strs[0], afi, safi)
187                         : bgpClient.disableAddressFamily(op.strs[0], afi, safi);
188                 break;
189             case GR:
190                 result = bop.add ?
191                         bgpClient.enableGracefulRestart(op.ints[0])
192                         : bgpClient.disableGracefulRestart();
193                 break;
194         }
195         if (result != 0) {
196             throw new BgpRouterException(result);
197         }
198     }
199
200     public synchronized void startBgp(int asNum, String rtrId, int stalepathTime, boolean announceFbit)
201             throws TException, BgpRouterException {
202         bop.type = Optype.START;
203         bop.add = announceFbit;
204         bop.ints[0] = asNum;
205         bop.ints[1] = stalepathTime;
206         bop.strs[0] = rtrId;
207         LOGGER.debug("Starting BGP with as number {} and router ID {} StalePathTime: {}", asNum, rtrId, stalepathTime);
208         dispatch(bop);
209     }
210
211     public synchronized void stopBgp(int asNum)
212             throws TException, BgpRouterException {
213         bop.type = Optype.STOP;
214         bop.ints[0] = asNum;
215         LOGGER.debug("Stopping BGP with as number {}", asNum);
216         dispatch(bop);
217     }
218
219     public synchronized void addNeighbor(String nbrIp, int nbrAsNum) throws TException, BgpRouterException {
220         bop.type = Optype.NBR;
221         bop.add = true;
222         bop.strs[0] = nbrIp;
223         bop.ints[0] = nbrAsNum;
224         LOGGER.debug("Adding BGP Neighbor {} with as number {} ", nbrIp, nbrAsNum);
225         dispatch(bop);
226     }
227
228     public synchronized void delNeighbor(String nbrIp) throws TException, BgpRouterException {
229         bop.type = Optype.NBR;
230         bop.add = false;
231         bop.strs[0] = nbrIp;
232         LOGGER.debug("Deleting BGP Neighbor {} ", nbrIp);
233         dispatch(bop);
234     }
235
236     public synchronized void addVrf(String rd, List<String> irts, List<String> erts)
237             throws TException, BgpRouterException {
238         bop.type = Optype.VRF;
239         bop.add = true;
240         bop.strs[0] = rd;
241         bop.irts = irts;
242         bop.erts = erts;
243         LOGGER.debug("Adding BGP VRF rd: {} ", rd);
244         dispatch(bop);
245     }
246
247     public synchronized void delVrf(String rd) throws TException, BgpRouterException {
248         bop.type = Optype.VRF;
249         bop.add = false;
250         bop.strs[0] = rd;
251         LOGGER.debug("Deleting BGP VRF rd: {} " + rd);
252         dispatch(bop);
253     }
254
255     // bit of a mess-up: the order of arguments is different in
256     // the Thrift RPC: prefix-nexthop-rd-label.
257
258     public synchronized void addPrefix(String rd, String prefix, String nexthop, int label)
259             throws TException, BgpRouterException {
260         bop.type = Optype.PFX;
261         bop.add = true;
262         bop.strs[0] = rd;
263         bop.strs[1] = prefix;
264         bop.strs[2] = nexthop;
265         bop.ints[0] = label;
266         LOGGER.debug("Adding BGP route - rd:{} prefix:{} nexthop:{} label:{} ", rd ,prefix, nexthop, label);
267         dispatch(bop);
268     }
269
270     public synchronized void delPrefix(String rd, String prefix) throws TException, BgpRouterException {
271         bop.type = Optype.PFX;
272         bop.add = false;
273         bop.strs[0] = rd;
274         bop.strs[1] = prefix;
275         LOGGER.debug("Deleting BGP route - rd:{} prefix:{} ", rd, prefix);
276         dispatch(bop);
277     }
278
279     public int initRibSync(BgpSyncHandle handle) throws TException, BgpRouterException {
280         if (bgpClient == null) {
281             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
282         }
283         if (handle.getState() == BgpSyncHandle.ITERATING) {
284             return BgpRouterException.BGP_ERR_IN_ITER;
285         }
286         handle.setState(BgpSyncHandle.INITED);
287         handle.setMore(1);
288         return 0;
289     }
290
291     public int endRibSync(BgpSyncHandle handle) throws TException, BgpRouterException {
292         if (bgpClient == null) {
293             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
294         }
295         int state = handle.getState();
296         switch (state) {
297             case BgpSyncHandle.INITED:
298             case BgpSyncHandle.ITERATING:
299                 handle.setState(BgpSyncHandle.ABORTED);
300                 break;
301             case BgpSyncHandle.DONE:
302                 break;
303             case BgpSyncHandle.NEVER_DONE:
304                 return BgpRouterException.BGP_ERR_NOT_ITER;
305             default:
306                 break;
307         }
308         return 0;
309     }
310
311     public Routes doRibSync(BgpSyncHandle handle) throws TException, BgpRouterException {
312         if (bgpClient == null) {
313             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
314         }
315         int state = handle.getState();
316         if (state != BgpSyncHandle.INITED && state != BgpSyncHandle.ITERATING) {
317             Routes r = new Routes();
318             r.setErrcode(BgpRouterException.BGP_ERR_NOT_ITER);
319             return r;
320         }
321         int op = (state == BgpSyncHandle.INITED) ?
322                 GET_RTS_INIT : GET_RTS_NEXT;
323         handle.setState(BgpSyncHandle.ITERATING);
324         int winSize = handle.getMaxCount()*handle.getRouteSize();
325         Routes outRoutes = bgpClient.getRoutes(op, winSize);
326         if (outRoutes.errcode != 0) {
327             return outRoutes;
328         }
329         handle.setMore(outRoutes.more);
330         if (outRoutes.more == 0) {
331             handle.setState(BgpSyncHandle.DONE);
332         }
333         return outRoutes;
334     }
335
336     public synchronized void setLogging(String fileName, String debugLevel) throws TException, BgpRouterException {
337         bop.type = Optype.LOG;
338         bop.strs[0] = fileName;
339         bop.strs[1] = debugLevel;
340         LOGGER.debug("Setting Log file to BGP VRF rd: {} ", fileName, debugLevel);
341         dispatch(bop);
342     }
343
344     public synchronized void addEbgpMultihop(String nbrIp, int nhops) throws TException, BgpRouterException {
345         bop.type = Optype.MHOP;
346         bop.add = true;
347         bop.strs[0] = nbrIp;
348         bop.ints[0] = nhops;
349         LOGGER.debug("ebgp-multihop set for peer {}, num hops = {}",
350                 nbrIp, nhops);
351         dispatch(bop);
352     }
353
354     public synchronized void delEbgpMultihop(String nbrIp) throws TException, BgpRouterException {
355         bop.type = Optype.MHOP;
356         bop.add = false;
357         bop.strs[0] = nbrIp;
358         LOGGER.debug("ebgp-multihop deleted for peer {}", nbrIp);
359         dispatch(bop);
360     }
361
362     public synchronized void addUpdateSource(String nbrIp, String srcIp) throws TException, BgpRouterException {
363         bop.type = Optype.SRC;
364         bop.add = true;
365         bop.strs[0] = nbrIp;
366         bop.strs[1] = srcIp;
367         LOGGER.debug("update-source added for peer {}, src-ip = {}",
368                 nbrIp, srcIp);
369         dispatch(bop);
370     }
371
372     public synchronized void delUpdateSource(String nbrIp) throws TException, BgpRouterException {
373         bop.type = Optype.SRC;
374         bop.add = false;
375         bop.strs[0] = nbrIp;
376         LOGGER.debug("update-source deleted for peer {}", nbrIp);
377         dispatch(bop);
378     }
379
380     public synchronized void addAddressFamily(String nbrIp, af_afi afi, af_safi safi)
381             throws TException, BgpRouterException {
382         bop.type = Optype.AF;
383         bop.add = true;
384         bop.strs[0] = nbrIp;
385         bop.ints[0] = afi.getValue();
386         bop.ints[1] = safi.getValue();
387         LOGGER.debug("addr family added for peer {}, afi = {}, safi = {}",
388                 nbrIp, bop.ints[0], bop.ints[1]);
389         dispatch(bop);
390     }
391
392     public synchronized void delAddressFamily(String nbrIp, af_afi afi, af_safi safi)
393             throws TException, BgpRouterException {
394         bop.type = Optype.AF;
395         bop.add = false;
396         bop.strs[0] = nbrIp;
397         bop.ints[0] = afi.getValue();
398         bop.ints[1] = safi.getValue();
399         LOGGER.debug("addr family deleted for peer {}, afi = {}, safi = {}",
400                 nbrIp, bop.ints[0], bop.ints[1]);
401         dispatch(bop);
402     }
403
404     public synchronized void addGracefulRestart(int stalepathTime) throws TException, BgpRouterException {
405         bop.type = Optype.GR;
406         bop.add = true;
407         bop.ints[0] = stalepathTime;
408         LOGGER.debug("graceful restart added, stale-path-time = {}",
409                 stalepathTime);
410         dispatch(bop);
411     }
412
413     public synchronized void delGracefulRestart() throws TException, BgpRouterException {
414         bop.type = Optype.GR;
415         bop.add = false;
416         LOGGER.debug("graceful restart deleted");
417         dispatch(bop);
418     }
419 }