c3eb1ce25df0ea37be8621adc5fbd4031571e578
[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 com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
12 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getAfiSafiWithDefault;
13 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getGlobalClusterIdentifier;
14 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.toTableTypes;
15
16 import com.google.common.util.concurrent.FluentFuture;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import java.util.Collection;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.stream.Collectors;
23 import org.checkerframework.checker.lock.qual.GuardedBy;
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.DOMTransactionChain;
28 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
29 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
30 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.BGPRibRoutingPolicyFactory;
31 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
32 import org.opendaylight.protocol.bgp.rib.impl.RIBImpl;
33 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
34 import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry;
35 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
36 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
37 import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
38 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
39 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
40 import org.opendaylight.protocol.bgp.rib.spi.state.BGPRibState;
41 import org.opendaylight.protocol.bgp.rib.spi.state.BGPRibStateProvider;
42 import org.opendaylight.protocol.bgp.rib.spi.state.BGPStateProviderRegistry;
43 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
44 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base.Config;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
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.PeerId;
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.rev200120.BgpId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.ClusterIdentifier;
58 import org.opendaylight.yangtools.concepts.Registration;
59 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
60 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 public final class RibImpl implements RIB, BGPRibStateProvider {
65
66     private static final Logger LOG = LoggerFactory.getLogger(RibImpl.class);
67
68     private final RIBExtensionConsumerContext extensionProvider;
69     private final BGPDispatcher dispatcher;
70     private final CodecsRegistry codecsRegistry;
71     private final DOMDataBroker domBroker;
72     private final BGPRibRoutingPolicyFactory policyProvider;
73     private final BGPStateProviderRegistry stateProviderRegistry;
74     @GuardedBy("this")
75     private RIBImpl ribImpl;
76     @GuardedBy("this")
77     private Registration stateProviderRegistration;
78     @GuardedBy("this")
79     private Collection<AfiSafi> afiSafi;
80     @GuardedBy("this")
81     private AsNumber asNumber;
82     @GuardedBy("this")
83     private Ipv4AddressNoZone routerId;
84     @GuardedBy("this")
85     private ClusterIdentifier clusterId;
86     @GuardedBy("this")
87     private RibId ribId;
88
89     public RibImpl(
90             final RIBExtensionConsumerContext extensionProvider,
91             final BGPDispatcher dispatcher,
92             final BGPRibRoutingPolicyFactory policyProvider,
93             final CodecsRegistry codecsRegistry,
94             final BGPStateProviderRegistry stateProviderRegistry,
95             final DOMDataBroker domBroker) {
96         this.extensionProvider = requireNonNull(extensionProvider);
97         this.dispatcher = requireNonNull(dispatcher);
98         this.codecsRegistry = requireNonNull(codecsRegistry);
99         this.domBroker = requireNonNull(domBroker);
100         this.policyProvider = requireNonNull(policyProvider);
101         this.stateProviderRegistry = requireNonNull(stateProviderRegistry);
102     }
103
104     synchronized void start(final Global global, final String instanceName,
105             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
106         checkState(ribImpl == null, "Previous instance %s was not closed.", this);
107         LOG.info("Starting BGP instance {}", instanceName);
108         ribId = new RibId(instanceName);
109         ribImpl = createRib(global, tableTypeRegistry);
110         stateProviderRegistration =  stateProviderRegistry.register(this);
111     }
112
113     synchronized ListenableFuture<?> stop() {
114         if (ribImpl == null) {
115             LOG.info("RIB instance {} already closed, skipping", ribId);
116             return Futures.immediateVoidFuture();
117         }
118
119         LOG.info("Closing RIB instance {}", ribId);
120         if (stateProviderRegistration != null) {
121             LOG.info("Unregistering state provider for RIB instance {}", ribId);
122             stateProviderRegistration.close();
123             stateProviderRegistration = null;
124         }
125
126         final var future = ribImpl.closeServiceInstance();
127         ribImpl = null;
128         return future;
129     }
130
131     synchronized boolean isGlobalEqual(final Global global) {
132         final Collection<AfiSafi> globalAfiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true).values();
133         final Config globalConfig = global.getConfig();
134         final AsNumber globalAs = globalConfig.getAs();
135         final Ipv4Address globalRouterId = global.getConfig().getRouterId();
136         final ClusterIdentifier globalClusterId = getGlobalClusterIdentifier(globalConfig);
137         return afiSafi.containsAll(globalAfiSafi) && globalAfiSafi.containsAll(afiSafi)
138                 && globalAs.equals(asNumber)
139                 && globalRouterId.getValue().equals(routerId.getValue())
140                 && globalClusterId.getValue().equals(clusterId.getValue());
141     }
142
143     @Override
144     public synchronized KeyedInstanceIdentifier<Rib, RibKey> getInstanceIdentifier() {
145         return ribImpl.getInstanceIdentifier();
146     }
147
148     @Override
149     public synchronized AsNumber getLocalAs() {
150         return ribImpl.getLocalAs();
151     }
152
153     @Override
154     public synchronized BgpId getBgpIdentifier() {
155         return ribImpl.getBgpIdentifier();
156     }
157
158     @Override
159     public synchronized Set<? extends BgpTableType> getLocalTables() {
160         return ribImpl.getLocalTables();
161     }
162
163     @Override
164     public synchronized BGPDispatcher getDispatcher() {
165         return ribImpl.getDispatcher();
166     }
167
168     @Override
169     public synchronized DOMTransactionChain createPeerDOMChain(final DOMTransactionChainListener listener) {
170         return ribImpl.createPeerDOMChain(listener);
171     }
172
173     @Override
174     public synchronized RIBExtensionConsumerContext getRibExtensions() {
175         return ribImpl.getRibExtensions();
176     }
177
178     @Override
179     public synchronized RIBSupportContextRegistry getRibSupportContext() {
180         return ribImpl.getRibSupportContext();
181     }
182
183     @Override
184     public synchronized YangInstanceIdentifier getYangRibId() {
185         return ribImpl.getYangRibId();
186     }
187
188     @Override
189     public synchronized CodecsRegistry getCodecsRegistry() {
190         return ribImpl.getCodecsRegistry();
191     }
192
193     @Override
194     public synchronized DOMDataTreeChangeService getService() {
195         return ribImpl.getService();
196     }
197
198     synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
199         if (ribImpl != null) {
200             return ribImpl.closeServiceInstance();
201         }
202         return CommitInfo.emptyFluentFuture();
203     }
204
205     @Override
206     public synchronized Set<TablesKey> getLocalTablesKeys() {
207         return ribImpl.getLocalTablesKeys();
208     }
209
210     @Override
211     public synchronized boolean supportsTable(final TablesKey tableKey) {
212         return ribImpl.supportsTable(tableKey);
213     }
214
215     @Override
216     public synchronized BGPRibRoutingPolicy getRibPolicies() {
217         return ribImpl.getRibPolicies();
218     }
219
220     @Override
221     public synchronized BGPPeerTracker getPeerTracker() {
222         return ribImpl.getPeerTracker();
223     }
224
225     @Override
226     public synchronized String toString() {
227         return ribImpl != null ? ribImpl.toString() : "";
228     }
229
230     private synchronized RIBImpl createRib(
231             final Global global,
232             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
233         afiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true).values();
234         final Config globalConfig = global.getConfig();
235         asNumber = globalConfig.getAs();
236         routerId = IetfInetUtil.ipv4AddressNoZoneFor(globalConfig.getRouterId());
237         clusterId = getGlobalClusterIdentifier(globalConfig);
238         final Map<TablesKey, PathSelectionMode> pathSelectionModes = OpenConfigMappingUtil
239                 .toPathSelectionMode(afiSafi, tableTypeRegistry).entrySet()
240                 .stream()
241                 .collect(Collectors.toMap(entry ->
242                         new TablesKey(entry.getKey().getAfi(), entry.getKey().getSafi()), Map.Entry::getValue));
243
244         final BGPRibRoutingPolicy ribPolicy = policyProvider.buildBGPRibPolicy(asNumber.getValue().toJava(),
245                 routerId, clusterId, RoutingPolicyUtil.getApplyPolicy(global.getApplyPolicy()));
246
247         return new RIBImpl(
248                 tableTypeRegistry,
249                 ribId,
250                 asNumber,
251                 new BgpId(routerId),
252                 extensionProvider,
253                 dispatcher,
254                 codecsRegistry,
255                 domBroker,
256                 ribPolicy,
257                 toTableTypes(afiSafi, tableTypeRegistry),
258                 pathSelectionModes);
259     }
260
261     @Override
262     public synchronized BGPRibState getRIBState() {
263         return ribImpl.getRIBState();
264     }
265
266     public synchronized void instantiateServiceInstance() {
267         if (ribImpl != null) {
268             ribImpl.instantiateServiceInstance();
269         }
270     }
271
272     @Override
273     public synchronized void refreshTable(final TablesKey tk, final PeerId peerId) {
274         ribImpl.refreshTable(tk, peerId);
275     }
276 }