Multiple meter support added and meter action added for OF1.5
MeterFeaturesFlag added for OF1.5

Change-Id: I84d2785f37ea51b08244de9c54effe5224af9531
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
index 8bde2f6..c6a1c16 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -19,7 +19,10 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 import org.onlab.packet.EthType;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
@@ -56,7 +59,7 @@
 
     private static final DefaultTrafficTreatment EMPTY
             = new DefaultTrafficTreatment(ImmutableList.of(Instructions.createNoAction()));
-    private final Instructions.MeterInstruction meter;
+    private final Set<Instructions.MeterInstruction> meter;
 
     /**
      * Creates a new traffic treatment from the specified list of instructions.
@@ -70,7 +73,7 @@
         this.hasClear = false;
         this.table = null;
         this.meta = null;
-        this.meter = null;
+        this.meter = ImmutableSet.of();
         this.statTrigger = null;
     }
 
@@ -87,7 +90,7 @@
                                     Instructions.TableTypeTransition table,
                                     boolean clear,
                                     Instructions.MetadataInstruction meta,
-                                    Instructions.MeterInstruction meter,
+                                    Set<Instructions.MeterInstruction> meters,
                                     Instructions.StatTriggerInstruction statTrigger
                                     ) {
         this.immediate = ImmutableList.copyOf(checkNotNull(immediate));
@@ -99,7 +102,7 @@
         this.table = table;
         this.meta = meta;
         this.hasClear = clear;
-        this.meter = meter;
+        this.meter = ImmutableSet.copyOf(meters);
         this.statTrigger = statTrigger;
     }
 
@@ -140,6 +143,14 @@
 
     @Override
     public Instructions.MeterInstruction metered() {
+        if (meter.isEmpty()) {
+            return null;
+        }
+        return meter.iterator().next();
+    }
+
+    @Override
+    public Set<Instructions.MeterInstruction> meters() {
         return meter;
     }
 
@@ -200,7 +211,7 @@
                 .add("immediate", immediate)
                 .add("deferred", deferred)
                 .add("transition", table == null ? "None" : table.toString())
-                .add("meter", meter == null ? "None" : meter.toString())
+                .add("meter", meter == null ? "None" : meter)
                 .add("cleared", hasClear)
                 .add("StatTrigger", statTrigger)
                 .add("metadata", meta)
@@ -219,7 +230,7 @@
 
         Instructions.MetadataInstruction meta;
 
-        Instructions.MeterInstruction meter;
+        Set<Instructions.MeterInstruction> meter = Sets.newHashSet();
 
         Instructions.StatTriggerInstruction statTrigger;
 
@@ -271,7 +282,7 @@
                     meta = (Instructions.MetadataInstruction) instruction;
                     break;
                 case METER:
-                    meter = (Instructions.MeterInstruction) instruction;
+                    meter.add((Instructions.MeterInstruction) instruction);
                     break;
                 case STAT_TRIGGER:
                     statTrigger = (Instructions.StatTriggerInstruction) instruction;
diff --git a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
index 057f0f8..f61b017 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
@@ -17,6 +17,7 @@
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import com.google.common.annotations.Beta;
 import org.onlab.packet.EthType;
@@ -90,11 +91,18 @@
     /**
      * Returns the meter instruction if there is one.
      *
-     * @return a meter instruction that may be null
+     * @return a meter instruction that may be a null.
      */
     Instructions.MeterInstruction metered();
 
     /**
+     * Returns the meter instructions if there is any.
+     *
+     * @return meter instructions that may be an empty set.
+     */
+    Set<Instructions.MeterInstruction> meters();
+
+    /**
      * Builder of traffic treatment entities.
      */
     interface Builder {
diff --git a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterFeatures.java b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterFeatures.java
index 1835872..bd5d998 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterFeatures.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterFeatures.java
@@ -16,6 +16,7 @@
 package org.onosproject.net.meter;
 
 import com.google.common.base.MoreObjects;
+import com.google.common.collect.Sets;
 import org.onosproject.net.DeviceId;
 
 import java.util.HashSet;
@@ -35,11 +36,12 @@
     private boolean stats;
     private short maxBands;
     private short maxColor;
+    private Set<MeterFeaturesFlag> features;
 
     private DefaultMeterFeatures(DeviceId did, long maxMeter,
                                  Set<Band.Type> bandTypes, Set<Meter.Unit> units,
                                  boolean burst, boolean stats,
-                                 short maxBands, short maxColor) {
+                                 short maxBands, short maxColor, Set<MeterFeaturesFlag> flag) {
         this.deviceId = did;
         this.maxMeter = maxMeter;
         this.bandTypes = bandTypes;
@@ -48,6 +50,7 @@
         this.units = units;
         this.maxBands = maxBands;
         this.maxColor = maxColor;
+        this.features = flag;
     }
 
     @Override
@@ -90,6 +93,11 @@
         return maxColor;
     }
 
