<groupId>io.netty</groupId>
<artifactId>netty-common</artifactId>
</dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-buffer</artifactId>
- </dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-inet-types</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.tcpmd5</groupId>
+ <artifactId>tcpmd5-jni</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.tcpmd5</groupId>
+ <artifactId>tcpmd5-netty</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.tcpmd5</groupId>
+ <artifactId>tcpmd5-api</artifactId>
+ </dependency>
<!-- Testing dependencies -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>pcep-testtool</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
+import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.opendaylight.protocol.pcep.impl.DefaultPCEPSessionNegotiatorFactory;
import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
+import org.opendaylight.tcpmd5.api.KeyMapping;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
import org.slf4j.Logger;
final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
short ka = DEFAULT_KEEP_ALIVE;
short dt = DEFAULT_DEAD_TIMER;
+ String password = null;
getRootLogger(lc).setLevel(ch.qos.logback.classic.Level.INFO);
int argIdx = 0;
ka = Short.valueOf(args[++argIdx]);
} else if (args[argIdx].equals("--deadtimer") || args[argIdx].equals("-d")) {
dt = Short.valueOf(args[++argIdx]);
+ } else if (args[argIdx].equals("--password")) {
+ password = args[++argIdx];
} else {
LOG.warn("WARNING: Unrecognized argument: {}", args[argIdx]);
}
argIdx++;
}
- createPCCs(lsps, pcError, pccCount, localAddress, remoteAddress, ka, dt);
+ createPCCs(lsps, pcError, pccCount, localAddress, remoteAddress, ka, dt, password);
}
public static void createPCCs(final int lspsPerPcc, final boolean pcerr, final int pccCount,
- final InetAddress localAddress, final List<InetAddress> remoteAddress, final short keepalive, final short deadtimer) throws InterruptedException, ExecutionException {
+ final InetAddress localAddress, final List<InetAddress> remoteAddress, final short keepalive, final short deadtimer,
+ final String password) throws InterruptedException, ExecutionException {
final StatefulActivator activator07 = new StatefulActivator();
activator07.start(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance());
InetAddress currentAddress = localAddress;
final PCCDispatcher pccDispatcher = new PCCDispatcher(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance().getMessageHandlerRegistry(),
getSessionNegotiatorFactory(keepalive, deadtimer));
for (int i = 0; i < pccCount; i++) {
- createPCC(lspsPerPcc, pcerr, currentAddress, remoteAddress, keepalive, deadtimer, pccDispatcher);
+ createPCC(lspsPerPcc, pcerr, currentAddress, remoteAddress, keepalive, deadtimer, pccDispatcher, password);
currentAddress = InetAddresses.increment(currentAddress);
}
}
private static void createPCC(final int lspsPerPcc, final boolean pcerr, final InetAddress localAddress,
- final List<InetAddress> remoteAddress, final short keepalive, final short deadtimer, final PCCDispatcher pccDispatcher) throws InterruptedException, ExecutionException {
+ final List<InetAddress> remoteAddress, final short keepalive, final short deadtimer, final PCCDispatcher pccDispatcher,
+ final String password) throws InterruptedException, ExecutionException {
final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = getSessionNegotiatorFactory(keepalive, deadtimer);
for (final InetAddress pceAddress : remoteAddress) {
pccDispatcher.createClient(new InetSocketAddress(localAddress, 0), new InetSocketAddress(pceAddress, DEFAULT_PORT), new ReconnectImmediatelyStrategy(GlobalEventExecutor.INSTANCE, RECONNECT_STRATEGY_TIMEOUT), new SessionListenerFactory<PCEPSessionListener>() {
public PCEPSessionListener getSessionListener() {
return new SimpleSessionListener(lspsPerPcc, pcerr, localAddress);
}
- }, snf);
+ }, snf, getKeyMapping(pceAddress, password));
}
}
});
}
+ private static KeyMapping getKeyMapping(final InetAddress inetAddress, final String password) {
+ if (password != null) {
+ final KeyMapping keyMapping = new KeyMapping();
+ keyMapping.put(inetAddress, password.getBytes(Charsets.US_ASCII));
+ return keyMapping;
+ }
+ return null;
+ }
+
}
import org.opendaylight.protocol.pcep.impl.PCEPHandlerFactory;
import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
import org.opendaylight.protocol.pcep.spi.MessageRegistry;
+import org.opendaylight.tcpmd5.api.DummyKeyAccessFactory;
+import org.opendaylight.tcpmd5.api.KeyAccessFactory;
+import org.opendaylight.tcpmd5.api.KeyMapping;
+import org.opendaylight.tcpmd5.jni.NativeKeyAccessFactory;
+import org.opendaylight.tcpmd5.jni.NativeSupportUnavailableException;
+import org.opendaylight.tcpmd5.netty.MD5ChannelFactory;
+import org.opendaylight.tcpmd5.netty.MD5ChannelOption;
+import org.opendaylight.tcpmd5.netty.MD5NioSocketChannelFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public final class PCCDispatcher extends PCEPDispatcherImpl {
private InetSocketAddress localAddress;
private final PCEPHandlerFactory factory;
+ private final MD5ChannelFactory<?> cf;
+ private KeyMapping keys;
public PCCDispatcher(final MessageRegistry registry,
final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> negotiatorFactory) {
super(registry, negotiatorFactory, new NioEventLoopGroup(), new NioEventLoopGroup(), null, null);
this.factory = new PCEPHandlerFactory(registry);
+ this.cf = new MD5NioSocketChannelFactory(DeafultKeyAccessFactory.getKeyAccessFactory());
}
@Override
protected void customizeBootstrap(final Bootstrap b) {
- super.customizeBootstrap(b);
+ if (this.keys != null && !this.keys.isEmpty()) {
+ if (this.cf == null) {
+ throw new UnsupportedOperationException("No key access instance available, cannot use key mapping");
+ }
+
+ b.channelFactory(this.cf);
+ b.option(MD5ChannelOption.TCP_MD5SIG, this.keys);
+ }
if (this.localAddress != null) {
b.localAddress(this.localAddress);
}
public synchronized Future<PCEPSessionImpl> createClient(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress,
final ReconnectStrategy strategy, final SessionListenerFactory<PCEPSessionListener> listenerFactory,
- final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> negotiatorFactory) {
+ final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> negotiatorFactory, final KeyMapping keys) {
this.localAddress = localAddress;
+ this.keys = keys;
final Future<PCEPSessionImpl> futureClient = super.createClient(remoteAddress, strategy, new PipelineInitializer<PCEPSessionImpl>() {
@Override
public void initializeChannel(final SocketChannel ch, final Promise<PCEPSessionImpl> promise) {
}
});
this.localAddress = null;
+ this.keys = null;
return futureClient;
}
+
+ private static final class DeafultKeyAccessFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(DeafultKeyAccessFactory.class);
+ private static final KeyAccessFactory FACTORY;
+
+ static {
+ KeyAccessFactory factory;
+
+ try {
+ factory = NativeKeyAccessFactory.getInstance();
+ } catch (NativeSupportUnavailableException e) {
+ LOG.debug("Native key access not available, using no-op fallback", e);
+ factory = DummyKeyAccessFactory.getInstance();
+ }
+
+ FACTORY = factory;
+ }
+
+ private DeafultKeyAccessFactory() {
+ throw new UnsupportedOperationException("Utility class should never be instantiated");
+ }
+
+ public static KeyAccessFactory getKeyAccessFactory() {
+ return FACTORY;
+ }
+ }
}