summaryrefslogtreecommitdiff
path: root/ofproto
diff options
context:
space:
mode:
authorAndy Zhou <azhou@ovn.org>2017-04-05 16:16:12 -0700
committerAndy Zhou <azhou@ovn.org>2017-04-28 14:22:03 -0700
commit9e638f223feb09a891e653796218982e4d64d342 (patch)
tree8e0aca8811ed2ec90b035de132d38ca731f43392 /ofproto
parent333ad77dbd13e5af28172455577b11c5848e20dd (diff)
downloadopenvswitch-9e638f223feb09a891e653796218982e4d64d342.tar.gz
ofproto: Support action upcall meters
Allow action upcall meters, i.e. slowpath and controller meters, to be added and displayed. Keep track of datapath meter ID of those action upcall meters in ofproto to aid action translation. Later patches will make use of them. Signed-off-by: Andy Zhou <azhou@ovn.org> Acked-by: Jarno Rajahalme <jarno@ovn.org>
Diffstat (limited to 'ofproto')
-rw-r--r--ofproto/ofproto-provider.h4
-rw-r--r--ofproto/ofproto.c50
2 files changed, 51 insertions, 3 deletions
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 000326d7f..688a9e5d3 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -112,6 +112,10 @@ struct ofproto {
/* Meter table. */
struct ofputil_meter_features meter_features;
struct hmap meters; /* uint32_t indexed 'struct meter *'. */
+ uint32_t slowpath_meter_id; /* Datapath slowpath meter. UINT32_MAX
+ if not defined. */
+ uint32_t controller_meter_id; /* Datapath controller meter. UINT32_MAX
+ if not defined. */
/* OpenFlow connections. */
struct connmgr *connmgr;
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 54e3d4474..32b5b303b 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -568,6 +568,8 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
memset(&ofproto->meter_features, 0, sizeof ofproto->meter_features);
}
hmap_init(&ofproto->meters);
+ ofproto->slowpath_meter_id = UINT32_MAX;
+ ofproto->controller_meter_id = UINT32_MAX;
/* Set the initial tables version. */
ofproto_bump_tables_version(ofproto);
@@ -6236,9 +6238,33 @@ ofproto_get_meter(const struct ofproto *ofproto, uint32_t meter_id)
return NULL;
}
+static uint32_t *
+ofproto_upcall_meter_ptr(struct ofproto *ofproto, uint32_t meter_id)
+{
+ switch(meter_id) {
+ case OFPM13_SLOWPATH:
+ return &ofproto->slowpath_meter_id;
+ break;
+ case OFPM13_CONTROLLER:
+ return &ofproto->controller_meter_id;
+ break;
+ case OFPM13_ALL:
+ OVS_NOT_REACHED();
+ default:
+ return NULL;
+ }
+}
+
static void
ofproto_add_meter(struct ofproto *ofproto, struct meter *meter)
{
+ uint32_t *upcall_meter_ptr = ofproto_upcall_meter_ptr(ofproto, meter->id);
+
+ /* Cache datapath meter IDs of special meters. */
+ if (upcall_meter_ptr) {
+ *upcall_meter_ptr = meter->provider_meter_id.uint32;
+ }
+
hmap_insert(&ofproto->meters, &meter->node, hash_int(meter->id, 0));
}
@@ -6310,6 +6336,12 @@ static void
meter_destroy(struct ofproto *ofproto, struct meter *meter)
OVS_REQUIRES(ofproto_mutex)
{
+ uint32_t *upcall_meter_ptr;
+ upcall_meter_ptr = ofproto_upcall_meter_ptr(ofproto, meter->id);
+ if (upcall_meter_ptr) {
+ *upcall_meter_ptr = UINT32_MAX;
+ }
+
if (!ovs_list_is_empty(&meter->rules)) {
struct rule_collection rules;
struct rule *rule;
@@ -6442,12 +6474,24 @@ handle_meter_mod(struct ofconn *ofconn, const struct ofp_header *oh)
if (mm.command != OFPMC13_DELETE) {
/* Fails also when meters are not implemented by the provider. */
- if (meter_id == 0 || meter_id > OFPM13_MAX) {
+ if (ofproto->meter_features.max_meters == 0) {
error = OFPERR_OFPMMFC_INVALID_METER;
goto exit_free_bands;
- } else if (meter_id > ofproto->meter_features.max_meters) {
- error = OFPERR_OFPMMFC_OUT_OF_METERS;
+ }
+
+ if (meter_id == 0) {
+ error = OFPERR_OFPMMFC_INVALID_METER;
goto exit_free_bands;
+ } else if (meter_id > OFPM13_MAX) {
+ switch(meter_id) {
+ case OFPM13_SLOWPATH:
+ case OFPM13_CONTROLLER:
+ break;
+ case OFPM13_ALL:
+ default:
+ error = OFPERR_OFPMMFC_INVALID_METER;
+ goto exit_free_bands;
+ }
}
if (mm.meter.n_bands > ofproto->meter_features.max_bands) {
error = OFPERR_OFPMMFC_OUT_OF_BANDS;