Re: [net-next v2 3/4] openvswitch: Add meter infrastructure

2017-11-03 Thread Pravin Shelar
On Thu, Nov 2, 2017 at 7:43 PM, Andy Zhou  wrote:
> On Thu, Nov 2, 2017 at 5:07 AM, Pravin Shelar  wrote:
>> On Thu, Nov 2, 2017 at 3:07 AM, Andy Zhou  wrote:
>>> On Fri, Oct 20, 2017 at 8:32 PM, Pravin Shelar  wrote:
 On Thu, Oct 19, 2017 at 5:58 PM, Andy Zhou  wrote:
>
> On Thu, Oct 19, 2017 at 02:47 Pravin Shelar  wrote:
>>
>> On Tue, Oct 17, 2017 at 12:36 AM, Andy Zhou  wrote:
>> > OVS kernel datapath so far does not support Openflow meter action.
>> > This is the first stab at adding kernel datapath meter support.
>> > This implementation supports only drop band type.
>> >
>> > Signed-off-by: Andy Zhou 
>> > ---
>> >  net/openvswitch/Makefile   |   1 +
>> >  net/openvswitch/datapath.c |  14 +-
>> >  net/openvswitch/datapath.h |   3 +
>> >  net/openvswitch/meter.c| 604
>> > +
>> >  net/openvswitch/meter.h|  54 
>> >  5 files changed, 674 insertions(+), 2 deletions(-)
>> >  create mode 100644 net/openvswitch/meter.c
>> >  create mode 100644 net/openvswitch/meter.h
>> >
>> This patch mostly looks good. I have one comment below.
>>
>> > +static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info
>> > *info)
>> > +{
>> > +   struct nlattr **a = info->attrs;
>> > +   struct dp_meter *meter, *old_meter;
>> > +   struct sk_buff *reply;
>> > +   struct ovs_header *ovs_reply_header;
>> > +   struct ovs_header *ovs_header = info->userhdr;
>> > +   struct datapath *dp;
>> > +   int err;
>> > +   u32 meter_id;
>> > +   bool failed;
>> > +
>> > +   meter = dp_meter_create(a);
>> > +   if (IS_ERR_OR_NULL(meter))
>> > +   return PTR_ERR(meter);
>> > +
>> > +   reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
>> > + _reply_header);
>> > +   if (IS_ERR(reply)) {
>> > +   err = PTR_ERR(reply);
>> > +   goto exit_free_meter;
>> > +   }
>> > +
>> > +   ovs_lock();
>> > +   dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
>> > +   if (!dp) {
>> > +   err = -ENODEV;
>> > +   goto exit_unlock;
>> > +   }
>> > +
>> > +   if (!a[OVS_METER_ATTR_ID]) {
>> > +   err = -ENODEV;
>> > +   goto exit_unlock;
>> > +   }
>> > +
>> > +   meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
>> > +
>> > +   /* Cannot fail after this. */
>> > +   old_meter = lookup_meter(dp, meter_id);
>> I do not see RCU read lock taken here. This is not correctness issue
>> but it could cause RCU checker to spit out warning message. You could
>> do same trick that is done in get_dp() to avoid this issue.
>
> O.K.
>>
>>
>>
>> Can you also test the code with rcu sparse check config option enabled?
>
>
> Do you mean to sparse compile with CONFIG_PROVE_LOCKING and
> CONFIG_DENUG_OBJECTS_RCU_HEAD?

 You could use all following options simultaneously:
 CONFIG_PREEMPT
 CONFIG_DEBUG_PREEMPT
 CONFIG_DEBUG_SPINLOCK
 CONFIG_DEBUG_ATOMIC_SLEEP
 CONFIG_PROVE_RCU
 CONFIG_DEBUG_OBJECTS_RCU_HEAD
>>>
>>> Thanks, I turned on those flags but did not get any error message. Do you
>>> mind share the RCU checker message?
>>
>> There would be assert failure and stack trace. so it would be pretty
>> obvious in kernel log messages.
>> Let me know if you do not see any stack trace while running meter
>> create, delete and execute.
>
> No I did not see them.
ok, Can you send out patch against latest net-next?


Re: [net-next v2 3/4] openvswitch: Add meter infrastructure

