From 6fb89f647f3f393c8f2c697076da53fb987f03ef Mon Sep 17 00:00:00 2001 From: Timotej Kubas Date: Mon, 28 Oct 2013 09:00:41 +0100 Subject: [PATCH] multipart reply message updated added actions added match entries fixed names for augmentation Change-Id: I4d663eabb8ad0ac883c470ca0577b9c853e50805 Signed-off-by: Timotej Kubas --- openflow-protocol-api/pom.xml | 5 + .../src/main/yang/openflow-augments.yang | 47 +- .../MultipartReplyMessageFactory.java | 72 +++- .../protocol/impl/util/ActionCreator.java | 403 +++++++++++++++++ .../impl/util/MatchEntriesCreator.java | 117 +++++ .../MultipartReplyMessageFactoryTest.java | 408 +++++++++++++++++- 6 files changed, 1043 insertions(+), 9 deletions(-) create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/ActionCreator.java create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/MatchEntriesCreator.java diff --git a/openflow-protocol-api/pom.xml b/openflow-protocol-api/pom.xml index c8cea44e..fc71be0d 100644 --- a/openflow-protocol-api/pom.xml +++ b/openflow-protocol-api/pom.xml @@ -145,6 +145,11 @@ ietf-yang-types 2010.09.24-SNAPSHOT + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + \ No newline at end of file diff --git a/openflow-protocol-api/src/main/yang/openflow-augments.yang b/openflow-protocol-api/src/main/yang/openflow-augments.yang index 37c2f5b2..75c6590b 100644 --- a/openflow-protocol-api/src/main/yang/openflow-augments.yang +++ b/openflow-protocol-api/src/main/yang/openflow-augments.yang @@ -1,7 +1,8 @@ module openflow-augments { namespace "urn:opendaylight:openflow:augments"; prefix "aug"; - + + import yang-ext {prefix ext;} import ietf-inet-types {prefix inet;} import ietf-yang-types {prefix yang;} @@ -17,126 +18,151 @@ module openflow-augments { // OFP_MATCH AUGMENTS augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "port-number-match-entry"; leaf port-number { type oft:port-number; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "metadata-match-entry"; leaf metadata { type binary; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "mask-match-entry"; leaf mask { type binary; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "mac-address-match-entry"; leaf mac-address { type yang:mac-address; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "eth-type-match-entry"; leaf eth-type { type oft:ether-type; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "vlan-vid-match-entry"; leaf vlan-vid { type uint16; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "vlan-pcp-match-entry"; leaf vlan-pcp { type uint8; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "dscp-match-entry"; leaf dscp { type inet:dscp; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "ecn-match-entry"; leaf ecn { type uint8; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "protocol-number-match-entry"; leaf protocol-number { 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 { type inet:port-number; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "icmpv4-type-match-entry"; leaf icmpv4-type { type uint8; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "icmpv4-code-match-entry"; leaf icmpv4-code { type uint8; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "op-code-match-entry"; leaf op-code { 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 { type inet:ipv6-flow-label; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "icmpv6-type-match-entry"; leaf icmpv6-type { type uint8; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "icmpv6-code-match-entry"; leaf icmpv6-code { type uint8; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "ipv6-address-match-entry"; leaf ipv6-address { type inet:ipv6-address; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "mpls-label-match-entry"; leaf mpls-label { type uint32; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "tc-match-entry"; leaf tc { type uint8; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "bos-match-entry"; leaf bos { type boolean; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "isid-match-entry"; leaf isid { type uint32; } } augment "/oxm:oxm-container/oxm:match-entries" { + ext:augment-identifier "pseudo-field-match-entry"; leaf pseudo-field { type bits { bit nonext { @@ -181,44 +207,53 @@ module openflow-augments { // OFP_ACTION AUGMENTS augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "port-action"; leaf port { type oft:any-port-number; } } augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "max-length-action"; leaf max-length { type uint16; } } augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "mpls-ttl-action"; leaf mpls-ttl { type uint8; } } augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "ethertype-action"; leaf ethertype { type oft:ether-type; } } augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "queue-id-action"; leaf queue-id { type uint32; } } augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "group-id-action"; leaf group-id { type uint32; } } augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "nw-ttl-action"; leaf nw-ttl { type uint8; } } augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "oxm-fields-action"; uses oxm:oxm-fields; } augment "/ofaction:actions-container/ofaction:action" { + ext:augment-identifier "experimenter-action"; leaf experimenter { type uint32; } @@ -226,11 +261,13 @@ module openflow-augments { // OFP_TABLE_FEATURES_PROPERTIES AUGMENTS augment "/ofproto:table-features-properties-container/ofproto:table-feature-properties" { + ext:augment-identifier "instruction-ids-table-feature-properties"; list instruction-ids { uses ofinstruction:instructions; } } augment "/ofproto:table-features-properties-container/ofproto:table-feature-properties" { + ext:augment-identifier "next-table-ids-table-feature-properties"; list next-table-ids { leaf table-id { type uint8; @@ -238,16 +275,19 @@ module openflow-augments { } } augment "/ofproto:table-features-properties-container/ofproto:table-feature-properties" { + ext:augment-identifier "action-ids-table-feature-properties"; list action-ids { uses ofaction:action-header; } } augment "/ofproto:table-features-properties-container/ofproto:table-feature-properties" { + ext:augment-identifier "oxm-ids-table-feature-properties"; list oxm-ids { uses oxm:oxm-fields; } } augment "/ofproto:table-features-properties-container/ofproto:table-feature-properties" { + ext:augment-identifier "experimenter-table-feature-properties"; leaf experimenter { type uint32; } @@ -261,11 +301,13 @@ module openflow-augments { // OFP_INSTRUCTION AUGMENTS augment "/ofinstruction:instruction-container/ofinstruction:instruction" { + ext:augment-identifier "table-id-instruction"; leaf table-id { type uint8; } } augment "/ofinstruction:instruction-container/ofinstruction:instruction" { + ext:augment-identifier "metadata-instruction"; leaf metadata { type binary; } @@ -274,16 +316,19 @@ module openflow-augments { } } augment "/ofinstruction:instruction-container/ofinstruction:instruction" { + ext:augment-identifier "action-header-instruction"; list actions { uses ofaction:action-header; } } augment "/ofinstruction:instruction-container/ofinstruction:instruction" { + ext:augment-identifier "meter-id-instruction"; leaf meter-id { type uint32; } } augment "/ofinstruction:instruction-container/ofinstruction:instruction" { + ext:augment-identifier "experimenter-instruction"; leaf experimenter { type uint32; } 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 ffa36485..a8011b81 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,8 +8,10 @@ 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; 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.GroupType; 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; @@ -17,9 +19,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber; 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.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; @@ -33,6 +37,8 @@ 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.MultipartReplyFlowBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroup; 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.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; @@ -51,6 +57,10 @@ 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.flow.FlowStatsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.GroupStats; 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; @@ -119,6 +129,8 @@ public class MultipartReplyMessageFactory implements OFDeserializer flowStatsList = new ArrayList<>(); FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder(); - int flowLen = 0; while (input.readableBytes() > 0) { - flowLen = input.readUnsignedShort(); + input.skipBytes(flowLength); flowStatsBuilder.setTableId(input.readUnsignedByte()); input.skipBytes(PADDING_IN_FLOW_STATS_HEADER_01); flowStatsBuilder.setDurationSec(input.readUnsignedInt()); @@ -461,6 +473,7 @@ public class MultipartReplyMessageFactory implements OFDeserializer meterConfigList = new ArrayList<>(); @@ -481,18 +494,17 @@ public class MultipartReplyMessageFactory implements OFDeserializer groupDescsList = new ArrayList<>(); + BucketsListBuilder bucketsBuilder = new BucketsListBuilder(); + List bucketsList = new ArrayList<>(); + List actionsList = new ArrayList<>(); + + while (input.readableBytes() > 0) { + bodyLength = input.readUnsignedShort(); + actualLength = 0; + + groupDescBuilder.setType(GroupType.forValue(input.readUnsignedByte())); // TODO enum or class? + input.skipBytes(PADDING_IN_GROUP_DESC_HEADER); + groupDescBuilder.setGroupId(input.readUnsignedInt()); + actualLength = GROUP_DESC_HEADER_LENGTH; + + while (actualLength < bodyLength) { + + bucketsLength = input.readUnsignedShort(); + bucketsBuilder.setWeight(input.readUnsignedShort()); + bucketsBuilder.setWatchPort(new PortNumber(input.readUnsignedInt())); + bucketsBuilder.setWatchGroup(input.readUnsignedInt()); + input.skipBytes(PADDING_IN_BUCKETS_HEADER); + bucketsCurrentLength = bucketsLength; + actionsList = ActionCreator.createActionsList(input, bucketsLength); + bucketsBuilder.setActionsList(new ArrayList<>(actionsList)); + actionsList.clear(); + bucketsList.add(bucketsBuilder.build()); + actualLength = actualLength + bucketsCurrentLength; + } + groupDescBuilder.setBucketsList(new ArrayList<>(bucketsList)); + bucketsList.clear(); + groupDescsList.add(groupDescBuilder.build()); + } + builder.setGroupDesc(new ArrayList<>(groupDescsList)); + groupDescsList.clear(); + return builder.build(); + } + } diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/ActionCreator.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/ActionCreator.java new file mode 100644 index 00000000..3610d735 --- /dev/null +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/ActionCreator.java @@ -0,0 +1,403 @@ +/* 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.opendaylight.openflow.augments.rev131002.EthertypeAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthertypeActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.GroupIdAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.GroupIdActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaxLengthAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaxLengthActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsTtlAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsTtlActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NwTtlAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NwTtlActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmFieldsAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmFieldsActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.QueueIdAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.QueueIdActionBuilder; +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.ActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.AnyPortNumber; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.bucket.ActionsList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.bucket.ActionsListBuilder; + +/** + * Class for easy creation of actions + * + * @author timotej.kubas + * @author michal.polkorab + */ +public abstract class ActionCreator { + final static byte PAD_ACTION_LENGTH = 2; + private static ActionBuilder actionBuilder = new ActionBuilder(); + private static ActionsListBuilder actionsListBuilder = new ActionsListBuilder(); + private static List actionsList = new ArrayList<>(); +/** + * @param inp input ByteBuf + * @param bucketsLength length of buckets + * @return ActionsList + */ + public static List createActionsList(ByteBuf inp, 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; + break; + case 11: + actionsLength = inp.readUnsignedShort();//empty header length + actionsList.add(ActionCreator.createCopyTtlOutAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 12: + actionsLength = inp.readUnsignedShort();//empty header length + actionsList.add(ActionCreator.createCopyTtlInAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 15: + actionsLength = inp.readUnsignedShort();//empty header length + actionsList.add(ActionCreator.createSetMplsTtlAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 16: + actionsLength = inp.readUnsignedShort();//empty header length + actionsList.add(ActionCreator.createDecMplsTtlOutAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 17: + actionsLength = inp.readUnsignedShort(); + actionsList.add(ActionCreator.createPushVlanAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 18: + actionsLength = inp.readUnsignedShort();//empty header length + actionsList.add(ActionCreator.createPopVlanAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 19: + actionsLength = inp.readUnsignedShort();//8 + actionsList.add(ActionCreator.createPushMplsAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 20: + actionsLength = inp.readUnsignedShort();//8 + actionsList.add(ActionCreator.createPopMplsAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 21: + actionsLength = inp.readUnsignedShort(); + actionsList.add(ActionCreator.createSetQueueAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 22: + actionsLength = inp.readUnsignedShort();//8 + actionsList.add(ActionCreator.createGroupAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 23: + actionsLength = inp.readUnsignedShort();//8 + actionsList.add(ActionCreator.createSetNwTtlAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 24: + actionsLength = inp.readUnsignedShort();//empty header length + actionsList.add(ActionCreator.createDecNwTtlAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 25: + actionsLength = inp.readUnsignedShort();//8 + //TODO field + actionsList.add(ActionCreator.createSetFieldAction(inp, actionsLength)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + case 26: + actionsLength = inp.readUnsignedShort();//8 + actionsList.add(ActionCreator.createPushPbbAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 27: + actionsLength = inp.readUnsignedShort();//empty header length + actionsList.add(ActionCreator.createPopPbbAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + + case 0xFFFF: + actionsLength = inp.readUnsignedShort(); + actionsList.add(ActionCreator.createExperimenterAction(inp)); + bucketsCurrentLength = bucketsCurrentLength + actionsLength; + break; + default: + break; + } + } + return actionsList; + } + + + /** + * @param action input action that contains empty header + * @param in input ByteBuf + * @return Action + */ + private static ActionsList createEmptyHeader(Class action, ByteBuf in) { + final byte PADDING_IN_ACTIONS_HEADER = 4; + + actionBuilder.setType(action); + in.skipBytes(PADDING_IN_ACTIONS_HEADER); + actionsListBuilder.setAction(actionBuilder.build()); + return actionsListBuilder.build(); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createCopyTtlInAction(ByteBuf in) { + return createEmptyHeader(CopyTtlIn.class, in); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createCopyTtlOutAction(ByteBuf in) { + return createEmptyHeader(CopyTtlOut.class, in); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createDecMplsTtlOutAction(ByteBuf in) { + return createEmptyHeader(DecMplsTtl.class, in); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createPopVlanAction(ByteBuf in) { + return createEmptyHeader(PopVlan.class, in); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createDecNwTtlAction(ByteBuf in) { + return createEmptyHeader(DecNwTtl.class, in); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createPopPbbAction(ByteBuf in) { + return createEmptyHeader(PopPbb.class, in); + } + + /** + * @param in input ByteBuf + * @return ActionList + */ + public static ActionsList createOutputAction(ByteBuf in) { + final byte PADDING_IN_OUTPUT_ACTIONS_HEADER = 6; + + actionBuilder.setType(Output.class); + PortActionBuilder port = new PortActionBuilder(); + port.setPort(new AnyPortNumber(new PortNumber(in.readUnsignedInt()))); + actionBuilder.addAugmentation(PortAction.class, port.build()); + MaxLengthActionBuilder maxLen = new MaxLengthActionBuilder(); + maxLen.setMaxLength(in.readUnsignedShort()); + actionBuilder.addAugmentation(MaxLengthAction.class, maxLen.build()); + actionsListBuilder.setAction(actionBuilder.build()); + in.skipBytes(PADDING_IN_OUTPUT_ACTIONS_HEADER); + + return actionsListBuilder.build(); + } + + /** + * @param in input ByteBuf + * @return ActionList + */ + public static ActionsList createSetMplsTtlAction(ByteBuf in) { + final byte PADDING_IN_SET_MPLS_TTL_ACTIONS_HEADER = 3; + + actionBuilder.setType(SetMplsTtl.class); + MplsTtlActionBuilder mplsTtl = new MplsTtlActionBuilder(); + mplsTtl.setMplsTtl(in.readUnsignedByte()); + actionBuilder.addAugmentation(MplsTtlAction.class, mplsTtl.build()); + actionsListBuilder.setAction(actionBuilder.build()); + in.skipBytes(PADDING_IN_SET_MPLS_TTL_ACTIONS_HEADER); + + return actionsListBuilder.build(); + } + + /** + * @param action input action that contains push + * @param in input ByteBuf + * @return ActionList + */ + private static ActionsList createPushAction(Class action, ByteBuf in) { + final byte PADDING_IN_PUSH_VLAN_ACTIONS_HEADER = 2; + + actionBuilder.setType(action); + EthertypeActionBuilder etherType = new EthertypeActionBuilder(); + etherType.setEthertype(new EtherType(in.readUnsignedShort())); + actionBuilder.addAugmentation(EthertypeAction.class, etherType.build()); + actionsListBuilder.setAction(actionBuilder.build()); + in.skipBytes(PADDING_IN_PUSH_VLAN_ACTIONS_HEADER); + + return actionsListBuilder.build(); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createPushVlanAction(ByteBuf in) { + return createPushAction(PushVlan.class, in); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createPushMplsAction(ByteBuf in) { + return createPushAction(PushMpls.class, in); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createPopMplsAction(ByteBuf in) { + return createPushAction(PopMpls.class, in); + } + + /** + * @param in input ByteBuf + * @return Action + */ + public static ActionsList createPushPbbAction(ByteBuf in) { + return createPushAction(PushPbb.class, in); + } + + /** + * @param in input ByteBuf + * @return ActionList + */ + public static ActionsList createSetQueueAction(ByteBuf in) { + actionBuilder.setType(SetQueue.class); + QueueIdActionBuilder queueId = new QueueIdActionBuilder(); + queueId.setQueueId(in.readUnsignedInt()); + actionBuilder.addAugmentation(QueueIdAction.class, queueId.build()); + actionsListBuilder.setAction(actionBuilder.build()); + + return actionsListBuilder.build(); + } + + /** + * @param in input ByteBuf + * @return ActionList + */ + public static ActionsList createGroupAction(ByteBuf in) { + actionBuilder.setType(Group.class); + GroupIdActionBuilder group = new GroupIdActionBuilder(); + group.setGroupId(in.readUnsignedInt()); + actionBuilder.addAugmentation(GroupIdAction.class, group.build()); + actionsListBuilder.setAction(actionBuilder.build()); + + return actionsListBuilder.build(); + } + + /** + * @param in input ByteBuf + * @return ActionList + */ + public static ActionsList createExperimenterAction(ByteBuf in) { + actionBuilder.setType(Experimenter.class); + ExperimenterActionBuilder experimenter = new ExperimenterActionBuilder(); + experimenter.setExperimenter(in.readUnsignedInt()); + actionBuilder.addAugmentation(ExperimenterAction.class, experimenter.build()); + actionsListBuilder.setAction(actionBuilder.build()); + + return actionsListBuilder.build(); + } + + /** + * @param in input ByteBuf + * @return ActionList + */ + public static ActionsList createSetNwTtlAction(ByteBuf in) { + final byte PADDING_IN_NW_TTL_ACTIONS_HEADER = 3; + + actionBuilder.setType(SetNwTtl.class); + NwTtlActionBuilder nwTtl = new NwTtlActionBuilder(); + nwTtl.setNwTtl(in.readUnsignedByte()); + actionBuilder.addAugmentation(NwTtlAction.class, nwTtl.build()); + actionsListBuilder.setAction(actionBuilder.build()); + in.skipBytes(PADDING_IN_NW_TTL_ACTIONS_HEADER); + + return actionsListBuilder.build(); + } + + /** + * @param in input ByteBuf + * @param actionLength length of action + * @return ActionList + */ + public static ActionsList createSetFieldAction(ByteBuf in, int actionLength) { + actionBuilder.setType(SetField.class); + OxmFieldsActionBuilder matchEntries = new OxmFieldsActionBuilder(); + matchEntries.setMatchEntries(MatchEntriesCreator.createMatchEntry(in, actionLength - 4)); + actionBuilder.addAugmentation(OxmFieldsAction.class, matchEntries.build()); + actionsListBuilder.setAction(actionBuilder.build()); + + return actionsListBuilder.build(); + } +} 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 new file mode 100644 index 00000000..7d5456c1 --- /dev/null +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/MatchEntriesCreator.java @@ -0,0 +1,117 @@ +/* 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