changes for faster dcgw failure detection.
[netvirt.git] / bgpmanager / impl / src / main / java / org / opendaylight / netvirt / bgpmanager / thrift / client / BgpRouter.java
1 /*
2  * Copyright (c) 2016, 2017 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 com.google.common.annotations.VisibleForTesting;
12 import java.net.ConnectException;
13 import java.util.List;
14 import java.util.function.BooleanSupplier;
15 import java.util.function.Supplier;
16 import javax.annotation.Nullable;
17 import org.apache.thrift.TException;
18 import org.apache.thrift.protocol.TBinaryProtocol;
19 import org.apache.thrift.transport.TSocket;
20 import org.apache.thrift.transport.TTransport;
21 import org.apache.thrift.transport.TTransportException;
22 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager;
23 import org.opendaylight.netvirt.bgpmanager.RetryOnException;
24 import org.opendaylight.netvirt.bgpmanager.thrift.gen.BfdConfigData;
25 import org.opendaylight.netvirt.bgpmanager.thrift.gen.BgpConfigurator;
26 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
27 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
28 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
29 import org.opendaylight.netvirt.bgpmanager.thrift.gen.encap_type;
30 import org.opendaylight.netvirt.bgpmanager.thrift.gen.layer_type;
31 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
32 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
33 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.LayerType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 public final class BgpRouter {
38     private static final Logger LOG = LoggerFactory.getLogger(BgpRouter.class);
39
40     private static final int THRIFT_TIMEOUT_MILLI = 10000;
41     private static final int GET_RTS_INIT = 0;
42     private static final int GET_RTS_NEXT = 1;
43     private static final int CONNECTION_TIMEOUT = 60000;
44
45     private enum Optype {
46         START, STOP, NBR, VRF, PFX, SRC, MHOP, LOG, AF, GR, MP, VRFMP, EOR, DELAY_EOR, BFD, PEER_STATUS
47     }
48
49     private static class BgpOp {
50         static final int IGNORE = 0;
51
52         Optype type;
53         boolean add;
54         boolean multiHop;
55         String[] strs;
56         int[] ints;
57         List<String> irts;
58         List<String> erts;
59         long asNumber;
60         layer_type thriftLayerType;
61         protocol_type thriftProtocolType;
62         int ethernetTag;
63         String esi;
64         String macAddress;
65         int l2label;
66         int l3label;
67         encap_type thriftEncapType;
68         String routermac;
69         public af_afi afi;
70         int delayEOR;
71         public af_safi safi;
72
73         BgpOp() {
74             strs = new String[3];
75             ints = new int[3];
76         }
77     }
78
79     private final BgpOp bop = new BgpOp();
80     private final Supplier<Bgp> bgpConfigSupplier;
81     private final BooleanSupplier isBGPEntityOwner;
82
83     private volatile TTransport transport;
84     private volatile BgpConfigurator.Client bgpClient;
85     private volatile boolean isConnected = false;
86     private volatile long startTS;
87     private volatile long connectTS;
88     private volatile long lastConnectedTS;
89     private volatile boolean configServerUpdated = false;
90
91     private BgpRouter(Supplier<Bgp> bgpConfigSupplier, BooleanSupplier isBGPEntityOwner) {
92         this.bgpConfigSupplier = bgpConfigSupplier;
93         this.isBGPEntityOwner = isBGPEntityOwner;
94     }
95
96     // private ctor FOR UNIT TESTS ONLY
97     private BgpRouter(BgpConfigurator.Client bgpClient) {
98         this(() -> null, () -> false);
99         this.bgpClient = bgpClient;
100     }
101
102     // FOR UNIT TESTS ONLY
103     @VisibleForTesting
104     static BgpRouter newTestingInstance(BgpConfigurator.Client bgpClient) {
105         return new BgpRouter(bgpClient);
106     }
107
108     public static BgpRouter newInstance(Supplier<Bgp> bgpConfigSupplier, BooleanSupplier isEntityBGPOwner) {
109         return new BgpRouter(bgpConfigSupplier, isEntityBGPOwner);
110     }
111
112     public TTransport getTransport() {
113         return transport;
114     }
115
116     public long getLastConnectedTS() {
117         return lastConnectedTS;
118     }
119
120     public void setLastConnectedTS(long lastConnectedTS) {
121         this.lastConnectedTS = lastConnectedTS;
122     }
123
124     public long getConnectTS() {
125         return connectTS;
126     }
127
128     public void setConnectTS(long connectTS) {
129         this.connectTS = connectTS;
130     }
131
132     public long getStartTS() {
133         return startTS;
134     }
135
136     public void setStartTS(long startTS) {
137         this.startTS = startTS;
138     }
139
140     public void configServerUpdated() {
141         configServerUpdated = true;
142     }
143
144     public synchronized void disconnect() {
145         bgpClient = null;
146         isConnected = false;
147         if (transport != null) {
148             transport.close();
149         }
150     }
151
152     public synchronized boolean connect(String bgpHost, int bgpPort) {
153         String msgPiece = "BGP config server at " + bgpHost + ":" + bgpPort;
154
155         if (!BgpConfigurationManager.isValidConfigBgpHostPort(bgpHost, bgpPort)) {
156             LOG.error("Invalid config server host: {}, port: {}", bgpHost, bgpPort);
157             return false;
158         }
159
160         final int numberOfConnectRetries = 180;
161         configServerUpdated = false;
162         RetryOnException connectRetry = new RetryOnException(numberOfConnectRetries);
163
164         disconnect();
165         setConnectTS(System.currentTimeMillis());
166         do {
167             if (!isBGPEntityOwner.getAsBoolean()) {
168                 LOG.error("Non Entity BGP owner trying to connect to thrift. Returning");
169                 isConnected = false;
170                 return false;
171             }
172             if (configServerUpdated) {
173                 LOG.error("Config server updated while connecting to server {} {}", bgpHost, bgpPort);
174                 isConnected = false;
175                 return false;
176             }
177             try {
178                 LOG.error("Trying to connect BGP config server at {} : {}", bgpHost, bgpPort);
179                 TSocket ts = new TSocket(bgpHost, bgpPort, CONNECTION_TIMEOUT);
180                 transport = ts;
181                 transport.open();
182                 ts.setTimeout(THRIFT_TIMEOUT_MILLI);
183                 isConnected = true;
184                 setLastConnectedTS(System.currentTimeMillis());
185                 LOG.error("Connected to BGP config server at {} : {}", bgpHost, bgpPort);
186                 break;
187             } catch (TTransportException tte) {
188                 LOG.debug("Failed connecting to BGP config server at {} : {}. msg: {}; Exception :",
189                         bgpHost, bgpPort, msgPiece, tte);
190                 if (tte.getCause() instanceof ConnectException) {
191                     LOG.debug("Connect exception. Failed connecting to BGP config server at {} : {}. "
192                             + "msg: {}; Exception :", bgpHost, bgpPort, msgPiece, tte);
193                     connectRetry.errorOccured();
194                 } else {
195                     //In Case of other exceptions we try only 3 times
196                     connectRetry.errorOccured(60);
197                 }
198             }
199         } while (connectRetry.shouldRetry());
200
201         if (!connectRetry.shouldRetry()) {
202             isConnected = false;
203             return false;
204         }
205
206         bgpClient = new BgpConfigurator.Client(new TBinaryProtocol(transport));
207         LOG.info("Connected to {}", msgPiece);
208         return true;
209     }
210
211     public boolean isBgpConnected() {
212         return isConnected;
213     }
214
215     private void dispatch(BgpOp op) throws TException, BgpRouterException {
216         try {
217             dispatchInternal(op);
218         } catch (TTransportException tte) {
219             LOG.error("dispatch command to qthriftd failed, command: {}, exception:", op.toString(), tte);
220             reConnect(tte);
221             dispatchInternal(op);
222         }
223     }
224
225     private void reConnect(TTransportException tte) {
226         Bgp bgpConfig = bgpConfigSupplier.get();
227         if (bgpConfig != null) {
228             LOG.error("Received TTransportException, while configuring qthriftd, goind for Disconnect/Connect "
229                             + " Host: {}, Port: {}", bgpConfig.getConfigServer().getHost().getValue(),
230                     bgpConfig.getConfigServer().getPort().intValue());
231             disconnect();
232             try {
233                 Thread.sleep(2000);
234             } catch (InterruptedException e) {
235                 LOG.error("Exception wile reconnecting ", e);
236             }
237             connect(bgpConfig.getConfigServer().getHost().getValue(),
238                     bgpConfig.getConfigServer().getPort().intValue());
239         } else {
240             LOG.error("Unable to send commands to thrift and fetch bgp configuration", tte);
241         }
242     }
243
244     private void dispatchInternal(BgpOp op) throws TException, BgpRouterException {
245         int result = 1;
246
247         if (bgpClient == null) {
248             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
249         }
250
251         if (op.type == null) {
252             LOG.error("dispatchInternal called with op.type null", new Throwable("stack trace"));
253             return;
254         }
255
256         af_afi afi = af_afi.findByValue(op.ints[0]);
257         af_safi safi = af_safi.findByValue(op.ints[1]);
258
259         switch (op.type) {
260             case START:
261                 setStartTS(System.currentTimeMillis());
262                 LOG.debug("startBgp thrift call for AsId {}", op.asNumber);
263                 result = bgpClient.startBgp(op.asNumber, op.strs[0],
264                         BgpOp.IGNORE, BgpOp.IGNORE, BgpOp.IGNORE, op.ints[0], op.add);
265                 LOG.debug("Result of startBgp thrift call for AsId {} : {}", op.asNumber, result);
266                 break;
267             case STOP:
268                 result = bgpClient.stopBgp(op.asNumber);
269                 break;
270             case NBR:
271                 if (bop.add) {
272                     result = bgpClient.createPeer(op.strs[0], op.asNumber);
273                     if (result == 0 && op.strs[1] != null) { // createPeer worked and password is specified
274                         result = bgpClient.setPeerSecret(op.strs[0], op.strs[1]);
275                         if (result != 0) {
276                             throw new BgpRouterException(BgpRouterException.Function.SET_PEER_SECRET, result);
277                         }
278                     }
279                 } else { // delete
280                     result = bgpClient.deletePeer(op.strs[0]);
281                 }
282                 break;
283             case VRF:
284                 result = bop.add
285                            ? bgpClient.addVrf(op.thriftLayerType, op.strs[0], op.irts, op.erts, op.afi, op.safi)
286                            : bgpClient.delVrf(op.strs[0], op.afi, op.safi);
287                 break;
288             case PFX:
289                 // order of args is different in addPrefix(), hence the
290                 // seeming out-of-order-ness of string indices
291                 afi = af_afi.findByValue(org.opendaylight.netvirt.bgpmanager.BgpUtil
292                         .getAFItranslatedfromPrefix(op.strs[1]));
293                 result = bop.add
294                         ? bgpClient.pushRoute(
295                                 op.thriftProtocolType,
296                                 op.strs[1],//prefix
297                                 op.strs[2],//nexthop
298                                 op.strs[0],//rd
299                                 op.ethernetTag,
300                                 op.esi,
301                                 op.macAddress,
302                                 op.l3label,
303                                 op.l2label,
304                                 op.thriftEncapType,
305                                 op.routermac,
306                                 afi)
307
308                         : bgpClient.withdrawRoute(
309                         op.thriftProtocolType,
310                         op.strs[1],//prefix
311                         op.strs[0],//rd
312                         op.ethernetTag,
313                         op.esi,
314                         op.macAddress,
315                         afi);
316                 break;
317             case LOG:
318                 result = bgpClient.setLogConfig(op.strs[0], op.strs[1]);
319                 break;
320             case MHOP:
321                 result = bop.add
322                         ? bgpClient.setEbgpMultihop(op.strs[0], op.ints[0])
323                         : bgpClient.unsetEbgpMultihop(op.strs[0]);
324                 break;
325             case SRC:
326                 result = bop.add
327                         ? bgpClient.setUpdateSource(op.strs[0], op.strs[1])
328                         : bgpClient.unsetUpdateSource(op.strs[0]);
329                 break;
330             case AF:
331                 result = bop.add
332                         ? bgpClient.enableAddressFamily(op.strs[0], afi, safi)
333                         : bgpClient.disableAddressFamily(op.strs[0], afi, safi);
334                 break;
335             case GR:
336                 result = bop.add
337                         ? bgpClient.enableGracefulRestart(op.ints[0])
338                         : bgpClient.disableGracefulRestart();
339                 break;
340             case MP:
341                 result = bop.add
342                         ? bgpClient.enableMultipath(afi, safi)
343                         : bgpClient.disableMultipath(afi, safi);
344                 break;
345             case VRFMP:
346                 result = bgpClient.multipaths(bop.strs[0], bop.ints[0]);
347                 break;
348             case EOR:
349                 result = bgpClient.sendEOR();
350                 break;
351             case DELAY_EOR:
352                 bgpClient.send_enableEORDelay(op.delayEOR);
353                 break;
354             case BFD:
355                 BfdConfigData bfdConfigData = new BfdConfigData();
356                 bfdConfigData.setBfdConfigDataVersion((byte)1);
357                 bfdConfigData.setBfdDebounceDown(0);
358                 bfdConfigData.setBfdDebounceUp(0);
359                 bfdConfigData.setBfdFailureThreshold((byte)op.ints[0]);
360                 bfdConfigData.setBfdRxInterval(op.ints[1]);
361                 bfdConfigData.setBfdTxInterval(op.ints[2]);
362                 bfdConfigData.setBfdMultihop(op.multiHop);
363                 result = bop.add
364                         ? bgpClient.enableBFDFailover(bfdConfigData)
365                         : bgpClient.disableBFDFailover();
366                 break;
367             case PEER_STATUS:
368                 result = bgpClient.getPeerStatus(op.strs[0], op.asNumber).getValue();
369                 break;
370             default:
371                 break;
372         }
373         if (result != 0) {
374             throw new BgpRouterException(result);
375         }
376     }
377
378     public synchronized void startBgp(long asNum, String rtrId, int stalepathTime, boolean announceFbit)
379             throws TException, BgpRouterException {
380         bop.type = Optype.START;
381         bop.add = announceFbit;
382         bop.asNumber = asNum;
383         bop.ints[0] = stalepathTime;
384         bop.strs[0] = rtrId;
385         LOG.debug("Starting BGP with as number {} and router ID {} StalePathTime: {}", asNum, rtrId, stalepathTime);
386         dispatch(bop);
387     }
388
389     public synchronized void stopBgp(long asNum)
390             throws TException, BgpRouterException {
391         bop.type = Optype.STOP;
392         bop.asNumber = asNum;
393         LOG.debug("Stopping BGP with as number {}", asNum);
394         dispatch(bop);
395     }
396
397     public synchronized void addNeighbor(String nbrIp, long nbrAsNum, @Nullable String md5Secret)
398             throws TException, BgpRouterException {
399         if (md5Secret == null) {
400             LOG.debug("Adding BGP Neighbor {} with as number {} ", nbrIp, nbrAsNum);
401         } else {
402             LOG.debug("Adding BGP Neighbor {} with as number {} and MD5 secret {}", nbrIp, nbrAsNum, md5Secret);
403         }
404         bop.type = Optype.NBR;
405         bop.add = true;
406         bop.strs[0] = nbrIp;
407         bop.asNumber = nbrAsNum;
408         bop.strs[1] = md5Secret;
409         dispatch(bop);
410     } // public addNeighbor( nbrIp, nbrAsNum, md5Secret )
411
412     public synchronized void delNeighbor(String nbrIp) throws TException, BgpRouterException {
413         bop.type = Optype.NBR;
414         bop.add = false;
415         bop.strs[0] = nbrIp;
416         LOG.debug("Deleting BGP Neighbor {} ", nbrIp);
417         dispatch(bop);
418     }
419
420     public synchronized void addVrf(LayerType layerType, String rd, List<String> irts, List<String> erts)
421             throws TException, BgpRouterException {
422         bop.thriftLayerType = layerType == LayerType.LAYER2 ? layer_type.LAYER_2 : layer_type.LAYER_3;
423         bop.type = Optype.VRF;
424         bop.add = true;
425         bop.strs[0] = rd;
426         bop.irts = irts;
427         bop.erts = erts;
428         LOG.debug("Adding BGP VRF rd: {} ", rd);
429         dispatch(bop);
430     }
431
432     public synchronized void delVrf(String rd, long afi, long safi) throws TException, BgpRouterException {
433         bop.type = Optype.VRF;
434         bop.add = false;
435         bop.strs[0] = rd;
436         bop.afi = af_afi.findByValue((int)afi);
437         bop.safi = af_safi.findByValue((int)safi);
438         LOG.debug("Deleting BGP VRF rd: {}", rd);
439         dispatch(bop);
440     }
441
442     // bit of a mess-up: the order of arguments is different in
443     // the Thrift RPC: prefix-nexthop-rd-label.
444
445     public synchronized void addPrefix(String rd,
446                                        String prefix,
447                                        String nexthop,
448                                        int label,
449                                        int l3vni,
450                                        int l2vni,
451                                        protocol_type protocolType,
452                                        int ethtag,
453                                        String esi,
454                                        String macaddress,
455                                        encap_type encapType,
456                                        String routermac)
457             throws TException, BgpRouterException {
458         bop.type = Optype.PFX;
459         bop.add = true;
460         bop.strs[0] = rd;
461         bop.strs[1] = prefix;
462         bop.strs[2] = nexthop;
463         // TODO: set label2 or label3 based on encapsulation type and protocol type once L2label is applicable
464         bop.ints[0] = label;
465         if (protocolType.equals(protocol_type.PROTOCOL_EVPN) && encapType.equals(encap_type.VXLAN)) {
466             bop.l3label = l3vni; //L3VPN Over VxLan
467             bop.l2label = l2vni;
468         } else {
469             bop.l3label = label; // L3VPN Over MPLSGRE
470         }
471         bop.thriftProtocolType = protocolType;
472         bop.ethernetTag = ethtag;
473         bop.esi = esi;
474         bop.macAddress = macaddress;
475         bop.thriftEncapType = encapType;
476         bop.routermac = routermac;
477
478         LOG.debug("Adding BGP route - rd:{} prefix:{} nexthop:{} label:{} ", rd ,prefix, nexthop, label);
479         dispatch(bop);
480     }
481
482     public synchronized void delPrefix(String rd, String prefix) throws TException, BgpRouterException {
483         bop.type = Optype.PFX;
484         bop.add = false;
485         bop.strs[0] = rd;
486         bop.strs[1] = prefix;
487         LOG.debug("Deleting BGP route - rd:{} prefix:{} ", rd, prefix);
488         dispatch(bop);
489     }
490
491     public synchronized void addBfd(int detectMult, int minRx, int minTx, boolean multiHop)
492             throws TException, BgpRouterException {
493         bop.type = Optype.BFD;
494         bop.add = true;
495         bop.ints[0] = detectMult;
496         bop.ints[1] = minRx;
497         bop.ints[2] = minTx;
498         bop.multiHop = multiHop;
499         LOG.debug("Adding BFD config {} {} {} {}", detectMult, minRx, minTx, multiHop);
500         dispatch(bop);
501     }
502
503     public synchronized void delBfd() throws TException, BgpRouterException {
504         bop.type = Optype.BFD;
505         bop.add = false;
506         LOG.debug("Deleting BFD Config ");
507         dispatch(bop);
508     }
509
510     public int initRibSync(BgpSyncHandle handle) throws BgpRouterException {
511         if (bgpClient == null) {
512             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
513         }
514         if (handle.getState() == BgpSyncHandle.ITERATING) {
515             return BgpRouterException.BGP_ERR_IN_ITER;
516         }
517         handle.setState(BgpSyncHandle.INITED);
518         handle.setMore(1);
519         return 0;
520     }
521
522     public int endRibSync(BgpSyncHandle handle) throws BgpRouterException {
523         if (bgpClient == null) {
524             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
525         }
526         int state = handle.getState();
527         switch (state) {
528             case BgpSyncHandle.INITED:
529             case BgpSyncHandle.ITERATING:
530                 handle.setState(BgpSyncHandle.ABORTED);
531                 break;
532             case BgpSyncHandle.DONE:
533                 break;
534             case BgpSyncHandle.NEVER_DONE:
535                 return BgpRouterException.BGP_ERR_NOT_ITER;
536             default:
537                 break;
538         }
539         return 0;
540     }
541
542     public Routes doRibSync(BgpSyncHandle handle, af_afi afi) throws TException, BgpRouterException {
543         if (bgpClient == null) {
544             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
545         }
546         int state = handle.getState();
547         if (state != BgpSyncHandle.INITED && state != BgpSyncHandle.ITERATING) {
548             Routes routes = new Routes();
549             routes.setErrcode(BgpRouterException.BGP_ERR_NOT_ITER);
550             return routes;
551         }
552         int op = state == BgpSyncHandle.INITED ? GET_RTS_INIT : GET_RTS_NEXT;
553         handle.setState(BgpSyncHandle.ITERATING);
554         int winSize = handle.getMaxCount() * handle.getRouteSize();
555
556
557         // TODO: receive correct protocol_type here, currently populating with dummy protocol type
558         Routes outRoutes = bgpClient.getRoutes(protocol_type.PROTOCOL_ANY, op, winSize, afi);
559         handle.setMore(outRoutes.more);
560         if (outRoutes.more == 0) {
561             handle.setState(BgpSyncHandle.DONE);
562         }
563         return outRoutes;
564     }
565
566     public synchronized void setLogging(String fileName, String debugLevel) throws TException, BgpRouterException {
567         bop.type = Optype.LOG;
568         bop.strs[0] = fileName;
569         bop.strs[1] = debugLevel;
570         LOG.debug("Setting Log file to BGP VRF rd: {}, {}", fileName, debugLevel);
571         dispatch(bop);
572     }
573
574     public synchronized void addEbgpMultihop(String nbrIp, int nhops) throws TException, BgpRouterException {
575         bop.type = Optype.MHOP;
576         bop.add = true;
577         bop.strs[0] = nbrIp;
578         bop.ints[0] = nhops;
579         LOG.debug("ebgp-multihop set for peer {}, num hops = {}",
580                 nbrIp, nhops);
581         dispatch(bop);
582     }
583
584     public synchronized void delEbgpMultihop(String nbrIp) throws TException, BgpRouterException {
585         bop.type = Optype.MHOP;
586         bop.add = false;
587         bop.strs[0] = nbrIp;
588         LOG.debug("ebgp-multihop deleted for peer {}", nbrIp);
589         dispatch(bop);
590     }
591
592     public synchronized void addUpdateSource(String nbrIp, String srcIp) throws TException, BgpRouterException {
593         bop.type = Optype.SRC;
594         bop.add = true;
595         bop.strs[0] = nbrIp;
596         bop.strs[1] = srcIp;
597         LOG.debug("update-source added for peer {}, src-ip = {}",
598                 nbrIp, srcIp);
599         dispatch(bop);
600     }
601
602     public synchronized void delUpdateSource(String nbrIp) throws TException, BgpRouterException {
603         bop.type = Optype.SRC;
604         bop.add = false;
605         bop.strs[0] = nbrIp;
606         LOG.debug("update-source deleted for peer {}", nbrIp);
607         dispatch(bop);
608     }
609
610     public synchronized void addAddressFamily(String nbrIp, af_afi afi, af_safi safi)
611             throws TException, BgpRouterException {
612         bop.type = Optype.AF;
613         bop.add = true;
614         bop.strs[0] = nbrIp;
615         bop.ints[0] = afi.getValue();
616         bop.ints[1] = safi.getValue();
617         LOG.debug("addr family added for peer {}, afi = {}, safi = {}",
618                 nbrIp, bop.ints[0], bop.ints[1]);
619         dispatch(bop);
620     }
621
622     public synchronized void delAddressFamily(String nbrIp, af_afi afi, af_safi safi)
623             throws TException, BgpRouterException {
624         bop.type = Optype.AF;
625         bop.add = false;
626         bop.strs[0] = nbrIp;
627         bop.ints[0] = afi.getValue();
628         bop.ints[1] = safi.getValue();
629         LOG.debug("addr family deleted for peer {}, afi = {}, safi = {}",
630                 nbrIp, bop.ints[0], bop.ints[1]);
631         dispatch(bop);
632     }
633
634     public synchronized void addGracefulRestart(int stalepathTime) throws TException, BgpRouterException {
635         bop.type = Optype.GR;
636         bop.add = true;
637         bop.ints[0] = stalepathTime;
638         LOG.debug("graceful restart added, stale-path-time = {}",
639                 stalepathTime);
640         dispatch(bop);
641     }
642
643     public synchronized void delGracefulRestart() throws TException, BgpRouterException {
644         bop.type = Optype.GR;
645         bop.add = false;
646         LOG.debug("graceful restart deleted");
647         dispatch(bop);
648     }
649
650     public synchronized void enableMultipath(af_afi afi, af_safi safi) throws TException, BgpRouterException {
651         bop.type = Optype.MP;
652         bop.add = true;
653         LOG.debug("Enabling multipath for afi {}, safi {}", afi.getValue(), safi.getValue());
654         bop.ints[0] = afi.getValue();
655         bop.ints[1] = safi.getValue();
656         dispatch(bop);
657     }
658
659     public synchronized void disableMultipath(af_afi afi, af_safi safi) throws TException, BgpRouterException {
660         bop.type = Optype.MP;
661         bop.add = false;
662         LOG.debug("Disabling multipath for afi {}, safi {}", afi.getValue(), safi.getValue());
663         bop.ints[0] = afi.getValue();
664         bop.ints[1] = safi.getValue();
665         dispatch(bop);
666     }
667
668     public synchronized void multipaths(String rd, int maxpath) throws TException, BgpRouterException {
669         bop.type = Optype.VRFMP;
670         bop.strs[0] = rd;
671         bop.ints[0] = maxpath;
672         dispatch(bop);
673     }
674
675     public synchronized void sendEOR() throws TException, BgpRouterException {
676         bop.type = Optype.EOR;
677         LOG.debug("EOR message sent");
678         dispatch(bop);
679     }
680
681     public synchronized void delayEOR(int delay) throws TException, BgpRouterException {
682         bop.type = Optype.DELAY_EOR;
683         bop.delayEOR = delay;
684         LOG.debug("EOR delay time in Seconds sent");
685         dispatch(bop);
686     }
687
688     public synchronized void getPeerStatus(String nbrIp, long nbrAsNum)
689             throws TException, BgpRouterException {
690         bop.type = Optype.PEER_STATUS;
691         bop.strs[0] = nbrIp;
692         bop.asNumber = nbrAsNum;
693         dispatch(bop);
694     } // public getPeerStatus( nbrIp, nbrAsNum )
695
696 }
697