2017-11-02 Thread Andy Zhou
On Thu, Nov 2, 2017 at 5:07 AM, Pravin Shelar  wrote:
> On Thu, Nov 2, 2017 at 3:07 AM, Andy Zhou  wrote:
>> On Fri, Oct 20, 2017 at 8:32 PM, Pravin Shelar  wrote:
>>> On Thu, Oct 19, 2017 at 5:58 PM, Andy Zhou  wrote:

 On Thu, Oct 19, 2017 at 02:47 Pravin Shelar  wrote:
>
> On Tue, Oct 17, 2017 at 12:36 AM, Andy Zhou  wrote:
> > OVS kernel datapath so far does not support Openflow meter action.
> > This is the first stab at adding kernel datapath meter support.
> > This implementation supports only drop band type.
> >
> > Signed-off-by: Andy Zhou 
> > ---
> >  net/openvswitch/Makefile   |   1 +
> >  net/openvswitch/datapath.c |  14 +-
> >  net/openvswitch/datapath.h |   3 +
> >  net/openvswitch/meter.c| 604
> > +
> >  net/openvswitch/meter.h|  54 
> >  5 files changed, 674 insertions(+), 2 deletions(-)
> >  create mode 100644 net/openvswitch/meter.c
> >  create mode 100644 net/openvswitch/meter.h
> >
> This patch mostly looks good. I have one comment below.
>
> > +static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info
> > *info)
> > +{
> > +   struct nlattr **a = info->attrs;
> > +   struct dp_meter *meter, *old_meter;
> > +   struct sk_buff *reply;
> > +   struct ovs_header *ovs_reply_header;
> > +   struct ovs_header *ovs_header = info->userhdr;
> > +   struct datapath *dp;
> > +   int err;
> > +   u32 meter_id;
> > +   bool failed;
> > +
> > +   meter = dp_meter_create(a);
> > +   if (IS_ERR_OR_NULL(meter))
> > +   return PTR_ERR(meter);
> > +
> > +   reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
> > + _reply_header);
> > +   if (IS_ERR(reply)) {
> > +   err = PTR_ERR(reply);
> > +   goto exit_free_meter;
> > +   }
> > +
> > +   ovs_lock();
> > +   dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
> > +   if (!dp) {
> > +   err = -ENODEV;
> > +   goto exit_unlock;
> > +   }
> > +
> > +   if (!a[OVS_METER_ATTR_ID]) {
> > +   err = -ENODEV;
> > +   goto exit_unlock;
> > +   }
> > +
> > +   meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
> > +
> > +   /* Cannot fail after this. */
> > +   old_meter = lookup_meter(dp, meter_id);
> I do not see RCU read lock taken here. This is not correctness issue
> but it could cause RCU checker to spit out warning message. You could
> do same trick that is done in get_dp() to avoid this issue.

 O.K.
>
>
>
> Can you also test the code with rcu sparse check config option enabled?


 Do you mean to sparse compile with CONFIG_PROVE_LOCKING and
 CONFIG_DENUG_OBJECTS_RCU_HEAD?
>>>
>>> You could use all following options simultaneously:
>>> CONFIG_PREEMPT
>>> CONFIG_DEBUG_PREEMPT
>>> CONFIG_DEBUG_SPINLOCK
>>> CONFIG_DEBUG_ATOMIC_SLEEP
>>> CONFIG_PROVE_RCU
>>> CONFIG_DEBUG_OBJECTS_RCU_HEAD
>>
>> Thanks, I turned on those flags but did not get any error message. Do you
>> mind share the RCU checker message?
>
> There would be assert failure and stack trace. so it would be pretty
> obvious in kernel log messages.
> Let me know if you do not see any stack trace while running meter
> create, delete and execute.

No I did not see them.


Re: [net-next v2 3/4] openvswitch: Add meter infrastructure

