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