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