Hi all
I'm trying to contribute meter action for OF1.5 by using the existing patch
"https://patchwork.ozlabs.org/patch/731701/" in which meter is instruction.
Currently it seems working using ovs-ofctl, but I am not sure if I can pass the
version info as a parameter to the related function, I need a little help from
people who know OvS architecture.
- Volkan
diff --git a/include/openflow/openflow-1.5.h b/include/openflow/openflow-1.5.h
index 3649e6c..d6bdb4f 100644
--- a/include/openflow/openflow-1.5.h
+++ b/include/openflow/openflow-1.5.h
@@ -150,4 +150,99 @@ struct ofp15_group_desc_stats {
};
OFP_ASSERT(sizeof(struct ofp15_group_desc_stats) == 16);
+enum ofp15_instruction_type {
+ OVSINST_OFPIT15_DEPRECATED = 6, /* Deprecated (was apply meter) */
+ OVSINST_OFPIT15_STAT_TRIGGER = 7, /* Statistics triggers */
+ OVSINST_OFPIT15_EXPERIMENTER = 0xFFFF /* Experimenter instruction */
+};
+
+enum ofp15_action_type {
+ OFPACT15_METER = 6 /* Apply meter (rate limiter) */
+};
+
+/* Action structure for OFPAT_METER */
+struct ofp15_action_meter {
+ ovs_be16 type; /* OFPAT_METER */
+ ovs_be16 len; /* Length is 8. */
+ ovs_be32 meter_id; /* Meter instance. */
+};
+OFP_ASSERT(sizeof(struct ofp15_action_meter) == 8);
+
+/* Statistics for each meter band */
+struct ofp15_meter_band_stats {
+ ovs_be64 packet_band_count; /* Number of packets in band. */
+ ovs_be64 byte_band_count; /* Number of bytes in band. */
+};
+OFP_ASSERT(sizeof(struct ofp15_meter_band_stats) == 16);
+
+/* Body of reply to OFPMP_METER_STATS request. Meter statistics. */
+struct ofp15_meter_stats {
+ ovs_be32 meter_id; /* Meter instance. */
+ ovs_be16 len; /* Length in bytes of this stats. */
+ uint8_t pad[6];
+ ovs_be32 ref_count; /* Number of flows or groups that
+ directly reference this meter. */
+ ovs_be64 packet_in_count; /* Number of packets in input. */
+ ovs_be64 byte_in_count; /* Number of bytes in input. */
+ ovs_be32 duration_sec; /* Time meter has been alive in seconds. */
+ ovs_be32 duration_nsec; /* Time meter has been alive in nanoseconds
+ beyond duration_sec. */
+ struct ofp15_meter_band_stats band_stats[0]; /* The band_stats length is
inferred
+ from the length field. */
+};
+OFP_ASSERT(sizeof(struct ofp15_meter_stats) == 40);
+
+/* Common header for all meter bands */
+struct ofp15_meter_band_header {
+ ovs_be16 type; /* One of OFPMBT_*. */
+ ovs_be16 len; /* Length in bytes of this band. */
+ ovs_be32 rate; /* Rate for this band. */
+ ovs_be32 burst_size; /* Size of bursts. */
+};
+OFP_ASSERT(sizeof(struct ofp15_meter_band_header) == 12);
+
+/* Body of OFPMP15_METER_STATS and OFPMP15_METER_DESC requests. */
+struct ofp15_meter_multipart_request {
+ ovs_be32 meter_id; /* Meter instance, or OFPM_ALL. */
+ uint8_t pad[4]; /* Align to 64 bits. */
+};
+OFP_ASSERT(sizeof(struct ofp15_meter_multipart_request) == 8);
+
+/* Body of reply to OFPMP_METER_DESC request. Meter configuration. */
+struct ofp15_meter_desc {
+ ovs_be16 length; /* Length of this entry. */
+ ovs_be16 flags; /* All OFPMF15_* that apply. */
+ ovs_be32 meter_id; /* Meter instance. */
+ struct ofp15_meter_band_header bands[0]; /* The bands length is
+ inferred from the length field. */
+};
+OFP_ASSERT(sizeof(struct ofp15_meter_desc) == 8);
+
+/* Body of reply to OFPMP_METER_FEATURES request. Meter features. */
+struct ofp15_meter_features {
+ ovs_be32 max_meter; /* Maximum number of meters. */
+ ovs_be32 band_types; /* Bitmaps of (1 << OFPMBT_*) values supported. */
+ ovs_be32 capabilities; /* Bitmaps of "ofp_meter_flags". */
+ uint8_t max_bands; /* Maximum bands per meters */
+ uint8_t max_color; /* Maximum color value */
+ uint8_t pad[2];
+ ovs_be32 features; /* Bitmaps of "ofp_meter_feature_flags". */
+ uint8_t pad2[4];
+};
+OFP_ASSERT(sizeof(struct ofp15_meter_features) == 24);
+
+/* Meter configuration flags */
+enum ofp15_meter_flags {
+ OFPMF15_KBPS = 1 << 0, /* Rate value in kb/s (kilo-bit per second). */
+ OFPMF15_PKTPS = 1 << 1, /* Rate value in packet/sec. */
+ OFPMF15_BURST = 1 << 2, /* Do burst size. */
+ OFPMF15_STATS = 1 << 3, /* Collect statistics. */
+};
+
+/* Meter feature flags */
+enum ofp_meter_feature_flags {
+ OFPMFF15_ACTION_SET = 1 << 0, /* Support meter action in action set. */
+ OFPMFF15_ANY_POSITION = 1 << 1, /* Support any position in action list. */
+ OFPMFF15_MULTI_LIST = 1 << 2, /* Support multiple actions in action list.
*/
+};
#endif /* openflow/openflow-1.5.h */
diff --git a/include/openvswitch/ofp-actions.h
b/include/openvswitch/ofp-actions.h
index 324aac8..a943d46 100644
--- a/include/openvswitch/ofp-actions.h
+++ b/include/openvswitch/ofp-actions.h
@@ -113,6 +113,7 @@ struct vl_mff_map;
OFPACT(NAT, ofpact_nat, ofpact, "nat") \
OFPACT(OUTPUT_TRUNC, ofpact_output_trunc,ofpact, "output_trunc") \
OFPACT(CLONE, ofpact_nest, actions, "clone") \
+ OFPACT(METER, ofpact_meter, ofpact, "meter") \
\
/* Debugging actions. \
* \
@@ -121,7 +122,6 @@ struct vl_mff_map;
OFPACT(DEBUG_RECIRC, ofpact_null, ofpact, "debug_recirc") \
\
/* Instructions. */ \
- OFPACT(METER, ofpact_meter, ofpact, "meter") \
OFPACT(CLEAR_ACTIONS, ofpact_null, ofpact, "clear_actions") \
OFPACT(WRITE_ACTIONS, ofpact_nest, actions, "write_actions") \
OFPACT(WRITE_METADATA, ofpact_metadata, ofpact, "write_metadata") \
@@ -538,7 +538,7 @@ struct ofpact_metadata {
/* OFPACT_METER.
*
- * Used for OFPIT13_METER. */
+ * Used for OFPIT13_METER and OFPIT15_METER */
struct ofpact_meter {
struct ofpact ofpact;
uint32_t meter_id;
@@ -1179,7 +1179,7 @@ enum {
const char *ovs_instruction_name_from_type(enum ovs_instruction_type type);
int ovs_instruction_type_from_name(const char *name);
enum ovs_instruction_type ovs_instruction_type_from_ofpact_type(
- enum ofpact_type);
+ enum ofpact_type, enum ofp_version);
enum ofperr ovs_instruction_type_from_inst_type(
enum ovs_instruction_type *instruction_type, const uint16_t inst_type);
diff --git a/include/openvswitch/ofp-errors.h b/include/openvswitch/ofp-errors.h
index a5bba86..864ebe5 100644
--- a/include/openvswitch/ofp-errors.h
+++ b/include/openvswitch/ofp-errors.h
@@ -260,6 +260,9 @@ enum ofperr {
* bit set to 1. */
OFPERR_OFPBAC_BAD_SET_MASK,
+ /* OF1.5+(2,17). Invalid meter id in meter action. */
+ OFPERR_OFPBAC_BAD_METER,
+
/* NX1.0-1.1(2,256), NX1.2+(11). Must-be-zero action argument had nonzero
* value. */
OFPERR_NXBAC_MUST_BE_ZERO,
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 61e9860..5b75444 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -252,6 +252,10 @@ enum ofp_raw_action_type {
OFPAT_RAW15_COPY_FIELD,
/* ONF1.3-1.4(3200): struct onf_action_copy_field, ... VLMFF */
ONFACT_RAW13_COPY_FIELD,
+
+ /* OF1.5+(29): uint32_t. */
+ OFPAT_RAW15_METER,
+
/* NX1.0-1.4(6): struct nx_action_reg_move, ... VLMFF */
NXAST_RAW_REG_MOVE,
@@ -2348,6 +2352,15 @@ decode_ONFACT_RAW13_COPY_FIELD(const struct
onf_action_copy_field *oacf,
}
static enum ofperr
+decode_OFPAT_RAW15_METER(uint32_t meter_id,
+ enum ofp_version ofp_version OVS_UNUSED,
+ struct ofpbuf *out)
+{
+ ofpact_put_METER(out)->meter_id = meter_id;
+ return 0;
+}
+
+static enum ofperr
decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,
enum ofp_version ofp_version OVS_UNUSED,
const struct vl_mff_map *vl_mff_map,
@@ -6209,7 +6222,10 @@ static void
encode_METER(const struct ofpact_meter *meter,
enum ofp_version ofp_version, struct ofpbuf *out)
{
- if (ofp_version >= OFP13_VERSION) {
+ if (ofp_version >= OFP15_VERSION) {
+ printf("encode_METER - OFP15_VERSION\n");
+ put_OFPAT15_METER(out, meter->meter_id);
+ } else if (ofp_version >= OFP13_VERSION) {
instruction_put_OFPIT13_METER(out)->meter_id = htonl(meter->meter_id);
}
}
@@ -6228,7 +6244,7 @@ format_METER(const struct ofpact_meter *a, struct ds *s)
ds_put_format(s, "%smeter:%s%"PRIu32,
colors.param, colors.end, a->meter_id);
}
-^L
+
/* Clear-Actions instruction. */
static void
@@ -6855,11 +6871,14 @@ ovs_instruction_type_from_name(const char *name)
}
enum ovs_instruction_type
-ovs_instruction_type_from_ofpact_type(enum ofpact_type type)
+ovs_instruction_type_from_ofpact_type(enum ofpact_type type, enum ofp_version
version)
{
switch (type) {
case OFPACT_METER:
- return OVSINST_OFPIT13_METER;
+ if (version >= OFP15_VERSION)
+ return OVSINST_OFPIT11_APPLY_ACTIONS;
+ else
+ return OVSINST_OFPIT13_METER;
case OFPACT_CLEAR_ACTIONS:
return OVSINST_OFPIT11_CLEAR_ACTIONS;
case OFPACT_WRITE_ACTIONS:
@@ -6949,6 +6968,8 @@ struct ovsinst_map {
static const struct ovsinst_map *
get_ovsinst_map(enum ofp_version version)
{
+ const struct ovsinst_map *ret;
+
/* OpenFlow 1.1 and 1.2 instructions. */
static const struct ovsinst_map of11[] = {
{ OVSINST_OFPIT11_GOTO_TABLE, 1 },
@@ -6969,8 +6990,25 @@ get_ovsinst_map(enum ofp_version version)
{ OVSINST_OFPIT13_METER, 6 },
{ 0, -1 },
};
+ /* OpenFlow 1.5+ instructions. */
+ static const struct ovsinst_map of15[] = {
+ { OVSINST_OFPIT11_GOTO_TABLE, 1 },
+ { OVSINST_OFPIT11_WRITE_METADATA, 2 },
+ { OVSINST_OFPIT11_WRITE_ACTIONS, 3 },
+ { OVSINST_OFPIT11_APPLY_ACTIONS, 4 },
+ { OVSINST_OFPIT11_CLEAR_ACTIONS, 5 },
+ { OVSINST_OFPIT15_DEPRECATED, 6 },
+ { OVSINST_OFPIT15_STAT_TRIGGER, 7 },
+ { 0, -1 },
+ };
- return version < OFP13_VERSION ? of11 : of13;
+ if (version >= OFP15_VERSION)
+ ret = of15;
+ else if (version >= OFP13_VERSION)
+ ret = of13;
+ else
+ ret = of11;
+ return ret;
}
/* Converts 'ovsinst_bitmap', a bitmap whose bits correspond to OVSINST_*
@@ -7747,7 +7785,7 @@ ofpacts_verify(const struct ofpact ofpacts[], size_t
ofpacts_len,
return error;
}
- next = ovs_instruction_type_from_ofpact_type(a->type);
+ next = ovs_instruction_type_from_ofpact_type(a->type, OFP15_VERSION);
if (a > ofpacts
&& (inst == OVSINST_OFPIT11_APPLY_ACTIONS
? next < inst
@@ -7814,9 +7852,9 @@ ofpacts_put_openflow_actions(const struct ofpact
ofpacts[], size_t ofpacts_len,
}
static enum ovs_instruction_type
-ofpact_is_apply_actions(const struct ofpact *a)
+ofpact_is_apply_actions(const struct ofpact *a, enum ofp_version ofp_version)
{
- return (ovs_instruction_type_from_ofpact_type(a->type)
+ return (ovs_instruction_type_from_ofpact_type(a->type, ofp_version)
== OVSINST_OFPIT11_APPLY_ACTIONS);
}
@@ -7837,14 +7875,14 @@ ofpacts_put_openflow_instructions(const struct ofpact
ofpacts[],
a = ofpacts;
while (a < end) {
- if (ofpact_is_apply_actions(a)) {
+ if (ofpact_is_apply_actions(a, ofp_version)) {
size_t ofs = openflow->size;
instruction_put_OFPIT11_APPLY_ACTIONS(openflow);
do {
encode_ofpact(a, ofp_version, openflow);
a = ofpact_next(a);
- } while (a < end && ofpact_is_apply_actions(a));
+ } while (a < end && ofpact_is_apply_actions(a, ofp_version));
ofpacts_update_instruction_actions(openflow, ofs);
} else {
encode_ofpact(a, ofp_version, openflow);
@@ -8125,7 +8163,7 @@ ofpacts_get_meter(const struct ofpact ofpacts[], size_t
ofpacts_len)
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
enum ovs_instruction_type inst;
- inst = ovs_instruction_type_from_ofpact_type(a->type);
+ inst = ovs_instruction_type_from_ofpact_type(a->type, OFP15_VERSION);
if (a->type == OFPACT_METER) {
return ofpact_get_METER(a)->meter_id;
} else if (inst > OVSINST_OFPIT13_METER) {
@@ -8277,7 +8315,7 @@ ofpacts_parse__(char *str, struct ofpbuf *ofpacts,
if (ofpact_type_from_name(key, &type)) {
error = ofpact_parse(type, value, ofpacts, usable_protocols);
- inst = ovs_instruction_type_from_ofpact_type(type);
+ inst = ovs_instruction_type_from_ofpact_type(type, OFP15_VERSION);
} else if (!strcasecmp(key, "mod_vlan_vid")) {
error = parse_set_vlan_vid(value, ofpacts, true);
} else if (!strcasecmp(key, "mod_vlan_pcp")) {
_______________________________________________
discuss mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-discuss