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