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