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