BUG-4070: Define new specific Peer role for App Peer.
[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.Preconditions;
21 import com.google.common.net.InetAddresses;
22 import io.netty.util.concurrent.Future;
23 import java.net.InetSocketAddress;
24 import java.util.ArrayList;
25 import java.util.List;
26 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
27 import org.opendaylight.protocol.bgp.rib.impl.BGPPeer;
28 import org.opendaylight.protocol.bgp.rib.impl.StrictBGPPeerRegistry;
29 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
30 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
31 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
32 import org.opendaylight.tcpmd5.api.KeyMapping;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParametersBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilities;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.GracefulRestartCapabilityBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapabilityBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 /**
51  *
52  */
53 public final class BGPPeerModule extends org.opendaylight.controller.config.yang.bgp.rib.impl.AbstractBGPPeerModule {
54     private static final Logger LOG = LoggerFactory.getLogger(BGPPeerModule.class);
55
56     public BGPPeerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
57         final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
58         super(identifier, dependencyResolver);
59     }
60
61     public BGPPeerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
62         final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final BGPPeerModule oldModule,
63         final java.lang.AutoCloseable oldInstance) {
64
65         super(identifier, dependencyResolver, oldModule, oldInstance);
66     }
67
68     @Override
69     protected void customValidation() {
70         JmxAttributeValidationException.checkNotNull(getHost(), "value is not set.", hostJmxAttribute);
71         JmxAttributeValidationException.checkNotNull(getPort(), "value is not set.", portJmxAttribute);
72
73         if (getPassword() != null) {
74             /*
75              *  This is a nasty hack, but we don't have another clean solution. We cannot allow
76              *  password being set if the injected dispatcher does not have the optional
77              *  md5-server-channel-factory set.
78              *
79              *  FIXME: this is a use case for Module interfaces, e.g. RibImplModule
80              *         should something like isMd5ServerSupported()
81              */
82
83             final RIBImplModuleMXBean ribProxy = this.dependencyResolver.newMXBeanProxy(getRib(), RIBImplModuleMXBean.class);
84             final BGPDispatcherImplModuleMXBean bgpDispatcherProxy = this.dependencyResolver.newMXBeanProxy(
85                 ribProxy.getBgpDispatcher(), BGPDispatcherImplModuleMXBean.class);
86             final boolean isMd5Supported = bgpDispatcherProxy.getMd5ChannelFactory() != null;
87
88             JmxAttributeValidationException.checkCondition(isMd5Supported,
89                 "Underlying dispatcher does not support MD5 clients", passwordJmxAttribute);
90
91         }
92
93         if (getPeerRole() != null) {
94             final boolean isNotPeerRoleInternal= getPeerRole() != PeerRole.Internal;
95             JmxAttributeValidationException.checkCondition(isNotPeerRoleInternal,
96                 "Internal Peer Role is reserved for Application Peer use.", peerRoleJmxAttribute);
97         }
98     }
99
100     private InetSocketAddress createAddress() {
101         final IpAddress ip = getHost();
102         Preconditions.checkArgument(ip.getIpv4Address() != null || ip.getIpv6Address() != null, "Failed to handle host %s", ip);
103         if (ip.getIpv4Address() != null) {
104             return new InetSocketAddress(InetAddresses.forString(ip.getIpv4Address().getValue()), getPort().getValue());
105         }
106         return new InetSocketAddress(InetAddresses.forString(ip.getIpv6Address().getValue()), getPort().getValue());
107     }
108
109     @Override
110     public java.lang.AutoCloseable createInstance() {
111         final RIB r = getRibDependency();
112
113         final List<BgpParameters> tlvs = getTlvs(r);
114         final AsNumber remoteAs = getAsOrDefault(r);
115         final String password = getPasswordOrNull();
116         final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), remoteAs, tlvs);
117         final BGPPeer bgpClientPeer;
118
119         if (getPeerRole() != null) {
120             bgpClientPeer = new BGPPeer(peerName(getHostWithoutValue()), r, getPeerRole());
121         } else {
122             bgpClientPeer = new BGPPeer(peerName(getHostWithoutValue()), r, PeerRole.Ibgp);
123         }
124
125         bgpClientPeer.registerRootRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
126
127         getPeerRegistryBackwards().addPeer(getHostWithoutValue(), bgpClientPeer, prefs);
128
129         final CloseableNoEx peerCloseable = new CloseableNoEx() {
130             @Override
131             public void close() {
132                 bgpClientPeer.close();
133                 getPeerRegistryBackwards().removePeer(getHostWithoutValue());
134             }
135         };
136
137         // Initiate connection
138         if(getInitiateConnection()) {
139             final Future<Void> cf = initiateConnection(createAddress(), password, getPeerRegistryBackwards());
140             return new CloseableNoEx() {
141                 @Override
142                 public void close() {
143                     cf.cancel(true);
144                     peerCloseable.close();
145                 }
146             };
147         } else {
148             return peerCloseable;
149         }
150     }
151
152     private interface CloseableNoEx extends AutoCloseable {
153         @Override
154         void close();
155     }
156
157     private String getPasswordOrNull() {
158         final String password;
159         if (getPassword() != null) {
160             password = getPassword().getValue();
161         } else {
162             password = null;
163         }
164         return password;
165     }
166
167     private AsNumber getAsOrDefault(final RIB r) {
168         // Remote AS number defaults to our local AS
169         final AsNumber remoteAs;
170         if (getRemoteAs() != null) {
171             remoteAs = new AsNumber(getRemoteAs());
172         } else {
173             remoteAs = r.getLocalAs();
174         }
175         return remoteAs;
176     }
177
178     private List<BgpParameters> getTlvs(final RIB r) {
179         final List<BgpParameters> tlvs = new ArrayList<>();
180         final List<OptionalCapabilities> caps = new ArrayList<>();
181         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability(
182             new As4BytesCapabilityBuilder().setAsNumber(r.getLocalAs()).build()).build()).build());
183         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
184             new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder().build()).build()).build()).build());
185
186         for (final BgpTableType t : getAdvertizedTableDependency()) {
187             if (!r.getLocalTables().contains(t)) {
188                 LOG.info("RIB instance does not list {} in its local tables. Incoming data will be dropped.", t);
189             }
190
191             caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
192                 new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder(t).build()).build()).build()).build());
193         }
194         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(caps).build());
195         return tlvs;
196     }
197
198     public IpAddress getHostWithoutValue() {
199         // FIXME we need to remove field "value" from IpAddress since equals does not work as expected when value being present
200         // Remove after this bug is fixed https://bugs.opendaylight.org/show_bug.cgi?id=1276
201         final IpAddress host = super.getHost();
202         Preconditions.checkArgument(host.getIpv4Address() != null || host.getIpv6Address() != null, "Unexpected host %s", host);
203         if(host.getIpv4Address() != null) {
204             return new IpAddress(host.getIpv4Address());
205         }
206         return new IpAddress(host.getIpv6Address());
207     }
208
209     private io.netty.util.concurrent.Future<Void> initiateConnection(final InetSocketAddress address, final String password, final BGPPeerRegistry registry) {
210         final KeyMapping keys;
211         if (password != null) {
212             keys = new KeyMapping();
213             keys.put(address.getAddress(), password.getBytes(Charsets.US_ASCII));
214         } else {
215             keys = null;
216         }
217
218         final RIB rib = getRibDependency();
219         return rib.getDispatcher().createReconnectingClient(address, registry, rib.getTcpStrategyFactory(), keys);
220     }
221
222     private BGPPeerRegistry getPeerRegistryBackwards() {
223         return getPeerRegistry() == null ? StrictBGPPeerRegistry.GLOBAL : getPeerRegistryDependency();
224     }
225
226     private static String peerName(final IpAddress host) {
227         if (host.getIpv4Address() != null) {
228             return host.getIpv4Address().getValue();
229         }
230         if (host.getIpv6Address() != null) {
231             return host.getIpv6Address().getValue();
232         }
233
234         return null;
235     }
236
237 }