f6eccdc545b6922c5e033965b95fb4fc5b0d9b7f
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / config / RibImpl.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.protocol.bgp.rib.impl.config;
10
11 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getAfiSafiWithDefault;
12 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getClusterIdentifier;
13 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.toTableTypes;
14
15 import com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Optional;
21 import java.util.Set;
22 import java.util.stream.Collectors;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
24 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
25 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
26 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
27 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeFactory;
28 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
29 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
30 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
31 import org.opendaylight.protocol.bgp.rib.impl.BGPPeerTrackerImpl;
32 import org.opendaylight.protocol.bgp.rib.impl.CodecsRegistryImpl;
33 import org.opendaylight.protocol.bgp.rib.impl.RIBImpl;
34 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
35 import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry;
36 import org.opendaylight.protocol.bgp.rib.impl.spi.ImportPolicyPeerTracker;
37 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
38 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
39 import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
40 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
41 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
42 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
43 import org.opendaylight.protocol.bgp.rib.spi.state.BGPRIBState;
44 import org.opendaylight.protocol.bgp.rib.spi.state.BGPRIBStateConsumer;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
46 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base.Config;
47 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.Attributes;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.BgpTableType;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.RibId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.bgp.rib.Rib;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.bgp.rib.RibKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
58 import org.opendaylight.yangtools.concepts.ListenerRegistration;
59 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
60 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
61 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
62 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
63 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
64 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
65 import org.osgi.framework.ServiceRegistration;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68
69 public final class RibImpl implements RIB, BGPRIBStateConsumer, AutoCloseable {
70
71     private static final Logger LOG = LoggerFactory.getLogger(RibImpl.class);
72
73     private final RIBExtensionConsumerContext extensions;
74     private final BGPDispatcher dispatcher;
75     private final BindingCodecTreeFactory codecTreeFactory;
76     private final DOMDataBroker domBroker;
77     private final DOMSchemaService domSchemaService;
78     private RIBImpl ribImpl;
79     private ServiceRegistration<?> serviceRegistration;
80     private ListenerRegistration<SchemaContextListener> schemaContextRegistration;
81     private List<AfiSafi> afiSafi;
82     private AsNumber asNumber;
83     private Ipv4Address routerId;
84
85     private ClusterIdentifier clusterId;
86
87     public RibImpl(final RIBExtensionConsumerContext contextProvider, final BGPDispatcher dispatcher,
88             final BindingCodecTreeFactory codecTreeFactory, final DOMDataBroker domBroker,
89             final DOMSchemaService domSchemaService) {
90         this.extensions = contextProvider;
91         this.dispatcher = dispatcher;
92         this.codecTreeFactory = codecTreeFactory;
93         this.domBroker = domBroker;
94         this.domSchemaService = domSchemaService;
95     }
96
97     void start(final Global global, final String instanceName, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
98         Preconditions.checkState(this.ribImpl == null,
99                 "Previous instance %s was not closed.", this);
100         this.ribImpl = createRib(global, instanceName, tableTypeRegistry);
101         this.schemaContextRegistration = this.domSchemaService.registerSchemaContextListener(this.ribImpl);
102     }
103
104     Boolean isGlobalEqual(final Global global) {
105         final List<AfiSafi> globalAfiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true);
106         final Config globalConfig = global.getConfig();
107         final AsNumber globalAs = globalConfig.getAs();
108         final Ipv4Address globalRouterId = global.getConfig().getRouterId();
109         final ClusterIdentifier globalClusterId = getClusterIdentifier(globalConfig);
110         return this.afiSafi.containsAll(globalAfiSafi) && globalAfiSafi.containsAll(this.afiSafi)
111                 && globalAs.equals(this.asNumber)
112                 && globalRouterId.getValue().equals(this.routerId.getValue())
113                 && globalClusterId.getValue().equals(this.clusterId.getValue());
114     }
115
116     @Override
117     public KeyedInstanceIdentifier<Rib, RibKey> getInstanceIdentifier() {
118         return this.ribImpl.getInstanceIdentifier();
119     }
120
121     @Override
122     public AsNumber getLocalAs() {
123         return this.ribImpl.getLocalAs();
124     }
125
126     @Override
127     public BgpId getBgpIdentifier() {
128         return this.ribImpl.getBgpIdentifier();
129     }
130
131     @Override
132     public Set<? extends BgpTableType> getLocalTables() {
133         return this.ribImpl.getLocalTables();
134     }
135
136     @Override
137     public BGPDispatcher getDispatcher() {
138         return this.ribImpl.getDispatcher();
139     }
140
141     @Override
142     public DOMTransactionChain createPeerChain(final TransactionChainListener listener) {
143         return this.ribImpl.createPeerChain(listener);
144     }
145
146     @Override
147     public RIBExtensionConsumerContext getRibExtensions() {
148         return this.ribImpl.getRibExtensions();
149     }
150
151     @Override
152     public RIBSupportContextRegistry getRibSupportContext() {
153         return this.ribImpl.getRibSupportContext();
154     }
155
156     @Override
157     public YangInstanceIdentifier getYangRibId() {
158         return this.ribImpl.getYangRibId();
159     }
160
161     @Override
162     public CodecsRegistry getCodecsRegistry() {
163         return this.ribImpl.getCodecsRegistry();
164     }
165
166     @Override
167     public DOMDataTreeChangeService getService() {
168         return this.ribImpl.getService();
169     }
170
171     ListenableFuture<Void> closeServiceInstance() {
172         if (this.ribImpl != null) {
173             return this.ribImpl.closeServiceInstance();
174         }
175         return Futures.immediateFuture(null);
176     }
177
178     @Override
179     public void close() {
180         if (this.ribImpl != null) {
181             try {
182                 this.ribImpl.close();
183             } catch (final Exception e) {
184                 LOG.warn("Failed to close {} rib instance", this, e);
185             }
186             this.ribImpl = null;
187         }
188         if (this.schemaContextRegistration != null) {
189             this.schemaContextRegistration.close();
190             this.schemaContextRegistration = null;
191         }
192         if (this.serviceRegistration != null) {
193             try {
194                 this.serviceRegistration.unregister();
195             } catch (final IllegalStateException e) {
196                 LOG.warn("Failed to unregister {} service instance", this, e);
197             }
198             this.serviceRegistration = null;
199         }
200     }
201
202     void setServiceRegistration(final ServiceRegistration<?> serviceRegistration) {
203         this.serviceRegistration = serviceRegistration;
204     }
205
206     @Override
207     public ImportPolicyPeerTracker getImportPolicyPeerTracker() {
208         return this.ribImpl.getImportPolicyPeerTracker();
209     }
210
211     @Override
212     public ExportPolicyPeerTracker getExportPolicyPeerTracker(final TablesKey tablesKey) {
213         return this.ribImpl.getExportPolicyPeerTracker(tablesKey);
214     }
215
216     @Override
217     public Set<TablesKey> getLocalTablesKeys() {
218         return this.ribImpl.getLocalTablesKeys();
219     }
220
221     @Override
222     public boolean supportsTable(final TablesKey tableKey) {
223         return this.ribImpl.supportsTable(tableKey);
224     }
225
226     @Override
227     public BGPPeerTracker getPeerTracker() {
228         return this.ribImpl.getPeerTracker();
229     }
230
231     @Override
232     public String toString() {
233         return this.ribImpl != null ? this.ribImpl.toString() : "";
234     }
235
236     private RIBImpl createRib(
237             final Global global,
238             final String bgpInstanceName,
239             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
240         this.afiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true);
241         final Config globalConfig = global.getConfig();
242         this.asNumber = globalConfig.getAs();
243         this.routerId = globalConfig.getRouterId();
244         this.clusterId = getClusterIdentifier(globalConfig);
245
246         final BGPPeerTrackerImpl peerTracker = new BGPPeerTrackerImpl();
247         final Map<TablesKey, PathSelectionMode> pathSelectionModes = OpenConfigMappingUtil
248                 .toPathSelectionMode(this.afiSafi, tableTypeRegistry, peerTracker).entrySet()
249                 .stream()
250                 .collect(Collectors.toMap(entry ->
251                         new TablesKey(entry.getKey().getAfi(), entry.getKey().getSafi()), Map.Entry::getValue));
252
253         final CodecsRegistryImpl codecsRegistry = CodecsRegistryImpl.create(codecTreeFactory,
254                 this.extensions.getClassLoadingStrategy());
255
256         return new RIBImpl(
257                 new RibId(bgpInstanceName),
258                 this.asNumber,
259                 new BgpId(this.routerId),
260                 this.clusterId,
261                 this.extensions,
262                 this.dispatcher,
263                 codecsRegistry,
264                 this.domBroker,
265                 peerTracker,
266                 toTableTypes(this.afiSafi, tableTypeRegistry),
267                 pathSelectionModes);
268     }
269
270     @Override
271     public BGPRIBState getRIBState() {
272         return this.ribImpl.getRIBState();
273     }
274
275     public void instantiateServiceInstance() {
276         if (this.ribImpl != null) {
277             this.ribImpl.instantiateServiceInstance();
278         }
279     }
280
281     @Override
282     public Optional<Attributes> getAttributes(
283             RIBSupport ribSupport,
284             NodeIdentifierWithPredicates routeIdentifier, NormalizedNode<?, ?> route) {
285         return this.ribImpl.getAttributes(ribSupport, routeIdentifier, route);
286     }
287
288     @Override
289     public Optional<ContainerNode> toNormalizedNodeAttribute(
290             final RIBSupport ribSupport,
291             final NodeIdentifierWithPredicates routeIdentifier,
292             final Optional<Attributes> attributes) {
293         return this.ribImpl.toNormalizedNodeAttribute(ribSupport, routeIdentifier, attributes);
294     }
295 }