BUG-2383 : wired cluster id with effective RIB
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / RIBImpl.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. 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 package org.opendaylight.protocol.bgp.rib.impl;
9
10 import com.google.common.base.MoreObjects;
11 import com.google.common.base.MoreObjects.ToStringHelper;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.ImmutableSet;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Set;
21 import java.util.concurrent.BlockingQueue;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentMap;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.LinkedBlockingQueue;
26 import javax.annotation.concurrent.ThreadSafe;
27 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
28 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
29 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
33 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
34 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
35 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
36 import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
37 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
38 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
39 import org.opendaylight.protocol.bgp.rib.DefaultRibReference;
40 import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOut;
41 import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOutRegistration;
42 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
43 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
44 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
45 import org.opendaylight.protocol.bgp.rib.spi.AbstractAdjRIBs;
46 import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
47 import org.opendaylight.protocol.bgp.rib.spi.BGPObjectComparator;
48 import org.opendaylight.protocol.bgp.rib.spi.Peer;
49 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
50 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv4RoutesCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv6RoutesCase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.prefixes.DestinationIpv4Builder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.prefixes.destination.ipv4.Ipv4Prefixes;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.prefixes.destination.ipv4.Ipv4PrefixesBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationIpv4CaseBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.UpdateBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.Nlri;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.WithdrawnRoutes;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlri;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlri;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlriBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.BgpRib;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRib;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRibBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
87 import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory;
88 import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
89 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
90 import org.opendaylight.yangtools.yang.common.QName;
91 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
92 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
93 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
94 import org.slf4j.Logger;
95 import org.slf4j.LoggerFactory;
96
97 @ThreadSafe
98 public final class RIBImpl extends DefaultRibReference implements AutoCloseable, RIB, TransactionChainListener, SchemaContextListener {
99     private static final Logger LOG = LoggerFactory.getLogger(RIBImpl.class);
100     private static final Update EOR = new UpdateBuilder().build();
101     private static final TablesKey IPV4_UNICAST_TABLE = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
102     private static final QName RIB_ID_QNAME = QName.cachedReference(QName.create(Rib.QNAME, "id"));
103
104     /*
105      * FIXME: performance: this needs to be turned into a Peer->offset map.
106      *        The offset is used to locate a the per-peer state entry in the
107      *        RIB tables.
108      *
109      *        For the first release, that map is updated whenever configuration
110      *        changes and remains constant on peer flaps. On re-configuration
111      *        a resize task is scheduled, so large tables may take some time
112      *        before they continue reacting to updates.
113      *
114      *        For subsequent releases, if we make the reformat process concurrent,
115      *        we can trigger reformats when Graceful Restart Time expires for a
116      *        particular peer.
117      */
118     private final ConcurrentMap<Peer, AdjRIBsOut> ribOuts = new ConcurrentHashMap<>();
119     private final ReconnectStrategyFactory tcpStrategyFactory;
120     private final ReconnectStrategyFactory sessionStrategyFactory;
121
122     /**
123      * BGP Best Path selection comparator for ingress best path selection.
124      */
125     private final BGPObjectComparator comparator;
126     private final BGPDispatcher dispatcher;
127     private final BindingTransactionChain chain;
128     private final AsNumber localAs;
129     private final Ipv4Address bgpIdentifier;
130     private final ClusterIdentifier clusterId;
131     private final Set<BgpTableType> localTables;
132     private final RIBTables tables;
133     private final BlockingQueue<Peer> peers;
134     private final DataBroker dataBroker;
135     private final DOMDataBroker domDataBroker;
136     private final RIBExtensionConsumerContext extensions;
137     private final YangInstanceIdentifier yangRibId;
138     private final RIBSupportContextRegistryImpl ribContextRegistry;
139     private final Runnable scheduler = new Runnable() {
140         @Override
141         public void run() {
142             try {
143                 final Peer peer = RIBImpl.this.peers.take();
144                 LOG.debug("Advertizing loc-rib to new peer {}.", peer);
145                 for (final BgpTableType key : RIBImpl.this.localTables) {
146
147                     synchronized (RIBImpl.this) {
148                         final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(RIBImpl.this.ribOuts, RIBImpl.this.comparator, RIBImpl.this.chain.newWriteOnlyTransaction());
149                         final AbstractAdjRIBs<?, ?, ?> adj = (AbstractAdjRIBs<?, ?, ?>) RIBImpl.this.tables.get(new TablesKey(key.getAfi(), key.getSafi()));
150                         adj.addAllEntries(trans);
151                         Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
152                             @Override
153                             public void onSuccess(final Void result) {
154                                 LOG.trace("Advertizing {} to peer {} committed successfully", key.getAfi(), peer);
155                             }
156                             @Override
157                             public void onFailure(final Throwable t) {
158                                 LOG.error("Failed to update peer {} with RIB {}", peer, t);
159                             }
160                         });
161                     }
162                 }
163             } catch (final InterruptedException e) {
164                 LOG.info("Scheduler thread was interrupted.", e);
165             }
166         }
167     };
168
169     public RIBImpl(final RibId ribId, final AsNumber localAs, final Ipv4Address localBgpId, final Ipv4Address clusterId, final RIBExtensionConsumerContext extensions,
170         final BGPDispatcher dispatcher, final ReconnectStrategyFactory tcpStrategyFactory, final BindingCodecTreeFactory codecFactory,
171         final ReconnectStrategyFactory sessionStrategyFactory, final DataBroker dps, final DOMDataBroker domDataBroker, final List<BgpTableType> localTables, final GeneratedClassLoadingStrategy classStrategy) {
172         super(InstanceIdentifier.create(BgpRib.class).child(Rib.class, new RibKey(Preconditions.checkNotNull(ribId))));
173         this.chain = dps.createTransactionChain(this);
174         this.localAs = Preconditions.checkNotNull(localAs);
175         this.comparator = new BGPObjectComparator(localAs);
176         this.bgpIdentifier = Preconditions.checkNotNull(localBgpId);
177         this.clusterId = (clusterId == null) ? new ClusterIdentifier(localBgpId) : new ClusterIdentifier(clusterId);
178         this.dispatcher = Preconditions.checkNotNull(dispatcher);
179         this.sessionStrategyFactory = Preconditions.checkNotNull(sessionStrategyFactory);
180         this.tcpStrategyFactory = Preconditions.checkNotNull(tcpStrategyFactory);
181         this.localTables = ImmutableSet.copyOf(localTables);
182         this.tables = new RIBTables(extensions);
183         this.peers = new LinkedBlockingQueue<>();
184         this.dataBroker = dps;
185         this.domDataBroker = Preconditions.checkNotNull(domDataBroker);
186         this.extensions = Preconditions.checkNotNull(extensions);
187         this.ribContextRegistry = RIBSupportContextRegistryImpl.create(extensions, codecFactory, classStrategy);
188         this.yangRibId = YangInstanceIdentifier.builder().node(BgpRib.QNAME).node(Rib.QNAME).nodeWithKey(Rib.QNAME, RIB_ID_QNAME, ribId.getValue()).build();
189
190         LOG.debug("Instantiating RIB table {} at {}", ribId, getInstanceIdentifier());
191
192         final WriteTransaction trans = this.chain.newWriteOnlyTransaction();
193
194         final PolicyDatabase pd  = new PolicyDatabase(localAs.getValue(), localBgpId, this.clusterId);
195
196         final DOMDataBrokerExtension service = this.domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class);
197         final DOMTransactionChain domChain = this.createPeerChain(this);
198         EffectiveRibInWriter.create((DOMDataTreeChangeService) service, domChain, getYangRibId(), pd, this.ribContextRegistry);
199         LOG.debug("Effective RIB created.");
200
201         // put empty BgpRib if not exists
202         trans.put(LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier(),
203             new RibBuilder().setKey(new RibKey(ribId)).setPeer(Collections.<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer> emptyList()).setId(ribId).setLocRib(
204             new LocRibBuilder().setTables(Collections.<Tables> emptyList()).build()).build(), true);
205
206         for (final BgpTableType t : localTables) {
207             final TablesKey key = new TablesKey(t.getAfi(), t.getSafi());
208             if (this.tables.create(trans, this, key) == null) {
209                 LOG.debug("Did not create local table for unhandled table type {}", t);
210             }
211
212             // reusing the for cycle
213             // create locRibWriter for each table
214             // FIXME: temporary create writer only for Ipv4
215             if (key.getAfi().equals(Ipv4AddressFamily.class)) {
216                 LocRibWriter.create(this.ribContextRegistry.getRIBSupportContext(key).getRibSupport(), domChain, getYangRibId(), localAs, (DOMDataTreeChangeService) service, pd);
217             }
218         }
219
220         Futures.addCallback(trans.submit(), new FutureCallback<Void>() {
221             @Override
222             public void onSuccess(final Void result) {
223                 LOG.trace("Change committed successfully");
224             }
225
226             @Override
227             public void onFailure(final Throwable t) {
228                 LOG.error("Failed to initiate RIB {}", getInstanceIdentifier(), t);
229             }
230
231         });
232     }
233
234     synchronized void initTables(final byte[] remoteBgpId) {
235     }
236
237     @Override
238     public synchronized void updateTables(final Peer peer, final Update message) {
239         final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(this.ribOuts, this.comparator, this.chain.newWriteOnlyTransaction());
240
241         if (!EOR.equals(message)) {
242             final WithdrawnRoutes wr = message.getWithdrawnRoutes();
243             if (wr != null) {
244                 final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
245                 if (ari != null) {
246                     /*
247                      * create MPUnreach for the routes to be handled in the same way as linkstate routes
248                      */
249                     final List<Ipv4Prefixes> prefixes = new ArrayList<>();
250                     for (final Ipv4Prefix p : wr.getWithdrawnRoutes()) {
251                         prefixes.add(new Ipv4PrefixesBuilder().setPrefix(p).build());
252                     }
253                     ari.removeRoutes(
254                         trans,
255                         peer,
256                         new MpUnreachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).setWithdrawnRoutes(
257                             new WithdrawnRoutesBuilder().setDestinationType(
258                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationIpv4CaseBuilder().setDestinationIpv4(
259                                     new DestinationIpv4Builder().setIpv4Prefixes(prefixes).build()).build()).build()).build());
260                 } else {
261                     LOG.debug("Not removing objects from unhandled IPv4 Unicast");
262                 }
263             }
264
265             final PathAttributes attrs = message.getPathAttributes();
266             if (attrs != null) {
267                 final PathAttributes2 mpu = attrs.getAugmentation(PathAttributes2.class);
268                 if (mpu != null) {
269                     final MpUnreachNlri nlri = mpu.getMpUnreachNlri();
270                     final AdjRIBsIn<?, ?> ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
271                     // EOR messages do not contain withdrawn routes
272                     if (nlri.getWithdrawnRoutes() != null) {
273                         if (ari != null) {
274                             ari.removeRoutes(trans, peer, nlri);
275                         } else {
276                             LOG.debug("Not removing objects from unhandled NLRI {}", nlri);
277                         }
278                     } else {
279                         ari.markUptodate(trans, peer);
280                     }
281                 }
282             }
283
284             final Nlri ar = message.getNlri();
285             if (ar != null) {
286                 final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
287                 if (ari != null) {
288                     /*
289                      * create MPReach for the routes to be handled in the same way as linkstate routes
290                      */
291                     final List<Ipv4Prefixes> prefixes = new ArrayList<>();
292                     for (final Ipv4Prefix p : ar.getNlri()) {
293                         prefixes.add(new Ipv4PrefixesBuilder().setPrefix(p).build());
294                     }
295                     final MpReachNlriBuilder b = new MpReachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(
296                         UnicastSubsequentAddressFamily.class).setAdvertizedRoutes(
297                             new AdvertizedRoutesBuilder().setDestinationType(
298                                 new DestinationIpv4CaseBuilder().setDestinationIpv4(
299                                     new DestinationIpv4Builder().setIpv4Prefixes(prefixes).build()).build()).build());
300                     if (attrs != null) {
301                         b.setCNextHop(attrs.getCNextHop());
302                     }
303
304                     ari.addRoutes(trans, peer, b.build(), attrs);
305                 } else {
306                     LOG.debug("Not adding objects from unhandled IPv4 Unicast");
307                 }
308             }
309
310             if (attrs != null) {
311                 final PathAttributes1 mpr = attrs.getAugmentation(PathAttributes1.class);
312                 if (mpr != null) {
313                     final MpReachNlri nlri = mpr.getMpReachNlri();
314
315                     final AdjRIBsIn<?, ?> ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
316                     if (ari != null) {
317                         if (message.equals(ari.endOfRib())) {
318                             ari.markUptodate(trans, peer);
319                         } else {
320                             ari.addRoutes(trans, peer, nlri, attrs);
321                         }
322                     } else {
323                         LOG.debug("Not adding objects from unhandled NLRI {}", nlri);
324                     }
325                 }
326             }
327         } else {
328             final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
329             if (ari != null) {
330                 ari.markUptodate(trans, peer);
331             } else {
332                 LOG.debug("End-of-RIB for IPv4 Unicast ignored");
333             }
334         }
335
336         Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
337             @Override
338             public void onSuccess(final Void result) {
339                 LOG.debug("RIB modification successfully committed.");
340             }
341
342             @Override
343             public void onFailure(final Throwable t) {
344                 LOG.error("Failed to commit RIB modification", t);
345             }
346         });
347     }
348
349     @Override
350     public synchronized void clearTable(final Peer peer, final TablesKey key) {
351         final AdjRIBsIn<?, ?> ari = this.tables.get(key);
352         if (ari != null) {
353             final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(this.ribOuts, this.comparator, this.chain.newWriteOnlyTransaction());
354             ari.clear(trans, peer);
355
356             Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
357                 @Override
358                 public void onSuccess(final Void result) {
359                     LOG.trace("Table {} cleared successfully", key);
360                 }
361
362                 @Override
363                 public void onFailure(final Throwable t) {
364                     LOG.error("Failed to clear table {}", key, t);
365                 }
366             });
367         }
368     }
369
370     @Override
371     public String toString() {
372         return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
373     }
374
375     protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
376         return toStringHelper;
377     }
378
379     @SuppressWarnings("unchecked")
380     protected <K, V extends Route> AdjRIBsIn<K, V> getTable(final TablesKey key) {
381         return (AdjRIBsIn<K, V>) this.tables.get(key);
382     }
383
384     @Override
385     public synchronized void close() throws InterruptedException, ExecutionException {
386         final WriteTransaction t = this.chain.newWriteOnlyTransaction();
387         t.delete(LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier());
388         t.submit().get();
389         this.chain.close();
390     }
391
392     @Override
393     public AsNumber getLocalAs() {
394         return this.localAs;
395     }
396
397     @Override
398     public Ipv4Address getBgpIdentifier() {
399         return this.bgpIdentifier;
400     }
401
402     @Override
403     public Set<? extends BgpTableType> getLocalTables() {
404         return this.localTables;
405     }
406
407     @Override
408     public ReconnectStrategyFactory getTcpStrategyFactory() {
409         return this.tcpStrategyFactory;
410     }
411
412     @Override
413     public ReconnectStrategyFactory getSessionStrategyFactory() {
414         return this.sessionStrategyFactory;
415     }
416
417     @Override
418     public BGPDispatcher getDispatcher() {
419         return this.dispatcher;
420     }
421
422     @Override
423     public void initTable(final Peer bgpPeer, final TablesKey key) {
424         // FIXME: BUG-196: support graceful restart
425     }
426
427     @Override
428     public AdjRIBsOutRegistration registerRIBsOut(final Peer peer, final AdjRIBsOut aro) {
429         final AdjRIBsOutRegistration reg = new AdjRIBsOutRegistration(aro) {
430             @Override
431             protected void removeRegistration() {
432                 RIBImpl.this.ribOuts.remove(peer, aro);
433             }
434         };
435
436         this.ribOuts.put(peer, aro);
437         LOG.debug("Registering this peer {} to RIB-Out {}", peer, this.ribOuts);
438         try {
439             this.peers.put(peer);
440             new Thread(this.scheduler).start();
441         } catch (final InterruptedException e) {
442             //
443         }
444         return reg;
445     }
446
447     @Override
448     public void onTransactionChainFailed(final TransactionChain<?, ?> chain, final AsyncTransaction<?, ?> transaction, final Throwable cause) {
449         LOG.error("Broken chain in RIB {} transaction {}", getInstanceIdentifier(), transaction.getIdentifier(), cause);
450     }
451
452     @Override
453     public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
454         LOG.info("RIB {} closed successfully", getInstanceIdentifier());
455     }
456
457     @Override
458     public long getRoutesCount(final TablesKey key) {
459         try {
460             final Optional<Tables> tableMaybe = this.dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
461                     getInstanceIdentifier().child(LocRib.class).child(Tables.class, key)).checkedGet();
462             if (tableMaybe.isPresent()) {
463                 final Tables table = tableMaybe.get();
464                 if (table.getRoutes() instanceof Ipv4RoutesCase) {
465                     final Ipv4RoutesCase routesCase = (Ipv4RoutesCase) table.getRoutes();
466                     if (routesCase.getIpv4Routes() != null && routesCase.getIpv4Routes().getIpv4Route() != null) {
467                         return routesCase.getIpv4Routes().getIpv4Route().size();
468                     }
469                 } else if (table.getRoutes() instanceof Ipv6RoutesCase) {
470                     final Ipv6RoutesCase routesCase = (Ipv6RoutesCase) table.getRoutes();
471                     if (routesCase.getIpv6Routes() != null && routesCase.getIpv6Routes().getIpv6Route() != null) {
472                         return routesCase.getIpv6Routes().getIpv6Route().size();
473                     }
474                 }
475             }
476         } catch (final ReadFailedException e) {
477             //no-op
478         }
479         return 0;
480     }
481
482     @Override
483     public YangInstanceIdentifier getYangRibId() {
484         return this.yangRibId;
485     }
486
487     @Override
488     public DOMTransactionChain createPeerChain(final TransactionChainListener listener) {
489         return this.domDataBroker.createTransactionChain(listener);
490     }
491
492     @Override
493     public RIBExtensionConsumerContext getRibExtensions() {
494         return this.extensions;
495     }
496
497     @Override
498     public RIBSupportContextRegistry getRibSupportContext() {
499         return this.ribContextRegistry;
500     }
501
502     @Override
503     public void onGlobalContextUpdated(final SchemaContext context) {
504         this.ribContextRegistry.onSchemaContextUpdated(context);
505     }
506 }