2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.bgpmanager.thrift.client;
11 import java.util.List;
12 import javax.annotation.Nullable;
13 import org.apache.thrift.TException;
14 import org.apache.thrift.protocol.TBinaryProtocol;
15 import org.apache.thrift.protocol.TProtocol;
16 import org.apache.thrift.transport.TSocket;
17 import org.apache.thrift.transport.TTransport;
18 import org.apache.thrift.transport.TTransportException;
19 import org.opendaylight.netvirt.bgpmanager.thrift.gen.BgpConfigurator;
20 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
21 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
22 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
23 import org.opendaylight.netvirt.bgpmanager.thrift.gen.encap_type;
24 import org.opendaylight.netvirt.bgpmanager.thrift.gen.layer_type;
25 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
26 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.LayerType;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 public class BgpRouter {
31 private static TTransport transport;
32 private static TProtocol protocol;
33 private static BgpConfigurator.Client bgpClient = null;
34 boolean isConnected = false;
35 private static final Logger LOGGER = LoggerFactory.getLogger(BgpRouter.class);
36 public int startBGPresult = Integer.MIN_VALUE;
37 public String bgpHost = null;
38 public int bgpHostPort = 0;
39 private long startTS = 0;
40 private long connectTS = 0;
41 private long lastConnectedTS = 0;
43 public long getLastConnectedTS() {
44 return lastConnectedTS;
47 public void setLastConnectedTS(long lastConnectedTS) {
48 this.lastConnectedTS = lastConnectedTS;
51 public long getConnectTS() {
55 public void setConnectTS(long connectTS) {
56 this.connectTS = connectTS;
59 public long getStartTS() {
63 public void setStartTS(long startTS) {
64 this.startTS = startTS;
69 START, STOP, NBR, VRF, PFX, SRC, MHOP, LOG, AF, GR, MP, VRFMP
72 private static final int GET_RTS_INIT = 0;
73 private static final int GET_RTS_NEXT = 1;
74 private static final int CONNECTION_TIMEOUT = 60000;
83 public List<String> irts;
84 public List<String> erts;
86 static final int IGNORE = 0;
87 public layer_type thriftLayerType;
88 public protocol_type thriftProtocolType;
89 public int ethernetTag;
91 public String macAddress;
94 public encap_type thriftEncapType;
95 public String routermac;
104 private static BgpOp bop;
106 public synchronized void disconnect() {
109 if (transport != null) {
114 public synchronized boolean connect(String bgpHost, int bgpPort) {
115 String msgPiece = "BGP config server at " + bgpHost + ":" + bgpPort;
117 this.bgpHost = bgpHost;
118 this.bgpHostPort = bgpPort;
121 setConnectTS(System.currentTimeMillis());
123 TSocket ts = new TSocket(bgpHost, bgpPort, CONNECTION_TIMEOUT);
128 setLastConnectedTS(System.currentTimeMillis());
129 } catch (TTransportException tte) {
130 LOGGER.error("Failed connecting to " + msgPiece + "; Exception: " + tte);
134 protocol = new TBinaryProtocol(transport);
135 bgpClient = new BgpConfigurator.Client(protocol);
136 LOGGER.info("Connected to " + msgPiece);
140 public boolean isBgpConnected() {
144 private BgpRouter() {
148 private BgpRouter(BgpConfigurator.Client bgpClient) { // FOR UNIT TESTS ONLY
149 this.bgpClient = bgpClient;
150 this.bop = new BgpOp();
151 } // private ctor FOR UNIT TESTS ONLY
153 static BgpRouter makeTestingRouter(BgpConfigurator.Client bgpClient) { // FOR UNIT TESTS ONLY
154 return new BgpRouter(bgpClient);
155 } // static factory makeTestingRouter
157 private static BgpRouter br = null;
159 public static synchronized BgpRouter getInstance() {
160 return (br == null ? br = new BgpRouter() : br);
163 private void dispatch(BgpOp op) throws TException, BgpRouterException {
166 if (bgpClient == null) {
167 throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
170 af_afi afi = af_afi.findByValue(op.ints[0]);
171 af_safi safi = af_safi.findByValue(op.ints[1]);
175 setStartTS(System.currentTimeMillis());
176 LOGGER.debug("startBgp thrift call for AsId {}", op.asNumber);
177 result = bgpClient.startBgp(op.asNumber, op.strs[0],
178 BgpOp.IGNORE, BgpOp.IGNORE, BgpOp.IGNORE, op.ints[0], op.add);
179 LOGGER.debug("Result of startBgp thrift call for AsId {} : {}", op.asNumber, result);
180 startBGPresult = result;
183 result = bgpClient.stopBgp(op.asNumber);
187 result = bgpClient.createPeer(op.strs[0], op.asNumber);
188 if (result == 0 && op.strs[1] != null) { // createPeer worked and password is specified
189 result = bgpClient.setPeerSecret(op.strs[0], op.strs[1]);
191 throw new BgpRouterException(BgpRouterException.Function.SET_PEER_SECRET, result);
195 result = bgpClient.deletePeer(op.strs[0]);
200 ? bgpClient.addVrf(op.thriftLayerType, op.strs[0], op.irts, op.erts)
201 : bgpClient.delVrf(op.strs[0]);
204 // order of args is different in addPrefix(), hence the
205 // seeming out-of-order-ness of string indices
206 afi = af_afi.findByValue(org.opendaylight.netvirt.bgpmanager.BgpUtil
207 .getAFItranslatedfromPrefix(op.strs[1]));
209 ? bgpClient.pushRoute(
210 op.thriftProtocolType,
223 : bgpClient.withdrawRoute(
224 op.thriftProtocolType,
233 result = bgpClient.setLogConfig(op.strs[0], op.strs[1]);
237 ? bgpClient.setEbgpMultihop(op.strs[0], op.ints[0])
238 : bgpClient.unsetEbgpMultihop(op.strs[0]);
242 ? bgpClient.setUpdateSource(op.strs[0], op.strs[1])
243 : bgpClient.unsetUpdateSource(op.strs[0]);
247 ? bgpClient.enableAddressFamily(op.strs[0], afi, safi)
248 : bgpClient.disableAddressFamily(op.strs[0], afi, safi);
252 ? bgpClient.enableGracefulRestart(op.ints[0])
253 : bgpClient.disableGracefulRestart();
257 ? bgpClient.enableMultipath(afi, safi)
258 : bgpClient.disableMultipath(afi, safi);
261 result = bgpClient.multipaths(bop.strs[0], bop.ints[0]);
267 throw new BgpRouterException(result);
271 public synchronized void startBgp(long asNum, String rtrId, int stalepathTime, boolean announceFbit)
272 throws TException, BgpRouterException {
273 bop.type = Optype.START;
274 bop.add = announceFbit;
275 bop.asNumber = asNum;
276 bop.ints[0] = stalepathTime;
278 LOGGER.debug("Starting BGP with as number {} and router ID {} StalePathTime: {}", asNum, rtrId, stalepathTime);
282 public synchronized void stopBgp(long asNum)
283 throws TException, BgpRouterException {
284 bop.type = Optype.STOP;
285 bop.asNumber = asNum;
286 LOGGER.debug("Stopping BGP with as number {}", asNum);
290 public synchronized void addNeighbor(String nbrIp, long nbrAsNum, @Nullable String md5Secret)
291 throws TException, BgpRouterException {
292 if (md5Secret == null) {
293 LOGGER.debug("Adding BGP Neighbor {} with as number {} ", nbrIp, nbrAsNum);
295 LOGGER.debug("Adding BGP Neighbor {} with as number {} and MD5 secret {}", nbrIp, nbrAsNum, md5Secret);
297 bop.type = Optype.NBR;
300 bop.asNumber = nbrAsNum;
301 bop.strs[1] = md5Secret;
303 } // public addNeighbor( nbrIp, nbrAsNum, md5Secret )
305 public synchronized void delNeighbor(String nbrIp) throws TException, BgpRouterException {
306 bop.type = Optype.NBR;
309 LOGGER.debug("Deleting BGP Neighbor {} ", nbrIp);
313 public synchronized void addVrf(LayerType layerType, String rd, List<String> irts, List<String> erts)
314 throws TException, BgpRouterException {
315 bop.thriftLayerType = layerType == LayerType.LAYER2 ? layer_type.LAYER_2 : layer_type.LAYER_3;
316 bop.type = Optype.VRF;
321 LOGGER.debug("Adding BGP VRF rd: {} ", rd);
325 public synchronized void delVrf(String rd) throws TException, BgpRouterException {
326 bop.type = Optype.VRF;
329 LOGGER.debug("Deleting BGP VRF rd: {} " + rd);
333 // bit of a mess-up: the order of arguments is different in
334 // the Thrift RPC: prefix-nexthop-rd-label.
336 public synchronized void addPrefix(String rd,
341 protocol_type protocolType,
345 encap_type encapType,
347 throws TException, BgpRouterException {
348 bop.type = Optype.PFX;
351 bop.strs[1] = prefix;
352 bop.strs[2] = nexthop;
353 // TODO: set label2 or label3 based on encapsulation type and protocol type once L2label is applicable
355 if (protocolType.equals(protocol_type.PROTOCOL_EVPN) && encapType.equals(encap_type.VXLAN)) {
356 bop.l3label = l3vni; //L3VPN Over VxLan
358 bop.l3label = label; // L3VPN Over MPLSGRE
360 bop.thriftProtocolType = protocolType;
361 bop.ethernetTag = ethtag;
363 bop.macAddress = macaddress;
364 bop.thriftEncapType = encapType;
365 bop.routermac = routermac;
367 LOGGER.debug("Adding BGP route - rd:{} prefix:{} nexthop:{} label:{} ", rd ,prefix, nexthop, label);
371 public synchronized void delPrefix(String rd, String prefix) throws TException, BgpRouterException {
372 bop.type = Optype.PFX;
375 bop.strs[1] = prefix;
376 LOGGER.debug("Deleting BGP route - rd:{} prefix:{} ", rd, prefix);
380 public int initRibSync(BgpSyncHandle handle) throws TException, BgpRouterException {
381 if (bgpClient == null) {
382 throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
384 if (handle.getState() == BgpSyncHandle.ITERATING) {
385 return BgpRouterException.BGP_ERR_IN_ITER;
387 handle.setState(BgpSyncHandle.INITED);
392 public int endRibSync(BgpSyncHandle handle) throws TException, BgpRouterException {
393 if (bgpClient == null) {
394 throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
396 int state = handle.getState();
398 case BgpSyncHandle.INITED:
399 case BgpSyncHandle.ITERATING:
400 handle.setState(BgpSyncHandle.ABORTED);
402 case BgpSyncHandle.DONE:
404 case BgpSyncHandle.NEVER_DONE:
405 return BgpRouterException.BGP_ERR_NOT_ITER;
412 public Routes doRibSync(BgpSyncHandle handle, af_afi afi) throws TException, BgpRouterException {
413 if (bgpClient == null) {
414 throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
416 int state = handle.getState();
417 if (state != BgpSyncHandle.INITED && state != BgpSyncHandle.ITERATING) {
418 Routes routes = new Routes();
419 routes.setErrcode(BgpRouterException.BGP_ERR_NOT_ITER);
422 int op = (state == BgpSyncHandle.INITED) ? GET_RTS_INIT : GET_RTS_NEXT;
423 handle.setState(BgpSyncHandle.ITERATING);
424 int winSize = handle.getMaxCount() * handle.getRouteSize();
427 // TODO: receive correct protocol_type here, currently populating with dummy protocol type
428 Routes outRoutes = bgpClient.getRoutes(protocol_type.PROTOCOL_ANY, op, winSize, afi);
429 if (outRoutes.errcode != 0) {
432 handle.setMore(outRoutes.more);
433 if (outRoutes.more == 0) {
434 handle.setState(BgpSyncHandle.DONE);
439 public synchronized void setLogging(String fileName, String debugLevel) throws TException, BgpRouterException {
440 bop.type = Optype.LOG;
441 bop.strs[0] = fileName;
442 bop.strs[1] = debugLevel;
443 LOGGER.debug("Setting Log file to BGP VRF rd: {} ", fileName, debugLevel);
447 public synchronized void addEbgpMultihop(String nbrIp, int nhops) throws TException, BgpRouterException {
448 bop.type = Optype.MHOP;
452 LOGGER.debug("ebgp-multihop set for peer {}, num hops = {}",
457 public synchronized void delEbgpMultihop(String nbrIp) throws TException, BgpRouterException {
458 bop.type = Optype.MHOP;
461 LOGGER.debug("ebgp-multihop deleted for peer {}", nbrIp);
465 public synchronized void addUpdateSource(String nbrIp, String srcIp) throws TException, BgpRouterException {
466 bop.type = Optype.SRC;
470 LOGGER.debug("update-source added for peer {}, src-ip = {}",
475 public synchronized void delUpdateSource(String nbrIp) throws TException, BgpRouterException {
476 bop.type = Optype.SRC;
479 LOGGER.debug("update-source deleted for peer {}", nbrIp);
483 public synchronized void addAddressFamily(String nbrIp, af_afi afi, af_safi safi)
484 throws TException, BgpRouterException {
485 bop.type = Optype.AF;
488 bop.ints[0] = afi.getValue();
489 bop.ints[1] = safi.getValue();
490 LOGGER.debug("addr family added for peer {}, afi = {}, safi = {}",
491 nbrIp, bop.ints[0], bop.ints[1]);
495 public synchronized void delAddressFamily(String nbrIp, af_afi afi, af_safi safi)
496 throws TException, BgpRouterException {
497 bop.type = Optype.AF;
500 bop.ints[0] = afi.getValue();
501 bop.ints[1] = safi.getValue();
502 LOGGER.debug("addr family deleted for peer {}, afi = {}, safi = {}",
503 nbrIp, bop.ints[0], bop.ints[1]);
507 public synchronized void addGracefulRestart(int stalepathTime) throws TException, BgpRouterException {
508 bop.type = Optype.GR;
510 bop.ints[0] = stalepathTime;
511 LOGGER.debug("graceful restart added, stale-path-time = {}",
516 public synchronized void delGracefulRestart() throws TException, BgpRouterException {
517 bop.type = Optype.GR;
519 LOGGER.debug("graceful restart deleted");
523 public synchronized void enableMultipath(af_afi afi, af_safi safi) throws TException, BgpRouterException {
524 bop.type = Optype.MP;
526 LOGGER.debug("Enabling multipath for afi: " + afi.getValue() + " safi: " + safi.getValue());
527 bop.ints[0] = afi.getValue();
528 bop.ints[1] = safi.getValue();
532 public synchronized void disableMultipath(af_afi afi, af_safi safi) throws TException, BgpRouterException {
533 bop.type = Optype.MP;
535 LOGGER.debug("Disabling multipath for afi: " + afi.getValue() + " safi: " + safi.getValue());
536 bop.ints[0] = afi.getValue();
537 bop.ints[1] = safi.getValue();
541 public synchronized void multipaths(String rd, int maxpath) throws TException, BgpRouterException {
542 bop.type = Optype.VRFMP;
544 bop.ints[0] = maxpath;