2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.protocol.bgp.openconfig.impl.moduleconfig;
11 import com.google.common.base.Function;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import java.util.List;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigHolder;
21 import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
22 import org.opendaylight.protocol.bgp.openconfig.impl.util.GlobalIdentifier;
23 import org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil;
24 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Timers;
25 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Transport;
26 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
27 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.BgpPeer;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.BgpTableType;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.RibInstance;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.BgpPeerBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.AddPath;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.AddPathBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.AdvertizedTable;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.AdvertizedTableBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.Rib;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.RibBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.RpcRegistry;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.RpcRegistryBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.rev131028.BindingRpcRegistry;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.rfc2385.cfg.rev160324.Rfc2385Key;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 final class BGPPeerProvider {
51 private static final String PEER = "peer_";
53 private static final Logger LOG = LoggerFactory.getLogger(BGPPeerProvider.class);
55 private static final Function<String, AdvertizedTable> ADVERTIZED_TABLE_FUNCTION = new Function<String, AdvertizedTable>() {
57 public AdvertizedTable apply(final String instance) {
58 return new AdvertizedTableBuilder().setName(instance).setType(BgpTableType.class).build();
62 private static final Function<String, Rib> TO_RIB_FUNCTION = new Function<String, Rib>() {
64 public Rib apply(final String name) {
65 return new RibBuilder().setName(name).setType(RibInstance.class).build();
69 private static final Function<String, RpcRegistry> RPC_REG_FUNCTION = new Function<String, RpcRegistry>() {
71 public RpcRegistry apply(final String name) {
72 return new RpcRegistryBuilder().setName(name).setType(BindingRpcRegistry.class).build();
76 private static final Function<String, AddPath> ADD_PATH_FUNCTION = new Function<String, AddPath>() {
78 public AddPath apply(final String name) {
79 return new AddPathBuilder()
81 .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.AddPath.class)
86 private final BGPConfigHolder<Neighbor> neighborState;
87 private final BGPConfigHolder<Bgp> globalState;
88 private final BGPConfigModuleProvider configModuleOp;
89 private final DataBroker dataBroker;
91 public BGPPeerProvider(final BGPConfigStateStore configHolders, final BGPConfigModuleProvider configModuleWriter, final DataBroker dataBroker) {
92 this.dataBroker = dataBroker;
93 this.configModuleOp = Preconditions.checkNotNull(configModuleWriter);
94 this.globalState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Bgp.class));
95 this.neighborState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Neighbor.class));
98 public void onNeighborRemoved(final Neighbor removedNeighbor) {
99 final ModuleKey moduleKey = this.neighborState.getModuleKey(removedNeighbor.getKey());
100 if (moduleKey != null) {
102 final ReadWriteTransaction rwTx = this.dataBroker.newReadWriteTransaction();
103 final Optional<Module> maybeModule = this.configModuleOp.readModuleConfiguration(moduleKey, rwTx);
104 if (maybeModule.isPresent() && this.neighborState.remove(moduleKey, removedNeighbor)) {
105 this.configModuleOp.removeModuleConfiguration(moduleKey, rwTx);
107 } catch (ReadFailedException | TransactionCommitFailedException e) {
108 LOG.error("Failed to remove a configuration module: {}", moduleKey, e);
109 throw new IllegalStateException(e);
114 public void onNeighborModified(final Neighbor modifiedNeighbor) {
115 final ModuleKey moduleKey = this.neighborState.getModuleKey(modifiedNeighbor.getKey());
116 final ReadOnlyTransaction rTx = this.dataBroker.newReadOnlyTransaction();
117 final List<AdvertizedTable> advertizedTables = getAdvertizedTables(modifiedNeighbor, rTx);
118 final List<AddPath> addPathCapabilities = getAddPathCapabilities(modifiedNeighbor, rTx);
119 if (moduleKey != null) {
120 updateExistingPeerConfiguration(moduleKey, modifiedNeighbor, advertizedTables, rTx, addPathCapabilities);
122 createNewPeerConfiguration(moduleKey, modifiedNeighbor, advertizedTables, rTx, addPathCapabilities);
126 private List<AdvertizedTable> getAdvertizedTables(final Neighbor modifiedNeighbor, final ReadOnlyTransaction rTx) {
127 return TableTypesFunction.getLocalTables(rTx, this.configModuleOp, ADVERTIZED_TABLE_FUNCTION, modifiedNeighbor.getAfiSafis().getAfiSafi());
130 private List<AddPath> getAddPathCapabilities(final Neighbor modifiedNeighbor, final ReadOnlyTransaction rTx) {
131 return AddPathFunction.getAddPath(rTx, this.configModuleOp, ADD_PATH_FUNCTION, modifiedNeighbor.getAfiSafis().getAfiSafi());
134 private void updateExistingPeerConfiguration(final ModuleKey moduleKey, final Neighbor modifiedNeighbor, final List<AdvertizedTable>
135 advertizedTables, final ReadOnlyTransaction rTx, final List<AddPath> addPathCapabilities) {
136 if (neighborState.addOrUpdate(moduleKey, modifiedNeighbor.getKey(), modifiedNeighbor)) {
137 final Optional<Module> maybeModule = getOldModuleConfiguration(moduleKey, rTx);
138 if (maybeModule.isPresent()) {
139 final Module peerConfigModule = toPeerConfigModule(modifiedNeighbor, maybeModule.get(), advertizedTables, addPathCapabilities);
140 putOldModuleConfigurationIntoNewModule(peerConfigModule);
145 private Optional<Module> getOldModuleConfiguration(final ModuleKey moduleKey, final ReadOnlyTransaction rTx) {
147 return this.configModuleOp.readModuleConfiguration(moduleKey, rTx);
148 } catch (final Exception e) {
149 LOG.error("Failed to read module configuration: {}", moduleKey, e);
150 throw new IllegalStateException(e);
154 private void putOldModuleConfigurationIntoNewModule(final Module peerConfigModule) {
156 this.configModuleOp.putModuleConfiguration(peerConfigModule, this.dataBroker.newWriteOnlyTransaction());
157 } catch (final TransactionCommitFailedException e) {
158 LOG.error("Failed to update a configuration module: {}", peerConfigModule, e);
159 throw new IllegalStateException(e);
163 private void createNewPeerConfiguration(final ModuleKey moduleKey, final Neighbor modifiedNeighbor, final List<AdvertizedTable> advertizedTables,
164 final ReadOnlyTransaction rTx, final List<AddPath> addPathCapabilities) {
165 final ModuleKey ribImplKey = this.globalState.getModuleKey(GlobalIdentifier.GLOBAL_IDENTIFIER);
166 if (ribImplKey != null) {
168 final Rib rib = RibInstanceFunction.getRibInstance(this.configModuleOp, TO_RIB_FUNCTION, ribImplKey.getName(), rTx);
169 final RpcRegistry rpcReg = RpcRegistryFunction.getRpcRegistryInstance(rTx, this.configModuleOp, RPC_REG_FUNCTION);
170 final Module peerConfigModule = toPeerConfigModule(modifiedNeighbor, advertizedTables, rib, rpcReg, addPathCapabilities);
171 this.configModuleOp.putModuleConfiguration(peerConfigModule, this.dataBroker.newWriteOnlyTransaction());
172 this.neighborState.addOrUpdate(peerConfigModule.getKey(), modifiedNeighbor.getKey(), modifiedNeighbor);
173 } catch (final Exception e) {
174 LOG.error("Failed to create a configuration module: {}", moduleKey, e);
175 throw new IllegalStateException(e);
180 private static Module toPeerConfigModule(final Neighbor neighbor, final Module oldBgpPeer, final List<AdvertizedTable> tableTypes,
181 final List<AddPath> addPathCapabilities) {
182 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.BgpPeer bgpPeer =
183 (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.BgpPeer) oldBgpPeer.getConfiguration();
184 final BgpPeerBuilder bgpPeerBuilder = toBgpPeerConfig(neighbor, tableTypes, bgpPeer.getRib(), bgpPeer.getRpcRegistry(), addPathCapabilities);
185 bgpPeerBuilder.setPeerRegistry(((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.BgpPeer) oldBgpPeer.getConfiguration()).getPeerRegistry());
186 bgpPeerBuilder.setPort(((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.BgpPeer) oldBgpPeer.getConfiguration()).getPort());
188 final ModuleBuilder mBuilder = new ModuleBuilder(oldBgpPeer);
189 mBuilder.setConfiguration(bgpPeerBuilder.build());
190 return mBuilder.build();
193 private static Module toPeerConfigModule(final Neighbor neighbor, final List<AdvertizedTable> tableTypes, final Rib rib, final RpcRegistry rpcReg,
194 final List<AddPath> addPathCapabilities) {
195 final ModuleBuilder mBuilder = new ModuleBuilder();
196 mBuilder.setName(createPeerName(neighbor.getNeighborAddress()));
197 mBuilder.setType(BgpPeer.class);
198 mBuilder.setConfiguration(toBgpPeerConfig(neighbor, tableTypes, rib, rpcReg, addPathCapabilities).build());
199 mBuilder.setKey(new ModuleKey(mBuilder.getName(), mBuilder.getType()));
200 return mBuilder.build();
203 private static BgpPeerBuilder toBgpPeerConfig(final Neighbor neighbor, final List<AdvertizedTable> tableTypes, final Rib rib, final RpcRegistry rpcReg,
204 final List<AddPath> addPathCapabilities) {
205 final BgpPeerBuilder bgpPeerBuilder = new BgpPeerBuilder();
206 if (rpcReg != null) {
207 bgpPeerBuilder.setRpcRegistry(rpcReg);
209 bgpPeerBuilder.setAdvertizedTable(tableTypes);
210 bgpPeerBuilder.setAddPath(addPathCapabilities);
211 bgpPeerBuilder.setRib(rib);
212 bgpPeerBuilder.setHost(neighbor.getNeighborAddress());
213 final Timers timers = neighbor.getTimers();
214 if (timers != null && timers.getConfig() != null && timers.getConfig().getHoldTime() != null) {
215 bgpPeerBuilder.setHoldtimer(neighbor.getTimers().getConfig().getHoldTime().intValue());
217 final Transport transport = neighbor.getTransport();
218 if (transport != null && transport.getConfig() != null && transport.getConfig().isPassiveMode() != null) {
219 bgpPeerBuilder.setInitiateConnection(!neighbor.getTransport().getConfig().isPassiveMode());
221 if (neighbor.getConfig() != null) {
222 if (neighbor.getConfig().getAuthPassword() != null) {
223 bgpPeerBuilder.setPassword(new Rfc2385Key(neighbor.getConfig().getAuthPassword()));
225 if (neighbor.getConfig().getPeerAs() != null) {
226 bgpPeerBuilder.setRemoteAs(neighbor.getConfig().getPeerAs());
228 if (neighbor.getConfig().getPeerType() != null) {
229 bgpPeerBuilder.setPeerRole(OpenConfigUtil.toPeerRole(neighbor));
232 return bgpPeerBuilder;
235 private static String createPeerName(final IpAddress ipAddress) {
236 final String address = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
237 return PEER + address;