/*
* Copyright (c) 2013 Pantheon Technologies s.r.o. 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.openflowjava.protocol.it.integration;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener;
import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
import org.opendaylight.openflowjava.protocol.impl.core.SwitchConnectionProviderImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.util.concurrent.SettableFuture;
/**
* @author michal.polkorab
*
*/
public class MockPlugin implements OpenflowProtocolListener, SwitchConnectionHandler,
SystemNotificationsListener, ConnectionReadyListener {
protected static final Logger LOGGER = LoggerFactory.getLogger(MockPlugin.class);
protected volatile ConnectionAdapter adapter;
private SettableFuture<Void> finishedFuture;
private int idleCounter = 0;
/** Creates MockPlugin */
public MockPlugin() {
LOGGER.trace("Creating MockPlugin");
finishedFuture = SettableFuture.create();
LOGGER.debug("mockPlugin: {}", System.identityHashCode(this));
}
@Override
public void onSwitchConnected(ConnectionAdapter connection) {
LOGGER.debug("onSwitchConnected: {}", connection);
this.adapter = connection;
connection.setMessageListener(this);
connection.setSystemListener(this);
connection.setConnectionReadyListener(this);
}
@Override
public boolean accept(InetAddress switchAddress) {
LOGGER.debug("MockPlugin.accept(): {}", switchAddress.toString());
return true;
}
@Override
public void onEchoRequestMessage(final EchoRequestMessage notification) {
LOGGER.debug("MockPlugin.onEchoRequestMessage() adapter: {}", adapter);
new Thread(new Runnable() {
@Override
public void run() {
LOGGER.debug("MockPlugin.onEchoRequestMessage().run() started adapter: {}", adapter);
EchoReplyInputBuilder replyBuilder = new EchoReplyInputBuilder();
replyBuilder.setVersion((short) 4);
replyBuilder.setXid(notification.getXid());
EchoReplyInput echoReplyInput = replyBuilder.build();
adapter.echoReply(echoReplyInput);
LOGGER.debug("adapter.EchoReply(Input) sent : ", echoReplyInput.toString());
LOGGER.debug("MockPlugin.onEchoRequestMessage().run() finished adapter: {}", adapter);
}
}).start();
}
@Override
public void onErrorMessage(ErrorMessage notification) {
LOGGER.debug("Error message received");
}
@Override
public void onExperimenterMessage(ExperimenterMessage notification) {
LOGGER.debug("Experimenter message received");
}
@Override
public void onFlowRemovedMessage(FlowRemovedMessage notification) {
LOGGER.debug("FlowRemoved message received");
}
@Override
public void onHelloMessage(HelloMessage notification) {
new Thread(new Runnable() {
@Override
public void run() {
LOGGER.debug("MockPlugin.onHelloMessage().run() Hello message received");
HelloInputBuilder hib = new HelloInputBuilder();
hib.setVersion((short) 4);
hib.setXid(2L);
HelloInput hi = hib.build();
adapter.hello(hi);
LOGGER.debug("hello msg sent");
new Thread(new Runnable() {
@Override
public void run() {
getSwitchFeatures();
}
}).start();
}
}).start();
}
protected void getSwitchFeatures() {
GetFeaturesInputBuilder featuresBuilder = new GetFeaturesInputBuilder();
featuresBuilder.setVersion((short) 4);
featuresBuilder.setXid(3L);
GetFeaturesInput featuresInput = featuresBuilder.build();
try {
LOGGER.debug("Requesting features ");
RpcResult<GetFeaturesOutput> rpcResult = adapter.getFeatures(
featuresInput).get(2500, TimeUnit.MILLISECONDS);
if (rpcResult.isSuccessful()) {
byte[] byteArray = rpcResult.getResult().getDatapathId()
.toByteArray();
LOGGER.debug("DatapathId: {}", Arrays.toString(byteArray));
} else {
RpcError rpcError = rpcResult.getErrors().iterator().next();
LOGGER.warn("rpcResult failed", rpcError.getCause());
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
LOGGER.error("getSwitchFeatures() exception caught: ", e.getMessage(), e);
}
}
protected void shutdown() {
try {
LOGGER.debug("MockPlugin.shutdown() sleeping 5... : {}", System.identityHashCode(this));
Thread.sleep(500);
if (adapter != null) {
Future<Boolean> disconnect = adapter.disconnect();
disconnect.get();
LOGGER.debug("MockPlugin.shutdown() Disconnected");
}
} catch (Exception e) {
LOGGER.error("MockPlugin.shutdown() exception caught: ", e.getMessage(), e);
}
finishedFuture.set(null);
}
@Override
public void onMultipartReplyMessage(MultipartReplyMessage notification) {
LOGGER.debug("MultipartReply message received");
}
@Override
public void onPacketInMessage(PacketInMessage notification) {
LOGGER.debug("PacketIn message received");
LOGGER.debug("BufferId: {}", notification.getBufferId());
LOGGER.debug("TotalLength: {}", notification.getTotalLen());
LOGGER.debug("Reason: {}", notification.getReason());
LOGGER.debug("TableId: {}", notification.getTableId());
LOGGER.debug("Cookie: {}", notification.getCookie());
LOGGER.debug("Class: {}", notification.getMatch().getMatchEntry().get(0).getOxmClass());
LOGGER.debug("Field: {}", notification.getMatch().getMatchEntry().get(0).getOxmMatchField());
LOGGER.debug("Datasize: {}", notification.getData().length);
}
@Override
public void onPortStatusMessage(PortStatusMessage notification) {
LOGGER.debug("MockPlugin.onPortStatusMessage() message received");
}
@Override
public void onDisconnectEvent(DisconnectEvent notification) {
LOGGER.debug("disconnection occured: {}", notification.getInfo());
}
/**
* @return finishedFuture object
*/
public SettableFuture<Void> getFinishedFuture() {
return finishedFuture;
}
@Override
public void onSwitchIdleEvent(SwitchIdleEvent notification) {
LOGGER.debug("MockPlugin.onSwitchIdleEvent() switch status: {}", notification.getInfo());
idleCounter ++;
}
/**
* @return number of occured idleEvents
*/
public int getIdleCounter() {
return idleCounter;
}
@Override
public void onConnectionReady() {
LOGGER.trace("MockPlugin().onConnectionReady()");
}
/**
* Initiates connection to device
* @param switchConnectionProvider
* @param host - host IP
* @param port - port number
*/
public void initiateConnection(SwitchConnectionProviderImpl switchConnectionProvider, String host, int port) {
LOGGER.trace("MockPlugin().initiateConnection()");
switchConnectionProvider.initiateConnection(host, port);
}
}