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