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