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.binding.api.ReadOnlyTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
26 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
27 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
28 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
29 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
30 import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
31 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
32 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
33 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
34 import org.opendaylight.protocol.bgp.rib.DefaultRibReference;
35 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
36 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
37 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
38 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
39 import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
40 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv4RoutesCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv6RoutesCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.BgpRib;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRib;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
55 import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory;
56 import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
57 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
58 import org.opendaylight.yangtools.yang.common.QName;
59 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
60 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
61 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
62 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
63 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
64 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
65 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
66 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
67 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
68 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
69 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
70 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
75 public final class RIBImpl extends DefaultRibReference implements AutoCloseable, RIB, TransactionChainListener, SchemaContextListener {
76 private static final Logger LOG = LoggerFactory.getLogger(RIBImpl.class);
77 private static final QName RIB_ID_QNAME = QName.cachedReference(QName.create(Rib.QNAME, "id"));
78 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);
80 private final ReconnectStrategyFactory tcpStrategyFactory;
81 private final ReconnectStrategyFactory sessionStrategyFactory;
83 private final BGPDispatcher dispatcher;
84 private final DOMTransactionChain domChain;
85 private final AsNumber localAs;
86 private final Ipv4Address bgpIdentifier;
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.dispatcher = Preconditions.checkNotNull(dispatcher);
105 this.sessionStrategyFactory = Preconditions.checkNotNull(sessionStrategyFactory);
106 this.tcpStrategyFactory = Preconditions.checkNotNull(tcpStrategyFactory);
107 this.localTables = ImmutableSet.copyOf(localTables);
108 this.localTablesKeys = new HashSet<TablesKey>();
109 this.dataBroker = dps;
110 this.domDataBroker = Preconditions.checkNotNull(domDataBroker);
111 this.extensions = Preconditions.checkNotNull(extensions);
112 this.ribContextRegistry = RIBSupportContextRegistryImpl.create(extensions, codecFactory, classStrategy);
113 this.yangRibId = YangInstanceIdentifier.builder().node(BgpRib.QNAME).node(Rib.QNAME).nodeWithKey(Rib.QNAME, RIB_ID_QNAME, ribId.getValue()).build();
115 LOG.debug("Instantiating RIB table {} at {}", ribId, this.yangRibId);
117 final ContainerNode rib = Builders.containerBuilder()
118 .withNodeIdentifier(new NodeIdentifier(BgpRib.QNAME))
119 .addChild(ImmutableNodes.mapNodeBuilder(Rib.QNAME)
120 .addChild(ImmutableNodes.mapEntryBuilder(Rib.QNAME, RIB_ID_QNAME, ribId.getValue())
121 .addChild(ImmutableNodes.leafNode(RIB_ID_QNAME, ribId.getValue()))
122 .addChild(ImmutableNodes.mapNodeBuilder(Peer.QNAME).build())
123 .addChild(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(LocRib.QNAME))
124 .addChild(ImmutableNodes.mapNodeBuilder(Tables.QNAME).build())
131 final DOMDataWriteTransaction trans = this.domChain.newWriteOnlyTransaction();
133 // put empty BgpRib if not exists
134 trans.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().node(BgpRib.QNAME).build(), rib);
137 trans.submit().checkedGet();
138 } catch (final TransactionCommitFailedException e) {
139 LOG.error("Failed to initiate RIB {}", this.yangRibId, e);
141 final ClusterIdentifier cId = (clusterId == null) ? new ClusterIdentifier(localBgpId) : new ClusterIdentifier(clusterId);
142 final PolicyDatabase pd = new PolicyDatabase(localAs.getValue(), localBgpId, cId);
144 final DOMDataBrokerExtension domDatatreeChangeService = this.domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class);
145 this.service = domDatatreeChangeService;
146 this.efWriter = EffectiveRibInWriter.create(getService(), this.createPeerChain(this), getYangRibId(), pd, this.ribContextRegistry);
147 LOG.debug("Effective RIB created.");
149 for (final BgpTableType t : this.localTables) {
150 final TablesKey key = new TablesKey(t.getAfi(), t.getSafi());
151 this.localTablesKeys.add(key);
152 startLocRib(key, pd);
156 private void startLocRib(final TablesKey key, final PolicyDatabase pd) {
157 LOG.debug("Creating LocRib table for {}", key);
158 // create locRibWriter for each table
159 final DOMDataWriteTransaction tx = this.domChain.newWriteOnlyTransaction();
161 final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> table = ImmutableNodes.mapEntryBuilder();
162 table.withNodeIdentifier(RibSupportUtils.toYangTablesKey(key));
163 table.withChild(EMPTY_TABLE_ATTRIBUTES);
165 final NodeIdentifierWithPredicates tableKey = RibSupportUtils.toYangTablesKey(key);
166 final InstanceIdentifierBuilder tableId = YangInstanceIdentifier.builder(this.yangRibId.node(LocRib.QNAME).node(Tables.QNAME));
167 tableId.nodeWithKey(tableKey.getNodeType(), tableKey.getKeyValues());
168 for (final Entry<QName, Object> e : tableKey.getKeyValues().entrySet()) {
169 table.withChild(ImmutableNodes.leafNode(e.getKey(), e.getValue()));
172 final ChoiceNode routes = this.ribContextRegistry.getRIBSupportContext(key).getRibSupport().emptyRoutes();
173 table.withChild(routes);
175 tx.put(LogicalDatastoreType.OPERATIONAL, tableId.build(), table.build());
177 tx.submit().checkedGet();
178 } catch (final TransactionCommitFailedException e1) {
179 LOG.error("Failed to initiate LocRIB for key {}", key, e1);
181 LocRibWriter.create(this.ribContextRegistry, key, this.createPeerChain(this), getYangRibId(), this.localAs, getService(), pd);
185 public String toString() {
186 return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
189 protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
190 return toStringHelper;
194 public synchronized void close() throws InterruptedException, ExecutionException {
195 final DOMDataWriteTransaction t = this.domChain.newWriteOnlyTransaction();
196 t.delete(LogicalDatastoreType.OPERATIONAL, getYangRibId());
198 this.domChain.close();
199 this.efWriter.close();
203 public AsNumber getLocalAs() {
208 public Ipv4Address getBgpIdentifier() {
209 return this.bgpIdentifier;
213 public Set<? extends BgpTableType> getLocalTables() {
214 return this.localTables;
218 public ReconnectStrategyFactory getTcpStrategyFactory() {
219 return this.tcpStrategyFactory;
223 public ReconnectStrategyFactory getSessionStrategyFactory() {
224 return this.sessionStrategyFactory;
228 public BGPDispatcher getDispatcher() {
229 return this.dispatcher;
233 public void onTransactionChainFailed(final TransactionChain<?, ?> chain, final AsyncTransaction<?, ?> transaction, final Throwable cause) {
234 LOG.error("Broken chain in RIB {} transaction {}", getInstanceIdentifier(), transaction.getIdentifier(), cause);
238 public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
239 LOG.info("RIB {} closed successfully", getInstanceIdentifier());
243 public long getRoutesCount(final TablesKey key) {
244 try (final ReadOnlyTransaction tx = this.dataBroker.newReadOnlyTransaction()) {
245 final Optional<Tables> tableMaybe = tx.read(LogicalDatastoreType.OPERATIONAL,
246 getInstanceIdentifier().child(LocRib.class).child(Tables.class, key)).checkedGet();
247 if (tableMaybe.isPresent()) {
248 final Tables table = tableMaybe.get();
249 if (table.getRoutes() instanceof Ipv4RoutesCase) {
250 final Ipv4RoutesCase routesCase = (Ipv4RoutesCase) table.getRoutes();
251 if (routesCase.getIpv4Routes() != null && routesCase.getIpv4Routes().getIpv4Route() != null) {
252 return routesCase.getIpv4Routes().getIpv4Route().size();
254 } else if (table.getRoutes() instanceof Ipv6RoutesCase) {
255 final Ipv6RoutesCase routesCase = (Ipv6RoutesCase) table.getRoutes();
256 if (routesCase.getIpv6Routes() != null && routesCase.getIpv6Routes().getIpv6Route() != null) {
257 return routesCase.getIpv6Routes().getIpv6Route().size();
261 } catch (final ReadFailedException e) {
262 LOG.debug("Failed to read tables", e);
267 public Set<TablesKey> getLocalTablesKeys() {
268 return this.localTablesKeys;
271 public DOMDataTreeChangeService getService() {
272 return (DOMDataTreeChangeService) this.service;
276 public YangInstanceIdentifier getYangRibId() {
277 return this.yangRibId;
281 public DOMTransactionChain createPeerChain(final TransactionChainListener listener) {
282 return this.domDataBroker.createTransactionChain(listener);
286 public RIBExtensionConsumerContext getRibExtensions() {
287 return this.extensions;
291 public RIBSupportContextRegistry getRibSupportContext() {
292 return this.ribContextRegistry;
296 public void onGlobalContextUpdated(final SchemaContext context) {
297 this.ribContextRegistry.onSchemaContextUpdated(context);