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