Commit 96fbc13d authored by Andy Zhou's avatar Andy Zhou Committed by David S. Miller

openvswitch: Add meter infrastructure

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: default avatarAndy Zhou <azhou@ovn.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9602c01e
...@@ -12,6 +12,7 @@ openvswitch-y := \ ...@@ -12,6 +12,7 @@ openvswitch-y := \
flow.o \ flow.o \
flow_netlink.o \ flow_netlink.o \
flow_table.o \ flow_table.o \
meter.o \
vport.o \ vport.o \
vport-internal_dev.o \ vport-internal_dev.o \
vport-netdev.o vport-netdev.o
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include "flow.h" #include "flow.h"
#include "flow_table.h" #include "flow_table.h"
#include "flow_netlink.h" #include "flow_netlink.h"
#include "meter.h"
#include "vport-internal_dev.h" #include "vport-internal_dev.h"
#include "vport-netdev.h" #include "vport-netdev.h"
...@@ -174,6 +175,7 @@ static void destroy_dp_rcu(struct rcu_head *rcu) ...@@ -174,6 +175,7 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
ovs_flow_tbl_destroy(&dp->table); ovs_flow_tbl_destroy(&dp->table);
free_percpu(dp->stats_percpu); free_percpu(dp->stats_percpu);
kfree(dp->ports); kfree(dp->ports);
ovs_meters_exit(dp);
kfree(dp); kfree(dp);
} }
...@@ -1572,6 +1574,10 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) ...@@ -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++) for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
INIT_HLIST_HEAD(&dp->ports[i]); INIT_HLIST_HEAD(&dp->ports[i]);
err = ovs_meters_init(dp);
if (err)
goto err_destroy_ports_array;
/* Set up our datapath device. */ /* Set up our datapath device. */
parms.name = nla_data(a[OVS_DP_ATTR_NAME]); parms.name = nla_data(a[OVS_DP_ATTR_NAME]);
parms.type = OVS_VPORT_TYPE_INTERNAL; parms.type = OVS_VPORT_TYPE_INTERNAL;
...@@ -1600,7 +1606,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) ...@@ -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); 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, 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) ...@@ -1615,8 +1621,10 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
ovs_notify(&dp_datapath_genl_family, reply, info); ovs_notify(&dp_datapath_genl_family, reply, info);
return 0; return 0;
err_destroy_ports_array: err_destroy_meters:
ovs_unlock(); ovs_unlock();
ovs_meters_exit(dp);
err_destroy_ports_array:
kfree(dp->ports); kfree(dp->ports);
err_destroy_percpu: err_destroy_percpu:
free_percpu(dp->stats_percpu); free_percpu(dp->stats_percpu);
...@@ -2265,6 +2273,7 @@ static struct genl_family * const dp_genl_families[] = { ...@@ -2265,6 +2273,7 @@ static struct genl_family * const dp_genl_families[] = {
&dp_vport_genl_family, &dp_vport_genl_family,
&dp_flow_genl_family, &dp_flow_genl_family,
&dp_packet_genl_family, &dp_packet_genl_family,
&dp_meter_genl_family,
}; };
static void dp_unregister_genl(int n_families) static void dp_unregister_genl(int n_families)
...@@ -2445,3 +2454,4 @@ MODULE_ALIAS_GENL_FAMILY(OVS_DATAPATH_FAMILY); ...@@ -2445,3 +2454,4 @@ MODULE_ALIAS_GENL_FAMILY(OVS_DATAPATH_FAMILY);
MODULE_ALIAS_GENL_FAMILY(OVS_VPORT_FAMILY); MODULE_ALIAS_GENL_FAMILY(OVS_VPORT_FAMILY);
MODULE_ALIAS_GENL_FAMILY(OVS_FLOW_FAMILY); MODULE_ALIAS_GENL_FAMILY(OVS_FLOW_FAMILY);
MODULE_ALIAS_GENL_FAMILY(OVS_PACKET_FAMILY); MODULE_ALIAS_GENL_FAMILY(OVS_PACKET_FAMILY);
MODULE_ALIAS_GENL_FAMILY(OVS_METER_FAMILY);
...@@ -92,6 +92,9 @@ struct datapath { ...@@ -92,6 +92,9 @@ struct datapath {
u32 user_features; u32 user_features;
u32 max_headroom; u32 max_headroom;
/* Switch meters. */
struct hlist_head *meters;
}; };
/** /**
......
This diff is collapsed.
/*
* 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.
*/
#ifndef METER_H
#define METER_H 1
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netlink.h>
#include <linux/openvswitch.h>
#include <linux/genetlink.h>
#include <linux/skbuff.h>
#include "flow.h"
struct datapath;
#define DP_MAX_BANDS 1
struct dp_meter_band {
u32 type;
u32 rate;
u32 burst_size;
u32 bucket; /* 1/1000 packets, or in bits */
struct ovs_flow_stats stats;
};
struct dp_meter {
spinlock_t lock; /* Per meter lock */
struct rcu_head rcu;
struct hlist_node dp_hash_node; /*Element in datapath->meters
* hash table.
*/
u32 id;
u16 kbps:1, keep_stats:1;
u16 n_bands;
u32 max_delta_t;
u64 used;
struct ovs_flow_stats stats;
struct dp_meter_band bands[];
};
extern struct genl_family dp_meter_genl_family;
int ovs_meters_init(struct datapath *dp);
void ovs_meters_exit(struct datapath *dp);
bool ovs_meter_execute(struct datapath *dp, struct sk_buff *skb,
struct sw_flow_key *key, u32 meter_id);
#endif /* meter.h */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment