[ovs-discuss] meter action for OF1.5

Ali Volkan Atli Volkan.Atli at argela.com.tr
Tue Jun 6 12:37:56 UTC 2017


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")) {


More information about the discuss mailing list