BGPCEP-754: Rework EffectiveRibInWriter
[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.Set;
21 import java.util.stream.Collectors;
22 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
25 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
26 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
27 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
28 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeFactory;
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.RIB;
39 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
40 import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
41 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
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.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.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 = getClusterIdentifier(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 BindingTransactionChain createPeerChain(final TransactionChainListener listener) {
150         return this.ribImpl.createPeerChain(listener);
151     }
152
153     @Override
154     public DOMTransactionChain createPeerDOMChain(final TransactionChainListener listener) {
155         return this.ribImpl.createPeerDOMChain(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     ListenableFuture<Void> closeServiceInstance() {
189         if (this.ribImpl != null) {
190             return this.ribImpl.closeServiceInstance();
191         }
192         return Futures.immediateFuture(null);
193     }
194
195     @Override
196     public void close() {
197         if (this.ribImpl != null) {
198             try {
199                 this.ribImpl.close();
200             } catch (final Exception e) {
201                 LOG.warn("Failed to close {} rib instance", this, e);
202             }
203             this.ribImpl = null;
204         }
205         if (this.schemaContextRegistration != null) {
206             this.schemaContextRegistration.close();
207             this.schemaContextRegistration = null;
208         }
209         if (this.serviceRegistration != null) {
210             try {
211                 this.serviceRegistration.unregister();
212             } catch (final IllegalStateException e) {
213                 LOG.warn("Failed to unregister {} service instance", this, e);
214             }
215             this.serviceRegistration = null;
216         }
217     }
218
219     void setServiceRegistration(final ServiceRegistration<?> serviceRegistration) {
220         this.serviceRegistration = serviceRegistration;
221     }
222
223     @Override
224     public ExportPolicyPeerTracker getExportPolicyPeerTracker(final TablesKey tablesKey) {
225         return this.ribImpl.getExportPolicyPeerTracker(tablesKey);
226     }
227
228     @Override
229     public Set<TablesKey> getLocalTablesKeys() {
230         return this.ribImpl.getLocalTablesKeys();
231     }
232
233     @Override
234     public boolean supportsTable(final TablesKey tableKey) {
235         return this.ribImpl.supportsTable(tableKey);
236     }
237
238     @Override
239     public BGPRibRoutingPolicy getRibPolicies() {
240         return this.ribImpl.getRibPolicies();
241     }
242
243     @Override
244     public BGPPeerTracker getPeerTracker() {
245         return this.ribImpl.getPeerTracker();
246     }
247
248     @Override
249     public String toString() {
250         return this.ribImpl != null ? this.ribImpl.toString() : "";
251     }
252
253     private RIBImpl createRib(
254             final Global global,
255             final String bgpInstanceName,
256             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
257         this.afiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true);
258         final Config globalConfig = global.getConfig();
259         this.asNumber = globalConfig.getAs();
260         this.routerId = globalConfig.getRouterId();
261         this.clusterId = getClusterIdentifier(globalConfig);
262         final BGPPeerTrackerImpl peerTracker = new BGPPeerTrackerImpl();
263         final Map<TablesKey, PathSelectionMode> pathSelectionModes = OpenConfigMappingUtil
264                 .toPathSelectionMode(this.afiSafi, tableTypeRegistry, peerTracker).entrySet()
265                 .stream()
266                 .collect(Collectors.toMap(entry ->
267                         new TablesKey(entry.getKey().getAfi(), entry.getKey().getSafi()), Map.Entry::getValue));
268
269         final BGPRibRoutingPolicy ribPolicy = this.policyProvider.buildBGPRibPolicy(this.asNumber.getValue(),
270                 this.routerId, this.clusterId, RoutingPolicyUtil.getApplyPolicy(global.getApplyPolicy()));
271         final CodecsRegistryImpl codecsRegistry = CodecsRegistryImpl.create(codecTreeFactory,
272                 this.extensions.getClassLoadingStrategy());
273
274         return new RIBImpl(
275                 new RibId(bgpInstanceName),
276                 this.asNumber,
277                 new BgpId(this.routerId),
278                 this.clusterId,
279                 this.extensions,
280                 this.dispatcher,
281                 codecsRegistry,
282                 this.domBroker,
283                 this.dataBroker,
284                 ribPolicy,
285                 peerTracker,
286                 toTableTypes(this.afiSafi, tableTypeRegistry),
287                 pathSelectionModes);
288     }
289
290     @Override
291     public BGPRIBState getRIBState() {
292         return this.ribImpl.getRIBState();
293     }
294
295     public void instantiateServiceInstance() {
296         if (this.ribImpl != null) {
297             this.ribImpl.instantiateServiceInstance();
298         }
299     }
300 }