+    @Override
+    public Set<MeterFeaturesFlag> features() {
+        return features;
+    }
+
     public static Builder builder() {
         return new Builder();
     }
@@ -125,6 +133,7 @@
         private Set<Meter.Unit> units1 = new HashSet<>();
         private boolean burst = false;
         private boolean stats = false;
+        private Set<MeterFeaturesFlag> features = Sets.newHashSet();
 
         @Override
         public MeterFeatures.Builder forDevice(DeviceId deviceId) {
@@ -175,9 +184,15 @@
         }
 
         @Override
+        public MeterFeatures.Builder withFeatures(Set<MeterFeaturesFlag> featureFlags) {
+            features = featureFlags;
+            return this;
+        }
+
+        @Override
         public MeterFeatures build() {
             checkNotNull(did, "Must specify a device");
-            return new DefaultMeterFeatures(did, mmeter, bandTypes, units1, burst, stats, mbands, mcolors);
+            return new DefaultMeterFeatures(did, mmeter, bandTypes, units1, burst, stats, mbands, mcolors, features);
         }
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterFeatures.java b/core/api/src/main/java/org/onosproject/net/meter/MeterFeatures.java
index 143e927..2749687 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/MeterFeatures.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterFeatures.java
@@ -81,6 +81,14 @@
     short maxColor();
 
     /**
+     * Returns features flags that supported for meter actions by device.
+     *
+     * @return meter features flags
+     * otherwise empty set.
+     */
+    Set<MeterFeaturesFlag> features();
+
+    /**
      * A meter features builder.
      */
     interface Builder {
@@ -149,6 +157,14 @@
         Builder hasStats(boolean hasStats);
 
         /**
+         * Assigns the features for this meter features for OF1.5.
+         *
+         * @param featureFlags if meter features flags are supported
+         * @return this builder
+         */
+        Builder withFeatures(Set<MeterFeaturesFlag> featureFlags);
+
+        /**
          * Builds the Meter Features based on the specified parameters.
          *
          * @return the meter features
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterFeaturesFlag.java b/core/api/src/main/java/org/onosproject/net/meter/MeterFeaturesFlag.java
new file mode 100644
index 0000000..36356ef
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterFeaturesFlag.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+public enum MeterFeaturesFlag {
+    /**
+     * Support meter action in action set.
+     */
+    ACTION_SET,
+    /**
+     * Support any position in action list.
+     */
+    ANY_POSITION,
+    /**
+     * Support multiple actions in action list.
+     */
+    MULTI_LIST
+}
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
index a05745c..90cc697 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
@@ -16,6 +16,7 @@
 package org.onosproject.net.intent;
 
 import com.google.common.base.MoreObjects;
+import com.google.common.collect.Sets;
 import org.onlab.graph.Weight;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.DefaultPath;
@@ -121,6 +122,11 @@
         public Instructions.MeterInstruction metered() {
             return null;
         }
