Bump versions by 0.1.0 for next dev cycle
[vpnservice.git] / bgpmanager / bgpmanager-impl / src / main / java / org / opendaylight / bgpmanager / BgpConfigurationManager.java
1 /*
2  * Copyright (c) 2015 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.bgpmanager;
10
11 import com.google.common.base.Optional;
12
13 import java.util.*;
14 import java.io.BufferedReader;
15 import java.io.File;
16 import java.io.FileInputStream;
17 import java.io.FileOutputStream;
18 import java.io.InputStreamReader;
19 import java.lang.reflect.*;
20 import java.net.InetAddress;
21 import java.net.NetworkInterface;
22 import java.util.concurrent.*;
23 import java.util.concurrent.atomic.AtomicBoolean;
24 import java.util.concurrent.atomic.AtomicInteger;
25 import java.util.concurrent.atomic.AtomicReference;
26 import java.util.concurrent.locks.ReadWriteLock;
27 import java.util.concurrent.locks.ReentrantReadWriteLock;
28
29 import org.opendaylight.bgpmanager.commands.ClearBgpCli;
30 import org.opendaylight.bgpmanager.thrift.gen.*;
31 import org.opendaylight.bgpmanager.thrift.client.*;
32 import org.opendaylight.bgpmanager.thrift.server.*;
33 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
34 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
35 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
36 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
37 //import org.opendaylight.vpnservice.itm.api.IITMProvider;
38 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.*;
39 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.*;
40 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.*;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.*;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
45 import org.opendaylight.yangtools.concepts.ListenerRegistration;
46 import org.opendaylight.yangtools.yang.binding.DataObject;
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
48 import org.osgi.framework.Bundle;
49 import org.osgi.framework.BundleContext;
50 import org.osgi.framework.FrameworkUtil;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 public class BgpConfigurationManager {
55     private static final Logger LOG =
56     LoggerFactory.getLogger(BgpConfigurationManager.class);
57     private static DataBroker broker;
58     private static FibDSWriter fib;
59     private boolean restarting = false;
60     private static Bgp config;
61     private static BgpRouter bgpRouter;
62     private static BgpThriftService updateServer;
63
64     private static final String DEF_LOGFILE = "/var/log/bgp_debug.log";
65     private static final String DEF_LOGLEVEL = "errors";
66     private static final String UPDATE_PORT = "bgp.thrift.service.port";
67     private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
68     private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
69     private static final String DEF_UPORT = "6644";
70     private static final String DEF_CHOST = "127.0.0.1";
71     private static final String DEF_CPORT = "7644";
72     private static final String SDNC_BGP_MIP = "sdnc_bgp_mip";
73     private static final String CLUSTER_CONF_FILE = "/cluster/etc/cluster.conf";
74     private static final Timer ipActivationCheckTimer = new Timer();
75
76     // to have stale FIB map (RD, Prefix)
77     //  number of seconds wait for route sync-up between ODL and BGP.
78     private static final int BGP_RESTART_ROUTE_SYNC_SEC = 360;
79
80     static String odlThriftIp = "127.0.0.1";
81     private static String cHostStartup; 
82     private static String cPortStartup; 
83     private static CountDownLatch initer = new CountDownLatch(1);
84     //static IITMProvider itmProvider;
85     public static BgpManager bgpManager;
86     //map<rd, map<prefix/len, nexthop/label>>
87     private static Map<String, Map<String, String>> staledFibEntriesMap = new ConcurrentHashMap<>();
88
89     private static final Class[] reactors =  
90     {
91         ConfigServerReactor.class, AsIdReactor.class,
92         GracefulRestartReactor.class, LoggingReactor.class,
93         NeighborsReactor.class, UpdateSourceReactor.class,
94         EbgpMultihopReactor.class, AddressFamiliesReactor.class,
95         NetworksReactor.class, VrfsReactor.class, BgpReactor.class
96     };
97     
98     private ListenerRegistration<DataChangeListener>[] registrations;
99
100     private Object createListener(Class<?> cls) {
101         Constructor<?> ctor;
102         Object obj = null;
103
104         try {
105             ctor= cls.getConstructor(BgpConfigurationManager.class);
106             obj =  ctor.newInstance(this);
107         } catch (Exception e) {
108             LOG.error("Failed to create listener object", e);
109         }
110         return obj;
111     }
112
113     private void registerCallbacks() {
114         String emsg = "Failed to register listener";
115         registrations = (ListenerRegistration<DataChangeListener>[])
116         new ListenerRegistration[reactors.length];
117         InstanceIdentifier<?> iid = InstanceIdentifier.create(Bgp.class);
118         for (int i = 0; i < reactors.length; i++) {
119             DataChangeListener dcl = 
120             (DataChangeListener) createListener(reactors[i]);
121             String dclName = dcl.getClass().getName();
122             try {
123                 registrations[i] =  broker.registerDataChangeListener(
124                                       LogicalDatastoreType.CONFIGURATION,
125                                       iid, dcl, DataChangeScope.SUBTREE);
126             } catch (Exception e) {
127                 LOG.error(emsg, e);
128                 throw new IllegalStateException(emsg+" "+dclName, e);
129             }
130         }
131     }
132
133     public void close() {
134         if (updateServer != null) {
135             updateServer.stop();
136         } 
137     }
138
139     private boolean configExists() {
140         InstanceIdentifier.InstanceIdentifierBuilder<Bgp> iib =
141         InstanceIdentifier.builder(Bgp.class);
142         InstanceIdentifier<Bgp> iid = iib.build();
143         Optional<Bgp> b = BgpUtil.read(broker, 
144         LogicalDatastoreType.CONFIGURATION, iid);
145         return b.isPresent();
146     }
147
148     private String getProperty(String var, String def) {
149         Bundle b = FrameworkUtil.getBundle(BgpManager.class);
150         if (b == null) {
151             return def;
152         }
153         BundleContext context = b.getBundleContext();
154         if (context == null) {
155             return def;
156         }
157         String s = context.getProperty(var);
158         return (s == null ? def : s);
159     }
160
161     public BgpConfigurationManager(BgpManager bgpMgr) {
162         broker = bgpMgr.getBroker();
163         fib = bgpMgr.getFibWriter();
164         //itmProvider = bgpMgr.getItmProvider();
165         // there must be a good way to detect that we're restarting.
166         // but for now infer it from the existance of config
167         restarting = configExists();
168         bgpManager = bgpMgr;
169         bgpRouter = BgpRouter.getInstance();
170         String uPort = getProperty(UPDATE_PORT, DEF_UPORT); 
171         cHostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
172         cPortStartup = getProperty(CONFIG_PORT, DEF_CPORT);
173         VtyshCli.setHostAddr(cHostStartup);
174         ClearBgpCli.setHostAddr(cHostStartup);
175         LOG.info("UpdateServer at localhost:"+uPort+" ConfigServer at "
176                  +cHostStartup+":"+cPortStartup);
177         updateServer = new BgpThriftService(Integer.parseInt(uPort), bgpMgr);
178         updateServer.start();
179         readOdlThriftIpForBgpCommunication();
180         registerCallbacks();
181
182         // this shouldn't be done. config client must connect in 
183         // response to config; but connecting at startup to a default
184         // host is legacy behavior. 
185         if (!restarting) {
186             bgpRouter.connect(cHostStartup, Integer.parseInt(cPortStartup)); 
187         }
188         LOG.info("BGP Configuration manager initialized");
189         initer.countDown();
190     }
191
192     public Bgp get() {
193         return config;
194     }
195
196     private static final String addWarn = 
197               "Config store updated; undo with Delete if needed.";
198     private static final String delWarn = 
199               "Config store updated; undo with Add if needed.";
200     private static final String updWarn =
201               "Update operation not supported; Config store updated;"
202                +" restore with another Update if needed.";
203
204     public class ConfigServerReactor 
205     extends AbstractDataChangeListener<ConfigServer> 
206     implements AutoCloseable {
207         private static final String yangObj = "config-server ";
208         public ConfigServerReactor() {
209             super(ConfigServer.class);
210         }
211
212         protected synchronized void 
213         add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
214             LOG.debug("received bgp connect config host {}", val.getHost().getValue());
215             try {
216                 initer.await();
217             } catch (Exception e) {
218             }
219             LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
220             synchronized(BgpConfigurationManager.this) {
221                 boolean res = bgpRouter.connect(val.getHost().getValue(), 
222                                                 val.getPort().intValue());
223                 if (!res) {
224                     LOG.error(yangObj + "Add failed; "+addWarn);
225                 }
226             }
227         }
228
229         protected synchronized void 
230         remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
231             LOG.debug("received bgp disconnect");
232             synchronized(BgpConfigurationManager.this) {
233                 bgpRouter.disconnect();
234             }
235         }
236                           
237         protected void update(InstanceIdentifier<ConfigServer> iid,
238                               ConfigServer oldval, ConfigServer newval) {
239             LOG.error(yangObj + updWarn);
240         }
241
242         public void close() {
243             int i;
244             for (i=0 ; i < reactors.length ; i++) {
245                 if (reactors[i] == ConfigServerReactor.class) {
246                     break;
247                 }
248             }
249             registrations[i].close();
250         }
251     }
252
253     private BgpRouter getClient(String yangObj) {
254         if (bgpRouter == null) {
255             LOG.warn(yangObj+": configuration received when BGP is inactive");
256         }
257         return bgpRouter;
258     } 
259
260     public class AsIdReactor 
261     extends AbstractDataChangeListener<AsId> 
262     implements AutoCloseable {
263
264         private static final String yangObj = "as-id ";
265
266         public AsIdReactor() {
267             super(AsId.class);
268         }
269
270         protected synchronized void 
271         add(InstanceIdentifier<AsId> iid, AsId val) {
272             LOG.debug("received add router config asNum {}", val.getLocalAs().intValue());
273             synchronized(BgpConfigurationManager.this) {
274                 BgpRouter br = getClient(yangObj);
275                 if (br == null) {
276                     return;
277                 }
278                 int asNum = val.getLocalAs().intValue();
279                 Ipv4Address routerId = val.getRouterId();
280                 Long spt = val.getStalepathTime();
281                 Boolean afb = val.isAnnounceFbit();
282                 String rid = (routerId == null) ? "" : routerId.getValue();
283                 int stalepathTime = (spt == null) ? 90 : spt.intValue(); 
284                 boolean announceFbit = (afb == null) ? false : afb.booleanValue();
285                 try {
286                     br.startBgp(asNum, rid, stalepathTime, announceFbit); 
287                     if (bgpManager.getBgpCounters() == null) {
288                         bgpManager.startBgpCountersTask();
289                     }
290                 } catch (BgpRouterException bre) {
291                     if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
292                         LOG.error(yangObj+"Add requested when BGP is already active");
293                     } else {
294                         LOG.error(yangObj+"Add received exception: \"" 
295                                   +bre+"\"; "+addWarn);
296                     }
297                 } catch (Exception e) {
298                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "+addWarn);
299                 }
300             }
301         } 
302
303         protected synchronized void 
304         remove(InstanceIdentifier<AsId> iid, AsId val) {
305             LOG.debug("received delete router config asNum {}", val.getLocalAs().intValue());
306             synchronized(BgpConfigurationManager.this) {
307                 BgpRouter br = getClient(yangObj);
308                 if (br == null) {
309                     return;
310                 }
311                 int asNum = val.getLocalAs().intValue(); 
312                 try {
313                     br.stopBgp(asNum);
314                 } catch (Exception e) {
315                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "+delWarn);
316                 }
317                 if (bgpManager.getBgpCounters() != null) {
318                     bgpManager.stopBgpCountersTask();
319                 }
320             }
321         }
322                           
323         protected void update(InstanceIdentifier<AsId> iid,
324                               AsId oldval, AsId newval) {
325             LOG.error(yangObj + updWarn);
326         }
327
328         public void close() {
329             int i;
330             for (i=0 ; i < reactors.length ; i++) {
331                 if (reactors[i] == AsIdReactor.class) {
332                     break;
333                 }
334             }
335             registrations[i].close();
336         }
337     }
338
339     public class GracefulRestartReactor 
340     extends AbstractDataChangeListener<GracefulRestart> 
341     implements AutoCloseable {
342
343         private static final String yangObj = "graceful-restart ";
344
345         public GracefulRestartReactor() {
346             super(GracefulRestart.class);
347         }
348
349         protected synchronized void
350         add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
351             synchronized(BgpConfigurationManager.this) {
352                 BgpRouter br = getClient(yangObj);
353                 if (br == null) {
354                     return;
355                 }
356                 try {
357                     br.addGracefulRestart(val.getStalepathTime().intValue());
358                 } catch (Exception e) {
359                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "+addWarn);
360                 }
361             }
362         }
363
364         protected synchronized void 
365         remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
366             LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
367             synchronized(BgpConfigurationManager.this) {
368                 BgpRouter br = getClient(yangObj);
369                 if (br == null) {
370                     return;
371                 }
372                 try {
373                     br.delGracefulRestart();
374                 } catch (Exception e) {
375                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "
376                               +delWarn);
377                 }
378             }
379         }
380                           
381         protected void update(InstanceIdentifier<GracefulRestart> iid,
382                               GracefulRestart oldval, GracefulRestart newval) {
383                 LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
384             synchronized(BgpConfigurationManager.this) {
385                 BgpRouter br = getClient(yangObj);
386                 if (br == null) {
387                     return;
388                 }
389                 try {
390                     br.addGracefulRestart(newval.getStalepathTime().intValue());
391                 } catch (Exception e) {
392                     LOG.error(yangObj+"update received exception: \""+e+"\"; "+addWarn);
393                 }
394             }
395         }
396
397         public void close() {
398             int i;
399             for (i=0 ; i < reactors.length ; i++) {
400                 if (reactors[i] == GracefulRestartReactor.class) {
401                     break;
402                 }
403             }
404             registrations[i].close();
405         }
406     }
407
408     public class LoggingReactor 
409     extends AbstractDataChangeListener<Logging> 
410     implements AutoCloseable {
411
412         private static final String yangObj = "logging ";
413
414         public LoggingReactor() {
415             super(Logging.class);
416         }
417
418         protected synchronized void
419         add(InstanceIdentifier<Logging> iid, Logging val) {
420             synchronized(BgpConfigurationManager.this) {
421                 BgpRouter br = getClient(yangObj);
422                 if (br == null) {
423                     return;
424                 }
425                 try {
426                     br.setLogging(val.getFile(),val.getLevel());
427                 } catch (Exception e) {
428                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "
429                               +addWarn);
430                 }
431             }
432         }
433
434         protected synchronized void 
435         remove(InstanceIdentifier<Logging> iid, Logging val) {
436             LOG.debug("received remove Logging config val {}", val.getLevel());
437             synchronized(BgpConfigurationManager.this) {
438                 BgpRouter br = getClient(yangObj);
439                 if (br == null) {
440                     return;
441                 }
442                 try {
443                     br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
444                 } catch (Exception e) {
445                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "
446                               +delWarn);
447                 }
448             }
449         }
450                           
451         protected void update(InstanceIdentifier<Logging> iid,
452                               Logging oldval, Logging newval) {
453             synchronized(BgpConfigurationManager.this) {
454                 BgpRouter br = getClient(yangObj);
455                 if (br == null) {
456                     return;
457                 }
458                 try {
459                     br.setLogging(newval.getFile(),newval.getLevel());
460                 } catch (Exception e) {
461                     LOG.error(yangObj+"newval received exception: \""+e+"\"; "
462                               +addWarn);
463                 }
464             }
465         }
466
467         public void close() {
468             int i;
469             for (i=0 ; i < reactors.length ; i++) {
470                 if (reactors[i] == LoggingReactor.class) {
471                     break;
472                 }
473             }
474             registrations[i].close();
475         }
476     }
477
478     public class NeighborsReactor 
479     extends AbstractDataChangeListener<Neighbors> 
480     implements AutoCloseable {
481
482         private static final String yangObj = "neighbors ";
483
484         public NeighborsReactor() {
485             super(Neighbors.class);
486         }
487
488         protected synchronized void 
489         add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
490             LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
491             synchronized(BgpConfigurationManager.this) {
492                 BgpRouter br = getClient(yangObj);
493                 if (br == null) {
494                     return;
495                 }
496                 String peerIp = val.getAddress().getValue();
497                 int as = val.getRemoteAs().intValue();
498                 try {
499                     //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
500                     br.addNeighbor(peerIp, as);
501             
502                 } catch (Exception e) {
503                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "
504                               +addWarn);
505                 }
506             }
507         }
508
509         protected synchronized void 
510         remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
511             LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
512             synchronized(BgpConfigurationManager.this) {
513                 BgpRouter br = getClient(yangObj);
514                 if (br == null) {
515                     return;
516                 }
517                 String peerIp = val.getAddress().getValue();
518                 try {
519                     //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
520                     br.delNeighbor(peerIp);
521                 } catch (Exception e) {
522                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "
523                               +delWarn);
524                 }
525             }
526         }
527                           
528         protected void update(InstanceIdentifier<Neighbors> iid,
529                               Neighbors oldval, Neighbors newval) {
530             //purposefully nothing to do.
531         }
532
533         public void close() {
534             int i;
535             for (i=0 ; i < reactors.length ; i++) {
536                 if (reactors[i] == NeighborsReactor.class) {
537                     break;
538                 }
539             }
540             registrations[i].close();
541         }
542     }
543
544     public class EbgpMultihopReactor 
545     extends AbstractDataChangeListener<EbgpMultihop> 
546     implements AutoCloseable {
547
548         private static final String yangObj = "ebgp-multihop ";
549
550         public EbgpMultihopReactor() {
551             super(EbgpMultihop.class);
552         }
553
554         protected synchronized void 
555         add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
556             LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());  
557             synchronized(BgpConfigurationManager.this) {
558                 BgpRouter br = getClient(yangObj);
559                 if (br == null) {
560                     return;
561                 }
562                 String peerIp = val.getPeerIp().getValue();
563                 try {
564                     br.addEbgpMultihop(peerIp, val.getNhops().intValue()); 
565                 } catch (Exception e) {
566                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "
567                               +addWarn);
568                 }
569             }
570         }
571
572         protected synchronized void 
573         remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
574             LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
575             synchronized(BgpConfigurationManager.this) {
576                 BgpRouter br = getClient(yangObj);
577                 if (br == null) {
578                     return;
579                 }
580                 String peerIp = val.getPeerIp().getValue();
581                 try {
582                     br.delEbgpMultihop(peerIp);
583                 } catch (Exception e) {
584                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "
585                               +delWarn);
586                 }
587             }
588         }
589                           
590         protected void update(InstanceIdentifier<EbgpMultihop> iid,
591                               EbgpMultihop oldval, EbgpMultihop newval) {
592             LOG.error(yangObj + updWarn);
593         }
594
595         public void close() {
596             int i;
597             for (i=0 ; i < reactors.length ; i++) {
598                 if (reactors[i] == EbgpMultihopReactor.class) {
599                     break;
600                 }
601             }
602             registrations[i].close();
603         }
604     }
605
606     public class UpdateSourceReactor 
607     extends AbstractDataChangeListener<UpdateSource> 
608     implements AutoCloseable {
609
610         private static final String yangObj = "update-source ";
611
612         public UpdateSourceReactor() {
613             super(UpdateSource.class);
614         }
615
616         protected synchronized void 
617         add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
618             LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
619             synchronized(BgpConfigurationManager.this) {
620                 BgpRouter br = getClient(yangObj);
621                 if (br == null) {
622                     return;
623                 }
624                 String peerIp = val.getPeerIp().getValue();
625                 try {
626                     br.addUpdateSource(peerIp, val.getSourceIp().getValue()); 
627                 } catch (Exception e) {
628                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "
629                               +addWarn);
630                 }
631             }
632         }
633
634         protected synchronized void 
635         remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
636             LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
637             synchronized(BgpConfigurationManager.this) {
638                 BgpRouter br = getClient(yangObj);
639                 if (br == null) {
640                     return;
641                 }
642                 String peerIp = val.getPeerIp().getValue();
643                 try {
644                     br.delUpdateSource(peerIp);
645                 } catch (Exception e) {
646                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "
647                               +delWarn);
648                 }
649             }
650         }
651                           
652         protected void update(InstanceIdentifier<UpdateSource> iid,
653                               UpdateSource oldval, UpdateSource newval) {
654             LOG.error(yangObj + updWarn);
655         }
656
657         public void close() {
658             int i;
659             for (i=0 ; i < reactors.length ; i++) {
660                 if (reactors[i] == UpdateSourceReactor.class) {
661                     break;
662                 }
663             }
664             registrations[i].close();
665         }
666     }
667
668     public class AddressFamiliesReactor 
669     extends AbstractDataChangeListener<AddressFamilies> 
670     implements AutoCloseable {
671
672         private static final String yangObj = "address-families ";
673
674         public AddressFamiliesReactor() {
675             super(AddressFamilies.class);
676         }
677
678         protected synchronized void 
679         add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
680             LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
681             synchronized(BgpConfigurationManager.this) {
682                 BgpRouter br = getClient(yangObj);
683                 if (br == null) {
684                     return;
685                 }
686                 String peerIp = val.getPeerIp().getValue();
687                 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
688                 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
689                 try {
690                     br.addAddressFamily(peerIp, afi, safi); 
691                 } catch (Exception e) {
692                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "
693                               +addWarn);
694                 }
695             }
696         }
697
698         protected synchronized void 
699         remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
700             LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
701             synchronized(BgpConfigurationManager.this) {
702                 BgpRouter br = getClient(yangObj);
703                 if (br == null) {
704                     return;
705                 }
706                 String peerIp = val.getPeerIp().getValue();
707                 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
708                 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
709                 try {
710                     br.delAddressFamily(peerIp, afi, safi);
711                 } catch (Exception e) {
712                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "
713                               +delWarn);
714                 }
715             }
716         }
717                           
718         protected void update(InstanceIdentifier<AddressFamilies> iid,
719                               AddressFamilies oldval, AddressFamilies newval) {
720             LOG.error(yangObj + updWarn);
721         }
722
723         public void close() {
724             int i;
725             for (i=0 ; i < reactors.length ; i++) {
726                 if (reactors[i] == AddressFamiliesReactor.class) {
727                     break;
728                 }
729             }
730             registrations[i].close();
731         }
732     }
733
734     public class NetworksReactor 
735     extends AbstractDataChangeListener<Networks> 
736     implements AutoCloseable {
737
738         private static final String yangObj = "networks ";
739
740         public NetworksReactor() {
741             super(Networks.class);
742         }
743
744         protected synchronized void 
745         add(InstanceIdentifier<Networks> iid, Networks val) {
746             LOG.debug("received add Networks config val {}", val.getPrefixLen());
747             synchronized(BgpConfigurationManager.this) {
748                 BgpRouter br = getClient(yangObj);
749                 if (br == null) {
750                     return;
751                 }
752                 String rd = val.getRd();
753                 String pfxlen = val.getPrefixLen();
754                 String nh = val.getNexthop().getValue();
755                 Long label = val.getLabel();
756                 int lbl = (label == null) ? qbgpConstants.LBL_NO_LABEL 
757                                             : label.intValue();
758                 try {
759                     br.addPrefix(rd, pfxlen, nh, lbl); 
760                 } catch (Exception e) {
761                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "+addWarn);
762                 }
763             }
764         }
765
766         protected synchronized void 
767         remove(InstanceIdentifier<Networks> iid, Networks val) {
768             LOG.debug("received remove Networks config val {}", val.getPrefixLen());
769             synchronized(BgpConfigurationManager.this) {
770                 BgpRouter br = getClient(yangObj);
771                 if (br == null) {
772                     return;
773                 }
774                 String rd = val.getRd();
775                 String pfxlen = val.getPrefixLen();
776                 Long label = val.getLabel();
777                 int lbl = (label == null) ? 0 : label.intValue();
778                 if (rd == null && lbl > 0) {
779                     //LU prefix is being deleted. 
780                     rd = Integer.toString(lbl);
781                 }
782                 try {
783                     br.delPrefix(rd, pfxlen);
784                 } catch (Exception e) {
785                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "
786                               +delWarn);
787                 }
788             }
789         }
790                           
791         protected void update(InstanceIdentifier<Networks> iid,
792                               Networks oldval, Networks newval) {
793             LOG.error(yangObj + updWarn);
794         }
795
796         public void close() {
797             int i;
798             for (i=0 ; i < reactors.length ; i++) {
799                 if (reactors[i] == NetworksReactor.class) {
800                     break;
801                 }
802             }
803             registrations[i].close();
804         }
805     }
806
807     public class VrfsReactor 
808     extends AbstractDataChangeListener<Vrfs> 
809     implements AutoCloseable {
810
811         private static final String yangObj = "vrfs ";
812
813         public VrfsReactor() {
814             super(Vrfs.class);
815         }
816
817         protected synchronized void 
818         add(InstanceIdentifier<Vrfs> iid, Vrfs val) {
819             LOG.debug("received add Vrfs config val {}", val.getRd());
820             synchronized(BgpConfigurationManager.this) {
821                 BgpRouter br = getClient(yangObj);
822                 if (br == null) {
823                     return;
824                 }
825                 try {
826                     br.addVrf(val.getRd(), val.getImportRts(), 
827                               val.getExportRts()); 
828                 } catch (Exception e) {
829                     LOG.error(yangObj+"Add received exception: \""+e+"\"; "
830                               +addWarn);
831                 }
832             }
833         }
834
835         protected synchronized void 
836         remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
837             LOG.debug("received remove Vrfs config val {}", val.getRd());
838             synchronized(BgpConfigurationManager.this) {
839                 BgpRouter br = getClient(yangObj);
840                 if (br == null) {
841                     return;
842                 }
843                 try {
844                     br.delVrf(val.getRd());
845                 } catch (Exception e) {
846                     LOG.error(yangObj+" Delete received exception:  \""+e+"\"; "
847                               +delWarn);
848                 }
849             }
850         }
851                           
852         protected void update(InstanceIdentifier<Vrfs> iid,
853                               Vrfs oldval, Vrfs newval) {
854             LOG.error(yangObj + updWarn);
855         }
856
857         public void close() {
858             int i;
859             for (i=0 ; i < reactors.length ; i++) {
860                 if (reactors[i] == VrfsReactor.class) {
861                     break;
862                 }
863             }
864             registrations[i].close();
865         }
866     }
867
868     Future lastCleanupJob;
869     AtomicReference<Future> lastCleanupJobReference = new AtomicReference<>();
870
871     AtomicBoolean started = new AtomicBoolean(false);
872     public class BgpReactor 
873     extends AbstractDataChangeListener<Bgp> 
874     implements AutoCloseable {
875  
876         private static final String yangObj = "Bgp ";
877
878         public BgpReactor() {
879             super(Bgp.class);
880         }
881
882         protected synchronized void 
883         add(InstanceIdentifier<Bgp> iid, Bgp val) {
884             LOG.debug("received add Bgp config replaying the config");
885             try {
886                 initer.await();
887             } catch (Exception e) {
888             }
889             synchronized(BgpConfigurationManager.this) {
890                 config = val;
891                 if (restarting) {
892                     if (isIpAvailable(odlThriftIp)) {
893                         bgpRestarted();
894                     } else {
895                         ipActivationCheckTimer.scheduleAtFixedRate(new TimerTask() {
896                             public void run() {
897                                 if (isIpAvailable(odlThriftIp)) {
898                                     bgpRestarted();
899                                     ipActivationCheckTimer.cancel();
900                                 }
901                             }
902                         }, 10000L, 10000L);
903                     }
904                 }
905             }
906         }
907
908         protected synchronized void 
909         remove(InstanceIdentifier<Bgp> iid, Bgp val) {
910             LOG.debug("received remove Bgp config");
911             synchronized(BgpConfigurationManager.this) {
912                 config = null;
913             }
914         }
915                           
916         protected void update(InstanceIdentifier<Bgp> iid,
917                               Bgp oldval, Bgp newval) {
918             synchronized(BgpConfigurationManager.this) {
919                 config = newval;
920             }
921         }
922
923         public void close() {
924             int i;
925             for (i=0 ; i < reactors.length ; i++) {
926                 if (reactors[i] == BgpReactor.class) {
927                     break;
928                 }
929             }
930             registrations[i].close();
931         }
932     }
933     
934     public void readOdlThriftIpForBgpCommunication() {
935         File f = new File(CLUSTER_CONF_FILE);
936         if (!f.exists()) {
937             odlThriftIp = "127.0.0.1";
938             return;
939         }
940         BufferedReader br = null;
941         try {
942             br = new BufferedReader(new InputStreamReader(
943                     new FileInputStream(f)));
944             String line = br.readLine();
945             while (line != null) {
946                 if (line.contains(SDNC_BGP_MIP)) {
947                     line = line.trim();
948                     odlThriftIp = line.substring(line.lastIndexOf(" ")+1);
949                     break;
950                 }
951                 line = br.readLine();
952             }
953         } catch (Exception e) {
954         } finally {
955             try {br.close();} catch (Exception ignore){}
956         }
957     }
958     
959     public boolean isIpAvailable(String odlip) {
960         
961         try {
962             if (odlip != null) {
963                 if ("127.0.0.1".equals(odlip)) {
964                     return true;
965                 }
966                 Enumeration e = NetworkInterface.getNetworkInterfaces();
967                 while(e.hasMoreElements())
968                 {
969                     NetworkInterface n = (NetworkInterface) e.nextElement();
970                     Enumeration ee = n.getInetAddresses();
971                     while (ee.hasMoreElements())
972                     {
973                         InetAddress i = (InetAddress) ee.nextElement();
974                         if (odlip.equals(i.getHostAddress())) {
975                             return true;
976                         };
977                     }
978                 }
979             }
980         } catch (Exception e) {
981         }
982         return false;
983     }
984
985     public void bgpRestarted() {
986         /*
987          * If there a thread which in the process of stale cleanup, cancel it
988          * and start a new thread (to avoid processing same again).
989          */
990         if (lastCleanupJobReference.get() != null) {
991             lastCleanupJobReference.get().cancel(true);
992             lastCleanupJobReference.set(null);
993         }
994         Runnable task = new Runnable() {
995             @Override
996             public void run() {
997                 try {
998                     long startTime = System.currentTimeMillis();
999                     LOG.error("started creating stale fib  map ");
1000                     createStaleFibMap();
1001                     long endTime = System.currentTimeMillis();
1002                     LOG.error("took {} msecs for stale fib map creation ", endTime - startTime);
1003                     LOG.error("started bgp config replay ");
1004                     startTime = endTime;
1005                     replay();
1006                     endTime = System.currentTimeMillis();
1007                     LOG.error("took {} msecs for bgp replay ", endTime - startTime);
1008                     long route_sync_time = BGP_RESTART_ROUTE_SYNC_SEC;
1009                     try {
1010                         route_sync_time = bgpManager.getConfig().getGracefulRestart().getStalepathTime();
1011                     } catch (Exception e) {
1012                         LOG.error("BGP config/Stale-path time is not set");
1013                     }
1014                     Thread.sleep(route_sync_time * 1000L);
1015                     new RouteCleanup().call();
1016
1017                 } catch (Exception eCancel) {
1018                     LOG.error("Stale Cleanup Task Cancelled", eCancel);
1019                 }
1020             }
1021         };
1022         lastCleanupJob = executor.submit(task);
1023         lastCleanupJobReference.set(lastCleanupJob);
1024     }
1025
1026     private static void doRouteSync() {
1027         BgpSyncHandle bsh = BgpSyncHandle.getInstance();
1028         LOG.debug("Starting BGP route sync");
1029         try {
1030             bgpRouter.initRibSync(bsh); 
1031         } catch (Exception e) {
1032             LOG.error("Route sync aborted, exception when initialzing: "+e);
1033             return;
1034         }
1035         while (bsh.getState() != bsh.DONE) {
1036             Routes routes = null;
1037             try {
1038                 routes = bgpRouter.doRibSync(bsh);
1039             } catch (Exception e) {
1040                 LOG.error("Route sync aborted, exception when syncing: "+e);
1041                 return;
1042             }
1043             Iterator<Update> updates = routes.getUpdatesIterator();
1044             while (updates.hasNext()) {
1045                 Update u = updates.next();
1046                 Map<String, Map<String, String>> stale_fib_rd_map = BgpConfigurationManager.getStaledFibEntriesMap();
1047                 String rd = u.getRd();
1048                 String nexthop = u.getNexthop();
1049                 int label = u.getLabel();
1050                 String prefix = u.getPrefix();
1051                 int plen = u.getPrefixlen();
1052                 onUpdatePushRoute(rd, prefix, plen, nexthop, label);
1053             }
1054         }
1055         try {
1056             LOG.debug("Ending BGP route-sync");
1057             bgpRouter.endRibSync(bsh);
1058         } catch (Exception e) {
1059         }
1060     }
1061
1062     /* onUpdatePushRoute
1063      * Get Stale fib map, and compare current route/fib entry.
1064      *  - Entry compare shall include NextHop, Label.
1065      *  - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1066      *  - If entry nor found, add to FIB Config DS.
1067      *  - If entry found, but either Label/NextHop doesnt match.
1068      *      - Update FIB Config DS with modified values.
1069      *      - delete from Stale Map.
1070      */
1071     public static void onUpdatePushRoute(String rd, String prefix, int plen,
1072                                   String nexthop, int label) {
1073         Map<String, Map<String, String>> stale_fib_rd_map = BgpConfigurationManager.getStaledFibEntriesMap();
1074         boolean addroute = false;
1075         if (!stale_fib_rd_map.isEmpty()) {
1076             // restart Scenario, as MAP is not empty.
1077             Map<String, String> map = stale_fib_rd_map.get(rd);
1078             if (map !=null) {
1079                 String nexthoplabel = map.get(prefix + "/" + plen);
1080                 if (null == nexthoplabel) {
1081                     // New Entry, which happend to be added during restart.
1082                     addroute = true;
1083                 } else {
1084                     map.remove(prefix + "/" + plen);
1085                     if (isRouteModified(nexthop, label, nexthoplabel)) {
1086                         LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix,
1087                                 plen, nexthop, label);
1088                         // Existing entry, where in Nexthop/Label got modified during restart
1089                         addroute = true;
1090                     }
1091                 }
1092             }
1093         } else {
1094             LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix,
1095                     plen, nexthop, label);
1096             addroute = true;
1097         }
1098         if (addroute) {
1099             fib.addFibEntryToDS(rd, prefix + "/" + plen,
1100                     nexthop, label);
1101         }
1102     }
1103
1104     private static boolean isRouteModified(String nexthop, int label, String nexthoplabel) {
1105         return !nexthoplabel.isEmpty() && !nexthoplabel.equals(nexthop+"/"+label);
1106     }
1107
1108     static private void replayNbrConfig(List<Neighbors> n, BgpRouter br) { 
1109         for (Neighbors nbr : n) {
1110             try {
1111                 br.addNeighbor(nbr.getAddress().getValue(),
1112                                nbr.getRemoteAs().intValue());
1113                 //itmProvider.buildTunnelsToDCGW(new IpAddress(nbr.getAddress().getValue().toCharArray()));
1114             } catch (Exception e) {
1115                 LOG.error("Replay:addNbr() received exception: \""+e+"\"");
1116                 continue;
1117             }
1118             EbgpMultihop en = nbr.getEbgpMultihop();
1119             if (en != null) {
1120                 try {
1121                     br.addEbgpMultihop(en.getPeerIp().getValue(), 
1122                                        en.getNhops().intValue()); 
1123                 } catch (Exception e) {
1124                     LOG.error("Replay:addEBgp() received exception: \""+e+"\"");
1125                 }
1126             }
1127             UpdateSource us = nbr.getUpdateSource();
1128             if (us != null) {
1129                 try {
1130                     br.addUpdateSource(us.getPeerIp().getValue(),
1131                                        us.getSourceIp().getValue());
1132                 } catch (Exception e) {
1133                     LOG.error("Replay:addUS() received exception: \""+e+"\"");
1134                 }
1135             }
1136             List<AddressFamilies> afs = nbr.getAddressFamilies();
1137             if (afs != null) {
1138                 for (AddressFamilies af : afs) {
1139                     af_afi afi = af_afi.findByValue(af.getAfi().intValue());
1140                     af_safi safi = af_safi.findByValue(af.getSafi().intValue());
1141                     try {
1142                         br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
1143                     } catch (Exception e) {
1144                         LOG.error("Replay:addAf() received exception: \""+e+"\"");
1145                     }
1146                 }
1147             }
1148         }
1149     }
1150
1151     public static String getConfigHost() {
1152         if (config == null) {
1153             return cHostStartup;
1154         }
1155         ConfigServer ts = config.getConfigServer();
1156         return (ts == null ? cHostStartup : ts.getHost().getValue());
1157     }
1158
1159     public static int getConfigPort() {
1160         if (config == null) {
1161             return Integer.parseInt(cPortStartup);
1162         }
1163         ConfigServer ts = config.getConfigServer();
1164         return (ts == null ? Integer.parseInt(cPortStartup) :
1165                              ts.getPort().intValue());
1166     }
1167
1168     public static synchronized void replay() {
1169         String host = getConfigHost();
1170         int port = getConfigPort();
1171         boolean res = bgpRouter.connect(host, port);
1172         if (!res) {
1173             String msg = "Cannot connect to BGP config server at "+host+":"+port;
1174             if (config != null) {
1175                 msg += "; Configuration Replay aborted";
1176             }
1177             LOG.error(msg);
1178             return;
1179         }
1180         if (config == null) {
1181             return;
1182         }
1183         BgpRouter br = bgpRouter; 
1184         AsId a = config.getAsId();
1185         if (a == null) {
1186             return;
1187         }
1188         int asNum = a.getLocalAs().intValue();
1189         Ipv4Address routerId = a.getRouterId();
1190         Long spt = a.getStalepathTime();
1191         Boolean afb = a.isAnnounceFbit();
1192         String rid = (routerId == null) ? "" : routerId.getValue();
1193         int stalepathTime = (spt == null) ? 90 : spt.intValue(); 
1194         boolean announceFbit = (afb == null) ? false : afb.booleanValue();
1195         try {
1196             br.startBgp(asNum, rid, stalepathTime, announceFbit); 
1197         } catch (BgpRouterException bre) {
1198             if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
1199                 doRouteSync();
1200             } else {
1201                 LOG.error("Replay: startBgp() received exception: \""
1202                           +bre+"\"; "+addWarn);
1203             }
1204         } catch (Exception e) {
1205             //not unusual. We may have restarted & BGP is already on
1206             LOG.error("Replay:startBgp() received exception: \""+e+"\"");
1207         }
1208
1209         if (bgpManager.getBgpCounters() == null) {
1210             bgpManager.startBgpCountersTask();
1211         }
1212       
1213         Logging l = config.getLogging();
1214         if (l != null) {
1215             try {
1216                 br.setLogging(l.getFile(), l.getLevel());
1217             } catch (Exception e) {
1218                 LOG.error("Replay:setLogging() received exception: \""+e+"\"");
1219             }
1220         }
1221
1222         GracefulRestart g = config.getGracefulRestart();
1223         if (g != null) {
1224             try {
1225                 br.addGracefulRestart(g.getStalepathTime().intValue()); 
1226             } catch (Exception e) {
1227                 LOG.error("Replay:addGr() received exception: \""+e+"\"");
1228             }
1229         }
1230
1231         List<Neighbors> n = config.getNeighbors();
1232         if (n != null) {
1233             replayNbrConfig(n, br);
1234         }
1235
1236         List<Vrfs> v = config.getVrfs();
1237         if (v != null) {
1238             for (Vrfs vrf : v)  {
1239                 try {
1240                     br.addVrf(vrf.getRd(), vrf.getImportRts(), 
1241                     vrf.getExportRts());
1242                 } catch (Exception e) {
1243                     LOG.error("Replay:addVrf() received exception: \""+e+"\"");
1244                 }
1245             }
1246         }
1247
1248         List<Networks> ln = config.getNetworks();
1249         if (ln != null) {
1250             for (Networks net : ln) {
1251                 String rd = net.getRd();
1252                 String pfxlen = net.getPrefixLen();
1253                 String nh = net.getNexthop().getValue();
1254                 Long label = net.getLabel();
1255                 int lbl = (label == null) ? 0 : label.intValue();
1256                 if (rd == null && lbl > 0) {
1257                     //LU prefix is being deleted. 
1258                     rd = Integer.toString(lbl);
1259                 }
1260                 try {
1261                     br.addPrefix(rd, pfxlen, nh, lbl); 
1262                 } catch (Exception e) {
1263                     LOG.error("Replay:addPfx() received exception: \""+e+"\"");
1264                 }
1265             }
1266         }
1267     }
1268
1269     private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
1270         BgpUtil.update(broker, LogicalDatastoreType.CONFIGURATION, iid, dto);
1271     }
1272
1273     private <T extends DataObject> void asyncWrite(InstanceIdentifier<T> iid, T dto) {
1274         BgpUtil.write(broker,LogicalDatastoreType.CONFIGURATION,iid,dto);
1275     }
1276
1277     private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
1278         BgpUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, iid);
1279     } 
1280
1281     public synchronized void
1282     startConfig(String bgpHost, int thriftPort) {
1283         InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
1284             InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
1285         InstanceIdentifier<ConfigServer> iid = iib.build();
1286         Ipv4Address ipAddr = new Ipv4Address(bgpHost);
1287         ConfigServer dto  = new ConfigServerBuilder().setHost(ipAddr)
1288                                             .setPort((long) thriftPort).build();
1289         update(iid, dto);
1290     }
1291
1292     public synchronized void
1293     startBgp(int as, String routerId, int spt, boolean fbit) {
1294         Long localAs = (long) as;
1295         Ipv4Address rid = (routerId == null) ? 
1296                            null : new Ipv4Address(routerId);
1297         Long staleTime = (long) spt;
1298         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
1299             InstanceIdentifier.builder(Bgp.class).child(AsId.class);
1300         InstanceIdentifier<AsId> iid = iib.build();
1301         AsId dto = new AsIdBuilder().setLocalAs(localAs)
1302                                     .setRouterId(rid)
1303                                     .setStalepathTime(staleTime)
1304                                     .setAnnounceFbit(fbit).build();
1305         update(iid, dto);
1306     }
1307
1308     public synchronized void
1309     addLogging(String fileName, String logLevel) {
1310         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
1311             InstanceIdentifier.builder(Bgp.class).child(Logging.class);
1312         InstanceIdentifier<Logging> iid = iib.build();
1313         Logging dto = new LoggingBuilder().setFile(fileName)
1314                                           .setLevel(logLevel).build();
1315         update(iid, dto);
1316     }
1317
1318     public synchronized void
1319     addGracefulRestart(int staleTime) {
1320         InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib = 
1321             InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
1322         InstanceIdentifier<GracefulRestart> iid = iib.build();
1323         GracefulRestart dto = new GracefulRestartBuilder()
1324                                      .setStalepathTime((long)staleTime).build();
1325         update(iid, dto);
1326     }
1327
1328     public synchronized void
1329     addNeighbor(String nbrIp, int remoteAs) {
1330         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1331         Long rAs = (long) remoteAs;
1332         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib = 
1333             InstanceIdentifier.builder(Bgp.class)
1334                               .child(Neighbors.class, new NeighborsKey(nbrAddr));
1335         InstanceIdentifier<Neighbors> iid = iib.build();
1336         Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
1337                                               .setRemoteAs(rAs).build();
1338         update(iid, dto);
1339     }
1340
1341     public synchronized void
1342     addUpdateSource(String nbrIp, String srcIp) {
1343         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1344         Ipv4Address srcAddr = new Ipv4Address(srcIp);
1345         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib = 
1346             InstanceIdentifier.builder(Bgp.class)
1347                               .child(Neighbors.class, new NeighborsKey(nbrAddr))
1348                               .child(UpdateSource.class);
1349         InstanceIdentifier<UpdateSource> iid = iib.build();
1350         UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
1351                                                   .setSourceIp(srcAddr).build();
1352         update(iid, dto);
1353     }
1354
1355     public synchronized void
1356     addEbgpMultihop(String nbrIp, int nHops) {
1357         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1358         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib = 
1359             InstanceIdentifier.builder(Bgp.class)
1360                               .child(Neighbors.class, new NeighborsKey(nbrAddr))
1361                               .child(EbgpMultihop.class);
1362         InstanceIdentifier<EbgpMultihop> iid = iib.build();
1363         EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
1364                                                  .setNhops((long)nHops).build();
1365         update(iid, dto);
1366     }
1367
1368     public synchronized void
1369     addAddressFamily(String nbrIp, int afi, int safi) {
1370         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1371         Long a = (long) afi;
1372         Long sa = (long) safi;
1373         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib = 
1374             InstanceIdentifier.builder(Bgp.class)
1375                               .child(Neighbors.class, new NeighborsKey(nbrAddr))
1376                    .child(AddressFamilies.class, new AddressFamiliesKey(a, sa));
1377         InstanceIdentifier<AddressFamilies> iid = iib.build();
1378         AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
1379                                                  .setAfi(a).setSafi(sa).build();
1380         update(iid, dto);
1381     }
1382
1383     public synchronized void
1384     addPrefix(String rd, String pfx, String nh, int lbl) {
1385         Ipv4Address nexthop = new Ipv4Address(nh);
1386         Long label = (long) lbl;
1387         InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib = 
1388             InstanceIdentifier.builder(Bgp.class)
1389                               .child(Networks.class, new NetworksKey(pfx, rd));
1390         InstanceIdentifier<Networks> iid = iib.build();
1391         Networks dto = new NetworksBuilder().setRd(rd)
1392                                             .setPrefixLen(pfx)
1393                                             .setNexthop(nexthop)
1394                                             .setLabel(label).build();
1395         update(iid, dto);
1396     }
1397
1398     public synchronized void
1399     addVrf(String rd, List<String> irts, List<String> erts) {
1400         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
1401             InstanceIdentifier.builder(Bgp.class)
1402                               .child(Vrfs.class, new VrfsKey(rd));
1403         InstanceIdentifier<Vrfs> iid = iib.build();
1404         Vrfs dto = new VrfsBuilder().setRd(rd)
1405                                     .setImportRts(irts)
1406                                     .setExportRts(erts).build();
1407
1408         asyncWrite(iid, dto);
1409     }
1410
1411     public synchronized void stopConfig() {
1412         InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
1413             InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
1414         InstanceIdentifier<ConfigServer> iid = iib.build();
1415         delete(iid);
1416     }
1417
1418     public synchronized void stopBgp() {
1419         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
1420             InstanceIdentifier.builder(Bgp.class).child(AsId.class);
1421         InstanceIdentifier<AsId> iid = iib.build();
1422         delete(iid);
1423     }
1424
1425     public synchronized void delLogging() {
1426         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
1427             InstanceIdentifier.builder(Bgp.class).child(Logging.class);
1428         InstanceIdentifier<Logging> iid = iib.build();
1429         delete(iid);
1430     }
1431
1432     public synchronized void delGracefulRestart() {
1433         InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib = 
1434             InstanceIdentifier.builder(Bgp.class)
1435                               .child(GracefulRestart.class);
1436         InstanceIdentifier<GracefulRestart> iid = iib.build();
1437         delete(iid);
1438     }
1439
1440     public synchronized void delNeighbor(String nbrIp) {
1441         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1442         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib = 
1443             InstanceIdentifier.builder(Bgp.class)
1444                               .child(Neighbors.class, new NeighborsKey(nbrAddr));
1445         InstanceIdentifier<Neighbors> iid = iib.build();
1446         delete(iid);
1447     }
1448
1449     public synchronized void delUpdateSource(String nbrIp) {
1450         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1451         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib = 
1452             InstanceIdentifier.builder(Bgp.class)
1453                               .child(Neighbors.class, new NeighborsKey(nbrAddr))
1454                               .child(UpdateSource.class);
1455         InstanceIdentifier<UpdateSource> iid = iib.build();
1456         delete(iid);
1457     }
1458
1459     public synchronized void delEbgpMultihop(String nbrIp) {
1460         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1461         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib = 
1462             InstanceIdentifier.builder(Bgp.class)
1463                               .child(Neighbors.class, new NeighborsKey(nbrAddr))
1464                               .child(EbgpMultihop.class);
1465         InstanceIdentifier<EbgpMultihop> iid = iib.build();
1466         delete(iid);
1467     }
1468
1469     public synchronized void 
1470     delAddressFamily(String nbrIp, int afi, int safi) {
1471         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1472         Long a = (long) afi;
1473         Long sa = (long) safi;
1474         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib = 
1475             InstanceIdentifier.builder(Bgp.class)
1476                               .child(Neighbors.class, new NeighborsKey(nbrAddr))
1477                    .child(AddressFamilies.class, new AddressFamiliesKey(a, sa));
1478         InstanceIdentifier<AddressFamilies> iid = iib.build();
1479         delete(iid);
1480     }
1481
1482     public synchronized void delPrefix(String rd, String pfx) {
1483         InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib = 
1484             InstanceIdentifier.builder(Bgp.class)
1485                               .child(Networks.class, new NetworksKey(pfx, rd));
1486         InstanceIdentifier<Networks> iid = iib.build();
1487         delete(iid);
1488     }
1489
1490     public synchronized void delVrf(String rd) {
1491         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib = 
1492             InstanceIdentifier.builder(Bgp.class)
1493                               .child(Vrfs.class, new VrfsKey(rd));
1494         InstanceIdentifier<Vrfs> iid = iib.build();
1495         delete(iid);
1496     }
1497
1498     static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
1499     /*
1500     * Remove Stale Marked Routes after timer expiry.
1501     */
1502     class RouteCleanup implements Callable<Integer> {
1503
1504         public Integer call () {
1505             int totalCleared = 0;
1506             try {
1507             if (staledFibEntriesMap.isEmpty()) {
1508                 LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
1509             } else {
1510                 for (String rd : staledFibEntriesMap.keySet()) {
1511                     if (Thread.interrupted()) {
1512                         return 0;
1513                     }
1514                     Map<String, String> map = staledFibEntriesMap.get(rd);
1515                     if (map != null) {
1516                         for (String prefix : map.keySet()) {
1517                             if (Thread.interrupted()) {
1518                                 return 0;
1519                             }
1520                             try {
1521                                 totalCleared++;
1522                                 bgpManager.deletePrefix(rd, prefix);
1523                             } catch (Exception e) {
1524                                 LOG.error("BGP: RouteCleanup deletePrefix failed rd:{}, prefix{}" + rd.toString() + prefix);
1525                             }
1526                         }
1527                     }
1528                 }
1529             }
1530             } catch(Exception e) {
1531                 LOG.error("Cleanup Thread Got interrupted, Failed to cleanup stale routes ", e);
1532             } finally {
1533                 staledFibEntriesMap.clear();
1534             }
1535             LOG.error("cleared {} stale routes after bgp restart", totalCleared);
1536             return 0;
1537         }
1538     }
1539
1540     /*
1541      * BGP restart scenario, ODL-BGP manager was/is running.
1542      * On re-sync notification, Get a copy of FIB database.
1543      */
1544     public static void createStaleFibMap() {
1545         int totalStaledCount = 0;
1546         try {
1547             staledFibEntriesMap.clear();
1548             InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
1549             DataBroker db = BgpUtil.getBroker();
1550             if (db == null) {
1551                 LOG.error("Couldn't find BgpUtil broker while creating createStaleFibMap");
1552                 return;
1553             }
1554     
1555             Optional<FibEntries> fibEntries = BgpUtil.read(BgpUtil.getBroker(),
1556                     LogicalDatastoreType.CONFIGURATION, id);
1557             if (fibEntries.isPresent()) {
1558                 List<VrfTables> stale_vrfTables = fibEntries.get().getVrfTables();
1559                 for (VrfTables vrfTable : stale_vrfTables) {
1560                     Map<String, String> stale_fib_ent_map = new HashMap<>();
1561                     for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
1562                         if (Thread.interrupted()) {
1563                             break;
1564                         }
1565                         totalStaledCount++;
1566                         //Create MAP from stale_vrfTables.
1567                         stale_fib_ent_map.put(vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddress() + "/" + vrfEntry.getLabel());
1568                     }
1569                 staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), stale_fib_ent_map);
1570                 }
1571             } else {
1572                     LOG.error("createStaleFibMap:: FIBentries.class is not present");
1573             }
1574         } catch (Exception e) {
1575             LOG.error("createStaleFibMap:: erorr ", e);
1576         }
1577         LOG.error("created {} staled entries ", totalStaledCount);
1578     }
1579
1580     //map<rd, map<prefix/len, nexthop/label>>
1581     public static Map<String, Map<String, String>> getStaledFibEntriesMap() {
1582         return staledFibEntriesMap;
1583     }
1584
1585
1586 }