namespace "urn:opendaylight:openflowplugin:experimenter:types";
prefix exp-type;
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
+
revision "2015-10-20" {
description "Initial revision of experimenter basic types";
}
// to be augmented by vendors
}
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-experimenter {
+ uses experimenter-core-message;
+ }
+ }
+
}
--- /dev/null
+module opendaylight-multipart-types {
+ namespace "urn:opendaylight:multipart:types";
+ prefix multipart;
+
+ import openflow-protocol { prefix ofproto; revision-date "2013-07-31"; }
+
+ revision "2017-01-12" {
+ description "Initial revision";
+ }
+
+ container multipart-reply {
+ uses ofproto:ofHeader;
+
+ leaf request-more {
+ type boolean;
+ default false;
+ }
+
+ choice multipart-reply-body {
+ }
+ }
+}
import ietf-yang-types {prefix yang; revision-date "2013-07-15";}
import opendaylight-queue-types {prefix queue-types; revision-date "2013-09-25";}
import openflow-protocol { prefix ofproto; revision-date "2013-07-31"; }
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
revision "2013-09-25" {
description "Initial revision of Port Inventory model";
}
-
+
typedef port-reason {
type enumeration {
enum add;
enum update;
}
}
-
+
typedef port-config {
type bits {
bit PORT-DOWN;
bit NO-PACKET-IN;
}
}
-
+
grouping port-state {
leaf link-down {
type boolean;
}
leaf blocked {
type boolean;
- }
+ }
leaf live {
type boolean;
}
}
-
+
typedef port-features {
type bits {
bit ten-mb-hd;
bit pause-asym;
}
}
-
+
typedef port-number-uni {
description "Union port number: 4B number / string (reserved port name)";
type union {
type string;
}
}
-
+
grouping common-port {
leaf port-number {
type port-number-uni;
}
-
+
leaf hardware-address {
type yang:mac-address;
description "MAC Address of the port";
-
+
}
-
+
leaf configuration {
type port-config;
- description "Bit map of OFPPC-* flags";
+ description "Bit map of OFPPC-* flags";
}
-
+
leaf advertised-features {
type port-features;
- description "Features being advertised by the port";
+ description "Features being advertised by the port";
}
}
-
+
grouping flow-port-status {
leaf reason {
type port-reason;
}
-
+
uses flow-capable-port;
}
-
+
grouping queues {
list queue {
key "queue-id";
uses queue-types:queue-packet;
}
}
-
- grouping flow-capable-port {
-
+
+ grouping flow-capable-port {
+
uses common-port;
-
+
leaf name {
type string;
- description "Human readable name of the port";
+ description "Human readable name of the port";
}
-
+
container state {
uses port-state;
- description "Description of state of port";
+ description "Description of state of port";
}
-
+
leaf current-feature {
type port-features;
- description "Bit map of OFPPF-* flags";
- }
-
+ description "Bit map of OFPPF-* flags";
+ }
+
leaf supported {
type port-features;
- description "Features supported by the port";
+ description "Features supported by the port";
}
-
+
leaf peer-features {
type port-features;
- description "Features advertised by peer";
+ description "Features advertised by peer";
}
-
+
leaf current-speed {
type uint32;
units "kbps";
- description "Current port bit rate in kbps";
+ description "Current port bit rate in kbps";
}
-
+
leaf maximum-speed {
type uint32;
units "kbps";
- description "Max port bit rate in kbps";
+ description "Max port bit rate in kbps";
}
-
+
uses queues;
- }
-
+ }
+
grouping port-mod {
container port {
list port {
key "port-mod-order";
leaf port-mod-order {
type uint32;
- }
-
+ }
+
uses common-port;
-
+
leaf mask {
type port-config;
description "Bitmap of OFPPC-* flags to be changed";
- }
-
+ }
+
leaf container-name {
- type string;
+ type string;
}
-
+
leaf port-name {
- type string;
- }
+ type string;
+ }
leaf barrier {
- type boolean;
- }
- }
- }
+ type boolean;
+ }
+ }
+ }
}
container port-message {
uses common-port;
uses ofproto:ofHeader;
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-port-desc {
+ list ports {
+ uses flow-capable-port;
+ }
+ }
+ }
}
import opendaylight-flow-types {prefix flow;revision-date "2013-10-26";}
import opendaylight-group-types {prefix group;revision-date "2013-10-18";}
import opendaylight-meter-types {prefix meter;revision-date "2013-09-18";}
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
description "Flow Capable Node extensions to the Inventory model";
}
}
- grouping flow-node {
- description "Openflow node structure = device";
+ grouping desc {
leaf manufacturer {
type string;
}
leaf description {
type string;
}
+ }
+ grouping flow-node {
+ description "Openflow node structure = device";
+ uses desc;
uses tables;
uses table:table-features;
uses group:groups;
This is contructed by asynchronous process.";
uses snapshot-gathering-status-grouping;
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-desc {
+ uses desc;
+ }
+ }
}
description "Openflow table identifier";
type instance-identifier;
}
-
+
grouping node-flow-removed {
description "Flow removed message structure.";
leaf node {
}
uses types:flow-mod-removed;
}
-
+
grouping node-flow {
description "Top openflow flow structure suitable for rpc input (contains node-context).";
uses "inv:node-context-ref";
leaf flow-ref {
type types:flow-ref;
}
- uses node-flow;
+ uses node-flow;
}
output {
uses tr:transaction-aware;
leaf flow-ref {
type types:flow-ref;
}
- uses node-flow;
+ uses node-flow;
}
output {
uses tr:transaction-aware;
leaf flow-ref {
type types:flow-ref;
}
- uses flow-update;
+ uses flow-update;
}
output {
uses tr:transaction-aware;
type types:flow-ref;
}
uses node-flow;
- uses tr:transaction-aware;
+ uses tr:transaction-aware;
}
notification flow-removed {
uses node-flow;
uses tr:transaction-aware;
}
-
+
notification switch-flow-removed {
status deprecated;
uses node-flow-removed;
}
-
+
notification node-error-notification {
status deprecated;
uses node-error-reference;
uses base-node-error-notification;
}
-
+
notification node-experimenter-error-notification {
status deprecated;
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";}
import flow-capable-transaction {prefix tr; revision-date "2015-03-04";}
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
description "Openflow table management.";
uses tr:multipart-transaction-aware;
uses table-type:table-features;
}
+
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-table-features {
+ uses table-type:table-features;
+ }
+ }
}
import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
import flow-capable-transaction {prefix tr;}
import ietf-inet-types {prefix inet; revision-date "2013-07-15";}
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
description "Openflow statistics polling.";
}
rpc get-aggregate-flow-statistics-from-flow-table-for-given-match {
- description "Fetch aggregate statistics for flows filtered by
+ description "Fetch aggregate statistics for flows filtered by
- table (eventually all tables)
- match
- port
uses stat-types:aggregate-flow-statistics;
uses tr:multipart-transaction-aware;
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-flow-stats {
+ uses flow-and-statistics-map-list;
+ }
+
+ case multipart-reply-flow-aggregate-stats {
+ uses stat-types:aggregate-flow-statistics;
+ }
+ }
}
import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
import opendaylight-table-types {prefix table-types;revision-date "2013-10-26";}
import opendaylight-statistics-types {prefix stat-types;revision-date "2013-09-25";}
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
description "Openflow flow table statistics structures.";
uses flow-table-and-statistics-map;
uses tr:multipart-transaction-aware;
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-flow-table-stats {
+ uses flow-table-and-statistics-map;
+ }
+ }
}
import opendaylight-group-types {prefix group-types;revision-date "2013-10-18";}
import flow-capable-transaction {prefix tr; revision-date "2015-03-04";}
import flow-node-inventory {prefix fni; revision-date "2013-08-19";}
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
description "Openflow group statistics structures.";
uses group-types:group-features-reply;
uses tr:multipart-transaction-aware;
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-group-stats {
+ uses group-types:group-statistics-reply;
+ }
+
+ case multipart-reply-group-desc {
+ uses group-types:group-desc-stats-reply;
+ }
+
+ case multipart-reply-group-features {
+ uses group-types:group-features-reply;
+ }
+ }
}
import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
import opendaylight-meter-types {prefix meter-types; revision-date "2013-09-18";}
import flow-capable-transaction {prefix tr; revision-date "2015-03-04";}
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
description "Openflowplugin meter statistics structures.";
uses meter-types:meter-features-reply;
uses tr:multipart-transaction-aware;
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-meter-stats {
+ uses meter-types:meter-statistics-reply;
+ }
+
+ case multipart-reply-meter-config {
+ uses meter-types:meter-config-stats-reply;
+ }
+
+ case multipart-reply-meter-features {
+ uses meter-types:meter-features-reply;
+ }
+ }
}
import yang-ext {prefix ext; revision-date "2013-07-09";}
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import opendaylight-statistics-types {prefix stat-types;revision-date "2013-09-25";}
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
description "Openflow port statistics structures.";
ext:augment-identifier "flow-capable-node-connector-statistics-data";
uses flow-capable-node-connector-statistics;
}
-
+
grouping flow-capable-node-connector-statistics {
description "TODO:: simplify";
container flow-capable-node-connector-statistics {
uses stat-types:node-connector-statistics;
}
}
-
+
// RPC calls
rpc get-all-node-connectors-statistics {
status deprecated;
uses node-connector-statistics-and-port-number-map;
uses tr:multipart-transaction-aware;
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-port-stats {
+ uses node-connector-statistics-and-port-number-map;
+ }
+ }
}
import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
import opendaylight-queue-types {prefix queue-types;revision-date "2013-09-25";}
import opendaylight-statistics-types {prefix stat-types;revision-date "2013-09-25";}
+ import opendaylight-multipart-types { prefix multipart; revision-date "2017-01-12"; }
description "Openflowplugin queue statistics structures.";
uses queue-id-and-statistics-map;
uses tr:multipart-transaction-aware;
}
+
+ augment "/multipart:multipart-reply/multipart:multipart-reply-body" {
+ case multipart-reply-queue-stats {
+ uses queue-id-and-statistics-map;
+ }
+ }
}
ActionDeserializerInjector.injectDeserializers(provider);
InstructionDeserializerInjector.injectDeserializers(provider);
MessageDeserializerInjector.injectDeserializers(provider);
+ MultipartDeserializerInjector.injectDeserializers(provider);
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.openflowplugin.impl.protocol.deserialization;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.api.keys.TypeToClassKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyDescDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyExperimenterDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyFlowAggregateStatsDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyFlowStatsDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyFlowTableStatsDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyGroupDescDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyGroupFeaturesDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyGroupStatsDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyMessageDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyMeterConfigDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyMeterFeaturesDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyMeterStatsDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyPortDescDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyPortStatsDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyQueueStatsDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyTableFeaturesDeserializer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+
+public class MultipartDeserializerInjector {
+
+ /**
+ * Injects message deserializers into provided {@link org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider}
+ * @param provider OpenflowJava deserializer extension provider
+ */
+ static void injectDeserializers(final DeserializerExtensionProvider provider) {
+ final short version = EncodeConstants.OF13_VERSION_ID;
+
+ // Inject main multipart reply deserializer
+ injectMultipartReplyDeserializer(provider, version);
+
+ // Inject new multipart body deserializers here using injector created by createInjector method
+ final Function<Integer, Consumer<OFDeserializer<? extends MultipartReplyBody>>> injector =
+ createInjector(provider, version);
+ injector.apply(MultipartType.OFPMPDESC.getIntValue()).accept(new MultipartReplyDescDeserializer());
+ injector.apply(MultipartType.OFPMPFLOW.getIntValue()).accept(new MultipartReplyFlowStatsDeserializer());
+ injector.apply(MultipartType.OFPMPAGGREGATE.getIntValue()).accept(new MultipartReplyFlowAggregateStatsDeserializer());
+ injector.apply(MultipartType.OFPMPTABLE.getIntValue()).accept(new MultipartReplyFlowTableStatsDeserializer());
+ injector.apply(MultipartType.OFPMPPORTSTATS.getIntValue()).accept(new MultipartReplyPortStatsDeserializer());
+ injector.apply(MultipartType.OFPMPQUEUE.getIntValue()).accept(new MultipartReplyQueueStatsDeserializer());
+ injector.apply(MultipartType.OFPMPGROUP.getIntValue()).accept(new MultipartReplyGroupStatsDeserializer());
+ injector.apply(MultipartType.OFPMPGROUPDESC.getIntValue()).accept(new MultipartReplyGroupDescDeserializer());
+ injector.apply(MultipartType.OFPMPGROUPFEATURES.getIntValue()).accept(new MultipartReplyGroupFeaturesDeserializer());
+ injector.apply(MultipartType.OFPMPMETER.getIntValue()).accept(new MultipartReplyMeterStatsDeserializer());
+ injector.apply(MultipartType.OFPMPMETERCONFIG.getIntValue()).accept(new MultipartReplyMeterConfigDeserializer());
+ injector.apply(MultipartType.OFPMPMETERFEATURES.getIntValue()).accept(new MultipartReplyMeterFeaturesDeserializer());
+ injector.apply(MultipartType.OFPMPTABLEFEATURES.getIntValue()).accept(new MultipartReplyTableFeaturesDeserializer());
+ injector.apply(MultipartType.OFPMPPORTDESC.getIntValue()).accept(new MultipartReplyPortDescDeserializer());
+ injector.apply(MultipartType.OFPMPEXPERIMENTER.getIntValue()).accept(new MultipartReplyExperimenterDeserializer());
+ }
+
+ /**
+ * Register main multipart reply deserializer
+ * @param provider OpenflowJava deserializer extension provider
+ * @param version Openflow version
+ */
+ static void injectMultipartReplyDeserializer(final DeserializerExtensionProvider provider, final short version) {
+ final short code = 19;
+ final Class<? extends OfHeader> retType = MultipartReply.class;
+ provider.unregisterDeserializerMapping(new TypeToClassKey(version, code));
+ provider.registerDeserializerMapping(new TypeToClassKey(version, code), retType);
+ provider.registerDeserializer(
+ new MessageCodeKey(version, code, retType),
+ new MultipartReplyMessageDeserializer());
+ }
+
+ /**
+ * Create injector that will inject new deserializers into #{@link org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider}
+ * @param provider OpenflowJava deserializer extension provider
+ * @param version Openflow version
+ * @return injector
+ */
+ @VisibleForTesting
+ static Function<Integer, Consumer<OFDeserializer<? extends MultipartReplyBody>>> createInjector(
+ final DeserializerExtensionProvider provider,
+ final short version) {
+ return code -> deserializer -> {
+ provider.registerDeserializer(
+ new MessageCodeKey(version, code, MultipartReplyBody.class),
+ deserializer);
+ };
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.multipart.reply.multipart.reply.body.MultipartReplyDescBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyDescDeserializer implements OFDeserializer<MultipartReplyBody> {
+ private static final int DESC_STR_LEN = 256;
+ private static final int SERIAL_NUM_LEN = 32;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ byte[] mfrDescBytes = new byte[DESC_STR_LEN];
+ message.readBytes(mfrDescBytes);
+
+ byte[] hwDescBytes = new byte[DESC_STR_LEN];
+ message.readBytes(hwDescBytes);
+
+ byte[] swDescBytes = new byte[DESC_STR_LEN];
+ message.readBytes(swDescBytes);
+
+ byte[] serialNumBytes = new byte[SERIAL_NUM_LEN];
+ message.readBytes(serialNumBytes);
+
+ byte[] dpDescBytes = new byte[DESC_STR_LEN];
+ message.readBytes(dpDescBytes);
+
+ return new MultipartReplyDescBuilder()
+ .setManufacturer(new String(mfrDescBytes))
+ .setHardware(new String(hwDescBytes))
+ .setSoftware(new String(swDescBytes))
+ .setSerialNumber(new String(serialNumBytes))
+ .setDescription(new String(dpDescBytes))
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdTypeDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.util.ExperimenterDeserializerKeyFactory;
+import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
+import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
+import org.opendaylight.openflowplugin.extension.api.path.MessagePath;
+import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.multipart.reply.multipart.reply.body.MultipartReplyExperimenterBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MultipartReplyExperimenterDeserializer implements OFDeserializer<MultipartReplyBody>, DeserializerRegistryInjector {
+ private static final Logger LOG = LoggerFactory.getLogger(MultipartReplyExperimenterDeserializer.class);
+ private DeserializerRegistry registry;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyExperimenterBuilder builder = new MultipartReplyExperimenterBuilder();
+ final long expId = message.readUnsignedInt();
+ final long expType = message.readUnsignedInt();
+
+ try {
+ final OFDeserializer<ExperimenterMessageOfChoice> deserializer = registry
+ .getDeserializer(new ExperimenterIdTypeDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID, expId, expType, ExperimenterMessageOfChoice.class));
+
+ builder.setExperimenterMessageOfChoice(deserializer.deserialize(message));
+ } catch (ClassCastException | IllegalStateException es) {
+ final OFDeserializer<ExperimenterDataOfChoice> deserializer = registry.getDeserializer(
+ ExperimenterDeserializerKeyFactory.createMultipartReplyMessageDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID, expId, expType));
+
+ final ExperimenterDataOfChoice data = deserializer.deserialize(message);
+ final MessageTypeKey<? extends ExperimenterDataOfChoice> key = new MessageTypeKey<>(
+ EncodeConstants.OF13_VERSION_ID,
+ (Class<? extends ExperimenterDataOfChoice>) data.getImplementedInterface());
+
+ final ConvertorMessageFromOFJava<ExperimenterDataOfChoice, MessagePath> convertor = OFSessionUtil
+ .getExtensionConvertorProvider()
+ .getMessageConverter(key);
+
+ try {
+ builder.setExperimenterMessageOfChoice(convertor.convert(data, MessagePath.MPMESSAGE_RPC_OUTPUT));
+ } catch (ConversionException ce) {
+ LOG.debug("Failed to deserialize multipart reply experimenter for key: {}", key);
+ }
+ }
+
+ return builder.build();
+ }
+
+ @Override
+ public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+ registry = deserializerRegistry;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.math.BigInteger;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowAggregateStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyFlowAggregateStatsDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ private static final byte PADDING_IN_AGGREGATE_HEADER = 4;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyFlowAggregateStatsBuilder builder = new MultipartReplyFlowAggregateStatsBuilder()
+ .setPacketCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setByteCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setFlowCount(new Counter32(message.readUnsignedInt()));
+
+ message.skipBytes(PADDING_IN_AGGREGATE_HEADER);
+ return builder.build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MessageCodeExperimenterKey;
+import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
+import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeActionExperimenterKey;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeMatchKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyFlowStatsDeserializer implements OFDeserializer<MultipartReplyBody>, DeserializerRegistryInjector {
+
+ private static final MessageCodeKey MATCH_KEY = new MessageCodeMatchKey(EncodeConstants.OF13_VERSION_ID,
+ EncodeConstants.EMPTY_VALUE, Match.class,
+ MatchPath.FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_MATCH);
+
+ private static final byte PADDING_IN_FLOW_STATS_HEADER_01 = 1;
+ private static final byte PADDING_IN_FLOW_STATS_HEADER_02 = 4;
+ private DeserializerRegistry registry;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyFlowStatsBuilder builder = new MultipartReplyFlowStatsBuilder();
+ final List<FlowAndStatisticsMapList> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final FlowAndStatisticsMapListBuilder itemBuilder = new FlowAndStatisticsMapListBuilder();
+ final int itemLength = message.readUnsignedShort();
+ final ByteBuf itemMessage = message.readSlice(itemLength - EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+
+ itemBuilder.setTableId(itemMessage.readUnsignedByte());
+ itemMessage.skipBytes(PADDING_IN_FLOW_STATS_HEADER_01);
+
+
+ itemBuilder
+ .setDuration(new DurationBuilder()
+ .setSecond(new Counter32(itemMessage.readUnsignedInt()))
+ .setNanosecond(new Counter32(itemMessage.readUnsignedInt()))
+ .build())
+ .setPriority(itemMessage.readUnsignedShort())
+ .setIdleTimeout(itemMessage.readUnsignedShort())
+ .setHardTimeout(itemMessage.readUnsignedShort())
+ .setFlags(createFlowModFlagsFromBitmap(itemMessage.readUnsignedShort()));
+
+ itemMessage.skipBytes(PADDING_IN_FLOW_STATS_HEADER_02);
+
+ itemBuilder
+ .setCookie(new FlowCookie(BigInteger.valueOf(message.readLong())))
+ .setCookieMask(new FlowCookie(BigInteger.valueOf(message.readLong())))
+ .setPacketCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setByteCount(new Counter64(BigInteger.valueOf(message.readLong())));
+
+
+ final OFDeserializer<Match> matchDeserializer = registry.getDeserializer(MATCH_KEY);
+ itemBuilder.setMatch(new MatchBuilder(matchDeserializer.deserialize(message)).build());
+
+ final int length = itemMessage.readableBytes();
+
+ if (length > 0) {
+ final List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
+ .Instruction> instructions = new ArrayList<>();
+ final int startIndex = itemMessage.readerIndex();
+ int offset = 0;
+
+ while ((itemMessage.readerIndex() - startIndex) < length) {
+ final int type = itemMessage.getUnsignedShort(itemMessage.readerIndex());
+ OFDeserializer<Instruction> deserializer = null;
+
+ if (InstructionConstants.APPLY_ACTIONS_TYPE == type) {
+ deserializer = registry.getDeserializer(
+ new MessageCodeActionExperimenterKey(
+ EncodeConstants.OF13_VERSION_ID, type, Instruction.class,
+ ActionPath.NODES_NODE_TABLE_FLOW_INSTRUCTIONS_INSTRUCTION_APPLYACTIONSCASE_APPLYACTIONS_ACTION_ACTION_EXTENSIONLIST_EXTENSION,
+ null));
+ } else if (InstructionConstants.WRITE_ACTIONS_TYPE == type) {
+ deserializer = registry.getDeserializer(
+ new MessageCodeActionExperimenterKey(
+ EncodeConstants.OF13_VERSION_ID, type, Instruction.class,
+ ActionPath.NODES_NODE_TABLE_FLOW_INSTRUCTIONS_INSTRUCTION_WRITEACTIONSCASE_WRITEACTIONS_ACTION_ACTION_EXTENSIONLIST_EXTENSION,
+ null));
+ } else {
+ Long expId = null;
+
+ if (EncodeConstants.EXPERIMENTER_VALUE == type) {
+ expId = itemMessage.getUnsignedInt(itemMessage.readerIndex() +
+ 2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+ }
+
+ deserializer = registry.getDeserializer(
+ new MessageCodeExperimenterKey(
+ EncodeConstants.OF13_VERSION_ID, type, Instruction.class, expId));
+ }
+
+ instructions.add(new InstructionBuilder()
+ .setKey(new InstructionKey(offset))
+ .setOrder(offset)
+ .setInstruction(deserializer.deserialize(itemMessage))
+ .build());
+
+ offset++;
+ }
+
+ itemBuilder.setInstructions(new InstructionsBuilder()
+ .setInstruction(instructions)
+ .build());
+ }
+
+ items.add(itemBuilder.build());
+ }
+
+ return builder
+ .setFlowAndStatisticsMapList(items)
+ .build();
+ }
+
+ private static FlowModFlags createFlowModFlagsFromBitmap(int input) {
+ final Boolean _oFPFFSENDFLOWREM = (input & (1 << 0)) > 0;
+ final Boolean _oFPFFCHECKOVERLAP = (input & (1 << 1)) > 0;
+ final Boolean _oFPFFRESETCOUNTS = (input & (1 << 2)) > 0;
+ final Boolean _oFPFFNOPKTCOUNTS = (input & (1 << 3)) > 0;
+ final Boolean _oFPFFNOBYTCOUNTS = (input & (1 << 4)) > 0;
+ return new FlowModFlags(_oFPFFCHECKOVERLAP, _oFPFFNOBYTCOUNTS, _oFPFFNOPKTCOUNTS, _oFPFFRESETCOUNTS,
+ _oFPFFSENDFLOWREM);
+ }
+
+ @Override
+ public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+ registry = deserializerRegistry;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.multipart.reply.multipart.reply.body.MultipartReplyFlowTableStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
+
+public class MultipartReplyFlowTableStatsDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ private static final byte PADDING_IN_TABLE_HEADER = 3;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyFlowTableStatsBuilder builder = new MultipartReplyFlowTableStatsBuilder();
+ final List<FlowTableAndStatisticsMap> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final FlowTableAndStatisticsMapBuilder itemBuilder = new FlowTableAndStatisticsMapBuilder()
+ .setTableId(new TableId(message.readUnsignedByte()));
+
+ message.skipBytes(PADDING_IN_TABLE_HEADER);
+
+ items.add(itemBuilder
+ .setActiveFlows(new Counter32(message.readUnsignedInt()))
+ .setPacketsLookedUp(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setPacketsMatched(new Counter64(BigInteger.valueOf(message.readLong())))
+ .build());
+ }
+
+ return builder
+ .setFlowTableAndStatisticsMap(items)
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.util.ActionUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupDescBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyGroupDescDeserializer implements OFDeserializer<MultipartReplyBody>, DeserializerRegistryInjector {
+
+ private static final byte PADDING_IN_GROUP_DESC_HEADER = 1;
+ private static final byte PADDING_IN_BUCKETS_HEADER = 4;
+ private static final byte GROUP_DESC_HEADER_LENGTH = 8;
+ private static final byte BUCKETS_HEADER_LENGTH = 16;
+ private DeserializerRegistry registry;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyGroupDescBuilder builder = new MultipartReplyGroupDescBuilder();
+ final List<GroupDescStats> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final int itemLength = message.readUnsignedShort();
+
+ final GroupDescStatsBuilder itemBuilder = new GroupDescStatsBuilder()
+ .setGroupType(GroupTypes.forValue(message.readUnsignedByte()));
+
+ message.skipBytes(PADDING_IN_GROUP_DESC_HEADER);
+ itemBuilder.setGroupId(new GroupId(message.readUnsignedInt()));
+
+ final List<Bucket> subItems = new ArrayList<>();
+ int actualLength = GROUP_DESC_HEADER_LENGTH;
+
+ while (actualLength < itemLength) {
+ final int bucketsLength = message.readUnsignedShort();
+
+ final BucketBuilder bucketBuilder = new BucketBuilder()
+ .setWeight(message.readUnsignedShort())
+ .setWatchPort(message.readUnsignedInt())
+ .setWatchGroup(message.readUnsignedInt());
+
+ message.skipBytes(PADDING_IN_BUCKETS_HEADER);
+
+ if (message.readableBytes() > 0) {
+ final List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list
+ .Action> actions = new ArrayList<>();
+ final int startIndex = message.readerIndex();
+ final int bucketLength = bucketsLength - BUCKETS_HEADER_LENGTH;
+ int offset = 0;
+
+ while ((message.readerIndex() - startIndex) < bucketLength) {
+ actions.add(new ActionBuilder()
+ .setKey(new ActionKey(offset))
+ .setOrder(offset)
+ .setAction(ActionUtil.readAction(EncodeConstants.OF13_VERSION_ID, message, registry,
+ ActionPath.GROUPDESCSTATSUPDATED_GROUPDESCSTATS_BUCKETS_BUCKET_ACTION))
+ .build());
+
+ offset++;
+ }
+
+ bucketBuilder.setAction(actions);
+ }
+
+ subItems.add(bucketBuilder.build());
+ actualLength += bucketsLength;
+ }
+
+ items.add(itemBuilder
+ .setBuckets(new BucketsBuilder()
+ .setBucket(subItems)
+ .build())
+ .build());
+ }
+
+ return builder
+ .setGroupDescStats(items)
+ .build();
+ }
+
+ @Override
+ public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+ registry = deserializerRegistry;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Chaining;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.ChainingChecks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupAll;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupIndirect;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupSelect;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectLiveness;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectWeight;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyGroupFeaturesDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ private static final int GROUP_TYPES = 4;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyGroupFeaturesBuilder builder = new MultipartReplyGroupFeaturesBuilder();
+
+ return builder
+ .setGroupTypesSupported(readGroupTypes(message))
+ .setGroupCapabilitiesSupported(readGroupCapabilities(message))
+ .setMaxGroups(IntStream
+ .range(0, GROUP_TYPES)
+ .mapToObj(i -> message.readUnsignedInt())
+ .collect(Collectors.toList()))
+ .setActions(IntStream
+ .range(0, GROUP_TYPES)
+ .mapToObj(i -> message.readUnsignedInt())
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ private static List<Class<? extends GroupCapability>> readGroupCapabilities(ByteBuf message) {
+ final List<Class<? extends GroupCapability>> groupCapabilities = new ArrayList<>();
+ final long capabilitiesMask = message.readUnsignedInt();
+
+ final boolean gcSelectWeight = ((capabilitiesMask) & (1 << 0)) != 0;
+ final boolean gcSelectLiveness = ((capabilitiesMask) & (1 << 1)) != 0;
+ final boolean gcChaining = ((capabilitiesMask) & (1 << 2)) != 0;
+ final boolean gcChainingChecks = ((capabilitiesMask) & (1 << 3)) != 0;
+
+ if (gcSelectWeight) groupCapabilities.add(SelectWeight.class);
+ if (gcSelectLiveness) groupCapabilities.add(SelectLiveness.class);
+ if (gcChaining) groupCapabilities.add(Chaining.class);
+ if (gcChainingChecks) groupCapabilities.add(ChainingChecks.class);
+
+ return groupCapabilities;
+ }
+
+ private static List<Class<? extends GroupType>> readGroupTypes(ByteBuf message) {
+ final List<Class<? extends GroupType>> groupTypes = new ArrayList<>();
+ final long typesMask = message.readUnsignedInt();
+
+ final boolean gtAll = ((typesMask) & (1 << 0)) != 0;
+ final boolean gtSelect = ((typesMask) & (1 << 1)) != 0;
+ final boolean gtIndirect = ((typesMask) & (1 << 2)) != 0;
+ final boolean gtFF = ((typesMask) & (1 << 3)) != 0;
+
+ if (gtAll) groupTypes.add(GroupAll.class);
+ if (gtSelect) groupTypes.add(GroupSelect.class);
+ if (gtIndirect) groupTypes.add(GroupIndirect.class);
+ if (gtFF) groupTypes.add(GroupFf.class);
+
+ return groupTypes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.BucketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.buckets.BucketCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.buckets.BucketCounterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyGroupStatsDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ private static final byte PADDING_IN_GROUP_HEADER_01 = 2;
+ private static final byte PADDING_IN_GROUP_HEADER_02 = 4;
+ private static final byte GROUP_BODY_LENGTH = 40;
+ private static final byte BUCKET_COUNTER_LENGTH = 16;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyGroupStatsBuilder builder = new MultipartReplyGroupStatsBuilder();
+ final List<GroupStats> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final int itemLength = message.readUnsignedShort();
+ message.skipBytes(PADDING_IN_GROUP_HEADER_01);
+
+ final GroupStatsBuilder itemBuilder = new GroupStatsBuilder()
+ .setGroupId(new GroupId(message.readUnsignedInt()))
+ .setRefCount(new Counter32(message.readUnsignedInt()));
+
+ message.skipBytes(PADDING_IN_GROUP_HEADER_02);
+
+ itemBuilder
+ .setPacketCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setByteCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setDuration(new DurationBuilder()
+ .setSecond(new Counter32(message.readUnsignedInt()))
+ .setNanosecond(new Counter32(message.readUnsignedInt()))
+ .build());
+
+ final List<BucketCounter> subItems = new ArrayList<>();
+ int actualLength = GROUP_BODY_LENGTH;
+
+ while (actualLength < itemLength) {
+ subItems.add(new BucketCounterBuilder()
+ .setPacketCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setByteCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .build());
+
+ actualLength += BUCKET_COUNTER_LENGTH;
+ }
+
+ items.add(itemBuilder
+ .setBuckets(new BucketsBuilder()
+ .setBucketCounter(subItems)
+ .build())
+ .build());
+ }
+
+ return builder
+ .setGroupStats(items)
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReplyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+
+public class MultipartReplyMessageDeserializer implements OFDeserializer<MultipartReply>, DeserializerRegistryInjector {
+
+ private static final byte PADDING_IN_MULTIPART_REPLY_HEADER = 4;
+
+ private DeserializerRegistry registry;
+
+ @Override
+ public MultipartReply deserialize(ByteBuf message) {
+ final long xid = message.readUnsignedInt();
+ final int type = message.readUnsignedShort();
+ final boolean reqMore = (message.readUnsignedShort() & 0x01) != 0;
+ message.skipBytes(PADDING_IN_MULTIPART_REPLY_HEADER);
+
+ final OFDeserializer<MultipartReplyBody> deserializer = registry
+ .getDeserializer(new MessageCodeKey(EncodeConstants.OF13_VERSION_ID,
+ type, MultipartReplyBody.class));
+
+ return new MultipartReplyBuilder()
+ .setVersion((short) EncodeConstants.OF13_VERSION_ID)
+ .setXid(xid)
+ .setRequestMore(reqMore)
+ .setMultipartReplyBody(deserializer.deserialize(message))
+ .build();
+ }
+
+ @Override
+ public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+ registry = deserializerRegistry;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DropBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DscpRemarkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Experimenter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.MeterBandHeadersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.meter.band.header.MeterBandTypesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyMeterConfigDeserializer implements OFDeserializer<MultipartReplyBody>, DeserializerRegistryInjector {
+
+ private static final byte METER_CONFIG_LENGTH = 8;
+
+ private static final int OFPMBTDROP = 1;
+ private static final int OFPMBTDSCP = 2;
+ private static final int OFPMBTEXPERIMENTER = 0xFFFF;
+ private static final byte PADDING_IN_METER_BAND_DROP_HEADER = 4;
+ private static final byte PADDING_IN_METER_BAND_DSCP_HEADER = 3;
+
+ private DeserializerRegistry registry;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyMeterConfigBuilder builder = new MultipartReplyMeterConfigBuilder();
+ final List<MeterConfigStats> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final int itemLength = message.readUnsignedShort();
+
+ final MeterConfigStatsBuilder itemBuilder = new MeterConfigStatsBuilder()
+ .setFlags(readMeterFlags(message))
+ .setMeterId(new MeterId(message.readUnsignedInt()));
+
+ final List<MeterBandHeader> subItems = new ArrayList<>();
+ int actualLength = METER_CONFIG_LENGTH;
+
+ while (actualLength < itemLength) {
+ final int itemStartIndex = message.readerIndex();
+ final int itemBandType = message.readUnsignedShort();
+ final MeterBandHeaderBuilder subItemBuilder = new MeterBandHeaderBuilder();
+ actualLength += message.readUnsignedShort();
+
+ switch (itemBandType) {
+ case OFPMBTDROP:
+ subItemBuilder
+ .setMeterBandTypes(new MeterBandTypesBuilder()
+ .setFlags(new MeterBandType(true, false, false))
+ .build())
+ .setBandType(new DropBuilder()
+ .setDropRate(message.readUnsignedInt())
+ .setDropBurstSize(message.readUnsignedInt())
+ .build());
+ message.skipBytes(PADDING_IN_METER_BAND_DROP_HEADER);
+ break;
+
+ case OFPMBTDSCP:
+ subItemBuilder
+ .setMeterBandTypes(new MeterBandTypesBuilder()
+ .setFlags(new MeterBandType(false, true, false))
+ .build())
+ .setBandType(new DscpRemarkBuilder()
+ .setDscpRemarkRate(message.readUnsignedInt())
+ .setDscpRemarkBurstSize(message.readUnsignedInt())
+ .setPrecLevel(message.readUnsignedByte())
+ .build());
+ message.skipBytes(PADDING_IN_METER_BAND_DSCP_HEADER);
+ break;
+
+ case OFPMBTEXPERIMENTER:
+ // TODO: Finish meter band experimenter deserialization
+ final long expId = message.getUnsignedInt(message.readerIndex() + 2 * EncodeConstants.SIZE_OF_INT_IN_BYTES);
+ message.readerIndex(itemStartIndex);
+
+ final OFDeserializer<Experimenter> deserializer = registry.getDeserializer(
+ new ExperimenterIdDeserializerKey(EncodeConstants.OF13_VERSION_ID, expId, Experimenter.class));
+
+ subItemBuilder
+ .setMeterBandTypes(new MeterBandTypesBuilder()
+ .setFlags(new MeterBandType(false, false, true))
+ .build())
+ .setBandType(deserializer.deserialize(message));
+ break;
+
+ }
+ }
+
+ items.add(itemBuilder
+ .setMeterBandHeaders(new MeterBandHeadersBuilder()
+ .setMeterBandHeader(subItems)
+ .build())
+ .build());
+ }
+
+ return builder
+ .setMeterConfigStats(items)
+ .build();
+ }
+
+ private static MeterFlags readMeterFlags(ByteBuf message) {
+ int input = message.readUnsignedShort();
+ final Boolean mfKBPS = (input & (1)) != 0;
+ final Boolean mfPKTPS = (input & (1 << 1)) != 0;
+ final Boolean mfBURST = (input & (1 << 2)) != 0;
+ final Boolean mfSTATS = (input & (1 << 3)) != 0;
+ return new MeterFlags(mfBURST, mfKBPS, mfPKTPS, mfSTATS);
+ }
+
+ @Override
+ public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+ registry = deserializerRegistry;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBand;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDrop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDscpRemark;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBurst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterKbps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterPktps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyMeterFeaturesDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ return new MultipartReplyMeterFeaturesBuilder()
+ .setMaxMeter(new Counter32(message.readUnsignedInt()))
+ .setMeterBandSupported(readMeterBands(message))
+ .setMeterCapabilitiesSupported(readMeterCapabilities(message))
+ .setMaxBands(message.readUnsignedByte())
+ .setMaxColor(message.readUnsignedByte())
+ .build();
+ }
+
+ private static List<Class<? extends MeterBand>> readMeterBands(ByteBuf message) {
+ final List<Class<? extends MeterBand>> bandTypes = new ArrayList<>();
+ final long typesMask = message.readUnsignedInt();
+ final boolean mbtDROP = (typesMask & (1 << 1)) != 0;
+ final boolean mbtDSCPREMARK = (typesMask & (1 << 2)) != 0;
+
+ if (mbtDROP) bandTypes.add(MeterBandDrop.class);
+ if (mbtDSCPREMARK) bandTypes.add(MeterBandDscpRemark.class);
+
+ return bandTypes;
+ }
+
+ private static List<Class<? extends MeterCapability>> readMeterCapabilities(ByteBuf message) {
+ final List<Class<? extends MeterCapability>> meterCapabilities = new ArrayList<>();
+ final long capabilitiesMask = message.readUnsignedInt();
+
+ final boolean mfKBPS = (capabilitiesMask & (1 << 0)) != 0;
+ final boolean mfPKTPS = (capabilitiesMask & (1 << 1)) != 0;
+ final boolean mfBURST = (capabilitiesMask & (1 << 2)) != 0;
+ final boolean mfSTATS = (capabilitiesMask & (1 << 3)) != 0;
+
+ if (mfKBPS) meterCapabilities.add(MeterKbps.class);
+ if (mfPKTPS) meterCapabilities.add(MeterPktps.class);
+ if (mfBURST) meterCapabilities.add(MeterBurst.class);
+ if (mfSTATS) meterCapabilities.add(MeterStats.class);
+
+ return meterCapabilities;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.MeterBandStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.meter.band.stats.BandStat;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.meter.band.stats.BandStatBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyMeterStatsDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ private static final byte PADDING_IN_METER_STATS_HEADER = 6;
+ private static final byte METER_BODY_LENGTH = 40;
+ private static final byte METER_BAND_STATS_LENGTH = 16;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyMeterStatsBuilder builder = new MultipartReplyMeterStatsBuilder();
+ final List<MeterStats> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final MeterStatsBuilder itemBuilder = new MeterStatsBuilder()
+ .setMeterId(new MeterId(message.readUnsignedInt()));
+
+ final int itemLength = message.readUnsignedShort();
+ message.skipBytes(PADDING_IN_METER_STATS_HEADER);
+
+ itemBuilder
+ .setFlowCount(new Counter32(message.readUnsignedInt()))
+ .setPacketInCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setByteInCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setDuration(new DurationBuilder()
+ .setSecond(new Counter32(message.readUnsignedInt()))
+ .setNanosecond(new Counter32(message.readUnsignedInt()))
+ .build());
+
+ final List<BandStat> subItems = new ArrayList<>();
+ int actualLength = METER_BODY_LENGTH;
+
+ while (actualLength < itemLength) {
+ subItems.add(new BandStatBuilder()
+ .setPacketBandCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setByteBandCount(new Counter64(BigInteger.valueOf(message.readLong())))
+ .build());
+
+ actualLength += METER_BAND_STATS_LENGTH;
+ }
+
+ items.add(itemBuilder
+ .setMeterBandStats(new MeterBandStatsBuilder()
+ .setBandStat(subItems)
+ .build())
+ .build());
+ }
+
+ return builder
+ .setMeterStats(items)
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortNumberUni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.MultipartReplyPortDescBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.multipart.reply.port.desc.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.multipart.reply.port.desc.PortsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public class MultipartReplyPortDescDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ private static final byte PADDING_IN_PORT_DESC_HEADER_01 = 4;
+ private static final byte PADDING_IN_PORT_DESC_HEADER_02 = 2;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyPortDescBuilder builder = new MultipartReplyPortDescBuilder();
+ final List<Ports> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final PortsBuilder itemBuilder = new PortsBuilder();
+ itemBuilder.setPortNumber(new PortNumberUni(message.readUnsignedInt()));
+ message.skipBytes(PADDING_IN_PORT_DESC_HEADER_01);
+ itemBuilder.setHardwareAddress(ByteBufUtils.readIetfMacAddress(message));
+ message.skipBytes(PADDING_IN_PORT_DESC_HEADER_02);
+
+ items.add(itemBuilder
+ .setName(ByteBufUtils.decodeNullTerminatedString(message, EncodeConstants.MAX_PORT_NAME_LENGTH))
+ .setConfiguration(readPortConfig(message))
+ .setState(readPortState(message))
+ .setCurrentFeature(readPortFeatures(message))
+ .setAdvertisedFeatures(readPortFeatures(message))
+ .setSupported(readPortFeatures(message))
+ .setPeerFeatures(readPortFeatures(message))
+ .setCurrentSpeed(message.readUnsignedInt())
+ .setMaximumSpeed(message.readUnsignedInt())
+ .build());
+ }
+
+ return builder
+ .setPorts(items)
+ .build();
+ }
+
+
+ private static PortConfig readPortConfig(final ByteBuf message) {
+ final long input = message.readUnsignedInt();
+ final Boolean pcPortDown = ((input) & (1)) != 0;
+ final Boolean pcNRecv = ((input) & (1 << 2)) != 0;
+ final Boolean pcNFwd = ((input) & (1 << 5)) != 0;
+ final Boolean pcNPacketIn = ((input) & (1 << 6)) != 0;
+ return new PortConfig(pcNFwd, pcNPacketIn, pcNRecv, pcPortDown);
+ }
+
+ private static State readPortState(final ByteBuf message) {
+ final long input = message.readUnsignedInt();
+ final Boolean psLinkDown = ((input) & (1)) != 0;
+ final Boolean psBlocked = ((input) & (1 << 1)) != 0;
+ final Boolean psLive = ((input) & (1 << 2)) != 0;
+ return new StateBuilder()
+ .setBlocked(psBlocked)
+ .setLinkDown(psLinkDown)
+ .setLive(psLive)
+ .build();
+ }
+
+ private static PortFeatures readPortFeatures(ByteBuf message) {
+ final long input = message.readUnsignedInt();
+ final Boolean pf10mbHd = ((input) & (1)) != 0;
+ final Boolean pf10mbFd = ((input) & (1 << 1)) != 0;
+ final Boolean pf100mbHd = ((input) & (1 << 2)) != 0;
+ final Boolean pf100mbFd = ((input) & (1 << 3)) != 0;
+ final Boolean pf1gbHd = ((input) & (1 << 4)) != 0;
+ final Boolean pf1gbFd = ((input) & (1 << 5)) != 0;
+ final Boolean pf10gbFd = ((input) & (1 << 6)) != 0;
+ final Boolean pf40gbFd = ((input) & (1 << 7)) != 0;
+ final Boolean pf100gbFd = ((input) & (1 << 8)) != 0;
+ final Boolean pf1tbFd = ((input) & (1 << 9)) != 0;
+ final Boolean pfOther = ((input) & (1 << 10)) != 0;
+ final Boolean pfCopper = ((input) & (1 << 11)) != 0;
+ final Boolean pfFiber = ((input) & (1 << 12)) != 0;
+ final Boolean pfAutoneg = ((input) & (1 << 13)) != 0;
+ final Boolean pfPause = ((input) & (1 << 14)) != 0;
+ final Boolean pfPauseAsym = ((input) & (1 << 15)) != 0;
+ return new PortFeatures(pfAutoneg, pfCopper, pfFiber, pf40gbFd,
+ pf100gbFd, pf100mbFd, pf100mbHd, pf1gbFd, pf1gbHd, pf1tbFd,
+ pfOther, pfPause, pfPauseAsym, pf10gbFd, pf10mbFd, pf10mbHd);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.BytesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.PacketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.multipart.reply.multipart.reply.body.MultipartReplyPortStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
+
+public class MultipartReplyPortStatsDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ private static final byte PADDING_IN_PORT_STATS_HEADER = 4;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyPortStatsBuilder builder = new MultipartReplyPortStatsBuilder();
+ final List<NodeConnectorStatisticsAndPortNumberMap> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final NodeConnectorStatisticsAndPortNumberMapBuilder itemBuilder =
+ new NodeConnectorStatisticsAndPortNumberMapBuilder();
+
+ final long port = message.readUnsignedInt();
+ final String portName = OpenflowPortsUtil.getPortLogicalName(EncodeConstants.OF13_VERSION_ID, port);
+
+ // We do not assign datapath ID here, because we simply do not have it
+ itemBuilder.setNodeConnectorId(new NodeConnectorId(Objects.isNull(portName)
+ ? String.valueOf(port)
+ : portName));
+
+ message.skipBytes(PADDING_IN_PORT_STATS_HEADER);
+
+ items.add(itemBuilder
+ .setPackets(new PacketsBuilder()
+ .setReceived(BigInteger.valueOf(message.readLong()))
+ .setTransmitted(BigInteger.valueOf(message.readLong()))
+ .build())
+ .setBytes(new BytesBuilder()
+ .setReceived(BigInteger.valueOf(message.readLong()))
+ .setTransmitted(BigInteger.valueOf(message.readLong()))
+ .build())
+ .setReceiveDrops(BigInteger.valueOf(message.readLong()))
+ .setTransmitDrops(BigInteger.valueOf(message.readLong()))
+ .setReceiveErrors(BigInteger.valueOf(message.readLong()))
+ .setTransmitErrors(BigInteger.valueOf(message.readLong()))
+ .setReceiveFrameError(BigInteger.valueOf(message.readLong()))
+ .setReceiveOverRunError(BigInteger.valueOf((message.readLong())))
+ .setReceiveCrcError(BigInteger.valueOf((message.readLong())))
+ .setCollisionCount(BigInteger.valueOf(message.readLong()))
+ .setDuration(new DurationBuilder()
+ .setSecond(new Counter32(message.readUnsignedInt()))
+ .setNanosecond(new Counter32(message.readUnsignedInt()))
+ .build())
+ .build());
+ }
+
+ return builder
+ .setNodeConnectorStatisticsAndPortNumberMap(items)
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.multipart.reply.multipart.reply.body.MultipartReplyQueueStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder;
+
+public class MultipartReplyQueueStatsDeserializer implements OFDeserializer<MultipartReplyBody> {
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyQueueStatsBuilder builder = new MultipartReplyQueueStatsBuilder();
+ final List<QueueIdAndStatisticsMap> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final long port = message.readUnsignedInt();
+ final String portName = OpenflowPortsUtil.getPortLogicalName(EncodeConstants.OF13_VERSION_ID, port);
+
+ // We do not assign datapath ID here, because we simply do not have it
+ items.add(new QueueIdAndStatisticsMapBuilder()
+ .setNodeConnectorId(new NodeConnectorId(Objects.isNull(portName)
+ ? String.valueOf(port)
+ : portName))
+ .setQueueId(new QueueId(message.readUnsignedInt()))
+ .setTransmittedBytes(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setTransmittedPackets(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setTransmissionErrors(new Counter64(BigInteger.valueOf(message.readLong())))
+ .setDuration(new DurationBuilder()
+ .setSecond(new Counter32(message.readUnsignedInt()))
+ .setNanosecond(new Counter32(message.readUnsignedInt()))
+ .build())
+ .build());
+ }
+
+ return builder
+ .setQueueIdAndStatisticsMap(items)
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderDeserializer;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.openflowjava.util.ExperimenterDeserializerKeyFactory;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MessageCodeExperimenterKey;
+import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeActionExperimenterKey;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.util.ActionUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.set.field.match.SetFieldMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplyActionsMissBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplySetfieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplySetfieldMissBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.InstructionsMissBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.NextTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.NextTableMissBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WildcardsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteActionsMissBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteSetfieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteSetfieldMissBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.match.MatchSetfieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.next.table.TablesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.next.table.miss.TablesMissBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.wildcards.WildcardSetfieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.TableProperties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.TablePropertiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.table.properties.TableFeatureProperties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.table.properties.TableFeaturePropertiesBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MultipartReplyTableFeaturesDeserializer implements OFDeserializer<MultipartReplyBody>, DeserializerRegistryInjector {
+ private static final Logger LOG = LoggerFactory.getLogger(MultipartReplyTableFeaturesDeserializer.class);
+ private static final byte PADDING_IN_MULTIPART_REPLY_TABLE_FEATURES = 5;
+ private static final byte MAX_TABLE_NAME_LENGTH = 32;
+ private static final byte MULTIPART_REPLY_TABLE_FEATURES_STRUCTURE_LENGTH = 64;
+ private static final byte COMMON_PROPERTY_LENGTH = 4;
+ private static final TableFeaturesMatchFieldDeserializer MATCH_FIELD_DESERIALIZER =
+ new TableFeaturesMatchFieldDeserializer();
+
+ private DeserializerRegistry registry;
+
+ @Override
+ public MultipartReplyBody deserialize(ByteBuf message) {
+ final MultipartReplyTableFeaturesBuilder builder = new MultipartReplyTableFeaturesBuilder();
+ final List<TableFeatures> items = new ArrayList<>();
+
+ while (message.readableBytes() > 0) {
+ final int itemLength = message.readUnsignedShort();
+ final TableFeaturesBuilder itemBuilder = new TableFeaturesBuilder()
+ .setTableId(message.readUnsignedByte());
+
+ message.skipBytes(PADDING_IN_MULTIPART_REPLY_TABLE_FEATURES);
+
+ items.add(itemBuilder
+ .setName(ByteBufUtils.decodeNullTerminatedString(message, MAX_TABLE_NAME_LENGTH))
+ .setMetadataMatch(BigInteger.valueOf(message.readLong()))
+ .setMetadataWrite(BigInteger.valueOf(message.readLong()))
+ .setConfig(readTableConfig(message))
+ .setMaxEntries(message.readUnsignedInt())
+ .setTableProperties(readTableProperties(message,
+ itemLength - MULTIPART_REPLY_TABLE_FEATURES_STRUCTURE_LENGTH))
+ .build());
+ }
+
+ return builder
+ .setTableFeatures(items)
+ .build();
+ }
+
+ private final TableConfig readTableConfig(ByteBuf message) {
+ final long input = message.readUnsignedInt();
+ final boolean deprecated = (input & 3) != 0;
+
+ return new TableConfig(deprecated);
+ }
+
+ private final TableProperties readTableProperties(ByteBuf message, int length) {
+ final List<TableFeatureProperties> items = new ArrayList<>();
+ int tableFeaturesLength = length;
+
+ while (tableFeaturesLength > 0) {
+ final int propStartIndex = message.readerIndex();
+ final TableFeaturesPropType propType = TableFeaturesPropType.forValue(message.readUnsignedShort());
+ int propertyLength = message.readUnsignedShort();
+ final int paddingRemainder = propertyLength % EncodeConstants.PADDING;
+ tableFeaturesLength -= propertyLength;
+ final int commonPropertyLength = propertyLength - COMMON_PROPERTY_LENGTH;
+ final TableFeaturePropertiesBuilder propBuilder = new TableFeaturePropertiesBuilder();
+
+ switch (propType) {
+ case OFPTFPTINSTRUCTIONS:
+ propBuilder.setTableFeaturePropType(new InstructionsBuilder()
+ .setInstructions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.instructions.InstructionsBuilder()
+ .setInstruction(readInstructions(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTINSTRUCTIONSMISS:
+ propBuilder.setTableFeaturePropType(new InstructionsMissBuilder()
+ .setInstructionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.instructions.miss.InstructionsMissBuilder()
+ .setInstruction(readInstructions(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTNEXTTABLES:
+ propBuilder.setTableFeaturePropType(new NextTableBuilder()
+ .setTables(new TablesBuilder()
+ .setTableIds(readNextTableIds(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTNEXTTABLESMISS:
+ propBuilder.setTableFeaturePropType(new NextTableMissBuilder()
+ .setTablesMiss(new TablesMissBuilder()
+ .setTableIds(readNextTableIds(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTWRITEACTIONS:
+ propBuilder.setTableFeaturePropType(new WriteActionsBuilder()
+ .setWriteActions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.write.actions.WriteActionsBuilder()
+ .setAction(readActions(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTWRITEACTIONSMISS:
+ propBuilder.setTableFeaturePropType(new WriteActionsMissBuilder()
+ .setWriteActionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.write.actions.miss.WriteActionsMissBuilder()
+ .setAction(readActions(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTAPPLYACTIONS:
+ propBuilder.setTableFeaturePropType(new ApplyActionsBuilder()
+ .setApplyActions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.apply.actions.ApplyActionsBuilder()
+ .setAction(readActions(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTAPPLYACTIONSMISS:
+ propBuilder.setTableFeaturePropType(new ApplyActionsMissBuilder()
+ .setApplyActionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.apply.actions.miss.ApplyActionsMissBuilder()
+ .setAction(readActions(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTMATCH:
+ propBuilder.setTableFeaturePropType(new MatchBuilder()
+ .setMatchSetfield(new MatchSetfieldBuilder()
+ .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTWILDCARDS:
+ propBuilder.setTableFeaturePropType(new WildcardsBuilder()
+ .setWildcardSetfield(new WildcardSetfieldBuilder()
+ .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTWRITESETFIELD:
+ propBuilder.setTableFeaturePropType(new WriteSetfieldBuilder()
+ .setWriteSetfield(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.write.setfield.WriteSetfieldBuilder()
+ .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTWRITESETFIELDMISS:
+ propBuilder.setTableFeaturePropType(new WriteSetfieldMissBuilder()
+ .setWriteSetfieldMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.write.setfield.miss.WriteSetfieldMissBuilder()
+ .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTAPPLYSETFIELD:
+ propBuilder.setTableFeaturePropType(new ApplySetfieldBuilder()
+ .setApplySetfield(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.apply.setfield.ApplySetfieldBuilder()
+ .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
+ .build())
+ .build());
+ break;
+ case OFPTFPTAPPLYSETFIELDMISS:
+ propBuilder.setTableFeaturePropType(new ApplySetfieldMissBuilder()
+ .setApplySetfieldMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.apply.setfield.miss.ApplySetfieldMissBuilder()
+ .build())
+ .build());
+ break;
+ case OFPTFPTEXPERIMENTER:
+ case OFPTFPTEXPERIMENTERMISS:
+ final long expId = message.readUnsignedInt();
+ message.readerIndex(propStartIndex);
+
+ final OFDeserializer<TableFeatureProperties> propDeserializer = registry
+ .getDeserializer(ExperimenterDeserializerKeyFactory
+ .createMultipartReplyTFDeserializerKey(EncodeConstants.OF13_VERSION_ID, expId));
+
+ // TODO: Finish experimenter table features (currently using OFJava deserialization only to skip
+ // bytes)
+ propDeserializer.deserialize(message);
+ LOG.debug("Table feature property type {} is not handled yet.", propType);
+ break;
+ }
+
+
+ if (paddingRemainder != 0) {
+ message.skipBytes(EncodeConstants.PADDING - paddingRemainder);
+ tableFeaturesLength -= EncodeConstants.PADDING - paddingRemainder;
+ }
+
+ items.add(propBuilder.build());
+ }
+
+
+ return new TablePropertiesBuilder()
+ .setTableFeatureProperties(items)
+ .build();
+ }
+
+ private List<SetFieldMatch> readMatchFields(ByteBuf message, int length) {
+ final List<SetFieldMatch> matchFields = new ArrayList<>();
+
+ final int startIndex = message.readerIndex();
+
+ while ((message.readerIndex() - startIndex) < length) {
+ MATCH_FIELD_DESERIALIZER
+ .deserialize(message)
+ .ifPresent(matchField -> matchFields.add(matchField));
+ }
+
+ return matchFields;
+ }
+
+ private List<Short> readNextTableIds(ByteBuf message, int length) {
+ final List<Short> tableIds = new ArrayList<>();
+
+ while (length > 0) {
+ tableIds.add(message.readUnsignedByte());
+ length--;
+ }
+
+ return tableIds;
+ }
+
+ private List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
+ .Instruction> readInstructions(ByteBuf message, int length) {
+
+ final List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
+ .Instruction> instructions = new ArrayList<>();
+ final int startIndex = message.readerIndex();
+ int offset = 0;
+
+ while ((message.readerIndex() - startIndex) < length) {
+ final int type = message.getUnsignedShort(message.readerIndex());
+ HeaderDeserializer<Instruction> deserializer = null;
+
+ if (InstructionConstants.APPLY_ACTIONS_TYPE == type) {
+ deserializer = registry.getDeserializer(
+ new MessageCodeActionExperimenterKey(
+ EncodeConstants.OF13_VERSION_ID, type, Instruction.class,
+ ActionPath.NODES_NODE_TABLE_FLOW_INSTRUCTIONS_INSTRUCTION_APPLYACTIONSCASE_APPLYACTIONS_ACTION_ACTION_EXTENSIONLIST_EXTENSION,
+ null));
+ } else if (InstructionConstants.WRITE_ACTIONS_TYPE == type) {
+ deserializer = registry.getDeserializer(
+ new MessageCodeActionExperimenterKey(
+ EncodeConstants.OF13_VERSION_ID, type, Instruction.class,
+ ActionPath.NODES_NODE_TABLE_FLOW_INSTRUCTIONS_INSTRUCTION_WRITEACTIONSCASE_WRITEACTIONS_ACTION_ACTION_EXTENSIONLIST_EXTENSION,
+ null));
+ } else {
+ Long expId = null;
+
+ if (EncodeConstants.EXPERIMENTER_VALUE == type) {
+ expId = message.getUnsignedInt(message.readerIndex() +
+ 2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+ }
+
+ deserializer = registry.getDeserializer(
+ new MessageCodeExperimenterKey(
+ EncodeConstants.OF13_VERSION_ID, type, Instruction.class, expId));
+ }
+
+ instructions.add(new InstructionBuilder()
+ .setKey(new InstructionKey(offset))
+ .setOrder(offset)
+ .setInstruction(deserializer.deserializeHeader(message))
+ .build());
+
+ offset++;
+ }
+
+ return instructions;
+ }
+
+ private List<Action> readActions(ByteBuf message, int length) {
+ final List<Action> actions = new ArrayList<>();
+ final int startIndex = message.readerIndex();
+ int offset = 0;
+
+ while ((message.readerIndex() - startIndex) < length) {
+ try {
+ actions.add(new ActionBuilder()
+ .setKey(new ActionKey(offset))
+ .setOrder(offset)
+ .setAction(ActionUtil.readActionHeader(EncodeConstants.OF13_VERSION_ID, message, registry,
+ ActionPath.FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_INSTRUCTIONS_INSTRUCTION_INSTRUCTION_APPLYACTIONSCASE_APPLYACTIONS_ACTION_ACTION))
+ .build());
+
+ offset++;
+ } catch (ClassCastException | IllegalStateException e) {
+ message.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+ continue;
+ }
+ }
+
+ return actions;
+ }
+
+ @Override
+ public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+ registry = deserializerRegistry;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.openflowplugin.impl.protocol.deserialization.multipart;
+
+import com.google.common.collect.ImmutableMap;
+import io.netty.buffer.ByteBuf;
+import java.util.Map;
+import java.util.Optional;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpOp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpSha;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpSpa;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpTha;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpTpa;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.EthDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.EthSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Icmpv4Code;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Icmpv4Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Icmpv6Code;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Icmpv6Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.InPhyPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.InPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.IpDscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.IpEcn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.IpProto;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv4Dst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv4Src;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6Dst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6Exthdr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6Flabel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6NdSll;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6NdTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6NdTll;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6Src;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MatchField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Metadata;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MplsBos;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MplsLabel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MplsTc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.PbbIsid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.SctpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.SctpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TcpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TcpFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TcpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TunnelId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.UdpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.UdpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.VlanPcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.VlanVid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.set.field.match.SetFieldMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.set.field.match.SetFieldMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.set.field.match.SetFieldMatchKey;
+
+public class TableFeaturesMatchFieldDeserializer {
+
+ /**
+ * Mapping of match entry code to match set field class
+ */
+ private final Map<MatchEntryDeserializerKey, Class<? extends MatchField>> CODE_TO_FIELD = ImmutableMap
+ .<MatchEntryDeserializerKey, Class<? extends MatchField>>builder()
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ARP_OP), ArpOp.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ARP_SHA), ArpSha.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ARP_SPA), ArpSpa.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ARP_THA), ArpTha.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ARP_TPA), ArpTpa.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ETH_DST), EthDst.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ETH_SRC), EthSrc.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ICMPV4_CODE), Icmpv4Code.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ICMPV4_TYPE), Icmpv4Type.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ICMPV6_CODE), Icmpv6Code.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.ICMPV6_TYPE), Icmpv6Type.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IN_PHY_PORT), InPhyPort.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IN_PORT), InPort.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IP_DSCP), IpDscp.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IP_ECN), IpEcn.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IP_PROTO), IpProto.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV4_DST), Ipv4Dst.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV4_SRC), Ipv4Src.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV6_DST), Ipv6Dst.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV6_SRC), Ipv6Src.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV6_EXTHDR), Ipv6Exthdr.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV6_FLABEL), Ipv6Flabel.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV6_ND_SLL), Ipv6NdSll.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV6_ND_TLL), Ipv6NdTll.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.IPV6_ND_TARGET), Ipv6NdTarget.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.METADATA), Metadata.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.MPLS_BOS), MplsBos.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.MPLS_LABEL), MplsLabel.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.MPLS_TC), MplsTc.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.PBB_ISID), PbbIsid.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.SCTP_DST), SctpDst.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.SCTP_SRC), SctpSrc.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.TCP_SRC), TcpSrc.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.TCP_DST), TcpDst.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.TUNNEL_ID), TunnelId.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.UDP_SRC), UdpSrc.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.UDP_DST), UdpDst.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.VLAN_PCP), VlanPcp.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.OPENFLOW_BASIC_CLASS,
+ OxmMatchConstants.VLAN_VID), VlanVid.class)
+ .put(new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID,
+ OxmMatchConstants.EXPERIMENTER_CLASS,
+ OxmMatchConstants.NXM_NX_TCP_FLAG), TcpFlags.class)
+ .build();
+
+ /**
+ * Processes match entry header and returns if it have mask, or not
+ * @param in input buffer
+ * @return SetFieldMatchBuilder with hasMask properly set
+ */
+ protected static SetFieldMatchBuilder processHeader(ByteBuf in) {
+ in.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES); // skip oxm_class
+ boolean hasMask = (in.readUnsignedByte() & 1) != 0;
+ in.skipBytes(EncodeConstants.SIZE_OF_BYTE_IN_BYTES); // skip match entry length
+
+ return new SetFieldMatchBuilder()
+ .setHasMask(hasMask);
+ }
+
+ /**
+ * Deserialize match field if deserializer supports it, otherwise returns empty optional
+ * @param message input buffer
+ * @return set field match
+ */
+ public Optional<SetFieldMatch> deserialize(ByteBuf message) {
+ int oxmClass = message.getUnsignedShort(message.readerIndex());
+ int oxmField = message.getUnsignedByte(message.readerIndex()
+ + EncodeConstants.SIZE_OF_SHORT_IN_BYTES) >>> 1;
+ Long expId = null;
+
+ if (oxmClass == EncodeConstants.EXPERIMENTER_VALUE) {
+ expId = message.getUnsignedInt(message.readerIndex() + EncodeConstants.SIZE_OF_SHORT_IN_BYTES
+ + 2 * EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
+ }
+
+ final MatchEntryDeserializerKey key =
+ new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, oxmClass, oxmField);
+
+ key.setExperimenterId(expId);
+
+ return Optional
+ .ofNullable(CODE_TO_FIELD.get(key))
+ .map(clazz -> processHeader(message)
+ .setKey(new SetFieldMatchKey(clazz))
+ .setMatchType(clazz)
+ .build());
+ }
+}
import java.util.Objects;
import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderDeserializer;
import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
import org.opendaylight.openflowjava.protocol.api.keys.ActionDeserializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterActionDeserializerKey;
final OFDeserializer<Action> deserializer = registry.getDeserializer(key);
return deserializer.deserialize(message);
- } catch (IllegalStateException e) {
+ } catch (ClassCastException | IllegalStateException e) {
final MessageCodeKey key = Objects.nonNull(expId)
? new ExperimenterActionDeserializerKey(version, expId)
: new ActionDeserializerKey(version, type, expId);
}
}
+ /**
+ * Deserialize OpenFlow action header, using extension converter if available
+ * TODO: Remove also extension converters
+ *
+ * @param version OpenFlow version
+ * @param message OpenFlow buffered message
+ * @param registry deserializer registry
+ * @param path Action path
+ */
+ public static Action readActionHeader(short version, ByteBuf message, DeserializerRegistry registry,
+ ActionPath path) {
+ int type = message.getUnsignedShort(message.readerIndex());
+ Long expId = null;
+
+ if (type == EncodeConstants.EXPERIMENTER_VALUE) {
+ expId = message.getUnsignedInt(message.readerIndex()
+ + 2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+ }
+
+ try {
+ final MessageCodeExperimenterKey key = new MessageCodeExperimenterKey(
+ version, type, Action.class, expId);
+
+ final HeaderDeserializer<Action> deserializer = registry.getDeserializer(key);
+
+ return deserializer.deserializeHeader(message);
+ } catch (ClassCastException | IllegalStateException e) {
+ final MessageCodeKey key = Objects.nonNull(expId)
+ ? new ExperimenterActionDeserializerKey(version, expId)
+ : new ActionDeserializerKey(version, type, expId);
+
+ final HeaderDeserializer<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203
+ .actions.grouping.Action> deserializer = registry.getDeserializer(key);
+
+ return ActionExtensionHelper.processAlienAction(deserializer.deserializeHeader(message),
+ OpenflowVersion.get(version), path);
+ }
+ }
+
}