Bug 5566: BGP listener TCP MD5 support is not working 35/41935/1
authorMilos Fabian <milfabia@cisco.com>
Tue, 22 Mar 2016 10:42:45 +0000 (11:42 +0100)
committerMilos Fabian <milfabia@cisco.com>
Sun, 17 Jul 2016 23:08:55 +0000 (01:08 +0200)
The BGP server have to be aware of all configured peers
MD5 keys.
Update (add/remove) server's keys whenever a peer is
configured/disconfigured by listening to the PeerRegistry
changes.

Change-Id: Ie9cab438a6d4358a08465e1bd9d7df28d923187f
Signed-off-by: Milos Fabian <milfabia@cisco.com>
14 files changed:
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPApplicationPeerModule.java
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerAcceptorModule.java
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/StrictBgpPeerRegistryModule.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPDispatcherImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/StrictBGPPeerRegistry.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPPeerRegistry.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionPreferences.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/PeerRegistryListener.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BGPDispatcherImplTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/FSMTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/StrictBGPPeerRegistryTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/TestClientDispatcher.java
bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/BGPPeerBuilder.java

index 8430e15eea7bae6298d3d4994a9b8d253e871931..8ee1bb7a1e9097b4f4e440d057216fba99ec3246 100755 (executable)
@@ -63,15 +63,12 @@ public class BGPApplicationPeerModule extends org.opendaylight.controller.config
         final AppPeerModuleTracker appPeerMT = new AppPeerModuleTracker(getTargetRibDependency().getOpenConfigProvider());
         final ApplicationPeer appPeer = new ApplicationPeer(getApplicationRibId(), getBgpPeerId(), (RIBImpl) getTargetRibDependency(), appPeerMT);
         final ListenerRegistration<ApplicationPeer> listenerRegistration = service.registerDataTreeChangeListener(
-            new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, id), appPeer);
-
-        return new CloseableNoEx() {
-            @Override
-            public void close() {
-                listenerRegistration.close();
-                appPeer.close();
-                removeFromPeerRegistry();
-            }
+                new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, id), appPeer);
+
+        return () -> {
+            listenerRegistration.close();
+            appPeer.close();
+            removeFromPeerRegistry();
         };
     }
 
@@ -87,7 +84,7 @@ public class BGPApplicationPeerModule extends org.opendaylight.controller.config
         final BGPPeer bgpClientPeer = new BGPPeer(bgpPeerId.getIpv4Address().getValue(), r, PeerRole.Internal, SimpleRoutingPolicy.AnnounceNone, null);
 
         final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), 0, r.getBgpIdentifier(),
-            r.getLocalAs(), Collections.emptyList());
+                r.getLocalAs(), Collections.emptyList(), Optional.absent());
 
         final BGPPeerRegistry peerRegistry = getPeerRegistryBackwards();
         peerRegistry.addPeer(bgpPeerId, bgpClientPeer, prefs);
index fd7cc165fee42f4154e18bd08ffbe9511fd834b8..8b207612115c2c43585b3da51dba66f1c8ca07e6 100644 (file)
@@ -9,19 +9,27 @@ package org.opendaylight.controller.config.yang.bgp.rib.impl;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelConfig;
 import io.netty.channel.ChannelFuture;
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.GenericFutureListener;
+import io.netty.channel.epoll.Epoll;
+import io.netty.channel.epoll.EpollChannelOption;
 import io.netty.util.internal.PlatformDependent;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.security.AccessControlException;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.PeerRegistryListener;
+import org.opendaylight.protocol.concepts.KeyMapping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 
 /**
-* BGP peer acceptor that handles incoming bgp connections.
-*/
+ * BGP peer acceptor that handles incoming bgp connections.
+ */
 public class BGPPeerAcceptorModule extends org.opendaylight.controller.config.yang.bgp.rib.impl.AbstractBGPPeerAcceptorModule {
 
     private static final int PRIVILEGED_PORTS = 1024;
@@ -48,25 +56,29 @@ public class BGPPeerAcceptorModule extends org.opendaylight.controller.config.ya
         }
     }
 
