Merge "BUG-2982 : moved path-attributes container to grouping"
[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.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.path.attributes.Attributes;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.Nlri;
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.Attributes1;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.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, this.createPeerChain(this), 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             LocRibWriter.create(this.ribContextRegistry, key, this.createPeerChain(this), getYangRibId(), localAs, (DOMDataTreeChangeService) service, pd);
232         }
233     }
234
235     @Deprecated
236     synchronized void initTables(final byte[] remoteBgpId) {
237     }
238
239     @Override
240     @Deprecated
241     public synchronized void updateTables(final Peer peer, final Update message) {
242         final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(this.ribOuts, this.comparator, this.chain.newWriteOnlyTransaction());
243
244         if (!EOR.equals(message)) {
245             final WithdrawnRoutes wr = message.getWithdrawnRoutes();
246             if (wr != null) {
247                 final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
248                 if (ari != null) {
249                     /*
250                      * create MPUnreach for the routes to be handled in the same way as linkstate routes
251                      */
252                     final List<Ipv4Prefixes> prefixes = new ArrayList<>();
253                     for (final Ipv4Prefix p : wr.getWithdrawnRoutes()) {
254                         prefixes.add(new Ipv4PrefixesBuilder().setPrefix(p).build());
255                     }
256                     ari.removeRoutes(
257                         trans,
258                         peer,
259                         new MpUnreachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).setWithdrawnRoutes(
260                             new WithdrawnRoutesBuilder().setDestinationType(
261                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationIpv4CaseBuilder().setDestinationIpv4(
262                                     new DestinationIpv4Builder().setIpv4Prefixes(prefixes).build()).build()).build()).build());
263                 } else {
264                     LOG.debug("Not removing objects from unhandled IPv4 Unicast");
265                 }
266             }
267
268             final Attributes attrs = message.getAttributes();
269             if (attrs != null) {
270                 final Attributes2 mpu = attrs.getAugmentation(Attributes2.class);
271                 if (mpu != null) {
272                     final MpUnreachNlri nlri = mpu.getMpUnreachNlri();
273                     final AdjRIBsIn<?, ?> ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
274                     // EOR messages do not contain withdrawn routes
275                     if (nlri.getWithdrawnRoutes() != null) {
276                         if (ari != null) {
277                             ari.removeRoutes(trans, peer, nlri);
278                         } else {
279                             LOG.debug("Not removing objects from unhandled NLRI {}", nlri);
280                         }
281                     } else {
282                         ari.markUptodate(trans, peer);
283                     }
284                 }
285             }
286
287             final Nlri ar = message.getNlri();
288             if (ar != null) {
289                 final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
290                 if (ari != null) {
291                     /*
292                      * create MPReach for the routes to be handled in the same way as linkstate routes
293                      */
294                     final List<Ipv4Prefixes> prefixes = new ArrayList<>();
295                     for (final Ipv4Prefix p : ar.getNlri()) {
296                         prefixes.add(new Ipv4PrefixesBuilder().setPrefix(p).build());
297                     }
298                     final MpReachNlriBuilder b = new MpReachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(
299                         UnicastSubsequentAddressFamily.class).setAdvertizedRoutes(
300                             new AdvertizedRoutesBuilder().setDestinationType(
301                                 new DestinationIpv4CaseBuilder().setDestinationIpv4(
302                                     new DestinationIpv4Builder().setIpv4Prefixes(prefixes).build()).build()).build());
303                     if (attrs != null) {
304                         b.setCNextHop(attrs.getCNextHop());
305                     }
306
307                     ari.addRoutes(trans, peer, b.build(), attrs);
308                 } else {
309                     LOG.debug("Not adding objects from unhandled IPv4 Unicast");
310                 }
311             }
312
313             if (attrs != null) {
314                 final Attributes1 mpr = attrs.getAugmentation(Attributes1.class);
315                 if (mpr != null) {
316                     final MpReachNlri nlri = mpr.getMpReachNlri();
317
318                     final AdjRIBsIn<?, ?> ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
319                     if (ari != null) {
320                         if (message.equals(ari.endOfRib())) {
321                             ari.markUptodate(trans, peer);
322                         } else {
323                             ari.addRoutes(trans, peer, nlri, attrs);
324                         }
325                     } else {
326                         LOG.debug("Not adding objects from unhandled NLRI {}", nlri);
327                     }
328                 }
329             }
330         } else {
331             final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
332             if (ari != null) {
333                 ari.markUptodate(trans, peer);
334             } else {
335                 LOG.debug("End-of-RIB for IPv4 Unicast ignored");
336             }
337         }
338
339         Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
340             @Override
341             public void onSuccess(final Void result) {
342                 LOG.debug("RIB modification successfully committed.");
343             }
344
345             @Override
346             public void onFailure(final Throwable t) {
347                 LOG.error("Failed to commit RIB modification", t);
348             }
349         });
350     }
351
352     @Deprecated
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     @Deprecated
385     protected <K, V extends Route> AdjRIBsIn<K, V> getTable(final TablesKey key) {
386         return (AdjRIBsIn<K, V>) this.tables.get(key);
387     }
388
389     @Override
390     public synchronized void close() throws InterruptedException, ExecutionException {
391         final WriteTransaction t = this.chain.newWriteOnlyTransaction();
392         t.delete(LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier());
393         t.submit().get();
394         this.chain.close();
395     }
396
397     @Override
398     public AsNumber getLocalAs() {
399         return this.localAs;
400     }
401
402     @Override
403     public Ipv4Address getBgpIdentifier() {
404         return this.bgpIdentifier;
405     }
406
407     @Override
408     public Set<? extends BgpTableType> getLocalTables() {
409         return this.localTables;
410     }
411
412     @Override
413     public ReconnectStrategyFactory getTcpStrategyFactory() {
414         return this.tcpStrategyFactory;
415     }
416
417     @Override
418     public ReconnectStrategyFactory getSessionStrategyFactory() {
419         return this.sessionStrategyFactory;
420     }
421
422     @Override
423     public BGPDispatcher getDispatcher() {
424         return this.dispatcher;
425     }
426
427     @Deprecated
428     @Override
429     public void initTable(final Peer bgpPeer, final TablesKey key) {
430         // FIXME: BUG-196: support graceful restart
431     }
432
433     @Override
434     public AdjRIBsOutRegistration registerRIBsOut(final Peer peer, final AdjRIBsOut aro) {
435         final AdjRIBsOutRegistration reg = new AdjRIBsOutRegistration(aro) {
436             @Override
437             protected void removeRegistration() {
438                 RIBImpl.this.ribOuts.remove(peer, aro);
439             }
440         };
441
442         this.ribOuts.put(peer, aro);
443         LOG.debug("Registering this peer {} to RIB-Out {}", peer, this.ribOuts);
444         try {
445             this.peers.put(peer);
446             new Thread(this.scheduler).start();
447         } catch (final InterruptedException e) {
448             //
449         }
450         return reg;
451     }
452
453     @Override
454     public void onTransactionChainFailed(final TransactionChain<?, ?> chain, final AsyncTransaction<?, ?> transaction, final Throwable cause) {
455         LOG.error("Broken chain in RIB {} transaction {}", getInstanceIdentifier(), transaction.getIdentifier(), cause);
456     }
457
458     @Override
459     public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
460         LOG.info("RIB {} closed successfully", getInstanceIdentifier());
461     }
462
463     @Override
464     public long getRoutesCount(final TablesKey key) {
465         try {
466             final Optional<Tables> tableMaybe = this.dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
467                     getInstanceIdentifier().child(LocRib.class).child(Tables.class, key)).checkedGet();
468             if (tableMaybe.isPresent()) {
469                 final Tables table = tableMaybe.get();
470                 if (table.getRoutes() instanceof Ipv4RoutesCase) {
471                     final Ipv4RoutesCase routesCase = (Ipv4RoutesCase) table.getRoutes();
472                     if (routesCase.getIpv4Routes() != null && routesCase.getIpv4Routes().getIpv4Route() != null) {
473                         return routesCase.getIpv4Routes().getIpv4Route().size();
474                     }
475                 } else if (table.getRoutes() instanceof Ipv6RoutesCase) {
476                     final Ipv6RoutesCase routesCase = (Ipv6RoutesCase) table.getRoutes();
477                     if (routesCase.getIpv6Routes() != null && routesCase.getIpv6Routes().getIpv6Route() != null) {
478                         return routesCase.getIpv6Routes().getIpv6Route().size();
479                     }
480                 }
481             }
482         } catch (final ReadFailedException e) {
483             //no-op
484         }
485         return 0;
486     }
487
488     @Override
489     public YangInstanceIdentifier getYangRibId() {
490         return this.yangRibId;
491     }
492
493     @Override
494     public DOMTransactionChain createPeerChain(final TransactionChainListener listener) {
495         return this.domDataBroker.createTransactionChain(listener);
496     }
497
498     @Override
499     public RIBExtensionConsumerContext getRibExtensions() {
500         return this.extensions;
501     }
502
503     @Override
504     public RIBSupportContextRegistry getRibSupportContext() {
505         return this.ribContextRegistry;
506     }
507
508     @Override
509     public void onGlobalContextUpdated(final SchemaContext context) {
510         this.ribContextRegistry.onSchemaContextUpdated(context);
511     }
512 }