From 0d9c30aa4c3e66f92eca0a867d3cf678b07770ca Mon Sep 17 00:00:00 2001 From: Michal Polkorab Date: Mon, 4 Nov 2013 09:07:34 +0100 Subject: [PATCH] Match and actions (de)serialization + fix YANG files - added missing instructions in some messages YANG files - unified bucketslist, actionslist Signed-off-by: Michal Polkorab Change-Id: Ia2865fdf389248554c4fdea8a0d84e9705c8086e --- .../src/main/yang/openflow-action.yang | 8 +- .../src/main/yang/openflow-augments.yang | 20 +- .../main/yang/openflow-extensible-match.yang | 3 + .../src/main/yang/openflow-protocol.yang | 67 +-- .../src/main/yang/openflow-types.yang | 10 +- .../MultipartReplyMessageFactory.java | 71 ++- .../impl/serialization/OFSerializer.java | 1 + .../GroupModInputMessageFactory.java | 48 +- .../factories/HelloInputMessageFactory.java | 1 + .../PacketOutInputMessageFactory.java | 6 +- ...nCreator.java => ActionsDeserializer.java} | 114 ++-- .../protocol/impl/util/ActionsSerializer.java | 267 +++++++++ .../impl/util/MatchEntriesCreator.java | 117 ---- .../impl/util/MatchEntriesDeserializer.java | 520 ++++++++++++++++++ .../protocol/impl/util/MatchSerializer.java | 315 +++++++++++ .../MultipartReplyMessageFactoryTest.java | 5 +- ...QueueGetConfigReplyMessageFactoryTest.java | 7 +- .../GroupModInputMessageFactoryTest.java | 20 +- pom.xml | 3 +- 19 files changed, 1321 insertions(+), 282 deletions(-) rename openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/{ActionCreator.java => ActionsDeserializer.java} (72%) create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/ActionsSerializer.java delete mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/MatchEntriesCreator.java create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/MatchEntriesDeserializer.java create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/MatchSerializer.java diff --git a/openflow-protocol-api/src/main/yang/openflow-action.yang b/openflow-protocol-api/src/main/yang/openflow-action.yang index 2b244ac9..77dca25e 100644 --- a/openflow-protocol-api/src/main/yang/openflow-action.yang +++ b/openflow-protocol-api/src/main/yang/openflow-action.yang @@ -76,10 +76,16 @@ module openflow-action { description ""; base oft:action; } - + container actions-container { uses action-header; } + + grouping actions { + list actions-list { + uses action-header; + } + } grouping action-header { container action { diff --git a/openflow-protocol-api/src/main/yang/openflow-augments.yang b/openflow-protocol-api/src/main/yang/openflow-augments.yang index 75c6590b..a62f91ac 100644 --- a/openflow-protocol-api/src/main/yang/openflow-augments.yang +++ b/openflow-protocol-api/src/main/yang/openflow-augments.yang @@ -77,12 +77,6 @@ module openflow-augments { type uint8; } } - augment "/oxm:oxm-container/oxm:match-entries" { - ext:augment-identifier "ipv4-prefix-match-entry"; - leaf ipv4-prefix { - type inet:ipv4-prefix; - } - } augment "/oxm:oxm-container/oxm:match-entries" { ext:augment-identifier "port-match-entry"; leaf port { @@ -107,12 +101,6 @@ module openflow-augments { type uint16; } } - augment "/oxm:oxm-container/oxm:match-entries" { - ext:augment-identifier "ipv6-prefix-match-entry"; - leaf ipv6-prefix { - type inet:ipv6-prefix; - } - } augment "/oxm:oxm-container/oxm:match-entries" { ext:augment-identifier "ipv6-flabel-match-entry"; leaf ipv6-flabel { @@ -137,6 +125,12 @@ module openflow-augments { type inet:ipv6-address; } } + augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "ipv4-address-match-entry"; + leaf ipv4-address { + type inet:ipv4-address; + } + } augment "/oxm:oxm-container/oxm:match-entries" { ext:augment-identifier "mpls-label-match-entry"; leaf mpls-label { @@ -209,7 +203,7 @@ module openflow-augments { augment "/ofaction:actions-container/ofaction:action" { ext:augment-identifier "port-action"; leaf port { - type oft:any-port-number; + type oft:port-number; } } augment "/ofaction:actions-container/ofaction:action" { diff --git a/openflow-protocol-api/src/main/yang/openflow-extensible-match.yang b/openflow-protocol-api/src/main/yang/openflow-extensible-match.yang index 05afce9f..46849a7f 100644 --- a/openflow-protocol-api/src/main/yang/openflow-extensible-match.yang +++ b/openflow-protocol-api/src/main/yang/openflow-extensible-match.yang @@ -223,6 +223,9 @@ module openflow-extensible-match { base match-field; } } + leaf has-mask { + type boolean; + } } } diff --git a/openflow-protocol-api/src/main/yang/openflow-protocol.yang b/openflow-protocol-api/src/main/yang/openflow-protocol.yang index cca7011f..7f65a22b 100644 --- a/openflow-protocol-api/src/main/yang/openflow-protocol.yang +++ b/openflow-protocol-api/src/main/yang/openflow-protocol.yang @@ -80,6 +80,26 @@ module openflow-protocol { uses oxm:oxm-fields; } + grouping buckets { + list buckets-list { + uses bucket; + } + } + + grouping bucket { + leaf weight { + type uint16; + } + leaf watch-port { + type oft:port-number; + } + leaf watch-group { + type uint32; + } + + uses ofaction:actions; + } + container table-features-properties-container { uses table-features-properties; } @@ -339,14 +359,11 @@ module openflow-protocol { uses ofHeader; - list actions-list { - uses ofaction:action-header; - - leaf data { - type binary; - } - } + uses ofaction:actions; + leaf data { + type binary; + } leaf buffer-id { type uint32; } @@ -396,6 +413,8 @@ module openflow-protocol { container match { uses match; } + + uses ofinstruction:instructions; } grouping group-mod { // reference "OFPT_GROUP_MOD message in Openflow Switch 1.3 Spec" @@ -413,24 +432,9 @@ module openflow-protocol { type uint32; } - list buckets-list { - uses bucket; - } - } - grouping bucket { - leaf weight { - type uint16; - } - leaf watch-port { - type oft:port-number; - } - leaf watch-group { - type uint32; - } - list actions-list { - uses ofaction:action-header; - } + uses buckets; } + grouping port-mod { // reference "OFPT_PORT_MOD message in Openflow Switch 1.3 Spec" /* Controller/switch message */ @@ -647,6 +651,8 @@ module openflow-protocol { container match { uses match; } + + uses ofinstruction:instructions; } } case multipart-reply-aggregate { @@ -789,9 +795,7 @@ module openflow-protocol { leaf group-id { type uint32; } - list buckets-list { - uses bucket; - } + uses buckets; } } case multipart-reply-group-features { @@ -804,12 +808,8 @@ module openflow-protocol { leaf-list max_groups { type uint32; } - //leaf-list actions { - // type ofaction:action-type; - //} - list actions-list { - uses ofaction:action-header; - } + + uses ofaction:actions; } case multipart-reply-meter { list meter-stats { @@ -891,6 +891,7 @@ module openflow-protocol { leaf max-entries { type uint32; } + uses table-features-properties; } } case multipart-reply-port-desc { diff --git a/openflow-protocol-api/src/main/yang/openflow-types.yang b/openflow-protocol-api/src/main/yang/openflow-types.yang index f2254db7..a2b11ddb 100644 --- a/openflow-protocol-api/src/main/yang/openflow-types.yang +++ b/openflow-protocol-api/src/main/yang/openflow-types.yang @@ -185,13 +185,13 @@ module openflow-types { base oft:match-type-base; } - typedef match-type { - //type identityref { - // base oft:match-type-base; - //} + typedef oxm-match-type { + type identityref { + base oft:match-type-base; + } //TODO: use identityref, when generating available - type string; + //type string; } identity instruction { diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/MultipartReplyMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/MultipartReplyMessageFactory.java index a8011b81..2a2bba56 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/MultipartReplyMessageFactory.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/MultipartReplyMessageFactory.java @@ -8,10 +8,13 @@ import java.util.ArrayList; import java.util.List; import org.opendaylight.openflowjava.protocol.impl.deserialization.OFDeserializer; -import org.opendaylight.openflowjava.protocol.impl.util.ActionCreator; +import org.opendaylight.openflowjava.protocol.impl.util.ActionsDeserializer; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupCapabilities; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupTypes; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterBandType; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterFlags; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterModCommand; @@ -23,10 +26,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.bucket.ActionsList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.BucketsList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.BucketsListBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandDropBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandDscpRemarkBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandExperimenterBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregate; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDesc; @@ -39,6 +44,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupDesc; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupDescBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupFeaturesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeter; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterConfig; @@ -59,8 +65,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.GroupStatsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc.GroupDesc; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc.GroupDescBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc.group.desc.BucketsList; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc.group.desc.BucketsListBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.group.stats.BucketStats; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.group.stats.BucketStatsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.MeterStats; @@ -111,8 +115,6 @@ public class MultipartReplyMessageFactory implements OFDeserializer 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; + 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); } @@ -416,10 +420,10 @@ public class MultipartReplyMessageFactory implements OFDeserializer 0; - final Boolean _oFPMFPKTPS = (input & (1 << 1)) > 0; - final Boolean _oFPMFBURST = (input & (1 << 2)) > 0; - final Boolean _oFPMFSTATS = (input & (1 << 3)) > 0; + final Boolean _oFPMFKBPS = (input & (1 << 0)) != 0; + final Boolean _oFPMFPKTPS = (input & (1 << 1)) != 0; + final Boolean _oFPMFBURST = (input & (1 << 2)) != 0; + final Boolean _oFPMFSTATS = (input & (1 << 3)) != 0; return new MeterFlags(_oFPMFBURST, _oFPMFKBPS, _oFPMFPKTPS, _oFPMFSTATS); } @@ -478,7 +482,7 @@ public class MultipartReplyMessageFactory implements OFDeserializer meterConfigList = new ArrayList<>(); MeterConfigBuilder meterConfigBuilder = new MeterConfigBuilder(); - List bandsList = new ArrayList(); + List bandsList = new ArrayList<>(); BandsBuilder bandsBuilder = new BandsBuilder(); while (input.readableBytes() > 0) { @@ -620,6 +624,37 @@ public class MultipartReplyMessageFactory implements OFDeserializer maxGroupsList = new ArrayList<>(); + for (int i = 0; i < SIZE_OF_MAX_GROUPS ; i++) { + maxGroupsList.add(rawMessage.readUnsignedInt()); + } + featuresBuilder.setMaxGroups(maxGroupsList); + // TODO - groupfeatures - actions bitmap + rawMessage.skipBytes(4); + return featuresBuilder.build(); + } + + private static GroupCapabilities createCapabilities(long input) { + final Boolean OFOFPGFC_SELECT_WEIGHT = ((input) & (1<<0)) != 0; + final Boolean OFPGFC_SELECT_LIVENESS = ((input) & (1<<1)) != 0; + final Boolean OFPGFC_CHAINING = ((input) & (1<<2)) != 0; + final Boolean OFPGFC_CHAINING_CHECKS = ((input) & (1<<3)) != 0; + return new GroupCapabilities(OFPGFC_CHAINING, OFPGFC_CHAINING_CHECKS, OFPGFC_SELECT_LIVENESS, OFOFPGFC_SELECT_WEIGHT); + } + + private static GroupTypes createGroupType(long input) { + final Boolean OFPGT_ALL = ((input) & (1<<0)) != 0; + final Boolean OFPGT_SELECT = ((input) & (1<<1)) != 0; + final Boolean OFPGT_INDIRECT = ((input) & (1<<2)) != 0; + final Boolean OFPGT_FF = ((input) & (1<<3)) != 0; + return new GroupTypes(OFPGT_ALL, OFPGT_FF, OFPGT_INDIRECT, OFPGT_SELECT); + } + private static MultipartReplyGroupDesc setGroupDesc(ByteBuf input) { final byte PADDING_IN_GROUP_DESC_HEADER = 1; final byte PADDING_IN_BUCKETS_HEADER = 4; @@ -652,7 +687,7 @@ public class MultipartReplyMessageFactory implements OFDeserializer(actionsList)); actionsList.clear(); bucketsList.add(bucketsBuilder.build()); diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/OFSerializer.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/OFSerializer.java index 0148ffb9..1413063f 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/OFSerializer.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/OFSerializer.java @@ -22,6 +22,7 @@ public interface OFSerializer { /** * Compute length of received message + * @param message TODO * @return computed length */ public abstract int computeLength(E message); diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java index 0a914269..6fa791d3 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java @@ -3,13 +3,13 @@ package org.opendaylight.openflowjava.protocol.impl.serialization.factories; import io.netty.buffer.ByteBuf; -import java.util.Iterator; import java.util.List; import org.opendaylight.openflowjava.protocol.impl.serialization.OFSerializer; +import org.opendaylight.openflowjava.protocol.impl.util.ActionsSerializer; import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.group.mod.BucketsList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.BucketsList; /** * @author timotej.kubas @@ -18,9 +18,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731 public class GroupModInputMessageFactory implements OFSerializer { private static final byte MESSAGE_TYPE = 15; private static final byte PADDING_IN_GROUP_MOD_MESSAGE = 1; - private static final int MESSAGE_LENGTH = 16; + private static final int MESSAGE_LENGTH = 16; + private static final byte LENGTH_OF_BUCKET_STRUCTURE = 16; private static GroupModInputMessageFactory instance; - + private GroupModInputMessageFactory() { // singleton } @@ -48,7 +49,7 @@ public class GroupModInputMessageFactory implements OFSerializer @Override public int computeLength(GroupModInput message) { - return MESSAGE_LENGTH; + return MESSAGE_LENGTH + computeLengthOfBuckets(message.getBucketsList()); } @Override @@ -58,16 +59,35 @@ public class GroupModInputMessageFactory implements OFSerializer private static void encodeBuckets(List buckets, ByteBuf outBuffer) { final byte PADDING_IN_BUCKET = 4; - - for (Iterator iterator = buckets.iterator(); iterator.hasNext();) { - BucketsList currentBucket = iterator.next(); - // TODO get method for field length missing - outBuffer.writeShort(currentBucket.getWeight().intValue()); - outBuffer.writeInt(currentBucket.getWatchPort().getValue().intValue()); - outBuffer.writeInt(currentBucket.getWatchGroup().intValue()); - ByteBufUtils.padBuffer(PADDING_IN_BUCKET, outBuffer); - // TODO actions structure missing + if (buckets != null) { + for (BucketsList currentBucket : buckets) { + outBuffer.writeShort(computeLengthOfBucket(currentBucket)); + outBuffer.writeShort(currentBucket.getWeight().shortValue()); + outBuffer.writeInt(currentBucket.getWatchPort().getValue().intValue()); + outBuffer.writeInt(currentBucket.getWatchGroup().intValue()); + ByteBufUtils.padBuffer(PADDING_IN_BUCKET, outBuffer); + ActionsSerializer.encodeActions(currentBucket.getActionsList(), outBuffer); + } + } + } + + private static int computeLengthOfBucket(BucketsList bucket) { + int lengthOfBuckets = 0; + if (bucket != null) { + lengthOfBuckets = LENGTH_OF_BUCKET_STRUCTURE + ActionsSerializer.computeLengthOfActions(bucket.getActionsList()); } + return lengthOfBuckets; + } + + private static int computeLengthOfBuckets(List buckets) { + int lengthOfBuckets = 0; + if (buckets != null) { + for (BucketsList currentBucket : buckets) { + lengthOfBuckets += LENGTH_OF_BUCKET_STRUCTURE + ActionsSerializer.computeLengthOfActions(currentBucket.getActionsList()); + } + } + return lengthOfBuckets; } + } diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/HelloInputMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/HelloInputMessageFactory.java index d2b7f33c..e6877ccc 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/HelloInputMessageFactory.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/HelloInputMessageFactory.java @@ -22,6 +22,7 @@ public class HelloInputMessageFactory implements OFSerializer{ /** Code type of Hello message */ private static final byte MESSAGE_TYPE = 0; private static int MESSAGE_LENGTH = 8; + /** Size of hello element header (in bytes) */ public static final byte HELLO_ELEMENT_HEADER_SIZE = 4; private static HelloInputMessageFactory instance; diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PacketOutInputMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PacketOutInputMessageFactory.java index dd3f72b2..a05aefe3 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PacketOutInputMessageFactory.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PacketOutInputMessageFactory.java @@ -4,6 +4,7 @@ package org.opendaylight.openflowjava.protocol.impl.serialization.factories; import io.netty.buffer.ByteBuf; import org.opendaylight.openflowjava.protocol.impl.serialization.OFSerializer; +import org.opendaylight.openflowjava.protocol.impl.util.ActionsSerializer; import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput; @@ -40,11 +41,10 @@ public class PacketOutInputMessageFactory implements OFSerializer actionsList = new ArrayList<>(); -/** - * @param inp input ByteBuf - * @param bucketsLength length of buckets - * @return ActionsList - */ - public static List createActionsList(ByteBuf inp, int bucketsLength) { + + /** + * @param input input ByteBuf + * @param bucketsLength length of buckets + * @return ActionsList + */ + public static List createActionsList(ByteBuf input, int bucketsLength) { final byte BUCKET_HEADER_LENGTH = 16; int bucketsCurrentLength = BUCKET_HEADER_LENGTH; int actionsLength = 0; while (bucketsCurrentLength < bucketsLength) { - switch(inp.readUnsignedShort()) { - case 0: actionsLength = inp.readUnsignedShort(); //outputActionLength - actionsList.add(ActionCreator.createOutputAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + switch(input.readUnsignedShort()) { + case 0: actionsLength = input.readUnsignedShort(); //outputActionLength + actionsList.add(ActionsDeserializer.createOutputAction(input)); break; case 11: - actionsLength = inp.readUnsignedShort();//empty header length - actionsList.add(ActionCreator.createCopyTtlOutAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//empty header length + actionsList.add(ActionsDeserializer.createCopyTtlOutAction(input)); break; case 12: - actionsLength = inp.readUnsignedShort();//empty header length - actionsList.add(ActionCreator.createCopyTtlInAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//empty header length + actionsList.add(ActionsDeserializer.createCopyTtlInAction(input)); break; case 15: - actionsLength = inp.readUnsignedShort();//empty header length - actionsList.add(ActionCreator.createSetMplsTtlAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//empty header length + actionsList.add(ActionsDeserializer.createSetMplsTtlAction(input)); break; case 16: - actionsLength = inp.readUnsignedShort();//empty header length - actionsList.add(ActionCreator.createDecMplsTtlOutAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//empty header length + actionsList.add(ActionsDeserializer.createDecMplsTtlOutAction(input)); break; case 17: - actionsLength = inp.readUnsignedShort(); - actionsList.add(ActionCreator.createPushVlanAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort(); + actionsList.add(ActionsDeserializer.createPushVlanAction(input)); break; case 18: - actionsLength = inp.readUnsignedShort();//empty header length - actionsList.add(ActionCreator.createPopVlanAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//empty header length + actionsList.add(ActionsDeserializer.createPopVlanAction(input)); break; case 19: - actionsLength = inp.readUnsignedShort();//8 - actionsList.add(ActionCreator.createPushMplsAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//8 + actionsList.add(ActionsDeserializer.createPushMplsAction(input)); break; case 20: - actionsLength = inp.readUnsignedShort();//8 - actionsList.add(ActionCreator.createPopMplsAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//8 + actionsList.add(ActionsDeserializer.createPopMplsAction(input)); break; case 21: - actionsLength = inp.readUnsignedShort(); - actionsList.add(ActionCreator.createSetQueueAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort(); + actionsList.add(ActionsDeserializer.createSetQueueAction(input)); break; case 22: - actionsLength = inp.readUnsignedShort();//8 - actionsList.add(ActionCreator.createGroupAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//8 + actionsList.add(ActionsDeserializer.createGroupAction(input)); break; case 23: - actionsLength = inp.readUnsignedShort();//8 - actionsList.add(ActionCreator.createSetNwTtlAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//8 + actionsList.add(ActionsDeserializer.createSetNwTtlAction(input)); break; case 24: - actionsLength = inp.readUnsignedShort();//empty header length - actionsList.add(ActionCreator.createDecNwTtlAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//empty header length + actionsList.add(ActionsDeserializer.createDecNwTtlAction(input)); break; case 25: - actionsLength = inp.readUnsignedShort();//8 + actionsLength = input.readUnsignedShort();//8 //TODO field - actionsList.add(ActionCreator.createSetFieldAction(inp, actionsLength)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsList.add(ActionsDeserializer.createSetFieldAction(input, actionsLength)); break; case 26: - actionsLength = inp.readUnsignedShort();//8 - actionsList.add(ActionCreator.createPushPbbAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//8 + actionsList.add(ActionsDeserializer.createPushPbbAction(input)); break; case 27: - actionsLength = inp.readUnsignedShort();//empty header length - actionsList.add(ActionCreator.createPopPbbAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort();//empty header length + actionsList.add(ActionsDeserializer.createPopPbbAction(input)); break; case 0xFFFF: - actionsLength = inp.readUnsignedShort(); - actionsList.add(ActionCreator.createExperimenterAction(inp)); - bucketsCurrentLength = bucketsCurrentLength + actionsLength; + actionsLength = input.readUnsignedShort(); + actionsList.add(ActionsDeserializer.createExperimenterAction(input)); break; default: break; } + bucketsCurrentLength += actionsLength; } return actionsList; } @@ -249,7 +233,7 @@ public abstract class ActionCreator { actionBuilder.setType(Output.class); PortActionBuilder port = new PortActionBuilder(); - port.setPort(new AnyPortNumber(new PortNumber(in.readUnsignedInt()))); + port.setPort(new PortNumber(in.readUnsignedInt())); actionBuilder.addAugmentation(PortAction.class, port.build()); MaxLengthActionBuilder maxLen = new MaxLengthActionBuilder(); maxLen.setMaxLength(in.readUnsignedShort()); @@ -394,7 +378,7 @@ public abstract class ActionCreator { public static ActionsList createSetFieldAction(ByteBuf in, int actionLength) { actionBuilder.setType(SetField.class); OxmFieldsActionBuilder matchEntries = new OxmFieldsActionBuilder(); - matchEntries.setMatchEntries(MatchEntriesCreator.createMatchEntry(in, actionLength - 4)); + matchEntries.setMatchEntries(MatchEntriesDeserializer.createMatchEntry(in, actionLength - 4)); actionBuilder.addAugmentation(OxmFieldsAction.class, matchEntries.build()); actionsListBuilder.setAction(actionBuilder.build()); diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/ActionsSerializer.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/ActionsSerializer.java new file mode 100644 index 00000000..c95cb4bb --- /dev/null +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/ActionsSerializer.java @@ -0,0 +1,267 @@ +/* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */ +package org.opendaylight.openflowjava.protocol.impl.util; + +import io.netty.buffer.ByteBuf; + +import java.util.List; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthertypeAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.GroupIdAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaxLengthAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsTtlAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NwTtlAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.QueueIdAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.CopyTtlIn; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.CopyTtlOut; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.DecMplsTtl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.DecNwTtl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Experimenter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Output; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopMpls; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopPbb; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopVlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushMpls; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushPbb; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushVlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetField; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetMplsTtl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetNwTtl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetQueue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.action.header.Action; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class for easy serialization of actions + * + * @author michal.polkorab + * @author timotej.kubas + */ +public abstract class ActionsSerializer { + + private static final Logger LOGGER = LoggerFactory.getLogger(ActionsSerializer.class); + + /** + * Encodes actions to ByteBuf + * @param actionsList list of actions to be encoded + * @param outBuffer output ByteBuf + */ + public static void encodeActions(List actionsList, ByteBuf outBuffer) { + if (actionsList == null) { + return; + } + for (ActionsList list : actionsList) { + Action action = list.getAction(); + if (action.getType().equals(Output.class)) { + encodeOutputAction(action, outBuffer); + } else if (action.getType().equals(CopyTtlOut.class)) { + encodeCopyTtlOutAction(outBuffer); + } else if (action.getType().equals(CopyTtlIn.class)) { + encodeCopyTtlInAction(outBuffer); + } else if (action.getType().equals(SetMplsTtl.class)) { + encodeSetMplsTtltAction(action, outBuffer); + } else if (action.getType().equals(DecMplsTtl.class)) { + encodeDecMplsTtlAction(outBuffer); + } else if (action.getType().equals(PushVlan.class)) { + encodePushVlanAction(action, outBuffer); + } else if (action.getType().equals(PopVlan.class)) { + encodePopVlanAction(outBuffer); + } else if (action.getType().equals(PushMpls.class)) { + encodePushMplsAction(action, outBuffer); + } else if (action.getType().equals(PopMpls.class)) { + encodePopMplsAction(action, outBuffer); + } else if (action.getType().equals(SetQueue.class)) { + encodeSetQueueAction(action, outBuffer); + } else if (action.getType().equals(Group.class)) { + encodeGroupAction(action, outBuffer); + } else if (action.getType().equals(SetNwTtl.class)) { + encodeSetNwTtlAction(action, outBuffer); + } else if (action.getType().equals(DecNwTtl.class)) { + encodeDecNwTtlAction(outBuffer); + } else if (action.getType().equals(SetField.class)) { + encodeSetFieldAction(action, outBuffer); + } else if (action.getType().equals(PushPbb.class)) { + encodePushPbbAction(action, outBuffer); + } else if (action.getType().equals(PopPbb.class)) { + encodePopPbbAction(outBuffer); + } else if (action.getType().equals(Experimenter.class)) { + encodeExperimenterAction(action, outBuffer); + } + } + } + + private static void encodeOutputAction(Action action, ByteBuf outBuffer) { + final byte OUTPUT_CODE = 0; + final byte OUTPUT_LENGTH = 16; + final byte OUTPUT_PADDING = 6; + outBuffer.writeShort(OUTPUT_CODE); + outBuffer.writeShort(OUTPUT_LENGTH); + PortAction port = action.getAugmentation(PortAction.class); + outBuffer.writeInt(port.getPort().getValue().intValue()); + MaxLengthAction maxlength = action.getAugmentation(MaxLengthAction.class); + outBuffer.writeShort(maxlength.getMaxLength()); + ByteBufUtils.padBuffer(OUTPUT_PADDING, outBuffer); + } + + private static void encodeCopyTtlOutAction(ByteBuf outBuffer) { + final byte COPY_TTL_OUT_CODE = 11; + outBuffer.writeShort(COPY_TTL_OUT_CODE); + encodeRestOfActionHeader(outBuffer); + } + + private static void encodeCopyTtlInAction(ByteBuf outBuffer) { + final byte COPY_TTL_IN_CODE = 12; + outBuffer.writeShort(COPY_TTL_IN_CODE); + encodeRestOfActionHeader(outBuffer); + } + + private static void encodeSetMplsTtltAction(Action action, ByteBuf outBuffer) { + final byte SET_MPLS_TTL_CODE = 15; + final byte SET_MPLS_TTL_LENGTH = 8; + final byte SET_MPLS_TTL_PADDING = 3; + outBuffer.writeShort(SET_MPLS_TTL_CODE); + outBuffer.writeShort(SET_MPLS_TTL_LENGTH); + MplsTtlAction mplsTtl = action.getAugmentation(MplsTtlAction.class); + outBuffer.writeByte(mplsTtl.getMplsTtl()); + ByteBufUtils.padBuffer(SET_MPLS_TTL_PADDING, outBuffer); + } + + private static void encodeDecMplsTtlAction(ByteBuf outBuffer) { + final byte DEC_MPLS_TTL_CODE = 16; + outBuffer.writeShort(DEC_MPLS_TTL_CODE); + encodeRestOfActionHeader(outBuffer); + } + + private static void encodePushVlanAction(Action action, ByteBuf outBuffer) { + final byte PUSH_VLAN_CODE = 17; + outBuffer.writeShort(PUSH_VLAN_CODE); + encodeCommonEthertype(action, outBuffer); + } + + private static void encodePopVlanAction(ByteBuf outBuffer) { + final byte POP_VLAN_CODE = 18; + outBuffer.writeShort(POP_VLAN_CODE); + encodeRestOfActionHeader(outBuffer); + } + + private static void encodePushMplsAction(Action action, ByteBuf outBuffer) { + final byte PUSH_MPLS_CODE = 19; + outBuffer.writeShort(PUSH_MPLS_CODE); + encodeCommonEthertype(action, outBuffer); + } + + private static void encodePopMplsAction(Action action, ByteBuf outBuffer) { + final byte POP_MPLS_CODE = 20; + outBuffer.writeShort(POP_MPLS_CODE); + encodeCommonEthertype(action, outBuffer); + } + + private static void encodeSetQueueAction(Action action, ByteBuf outBuffer) { + final byte SET_QUEUE_CODE = 21; + final byte SET_QUEUE_LENGTH = 8; + outBuffer.writeShort(SET_QUEUE_CODE); + outBuffer.writeShort(SET_QUEUE_LENGTH); + QueueIdAction queueId = action.getAugmentation(QueueIdAction.class); + outBuffer.writeInt(queueId.getQueueId().intValue()); + } + + private static void encodeGroupAction(Action action, ByteBuf outBuffer) { + final byte GROUP_CODE = 22; + final byte GROUP_LENGTH = 8; + outBuffer.writeShort(GROUP_CODE); + outBuffer.writeShort(GROUP_LENGTH); + GroupIdAction groupId = action.getAugmentation(GroupIdAction.class); + outBuffer.writeInt(groupId.getGroupId().intValue()); + } + + private static void encodeSetNwTtlAction(Action action, ByteBuf outBuffer) { + final byte SET_NW_TTL_CODE = 23; + final byte SET_NW_TTL_LENGTH = 8; + final byte SET_NW_TTL_PADDING = 3; + outBuffer.writeShort(SET_NW_TTL_CODE); + outBuffer.writeShort(SET_NW_TTL_LENGTH); + NwTtlAction nwTtl = action.getAugmentation(NwTtlAction.class); + outBuffer.writeByte(nwTtl.getNwTtl()); + ByteBufUtils.padBuffer(SET_NW_TTL_PADDING, outBuffer); + } + + private static void encodeDecNwTtlAction(ByteBuf outBuffer) { + final byte DEC_NW_TTL_CODE = 24; + outBuffer.writeShort(DEC_NW_TTL_CODE); + encodeRestOfActionHeader(outBuffer); + } + + private static void encodeSetFieldAction(Action action, ByteBuf outBuffer) { + final int SET_FIELD_CODE = 25; // 0xFFFF + final byte SET_FIELD_LENGTH = 8; + // TODO - figure out definition from testing + check length + LOGGER.warn("Received set-field action - possible wrong or no implementation"); + outBuffer.writeShort(SET_FIELD_CODE); + outBuffer.writeShort(SET_FIELD_LENGTH); + ExperimenterAction experimenter = action.getAugmentation(ExperimenterAction.class); + outBuffer.writeInt(experimenter.getExperimenter().intValue()); + } + + private static void encodePushPbbAction(Action action, ByteBuf outBuffer) { + final byte PUSH_PBB_CODE = 26; + outBuffer.writeShort(PUSH_PBB_CODE); + encodeCommonEthertype(action, outBuffer); + } + + private static void encodePopPbbAction(ByteBuf outBuffer) { + final byte POP_PBB_CODE = 27; + outBuffer.writeShort(POP_PBB_CODE); + encodeRestOfActionHeader(outBuffer); + } + + private static void encodeExperimenterAction(Action action, ByteBuf outBuffer) { + final int EXPERIMENTER_CODE = 65535; // 0xFFFF + final byte EXPERIMENTER_LENGTH = 8; + outBuffer.writeShort(EXPERIMENTER_CODE); + outBuffer.writeShort(EXPERIMENTER_LENGTH); + ExperimenterAction experimenter = action.getAugmentation(ExperimenterAction.class); + outBuffer.writeInt(experimenter.getExperimenter().intValue()); + } + + private static void encodeRestOfActionHeader(ByteBuf outBuffer) { + final byte ACTION_HEADER_LENGTH = 8; + final byte PADDING_IN_ACTION_HEADER = 4; + outBuffer.writeShort(ACTION_HEADER_LENGTH); + ByteBufUtils.padBuffer(PADDING_IN_ACTION_HEADER, outBuffer); + } + + private static void encodeCommonEthertype(Action action, ByteBuf outBuffer) { + final byte LENGTH_OF_ETHERTYPE_ACTION = 8; + final byte ETHERTYPE_ACTION_PADDING = 2; + outBuffer.writeShort(LENGTH_OF_ETHERTYPE_ACTION); + EthertypeAction ethertype = action.getAugmentation(EthertypeAction.class); + outBuffer.writeShort(ethertype.getEthertype().getValue()); + ByteBufUtils.padBuffer(ETHERTYPE_ACTION_PADDING, outBuffer); + } + + /** + * Computes length of actions + * @param actionsList list of actions + * @return actions length + */ + public static int computeLengthOfActions(List actionsList) { + final byte OUTPUT_LENGTH = 16; + final byte LENGTH_OF_OTHER_ACTIONS = 8; + int lengthOfActions = 0; + if (actionsList != null) { + for (ActionsList list : actionsList) { + Action action = list.getAction(); + if (action.getType().equals(Output.class)) { + lengthOfActions += OUTPUT_LENGTH; + } else { + lengthOfActions += LENGTH_OF_OTHER_ACTIONS; + } + } + } + return lengthOfActions; + } +} diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/MatchEntriesCreator.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/MatchEntriesCreator.java deleted file mode 100644 index 7d5456c1..00000000 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/MatchEntriesCreator.java +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */ -package org.opendaylight.openflowjava.protocol.impl.util; - -import io.netty.buffer.ByteBuf; - -import java.util.ArrayList; -import java.util.List; - -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MacAddressMatchEntry; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MacAddressMatchEntryBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataMatchEntry; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataMatchEntryBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntry; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntryBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthDst; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ExperimenterClass; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPhyPort; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPort; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Metadata; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Nxm0Class; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Nxm1Class; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OpenflowBasicClass; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntriesBuilder; - -/** - * To create matches - * @author timotej.kubas - * @author michal.polkorab - */ -public abstract class MatchEntriesCreator { - private static List matchEntriesList = new ArrayList<>(); - private static MatchEntriesBuilder matchEntriesBuilder = new MatchEntriesBuilder(); - - /** - * @param in input ByteBuf - * @param matchArrayLength to infer size of array - * @return MatchEntriesList - */ - public static List createMatchEntry(ByteBuf in, int matchArrayLength) { - int currMatchLength = 0; - final byte MATCH_LENGTH = 1; - - while(currMatchLength < matchArrayLength) { - - switch (in.readUnsignedShort()) { - case 0x0000: - matchEntriesBuilder.setOxmClass(Nxm0Class.class); - break; - case 0x0001: - matchEntriesBuilder.setOxmClass(Nxm1Class.class); - break; - case 0x8000: - matchEntriesBuilder.setOxmClass(OpenflowBasicClass.class); - break; - case 0xFFFF: - matchEntriesBuilder.setOxmClass(ExperimenterClass.class); - break; - default: - break; - } - currMatchLength = currMatchLength +2; - - int matchField = in.readUnsignedByte() >>> 1; - in.skipBytes(MATCH_LENGTH); - - currMatchLength = currMatchLength + 2; - - switch(matchField) { - case 0: - matchEntriesBuilder.setOxmMatchField(InPort.class); - PortNumberMatchEntryBuilder port = new PortNumberMatchEntryBuilder(); - port.setPortNumber(new PortNumber(in.readUnsignedInt())); - matchEntriesBuilder.addAugmentation(PortNumberMatchEntry.class, port.build()); - currMatchLength = currMatchLength + 4; - break; - case 1: - matchEntriesBuilder.setOxmMatchField(InPhyPort.class); - PortNumberMatchEntryBuilder phyPort = new PortNumberMatchEntryBuilder(); - phyPort.setPortNumber(new PortNumber(in.readUnsignedInt())); - matchEntriesBuilder.addAugmentation(PortNumberMatchEntry.class, phyPort.build()); - currMatchLength = currMatchLength + 4; - break; - case 2: - matchEntriesBuilder.setOxmMatchField(Metadata.class); - MetadataMatchEntryBuilder metadata = new MetadataMatchEntryBuilder(); - byte[] metadataBytes = new byte[Long.SIZE/Byte.SIZE]; - in.readBytes(metadataBytes); - metadata.setMetadata(metadataBytes); - matchEntriesBuilder.addAugmentation(MetadataMatchEntry.class, metadata.build()); - currMatchLength = currMatchLength + 8; - break; - case 3: - matchEntriesBuilder.setOxmMatchField(EthDst.class); - MacAddressMatchEntryBuilder macAddress = new MacAddressMatchEntryBuilder(); - StringBuffer macToString = new StringBuffer(); - final int macAddressLength = 6; - for(int i=0; i matchEntriesList = new ArrayList<>(); + private static MatchEntriesBuilder matchEntriesBuilder = new MatchEntriesBuilder(); + + /** + * @param in input ByteBuf + * @param matchArrayLength to infer size of array + * @return MatchEntriesList + */ + public static List createMatchEntry(ByteBuf in, int matchArrayLength) { + int currMatchLength = 0; + while(currMatchLength < matchArrayLength) { + switch (in.readUnsignedShort()) { + case 0x0000: + matchEntriesBuilder.setOxmClass(Nxm0Class.class); + break; + case 0x0001: + matchEntriesBuilder.setOxmClass(Nxm1Class.class); + break; + case 0x8000: + matchEntriesBuilder.setOxmClass(OpenflowBasicClass.class); + break; + case 0xFFFF: + matchEntriesBuilder.setOxmClass(ExperimenterClass.class); + break; + default: + break; + } + + int matchField = in.readUnsignedByte() >>> 1; + short matchEntryLength = in.readUnsignedByte(); + currMatchLength = currMatchLength + SIZE_OF_SHORT_IN_BYTES + (2 * SIZE_OF_BYTE_IN_BYTES) + matchEntryLength; + + switch(matchField) { + case 0: + matchEntriesBuilder.setOxmMatchField(InPort.class); + PortNumberMatchEntryBuilder port = new PortNumberMatchEntryBuilder(); + port.setPortNumber(new PortNumber(in.readUnsignedInt())); + matchEntriesBuilder.addAugmentation(PortNumberMatchEntry.class, port.build()); + break; + case 1: + matchEntriesBuilder.setOxmMatchField(InPhyPort.class); + PortNumberMatchEntryBuilder phyPort = new PortNumberMatchEntryBuilder(); + phyPort.setPortNumber(new PortNumber(in.readUnsignedInt())); + matchEntriesBuilder.addAugmentation(PortNumberMatchEntry.class, phyPort.build()); + break; + case 2: + matchEntriesBuilder.setOxmMatchField(Metadata.class); + currMatchLength = matchEntryLength; + addMetadataAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_LONG_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 3: + matchEntriesBuilder.setOxmMatchField(EthDst.class); + addMacAddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_LONG_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 4: + matchEntriesBuilder.setOxmMatchField(EthSrc.class); + addMacAddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_LONG_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 5: + matchEntriesBuilder.setOxmMatchField(EthType.class); + EthTypeMatchEntryBuilder ethertypeBuilder = new EthTypeMatchEntryBuilder(); + ethertypeBuilder.setEthType(new EtherType(in.readUnsignedShort())); + matchEntriesBuilder.addAugmentation(EthTypeMatchEntry.class, ethertypeBuilder.build()); + break; + case 6: + matchEntriesBuilder.setOxmMatchField(VlanVid.class); + VlanVidMatchEntryBuilder vlanVidBuilder = new VlanVidMatchEntryBuilder(); + vlanVidBuilder.setVlanVid(in.readUnsignedShort()); + matchEntriesBuilder.addAugmentation(VlanVidMatchEntry.class, vlanVidBuilder.build()); + matchEntryLength -= SIZE_OF_SHORT_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 7: + matchEntriesBuilder.setOxmMatchField(VlanPcp.class); + VlanPcpMatchEntryBuilder vlanPcpBuilder = new VlanPcpMatchEntryBuilder(); + vlanPcpBuilder.setVlanPcp(in.readUnsignedByte()); + matchEntriesBuilder.addAugmentation(VlanPcpMatchEntry.class, vlanPcpBuilder.build()); + break; + case 8: + matchEntriesBuilder.setOxmMatchField(IpDscp.class); + DscpMatchEntryBuilder dscpBuilder = new DscpMatchEntryBuilder(); + dscpBuilder.setDscp(new Dscp(in.readUnsignedByte())); + matchEntriesBuilder.addAugmentation(DscpMatchEntry.class, dscpBuilder.build()); + break; + case 9: + matchEntriesBuilder.setOxmMatchField(IpEcn.class); + EcnMatchEntryBuilder ecnBuilder = new EcnMatchEntryBuilder(); + ecnBuilder.setEcn(in.readUnsignedByte()); + matchEntriesBuilder.addAugmentation(EcnMatchEntry.class, ecnBuilder.build()); + break; + case 10: + matchEntriesBuilder.setOxmMatchField(IpProto.class); + ProtocolNumberMatchEntryBuilder protoNumberBuilder = new ProtocolNumberMatchEntryBuilder(); + protoNumberBuilder.setProtocolNumber(in.readUnsignedByte()); + matchEntriesBuilder.addAugmentation(ProtocolNumberMatchEntry.class, protoNumberBuilder.build()); + break; + case 11: + matchEntriesBuilder.setOxmMatchField(Ipv4Src.class); + // TODO - ipv4address - check format with tests + LOGGER.warn("IPV4address(ipv4src): received but possible wrong deserialization"); + addIpv4AddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_INT_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 12: + matchEntriesBuilder.setOxmMatchField(Ipv4Dst.class); + // TODO - ipv4address - check format with tests + LOGGER.warn("IPV4address(ipv4dst): received but possible wrong deserialization"); + addIpv4AddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_INT_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 13: + matchEntriesBuilder.setOxmMatchField(TcpSrc.class); + addPortAugmentation(null, in); + break; + case 14: + matchEntriesBuilder.setOxmMatchField(TcpDst.class); + addPortAugmentation(null, in); + break; + case 15: + matchEntriesBuilder.setOxmMatchField(UdpSrc.class); + addPortAugmentation(null, in); + break; + case 16: + matchEntriesBuilder.setOxmMatchField(UdpDst.class); + addPortAugmentation(null, in); + break; + case 17: + matchEntriesBuilder.setOxmMatchField(SctpSrc.class); + addPortAugmentation(null, in); + break; + case 18: + matchEntriesBuilder.setOxmMatchField(SctpDst.class); + addPortAugmentation(null, in); + break; + case 19: + matchEntriesBuilder.setOxmMatchField(Icmpv4Type.class); + Icmpv4TypeMatchEntryBuilder icmpv4TypeBuilder = new Icmpv4TypeMatchEntryBuilder(); + icmpv4TypeBuilder.setIcmpv4Type(in.readUnsignedByte()); + matchEntriesBuilder.addAugmentation(Icmpv4TypeMatchEntry.class, icmpv4TypeBuilder.build()); + break; + case 20: + matchEntriesBuilder.setOxmMatchField(Icmpv4Code.class); + Icmpv4CodeMatchEntryBuilder icmpv4CodeBuilder = new Icmpv4CodeMatchEntryBuilder(); + icmpv4CodeBuilder.setIcmpv4Code(in.readUnsignedByte()); + matchEntriesBuilder.addAugmentation(Icmpv4CodeMatchEntry.class, icmpv4CodeBuilder.build()); + break; + case 21: + matchEntriesBuilder.setOxmMatchField(ArpOp.class); + OpCodeMatchEntryBuilder opcodeBuilder = new OpCodeMatchEntryBuilder(); + opcodeBuilder.setOpCode(in.readUnsignedShort()); + matchEntriesBuilder.addAugmentation(OpCodeMatchEntry.class, opcodeBuilder.build()); + break; + case 22: + matchEntriesBuilder.setOxmMatchField(ArpSpa.class); + // TODO - ipv4address - check format with tests + LOGGER.warn("IPV4address(arpspa): received but possible wrong deserialization"); + addIpv4AddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_INT_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 23: + matchEntriesBuilder.setOxmMatchField(ArpTpa.class); + // TODO - ipv4address - check format with tests + LOGGER.warn("IPV4address(arptpa): received but possible wrong deserialization"); + addIpv4AddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_INT_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 24: + matchEntriesBuilder.setOxmMatchField(ArpSha.class); + addMacAddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_LONG_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 25: + matchEntriesBuilder.setOxmMatchField(ArpTha.class); + addMacAddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_LONG_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 26: + matchEntriesBuilder.setOxmMatchField(Ipv6Src.class); + // TODO - ipv6address - check format with tests + LOGGER.warn("IPV6address(Ipv6Src): received but possible wrong deserialization"); + addIpv6AddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_IPV6_ADDRESS_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 27: + matchEntriesBuilder.setOxmMatchField(Ipv6Dst.class); + // TODO - ipv6address - check format with tests + LOGGER.warn("IPV6address(Ipv6Dst): received but possible wrong deserialization"); + addIpv6AddressAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_IPV6_ADDRESS_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 28: + matchEntriesBuilder.setOxmMatchField(Ipv6Flabel.class); + Ipv6FlabelMatchEntryBuilder ipv6FlabelBuilder = new Ipv6FlabelMatchEntryBuilder(); + ipv6FlabelBuilder.setIpv6Flabel(new Ipv6FlowLabel(in.readUnsignedInt())); + matchEntriesBuilder.addAugmentation(Ipv6FlabelMatchEntry.class, ipv6FlabelBuilder.build()); + matchEntryLength -= SIZE_OF_INT_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 29: + matchEntriesBuilder.setOxmMatchField(Icmpv6Type.class); + Icmpv6TypeMatchEntryBuilder icmpv6TypeBuilder = new Icmpv6TypeMatchEntryBuilder(); + icmpv6TypeBuilder.setIcmpv6Type(in.readUnsignedByte()); + matchEntriesBuilder.addAugmentation(Icmpv6TypeMatchEntry.class, icmpv6TypeBuilder.build()); + break; + case 30: + matchEntriesBuilder.setOxmMatchField(Icmpv6Code.class); + Icmpv6CodeMatchEntryBuilder icmpv6CodeBuilder = new Icmpv6CodeMatchEntryBuilder(); + icmpv6CodeBuilder.setIcmpv6Code(in.readUnsignedByte()); + matchEntriesBuilder.addAugmentation(Icmpv6CodeMatchEntry.class, icmpv6CodeBuilder.build()); + break; + case 31: + matchEntriesBuilder.setOxmMatchField(Ipv6NdTarget.class); + // TODO - ipv6address - check format with tests + LOGGER.warn("IPV6address(Ipv6NdTarget): received but possible wrong deserialization"); + addIpv6AddressAugmentation(matchEntriesBuilder, in); + break; + case 32: + matchEntriesBuilder.setOxmMatchField(Ipv6NdSll.class); + addMacAddressAugmentation(matchEntriesBuilder, in); + break; + case 33: + matchEntriesBuilder.setOxmMatchField(Ipv6NdTll.class); + addMacAddressAugmentation(matchEntriesBuilder, in); + break; + case 34: + matchEntriesBuilder.setOxmMatchField(MplsLabel.class); + MplsLabelMatchEntryBuilder mplsLabelBuilder = new MplsLabelMatchEntryBuilder(); + mplsLabelBuilder.setMplsLabel(in.readUnsignedInt()); + matchEntriesBuilder.addAugmentation(MplsLabelMatchEntry.class, mplsLabelBuilder.build()); + break; + case 35: + matchEntriesBuilder.setOxmMatchField(MplsTc.class); + TcMatchEntryBuilder tcBuilder = new TcMatchEntryBuilder(); + tcBuilder.setTc(in.readUnsignedByte()); + matchEntriesBuilder.addAugmentation(TcMatchEntry.class, tcBuilder.build()); + break; + case 36: + matchEntriesBuilder.setOxmMatchField(MplsBos.class); + BosMatchEntryBuilder bosBuilder = new BosMatchEntryBuilder(); + if (in.readUnsignedByte() != 0) { + bosBuilder.setBos(true); + } else { + bosBuilder.setBos(false); + } + matchEntriesBuilder.addAugmentation(BosMatchEntry.class, bosBuilder.build()); + break; + case 37: + matchEntriesBuilder.setOxmMatchField(PbbIsid.class); + IsidMatchEntryBuilder isidBuilder = new IsidMatchEntryBuilder(); + isidBuilder.setIsid(in.readUnsignedInt()); + matchEntriesBuilder.addAugmentation(IsidMatchEntry.class, isidBuilder.build()); + matchEntryLength -= SIZE_OF_INT_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 38: + matchEntriesBuilder.setOxmMatchField(TunnelId.class); + addMetadataAugmentation(matchEntriesBuilder, in); + matchEntryLength -= SIZE_OF_LONG_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + case 39: + matchEntriesBuilder.setOxmMatchField(Ipv6Exthdr.class); + PseudoFieldMatchEntryBuilder pseudoBuilder = new PseudoFieldMatchEntryBuilder(); + int bitmap = in.readUnsignedShort(); + final Boolean NONEXT = ((bitmap) & (1<<0)) != 0; + final Boolean ESP = ((bitmap) & (1<<1)) != 0; + final Boolean AUTH = ((bitmap) & (1<<2)) != 0; + final Boolean DEST = ((bitmap) & (1<<3)) != 0; + final Boolean FRAG = ((bitmap) & (1<<4)) != 0; + final Boolean ROUTER = ((bitmap) & (1<<5)) != 0; + final Boolean HOP = ((bitmap) & (1<<6)) != 0; + final Boolean UNREP = ((bitmap) & (1<<7)) != 0; + final Boolean UNSEQ = ((bitmap) & (1<<8)) != 0; + pseudoBuilder.setPseudoField(new PseudoField(AUTH, DEST, ESP, FRAG, HOP, NONEXT, ROUTER, UNREP, UNSEQ)); + matchEntriesBuilder.addAugmentation(PseudoFieldMatchEntry.class, pseudoBuilder.build()); + matchEntryLength -= SIZE_OF_SHORT_IN_BYTES; + if (matchEntryLength > 0) { + addMaskAugmentation(matchEntriesBuilder, in, matchEntryLength); + } + break; + default: + break; + } + matchEntriesList.add(matchEntriesBuilder.build()); + } + + return matchEntriesList; + } + + private static void addMaskAugmentation(MatchEntriesBuilder builder, ByteBuf in, int matchEntryLength) { +// TODO - check if matchEntryLength is in bytes + MaskMatchEntryBuilder maskBuilder = new MaskMatchEntryBuilder(); + byte[] mask = new byte[matchEntryLength]; + in.readBytes(mask); + maskBuilder.setMask(mask); + builder.addAugmentation(MaskMatchEntry.class, maskBuilder.build()); + } + + private static void addIpv6AddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) { + final byte GROUPS_IN_IPV6_ADDRESS = 8; + Ipv6AddressMatchEntryBuilder ipv6AddressBuilder = new Ipv6AddressMatchEntryBuilder(); + List groups = new ArrayList<>(); + for (int i = 0; i < GROUPS_IN_IPV6_ADDRESS; i++) { + groups.add(String.format("X", in.readUnsignedShort())); + } + Joiner joiner = Joiner.on(":"); + ipv6AddressBuilder.setIpv6Address(new Ipv6Address(joiner.join(groups))); + builder.addAugmentation(Ipv6AddressMatchEntry.class, ipv6AddressBuilder.build()); + } + + private static void addMetadataAugmentation(MatchEntriesBuilder builder, ByteBuf in) { + MetadataMatchEntryBuilder metadata = new MetadataMatchEntryBuilder(); + byte[] metadataBytes = new byte[Long.SIZE/Byte.SIZE]; + in.readBytes(metadataBytes); + metadata.setMetadata(metadataBytes); + builder.addAugmentation(MetadataMatchEntry.class, metadata.build()); + } + + private static void addIpv4AddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) { + final byte GROUPS_IN_IPV4_ADDRESS = 4; + Ipv4AddressMatchEntryBuilder ipv4AddressBuilder = new Ipv4AddressMatchEntryBuilder(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < GROUPS_IN_IPV4_ADDRESS; i++) { + sb.append(in.readUnsignedByte()); + } + ipv4AddressBuilder.setIpv4Address(new Ipv4Address(sb.toString())); + builder.addAugmentation(Ipv4AddressMatchEntry.class, ipv4AddressBuilder.build()); + } + + private static void addMacAddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) { + MacAddressMatchEntryBuilder macAddress = new MacAddressMatchEntryBuilder(); + StringBuffer macToString = new StringBuffer(); + final int macAddressLength = 6; + for(int i=0; i matchEntries, ByteBuf out) { + if (matchEntries == null) { + LOGGER.warn("Match entry is null"); + return; + } + for (MatchEntries entry : matchEntries) { + encodeClass(entry.getOxmClass(), out); + encodeRest(entry, null); + } + } + + private static void encodeClass(Class clazz, ByteBuf out) { + final int NXM0_CLASS_CODE = 0x0000; + final int NXM1_CLASS_CODE = 0x0001; + final int OPENFLOW_BASIC_CLASS_CODE = 0x8000; + final int EXPERIMENTER_CLASS_CODE = 0xFFFF; + if (Nxm0Class.class.equals(clazz)) { + out.writeShort(NXM0_CLASS_CODE); + } else if (Nxm1Class.class.equals(clazz)) { + out.writeShort(NXM1_CLASS_CODE); + } else if (OpenflowBasicClass.class.equals(clazz)) { + out.writeShort(OPENFLOW_BASIC_CLASS_CODE); + } else if (ExperimenterClass.class.equals(clazz)) { + out.writeShort(EXPERIMENTER_CLASS_CODE); + } + } + + private static void encodeRest(MatchEntries entry, ByteBuf out) { + int fieldValue = 0; + Class field = entry.getOxmMatchField(); + if (field.equals(InPort.class)) { + fieldValue = 0; + writeOxmFieldAndLength(out, fieldValue, Integer.SIZE / Byte.SIZE); + out.writeInt(entry.getAugmentation(PortNumberMatchEntry.class).getPortNumber().getValue().intValue()); + } else if (field.equals(InPhyPort.class)) { + fieldValue = 1; + writeOxmFieldAndLength(out, fieldValue, Integer.SIZE / Byte.SIZE); + out.writeInt(entry.getAugmentation(PortNumberMatchEntry.class).getPortNumber().getValue().intValue()); + } else if (field.equals(Metadata.class)) { + fieldValue = 2; + fieldValue = fieldValue << 1; + if (entry.isHasMask()) { + fieldValue = fieldValue | 1; + out.writeByte(fieldValue); + byte[] mask = entry.getAugmentation(MaskMatchEntry.class).getMask(); + out.writeByte(Long.SIZE / Byte.SIZE + mask.length); + out.writeBytes(entry.getAugmentation(MetadataMatchEntry.class).getMetadata()); + out.writeBytes(mask); + } else { + out.writeByte(fieldValue); + out.writeByte(Long.SIZE / Byte.SIZE); + out.writeBytes(entry.getAugmentation(MetadataMatchEntry.class).getMetadata()); + } + } else if (field.equals(EthDst.class)) { + fieldValue = 3; + fieldValue = fieldValue << 1; + if (entry.isHasMask()) { + fieldValue = fieldValue | 1; + out.writeByte(fieldValue); + byte[] mask = entry.getAugmentation(MaskMatchEntry.class).getMask(); + out.writeByte((Integer.SIZE + Short.SIZE) / Byte.SIZE + mask.length); + out.writeBytes(entry.getAugmentation(MacAddressMatchEntry.class).getMacAddress().getValue().getBytes()); + out.writeBytes(entry.getAugmentation(MaskMatchEntry.class).getMask()); + } else { + out.writeByte(fieldValue); + out.writeByte(Long.SIZE / Byte.SIZE); + out.writeBytes(entry.getAugmentation(MacAddressMatchEntry.class).getMacAddress().getValue().getBytes()); + } + } else if (field.equals(EthSrc.class)) { + fieldValue = 4; + fieldValue = fieldValue << 1; + if (entry.isHasMask()) { + fieldValue = fieldValue | 1; + out.writeByte(fieldValue); + byte[] mask = entry.getAugmentation(MaskMatchEntry.class).getMask(); + out.writeByte(Long.SIZE / Byte.SIZE + mask.length); + out.writeBytes(entry.getAugmentation(MacAddressMatchEntry.class).getMacAddress().getValue().getBytes()); + out.writeBytes(mask); + } else { + out.writeByte(fieldValue); + out.writeByte(Long.SIZE / Byte.SIZE); + out.writeBytes(entry.getAugmentation(MacAddressMatchEntry.class).getMacAddress().getValue().getBytes()); + } + } else if (field.equals(EthType.class)) { + fieldValue = 5; + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(EthTypeMatchEntry.class).getEthType().getValue().shortValue()); + } else if (field.equals(VlanVid.class)) { + fieldValue = 6; + fieldValue = fieldValue << 1; + if (entry.isHasMask()) { + fieldValue = fieldValue | 1; + out.writeByte(fieldValue); + byte[] mask = entry.getAugmentation(MaskMatchEntry.class).getMask(); + out.writeByte(Short.SIZE / Byte.SIZE + mask.length); + out.writeShort(entry.getAugmentation(VlanVidMatchEntry.class).getVlanVid()); + out.writeBytes(mask); + } else { + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(VlanVidMatchEntry.class).getVlanVid()); + } + } else if (field.equals(VlanPcp.class)) { + fieldValue = 7; + writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE); + out.writeByte(entry.getAugmentation(VlanPcpMatchEntry.class).getVlanPcp().byteValue()); + } else if (field.equals(IpDscp.class)) { + fieldValue = 8; + } else if (field.equals(IpEcn.class)) { + fieldValue = 9; + } else if (field.equals(IpProto.class)) { + fieldValue = 10; + } else if (field.equals(Ipv4Src.class)) { + fieldValue = 11; + } else if (field.equals(Ipv4Dst.class)) { + fieldValue = 12; + } else if (field.equals(TcpSrc.class)) { + fieldValue = 13; + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue()); + } else if (field.equals(TcpDst.class)) { + fieldValue = 14; + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue()); + } else if (field.equals(UdpSrc.class)) { + fieldValue = 15; + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue()); + } else if (field.equals(UdpDst.class)) { + fieldValue = 16; + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue()); + } else if (field.equals(SctpSrc.class)) { + fieldValue = 17; + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue()); + } else if (field.equals(SctpDst.class)) { + fieldValue = 18; + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue()); + } else if (field.equals(Icmpv4Type.class)) { + fieldValue = 19; + writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE); + out.writeByte(entry.getAugmentation(Icmpv4TypeMatchEntry.class).getIcmpv4Type()); + } else if (field.equals(Icmpv4Code.class)) { + fieldValue = 20; + writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE); + out.writeByte(entry.getAugmentation(Icmpv4CodeMatchEntry.class).getIcmpv4Code()); + } else if (field.equals(ArpOp.class)) { + fieldValue = 21; + writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE); + out.writeShort(entry.getAugmentation(OpCodeMatchEntry.class).getOpCode()); + } else if (field.equals(ArpSpa.class)) { + fieldValue = 22; + } else if (field.equals(ArpTpa.class)) { + fieldValue = 23; + } else if (field.equals(ArpSha.class)) { + fieldValue = 24; + } else if (field.equals(ArpTha.class)) { + fieldValue = 25; + } else if (field.equals(Ipv6Src.class)) { + fieldValue = 26; + } else if (field.equals(Ipv6Dst.class)) { + fieldValue = 27; + } else if (field.equals(Ipv6Flabel.class)) { + fieldValue = 28; + } else if (field.equals(Icmpv6Type.class)) { + fieldValue = 29; + writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE); + out.writeByte(entry.getAugmentation(Icmpv6TypeMatchEntry.class).getIcmpv6Type()); + } else if (field.equals(Icmpv6Code.class)) { + fieldValue = 30; + writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE); + out.writeByte(entry.getAugmentation(Icmpv6CodeMatchEntry.class).getIcmpv6Code()); + } else if (field.equals(Ipv6NdTarget.class)) { + fieldValue = 31; + } else if (field.equals(Ipv6NdSll.class)) { + fieldValue = 32; + } else if (field.equals(Ipv6NdTll.class)) { + fieldValue = 33; + } else if (field.equals(MplsLabel.class)) { + fieldValue = 34; + writeOxmFieldAndLength(out, fieldValue, Integer.SIZE / Byte.SIZE); + out.writeInt(entry.getAugmentation(MplsLabelMatchEntry.class).getMplsLabel().intValue()); + } else if (field.equals(MplsTc.class)) { + fieldValue = 35; + writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE); + out.writeByte(entry.getAugmentation(TcMatchEntry.class).getTc()); + } else if (field.equals(MplsBos.class)) { + fieldValue = 36; + writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE); + out.writeBoolean(entry.getAugmentation(BosMatchEntry.class).isBos().booleanValue()); + } else if (field.equals(PbbIsid.class)) { + fieldValue = 37; + } else if (field.equals(TunnelId.class)) { + fieldValue = 38; + } else if (field.equals(Ipv6Exthdr.class)) { + fieldValue = 39; + } + } + + private static void writeOxmFieldAndLength(ByteBuf out, int fieldValue, int length) { + int fieldAndMask = fieldValue << 1; + out.writeByte(fieldAndMask); + out.writeByte(length); + } + +} diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/MultipartReplyMessageFactoryTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/MultipartReplyMessageFactoryTest.java index e96b05b8..df0ac6f0 100644 --- a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/MultipartReplyMessageFactoryTest.java +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/MultipartReplyMessageFactoryTest.java @@ -535,6 +535,9 @@ public class MultipartReplyMessageFactoryTest { message.getMeterStats().get(0).getMeterBandStats().get(2).getByteBandCount()); } + /** + * Testing {@link MultipartReplyMessageFactory} for correct translation into POJO + */ @Test public void testMultipartReplyMeterBodyMulti(){ ByteBuf bb = BufferHelper.buildBuffer("00 09 00 01 00 00 00 00 "+ @@ -935,7 +938,7 @@ public class MultipartReplyMessageFactoryTest { Assert.assertEquals("Wrong outputPort", 4351, message.getGroupDesc().get(0).getBucketsList().get(0).getActionsList().get(0). getAction().getAugmentation(PortAction.class). - getPort().getPortNumber().getValue().intValue()); + getPort().getValue().intValue()); Assert.assertEquals("Wrong outputMaxLen", 65535, message.getGroupDesc().get(0).getBucketsList().get(0).getActionsList().get(0). diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/QueueGetConfigReplyMessageFactoryTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/QueueGetConfigReplyMessageFactoryTest.java index 3b213648..4c447fc3 100644 --- a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/QueueGetConfigReplyMessageFactoryTest.java +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/QueueGetConfigReplyMessageFactoryTest.java @@ -24,6 +24,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731 */ public class QueueGetConfigReplyMessageFactoryTest { + /** + * Testing {@link QueueGetConfigReplyMessageFactory} for correct translation into POJO + */ @Test public void test(){ ByteBuf bb = BufferHelper.buildBuffer("00 01 02 03 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00"); @@ -33,7 +36,7 @@ public class QueueGetConfigReplyMessageFactoryTest { Assert.assertEquals("Wrong queues", builtByFactory.getQueues(), createQueuesList()); } - public List createQueuesList(){ + private static List createQueuesList(){ List queuesList = new ArrayList<>(); QueuesBuilder qb = new QueuesBuilder(); qb.setQueueId(new QueueId(1L)); @@ -44,7 +47,7 @@ public class QueueGetConfigReplyMessageFactoryTest { return queuesList; } - public List createPropertiesList(){ + private static List createPropertiesList(){ List propertiesList = new ArrayList<>(); PropertiesBuilder pb = new PropertiesBuilder(); pb.setProperty(QueueProperty.values()[2]); diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactoryTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactoryTest.java index bc5950fd..d42d5255 100644 --- a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactoryTest.java +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactoryTest.java @@ -7,8 +7,7 @@ import io.netty.buffer.UnpooledByteBufAllocator; import java.util.ArrayList; import java.util.List; -import junit.framework.Assert; - +import org.junit.Assert; import org.junit.Test; import org.opendaylight.openflowjava.protocol.impl.deserialization.factories.HelloMessageFactoryTest; import org.opendaylight.openflowjava.protocol.impl.util.BufferHelper; @@ -17,8 +16,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.group.mod.BucketsList; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.group.mod.BucketsListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.BucketsList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.BucketsListBuilder; /** * @author timotej.kubas @@ -38,7 +37,8 @@ public class GroupModInputMessageFactoryTest { builder.setCommand(GroupModCommand.forValue(2)); builder.setType(GroupType.forValue(3)); builder.setGroupId(256L); - builder.setBucketsList(createBucketsList()); + List exp = createBucketsList(); + builder.setBucketsList(exp); GroupModInput message = builder.build(); ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer(); @@ -46,11 +46,12 @@ public class GroupModInputMessageFactoryTest { factory.messageToBuffer(HelloMessageFactoryTest.VERSION_YET_SUPPORTED, out, message); BufferHelper.checkHeaderV13(out, factory.getMessageType(), factory.computeLength(message)); - Assert.assertEquals("Wrong command", message.getCommand().getIntValue(), out.readShort()); - Assert.assertEquals("Wrong type", message.getType().getIntValue(), out.readByte()); + Assert.assertEquals("Wrong command", message.getCommand().getIntValue(), out.readUnsignedShort()); + Assert.assertEquals("Wrong type", message.getType().getIntValue(), out.readUnsignedByte()); out.skipBytes(PADDING_IN_GROUP_MOD_MESSAGE); Assert.assertEquals("Wrong groupId", message.getGroupId().intValue(), out.readUnsignedInt()); - Assert.assertEquals("Wrong bucketList", createBucketsList(), createBucketsListFromBufer(out)); + List rec = createBucketsListFromBufer(out); + Assert.assertArrayEquals("Wrong bucketList", exp.toArray(), rec.toArray()); } private static List createBucketsList(){ @@ -69,7 +70,8 @@ public class GroupModInputMessageFactoryTest { List bucketsList = new ArrayList<>(); BucketsListBuilder bucketsBuilder = new BucketsListBuilder(); BucketsList bucket; - bucketsBuilder.setWeight((int) out.readShort()); + out.skipBytes(Short.SIZE / Byte.SIZE); + bucketsBuilder.setWeight(out.readUnsignedShort()); bucketsBuilder.setWatchPort(new PortNumber(out.readUnsignedInt())); bucketsBuilder.setWatchGroup(out.readUnsignedInt()); out.skipBytes(4); diff --git a/pom.xml b/pom.xml index 9e26b860..f446c093 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,7 @@ 1.0-SNAPSHOT 2.4.0 14.0.1 + 4.0.10.Final @@ -153,7 +154,7 @@ io.netty netty-handler - 4.0.8.Final + ${netty.version} com.google.guava -- 2.36.6