+
+        @Override
+        public Set<Instructions.MeterInstruction> meters() {
+            return Sets.newHashSet();
+        }
     }
 
     /**
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/TrafficTreatmentCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/TrafficTreatmentCodec.java
index 0003318..4a2bc92 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/TrafficTreatmentCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/TrafficTreatmentCodec.java
@@ -23,6 +23,7 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
 
 import java.util.stream.IntStream;
 
@@ -51,7 +52,9 @@
         }
 
         if (treatment.metered() != null) {
-            jsonInstructions.add(instructionCodec.encode(treatment.metered(), context));
+            for (Instructions.MeterInstruction instruction : treatment.meters()) {
+                jsonInstructions.add(instructionCodec.encode(instruction, context));
+            }
         }
         if (treatment.tableTransition() != null) {
             jsonInstructions.add(instructionCodec.encode(treatment.tableTransition(), context));
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/TrafficTreatmentCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/TrafficTreatmentCodecTest.java
index ed87ce0..b014bcf 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/TrafficTreatmentCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/TrafficTreatmentCodecTest.java
@@ -35,6 +35,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
+import java.util.Optional;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -163,9 +164,11 @@
             // check metered
             JsonNode meterNode = getInstNode(jsonInstructions, "METER");
             String jsonMeterId = meterNode != null ? meterNode.get("meterId").asText() : null;
-            if (trafficTreatment.metered() != null) {
-                String meterId = trafficTreatment.metered().meterId().toString();
-                if (!StringUtils.equals(jsonMeterId, meterId)) {
+            if (trafficTreatment.metered() != null && !trafficTreatment.meters().isEmpty()) {
+                Optional<Instructions.MeterInstruction> optional = trafficTreatment.meters().stream().filter(
+                        meterInstruction -> StringUtils.equals(jsonMeterId, meterInstruction.meterId().toString()))
+                        .findAny();
+                if (!optional.isPresent()) {
                     description.appendText("meter id was " + jsonMeterId);
                     return false;
                 }
diff --git a/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
index 7785a38..3697641 100644
--- a/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
@@ -673,6 +673,11 @@
             return null;
         }
 
+        @Override
+        public Set<Instructions.MeterInstruction> meters() {
+            return Sets.newHashSet();
+        }
+
     }
 
     public class TestApplicationId extends DefaultApplicationId {
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
index 584401e..1561d4a 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
@@ -473,6 +473,11 @@
         public Instructions.MeterInstruction metered() {
             return null;
         }
+
+        @Override
+        public Set<Instructions.MeterInstruction> meters() {
+            return Sets.newHashSet();
+        }
     }
 
     private void validateEvents(TestFlowRuleListener listener, FlowRuleEvent.Type... events) {
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
index 2903663..b654652 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
@@ -40,6 +40,7 @@
 import org.onosproject.net.meter.MeterEvent;
 import org.onosproject.net.meter.MeterFailReason;
 import org.onosproject.net.meter.MeterFeatures;
+import org.onosproject.net.meter.MeterFeaturesFlag;
 import org.onosproject.net.meter.MeterFeaturesKey;
 import org.onosproject.net.meter.MeterId;
 import org.onosproject.net.meter.MeterKey;
@@ -159,7 +160,8 @@
                                                  DefaultMeterFeatures.class,
                                                  Band.Type.class,
                                                  Meter.Unit.class,
-                                                 MeterFailReason.class)).build();
+                                                 MeterFailReason.class,
+                                                 MeterFeaturesFlag.class)).build();
 
         // Init the set of the available ids
         availableMeterIds = new DefaultDistributedSet<>(storageService.<MeterKey>setBuilder()
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer15.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer15.java
index 7ba893a..7f5a099 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer15.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer15.java
@@ -172,9 +172,11 @@
         List<OFAction> actions = new LinkedList<>();
 
         //Meter action handling
-        if (null != treatment.metered() && immediateActions) {
-            OFAction meterAction = buildMultipleMeterAction(treatment.metered());
-            actions.add(meterAction);
+        if (null != treatment.meters() && immediateActions) {
+            treatment.meters().forEach(meterInstruction -> {
+                OFAction meterAction = buildMeterAction(meterInstruction);
+                actions.add(meterAction);
+            });
         }
 
         for (Instruction i : treatments) {
@@ -287,7 +289,7 @@
      * @param meterInstruction meter instruction
      * @return meter action
      */
