Merge "Bug 2938: register serializers for all augmentations"
[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 EffectiveRibInWriter efWriter;
140
141     private final Runnable scheduler = new Runnable() {
142         @Override
143         public void run() {
144             try {
145                 final Peer peer = RIBImpl.this.peers.take();
146                 LOG.debug("Advertizing loc-rib to new peer {}.", peer);
147                 for (final BgpTableType key : RIBImpl.this.localTables) {
148
149                     synchronized (RIBImpl.this) {
150                         final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(RIBImpl.this.ribOuts, RIBImpl.this.comparator, RIBImpl.this.chain.newWriteOnlyTransaction());
151                         final AbstractAdjRIBs<?, ?, ?> adj = (AbstractAdjRIBs<?, ?, ?>) RIBImpl.this.tables.get(new TablesKey(key.getAfi(), key.getSafi()));
152                         adj.addAllEntries(trans);
153                         Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
154                             @Override
155                             public void onSuccess(final Void result) {
156                                 LOG.trace("Advertizing {} to peer {} committed successfully", key.getAfi(), peer);
157                             }
158                             @Override
159                             public void onFailure(final Throwable t) {
160                                 LOG.error("Failed to update peer {} with RIB {}", peer, t);
161                             }
162                         });
163                     }
164                 }
165             } catch (final InterruptedException e) {
166                 LOG.info("Scheduler thread was interrupted.", e);
167             }
168         }
169     };
170
171     public RIBImpl(final RibId ribId, final AsNumber localAs, final Ipv4Address localBgpId, final Ipv4Address clusterId, final RIBExtensionConsumerContext extensions,
172         final BGPDispatcher dispatcher, final ReconnectStrategyFactory tcpStrategyFactory, final BindingCodecTreeFactory codecFactory,
173         final ReconnectStrategyFactory sessionStrategyFactory, final DataBroker dps, final DOMDataBroker domDataBroker, final List<BgpTableType> localTables, final GeneratedClassLoadingStrategy classStrategy) {
174         super(InstanceIdentifier.create(BgpRib.class).child(Rib.class, new RibKey(Preconditions.checkNotNull(ribId))));
175         this.chain = dps.createTransactionChain(this);
176         this.localAs = Preconditions.checkNotNull(localAs);
177         this.comparator = new BGPObjectComparator(localAs);
178         this.bgpIdentifier = Preconditions.checkNotNull(localBgpId);
179         this.clusterId = (clusterId == null) ? new ClusterIdentifier(localBgpId) : new ClusterIdentifier(clusterId);
180         this.dispatcher = Preconditions.checkNotNull(dispatcher);
181         this.sessionStrategyFactory = Preconditions.checkNotNull(sessionStrategyFactory);
182         this.tcpStrategyFactory = Preconditions.checkNotNull(tcpStrategyFactory);
183         this.localTables = ImmutableSet.copyOf(localTables);
184         this.tables = new RIBTables(extensions);
185         this.peers = new LinkedBlockingQueue<>();
186         this.dataBroker = dps;
187         this.domDataBroker = Preconditions.checkNotNull(domDataBroker);
188         this.extensions = Preconditions.checkNotNull(extensions);
189         this.ribContextRegistry = RIBSupportContextRegistryImpl.create(extensions, codecFactory, classStrategy);
190         this.yangRibId = YangInstanceIdentifier.builder().node(BgpRib.QNAME).node(Rib.QNAME).nodeWithKey(Rib.QNAME, RIB_ID_QNAME, ribId.getValue()).build();
191
192         LOG.debug("Instantiating RIB table {} at {}", ribId, getInstanceIdentifier());
193
194         final WriteTransaction trans = this.chain.newWriteOnlyTransaction();
195
196         // put empty BgpRib if not exists
197         trans.put(LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier(),
198             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(
199             new LocRibBuilder().setTables(Collections.<Tables> emptyList()).build()).build(), true);
200
201         for (final BgpTableType t : localTables) {
202             final TablesKey key = new TablesKey(t.getAfi(), t.getSafi());
203             if (this.tables.create(trans, this, key) == null) {
204                 LOG.debug("Did not create local table for unhandled table type {}", t);
205             }
206         }
207
208         Futures.addCallback(trans.submit(), new FutureCallback<Void>() {
209             @Override
210             public void onSuccess(final Void result) {
211                 LOG.trace("Change committed successfully");
212             }
213
214             @Override
215             public void onFailure(final Throwable t) {
216                 LOG.error("Failed to initiate RIB {}", getInstanceIdentifier(), t);
217             }
218
219         });
220
221         final PolicyDatabase pd  = new PolicyDatabase(localAs.getValue(), localBgpId, this.clusterId);
222
223         final DOMDataBrokerExtension service = this.domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class);
224         final DOMTransactionChain domChain = this.createPeerChain(this);
225         this.efWriter = EffectiveRibInWriter.create((DOMDataTreeChangeService) service, domChain, getYangRibId(), pd, this.ribContextRegistry);
226         LOG.debug("Effective RIB created.");
227
228         for (final BgpTableType t : localTables) {
229             final TablesKey key = new TablesKey(t.getAfi(), t.getSafi());
230             // create locRibWriter for each table
231             // FIXME: temporary create writer only for Ipv4
232             if (key.getAfi().equals(Ipv4AddressFamily.class)) {
233                 LocRibWriter.create(this.ribContextRegistry.getRIBSupportContext(key).getRibSupport(), key, domChain, getYangRibId(), localAs, (DOMDataTreeChangeService) service, pd);
234             }
235         }
236     }
237
238     @Deprecated
239     synchronized void initTables(final byte[] remoteBgpId) {
240     }
241
242     @Override
243     @Deprecated
244     public synchronized void updateTables(final Peer peer, final Update message) {
245         final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(this.ribOuts, this.comparator, this.chain.newWriteOnlyTransaction());
246
247         if (!EOR.equals(message)) {
248             final WithdrawnRoutes wr = message.getWithdrawnRoutes();
249             if (wr != null) {
250                 final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
251                 if (ari != null) {
252                     /*
253                      * create MPUnreach for the routes to be handled in the same way as linkstate routes
254                      */
255                     final List<Ipv4Prefixes> prefixes = new ArrayList<>();
256                     for (final Ipv4Prefix p : wr.getWithdrawnRoutes()) {
257                         prefixes.add(new Ipv4PrefixesBuilder().setPrefix(p).build());
258                     }
259                     ari.removeRoutes(
260                         trans,
261                         peer,
262                         new MpUnreachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).setWithdrawnRoutes(
263                             new WithdrawnRoutesBuilder().setDestinationType(
264                                 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(
265                                     new DestinationIpv4Builder().setIpv4Prefixes(prefixes).build()).build()).build()).build());
266                 } else {
267                     LOG.debug("Not removing objects from unhandled IPv4 Unicast");
268                 }
269             }
270
271             final PathAttributes attrs = message.getPathAttributes();
272             if (attrs != null) {
273                 final PathAttributes2 mpu = attrs.getAugmentation(PathAttributes2.class);
274                 if (mpu != null) {
275                     final MpUnreachNlri nlri = mpu.getMpUnreachNlri();
276                     final AdjRIBsIn<?, ?> ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
277                     // EOR messages do not contain withdrawn routes
278                     if (nlri.getWithdrawnRoutes() != null) {
279                         if (ari != null) {
280                             ari.removeRoutes(trans, peer, nlri);
281                         } else {
282                             LOG.debug("Not removing objects from unhandled NLRI {}", nlri);
283                         }
284                     } else {
285                         ari.markUptodate(trans, peer);
286                     }
287                 }
288             }
289
290             final Nlri ar = message.getNlri();
291             if (ar != null) {
292                 final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
293                 if (ari != null) {
294                     /*
295                      * create MPReach for the routes to be handled in the same way as linkstate routes
296                      */
297                     final List<Ipv4Prefixes> prefixes = new ArrayList<>();
298                     for (final Ipv4Prefix p : ar.getNlri()) {
299                         prefixes.add(new Ipv4PrefixesBuilder().setPrefix(p).build());
300                     }
301                     final MpReachNlriBuilder b = new MpReachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(
302                         UnicastSubsequentAddressFamily.class).setAdvertizedRoutes(
303                             new AdvertizedRoutesBuilder().setDestinationType(
304                                 new DestinationIpv4CaseBuilder().setDestinationIpv4(
305                                     new DestinationIpv4Builder().setIpv4Prefixes(prefixes).build()).build()).build());
306                     if (attrs != null) {
307                         b.setCNextHop(attrs.getCNextHop());
308                     }
309
310                     ari.addRoutes(trans, peer, b.build(), attrs);
311                 } else {
312                     LOG.debug("Not adding objects from unhandled IPv4 Unicast");
313                 }
314             }
315
316             if (attrs != null) {
317                 final PathAttributes1 mpr = attrs.getAugmentation(PathAttributes1.class);
318                 if (mpr != null) {
319                     final MpReachNlri nlri = mpr.getMpReachNlri();
320
321                     final AdjRIBsIn<?, ?> ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
322                     if (ari != null) {
323                         if (message.equals(ari.endOfRib())) {
324                             ari.markUptodate(trans, peer);
325                         } else {
326                             ari.addRoutes(trans, peer, nlri, attrs);
327                         }
328                     } else {
329                         LOG.debug("Not adding objects from unhandled NLRI {}", nlri);
330                     }
331                 }
332             }
333         } else {
334             final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
335             if (ari != null) {
336                 ari.markUptodate(trans, peer);
337             } else {
338                 LOG.debug("End-of-RIB for IPv4 Unicast ignored");
339             }
340         }
341
342         Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
343             @Override
344             public void onSuccess(final Void result) {
345                 LOG.debug("RIB modification successfully committed.");
346             }
347
348             @Override
349             public void onFailure(final Throwable t) {
350                 LOG.error("Failed to commit RIB modification", t);
351             }
352         });
353     }
354
355     @Deprecated
356     @Override
357     public synchronized void clearTable(final Peer peer, final TablesKey key) {
358         final AdjRIBsIn<?, ?> ari = this.tables.get(key);
359         if (ari != null) {
360             final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(this.ribOuts, this.comparator, this.chain.newWriteOnlyTransaction());
361             ari.clear(trans, peer);
362
363             Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
364                 @Override
365                 public void onSuccess(final Void result) {
366                     LOG.trace("Table {} cleared successfully", key);
367                 }
368
369                 @Override
370                 public void onFailure(final Throwable t) {
371                     LOG.error("Failed to clear table {}", key, t);
372                 }
373             });
374         }
375     }
376
377     @Override
378     public String toString() {
379         return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
380     }
381
382     protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
383         return toStringHelper;
384     }
385
386     @SuppressWarnings("unchecked")
387     @Deprecated
388     protected <K, V extends Route> AdjRIBsIn<K, V> getTable(final TablesKey key) {
389         return (AdjRIBsIn<K, V>) this.tables.get(key);
390     }
391
392     @Override
393     public synchronized void close() throws InterruptedException, ExecutionException {
394         final WriteTransaction t = this.chain.newWriteOnlyTransaction();
395         t.delete(LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier());
396         t.submit().get();
397         this.chain.close();
398     }
399
400     @Override
401     public AsNumber getLocalAs() {
402         return this.localAs;
403     }
404
405     @Override
406     public Ipv4Address getBgpIdentifier() {
407         return this.bgpIdentifier;
408     }
409
410     @Override
411     public Set<? extends BgpTableType> getLocalTables() {
412         return this.localTables;
413     }
414
415     @Override
416     public ReconnectStrategyFactory getTcpStrategyFactory() {
417         return this.tcpStrategyFactory;
418     }
419
420     @Override
421     public ReconnectStrategyFactory getSessionStrategyFactory() {
422         return this.sessionStrategyFactory;
423     }
424
425     @Override
426     public BGPDispatcher getDispatcher() {
427         return this.dispatcher;
428     }
429
430     @Deprecated
431     @Override
432     public void initTable(final Peer bgpPeer, final TablesKey key) {
433         // FIXME: BUG-196: support graceful restart
434     }
435
436     @Override
437     public AdjRIBsOutRegistration registerRIBsOut(final Peer peer, final AdjRIBsOut aro) {
438         final AdjRIBsOutRegistration reg = new AdjRIBsOutRegistration(aro) {
439             @Override
440             protected void removeRegistration() {
441                 RIBImpl.this.ribOuts.remove(peer, aro);
442             }
443         };
444
445         this.ribOuts.put(peer, aro);
446         LOG.debug("Registering this peer {} to RIB-Out {}", peer, this.ribOuts);
447         try {
448             this.peers.put(peer);
449             new Thread(this.scheduler).start();
450         } catch (final InterruptedException e) {
451             //
452         }
453         return reg;
454     }
455
456     @Override
457     public void onTransactionChainFailed(final TransactionChain<?, ?> chain, final AsyncTransaction<?, ?> transaction, final Throwable cause) {
458         LOG.error("Broken chain in RIB {} transaction {}", getInstanceIdentifier(), transaction.getIdentifier(), cause);
459     }
460
461     @Override
462     public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
463         LOG.info("RIB {} closed successfully", getInstanceIdentifier());
464     }
465
466     @Override
467     public long getRoutesCount(final TablesKey key) {
468         try {
469             final Optional<Tables> tableMaybe = this.dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
470                     getInstanceIdentifier().child(LocRib.class).child(Tables.class, key)).checkedGet();
471             if (tableMaybe.isPresent()) {
472                 final Tables table = tableMaybe.get();
473                 if (table.getRoutes() instanceof Ipv4RoutesCase) {
474                     final Ipv4RoutesCase routesCase = (Ipv4RoutesCase) table.getRoutes();
475                     if (routesCase.getIpv4Routes() != null && routesCase.getIpv4Routes().getIpv4Route() != null) {
476                         return routesCase.getIpv4Routes().getIpv4Route().size();
477                     }
478                 } else if (table.getRoutes() instanceof Ipv6RoutesCase) {
479                     final Ipv6RoutesCase routesCase = (Ipv6RoutesCase) table.getRoutes();
480                     if (routesCase.getIpv6Routes() != null && routesCase.getIpv6Routes().getIpv6Route() != null) {
481                         return routesCase.getIpv6Routes().getIpv6Route().size();
482                     }
483                 }
484             }
485         } catch (final ReadFailedException e) {
486             //no-op
487         }
488         return 0;
489     }
490
491     @Override
492     public YangInstanceIdentifier getYangRibId() {
493         return this.yangRibId;
494     }
495
496     @Override
497     public DOMTransactionChain createPeerChain(final TransactionChainListener listener) {
498         return this.domDataBroker.createTransactionChain(listener);
499     }
500
501     @Override
502     public RIBExtensionConsumerContext getRibExtensions() {
503         return this.extensions;
504     }
505
506     @Override
507     public RIBSupportContextRegistry getRibSupportContext() {
508         return this.ribContextRegistry;
509     }
510
511     @Override
512     public void onGlobalContextUpdated(final SchemaContext context) {
513         this.ribContextRegistry.onSchemaContextUpdated(context);
514     }
515 }