BUG-3888 : fix comparing ASnumbers
[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
94     private InetSocketAddress createAddress() {
95         final IpAddress ip = getHost();
96         Preconditions.checkArgument(ip.getIpv4Address() != null || ip.getIpv6Address() != null, "Failed to handle host %s", ip);
97         if (ip.getIpv4Address() != null) {
98             return new InetSocketAddress(InetAddresses.forString(ip.getIpv4Address().getValue()), getPort().getValue());
99         }
100         return new InetSocketAddress(InetAddresses.forString(ip.getIpv6Address().getValue()), getPort().getValue());
101     }
102
103     @Override
104     public java.lang.AutoCloseable createInstance() {
105         final RIB r = getRibDependency();
106
107         final List<BgpParameters> tlvs = getTlvs(r);
108         final AsNumber remoteAs = getAsOrDefault(r);
109         final String password = getPasswordOrNull();
110         final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), remoteAs, tlvs);
111         final BGPPeer bgpClientPeer;
112         if (getPeerRole() != null) {
113             bgpClientPeer = new BGPPeer(peerName(getHostWithoutValue()), r, getPeerRole());
114         } else {
115             bgpClientPeer = new BGPPeer(peerName(getHostWithoutValue()), r, PeerRole.Ibgp);
116         }
117
118         bgpClientPeer.registerRootRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
119
120         getPeerRegistryBackwards().addPeer(getHostWithoutValue(), bgpClientPeer, prefs);
121
122         final CloseableNoEx peerCloseable = new CloseableNoEx() {
123             @Override
124             public void close() {
125                 bgpClientPeer.close();
126                 getPeerRegistryBackwards().removePeer(getHostWithoutValue());
127             }
128         };
129
130         // Initiate connection
131         if(getInitiateConnection()) {
132             final Future<Void> cf = initiateConnection(createAddress(), password, remoteAs, getPeerRegistryBackwards());
133             return new CloseableNoEx() {
134                 @Override
135                 public void close() {
136                     cf.cancel(true);
137                     peerCloseable.close();
138                 }
139             };
140         } else {
141             return peerCloseable;
142         }
143     }
144
145     private interface CloseableNoEx extends AutoCloseable {
146         @Override
147         void close();
148     }
149
150     private String getPasswordOrNull() {
151         final String password;
152         if (getPassword() != null) {
153             password = getPassword().getValue();
154         } else {
155             password = null;
156         }
157         return password;
158     }
159
160     private AsNumber getAsOrDefault(final RIB r) {
161         // Remote AS number defaults to our local AS
162         final AsNumber remoteAs;
163         if (getRemoteAs() != null) {
164             remoteAs = new AsNumber(getRemoteAs());
165         } else {
166             remoteAs = r.getLocalAs();
167         }
168         return remoteAs;
169     }
170
171     private List<BgpParameters> getTlvs(final RIB r) {
172         final List<BgpParameters> tlvs = new ArrayList<>();
173         final List<OptionalCapabilities> caps = new ArrayList<>();
174         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability(
175             new As4BytesCapabilityBuilder().setAsNumber(r.getLocalAs()).build()).build()).build());
176         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
177             new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder().build()).build()).build()).build());
178
179         for (final BgpTableType t : getAdvertizedTableDependency()) {
180             if (!r.getLocalTables().contains(t)) {
181                 LOG.info("RIB instance does not list {} in its local tables. Incoming data will be dropped.", t);
182             }
183
184             caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
185                 new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder(t).build()).build()).build()).build());
186         }
187         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(caps).build());
188         return tlvs;
189     }
190
191     public IpAddress getHostWithoutValue() {
192         // FIXME we need to remove field "value" from IpAddress since equals does not work as expected when value being present
193         // Remove after this bug is fixed https://bugs.opendaylight.org/show_bug.cgi?id=1276
194         final IpAddress host = super.getHost();
195         Preconditions.checkArgument(host.getIpv4Address() != null || host.getIpv6Address() != null, "Unexpected host %s", host);
196         if(host.getIpv4Address() != null) {
197             return new IpAddress(host.getIpv4Address());
198         }
199         return new IpAddress(host.getIpv6Address());
200     }
201
202     private io.netty.util.concurrent.Future<Void> initiateConnection(final InetSocketAddress address, final String password, final AsNumber remoteAs, final BGPPeerRegistry registry) {
203         final KeyMapping keys;
204         if (password != null) {
205             keys = new KeyMapping();
206             keys.put(address.getAddress(), password.getBytes(Charsets.US_ASCII));
207         } else {
208             keys = null;
209         }
210
211         final RIB rib = getRibDependency();
212         return rib.getDispatcher().createReconnectingClient(address, remoteAs, registry, rib.getTcpStrategyFactory(), keys);
213     }
214
215     private BGPPeerRegistry getPeerRegistryBackwards() {
216         return getPeerRegistry() == null ? StrictBGPPeerRegistry.GLOBAL : getPeerRegistryDependency();
217     }
218
219     private static String peerName(final IpAddress host) {
220         if (host.getIpv4Address() != null) {
221             return host.getIpv4Address().getValue();
222         }
223         if (host.getIpv6Address() != null) {
224             return host.getIpv6Address().getValue();
225         }
226
227         return null;
228     }
229
230 }