[ovs-dev] [PATCH] ovs : Implementation to add meter in ovs flows

deepanshu.saxena30 at gmail.com deepanshu.saxena30 at gmail.com
Fri Jul 15 07:32:27 UTC 2016


From: Deepanshu Saxena <deepanshu.saxena1 at tcs.com>

This commit implements ovs meters in kernel space using the traffic
control (tc) module of Linux kernel. TC  is  used  to configure Traffic
Control features like Policing, Shaping etc. Ovs meters are analogous to
traffic control policing feature. The details from the meter command are
fetched and mapped to the corresponding fields of tc qdisc,class,filter
commands.

In this commit only the "ovs-ofctl add-meter" command is translated to
the respective commands of tc. In this only the drop meter band type is
implemented.

Tested the code using iperf3. Setup consist of ovs connected to VM using
tap interface port and another host via hardware interface.

Meter is a switch element that can measure and control the rate of packets. The
meter triggers a meter band if the packet rate or byte rate passing through
the meter exceeds a predefined threshold. If the meter band drops the
packet, it is called a Rate Limiter.

Signed-off-by: Deepanshu Saxena <deepanshu.saxena1 at tcs.com>
Co-authored-by : Jarno Rajahalme <jrajahalme at nicira.com>
---
 include/openvswitch/ofp-actions.h |   1 +
 lib/dpif-netdev.c                 |  35 +++++++++++++
 lib/dpif-netlink.c                |  36 ++++++++++++++
 lib/dpif-provider.h               |  16 ++++++
 lib/dpif.c                        |  38 ++++++++++++++
 lib/dpif.h                        |   8 +++
 ofproto/automake.mk               |   4 +-
 ofproto/meter_tc.c                |  74 ++++++++++++++++++++++++++++
 ofproto/meter_tc.h                |  38 ++++++++++++++
 ofproto/ofproto-dpif.c            |  21 +++++++-
 ofproto/ofproto.c                 | 101 +++++++++++++++++++++++---------------
 11 files changed, 329 insertions(+), 43 deletions(-)
 create mode 100644 ofproto/meter_tc.c
 create mode 100644 ofproto/meter_tc.h

diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h
index 0b8ccbb..9f2caa8 100644
--- a/include/openvswitch/ofp-actions.h
+++ b/include/openvswitch/ofp-actions.h
@@ -506,6 +506,7 @@ struct ofpact_metadata {
 struct ofpact_meter {
     struct ofpact ofpact;
     uint32_t meter_id;
+    uint32_t provider_meter_id;
 };
 
 /* OFPACT_WRITE_ACTIONS.
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index e0107b7..bc7bf08 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -79,6 +79,8 @@ DEFINE_STATIC_PER_THREAD_DATA(uint32_t, recirc_depth, 0)
 
 /* Configuration parameters. */
 enum { MAX_FLOWS = 65536 };     /* Maximum number of flows in flow table. */
+enum { MAX_METERS = 65536 };    /* Maximum number of meters. */
+enum { MAX_BANDS = 8 };         /* Maximum number of bands / meter. */
 
 /* Protects against changes to 'dp_netdevs'. */
 static struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;
@@ -170,6 +172,15 @@ static void dpcls_remove(struct dpcls *, struct dpcls_rule *);
 static bool dpcls_lookup(const struct dpcls *cls,
                          const struct netdev_flow_key keys[],
                          struct dpcls_rule **rules, size_t cnt);
+
+/* Set of supported meter flags */
+#define DP_SUPPORTED_METER_FLAGS_MASK \
+    (OFPMF13_STATS | OFPMF13_PKTPS | OFPMF13_KBPS | OFPMF13_BURST)
+
+/* Set of supported meter band types */
+#define DP_SUPPORTED_METER_BAND_TYPES           \
+    ( 1 << OFPMBT13_DROP )
+
 
 /* Datapath based on the network device interface from netdev.h.
  *
@@ -2908,6 +2919,28 @@ dp_netdev_disable_upcall(struct dp_netdev *dp)
     fat_rwlock_wrlock(&dp->upcall_rwlock);
 }
 
+/* Meters */
+static void
+dpif_netdev_meter_get_features(const struct dpif * dpif OVS_UNUSED,
+                               struct ofputil_meter_features *features)
+{
+    features->max_meters = MAX_METERS;
+    features->band_types = DP_SUPPORTED_METER_BAND_TYPES;
+    features->capabilities = DP_SUPPORTED_METER_FLAGS_MASK;
+    features->max_bands = MAX_BANDS;
+    features->max_color = 0;
+}
+
+static int
+dpif_netdev_meter_del(struct dpif *dpif OVS_UNUSED,
+                      ofproto_meter_id meter_id_ OVS_UNUSED,
+                      struct ofputil_meter_stats *stats OVS_UNUSED,
+                      uint16_t n_bands OVS_UNUSED)
+{
+    return EFBIG; /* meter_id out of range */
+}
+
+
 static void
 dpif_netdev_disable_upcall(struct dpif *dpif)
     OVS_NO_THREAD_SAFETY_ANALYSIS
@@ -4258,6 +4291,8 @@ const struct dpif_class dpif_netdev_class = {
     dpif_netdev_enable_upcall,
     dpif_netdev_disable_upcall,
     dpif_netdev_get_datapath_version,
+    dpif_netdev_meter_get_features,
+    dpif_netdev_meter_del,
     NULL,                       /* ct_dump_start */
     NULL,                       /* ct_dump_next */
     NULL,                       /* ct_dump_done */
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index e2bea23..c5feaf3 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -68,6 +68,19 @@ enum { MAX_PORTS = USHRT_MAX };
  * missing if we have old headers. */
 #define ETH_FLAG_LRO      (1 << 15)    /* LRO is enabled */
 
+/* Configuration parameters. */
+enum { MAX_FLOWS = 65536 };     /* Maximum number of flows in flow table. */
+enum { MAX_METERS = 65536 };    /* Maximum number of meters. */
+enum { MAX_BANDS = 8 };         /* Maximum number of bands / meter. */
+
+/* Set of supported meter flags */
+#define DP_SUPPORTED_METER_FLAGS_MASK \
+    (OFPMF13_STATS | OFPMF13_PKTPS | OFPMF13_KBPS | OFPMF13_BURST)
+
+/* Set of supported meter band types */
+#define DP_SUPPORTED_METER_BAND_TYPES           \
+    ( 1 << OFPMBT13_DROP )
+
 struct dpif_netlink_dp {
     /* Generic Netlink header. */
     uint8_t cmd;
@@ -2274,6 +2287,27 @@ dpif_netlink_get_datapath_version(void)
     return version_str;
 }
 
+/* Meters */
+static void
+dpif_netlink_meter_get_features(const struct dpif * dpif OVS_UNUSED,
+                                struct ofputil_meter_features *features)
+{
+    features->max_meters = MAX_METERS;
+    features->band_types = DP_SUPPORTED_METER_BAND_TYPES;
+    features->capabilities = DP_SUPPORTED_METER_FLAGS_MASK;
+    features->max_bands = MAX_BANDS;
+    features->max_color = 0;
+}
+
+static int
+dpif_netlink_meter_del(struct dpif *dpif OVS_UNUSED,
+                       ofproto_meter_id meter_id OVS_UNUSED,
+                       struct ofputil_meter_stats *stats OVS_UNUSED,
+                       uint16_t n_bands OVS_UNUSED)
+{
+    return EFBIG; /* meter_id out of range */
+}
+
 struct dpif_netlink_ct_dump_state {
     struct ct_dpif_dump_state up;
     struct nl_ct_dump_state *nl_ct_dump;
@@ -2375,6 +2409,8 @@ const struct dpif_class dpif_netlink_class = {
     NULL,                       /* enable_upcall */
     NULL,                       /* disable_upcall */
     dpif_netlink_get_datapath_version, /* get_datapath_version */
+    dpif_netlink_meter_get_features,
+    dpif_netlink_meter_del,
     dpif_netlink_ct_dump_start,
     dpif_netlink_ct_dump_next,
     dpif_netlink_ct_dump_done,
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index 25f4280..080d596 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -25,6 +25,7 @@
 #include "openflow/openflow.h"
 #include "dpif.h"
 #include "util.h"
+#include "openvswitch/ofp-util.h"
 
 #ifdef  __cplusplus
 extern "C" {
@@ -393,6 +394,21 @@ struct dpif_class {
      * returned.  */
     char *(*get_datapath_version)(void);
 
+    /* Meters */
+
+    /* Queries 'dpif' for supported meter features.
+     * NULL pointer means no meter features are supported. */
+    void (*meter_get_features)(const struct dpif *,
+                               struct ofputil_meter_features *);
+
+    /* Removes meter 'meter_id' from 'dpif'. Stores meter and band statistics
+     * (for maximum of 'n_bands', returning the number of band stats returned
+     * in 'stats->n_bands' if successful.  'stats' may be passed in as NULL if
+     * no stats are needed, in which case 'n_bands' must be passed in as
+     * zero. */
+    int (*meter_del)(struct dpif *, ofproto_meter_id meter_id,
+                     struct ofputil_meter_stats *, uint16_t n_bands);
+
     /* Conntrack entry dumping interface.
      *
      * These functions are used by ct-dpif.c to provide a datapath-agnostic
diff --git a/lib/dpif.c b/lib/dpif.c
index 5f1be41..7d8bb9b 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -63,6 +63,7 @@ COVERAGE_DEFINE(dpif_flow_del);
 COVERAGE_DEFINE(dpif_execute);
 COVERAGE_DEFINE(dpif_purge);
 COVERAGE_DEFINE(dpif_execute_with_help);
+COVERAGE_DEFINE(dpif_meter_del);
 
 static const struct dpif_class *base_dpif_classes[] = {
 #if defined(__linux__) || defined(_WIN32)
@@ -1743,3 +1744,40 @@ dpif_supports_tnl_push_pop(const struct dpif *dpif)
 {
     return dpif_is_netdev(dpif);
 }
+
+/* Meters */
+void
+dpif_meter_get_features(const struct dpif *dpif,
+                        struct ofputil_meter_features *features)
+{
+    memset(features, 0, sizeof *features);
+    if (dpif->dpif_class->meter_get_features) {
+        dpif->dpif_class->meter_get_features(dpif, features);
+    }
+}
+
+int
+dpif_meter_del(struct dpif *dpif, ofproto_meter_id meter_id,
+               struct ofputil_meter_stats *stats, uint16_t n_bands)
+{
+    int error;
+
+    COVERAGE_INC(dpif_meter_del);
+
+    error = dpif->dpif_class->meter_del(dpif, meter_id, stats, n_bands);
+    if (!error) {
+        VLOG_DBG_RL(&dpmsg_rl, "%s: DPIF meter %"PRIu32" deleted",
+                    dpif_name(dpif), meter_id.uint32);
+    } else {
+        VLOG_WARN_RL(&error_rl,
+                     "%s: failed to delete DPIF meter %"PRIu32": %s",
+                     dpif_name(dpif), meter_id.uint32, ovs_strerror(error));
+        if (stats) {
+            stats->packet_in_count = ~0;
+            stats->byte_in_count = ~0;
+            stats->n_bands = 0;
+        }
+    }
+    return error;
+}
+
diff --git a/lib/dpif.h b/lib/dpif.h
index 981868c..8835fcf 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -394,6 +394,7 @@
 #include "ovs-numa.h"
 #include "packets.h"
 #include "util.h"
+#include "openvswitch/ofp-util.h"
 
 #ifdef  __cplusplus
 extern "C" {
@@ -847,6 +848,13 @@ void dpif_enable_upcall(struct dpif *);
 void dpif_disable_upcall(struct dpif *);
 
 void dpif_print_packet(struct dpif *, struct dpif_upcall *);
+
+/* Meters. */
+void dpif_meter_get_features(const struct dpif *,
+                             struct ofputil_meter_features *);
+int dpif_meter_del(struct dpif *, ofproto_meter_id meter_id,
+                   struct ofputil_meter_stats *, uint16_t n_bands);
+
 
 /* Miscellaneous. */
 
diff --git a/ofproto/automake.mk b/ofproto/automake.mk
index 7486f2b..906226f 100644
--- a/ofproto/automake.mk
+++ b/ofproto/automake.mk
@@ -48,7 +48,9 @@ ofproto_libofproto_la_SOURCES = \
 	ofproto/tunnel.c \
 	ofproto/tunnel.h \
 	ofproto/bundles.c \
-	ofproto/bundles.h
+	ofproto/bundles.h \
+	ofproto/meter_tc.c \
+	ofproto/meter_tc.h
 
 ofproto_libofproto_la_CPPFLAGS = $(AM_CPPFLAGS)
 ofproto_libofproto_la_CFLAGS = $(AM_CFLAGS)
diff --git a/ofproto/meter_tc.c b/ofproto/meter_tc.c
new file mode 100644
index 0000000..fc7fa0b
--- /dev/null
+++ b/ofproto/meter_tc.c
@@ -0,0 +1,74 @@
+#include <config.h>
+#include "meter_tc.h"
+
+VLOG_DEFINE_THIS_MODULE(meter_tc);
+
+enum ofperr flow_mod_to_tc(struct ofproto *ofproto,
+                           struct ofputil_flow_mod ofm) {
+    FILE *fp;
+    ovs_be32 nw_src,nw_dst;
+    struct ofpact *a;
+    struct ofpact_meter *m_act;
+    struct ofport *ofport;
+    struct meter *meter;
+    uint32_t id,rate,rate_in_bytesps,burst_size,default_id;
+    char buffer[1024];
+    ofp_port_t port=0;
+    default_id=65535;
+    id=0;
+    struct ds nw_src_string = DS_EMPTY_INITIALIZER;
+    struct ds nw_dst_string = DS_EMPTY_INITIALIZER;
+    nw_src = ofm.match.flow.nw_src;
+    nw_dst = ofm.match.flow.nw_dst;
+    ds_put_format(&nw_src_string, IP_FMT, IP_ARGS(nw_src));
+    ds_put_format(&nw_dst_string, IP_FMT, IP_ARGS(nw_dst));
+    VLOG_INFO("Source IP : %s , Destination IP : %s",nw_src_string.string,
+              nw_dst_string.string);
+    OFPACT_FOR_EACH_FLATTENED (a, ofm.ofpacts, ofm.ofpacts_len) {
+        if (a->type == OFPACT_METER) {
+            m_act=ofpact_get_METER(a);
+            id=m_act->meter_id;
+        }
+        if(a->type == OFPACT_OUTPUT) {
+            port=ofpact_get_OUTPUT(a)->port;	
+        }
+    }
+    VLOG_INFO("Output Port Number : %d",port);
+    ofport=ofproto_get_port(ofproto,port);
+    if(ofport==NULL) {
+        VLOG_INFO("The port numbers defined in the flow donot correspond to "
+                  "any datapath port. try using ovs-ofctl show <br-name> to "
+                  "get the list of ports. Add ports to the bridge first");
+        return OFPERR_OFPBRC_BAD_PORT;
+    }
+    VLOG_INFO("Output Port Name : %s",ofport->pp.name);
+    VLOG_INFO("Meter id : %d",id);
+    meter = ofproto->meters[id];
+    rate=meter->bands->rate;
+    rate_in_bytesps=(uint32_t)((float)(meter->bands->rate/8)*1000);
+    burst_size=meter->bands->burst_size;
+    VLOG_INFO("Rate in kbitsps : %d, burst size in kbits  %d",rate,
+              burst_size);
+    snprintf(buffer,sizeof(buffer),"tc qdisc add dev %s root " 
+             "handle 1: htb default %x",ofport->pp.name,default_id);
+    fp=popen(buffer,"r");
+    snprintf(buffer,sizeof(buffer),"tc class add dev %s parent 1:0 " 
+             "classid 1:%x htb rate 20kbps ceil 100kbps prio 2",
+             ofport->pp.name,default_id);
+    fp = popen(buffer,"r");
+    pclose(fp);
+    snprintf(buffer,sizeof(buffer),"tc class add dev %s parent 1:0 classid " 
+             "1:%x htb rate %dkbit ceil %dkbit prio 1 mtu %d000 ",
+             ofport->pp.name,id,rate,rate,burst_size);
+    fp = popen(buffer,"r");
+    pclose(fp);
+    snprintf(buffer,sizeof(buffer),"tc filter add dev %s protocol ip parent " 
+             "1: prio 1 u32 match ip src %s match ip dst %s flowid 1:%x " 
+             "police rate %dbps burst %d000 mpu 0 conform-exceed drop/ok",
+             ofport->pp.name,nw_src_string.string,nw_dst_string.string,
+             id,rate_in_bytesps,burst_size);
+    fp = popen(buffer,"r");
+    VLOG_INFO("Meter attached successfully to the flow");
+    pclose(fp);
+    return 0;
+}
diff --git a/ofproto/meter_tc.h b/ofproto/meter_tc.h
new file mode 100644
index 0000000..7516b2c
--- /dev/null
+++ b/ofproto/meter_tc.h
@@ -0,0 +1,38 @@
+#ifndef METER_TC_H
+#define METER_TC_H
+#include<stdlib.h>
+#include<stdio.h>
+#include<string.h>
+#include "openvswitch/ofp-util.h"
+#include "include/openflow/openflow-1.3.h"
+#include "include/openvswitch/vlog.h"
+#include <config.h>
+#include "include/openvswitch/dynamic-string.h"
+#include "linux/pkt_sched.h"
+#include "openvswitch/packets.h"
+#include "openvswitch/match.h"
+#include "openvswitch/ofp-actions.h"
+#include "ofproto/ofproto-provider.h"
+#include "include/openvswitch/types.h"
+
+/* Meters implementation.
+ *
+ * Meter table entry, indexed by the OpenFlow meter_id.
+ * 'created' is used to compute the duration for meter stats.
+ * 'list rules' is needed so that we can delete the dependent rules when the
+ * meter table entry is deleted.
+ * 'provider_meter_id' is for the provider's private use.
+ */
+struct meter {
+    long long int created;      /* Time created. */
+    struct ovs_list rules;      /* List of "struct rule_dpif"s. */
+    ofproto_meter_id provider_meter_id;
+    uint16_t flags;             /* Meter flags. */
+    uint16_t n_bands;           /* Number of meter bands. */
+    struct ofputil_meter_band *bands;
+};
+
+/* Translates the add-flow command containing meter to the respective
+ * traffic control command. */
+enum ofperr flow_mod_to_tc(struct ofproto *, struct ofputil_flow_mod);
+#endif
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index ce9383a..db51e09 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -5575,6 +5575,23 @@ ofproto_dpif_delete_internal_flow(struct ofproto_dpif *ofproto,
     return 0;
 }
 
+static void
+meter_get_features(const struct ofproto *ofproto_,
+                   struct ofputil_meter_features *features)
+{
+    const struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+
+    dpif_meter_get_features(ofproto->backer->dpif, features);
+}      
+
+static void
+meter_del(struct ofproto *ofproto_, ofproto_meter_id meter_id)
+{
+    struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+
+    dpif_meter_del(ofproto->backer->dpif, meter_id, NULL, 0);
+}
+
 const struct uuid *
 ofproto_dpif_get_uuid(const struct ofproto_dpif *ofproto)
 {
@@ -5667,10 +5684,10 @@ const struct ofproto_class ofproto_dpif_class = {
     set_mac_table_config,
     set_mcast_snooping,
     set_mcast_snooping_port,
-    NULL,                       /* meter_get_features */
+    meter_get_features,         /* meter_get_features */
     NULL,                       /* meter_set */
     NULL,                       /* meter_get */
-    NULL,                       /* meter_del */
+    meter_del,                  /* meter_del */
     group_alloc,                /* group_alloc */
     group_construct,            /* group_construct */
     group_destruct,             /* group_destruct */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 5f84aa1..3b43d74 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -62,6 +62,7 @@
 #include "tun-metadata.h"
 #include "unaligned.h"
 #include "unixctl.h"
+#include "ofproto/meter_tc.h"
 
 VLOG_DEFINE_THIS_MODULE(ofproto);
 
@@ -2957,8 +2958,8 @@ ofproto_group_unref(struct ofgroup *group)
     }
 }
 
-static uint32_t get_provider_meter_id(const struct ofproto *,
-                                      uint32_t of_meter_id);
+static bool ofproto_fix_meter_action(const struct ofproto *,
+                                     struct ofpact_meter *);
 
 /* Creates and returns a new 'struct rule_actions', whose actions are a copy
  * of from the 'ofpacts_len' bytes of 'ofpacts'. */
@@ -3401,14 +3402,13 @@ ofproto_check_ofpacts(struct ofproto *ofproto,
                       const struct ofpact ofpacts[], size_t ofpacts_len)
 {
     const struct ofpact *a;
-    uint32_t mid;
-
-    mid = ofpacts_get_meter(ofpacts, ofpacts_len);
-    if (mid && get_provider_meter_id(ofproto, mid) == UINT32_MAX) {
-        return OFPERR_OFPMMFC_INVALID_METER;
-    }
 
     OFPACT_FOR_EACH_FLATTENED (a, ofpacts, ofpacts_len) {
+        if (a->type == OFPACT_METER &&
+            !ofproto_fix_meter_action(ofproto, ofpact_get_METER(a))) {
+            return OFPERR_OFPMMFC_INVALID_METER;
+        }
+
         if (a->type == OFPACT_GROUP
             && !ofproto_group_exists(ofproto, ofpact_get_GROUP(a)->group_id)) {
             return OFPERR_OFPBAC_BAD_OUT_GROUP;
@@ -4673,6 +4673,32 @@ add_flow_start(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
     struct cls_conjunction *conjs;
     size_t n_conjs;
     enum ofperr error;
+    uint8_t size_=0;
+
+    /*
+     * If the actions in add-flow contain meter then flow_mod_to_tc is called.
+     * OFPACT_METER is the enum for meter as action in add-flow command.
+     */
+    if(ofm->fm.ofpacts->type == OFPACT_METER) {
+        error = flow_mod_to_tc(ofproto,ofm->fm);
+        if(error) {
+            return error;
+        }
+        /*
+         * ofpacts_len is the total length of all actions in the flow.  
+         * ofpacts->len contain the length of particular action.  The meters
+         * are not set in datapath, so when flow tries to fetch the meter id
+         * from the datapath, it gives error at runtime.  To skip 
+         * meter, and move the pointer to the next action in ofpacts the
+         * following code is written.  Skipped meter action here 
+         * because this work is done by flow_mod_to_tc().
+         */
+        ofm->fm.ofpacts_len = ofm->fm.ofpacts_len - ofm->fm.ofpacts->len;
+        ofm->fm.ofpacts[0].type = 0;
+        ofm->fm.ofpacts[0].raw = 0;
+        size_ = ofm->fm.ofpacts[0].len / sizeof(ofm->fm.ofpacts[0]);
+        ofm->fm.ofpacts = &ofm->fm.ofpacts[size_];
+    }
 
     if (!check_table_id(ofproto, fm->table_id)) {
         error = OFPERR_OFPBRC_BAD_TABLE_ID;
@@ -5821,38 +5847,28 @@ handle_flow_monitor_cancel(struct ofconn *ofconn, const struct ofp_header *oh)
     return error;
 }
 
-/* Meters implementation.
- *
- * Meter table entry, indexed by the OpenFlow meter_id.
- * 'created' is used to compute the duration for meter stats.
- * 'list rules' is needed so that we can delete the dependent rules when the
- * meter table entry is deleted.
- * 'provider_meter_id' is for the provider's private use.
- */
-struct meter {
-    long long int created;      /* Time created. */
-    struct ovs_list rules;      /* List of "struct rule_dpif"s. */
-    ofproto_meter_id provider_meter_id;
-    uint16_t flags;             /* Meter flags. */
-    uint16_t n_bands;           /* Number of meter bands. */
-    struct ofputil_meter_band *bands;
-};
-
 /*
- * This is used in instruction validation at flow set-up time,
- * as flows may not use non-existing meters.
- * Return value of UINT32_MAX signifies an invalid meter.
+ * This is used in instruction validation at flow set-up time, to map
+ * the OpenFlow meter ID to the corresponding datapath provider meter
+ * ID.  If either does not exist, returns false.  Otherwise updates
+ * the meter action and returns true. 
  */
-static uint32_t
-get_provider_meter_id(const struct ofproto *ofproto, uint32_t of_meter_id)
+static bool
+ofproto_fix_meter_action(const struct ofproto *ofproto,
+                         struct ofpact_meter *ma)
 {
-    if (of_meter_id && of_meter_id <= ofproto->meter_features.max_meters) {
-        const struct meter *meter = ofproto->meters[of_meter_id];
-        if (meter) {
-            return meter->provider_meter_id.uint32;
-        }
+    if (ma->meter_id && ma->meter_id <= ofproto->meter_features.max_meters) {
+        const struct meter *meter = ofproto->meters[ma->meter_id];
+
+        if (meter && meter->provider_meter_id.uint32 != UINT32_MAX) {
+            /* Update the action with the provider's meter ID, so that we
+             * do not need any synchronization between ofproto_dpif_xlate
+             * and ofproto for meter table access. */
+            ma->provider_meter_id = meter->provider_meter_id.uint32;
+            return true;
+         }
     }
-    return UINT32_MAX;
+    return false;
 }
 
 /* Finds the meter invoked by 'rule''s actions and adds 'rule' to the meter's
@@ -5914,16 +5930,21 @@ meter_delete(struct ofproto *ofproto, uint32_t first, uint32_t last)
 static enum ofperr
 handle_add_meter(struct ofproto *ofproto, struct ofputil_meter_mod *mm)
 {
-    ofproto_meter_id provider_meter_id = { UINT32_MAX };
+    ofproto_meter_id provider_meter_id = {mm->meter.meter_id};
     struct meter **meterp = &ofproto->meters[mm->meter.meter_id];
     enum ofperr error;
 
     if (*meterp) {
         return OFPERR_OFPMMFC_METER_EXISTS;
     }
-
-    error = ofproto->ofproto_class->meter_set(ofproto, &provider_meter_id,
-                                              &mm->meter);
+    error=0;
+    /* 
+     * This line is deleted because meter_set() is declared in 
+     * ofproto/ofproto-provider.h but it doesnot have implementaion 
+     * in ofproto/ofproto-dpif.c in ofproto_dpif_class.  This function
+     * will basically set meter in the datapath.  To bypass this have
+     * deleted the line.  
+     */
     if (!error) {
         ovs_assert(provider_meter_id.uint32 != UINT32_MAX);
         *meterp = meter_create(&mm->meter, provider_meter_id);
-- 
1.9.1




More information about the dev mailing list