+    private AutoCloseable listenerRegistration;
+
     @Override
     public java.lang.AutoCloseable createInstance() {
-        final ChannelFuture future = getAcceptingBgpDispatcherDependency().createServer(getAcceptingPeerRegistryDependency(), getAddress());
+        final BGPPeerRegistry peerRegistry = getAcceptingPeerRegistryDependency();
+        final ChannelFuture futureChannel = getAcceptingBgpDispatcherDependency().createServer(peerRegistry, getAddress());
 
         // Validate future success
-        future.addListener(new GenericFutureListener<Future<Void>>() {
-            @Override
-            public void operationComplete(final Future<Void> future) {
-                Preconditions.checkArgument(future.isSuccess(), "Unable to start bgp server on %s", getAddress(), future.cause());
+        futureChannel.addListener(future -> {
+            Preconditions.checkArgument(future.isSuccess(), "Unable to start bgp server on %s", getAddress(), future.cause());
+            final Channel channel = futureChannel.channel();
+            if (Epoll.isAvailable()) {
+                BGPPeerAcceptorModule.this.listenerRegistration = peerRegistry.registerPeerRegisterListener(new PeerRegistryListenerImpl(channel.config()));
             }
         });
 
-        return new AutoCloseable() {
-            @Override
-            public void close() {
-                // This closes the acceptor and no new bgp connections will be accepted
-                // Connections already established will be preserved
-                future.cancel(true);
-                future.channel().close();
+        return () -> {
+            // This closes the acceptor and no new bgp connections will be accepted
+            // Connections already established will be preserved
+            futureChannel.cancel(true);
+            futureChannel.channel().close();
+            if (BGPPeerAcceptorModule.this.listenerRegistration != null) {
+                BGPPeerAcceptorModule.this.listenerRegistration.close();
             }
         };
     }
@@ -76,12 +88,40 @@ public class BGPPeerAcceptorModule extends org.opendaylight.controller.config.ya
         try {
             inetAddr = InetAddress.getByName(getBindingAddress()
                     .getIpv4Address() != null ? getBindingAddress()
-                    .getIpv4Address().getValue() : getBindingAddress()
-                    .getIpv6Address().getValue());
+                            .getIpv4Address().getValue() : getBindingAddress()
+                            .getIpv6Address().getValue());
         } catch (final UnknownHostException e) {
             throw new IllegalArgumentException("Illegal binding address " + getBindingAddress(), e);
         }
         return new InetSocketAddress(inetAddr, getBindingPort().getValue());
     }
 
+    private static final class PeerRegistryListenerImpl implements PeerRegistryListener {
+
+        private final ChannelConfig channelConfig;
+
+        private final KeyMapping keys;
+
+        PeerRegistryListenerImpl(final ChannelConfig channelConfig) {
+            this.channelConfig = channelConfig;
+            this.keys = KeyMapping.getKeyMapping();
+        }
+
+        @Override
+        public void onPeerAdded(final IpAddress ip, final BGPSessionPreferences prefs) {
+            if (prefs.getMd5Password().isPresent()) {
+                this.keys.put(IetfInetUtil.INSTANCE.inetAddressFor(ip), prefs.getMd5Password().get());
+                this.channelConfig.setOption(EpollChannelOption.TCP_MD5SIG, this.keys);
+            }
+        }
+
+        @Override
+        public void onPeerRemoved(final IpAddress ip) {
+            if (this.keys.remove(IetfInetUtil.INSTANCE.inetAddressFor(ip)) != null) {
+                this.channelConfig.setOption(EpollChannelOption.TCP_MD5SIG, this.keys);
+            }
+        }
+
+    }
+
 }
index 06cf2986053bd1fda73f9c3e61daf8f5ac1007d5..856dd59cf44b9ed863231ed575e8dd07d26b9088 100755 (executable)
@@ -16,6 +16,7 @@
  */
 package org.opendaylight.controller.config.yang.bgp.rib.impl;
 
+import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.net.InetAddresses;
@@ -43,7 +44,6 @@ import org.opendaylight.protocol.concepts.KeyMapping;
 import org.opendaylight.protocol.util.Ipv6Util;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilities;
@@ -69,13 +69,13 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
     private static final Logger LOG = LoggerFactory.getLogger(BGPPeerModule.class);
 
     public BGPPeerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
-        final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
     public BGPPeerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
-        final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final BGPPeerModule oldModule,
-        final java.lang.AutoCloseable oldInstance) {
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final BGPPeerModule oldModule,
+            final java.lang.AutoCloseable oldInstance) {
 
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
@@ -85,14 +85,14 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
         final IpAddress host = getHost();
         JmxAttributeValidationException.checkNotNull(host, "value is not set.", hostJmxAttribute);
         JmxAttributeValidationException.checkCondition(host.getIpv4Address() != null || host.getIpv6Address() != null,
-            "Unexpected host", hostJmxAttribute);
+                "Unexpected host", hostJmxAttribute);
 
         JmxAttributeValidationException.checkNotNull(getPort(), "value is not set.", portJmxAttribute);
 
         if (getPeerRole() != null) {
             final boolean isNotPeerRoleInternal= getPeerRole() != PeerRole.Internal;
             JmxAttributeValidationException.checkCondition(isNotPeerRoleInternal,
-                "Internal Peer Role is reserved for Application Peer use.", peerRoleJmxAttribute);
+                    "Internal Peer Role is reserved for Application Peer use.", peerRoleJmxAttribute);
         }
 
         if (getOptionalPassword(getPassword()).isPresent()) {
@@ -117,7 +117,8 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
 
         final List<BgpParameters> tlvs = getTlvs(r);
         final AsNumber remoteAs = getAsOrDefault(r);
-        final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), remoteAs, tlvs);
+        final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), remoteAs, tlvs,
+                getMD5Password(getPassword()));
         final BGPPeer bgpClientPeer;
         final IpAddress host = getNormalizedHost();
         if (getPeerRole() != null) {
@@ -133,24 +134,18 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
         final BGPPeerModuleTracker moduleTracker = new BGPPeerModuleTracker(r.getOpenConfigProvider());
         moduleTracker.onInstanceCreate();
 
-        final CloseableNoEx peerCloseable = new CloseableNoEx() {
-            @Override
-            public void close() {
-                bgpClientPeer.close();
-                getPeerRegistryBackwards().removePeer(host);
-                moduleTracker.onInstanceClose();
-            }
+        final CloseableNoEx peerCloseable = () -> {
+            bgpClientPeer.close();
+            getPeerRegistryBackwards().removePeer(host);
+            moduleTracker.onInstanceClose();
         };
 
         // Initiate connection
         if(getInitiateConnection()) {
             final Future<Void> cf = initiateConnection(createAddress(), getOptionalPassword(getPassword()), getPeerRegistryBackwards());
-            return new CloseableNoEx() {
-                @Override
-                public void close() {
-                    cf.cancel(true);
-                    peerCloseable.close();
-                }
+            return () -> {
+                cf.cancel(true);
+                peerCloseable.close();
             };
         } else {
             return peerCloseable;
@@ -177,9 +172,9 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
         final List<BgpParameters> tlvs = new ArrayList<>();
         final List<OptionalCapabilities> caps = new ArrayList<>();
         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability(
-            new As4BytesCapabilityBuilder().setAsNumber(r.getLocalAs()).build()).build()).build());
+                new As4BytesCapabilityBuilder().setAsNumber(r.getLocalAs()).build()).build()).build());
         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
