2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.protocol.bgp.rib.impl;
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 java.util.HashSet;
16 import java.util.List;
17 import java.util.Map.Entry;
19 import java.util.concurrent.ExecutionException;
20 import javax.annotation.concurrent.ThreadSafe;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
25 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
26 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
27 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
28 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
29 import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
30 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
31 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
32 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
33 import org.opendaylight.protocol.bgp.rib.DefaultRibReference;
34 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
35 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
36 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
37 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
38 import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
39 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv4RoutesCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv6RoutesCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.BgpRib;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRib;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
54 import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory;
55 import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
56 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
57 import org.opendaylight.yangtools.yang.common.QName;
58 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
59 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
60 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
61 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
62 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
63 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
64 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
65 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
66 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
67 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
68 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
69 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
74 public final class RIBImpl extends DefaultRibReference implements AutoCloseable, RIB, TransactionChainListener, SchemaContextListener {
75 private static final Logger LOG = LoggerFactory.getLogger(RIBImpl.class);
76 private static final QName RIB_ID_QNAME = QName.cachedReference(QName.create(Rib.QNAME, "id"));
77 private static final ContainerNode EMPTY_TABLE_ATTRIBUTES = ImmutableNodes.containerNode(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Attributes.QNAME);
79 private final ReconnectStrategyFactory tcpStrategyFactory;
80 private final ReconnectStrategyFactory sessionStrategyFactory;
82 private final BGPDispatcher dispatcher;
83 private final DOMTransactionChain domChain;
84 private final AsNumber localAs;
85 private final Ipv4Address bgpIdentifier;
86 private final ClusterIdentifier clusterId;
87 private final Set<BgpTableType> localTables;
88 private final Set<TablesKey> localTablesKeys;
89 private final DataBroker dataBroker;
90 private final DOMDataBroker domDataBroker;
91 private final RIBExtensionConsumerContext extensions;
92 private final YangInstanceIdentifier yangRibId;
93 private final RIBSupportContextRegistryImpl ribContextRegistry;
94 private final EffectiveRibInWriter efWriter;
95 private final DOMDataBrokerExtension service;
97 public RIBImpl(final RibId ribId, final AsNumber localAs, final Ipv4Address localBgpId, final Ipv4Address clusterId, final RIBExtensionConsumerContext extensions,
98 final BGPDispatcher dispatcher, final ReconnectStrategyFactory tcpStrategyFactory, final BindingCodecTreeFactory codecFactory,
99 final ReconnectStrategyFactory sessionStrategyFactory, final DataBroker dps, final DOMDataBroker domDataBroker, final List<BgpTableType> localTables, final GeneratedClassLoadingStrategy classStrategy) {
100 super(InstanceIdentifier.create(BgpRib.class).child(Rib.class, new RibKey(Preconditions.checkNotNull(ribId))));
101 this.domChain = domDataBroker.createTransactionChain(this);
102 this.localAs = Preconditions.checkNotNull(localAs);
103 this.bgpIdentifier = Preconditions.checkNotNull(localBgpId);
104 this.clusterId = (clusterId == null) ? new ClusterIdentifier(localBgpId) : new ClusterIdentifier(clusterId);
105 this.dispatcher = Preconditions.checkNotNull(dispatcher);
106 this.sessionStrategyFactory = Preconditions.checkNotNull(sessionStrategyFactory);
107 this.tcpStrategyFactory = Preconditions.checkNotNull(tcpStrategyFactory);
108 this.localTables = ImmutableSet.copyOf(localTables);
109 this.localTablesKeys = new HashSet<TablesKey>();
110 this.dataBroker = dps;
111 this.domDataBroker = Preconditions.checkNotNull(domDataBroker);
112 this.extensions = Preconditions.checkNotNull(extensions);
113 this.ribContextRegistry = RIBSupportContextRegistryImpl.create(extensions, codecFactory, classStrategy);
114 this.yangRibId = YangInstanceIdentifier.builder().node(BgpRib.QNAME).node(Rib.QNAME).nodeWithKey(Rib.QNAME, RIB_ID_QNAME, ribId.getValue()).build();
116 LOG.debug("Instantiating RIB table {} at {}", ribId, this.yangRibId);
118 final ContainerNode rib = Builders.containerBuilder()
119 .withNodeIdentifier(new NodeIdentifier(BgpRib.QNAME))
120 .addChild(ImmutableNodes.mapNodeBuilder(Rib.QNAME)
121 .addChild(ImmutableNodes.mapEntryBuilder(Rib.QNAME, RIB_ID_QNAME, ribId.getValue())
122 .addChild(ImmutableNodes.leafNode(RIB_ID_QNAME, ribId.getValue()))
123 .addChild(ImmutableNodes.mapNodeBuilder(Peer.QNAME).build())
124 .addChild(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(LocRib.QNAME))
125 .addChild(ImmutableNodes.mapNodeBuilder(Tables.QNAME).build())
132 final DOMDataWriteTransaction trans = this.domChain.newWriteOnlyTransaction();
134 // put empty BgpRib if not exists
135 trans.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().node(BgpRib.QNAME).build(), rib);
138 trans.submit().checkedGet();
139 } catch (final TransactionCommitFailedException e) {
140 LOG.error("Failed to initiate RIB {}", this.yangRibId);
143 final PolicyDatabase pd = new PolicyDatabase(localAs.getValue(), localBgpId, this.clusterId);
145 final DOMDataBrokerExtension service = this.domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class);
146 this.service = service;
147 this.efWriter = EffectiveRibInWriter.create(getService(), this.createPeerChain(this), getYangRibId(), pd, this.ribContextRegistry);
148 LOG.debug("Effective RIB created.");
150 for (final BgpTableType t : this.localTables) {
151 final TablesKey key = new TablesKey(t.getAfi(), t.getSafi());
152 this.localTablesKeys.add(key);
153 startLocRib(key, pd);
157 private void startLocRib(final TablesKey key, final PolicyDatabase pd) {
158 LOG.debug("Creating LocRib table for {}", key);
159 // create locRibWriter for each table
160 final DOMDataWriteTransaction tx = this.domChain.newWriteOnlyTransaction();
162 final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> table = ImmutableNodes.mapEntryBuilder();
163 table.withNodeIdentifier(RibSupportUtils.toYangTablesKey(key));
164 table.withChild(EMPTY_TABLE_ATTRIBUTES);
166 final NodeIdentifierWithPredicates tableKey = RibSupportUtils.toYangTablesKey(key);
167 final InstanceIdentifierBuilder tableId = YangInstanceIdentifier.builder(this.yangRibId.node(LocRib.QNAME).node(Tables.QNAME));
168 tableId.nodeWithKey(tableKey.getNodeType(), tableKey.getKeyValues());
169 for (final Entry<QName, Object> e : tableKey.getKeyValues().entrySet()) {
170 table.withChild(ImmutableNodes.leafNode(e.getKey(), e.getValue()));
173 final ChoiceNode routes = this.ribContextRegistry.getRIBSupportContext(key).getRibSupport().emptyRoutes();
174 table.withChild(routes);
176 tx.put(LogicalDatastoreType.OPERATIONAL, tableId.build(), table.build());
178 tx.submit().checkedGet();
179 } catch (final TransactionCommitFailedException e1) {
180 LOG.error("Failed to initiate LocRIB for key {}", key, e1);
182 LocRibWriter.create(this.ribContextRegistry, key, this.createPeerChain(this), getYangRibId(), this.localAs, getService(), pd);
186 public String toString() {
187 return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
190 protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
191 return toStringHelper;
195 public synchronized void close() throws InterruptedException, ExecutionException {
196 final DOMDataWriteTransaction t = this.domChain.newWriteOnlyTransaction();
197 t.delete(LogicalDatastoreType.OPERATIONAL, getYangRibId());
199 this.domChain.close();
200 this.efWriter.close();
204 public AsNumber getLocalAs() {
209 public Ipv4Address getBgpIdentifier() {
210 return this.bgpIdentifier;
214 public Set<? extends BgpTableType> getLocalTables() {
215 return this.localTables;
219 public ReconnectStrategyFactory getTcpStrategyFactory() {
220 return this.tcpStrategyFactory;
224 public ReconnectStrategyFactory getSessionStrategyFactory() {
225 return this.sessionStrategyFactory;
229 public BGPDispatcher getDispatcher() {
230 return this.dispatcher;
234 public void onTransactionChainFailed(final TransactionChain<?, ?> chain, final AsyncTransaction<?, ?> transaction, final Throwable cause) {
235 LOG.error("Broken chain in RIB {} transaction {}", getInstanceIdentifier(), transaction.getIdentifier(), cause);
239 public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
240 LOG.info("RIB {} closed successfully", getInstanceIdentifier());
244 public long getRoutesCount(final TablesKey key) {
246 final Optional<Tables> tableMaybe = this.dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
247 getInstanceIdentifier().child(LocRib.class).child(Tables.class, key)).checkedGet();
248 if (tableMaybe.isPresent()) {
249 final Tables table = tableMaybe.get();
250 if (table.getRoutes() instanceof Ipv4RoutesCase) {
251 final Ipv4RoutesCase routesCase = (Ipv4RoutesCase) table.getRoutes();
252 if (routesCase.getIpv4Routes() != null && routesCase.getIpv4Routes().getIpv4Route() != null) {
253 return routesCase.getIpv4Routes().getIpv4Route().size();
255 } else if (table.getRoutes() instanceof Ipv6RoutesCase) {
256 final Ipv6RoutesCase routesCase = (Ipv6RoutesCase) table.getRoutes();
257 if (routesCase.getIpv6Routes() != null && routesCase.getIpv6Routes().getIpv6Route() != null) {
258 return routesCase.getIpv6Routes().getIpv6Route().size();
262 } catch (final ReadFailedException e) {
268 public Set<TablesKey> getLocalTablesKeys() {
269 return this.localTablesKeys;
272 public DOMDataTreeChangeService getService() {
273 return (DOMDataTreeChangeService) this.service;
277 public YangInstanceIdentifier getYangRibId() {
278 return this.yangRibId;
282 public DOMTransactionChain createPeerChain(final TransactionChainListener listener) {
283 return this.domDataBroker.createTransactionChain(listener);
287 public RIBExtensionConsumerContext getRibExtensions() {
288 return this.extensions;
292 public RIBSupportContextRegistry getRibSupportContext() {
293 return this.ribContextRegistry;
297 public void onGlobalContextUpdated(final SchemaContext context) {
298 this.ribContextRegistry.onSchemaContextUpdated(context);