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.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.RouteReflector;
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.http.openconfig.net.yang.bgp.types.rev151009.PeerType;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.BgpPeer;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.BgpTableType;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.RibInstance;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.BgpPeerBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.AddPath;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.AddPathBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.AdvertizedTable;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.AdvertizedTableBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.Rib;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.RibBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.RpcRegistry;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.bgp.peer.RpcRegistryBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.rev131028.BindingRpcRegistry;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.tcpmd5.cfg.rev140427.Rfc2385Key;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 final class BGPPeerProvider {
53 private static final String PEER = "peer_";
55 private static final Logger LOG = LoggerFactory.getLogger(BGPPeerProvider.class);
57 private static final Function<String, AdvertizedTable> ADVERTIZED_TABLE_FUNCTION = new Function<String, AdvertizedTable>() {
59 public AdvertizedTable apply(final String instance) {
60 return new AdvertizedTableBuilder().setName(instance).setType(BgpTableType.class).build();
64 private static final Function<String, Rib> TO_RIB_FUNCTION = new Function<String, Rib>() {
66 public Rib apply(final String name) {
67 return new RibBuilder().setName(name).setType(RibInstance.class).build();
71 private static final Function<String, RpcRegistry> RPC_REG_FUNCTION = new Function<String, RpcRegistry>() {
73 public RpcRegistry apply(final String name) {
74 return new RpcRegistryBuilder().setName(name).setType(BindingRpcRegistry.class).build();
78 private static final Function<String, AddPath> ADD_PATH_FUNCTION = new Function<String, AddPath>() {
80 public AddPath apply(final String name) {
81 return new AddPathBuilder()
83 .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.AddPath.class)
88 private final BGPConfigHolder<Neighbor> neighborState;
89 private final BGPConfigHolder<Bgp> globalState;
90 private final BGPConfigModuleProvider configModuleOp;
91 private final DataBroker dataBroker;
93 public BGPPeerProvider(final BGPConfigStateStore configHolders, final BGPConfigModuleProvider configModuleWriter, final DataBroker dataBroker) {
94 this.dataBroker = dataBroker;
95 this.configModuleOp = Preconditions.checkNotNull(configModuleWriter);
96 this.globalState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Bgp.class));
97 this.neighborState = Preconditions.checkNotNull(configHolders.getBGPConfigHolder(Neighbor.class));
100 public void onNeighborRemoved(final Neighbor removedNeighbor) {
101 final ModuleKey moduleKey = this.neighborState.getModuleKey(removedNeighbor.getKey());
102 if (moduleKey != null) {
104 final ReadWriteTransaction rwTx = this.dataBroker.newReadWriteTransaction();
105 final Optional<Module> maybeModule = this.configModuleOp.readModuleConfiguration(moduleKey, rwTx);
106 if (maybeModule.isPresent() && this.neighborState.remove(moduleKey, removedNeighbor)) {
107 this.configModuleOp.removeModuleConfiguration(moduleKey, rwTx);
109 } catch (ReadFailedException | TransactionCommitFailedException e) {
110 LOG.error("Failed to remove a configuration module: {}", moduleKey, e);
111 throw new IllegalStateException(e);
116 public void onNeighborModified(final Neighbor modifiedNeighbor) {
117 final ModuleKey moduleKey = this.neighborState.getModuleKey(modifiedNeighbor.getKey());
118 final ReadOnlyTransaction rTx = this.dataBroker.newReadOnlyTransaction();
119 final List<AdvertizedTable> advertizedTables = getAdvertizedTables(modifiedNeighbor, rTx);
120 final List<AddPath> addPathCapabilities = getAddPathCapabilities(modifiedNeighbor, rTx);
121 if (moduleKey != null) {
122 updateExistingPeerConfiguration(moduleKey, modifiedNeighbor, advertizedTables, rTx, addPathCapabilities);
124 createNewPeerConfiguration(moduleKey, modifiedNeighbor, advertizedTables, rTx, addPathCapabilities);
128 private List<AdvertizedTable> getAdvertizedTables(final Neighbor modifiedNeighbor, final ReadOnlyTransaction rTx) {
129 return TableTypesFunction.getLocalTables(rTx, this.configModuleOp, ADVERTIZED_TABLE_FUNCTION, modifiedNeighbor.getAfiSafis().getAfiSafi());
132 private List<AddPath> getAddPathCapabilities(final Neighbor modifiedNeighbor, final ReadOnlyTransaction rTx) {
133 return AddPathFunction.getAddPath(rTx, this.configModuleOp, ADD_PATH_FUNCTION, modifiedNeighbor.getAfiSafis().getAfiSafi());
136 private void updateExistingPeerConfiguration(final ModuleKey moduleKey, final Neighbor modifiedNeighbor, final List<AdvertizedTable>
137 advertizedTables, final ReadOnlyTransaction rTx, final List<AddPath> addPathCapabilities) {
138 if (neighborState.addOrUpdate(moduleKey, modifiedNeighbor.getKey(), modifiedNeighbor)) {
139 final Optional<Module> maybeModule = getOldModuleConfiguration(moduleKey, rTx);
140 if (maybeModule.isPresent()) {
141 final Module peerConfigModule = toPeerConfigModule(modifiedNeighbor, maybeModule.get(), advertizedTables, addPathCapabilities);
142 putOldModuleConfigurationIntoNewModule(peerConfigModule);
147 private Optional<Module> getOldModuleConfiguration(final ModuleKey moduleKey, final ReadOnlyTransaction rTx) {
149 return this.configModuleOp.readModuleConfiguration(moduleKey, rTx);
150 } catch (final Exception e) {
151 LOG.error("Failed to read module configuration: {}", moduleKey, e);
152 throw new IllegalStateException(e);
156 private void putOldModuleConfigurationIntoNewModule(final Module peerConfigModule) {
158 this.configModuleOp.putModuleConfiguration(peerConfigModule, this.dataBroker.newWriteOnlyTransaction());
159 } catch (final TransactionCommitFailedException e) {
160 LOG.error("Failed to update a configuration module: {}", peerConfigModule, e);
161 throw new IllegalStateException(e);
165 private void createNewPeerConfiguration(final ModuleKey moduleKey, final Neighbor modifiedNeighbor, final List<AdvertizedTable> advertizedTables,
166 final ReadOnlyTransaction rTx, final List<AddPath> addPathCapabilities) {
167 final ModuleKey ribImplKey = this.globalState.getModuleKey(GlobalIdentifier.GLOBAL_IDENTIFIER);
168 if (ribImplKey != null) {
170 final Rib rib = RibInstanceFunction.getRibInstance(this.configModuleOp, TO_RIB_FUNCTION, ribImplKey.getName(), rTx);
171 final RpcRegistry rpcReg = RpcRegistryFunction.getRpcRegistryInstance(rTx, this.configModuleOp, RPC_REG_FUNCTION);
172 final Module peerConfigModule = toPeerConfigModule(modifiedNeighbor, advertizedTables, rib, rpcReg, addPathCapabilities);
173 this.configModuleOp.putModuleConfiguration(peerConfigModule, this.dataBroker.newWriteOnlyTransaction());
174 this.neighborState.addOrUpdate(peerConfigModule.getKey(), modifiedNeighbor.getKey(), modifiedNeighbor);
175 } catch (final Exception e) {
176 LOG.error("Failed to create a configuration module: {}", moduleKey, e);
177 throw new IllegalStateException(e);
182 private static Module toPeerConfigModule(final Neighbor neighbor, final Module oldBgpPeer, final List<AdvertizedTable> tableTypes,
183 final List<AddPath> addPathCapabilities) {
184 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.BgpPeer bgpPeer =
185 (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.bgp.rib.impl.rev160330.modules.module.configuration.BgpPeer) oldBgpPeer.getConfiguration();
186 final BgpPeerBuilder bgpPeerBuilder = toBgpPeerConfig(neighbor, tableTypes, bgpPeer.getRib(), bgpPeer.getRpcRegistry(), addPathCapabilities);
187 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());
188 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());
190 final ModuleBuilder mBuilder = new ModuleBuilder(oldBgpPeer);
191 mBuilder.setConfiguration(bgpPeerBuilder.build());
192 return mBuilder.build();
195 private static Module toPeerConfigModule(final Neighbor neighbor, final List<AdvertizedTable> tableTypes, final Rib rib, final RpcRegistry rpcReg,
196 final List<AddPath> addPathCapabilities) {
197 final ModuleBuilder mBuilder = new ModuleBuilder();
198 mBuilder.setName(createPeerName(neighbor.getNeighborAddress()));
199 mBuilder.setType(BgpPeer.class);
200 mBuilder.setConfiguration(toBgpPeerConfig(neighbor, tableTypes, rib, rpcReg, addPathCapabilities).build());
201 mBuilder.setKey(new ModuleKey(mBuilder.getName(), mBuilder.getType()));
202 return mBuilder.build();
205 private static BgpPeerBuilder toBgpPeerConfig(final Neighbor neighbor, final List<AdvertizedTable> tableTypes, final Rib rib, final RpcRegistry rpcReg,
206 final List<AddPath> addPathCapabilities) {
207 final BgpPeerBuilder bgpPeerBuilder = new BgpPeerBuilder();
208 if (rpcReg != null) {
209 bgpPeerBuilder.setRpcRegistry(rpcReg);
211 bgpPeerBuilder.setAdvertizedTable(tableTypes);
212 bgpPeerBuilder.setAddPath(addPathCapabilities);
213 bgpPeerBuilder.setRib(rib);
214 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress ipAdress = null;
215 if (neighbor.getNeighborAddress().getIpv4Address() != null) {
216 ipAdress = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress(new org.opendaylight.yang
217 .gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address(neighbor.getNeighborAddress().getIpv4Address().getValue()));
219 ipAdress = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress(new org.opendaylight.yang
220 .gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address(neighbor.getNeighborAddress().getIpv6Address().getValue()));
222 bgpPeerBuilder.setHost(ipAdress);
223 final Timers timers = neighbor.getTimers();
224 if (timers != null && timers.getConfig() != null && timers.getConfig().getHoldTime() != null) {
225 bgpPeerBuilder.setHoldtimer(neighbor.getTimers().getConfig().getHoldTime().intValue());
227 final Transport transport = neighbor.getTransport();
228 if (transport != null && transport.getConfig() != null && transport.getConfig().isPassiveMode() != null) {
229 bgpPeerBuilder.setInitiateConnection(!neighbor.getTransport().getConfig().isPassiveMode());
231 if (neighbor.getConfig() != null) {
232 if (neighbor.getConfig().getAuthPassword() != null) {
233 bgpPeerBuilder.setPassword(new Rfc2385Key(neighbor.getConfig().getAuthPassword()));
235 if (neighbor.getConfig().getPeerAs() != null) {
236 bgpPeerBuilder.setRemoteAs(neighbor.getConfig().getPeerAs().getValue());
238 if (neighbor.getConfig().getPeerType() != null) {
239 bgpPeerBuilder.setPeerRole(toPeerRole(neighbor));
242 return bgpPeerBuilder;
245 private static String createPeerName(final IpAddress ipAddress) {
246 final String address = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
247 return PEER + address;
250 private static PeerRole toPeerRole(final Neighbor neighbor) {
251 if (isRrClient(neighbor)) {
252 return PeerRole.RrClient;
255 if (neighbor.getConfig() != null) {
256 final PeerType peerType = neighbor.getConfig().getPeerType();
257 if (peerType == PeerType.INTERNAL) {
258 return PeerRole.Ibgp;
260 if (peerType == PeerType.EXTERNAL) {
261 return PeerRole.Ebgp;
264 LOG.info("Unknown peer role, setting peer {} role to iBGP", neighbor.getKey());
265 return PeerRole.Ibgp;
268 private static boolean isRrClient(final Neighbor neighbor) {
269 final RouteReflector routeReflector = neighbor.getRouteReflector();
270 if (routeReflector != null && routeReflector.getConfig() != null) {
271 return routeReflector.getConfig().isRouteReflectorClient();