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