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