9798a822892b678e75b012e9a45a97c7d6dfae78
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / controller / config / yang / bgp / rib / impl / BGPPeerModule.java
1 /*
2  * Copyright (c) 2013 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 /**
9  * Generated file
10
11  * Generated from: yang module name: bgp-rib-impl  yang module local name: bgp-peer
12  * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
13  * Generated at: Sat Jan 25 11:00:14 CET 2014
14  *
15  * Do not modify this file unless it is present under src/main directory
16  */
17 package org.opendaylight.controller.config.yang.bgp.rib.impl;
18
19 import com.google.common.base.Charsets;
20 import com.google.common.base.Optional;
21 import com.google.common.base.Preconditions;
22 import com.google.common.net.InetAddresses;
23 import io.netty.util.concurrent.Future;
24 import java.net.InetSocketAddress;
25 import java.util.ArrayList;
26 import java.util.List;
27 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
28 import org.opendaylight.protocol.bgp.openconfig.spi.BGPConfigModuleTracker;
29 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider;
30 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenconfigMapper;
31 import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfigurationIdentifier;
32 import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPPeerInstanceConfiguration;
33 import org.opendaylight.protocol.bgp.rib.impl.BGPPeer;
34 import org.opendaylight.protocol.bgp.rib.impl.StrictBGPPeerRegistry;
35 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
36 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
37 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
38 import org.opendaylight.protocol.util.Ipv6Util;
39 import org.opendaylight.tcpmd5.api.KeyMapping;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParametersBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilities;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.GracefulRestartCapabilityBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapabilityBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.tcpmd5.cfg.rev140427.Rfc2385Key;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 /**
59  *
60  */
61 public final class BGPPeerModule extends org.opendaylight.controller.config.yang.bgp.rib.impl.AbstractBGPPeerModule {
62     private static final Logger LOG = LoggerFactory.getLogger(BGPPeerModule.class);
63
64     public BGPPeerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
65         final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
66         super(identifier, dependencyResolver);
67     }
68
69     public BGPPeerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
70         final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final BGPPeerModule oldModule,
71         final java.lang.AutoCloseable oldInstance) {
72
73         super(identifier, dependencyResolver, oldModule, oldInstance);
74     }
75
76     @Override
77     protected void customValidation() {
78         final IpAddress host = getHost();
79         JmxAttributeValidationException.checkNotNull(host, "value is not set.", hostJmxAttribute);
80         JmxAttributeValidationException.checkCondition(host.getIpv4Address() != null || host.getIpv6Address() != null,
81             "Unexpected host", hostJmxAttribute);
82
83         JmxAttributeValidationException.checkNotNull(getPort(), "value is not set.", portJmxAttribute);
84
85         if (getOptionaPassword(getPassword()).isPresent()) {
86             /*
87              *  This is a nasty hack, but we don't have another clean solution. We cannot allow
88              *  password being set if the injected dispatcher does not have the optional
89              *  md5-server-channel-factory set.
90              *
91              *  FIXME: this is a use case for Module interfaces, e.g. RibImplModule
92              *         should something like isMd5ServerSupported()
93              */
94
95             final RIBImplModuleMXBean ribProxy = this.dependencyResolver.newMXBeanProxy(getRib(), RIBImplModuleMXBean.class);
96             final BGPDispatcherImplModuleMXBean bgpDispatcherProxy = this.dependencyResolver.newMXBeanProxy(
97                 ribProxy.getBgpDispatcher(), BGPDispatcherImplModuleMXBean.class);
98             final boolean isMd5Supported = bgpDispatcherProxy.getMd5ChannelFactory() != null;
99
100             JmxAttributeValidationException.checkCondition(isMd5Supported,
101                 "Underlying dispatcher does not support MD5 clients", passwordJmxAttribute);
102
103         }
104
105         if (getPeerRole() != null) {
106             final boolean isNotPeerRoleInternal= getPeerRole() != PeerRole.Internal;
107             JmxAttributeValidationException.checkCondition(isNotPeerRoleInternal,
108                 "Internal Peer Role is reserved for Application Peer use.", peerRoleJmxAttribute);
109         }
110     }
111
112     private InetSocketAddress createAddress() {
113         final IpAddress ip = getHost();
114         Preconditions.checkArgument(ip.getIpv4Address() != null || ip.getIpv6Address() != null, "Failed to handle host %s", ip);
115         if (ip.getIpv4Address() != null) {
116             return new InetSocketAddress(InetAddresses.forString(ip.getIpv4Address().getValue()), getPort().getValue());
117         }
118         return new InetSocketAddress(InetAddresses.forString(ip.getIpv6Address().getValue()), getPort().getValue());
119     }
120
121     @Override
122     public java.lang.AutoCloseable createInstance() {
123         final RIB r = getRibDependency();
124
125         final List<BgpParameters> tlvs = getTlvs(r);
126         final AsNumber remoteAs = getAsOrDefault(r);
127         final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), remoteAs, tlvs);
128         final BGPPeer bgpClientPeer;
129         final IpAddress host = getNormalizedHost();
130         if (getPeerRole() != null) {
131             bgpClientPeer = new BGPPeer(peerName(host), r, getPeerRole());
132         } else {
133             bgpClientPeer = new BGPPeer(peerName(host), r, PeerRole.Ibgp);
134         }
135
136         bgpClientPeer.registerRootRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
137
138         getPeerRegistryBackwards().addPeer(host, bgpClientPeer, prefs);
139
140         final BGPPeerModuleTracker moduleTracker = new BGPPeerModuleTracker(r.getOpenConfigProvider());
141         moduleTracker.onInstanceCreate();
142
143         final CloseableNoEx peerCloseable = new CloseableNoEx() {
144             @Override
145             public void close() {
146                 bgpClientPeer.close();
147                 getPeerRegistryBackwards().removePeer(host);
148                 moduleTracker.onInstanceClose();
149             }
150         };
151
152         // Initiate connection
153         if(getInitiateConnection()) {
154             final Future<Void> cf = initiateConnection(createAddress(), getOptionaPassword(getPassword()), getPeerRegistryBackwards());
155             return new CloseableNoEx() {
156                 @Override
157                 public void close() {
158                     cf.cancel(true);
159                     peerCloseable.close();
160                 }
161             };
162         } else {
163             return peerCloseable;
164         }
165     }
166
167     private interface CloseableNoEx extends AutoCloseable {
168         @Override
169         void close();
170     }
171
172     private AsNumber getAsOrDefault(final RIB r) {
173         // Remote AS number defaults to our local AS
174         final AsNumber remoteAs;
175         if (getRemoteAs() != null) {
176             remoteAs = new AsNumber(getRemoteAs());
177         } else {
178             remoteAs = r.getLocalAs();
179         }
180         return remoteAs;
181     }
182
183     private List<BgpParameters> getTlvs(final RIB r) {
184         final List<BgpParameters> tlvs = new ArrayList<>();
185         final List<OptionalCapabilities> caps = new ArrayList<>();
186         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability(
187             new As4BytesCapabilityBuilder().setAsNumber(r.getLocalAs()).build()).build()).build());
188         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
189             new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder().build()).build()).build()).build());
190
191         for (final BgpTableType t : getAdvertizedTableDependency()) {
192             if (!r.getLocalTables().contains(t)) {
193                 LOG.info("RIB instance does not list {} in its local tables. Incoming data will be dropped.", t);
194             }
195
196             caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
197                 new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder(t).build()).build()).build()).build());
198         }
199         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(caps).build());
200         return tlvs;
201     }
202
203     public IpAddress getNormalizedHost() {
204         final IpAddress host = getHost();
205         if(host.getIpv6Address() != null){
206             return new IpAddress(Ipv6Util.getFullForm(host.getIpv6Address()));
207         }
208         return host;
209     }
210
211     private io.netty.util.concurrent.Future<Void> initiateConnection(final InetSocketAddress address, final Optional<Rfc2385Key> password, final BGPPeerRegistry registry) {
212         KeyMapping keys = null;
213         if (password.isPresent()) {
214             keys = new KeyMapping();
215             keys.put(address.getAddress(), password.get().getValue().getBytes(Charsets.US_ASCII));
216         }
217
218         final RIB rib = getRibDependency();
219         final Optional<KeyMapping> optionalKey = Optional.fromNullable(keys);
220         return rib.getDispatcher().createReconnectingClient(address, registry, rib.getTcpStrategyFactory(), optionalKey);
221     }
222
223     private BGPPeerRegistry getPeerRegistryBackwards() {
224         return getPeerRegistry() == null ? StrictBGPPeerRegistry.GLOBAL : getPeerRegistryDependency();
225     }
226
227     private static String peerName(final IpAddress host) {
228         if (host.getIpv4Address() != null) {
229             return host.getIpv4Address().getValue();
230         }
231         if (host.getIpv6Address() != null) {
232             return host.getIpv6Address().getValue();
233         }
234
235         return null;
236     }
237
238     private final class BGPPeerModuleTracker implements BGPConfigModuleTracker {
239
240         private final BGPOpenconfigMapper<BGPPeerInstanceConfiguration> neighborProvider;
241         private final InstanceConfigurationIdentifier identifier;
242
243         public BGPPeerModuleTracker(final Optional<BGPOpenConfigProvider> openconfigProvider) {
244             if (openconfigProvider.isPresent()) {
245                 neighborProvider = openconfigProvider.get().getOpenConfigMapper(BGPPeerInstanceConfiguration.class);
246             } else {
247                 neighborProvider = null;
248             }
249             identifier = new InstanceConfigurationIdentifier(getIdentifier().getInstanceName());
250         }
251
252         @Override
253         public void onInstanceCreate() {
254             if (neighborProvider != null) {
255                 neighborProvider.writeConfiguration(new BGPPeerInstanceConfiguration(identifier, Rev130715Uitl.getIpvAddress(getNormalizedHost()),
256                     Rev130715Uitl.getPort(getPort().getValue()), getHoldtimer(), getPeerRole(), getInitiateConnection(),
257                         getAdvertizedTableDependency(), Rev130715Uitl.getASNumber(getAsOrDefault(getRibDependency()).getValue()),
258                         getOptionaPassword(getPassword())));
259             }
260         }
261
262         @Override
263         public void onInstanceClose() {
264             if (neighborProvider != null) {
265                 neighborProvider.removeConfiguration(identifier);
266             }
267         }
268
269     }
270
271     private Optional<Rfc2385Key> getOptionaPassword(Rfc2385Key password) {
272         return password != null && ! password.getValue().isEmpty() ? Optional.of(password) : Optional.<Rfc2385Key>absent();
273     }
274
275 }