2 * Copyright (c) 2016 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
8 package org.opendaylight.controller.config.yang.bgp.rib.impl;
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.Lists;
12 import io.netty.channel.Channel;
13 import io.netty.channel.ChannelConfig;
14 import io.netty.channel.ChannelFuture;
15 import io.netty.channel.epoll.Epoll;
16 import io.netty.channel.epoll.EpollChannelOption;
17 import io.netty.util.internal.PlatformDependent;
18 import java.net.InetAddress;
19 import java.net.InetSocketAddress;
20 import java.net.UnknownHostException;
21 import java.security.AccessControlException;
22 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
23 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
24 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
25 import org.opendaylight.protocol.bgp.rib.impl.spi.PeerRegistryListener;
26 import org.opendaylight.protocol.concepts.KeyMapping;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
31 * BGP peer acceptor that handles incoming bgp connections.
33 public class BGPPeerAcceptorModule extends org.opendaylight.controller.config.yang.bgp.rib.impl.AbstractBGPPeerAcceptorModule {
35 private static final int PRIVILEGED_PORTS = 1024;
37 public BGPPeerAcceptorModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
38 super(identifier, dependencyResolver);
41 public BGPPeerAcceptorModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerAcceptorModule oldModule, final java.lang.AutoCloseable oldInstance) {
42 super(identifier, dependencyResolver, oldModule, oldInstance);
46 public void customValidation() {
47 // check if unix root user
48 if (!PlatformDependent.isWindows() && !PlatformDependent.isRoot() && getBindingPort().getValue() < PRIVILEGED_PORTS) {
49 throw new AccessControlException("Unable to bind port " + getBindingPort().getValue() + " while running as non-root user.");
51 // Try to parse address
54 } catch (final IllegalArgumentException e) {
55 throw new JmxAttributeValidationException("Unable to resolve configured address", e, Lists.newArrayList(bindingAddressJmxAttribute, bindingPortJmxAttribute));
59 private AutoCloseable listenerRegistration;
62 public java.lang.AutoCloseable createInstance() {
63 final BGPPeerRegistry peerRegistry = getAcceptingPeerRegistryDependency();
64 final ChannelFuture futureChannel = getAcceptingBgpDispatcherDependency().createServer(peerRegistry, getAddress());
66 // Validate future success
67 futureChannel.addListener(future -> {
68 Preconditions.checkArgument(future.isSuccess(), "Unable to start bgp server on %s", getAddress(), future.cause());
69 final Channel channel = futureChannel.channel();
70 if (Epoll.isAvailable()) {
71 BGPPeerAcceptorModule.this.listenerRegistration = peerRegistry.registerPeerRegisterListener(new PeerRegistryListenerImpl(channel.config()));
76 // This closes the acceptor and no new bgp connections will be accepted
77 // Connections already established will be preserved
78 futureChannel.cancel(true);
79 futureChannel.channel().close();
80 if (BGPPeerAcceptorModule.this.listenerRegistration != null) {
81 BGPPeerAcceptorModule.this.listenerRegistration.close();
86 private InetSocketAddress getAddress() {
87 final InetAddress inetAddr;
89 inetAddr = InetAddress.getByName(getBindingAddress()
90 .getIpv4Address() != null ? getBindingAddress()
91 .getIpv4Address().getValue() : getBindingAddress()
92 .getIpv6Address().getValue());
93 } catch (final UnknownHostException e) {
94 throw new IllegalArgumentException("Illegal binding address " + getBindingAddress(), e);
96 return new InetSocketAddress(inetAddr, getBindingPort().getValue());
99 private static final class PeerRegistryListenerImpl implements PeerRegistryListener {
101 private final ChannelConfig channelConfig;
103 private final KeyMapping keys;
105 PeerRegistryListenerImpl(final ChannelConfig channelConfig) {
106 this.channelConfig = channelConfig;
107 this.keys = KeyMapping.getKeyMapping();
111 public void onPeerAdded(final IpAddress ip, final BGPSessionPreferences prefs) {
112 if (prefs.getMd5Password().isPresent()) {
113 this.keys.put(IetfInetUtil.INSTANCE.inetAddressFor(ip), prefs.getMd5Password().get());
114 this.channelConfig.setOption(EpollChannelOption.TCP_MD5SIG, this.keys);
119 public void onPeerRemoved(final IpAddress ip) {
120 if (this.keys.remove(IetfInetUtil.INSTANCE.inetAddressFor(ip)) != null) {
121 this.channelConfig.setOption(EpollChannelOption.TCP_MD5SIG, this.keys);