-    protected OFAction buildMultipleMeterAction(Instructions.MeterInstruction meterInstruction) {
+    protected OFAction buildMeterAction(Instructions.MeterInstruction meterInstruction) {
         OFActionMeter.Builder meterBuilder = factory().actions().buildMeter()
                 .setMeterId(meterInstruction.meterId().id());
         return meterBuilder.build();
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
index c16c34f..dee9455 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
@@ -49,6 +49,7 @@
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes;
 import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.meter.MeterId;
 import org.onosproject.openflow.controller.ExtensionSelectorInterpreter;
 import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
 import org.onosproject.provider.of.flow.impl.NewAdaptiveFlowStatsCollector;
@@ -66,6 +67,7 @@
 import org.projectfloodlight.openflow.protocol.action.OFActionEnqueue;
 import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
+import org.projectfloodlight.openflow.protocol.action.OFActionMeter;
 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
 import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls;
 import org.projectfloodlight.openflow.protocol.action.OFActionPushVlan;
@@ -605,6 +607,10 @@
                     OFActionPushVlan pushVlan = (OFActionPushVlan) act;
                     builder.pushVlan(new EthType((short) pushVlan.getEthertype().getValue()));
                     break;
+                case METER:
+                    OFActionMeter actionMeter = (OFActionMeter) act;
+                    builder.meter(MeterId.meterId(actionMeter.getMeterId()));
+                    break;
                 case SET_TP_DST:
                 case SET_TP_SRC:
                 case POP_PBB:
diff --git a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java
index 24fd49f..90a8a9b 100644
--- a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java
+++ b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java
@@ -22,6 +22,7 @@
 import org.projectfloodlight.openflow.protocol.OFMeterFlags;
 import org.projectfloodlight.openflow.protocol.OFMeterMod;
 import org.projectfloodlight.openflow.protocol.OFMeterModCommand;
+import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.protocol.meterband.OFMeterBand;
 import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandDrop;
 import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandDscpRemark;
@@ -118,8 +119,13 @@
             default:
                 log.warn("Unknown unit type {}", unit);
         }
-        //FIXME: THIS WILL CHANGE IN OF1.4 to setBands.
-        builder.setMeters(buildBands());
+
+        if (factory.getVersion().getWireVersion() >= OFVersion.OF_14.getWireVersion()) {
+            builder.setBands(buildBands());
+        } else {
+            builder.setMeters(buildBands());
+        }
+
         builder.setFlags(flags)
                 .setMeterId(id)
                 .setXid(xid);
diff --git a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/util/MeterFeaturesBuilder.java b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/util/MeterFeaturesBuilder.java
index abfa4aa..35f9dde 100644
--- a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/util/MeterFeaturesBuilder.java
+++ b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/util/MeterFeaturesBuilder.java
@@ -21,7 +21,9 @@
 import org.onosproject.net.meter.DefaultMeterFeatures;
 import org.onosproject.net.meter.Meter;
 import org.onosproject.net.meter.MeterFeatures;
+import org.onosproject.net.meter.MeterFeaturesFlag;
 import org.projectfloodlight.openflow.protocol.OFMeterFeatures;
+import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -32,9 +34,15 @@
 import static org.onosproject.net.meter.Band.Type.REMARK;
 import static org.onosproject.net.meter.Meter.Unit.KB_PER_SEC;
 import static org.onosproject.net.meter.Meter.Unit.PKTS_PER_SEC;
+import static org.onosproject.net.meter.MeterFeaturesFlag.ACTION_SET;
+import static org.onosproject.net.meter.MeterFeaturesFlag.ANY_POSITION;
+import static org.onosproject.net.meter.MeterFeaturesFlag.MULTI_LIST;
 import static org.projectfloodlight.openflow.protocol.ver13.OFMeterBandTypeSerializerVer13.DROP_VAL;
 import static org.projectfloodlight.openflow.protocol.ver13.OFMeterBandTypeSerializerVer13.DSCP_REMARK_VAL;
 import static org.projectfloodlight.openflow.protocol.ver13.OFMeterFlagsSerializerVer13.*;
+import static org.projectfloodlight.openflow.protocol.ver15.OFMeterFeatureFlagsSerializerVer15.ACTION_SET_VAL;
+import static org.projectfloodlight.openflow.protocol.ver15.OFMeterFeatureFlagsSerializerVer15.ANY_POSITION_VAL;
+import static org.projectfloodlight.openflow.protocol.ver15.OFMeterFeatureFlagsSerializerVer15.MULTI_LIST_VAL;
 
 /**
  * OpenFlow builder of MeterFeatures.
@@ -98,6 +106,24 @@
          * Stats are supported ?
          */
         builder.hasStats((STATS_VAL & ofMeterFeatures.getCapabilities()) != 0);
+
+        /*
+         * Along with the OF1.5, we extract meter features flags
+         */
+        if (ofMeterFeatures.getVersion().wireVersion >= OFVersion.OF_15.wireVersion) {
+            Set<MeterFeaturesFlag> meterFeaturesFlags = Sets.newHashSet();
+            if ((ACTION_SET_VAL & ofMeterFeatures.getFeatures()) != 0) {
+                meterFeaturesFlags.add(ACTION_SET);
+            }
+            if ((ANY_POSITION_VAL & ofMeterFeatures.getFeatures()) != 0) {
+                meterFeaturesFlags.add(ANY_POSITION);
+            }
+            if ((MULTI_LIST_VAL & ofMeterFeatures.getFeatures()) != 0) {
+                meterFeaturesFlags.add(MULTI_LIST);
+            }
+            builder.withFeatures(meterFeaturesFlags);
+        }
+
         return builder.build();
     }
 
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
index 8f2a0a5..3160ec7 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
@@ -20,6 +20,7 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
 import org.onosproject.app.ApplicationService;
 import org.onosproject.core.Application;
 import org.onosproject.core.ApplicationId;
