/* * Copyright (c) 2013, 2015 IBM Corporation 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.openflowplugin.openflow.md.core.session; import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.JdkFutureAdapters; import com.google.common.util.concurrent.ListenableFuture; import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter; import org.opendaylight.openflowplugin.api.ConnectionException; import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor; import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher; import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService; import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext; import org.opendaylight.openflowplugin.openflow.md.util.RpcResultUtil; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutputBuilder; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.math.BigInteger; import java.util.concurrent.Future; /** * message dispatch service to send the message to switch. * * @author AnilGujele */ public class MessageDispatchServiceImpl implements IMessageDispatchService { private static final Logger LOG = LoggerFactory.getLogger(MessageDispatchServiceImpl.class); private SessionContext session; /** * constructor * * @param session - MessageDispatchService for this session */ public MessageDispatchServiceImpl(SessionContext session) { this.session = session; } /** * get proper connection adapter to send the message to switch. * * @param cookie to identify the right connection, it can be null also. * @return connectionAdapter associated with cookie, otherwise return best * suitable connection. */ private ConnectionAdapter getConnectionAdapter(SwitchConnectionDistinguisher cookie) throws ConnectionException { if (!session.isValid()) { LOG.warn("No valid connection found for the node [datapath-id : {}]", session.getSessionKey().getId()); throw new ConnectionException(CONNECTION_ERROR_MESSAGE); } LOG.debug("finding connecton for cookie value {}. ", cookie); // set main connection as default ConnectionAdapter connectionAdapter = session.getPrimaryConductor().getConnectionAdapter(); if (null != cookie) { ConnectionConductor conductor = session.getAuxiliaryConductor(cookie); // check if auxiliary connection exist if (null != conductor) { LOG.debug("found auxiliary connection for the cookie."); connectionAdapter = conductor.getConnectionAdapter(); } } else { // TODO: pick connection to utilize all the available connection. } return connectionAdapter; } @Override public Future<RpcResult<BarrierOutput>> barrier(BarrierInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).barrier(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<Void>> experimenter(ExperimenterInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).experimenter(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<UpdateFlowOutput>> flowMod(final FlowModInput input, SwitchConnectionDistinguisher cookie) { LOG.debug("Calling OFLibrary flowMod"); Future<RpcResult<Void>> response = null; try { response = getConnectionAdapter(cookie).flowMod(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } // appending xid ListenableFuture<RpcResult<UpdateFlowOutput>> xidResult = Futures.transform( JdkFutureAdapters.listenInPoolThread(response), new Function<RpcResult<Void>, RpcResult<UpdateFlowOutput>>() { @Override public RpcResult<UpdateFlowOutput> apply(final RpcResult<Void> inputArg) { UpdateFlowOutputBuilder flowModOutput = new UpdateFlowOutputBuilder(); BigInteger bigIntXid = BigInteger.valueOf(input.getXid()); flowModOutput.setTransactionId(new TransactionId(bigIntXid)); UpdateFlowOutput result = flowModOutput.build(); RpcResult<UpdateFlowOutput> rpcResult = RpcResultBuilder .<UpdateFlowOutput>status(inputArg.isSuccessful()) .withResult(result).withRpcErrors(inputArg.getErrors()) .build(); return rpcResult; } }); return xidResult; } @Override public Future<RpcResult<GetAsyncOutput>> getAsync(GetAsyncInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).getAsync(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<GetConfigOutput>> getConfig(GetConfigInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).getConfig(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<GetFeaturesOutput>> getFeatures(GetFeaturesInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).getFeatures(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<GetQueueConfigOutput>> getQueueConfig(GetQueueConfigInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).getQueueConfig(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<UpdateGroupOutput>> groupMod(final GroupModInput input, SwitchConnectionDistinguisher cookie) { LOG.debug("Calling OFLibrary groupMod"); Future<RpcResult<Void>> response = null; try { response = getConnectionAdapter(cookie).groupMod(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } // appending xid ListenableFuture<RpcResult<UpdateGroupOutput>> xidResult = Futures.transform( JdkFutureAdapters.listenInPoolThread(response), new Function<RpcResult<Void>, RpcResult<UpdateGroupOutput>>() { @Override public RpcResult<UpdateGroupOutput> apply(final RpcResult<Void> inputArg) { UpdateGroupOutputBuilder groupModOutput = new UpdateGroupOutputBuilder(); BigInteger bigIntXid = BigInteger.valueOf(input.getXid()); groupModOutput.setTransactionId(new TransactionId(bigIntXid)); UpdateGroupOutput result = groupModOutput.build(); RpcResult<UpdateGroupOutput> rpcResult = RpcResultBuilder .<UpdateGroupOutput>status(inputArg.isSuccessful()).withResult(result) .withRpcErrors(inputArg.getErrors()).build(); return rpcResult; } }); return xidResult; } @Override public Future<RpcResult<UpdateMeterOutput>> meterMod(final MeterModInput input, SwitchConnectionDistinguisher cookie) { LOG.debug("Calling OFLibrary meterMod"); Future<RpcResult<Void>> response = null; try { response = getConnectionAdapter(cookie).meterMod(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } // appending xid ListenableFuture<RpcResult<UpdateMeterOutput>> xidResult = Futures.transform( JdkFutureAdapters.listenInPoolThread(response), new Function<RpcResult<Void>, RpcResult<UpdateMeterOutput>>() { @Override public RpcResult<UpdateMeterOutput> apply(final RpcResult<Void> inputArg) { UpdateMeterOutputBuilder meterModOutput = new UpdateMeterOutputBuilder(); BigInteger bigIntXid = BigInteger.valueOf(input.getXid()); meterModOutput.setTransactionId(new TransactionId(bigIntXid)); UpdateMeterOutput result = meterModOutput.build(); RpcResult<UpdateMeterOutput> rpcResult = RpcResultBuilder .<UpdateMeterOutput>status(inputArg.isSuccessful()).withResult(result) .withRpcErrors(inputArg.getErrors()).build(); return rpcResult; } }); return xidResult; } @Override public Future<RpcResult<java.lang.Void>> multipartRequest(MultipartRequestInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).multipartRequest(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<Void>> packetOut(PacketOutInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).packetOut(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<UpdatePortOutput>> portMod(final PortModInput input, SwitchConnectionDistinguisher cookie) { LOG.debug("Calling OFLibrary portMod"); Future<RpcResult<Void>> response = null; try { response = getConnectionAdapter(cookie).portMod(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } // appending xid ListenableFuture<RpcResult<UpdatePortOutput>> xidResult = Futures.transform( JdkFutureAdapters.listenInPoolThread(response), new Function<RpcResult<Void>, RpcResult<UpdatePortOutput>>() { @Override public RpcResult<UpdatePortOutput> apply(final RpcResult<Void> inputArg) { UpdatePortOutputBuilder portModOutput = new UpdatePortOutputBuilder(); BigInteger bigIntXid = BigInteger.valueOf(input.getXid()); portModOutput.setTransactionId(new TransactionId(bigIntXid)); UpdatePortOutput result = portModOutput.build(); RpcResult<UpdatePortOutput> rpcResult = RpcResultBuilder .<UpdatePortOutput>status(inputArg.isSuccessful()).withResult(result) .withRpcErrors(inputArg.getErrors()).build(); return rpcResult; } }); return xidResult; } @Override public Future<RpcResult<RoleRequestOutput>> roleRequest(RoleRequestInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).roleRequest(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<Void>> setAsync(SetAsyncInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).setAsync(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<Void>> setConfig(SetConfigInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).setConfig(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } @Override public Future<RpcResult<Void>> tableMod(TableModInput input, SwitchConnectionDistinguisher cookie) { try { return getConnectionAdapter(cookie).tableMod(input); } catch (ConnectionException e) { return RpcResultUtil.getRpcErrorFuture(e); } } }