2017-11-02 Thread Pravin Shelar
On Thu, Nov 2, 2017 at 3:07 AM, Andy Zhou  wrote:
> On Fri, Oct 20, 2017 at 8:32 PM, Pravin Shelar  wrote:
>> On Thu, Oct 19, 2017 at 5:58 PM, Andy Zhou  wrote:
>>>
>>> On Thu, Oct 19, 2017 at 02:47 Pravin Shelar  wrote:

 On Tue, Oct 17, 2017 at 12:36 AM, Andy Zhou  wrote:
 > OVS kernel datapath so far does not support Openflow meter action.
 > This is the first stab at adding kernel datapath meter support.
 > This implementation supports only drop band type.
 >
 > Signed-off-by: Andy Zhou 
 > ---
 >  net/openvswitch/Makefile   |   1 +
 >  net/openvswitch/datapath.c |  14 +-
 >  net/openvswitch/datapath.h |   3 +
 >  net/openvswitch/meter.c| 604
 > +
 >  net/openvswitch/meter.h|  54 
 >  5 files changed, 674 insertions(+), 2 deletions(-)
 >  create mode 100644 net/openvswitch/meter.c
 >  create mode 100644 net/openvswitch/meter.h
 >
 This patch mostly looks good. I have one comment below.

 > +static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info
 > *info)
 > +{
 > +   struct nlattr **a = info->attrs;
 > +   struct dp_meter *meter, *old_meter;
 > +   struct sk_buff *reply;
 > +   struct ovs_header *ovs_reply_header;
 > +   struct ovs_header *ovs_header = info->userhdr;
 > +   struct datapath *dp;
 > +   int err;
 > +   u32 meter_id;
 > +   bool failed;
 > +
 > +   meter = dp_meter_create(a);
 > +   if (IS_ERR_OR_NULL(meter))
 > +   return PTR_ERR(meter);
 > +
 > +   reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
 > + _reply_header);
 > +   if (IS_ERR(reply)) {
 > +   err = PTR_ERR(reply);
 > +   goto exit_free_meter;
 > +   }
 > +
 > +   ovs_lock();
 > +   dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
 > +   if (!dp) {
 > +   err = -ENODEV;
 > +   goto exit_unlock;
 > +   }
 > +
 > +   if (!a[OVS_METER_ATTR_ID]) {
 > +   err = -ENODEV;
 > +   goto exit_unlock;
 > +   }
 > +
 > +   meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
 > +
 > +   /* Cannot fail after this. */
 > +   old_meter = lookup_meter(dp, meter_id);
 I do not see RCU read lock taken here. This is not correctness issue
 but it could cause RCU checker to spit out warning message. You could
 do same trick that is done in get_dp() to avoid this issue.
>>>
>>> O.K.



 Can you also test the code with rcu sparse check config option enabled?
>>>
>>>
>>> Do you mean to sparse compile with CONFIG_PROVE_LOCKING and
>>> CONFIG_DENUG_OBJECTS_RCU_HEAD?
>>
>> You could use all following options simultaneously:
>> CONFIG_PREEMPT
>> CONFIG_DEBUG_PREEMPT
>> CONFIG_DEBUG_SPINLOCK
>> CONFIG_DEBUG_ATOMIC_SLEEP
>> CONFIG_PROVE_RCU
>> CONFIG_DEBUG_OBJECTS_RCU_HEAD
>
> Thanks, I turned on those flags but did not get any error message. Do you
> mind share the RCU checker message?

There would be assert failure and stack trace. so it would be pretty
obvious in kernel log messages.
Let me know if you do not see any stack trace while running meter
create, delete and execute.


Re: [net-next v2 3/4] openvswitch: Add meter infrastructure

