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