0ed4c7dcda5d1ee608f88710be1ee0bbb46bb92f
[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 package org.opendaylight.protocol.bgp.rib.impl.config;
9
10 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getAfiSafiWithDefault;
11 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getGlobalClusterIdentifier;
12 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.toTableTypes;
13
14 import com.google.common.base.Preconditions;
15 import com.google.common.util.concurrent.FluentFuture;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.stream.Collectors;
20 import org.opendaylight.mdsal.binding.api.DataBroker;
21 import org.opendaylight.mdsal.binding.api.TransactionChain;
22 import org.opendaylight.mdsal.binding.api.TransactionChainListener;
23 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeFactory;
24 import org.opendaylight.mdsal.common.api.CommitInfo;
25 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
27 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
28 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
29 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
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.CodecsRegistryImpl;
34 import org.opendaylight.protocol.bgp.rib.impl.RIBImpl;
35 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
36 import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry;
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.RIBExtensionConsumerContext;
41 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
42 import org.opendaylight.protocol.bgp.rib.spi.state.BGPRibState;
43 import org.opendaylight.protocol.bgp.rib.spi.state.BGPRibStateConsumer;
44 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base.Config;
46 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerId;
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 DOMTransactionChainListener listener) {
149         return this.ribImpl.createPeerDOMChain(listener);
150     }
151
152     @Override
153     public TransactionChain 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             this.ribImpl.close();
198             this.ribImpl = null;
199         }
200         if (this.schemaContextRegistration != null) {
201             this.schemaContextRegistration.close();
202             this.schemaContextRegistration = null;
203         }
204         if (this.serviceRegistration != null) {
205             try {
206                 this.serviceRegistration.unregister();
207             } catch (final IllegalStateException e) {
208                 LOG.warn("Failed to unregister {} service instance", this, e);
209             }
210             this.serviceRegistration = null;
211         }
212     }
213
214     void setServiceRegistration(final ServiceRegistration<?> serviceRegistration) {
215         this.serviceRegistration = serviceRegistration;
216     }
217
218     @Override
219     public Set<TablesKey> getLocalTablesKeys() {
220         return this.ribImpl.getLocalTablesKeys();
221     }
222
223     @Override
224     public boolean supportsTable(final TablesKey tableKey) {
225         return this.ribImpl.supportsTable(tableKey);
226     }
227
228     @Override
229     public BGPRibRoutingPolicy getRibPolicies() {
230         return this.ribImpl.getRibPolicies();
231     }
232
233     @Override
234     public BGPPeerTracker getPeerTracker() {
235         return this.ribImpl.getPeerTracker();
236     }
237
238     @Override
239     public String toString() {
240         return this.ribImpl != null ? this.ribImpl.toString() : "";
241     }
242
243     private RIBImpl createRib(
244             final Global global,
245             final String bgpInstanceName,
246             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
247         this.afiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true);
248         final Config globalConfig = global.getConfig();
249         this.asNumber = globalConfig.getAs();
250         this.routerId = globalConfig.getRouterId();
251         this.clusterId = getGlobalClusterIdentifier(globalConfig);
252         final Map<TablesKey, PathSelectionMode> pathSelectionModes = OpenConfigMappingUtil
253                 .toPathSelectionMode(this.afiSafi, tableTypeRegistry).entrySet()
254                 .stream()
255                 .collect(Collectors.toMap(entry ->
256                         new TablesKey(entry.getKey().getAfi(), entry.getKey().getSafi()), Map.Entry::getValue));
257
258         final BGPRibRoutingPolicy ribPolicy = this.policyProvider.buildBGPRibPolicy(this.asNumber.getValue().toJava(),
259                 this.routerId, this.clusterId, RoutingPolicyUtil.getApplyPolicy(global.getApplyPolicy()));
260         final CodecsRegistryImpl codecsRegistry = CodecsRegistryImpl.create(codecTreeFactory,
261                 this.extensions.getClassLoadingStrategy());
262
263         return new RIBImpl(
264                 tableTypeRegistry,
265                 new RibId(bgpInstanceName),
266                 this.asNumber,
267                 new BgpId(this.routerId),
268                 this.extensions,
269                 this.dispatcher,
270                 codecsRegistry,
271                 this.domBroker,
272                 this.dataBroker,
273                 ribPolicy,
274                 toTableTypes(this.afiSafi, tableTypeRegistry),
275                 pathSelectionModes);
276     }
277
278     @Override
279     public BGPRibState getRIBState() {
280         return this.ribImpl.getRIBState();
281     }
282
283     public void instantiateServiceInstance() {
284         if (this.ribImpl != null) {
285             this.ribImpl.instantiateServiceInstance();
286         }
287     }
288
289     @Override
290     public void refreshTable(final TablesKey tk, final PeerId peerId) {
291         this.ribImpl.refreshTable(tk, peerId);
292     }
293 }