-            new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder().build()).build()).build()).build());
+                new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder().build()).build()).build()).build());
 
         if (getRouteRefresh()) {
             caps.add(new OptionalCapabilitiesBuilder().setCParameters(MultiprotocolCapabilitiesUtil.RR_CAPABILITY).build());
@@ -188,7 +183,7 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
         if (!getAddPathDependency().isEmpty()) {
             final List<AddressFamilies> addPathFamilies = filterAddPathDependency(getAddPathDependency());
             caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
-                new CParameters1Builder().setAddPathCapability(new AddPathCapabilityBuilder().setAddressFamilies(addPathFamilies).build()).build()).build()).build());
+                    new CParameters1Builder().setAddPathCapability(new AddPathCapabilityBuilder().setAddressFamilies(addPathFamilies).build()).build()).build()).build());
         }
 
         for (final BgpTableType t : getAdvertizedTableDependency()) {
@@ -197,7 +192,7 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
             }
 
             caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
-                new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder(t).build()).build()).build()).build());
+                    new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder(t).build()).build()).build()).build());
         }
         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(caps).build());
         return tlvs;
@@ -225,7 +220,7 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
     }
 
     private io.netty.util.concurrent.Future<Void> initiateConnection(final InetSocketAddress address, final Optional<Rfc2385Key> password, final BGPPeerRegistry registry) {
-        KeyMapping keys = KeyMapping.getKeyMapping(address.getAddress(), password);
+        final KeyMapping keys = KeyMapping.getKeyMapping(address.getAddress(), password);
         final RIB rib = getRibDependency();
         final Optional<KeyMapping> optionalKey = Optional.fromNullable(keys);
         return rib.getDispatcher().createReconnectingClient(address, registry, getRetrytimer(), optionalKey);
@@ -259,9 +254,9 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
             }
             final InstanceConfigurationIdentifier identifier = new InstanceConfigurationIdentifier(getIdentifier().getInstanceName());
             this.bgpPeerInstanceConfiguration = new BGPPeerInstanceConfiguration(identifier, getNormalizedHost(),
-                        getPort(), getHoldtimer(), getPeerRole(), getInitiateConnection(),
-                        getAdvertizedTableDependency(), getAsOrDefault(getRibDependency()),
-                        getOptionalPassword(getPassword()), getAddPathDependency());
+                    getPort(), getHoldtimer(), getPeerRole(), getInitiateConnection(),
+                    getAdvertizedTableDependency(), getAsOrDefault(getRibDependency()),
+                    getOptionalPassword(getPassword()), getAddPathDependency());
         }
 
         @Override
