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