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