2017-11-02 Thread Andy Zhou
On Fri, Oct 20, 2017 at 8:32 PM, Pravin Shelar  wrote:
> On Thu, Oct 19, 2017 at 5:58 PM, Andy Zhou  wrote:
>>
>> On Thu, Oct 19, 2017 at 02:47 Pravin Shelar  wrote:
>>>
>>> On Tue, Oct 17, 2017 at 12:36 AM, Andy Zhou  wrote:
>>> > OVS kernel datapath so far does not support Openflow meter action.
>>> > This is the first stab at adding kernel datapath meter support.
>>> > This implementation supports only drop band type.
>>> >
>>> > Signed-off-by: Andy Zhou 
>>> > ---
>>> >  net/openvswitch/Makefile   |   1 +
>>> >  net/openvswitch/datapath.c |  14 +-
>>> >  net/openvswitch/datapath.h |   3 +
>>> >  net/openvswitch/meter.c| 604
>>> > +
>>> >  net/openvswitch/meter.h|  54 
>>> >  5 files changed, 674 insertions(+), 2 deletions(-)
>>> >  create mode 100644 net/openvswitch/meter.c
>>> >  create mode 100644 net/openvswitch/meter.h
>>> >
>>> This patch mostly looks good. I have one comment below.
>>>
>>> > +static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info
>>> > *info)
>>> > +{
>>> > +   struct nlattr **a = info->attrs;
>>> > +   struct dp_meter *meter, *old_meter;
>>> > +   struct sk_buff *reply;
>>> > +   struct ovs_header *ovs_reply_header;
>>> > +   struct ovs_header *ovs_header = info->userhdr;
>>> > +   struct datapath *dp;
>>> > +   int err;
>>> > +   u32 meter_id;
>>> > +   bool failed;
>>> > +
>>> > +   meter = dp_meter_create(a);
>>> > +   if (IS_ERR_OR_NULL(meter))
>>> > +   return PTR_ERR(meter);
>>> > +
>>> > +   reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
>>> > + _reply_header);
>>> > +   if (IS_ERR(reply)) {
>>> > +   err = PTR_ERR(reply);
>>> > +   goto exit_free_meter;
>>> > +   }
>>> > +
>>> > +   ovs_lock();
>>> > +   dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
>>> > +   if (!dp) {
>>> > +   err = -ENODEV;
>>> > +   goto exit_unlock;
>>> > +   }
>>> > +
>>> > +   if (!a[OVS_METER_ATTR_ID]) {
>>> > +   err = -ENODEV;
>>> > +   goto exit_unlock;
>>> > +   }
>>> > +
>>> > +   meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
>>> > +
>>> > +   /* Cannot fail after this. */
>>> > +   old_meter = lookup_meter(dp, meter_id);
>>> I do not see RCU read lock taken here. This is not correctness issue
>>> but it could cause RCU checker to spit out warning message. You could
>>> do same trick that is done in get_dp() to avoid this issue.
>>
>> O.K.
>>>
>>>
>>>
>>> Can you also test the code with rcu sparse check config option enabled?
>>
>>
>> Do you mean to sparse compile with CONFIG_PROVE_LOCKING and
>> CONFIG_DENUG_OBJECTS_RCU_HEAD?
>
> You could use all following options simultaneously:
> CONFIG_PREEMPT
> CONFIG_DEBUG_PREEMPT
> CONFIG_DEBUG_SPINLOCK
> CONFIG_DEBUG_ATOMIC_SLEEP
> CONFIG_PROVE_RCU
> CONFIG_DEBUG_OBJECTS_RCU_HEAD

Thanks, I turned on those flags but did not get any error message. Do you
mind share the RCU checker message?


Re: [net-next v2 3/4] openvswitch: Add meter infrastructure

2017-10-20 Thread Pravin Shelar
On Thu, Oct 19, 2017 at 5:58 PM, Andy Zhou  wrote:
>
> On Thu, Oct 19, 2017 at 02:47 Pravin Shelar  wrote:
>>
>> On Tue, Oct 17, 2017 at 12:36 AM, Andy Zhou  wrote:
>> > OVS kernel datapath so far does not support Openflow meter action.
>> > This is the first stab at adding kernel datapath meter support.
>> > This implementation supports only drop band type.
>> >
>> > Signed-off-by: Andy Zhou 
>> > ---
>> >  net/openvswitch/Makefile   |   1 +
>> >  net/openvswitch/datapath.c |  14 +-
>> >  net/openvswitch/datapath.h |   3 +
>> >  net/openvswitch/meter.c| 604
>> > +
>> >  net/openvswitch/meter.h|  54 
>> >  5 files changed, 674 insertions(+), 2 deletions(-)
>> >  create mode 100644 net/openvswitch/meter.c
>> >  create mode 100644 net/openvswitch/meter.h
>> >
>> This patch mostly looks good. I have one comment below.
>>
>> > +static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info
>> > *info)
>> > +{
>> > +   struct nlattr **a = info->attrs;
>> > +   struct dp_meter *meter, *old_meter;
>> > +   struct sk_buff *reply;
>> > +   struct ovs_header *ovs_reply_header;
>> > +   struct ovs_header *ovs_header = info->userhdr;
>> > +   struct datapath *dp;
>> > +   int err;
>> > +   u32 meter_id;
>> > +   bool failed;
>> > +
>> > +   meter = dp_meter_create(a);
>> > +   if (IS_ERR_OR_NULL(meter))
>> > +   return PTR_ERR(meter);
>> > +
>> > +   reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
>> > + _reply_header);
>> > +   if (IS_ERR(reply)) {
>> > +   err = PTR_ERR(reply);
>> > +   goto exit_free_meter;
>> > +   }
>> > +
>> > +   ovs_lock();
>> > +   dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
>> > +   if (!dp) {
>> > +   err = -ENODEV;
>> > +   goto exit_unlock;
>> > +   }
>> > +
>> > +   if (!a[OVS_METER_ATTR_ID]) {
>> > +   err = -ENODEV;
>> > +   goto exit_unlock;
>> > +   }
>> > +
>> > +   meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
>> > +
>> > +   /* Cannot fail after this. */
>> > +   old_meter = lookup_meter(dp, meter_id);
>> I do not see RCU read lock taken here. This is not correctness issue
>> but it could cause RCU checker to spit out warning message. You could
>> do same trick that is done in get_dp() to avoid this issue.
>
> O.K.
>>
>>
>>
>> Can you also test the code with rcu sparse check config option enabled?
>
>
> Do you mean to sparse compile with CONFIG_PROVE_LOCKING and
> CONFIG_DENUG_OBJECTS_RCU_HEAD?