@@ -325,7 +326,9 @@
                 formatInstructs(sb, imm, IMM);
                 formatInstructs(sb, def, DEF);
 
-                addLabVal(sb, METERED, treatment.metered());
+                treatment.meters().forEach(meterInstruction ->
+                        addLabVal(sb, METERED, meterInstruction)
+                );
                 addLabVal(sb, TRANSITION, treatment.tableTransition());
                 addLabVal(sb, METADATA, treatment.writeMetadata());
 
@@ -445,9 +448,9 @@
         private ObjectNode jsonTreatment(FlowEntry flow) {
             ObjectNode treat = objectNode();
             TrafficTreatment treatment = flow.treatment();
-            List<Instruction> imm = treatment.immediate();
+            List<Instruction> imm = Lists.newArrayList(treatment.immediate());
             List<Instruction> def = treatment.deferred();
-            Instructions.MeterInstruction meter = treatment.metered();
+            Set<Instructions.MeterInstruction> meter = treatment.meters();
             Instructions.TableTypeTransition table = treatment.tableTransition();
             Instructions.MetadataInstruction meta = treatment.writeMetadata();
 
@@ -457,8 +460,8 @@
             if (!def.isEmpty()) {
                 treat.set(DEFER, jsonInstrList(def));
             }
-            if (meter != null) {
-                treat.put(METER, meter.toString());
+            if (!meter.isEmpty()) {
+                treat.set(METER, jsonInstrList(Lists.newArrayList(meter)));
             }
             if (table != null) {
                 treat.put(TABLE, table.toString());