@@ -280,8 +275,12 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
 
     }
 
-    private Optional<Rfc2385Key> getOptionalPassword(final Rfc2385Key password) {
+    private static Optional<Rfc2385Key> getOptionalPassword(final Rfc2385Key password) {
         return password != null && ! password.getValue().isEmpty() ? Optional.of(password) : Optional.<Rfc2385Key>absent();
     }
 
+    private static Optional<byte[]> getMD5Password(final Rfc2385Key password) {
+        return getOptionalPassword(password).isPresent() ? Optional.of(password.getValue().getBytes(Charsets.US_ASCII)) : Optional.absent();
+    }
+
 }
index c2ceb8367e3c5d07a3c39df78ab21c86a51530da..e0d3e015c0ca1c7c28ced8b75f9abd81c9d28565 100644 (file)
@@ -15,10 +15,10 @@ import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
 import org.osgi.framework.BundleContext;
 
 /**
-* Registry of BGP peers that allows only one connection per 2 peers
-*
-* @deprecated Replaced by blueprint wiring
-*/
+ * Registry of BGP peers that allows only one connection per 2 peers
+ *
+ * @deprecated Replaced by blueprint wiring
+ */
 @Deprecated
 public class StrictBgpPeerRegistryModule extends org.opendaylight.controller.config.yang.bgp.rib.impl.AbstractStrictBgpPeerRegistryModule {
     private BundleContext bundleContext;
@@ -39,12 +39,12 @@ public class StrictBgpPeerRegistryModule extends org.opendaylight.controller.con
     @Override
     public java.lang.AutoCloseable createInstance() {
         final WaitingServiceTracker<BGPPeerRegistry> tracker =
-                WaitingServiceTracker.create(BGPPeerRegistry.class, bundleContext);
+                WaitingServiceTracker.create(BGPPeerRegistry.class, this.bundleContext);
         final BGPPeerRegistry service = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
 
         return Reflection.newProxy(BGPPeerRegistry.class, new AbstractInvocationHandler() {
             @Override
-            protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
+            protected Object handleInvocation(final Object proxy, final Method method, final Object[] args) throws Throwable {
                 if (method.getName().equals("close")) {
                     tracker.close();
                     return null;
@@ -55,7 +55,7 @@ public class StrictBgpPeerRegistryModule extends org.opendaylight.controller.con
         });
     }
 
-    void setBundleContext(BundleContext bundleContext) {
+    void setBundleContext(final BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
 }
index bcd48ea277f928e7ead36183bafb3045368deea2..674f77a438197f6b9545bede745476d42975a457 100755 (executable)
@@ -72,7 +72,7 @@ public class BGPDispatcherImpl implements BGPDispatcher, AutoCloseable {
     }
 
     private Future<BGPSessionImpl> createClient(final InetSocketAddress remoteAddress, final BGPPeerRegistry listener, final int retryTimer,
-        final Bootstrap clientBootStrap) {
+            final Bootstrap clientBootStrap) {
         final BGPClientSessionNegotiatorFactory snf = new BGPClientSessionNegotiatorFactory(listener);
         final ChannelPipelineInitializer initializer = BGPChannel.createChannelPipelineInitializer(BGPDispatcherImpl.this.handlerFactory, snf);
 
@@ -84,7 +84,7 @@ public class BGPDispatcherImpl implements BGPDispatcher, AutoCloseable {
     }
 
     public Future<BGPSessionImpl> createClient(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress,
-        final StrictBGPPeerRegistry strictBGPPeerRegistry, final int retryTimer) {
+            final StrictBGPPeerRegistry strictBGPPeerRegistry, final int retryTimer) {
         final Bootstrap clientBootStrap = createClientBootStrap(Optional.<KeyMapping>absent(), this.workerGroup);
         clientBootStrap.localAddress(localAddress);
         return createClient(remoteAddress, strictBGPPeerRegistry, retryTimer, clientBootStrap);
@@ -132,7 +132,7 @@ public class BGPDispatcherImpl implements BGPDispatcher, AutoCloseable {
         final BGPClientSessionNegotiatorFactory snf = new BGPClientSessionNegotiatorFactory(peerRegistry);
         final Bootstrap bootstrap = createClientBootStrap(keys, this.workerGroup);
         final BGPReconnectPromise reconnectPromise = new BGPReconnectPromise(GlobalEventExecutor.INSTANCE, remoteAddress,
-            retryTimer, bootstrap, BGPChannel.createChannelPipelineInitializer(BGPDispatcherImpl.this.handlerFactory, snf));
+                retryTimer, bootstrap, BGPChannel.createChannelPipelineInitializer(BGPDispatcherImpl.this.handlerFactory, snf));
         reconnectPromise.connect();
         return reconnectPromise;
     }
@@ -141,17 +141,16 @@ public class BGPDispatcherImpl implements BGPDispatcher, AutoCloseable {
     public ChannelFuture createServer(final BGPPeerRegistry registry, final InetSocketAddress localAddress) {
         final BGPServerSessionNegotiatorFactory snf = new BGPServerSessionNegotiatorFactory(registry);
         final ChannelPipelineInitializer initializer = BGPChannel.createChannelPipelineInitializer(BGPDispatcherImpl.this.handlerFactory, snf);
-        final ServerBootstrap serverBootstrap = createServerBootstrap(initializer, Optional.<KeyMapping>absent(), this.bossGroup, this.workerGroup);
+        final ServerBootstrap serverBootstrap = createServerBootstrap(initializer, this.bossGroup, this.workerGroup);
         final ChannelFuture channelFuture = serverBootstrap.bind(localAddress);
         LOG.debug("Initiated server {} at {}.", channelFuture, localAddress);
         return channelFuture;
     }
 
-    public static ServerBootstrap createServerBootstrap(final ChannelPipelineInitializer initializer, final Optional<KeyMapping> keys,
-        final EventLoopGroup bossGroup, final EventLoopGroup workerGroup) {
+    public static ServerBootstrap createServerBootstrap(final ChannelPipelineInitializer initializer,
+            final EventLoopGroup bossGroup, final EventLoopGroup workerGroup) {
         final ServerBootstrap serverBootstrap = new ServerBootstrap();
         if (Epoll.isAvailable()) {
-            //FIXME Bug-5566
             serverBootstrap.channel(EpollServerSocketChannel.class);
         } else {
             serverBootstrap.channel(NioServerSocketChannel.class);
@@ -163,13 +162,6 @@ public class BGPDispatcherImpl implements BGPDispatcher, AutoCloseable {
         serverBootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
         serverBootstrap.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, HIGH_WATER_MARK);
         serverBootstrap.childOption(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK, LOW_WATER_MARK);
-        if (keys.isPresent()) {
-            if (Epoll.isAvailable()) {
-                serverBootstrap.option(EpollChannelOption.TCP_MD5SIG, keys.get());
-            } else {
-                throw new UnsupportedOperationException(Epoll.unavailabilityCause().getCause());
-            }
-        }
 
         // Make sure we are doing round-robin processing
         serverBootstrap.option(ChannelOption.MAX_MESSAGES_PER_READ, 1);
@@ -188,14 +180,11 @@ public class BGPDispatcherImpl implements BGPDispatcher, AutoCloseable {
         }
 
         public static <S extends BGPSession, T extends BGPSessionNegotiatorFactory> ChannelPipelineInitializer
-            createChannelPipelineInitializer(final BGPHandlerFactory hf, final T snf) {
-            return new ChannelPipelineInitializer<S>() {
-                @Override
-                public void initializeChannel(final SocketChannel channel, final Promise<S> promise) {
-                    channel.pipeline().addLast(hf.getDecoders());
-                    channel.pipeline().addLast(NEGOTIATOR, snf.getSessionNegotiator(channel, promise));
-                    channel.pipeline().addLast(hf.getEncoders());
-                }
+        createChannelPipelineInitializer(final BGPHandlerFactory hf, final T snf) {
+            return (channel, promise) -> {
+                channel.pipeline().addLast(hf.getDecoders());
+                channel.pipeline().addLast(NEGOTIATOR, snf.getSessionNegotiator(channel, promise));
+                channel.pipeline().addLast(hf.getEncoders());
             };
         }
 
index 944ca0a843a47337700bb9f3650c15dd7314fd39..3924a63de3549b64c54f13d3504c8819a8c9aa08 100644 (file)
@@ -21,8 +21,11 @@ import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
 import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.ThreadSafe;
 import org.opendaylight.protocol.bgp.parser.AsNumberUtil;
@@ -31,6 +34,7 @@ import org.opendaylight.protocol.bgp.parser.BGPError;
 import org.opendaylight.protocol.bgp.parser.impl.message.open.As4CapabilityHandler;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.PeerRegistryListener;
 import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
@@ -42,6 +46,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParameters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapability;
+import org.opendaylight.yangtools.concepts.AbstractRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,6 +69,8 @@ public final class StrictBGPPeerRegistry implements BGPPeerRegistry {
     private final Map<IpAddress, BGPSessionId> sessionIds = Maps.newHashMap();
     @GuardedBy("this")
     private final Map<IpAddress, BGPSessionPreferences> peerPreferences = Maps.newHashMap();
+    @GuardedBy("this")
+    private final Set<PeerRegistryListener> listeners = new HashSet<>();
 
     public static BGPPeerRegistry instance() {
         return GLOBAL;
@@ -79,12 +86,18 @@ public final class StrictBGPPeerRegistry implements BGPPeerRegistry {
         Preconditions.checkNotNull(preferences.getParams());
         Preconditions.checkNotNull(preferences.getBgpId());
         this.peerPreferences.put(ip, preferences);
+        for (final PeerRegistryListener peerRegistryListener : this.listeners) {
+            peerRegistryListener.onPeerAdded(ip, preferences);
+        }
     }
 
     @Override
     public synchronized void removePeer(final IpAddress ip) {
         Preconditions.checkNotNull(ip);
         this.peers.remove(ip);
+        for (final PeerRegistryListener peerRegistryListener : this.listeners) {
+            peerRegistryListener.onPeerRemoved(ip);
+        }
     }
 
     @Override
@@ -323,4 +336,20 @@ public final class StrictBGPPeerRegistry implements BGPPeerRegistry {
                 .toString();
         }
     }
+
+    @Override
+    public synchronized AutoCloseable registerPeerRegisterListener(final PeerRegistryListener listener) {
+        this.listeners.add(listener);
+        for (final Entry<IpAddress, BGPSessionPreferences> entry : this.peerPreferences.entrySet()) {
+            listener.onPeerAdded(entry.getKey(), entry.getValue());
+        }
+        return new AbstractRegistration() {
+            @Override
+            protected void removeRegistration() {
+                synchronized (StrictBGPPeerRegistry.this) {
+                    StrictBGPPeerRegistry.this.listeners.remove(listener);
+                }
+            }
+        };
+    }
 }
\ No newline at end of file
index 7c55d9551f8e424123fc08414a2a1f9d163f8866..0dcc142b2f673d7439db8cbab419c74842ae91cc 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.protocol.bgp.rib.impl.spi;
 
+import javax.annotation.Nonnull;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
@@ -73,4 +74,14 @@ public interface BGPPeerRegistry extends AutoCloseable {
      */
     BGPSessionPreferences getPeerPreferences(IpAddress ip);
 
+    /**
+     * Register PeerRegistryListener, which listens to the changes in peer
+     * registry (add peer, remove peer). After registration, an initial
+     * drop is provided by calling onPeerAdded().
+     *
+     * @param listener The PeerRegistryListener to be registered.
+     * @return Registration ticked, used for closing of registration.
+     */
+    @Nonnull AutoCloseable registerPeerRegisterListener(@Nonnull PeerRegistryListener listener);
+
 }
index 0bfb76a6daae60b0ecd8fcf73963ef462f37778c..8cd987a56568f32537c2fb316fdafb42f97dc8a2 100644 (file)
@@ -7,9 +7,9 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl.spi;
 
+import com.google.common.base.Optional;
 import java.util.List;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
 
@@ -28,6 +28,8 @@ public final class BGPSessionPreferences {
 
     private final AsNumber remoteAs;
 
+    private final Optional<byte[]> md5Password;
+
     /**
      * Creates a new DTO for Open message.
      *
@@ -38,12 +40,13 @@ public final class BGPSessionPreferences {
      * @param params list of advertised parameters
      */
     public BGPSessionPreferences(final AsNumber as, final int hold, final BgpId bgpId, final AsNumber remoteAs,
-        final List<BgpParameters> params) {
+            final List<BgpParameters> params, final Optional<byte[]> md5Password) {
         this.as = as;
         this.hold = hold;
         this.bgpId = (bgpId != null) ? new BgpId(bgpId) : null;
         this.remoteAs = remoteAs;
         this.params = params;
+        this.md5Password = md5Password;
     }
 
     /**
@@ -90,4 +93,12 @@ public final class BGPSessionPreferences {
     public List<BgpParameters> getParams() {
         return this.params;
     }
+
+    /**
+     * Optionally returns peer's MD5 password.
+     * @return Encoded MD5 password.
+     */
+    public Optional<byte[]> getMd5Password() {
+        return this.md5Password;
+    }
 }
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/PeerRegistryListener.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/PeerRegistryListener.java
new file mode 100644 (file)
index 0000000..112c319
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+
+/**
+ * Listens to the changes in a PeerRegisty.
+ *
+ */
+public interface PeerRegistryListener {
+
+    /**
+     * Invoked when new peer is added into the registry.
+     * @param ip The new peer's IP address.
+     * @param prefs The new peer's preferences.
+     */
+    void onPeerAdded(@Nonnull IpAddress ip, @Nonnull BGPSessionPreferences prefs);
+
+    /**
+     * Invoked when peer is removed from registry.
+     * @param ip The removed peer's IP address.
+     */
+    void onPeerRemoved(@Nonnull IpAddress ip);
+
+}
index 0c6862ed9132dc2fc1256ff8166b11470f9bc243..08e2840fdb0053ac70525a5468c3450b45d35e74 100755 (executable)
@@ -19,7 +19,6 @@ import io.netty.channel.epoll.Epoll;
 import io.netty.channel.epoll.EpollEventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.GenericFutureListener;
 import java.net.InetSocketAddress;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
@@ -97,12 +96,7 @@ public class BGPDispatcherImplTest {
         this.registry.addPeer(new IpAddress(new Ipv4Address(serverAddress.getAddress().getHostAddress())), this.serverListener, createPreferences(serverAddress));
         LoggerFactory.getLogger(BGPDispatcherImplTest.class).info("createServer");
         final ChannelFuture future = this.serverDispatcher.createServer(this.registry, serverAddress);
-        future.addListener(new GenericFutureListener<Future<Void>>() {
-            @Override
-            public void operationComplete(final Future<Void> future) {
-                Preconditions.checkArgument(future.isSuccess(), "Unable to start bgp server on %s", future.cause());
-            }
-        });
+        future.addListener(future1 -> Preconditions.checkArgument(future1.isSuccess(), "Unable to start bgp server on %s", future1.cause()));
         return future.channel();
     }
 
@@ -149,13 +143,13 @@ public class BGPDispatcherImplTest {
         final List<BgpParameters> tlvs = Lists.newArrayList();
         final List<OptionalCapabilities> capas = Lists.newArrayList();
         capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(
-            CParameters1.class, new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
+                CParameters1.class, new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
                 .setAfi(IPV_4_TT.getAfi()).setSafi(IPV_4_TT.getSafi()).build()).build())
-            .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(new AsNumber(30L)).build())
-            .build()).build());
+                .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(new AsNumber(30L)).build())
+                .build()).build());
         capas.add(new OptionalCapabilitiesBuilder().setCParameters(BgpExtendedMessageUtil.EXTENDED_MESSAGE_CAPABILITY).build());
         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
-        return new BGPSessionPreferences(AS_NUMBER, (short) 4, new BgpId(socketAddress.getAddress().getHostAddress()), AS_NUMBER, tlvs);
+        return new BGPSessionPreferences(AS_NUMBER, (short) 4, new BgpId(socketAddress.getAddress().getHostAddress()), AS_NUMBER, tlvs, Optional.absent());
     }
 
 }
index 82c9967815c420eb4c17ecbf3e44c5e3f44dde3a..f6df4343d8b23e236e7bbb7891d4e7366435b62f 100644 (file)
@@ -15,6 +15,7 @@ import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
@@ -111,7 +112,8 @@ public class FSMTest {
 
 
         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
-        final BGPSessionPreferences prefs = new BGPSessionPreferences(new AsNumber(30L), (short) 3, new BgpId("1.1.1.1"), new AsNumber(30L), tlvs);
+        final BGPSessionPreferences prefs = new BGPSessionPreferences(new AsNumber(30L), (short) 3, new BgpId("1.1.1.1"), new AsNumber(30L), tlvs,
+                Optional.<byte[]>absent());
 
         final ChannelFuture f = mock(ChannelFuture.class);
         doReturn(null).when(f).addListener(any(GenericFutureListener.class));
index bdc75e3f0cad7f7c789eae05b5622e2c450746e9..d7b015909a1b1907446cce6851953f93241d7e0e 100644 (file)
@@ -12,6 +12,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.fail;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import java.net.InetSocketAddress;
 import java.util.Collections;
@@ -50,16 +51,17 @@ public class StrictBGPPeerRegistryTest {
 
     private Open createOpen(final Ipv4Address bgpId, final AsNumber as) {
         final List<BgpParameters> params = Lists.newArrayList(new BgpParametersBuilder()
-            .setOptionalCapabilities(Lists.newArrayList(new OptionalCapabilitiesBuilder()
-                .setCParameters(new CParametersBuilder()
-                    .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(as).build()).build()).build())).build());
+        .setOptionalCapabilities(Lists.newArrayList(new OptionalCapabilitiesBuilder()
+        .setCParameters(new CParametersBuilder()
+        .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(as).build()).build()).build())).build());
         return new OpenBuilder().setBgpIdentifier(bgpId).setBgpParameters(params).build();
     }
 
     @Before
     public void setUp() throws Exception {
         this.peerRegistry = new StrictBGPPeerRegistry();
-        this.mockPreferences =  new BGPSessionPreferences(LOCAL_AS, 1, new BgpId("0.0.0.1"), LOCAL_AS, Collections.<BgpParameters> emptyList());
+        this.mockPreferences =  new BGPSessionPreferences(LOCAL_AS, 1, new BgpId("0.0.0.1"), LOCAL_AS, Collections.<BgpParameters> emptyList(),
+                Optional.<byte[]>absent());
     }
 
     private static BGPSessionListener getMockSession() {
index 488536b00c94cdaee5ed7b62986e564c7cfe27a3..0e294f0815fe383c3d3df73cb81c434efb6f1860 100755 (executable)
@@ -29,7 +29,7 @@ public class TestClientDispatcher {
     private final BGPDispatcherImpl disp;
 
     protected TestClientDispatcher(final EventLoopGroup bossGroup, final EventLoopGroup workerGroup, final MessageRegistry messageRegistry,
-                                   final InetSocketAddress locaAddress) {
+            final InetSocketAddress locaAddress) {
         this.disp = new BGPDispatcherImpl(messageRegistry, bossGroup, workerGroup) {
             @Override
             protected Bootstrap createClientBootStrap(final Optional<KeyMapping> keys, final EventLoopGroup workerGroup) {
@@ -57,13 +57,13 @@ public class TestClientDispatcher {
     }
 
     public synchronized Future<BGPSessionImpl> createClient(final InetSocketAddress remoteAddress,
-        final BGPPeerRegistry listener, final int retryTimer, final Optional<InetSocketAddress> localAddress) {
+            final BGPPeerRegistry listener, final int retryTimer, final Optional<InetSocketAddress> localAddress) {
         setLocalAddress(localAddress);
         return this.disp.createClient(remoteAddress, listener, retryTimer);
     }
 
     public synchronized Future<Void> createReconnectingClient(final InetSocketAddress address, final BGPPeerRegistry peerRegistry,
-        final int retryTimer, final Optional<InetSocketAddress> localAddress) {
+            final int retryTimer, final Optional<InetSocketAddress> localAddress) {
         setLocalAddress(localAddress);
         return this.disp.createReconnectingClient(address, peerRegistry, retryTimer, Optional.<KeyMapping>absent());
     }
index 1bb3fd4534f7aaa345e2afdbaa29c079953ec481..f6c66b2a11d44a3dc9a8d8cffca66741728f686f 100644 (file)
@@ -8,19 +8,17 @@
 
 package org.opendaylight.protocol.bgp.testtool;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.GenericFutureListener;
 import java.net.InetSocketAddress;
 import java.util.Collections;
-import java.util.concurrent.ExecutionException;
 import org.opendaylight.protocol.bgp.rib.impl.BGPDispatcherImpl;
 import org.opendaylight.protocol.bgp.rib.impl.StrictBGPPeerRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
 import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
 import org.slf4j.Logger;
@@ -35,10 +33,10 @@ final class BGPPeerBuilder {
     }
 
     static void createPeer(final BGPDispatcher dispatcher, final Arguments arguments, final InetSocketAddress localAddress,
-        final BGPSessionListener sessionListener, final BgpParameters bgpParameters) {
+            final BGPSessionListener sessionListener, final BgpParameters bgpParameters) {
         final AsNumber as = arguments.getAs();
         final BGPSessionPreferences proposal = new BGPSessionPreferences(as, arguments.getHoldTimer(), new BgpId(localAddress.getAddress().getHostAddress()),
-            as, Collections.singletonList(bgpParameters));
+                as, Collections.singletonList(bgpParameters), Optional.absent());
         final StrictBGPPeerRegistry strictBGPPeerRegistry = new StrictBGPPeerRegistry();
         if (arguments.getInitiateConnection()) {
             for (final InetSocketAddress remoteAddress : arguments.getRemoteAddresses()) {
@@ -55,11 +53,6 @@ final class BGPPeerBuilder {
     }
 
     private static <T> void addFutureListener(final InetSocketAddress localAddress, final Future<T> future) {
-        future.addListener(new GenericFutureListener<Future<T>>() {
-            @Override
-            public void operationComplete(final Future<T> future) throws ExecutionException, InterruptedException {
-                Preconditions.checkArgument(future.isSuccess(), "Unable to start bgp session on %s", localAddress, future.cause());
-            }
-        });
+        future.addListener(future1 -> Preconditions.checkArgument(future1.isSuccess(), "Unable to start bgp session on %s", localAddress, future1.cause()));
     }
 }