You could use all following options simultaneously:
CONFIG_PREEMPT
CONFIG_DEBUG_PREEMPT
CONFIG_DEBUG_SPINLOCK
CONFIG_DEBUG_ATOMIC_SLEEP
CONFIG_PROVE_RCU
CONFIG_DEBUG_OBJECTS_RCU_HEAD

Thanks,
Pravin.


Re: [net-next v2 3/4] openvswitch: Add meter infrastructure

2017-10-18 Thread Pravin Shelar
On Tue, Oct 17, 2017 at 12:36 AM, Andy Zhou  wrote:
> OVS kernel datapath so far does not support Openflow meter action.
> This is the first stab at adding kernel datapath meter support.
> This implementation supports only drop band type.
>
> Signed-off-by: Andy Zhou 
> ---
>  net/openvswitch/Makefile   |   1 +
>  net/openvswitch/datapath.c |  14 +-
>  net/openvswitch/datapath.h |   3 +
>  net/openvswitch/meter.c| 604 
> +
>  net/openvswitch/meter.h|  54 
>  5 files changed, 674 insertions(+), 2 deletions(-)
>  create mode 100644 net/openvswitch/meter.c
>  create mode 100644 net/openvswitch/meter.h
>
This patch mostly looks good. I have one comment below.

> +static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info *info)
> +{
> +   struct nlattr **a = info->attrs;
> +   struct dp_meter *meter, *old_meter;
> +   struct sk_buff *reply;
> +   struct ovs_header *ovs_reply_header;
> +   struct ovs_header *ovs_header = info->userhdr;
> +   struct datapath *dp;
> +   int err;
> +   u32 meter_id;
> +   bool failed;
> +
> +   meter = dp_meter_create(a);
> +   if (IS_ERR_OR_NULL(meter))
> +   return PTR_ERR(meter);
> +
> +   reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
> + _reply_header);
> +   if (IS_ERR(reply)) {
> +   err = PTR_ERR(reply);
> +   goto exit_free_meter;
> +   }
> +
> +   ovs_lock();
> +   dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
> +   if (!dp) {
> +   err = -ENODEV;
> +   goto exit_unlock;
> +   }
> +
> +   if (!a[OVS_METER_ATTR_ID]) {
> +   err = -ENODEV;
> +   goto exit_unlock;
> +   }
> +
> +   meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
> +
> +   /* Cannot fail after this. */
> +   old_meter = lookup_meter(dp, meter_id);
I do not see RCU read lock taken here. This is not correctness issue
but it could cause RCU checker to spit out warning message. You could
do same trick that is done in get_dp() to avoid this issue.

Can you also test the code with rcu sparse check config option enabled?

Thanks.


[net-next v2 3/4] openvswitch: Add meter infrastructure

2017-10-17 Thread Andy Zhou
OVS kernel datapath so far does not support Openflow meter action.
This is the first stab at adding kernel datapath meter support.
This implementation supports only drop band type.

Signed-off-by: Andy Zhou 
---
 net/openvswitch/Makefile   |   1 +
 net/openvswitch/datapath.c |  14 +-
 net/openvswitch/datapath.h |   3 +
 net/openvswitch/meter.c| 604 +
 net/openvswitch/meter.h|  54 
 5 files changed, 674 insertions(+), 2 deletions(-)
 create mode 100644 net/openvswitch/meter.c
 create mode 100644 net/openvswitch/meter.h

