X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Futil%2FDeviceInitializationUtils.java;h=0bdbe08a9c82e01be756b0cabec21d027f6a2863;hb=9f8a5a168696e279ae49ed79efe4590abc49b9ba;hp=d4da3cc131c277265c5705d961d0e16dcd444c47;hpb=b977adac522d210e9fea06b77a40f8bd87c2d193;p=openflowplugin.git diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtils.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtils.java index d4da3cc131..0bdbe08a9c 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtils.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtils.java @@ -15,21 +15,20 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import java.math.BigInteger; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Iterator; import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutionException; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue; import org.opendaylight.openflowplugin.api.ConnectionException; import org.opendaylight.openflowplugin.api.OFConstants; import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; +import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo; import org.opendaylight.openflowplugin.api.openflow.device.DeviceState; import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; @@ -39,8 +38,10 @@ import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey; import org.opendaylight.openflowplugin.impl.common.MultipartRequestInputFactory; import org.opendaylight.openflowplugin.impl.common.NodeStaticReplyTranslatorUtil; import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IetfInetUtil; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.openflowplugin.openflow.md.core.sal.SwitchFeaturesUtil; +import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor; +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; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; @@ -59,6 +60,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111. import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.CapabilitiesV10; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping; @@ -89,21 +91,26 @@ public class DeviceInitializationUtils { private static final Logger LOG = LoggerFactory.getLogger(DeviceInitializationUtils.class); + private DeviceInitializationUtils() { + // Hiding implicit constructor + } + /** * InitializationNodeInformation is good to call only for MASTER otherwise we will have not empty transaction * for every Cluster Node (SLAVE too) and we will get race-condition by closing Connection. * * @param deviceContext * @param switchFeaturesMandatory - * @return future - recommended to have blocking call for this future + * @param convertorExecutor */ - public static ListenableFuture initializeNodeInformation(final DeviceContext deviceContext, final boolean switchFeaturesMandatory) { + public static void initializeNodeInformation(final DeviceContext deviceContext, final boolean switchFeaturesMandatory, final ConvertorExecutor convertorExecutor) throws ExecutionException, InterruptedException { Preconditions.checkArgument(deviceContext != null); final DeviceState deviceState = Preconditions.checkNotNull(deviceContext.getDeviceState()); + final DeviceInfo deviceInfo = deviceContext.getDeviceInfo(); final ConnectionContext connectionContext = Preconditions.checkNotNull(deviceContext.getPrimaryConnectionContext()); - final short version = deviceState.getVersion(); - LOG.trace("initalizeNodeInformation for node {}", deviceState.getNodeId()); - final SettableFuture returnFuture = SettableFuture.create(); + final short version = deviceInfo.getVersion(); + LOG.trace("initalizeNodeInformation for node {}", deviceInfo.getNodeId()); + final SettableFuture returnFuture = SettableFuture.create(); addNodeToOperDS(deviceContext, returnFuture); final ListenableFuture>>> deviceFeaturesFuture; if (OFConstants.OFP_VERSION_1_0 == version) { @@ -111,18 +118,18 @@ public class DeviceInitializationUtils { DeviceStateUtil.setDeviceStateBasedOnV10Capabilities(deviceState, capabilitiesV10); - deviceFeaturesFuture = createDeviceFeaturesForOF10(deviceContext, deviceState); + deviceFeaturesFuture = createDeviceFeaturesForOF10(deviceContext); // create empty tables after device description is processed chainTableTrunkWriteOF10(deviceContext, deviceFeaturesFuture); - final short ofVersion = deviceContext.getDeviceState().getVersion(); + final short ofVersion = deviceInfo.getVersion(); final TranslatorKey translatorKey = new TranslatorKey(ofVersion, PortGrouping.class.getName()); final MessageTranslator translator = deviceContext.oook() .lookupTranslator(translatorKey); - final BigInteger dataPathId = deviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId(); + final BigInteger dataPathId = deviceContext.getDeviceInfo().getDatapathId(); for (final PortGrouping port : connectionContext.getFeatures().getPhyPort()) { - final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, deviceContext.getDeviceState(), null); + final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, deviceContext.getDeviceInfo(), null); final NodeConnectorId nodeConnectorId = NodeStaticReplyTranslatorUtil.nodeConnectorId( dataPathId.toString(), port.getPortNo(), ofVersion); @@ -131,72 +138,53 @@ public class DeviceInitializationUtils { ncBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, new FlowCapableNodeConnectorStatisticsDataBuilder().build()); final NodeConnector connector = ncBuilder.build(); - final InstanceIdentifier connectorII = deviceState.getNodeInstanceIdentifier().child( + final InstanceIdentifier connectorII = deviceInfo.getNodeInstanceIdentifier().child( NodeConnector.class, connector.getKey()); try { deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, connectorII, connector); } catch (final Exception e) { - LOG.debug("Failed to write node {} to DS ", deviceContext.getDeviceState().getNodeId().toString(), + LOG.debug("initializeNodeInformation: Failed to write node {} to DS ", deviceInfo.getNodeId().toString(), e); } } } else if (OFConstants.OFP_VERSION_1_3 == version) { final Capabilities capabilities = connectionContext.getFeatures().getCapabilities(); - LOG.debug("Setting capabilities for device {}", deviceContext.getDeviceState().getNodeId()); + LOG.debug("Setting capabilities for device {}", deviceInfo.getNodeId()); DeviceStateUtil.setDeviceStateBasedOnV13Capabilities(deviceState, capabilities); - deviceFeaturesFuture = createDeviceFeaturesForOF13(deviceContext, deviceState, switchFeaturesMandatory); + createDeviceFeaturesForOF13(deviceContext, switchFeaturesMandatory, convertorExecutor).get(); } else { - deviceFeaturesFuture = Futures.immediateFailedFuture(new ConnectionException("Unsupported version " - + version)); + throw new ExecutionException(new ConnectionException("Unsupported version " + version)); } - Futures.addCallback(deviceFeaturesFuture, new FutureCallback>>>() { - @Override - public void onSuccess(final List>> result) { - LOG.debug("All init data for node {} is in submited.", deviceState.getNodeId()); - returnFuture.set(null); - } - - @Override - public void onFailure(final Throwable t) { - // FIXME : remove session - LOG.trace("Device capabilities gathering future failed."); - LOG.trace("more info in exploration failure..", t); - LOG.debug("All init data for node {} was not submited correctly - connection has to go down.", deviceState.getNodeId()); - returnFuture.setException(t); - } - }); - return returnFuture; } private static void addNodeToOperDS(final DeviceContext deviceContext, final SettableFuture future) { Preconditions.checkArgument(deviceContext != null); - final DeviceState deviceState = deviceContext.getDeviceState(); - final NodeBuilder nodeBuilder = new NodeBuilder().setId(deviceState.getNodeId()).setNodeConnector( - Collections.emptyList()); + final NodeBuilder nodeBuilder = new NodeBuilder().setId(deviceContext.getDeviceInfo().getNodeId()).setNodeConnector( + Collections.emptyList()); try { - deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, deviceState.getNodeInstanceIdentifier(), + deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), nodeBuilder.build()); } catch (final Exception e) { - LOG.warn("Failed to write node {} to DS ", deviceState.getNodeId(), e); + LOG.warn("addNodeToOperDS: Failed to write node {} to DS ", deviceContext.getDeviceInfo().getNodeId(), e); future.cancel(true); } } private static ListenableFuture>>> createDeviceFeaturesForOF10( - final DeviceContext deviceContext, final DeviceState deviceState) { + final DeviceContext deviceContext) { final ListenableFuture>> replyDesc = getNodeStaticInfo(MultipartType.OFPMPDESC, - deviceContext, deviceState.getNodeInstanceIdentifier(), deviceState.getVersion()); + deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion()); return Futures.allAsList(Arrays.asList(replyDesc)); } private static ListenableFuture>>> createDeviceFeaturesForOF13( - final DeviceContext deviceContext, final DeviceState deviceState, final boolean switchFeaturesMandatory) { + final DeviceContext deviceContext, final boolean switchFeaturesMandatory, final ConvertorExecutor convertorExecutor) { final ListenableFuture>> replyDesc = getNodeStaticInfo(MultipartType.OFPMPDESC, - deviceContext, deviceState.getNodeInstanceIdentifier(), deviceState.getVersion()); + deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion()); //first process description reply, write data to DS and write consequent data if successful return Futures.transform(replyDesc, @@ -206,32 +194,38 @@ public class DeviceInitializationUtils { final RpcResult> rpcResult) throws Exception { translateAndWriteReply(MultipartType.OFPMPDESC, deviceContext, - deviceState.getNodeInstanceIdentifier(), rpcResult.getResult()); + deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), rpcResult.getResult(), convertorExecutor); final ListenableFuture>> replyMeterFeature = getNodeStaticInfo( MultipartType.OFPMPMETERFEATURES, deviceContext, - deviceState.getNodeInstanceIdentifier(), deviceState.getVersion()); + deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion()); createSuccessProcessingCallback(MultipartType.OFPMPMETERFEATURES, deviceContext, - deviceState.getNodeInstanceIdentifier(), replyMeterFeature); + deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyMeterFeature, convertorExecutor); final ListenableFuture>> replyGroupFeatures = getNodeStaticInfo( MultipartType.OFPMPGROUPFEATURES, deviceContext, - deviceState.getNodeInstanceIdentifier(), deviceState.getVersion()); + deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion()); createSuccessProcessingCallback(MultipartType.OFPMPGROUPFEATURES, deviceContext, - deviceState.getNodeInstanceIdentifier(), replyGroupFeatures); + deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyGroupFeatures, convertorExecutor); - final ListenableFuture>> replyTableFeatures = getNodeStaticInfo( - MultipartType.OFPMPTABLEFEATURES, deviceContext, - deviceState.getNodeInstanceIdentifier(), deviceState.getVersion()); + final ListenableFuture>> replyTableFeatures; + + if (deviceContext.isSkipTableFeatures()) { + replyTableFeatures = RpcResultBuilder.>success().buildFuture(); + } else { + replyTableFeatures = getNodeStaticInfo( + MultipartType.OFPMPTABLEFEATURES, deviceContext, + deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion()); + } createSuccessProcessingCallback(MultipartType.OFPMPTABLEFEATURES, deviceContext, - deviceState.getNodeInstanceIdentifier(), replyTableFeatures); + deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyTableFeatures, convertorExecutor); final ListenableFuture>> replyPortDescription = getNodeStaticInfo( - MultipartType.OFPMPPORTDESC, deviceContext, deviceState.getNodeInstanceIdentifier(), - deviceState.getVersion()); + MultipartType.OFPMPPORTDESC, deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), + deviceContext.getDeviceInfo().getVersion()); createSuccessProcessingCallback(MultipartType.OFPMPPORTDESC, deviceContext, - deviceState.getNodeInstanceIdentifier(), replyPortDescription); + deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyPortDescription, convertorExecutor); if (switchFeaturesMandatory) { return Futures.allAsList(Arrays.asList(replyMeterFeature, replyGroupFeatures, replyTableFeatures, replyPortDescription)); @@ -245,116 +239,175 @@ public class DeviceInitializationUtils { } static void translateAndWriteReply(final MultipartType type, final DeviceContext dContext, - final InstanceIdentifier nodeII, final Collection result) { - try { - for (final MultipartReply reply : result) { - final MultipartReplyBody body = reply.getMultipartReplyBody(); - switch (type) { - case OFPMPDESC: - Preconditions.checkArgument(body instanceof MultipartReplyDescCase); - final MultipartReplyDesc replyDesc = ((MultipartReplyDescCase) body).getMultipartReplyDesc(); - final FlowCapableNode fcNode = NodeStaticReplyTranslatorUtil.nodeDescTranslator(replyDesc, - getIpAddressOf(dContext)); - final InstanceIdentifier fNodeII = nodeII.augmentation(FlowCapableNode.class); - dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, fNodeII, fcNode); - break; - - case OFPMPTABLEFEATURES: - Preconditions.checkArgument(body instanceof MultipartReplyTableFeaturesCase); - final MultipartReplyTableFeatures tableFeaturesMP = ((MultipartReplyTableFeaturesCase) body) - .getMultipartReplyTableFeatures(); - final List tableFeatures = NodeStaticReplyTranslatorUtil - .nodeTableFeatureTranslator(tableFeaturesMP); - for (final TableFeatures tableFeature : tableFeatures) { - final Short tableId = tableFeature.getTableId(); - final KeyedInstanceIdentifier tableFeaturesII = - nodeII.augmentation(FlowCapableNode.class) - .child(TableFeatures.class, new TableFeaturesKey(tableId)); - dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableFeaturesII, tableFeature); - - // write parent for table statistics - final KeyedInstanceIdentifier tableII = - nodeII.augmentation(FlowCapableNode.class) - .child(Table.class, new TableKey(tableId)); - final TableBuilder tableBld = new TableBuilder().setId(tableId) - .addAugmentation(FlowTableStatisticsData.class, - new FlowTableStatisticsDataBuilder().build()); - - dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableII, tableBld.build()); - } - break; - - case OFPMPMETERFEATURES: - Preconditions.checkArgument(body instanceof MultipartReplyMeterFeaturesCase); - final MultipartReplyMeterFeatures meterFeatures = ((MultipartReplyMeterFeaturesCase) body) - .getMultipartReplyMeterFeatures(); - final NodeMeterFeatures mFeature = NodeStaticReplyTranslatorUtil - .nodeMeterFeatureTranslator(meterFeatures); - final InstanceIdentifier mFeatureII = nodeII - .augmentation(NodeMeterFeatures.class); - dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, mFeatureII, mFeature); - if (0L < mFeature.getMeterFeatures().getMaxMeter().getValue()) { - dContext.getDeviceState().setMeterAvailable(true); - } - break; - - case OFPMPGROUPFEATURES: - Preconditions.checkArgument(body instanceof MultipartReplyGroupFeaturesCase); - final MultipartReplyGroupFeatures groupFeatures = ((MultipartReplyGroupFeaturesCase) body) - .getMultipartReplyGroupFeatures(); - final NodeGroupFeatures gFeature = NodeStaticReplyTranslatorUtil - .nodeGroupFeatureTranslator(groupFeatures); - final InstanceIdentifier gFeatureII = nodeII - .augmentation(NodeGroupFeatures.class); - dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, gFeatureII, gFeature); - break; - - case OFPMPPORTDESC: - Preconditions.checkArgument(body instanceof MultipartReplyPortDescCase); - final MultipartReplyPortDesc portDesc = ((MultipartReplyPortDescCase) body) - .getMultipartReplyPortDesc(); - for (final PortGrouping port : portDesc.getPorts()) { - final short ofVersion = dContext.getDeviceState().getVersion(); - final TranslatorKey translatorKey = new TranslatorKey(ofVersion, PortGrouping.class.getName()); - final MessageTranslator translator = dContext.oook() - .lookupTranslator(translatorKey); - final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, dContext.getDeviceState(), null); - - final BigInteger dataPathId = dContext.getPrimaryConnectionContext().getFeatures() - .getDatapathId(); - final NodeConnectorId nodeConnectorId = NodeStaticReplyTranslatorUtil.nodeConnectorId( - dataPathId.toString(), port.getPortNo(), ofVersion); - final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder().setId(nodeConnectorId); - ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcNodeConnector); - - ncBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, - new FlowCapableNodeConnectorStatisticsDataBuilder().build()); - final NodeConnector connector = ncBuilder.build(); - - final InstanceIdentifier connectorII = nodeII.child(NodeConnector.class, - connector.getKey()); - dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, connectorII, connector); - } + final InstanceIdentifier nodeII, final Collection result, + final ConvertorExecutor convertorExecutor) { + if (Objects.nonNull(result)) { + try { + result.stream() + .map(MultipartReply::getMultipartReplyBody) + .forEach(multipartReplyBody -> { + if (!(writeDesc(type, multipartReplyBody, dContext, nodeII) + || writeTableFeatures(type, multipartReplyBody, dContext, nodeII, convertorExecutor) + || writeMeterFeatures(type, multipartReplyBody, dContext, nodeII) + || writeGroupFeatures(type, multipartReplyBody, dContext, nodeII) + || writePortDesc(type, multipartReplyBody, dContext, nodeII))) { + throw new IllegalArgumentException("Unexpected MultipartType " + type); + } + }); + } catch (final Exception e) { + LOG.debug("translateAndWriteReply: Failed to write node {} to DS ", dContext.getDeviceInfo().getNodeId().toString(), e); + } + } else { + LOG.debug("translateAndWriteReply: Failed to write node {} to DS because we failed to gather device" + + "info.", + dContext.getDeviceInfo().getNodeId().toString()); + } + } - break; + private static boolean writeDesc(final MultipartType type, + final MultipartReplyBody body, + final DeviceContext dContext, + final InstanceIdentifier nodeII) { + if (!MultipartType.OFPMPDESC.equals(type)) { + return false; + } - default: - throw new IllegalArgumentException("Unnexpected MultipartType " + type); - } - } - } catch (final Exception e) { - LOG.debug("Failed to write node {} to DS ", dContext.getDeviceState().getNodeId().toString(), e); + Preconditions.checkArgument(body instanceof MultipartReplyDescCase); + final MultipartReplyDesc replyDesc = ((MultipartReplyDescCase) body).getMultipartReplyDesc(); + final FlowCapableNode fcNode = NodeStaticReplyTranslatorUtil + .nodeDescTranslator(replyDesc, getIpAddressOf(dContext)) + .setSwitchFeatures(SwitchFeaturesUtil.getInstance().buildSwitchFeatures( + new GetFeaturesOutputBuilder(dContext.getPrimaryConnectionContext().getFeatures()).build())) + .build(); + + final InstanceIdentifier fNodeII = nodeII.augmentation(FlowCapableNode.class); + dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, fNodeII, fcNode); + return true; + } + + private static boolean writeTableFeatures(final MultipartType type, + final MultipartReplyBody body, + final DeviceContext dContext, + final InstanceIdentifier nodeII, + final ConvertorExecutor convertorExecutor) { + if (!MultipartType.OFPMPTABLEFEATURES.equals(type)) { + return false; + } + + Preconditions.checkArgument(body instanceof MultipartReplyTableFeaturesCase); + final MultipartReplyTableFeatures tableFeaturesMP = ((MultipartReplyTableFeaturesCase) body) + .getMultipartReplyTableFeatures(); + final List tableFeatures = NodeStaticReplyTranslatorUtil + .nodeTableFeatureTranslator(tableFeaturesMP, dContext.getDeviceInfo().getVersion(), convertorExecutor); + for (final TableFeatures tableFeature : tableFeatures) { + final Short tableId = tableFeature.getTableId(); + final KeyedInstanceIdentifier tableFeaturesII = + nodeII.augmentation(FlowCapableNode.class) + .child(TableFeatures.class, new TableFeaturesKey(tableId)); + dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableFeaturesII, tableFeature); + + // write parent for table statistics + final KeyedInstanceIdentifier tableII = + nodeII.augmentation(FlowCapableNode.class) + .child(Table.class, new TableKey(tableId)); + final TableBuilder tableBld = new TableBuilder().setId(tableId) + .addAugmentation(FlowTableStatisticsData.class, + new FlowTableStatisticsDataBuilder().build()); + + dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableII, tableBld.build()); + } + + return true; + } + + private static boolean writeMeterFeatures(final MultipartType type, + final MultipartReplyBody body, + final DeviceContext dContext, + final InstanceIdentifier nodeII) { + if (!MultipartType.OFPMPMETERFEATURES.equals(type)) { + return false; + } + + Preconditions.checkArgument(body instanceof MultipartReplyMeterFeaturesCase); + final MultipartReplyMeterFeatures meterFeatures = ((MultipartReplyMeterFeaturesCase) body) + .getMultipartReplyMeterFeatures(); + final NodeMeterFeatures mFeature = NodeStaticReplyTranslatorUtil + .nodeMeterFeatureTranslator(meterFeatures); + final InstanceIdentifier mFeatureII = nodeII + .augmentation(NodeMeterFeatures.class); + dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, mFeatureII, mFeature); + if (0L < mFeature.getMeterFeatures().getMaxMeter().getValue()) { + dContext.getDeviceState().setMeterAvailable(true); + } + + return true; + } + + private static boolean writeGroupFeatures(final MultipartType type, + final MultipartReplyBody body, + final DeviceContext dContext, + final InstanceIdentifier nodeII) { + if (!MultipartType.OFPMPGROUPFEATURES.equals(type)) { + return false; } + + Preconditions.checkArgument(body instanceof MultipartReplyGroupFeaturesCase); + final MultipartReplyGroupFeatures groupFeatures = ((MultipartReplyGroupFeaturesCase) body) + .getMultipartReplyGroupFeatures(); + final NodeGroupFeatures gFeature = NodeStaticReplyTranslatorUtil + .nodeGroupFeatureTranslator(groupFeatures); + final InstanceIdentifier gFeatureII = nodeII + .augmentation(NodeGroupFeatures.class); + dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, gFeatureII, gFeature); + + return true; + } + + private static boolean writePortDesc(final MultipartType type, + final MultipartReplyBody body, + final DeviceContext dContext, + final InstanceIdentifier nodeII) { + if (!MultipartType.OFPMPPORTDESC.equals(type)) { + return false; + } + + Preconditions.checkArgument(body instanceof MultipartReplyPortDescCase); + final MultipartReplyPortDesc portDesc = ((MultipartReplyPortDescCase) body) + .getMultipartReplyPortDesc(); + for (final PortGrouping port : portDesc.getPorts()) { + final short ofVersion = dContext.getDeviceInfo().getVersion(); + final TranslatorKey translatorKey = new TranslatorKey(ofVersion, PortGrouping.class.getName()); + final MessageTranslator translator = dContext.oook() + .lookupTranslator(translatorKey); + final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, dContext.getDeviceInfo(), null); + + final BigInteger dataPathId = dContext.getPrimaryConnectionContext().getFeatures() + .getDatapathId(); + final NodeConnectorId nodeConnectorId = NodeStaticReplyTranslatorUtil.nodeConnectorId( + dataPathId.toString(), port.getPortNo(), ofVersion); + final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder().setId(nodeConnectorId); + ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcNodeConnector); + + ncBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, + new FlowCapableNodeConnectorStatisticsDataBuilder().build()); + final NodeConnector connector = ncBuilder.build(); + + final InstanceIdentifier connectorII = nodeII.child(NodeConnector.class, + connector.getKey()); + dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, connectorII, connector); + } + + return true; } private static void createEmptyFlowCapableNodeInDs(final DeviceContext deviceContext) { final FlowCapableNodeBuilder flowCapableNodeBuilder = new FlowCapableNodeBuilder(); - final InstanceIdentifier fNodeII = deviceContext.getDeviceState().getNodeInstanceIdentifier() + final InstanceIdentifier fNodeII = deviceContext.getDeviceInfo().getNodeInstanceIdentifier() .augmentation(FlowCapableNode.class); try { deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, fNodeII, flowCapableNodeBuilder.build()); } catch (final Exception e) { - LOG.debug("Failed to write node {} to DS ", deviceContext.getDeviceState().getNodeId().toString(), e); + LOG.debug("createEmptyFlowCapableNodeInDs: Failed to write node {} to DS ", deviceContext.getDeviceInfo().getNodeId().toString(), e); } } @@ -365,7 +418,7 @@ public class DeviceInitializationUtils { if (remoteAddress == null) { LOG.warn("IP address of the node {} cannot be obtained. No connection with switch.", deviceContext - .getDeviceState().getNodeId()); + .getDeviceInfo().getNodeId()); return null; } LOG.info("IP address of switch is: {}", remoteAddress); @@ -376,7 +429,9 @@ public class DeviceInitializationUtils { // FIXME : remove after ovs tableFeatures fix private static void makeEmptyTables(final DeviceContext dContext, final InstanceIdentifier nodeII, final Short nrOfTables) { - LOG.debug("About to create {} empty tables.", nrOfTables); + if (LOG.isDebugEnabled()) { + LOG.debug("About to create {} empty tables.", nrOfTables); + } for (int i = 0; i < nrOfTables; i++) { final short tId = (short) i; final InstanceIdentifier tableII = nodeII.augmentation(FlowCapableNode.class).child(Table.class, @@ -387,7 +442,7 @@ public class DeviceInitializationUtils { try { dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableII, tableBuilder.build()); } catch (final Exception e) { - LOG.debug("Failed to write node {} to DS ", dContext.getDeviceState().getNodeId().toString(), e); + LOG.debug("makeEmptyTables: Failed to write node {} to DS ", dContext.getDeviceInfo().getNodeId().toString(), e); } } @@ -395,20 +450,19 @@ public class DeviceInitializationUtils { static void createSuccessProcessingCallback(final MultipartType type, final DeviceContext deviceContext, final InstanceIdentifier nodeII, - final ListenableFuture>> requestContextFuture) { + final ListenableFuture>> requestContextFuture, + final ConvertorExecutor convertorExecutor) { Futures.addCallback(requestContextFuture, new FutureCallback>>() { @Override public void onSuccess(final RpcResult> rpcResult) { final List result = rpcResult.getResult(); if (result != null) { - LOG.info("Static node {} info: {} collected", deviceContext.getDeviceState().getNodeId(), type); - translateAndWriteReply(type, deviceContext, nodeII, result); + LOG.info("Static node {} info: {} collected", deviceContext.getDeviceInfo().getNodeId(), type); + translateAndWriteReply(type, deviceContext, nodeII, result, convertorExecutor); } else { - final Iterator rpcErrorIterator = rpcResult.getErrors().iterator(); - while (rpcErrorIterator.hasNext()) { - final RpcError rpcError = rpcErrorIterator.next(); + for (RpcError rpcError : rpcResult.getErrors()) { LOG.info("Failed to retrieve static node {} info: {}", type, rpcError.getMessage()); - if (null != rpcError.getCause()) { + if (LOG.isTraceEnabled() && Objects.nonNull(rpcError.getCause())) { LOG.trace("Detailed error:", rpcError.getCause()); } } @@ -427,11 +481,13 @@ public class DeviceInitializationUtils { } private static ListenableFuture>> getNodeStaticInfo(final MultipartType type, - final DeviceContext deviceContext, final InstanceIdentifier nodeII, final short version) { + final DeviceContext deviceContext, + final InstanceIdentifier nodeII, + final short version) { final OutboundQueue queue = deviceContext.getPrimaryConnectionContext().getOutboundQueueProvider(); - final Long reserved = deviceContext.reserveXidForDeviceMessage(); + final Long reserved = deviceContext.getDeviceInfo().reserveXidForDeviceMessage(); final RequestContext> requestContext = new AbstractRequestContext>( reserved) { @Override @@ -442,6 +498,11 @@ public class DeviceInitializationUtils { final Xid xid = requestContext.getXid(); + if (Objects.isNull(xid)) { + LOG.debug("Xid is not present, so cancelling node static info gathering."); + return Futures.immediateCancelledFuture(); + } + LOG.trace("Hooking xid {} to device context - precaution.", reserved); final MultiMsgCollector multiMsgCollector = deviceContext.getMultiMsgCollector(requestContext); @@ -480,24 +541,32 @@ public class DeviceInitializationUtils { static void chainTableTrunkWriteOF10(final DeviceContext deviceContext, final ListenableFuture>>> deviceFeaturesFuture) { - Futures.addCallback(deviceFeaturesFuture, new FutureCallback>>>() { - @Override - public void onSuccess(final List>> results) { - boolean allSucceeded = true; - for (final RpcResult> rpcResult : results) { - allSucceeded &= rpcResult.isSuccessful(); + + try { + if (LOG.isTraceEnabled()) { + LOG.trace("Waiting for protocol version 1.0"); + } + List>> results = deviceFeaturesFuture.get(); + boolean allSucceeded = true; + for (final RpcResult> rpcResult : results) { + allSucceeded &= rpcResult.isSuccessful(); + } + if (allSucceeded) { + if (LOG.isDebugEnabled()) { + LOG.debug("Creating empty flow capable node: {}", deviceContext.getDeviceInfo().getLOGValue()); } - if (allSucceeded) { - createEmptyFlowCapableNodeInDs(deviceContext); - makeEmptyTables(deviceContext, deviceContext.getDeviceState().getNodeInstanceIdentifier(), - deviceContext.getDeviceState().getFeatures().getTables()); + createEmptyFlowCapableNodeInDs(deviceContext); + if (LOG.isDebugEnabled()) { + LOG.debug("Creating empty tables for {}", deviceContext.getDeviceInfo().getLOGValue()); } + makeEmptyTables(deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), + deviceContext.getPrimaryConnectionContext().getFeatures().getTables()); } - - @Override - public void onFailure(final Throwable t) { - //NOOP + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Error occurred in preparation node {} for protocol 1.0", deviceContext.getDeviceInfo().getLOGValue()); + if (LOG.isTraceEnabled()) { + LOG.trace("Error for node {} : ", deviceContext.getDeviceInfo().getLOGValue(), e); } - }); + } } }