diff --git a/net/openvswitch/Makefile b/net/openvswitch/Makefile
index 60f809085b92..658383fbdf53 100644
--- a/net/openvswitch/Makefile
+++ b/net/openvswitch/Makefile
@@ -11,6 +11,7 @@ openvswitch-y := \
flow.o \
flow_netlink.o \
flow_table.o \
+   meter.o \
vport.o \
vport-internal_dev.o \
vport-netdev.o
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index ac7154018676..eef8d3ea3aae 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -55,6 +55,7 @@
 #include "flow.h"
 #include "flow_table.h"
 #include "flow_netlink.h"
+#include "meter.h"
 #include "vport-internal_dev.h"
 #include "vport-netdev.h"
 
@@ -174,6 +175,7 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
ovs_flow_tbl_destroy(>table);
free_percpu(dp->stats_percpu);
kfree(dp->ports);
+   ovs_meters_exit(dp);
kfree(dp);
 }
 
@@ -1572,6 +1574,10 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
INIT_HLIST_HEAD(>ports[i]);
 
+   err = ovs_meters_init(dp);
+   if (err)
+   goto err_destroy_ports_array;
+
/* Set up our datapath device. */
parms.name = nla_data(a[OVS_DP_ATTR_NAME]);
parms.type = OVS_VPORT_TYPE_INTERNAL;
@@ -1600,7 +1606,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
ovs_dp_reset_user_features(skb, info);
}
 
-   goto err_destroy_ports_array;
+   goto err_destroy_meters;
}
 
err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
@@ -1615,8 +1621,10 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
ovs_notify(_datapath_genl_family, reply, info);
return 0;
 
-err_destroy_ports_array:
+err_destroy_meters:
ovs_unlock();
+   ovs_meters_exit(dp);
+err_destroy_ports_array:
kfree(dp->ports);
 err_destroy_percpu:
free_percpu(dp->stats_percpu);
@@ -2244,6 +2252,7 @@ struct genl_family dp_vport_genl_family __ro_after_init = 
{
_vport_genl_family,
_flow_genl_family,
_packet_genl_family,
+   _meter_genl_family,
 };
 
 static void dp_unregister_genl(int n_families)
@@ -2424,3 +2433,4 @@ static void dp_cleanup(void)
 MODULE_ALIAS_GENL_FAMILY(OVS_VPORT_FAMILY);
 MODULE_ALIAS_GENL_FAMILY(OVS_FLOW_FAMILY);
 MODULE_ALIAS_GENL_FAMILY(OVS_PACKET_FAMILY);
+MODULE_ALIAS_GENL_FAMILY(OVS_METER_FAMILY);
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index ad14b571219d..d1ffa1d9fe57 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -92,6 +92,9 @@ struct datapath {
u32 user_features;
 
u32 max_headroom;
+
+   /* Switch meters. */
+   struct hlist_head *meters;
 };
 
 /**
diff --git a/net/openvswitch/meter.c b/net/openvswitch/meter.c
new file mode 100644
index ..ff57c1cb5f6a
--- /dev/null
+++ b/net/openvswitch/meter.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (c) 2017 Nicira, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "datapath.h"
+#include "meter.h"
+
+#define METER_HASH_BUCKETS 1024
+
+static const struct nla_policy meter_policy[OVS_METER_ATTR_MAX + 1] = {
+   [OVS_METER_ATTR_ID] = { .type = NLA_U32, },
+   [OVS_METER_ATTR_KBPS] = { .type = NLA_FLAG },
+   [OVS_METER_ATTR_STATS] = { .len = sizeof(struct ovs_flow_stats) },
+   [OVS_METER_ATTR_BANDS] = { .type = NLA_NESTED },
+   [OVS_METER_ATTR_USED] = { .type = NLA_U64 },
+   [OVS_METER_ATTR_CLEAR] = { .type = NLA_FLAG },
+   [OVS_METER_ATTR_MAX_METERS] = { .type = NLA_U32 },
+   [OVS_METER_ATTR_MAX_BANDS] = { .type = NLA_U32 },
+};
+
+static const struct nla_policy band_policy[OVS_BAND_ATTR_MAX + 1] = {
+   [OVS_BAND_ATTR_TYPE] = { .type = NLA_U32, },
+   [OVS_BAND_ATTR_RATE] = { .type = NLA_U32, },
+   [OVS_BAND_ATTR_BURST] = { .type = NLA_U32, },
+   [OVS_BAND_ATTR_STATS] = { .len = sizeof(struct