[ovs-dev] [PATCH v4 4/5] ofproto: handle OFPMP_TABLE_FEATURES msgs and its lifecycle.

Alexander Wu alexander.wu at huawei.com
Wed Dec 4 09:38:31 UTC 2013


V4:
  1. update abstract table-features to bitmap
  2. update ofproto, reduce copy when reply table features.
  3. Move max_table_feature to oftable.

V3:
  1. Delete variable OFPIT13_END, use OFPIT13_METER directly.
  2. Fix implement, restructure with macro.
  3. Add comments that describe table-features-set message is not
     implement yet.
  4. Update calls from ofp-util.
  5. Update comments of action-init.
  6. Add description for table-features get/set struct.

V2:
  1. fix function align, align to 79 bytes, fix BE64 to UINT64, etc.
  2. fix n_tables_miss init type.
  3. Change calls from ofputil.

V1:
  Add table_feature structs in ofproto && oftable to initialize.
  The struct in ofproto is used to get
  The struct in oftable is used to set (set is not implement yet)

  Add some functions to init table features(use ofp13_* struct
  currently, change it to ofputil later).
  Use the encode/decode functions to handle table features request.

  Currently we just implement GET table feature.
  SET table feature may be a hard job, we'll do it later.

Signed-off-by: Alexander Wu <alexander.wu at huawei.com>
---
 ofproto/ofproto-provider.h |    8 ++
 ofproto/ofproto.c          |  228 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 235 insertions(+), 1 deletions(-)

diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 2844e4c..7e852ca 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -258,6 +258,14 @@ struct oftable {
     uint32_t eviction_group_id_basis;
     struct hmap eviction_groups_by_id;
     struct heap eviction_groups_by_size;
+
+    /* Table-features to set.
+     * Describe the real abilities of this table. */
+    struct ofputil_table_features *real_table_feature;
+
+     /* Table-features to get. READ-ONLY after init.
+      * Describe the maxium abilities of tables. */
+    struct ofputil_table_features *max_table_feature;
 };
 
 /* Assigns TABLE to each oftable, in turn, in OFPROTO.
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index c4ce8a2..9783d77 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -590,6 +590,153 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
     return 0;
 }
 
+static void
+table_features_init_instruction_array(struct ofputil_table_features *tf,
+                                      enum ovs_tfprop_type type)
+{
+    int i;
+    unsigned long *instructions_bitmap = bitmap_allocate(OFPIT13_METER);
+
+    for (i = OFPIT11_GOTO_TABLE; i < OFPIT13_METER; i++){
+        bitmap_set1(instructions_bitmap, i);
+    }
+
+    tf->bitmaps[type].map = instructions_bitmap;
+    tf->bitmaps[type].end = OFPIT13_METER;
+}
+
+static void
+table_features_init_next_table_array(struct ofputil_table_features *tf,
+                                     enum ovs_tfprop_type type)
+{
+    uint8_t i;
+    unsigned long *next_tables_bitmap = bitmap_allocate(OFTABLE_NUM);
+
+    for (i = tf->table_id; i < OFTABLE_NUM - 1; i++) {
+        bitmap_set1(next_tables_bitmap, i + 1);
+    }
+
+    tf->bitmaps[type].map = next_tables_bitmap;
+    tf->bitmaps[type].end = OFTABLE_NUM;
+}
+
+static void
+table_features_init_action_array(struct ofputil_table_features *tf,
+                                 enum ovs_tfprop_type type)
+{
+    unsigned long *actions_bitmap = bitmap_allocate(OFPAT13_POP_PBB);
+
+/* If we need init the bitmap to all versions of OpenFlow, then here we should
+ * call bitmap_set1(actions_bitmap, OFPUTIL_##ENUM) and change the length of
+ * the bitmap from OFPAT13_POP_PBB to OFPUTIL_N_ACTIONS. */
+#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
+    bitmap_set1(actions_bitmap, ENUM);
+#include "ofp-util.def"
+
+    tf->bitmaps[type].map = actions_bitmap;
+    tf->bitmaps[type].end = OFPAT13_POP_PBB + 1;
+}
+
+static void
+table_features_init_oxm_array(struct ofputil_table_features *tf,
+                              enum ovs_tfprop_type type)
+{
+    int i = 0;
+    const struct mf_field *mf;
+
+    const int n_oxms_bitmap = MFF_N_IDS;
+    unsigned long *oxms_bitmap = bitmap_allocate(n_oxms_bitmap);
+
+    for (i = 0; i < MFF_N_IDS; i++) {
+        mf = mf_from_id(i);
+        if (OFPUTIL_P_OF13_OXM & mf->usable_protocols && mf->oxm_header) {
+            bitmap_set1(oxms_bitmap, i);
+        }
+    }
+
+    tf->bitmaps[type].map = oxms_bitmap;
+    tf->bitmaps[type].end = n_oxms_bitmap;
+}
+
+static void
+table_features_init_oxm_array_writable(struct ofputil_table_features *tf,
+                                       enum ovs_tfprop_type type)
+{
+    int i = 0;
+    const struct mf_field *mf;
+
+    const int n_oxms_bitmap = MFF_N_IDS;
+    unsigned long *oxms_bitmap = bitmap_allocate(n_oxms_bitmap);
+
+    for (i = 0; i < MFF_N_IDS; i++) {
+        mf = mf_from_id(i);
+        if (OFPUTIL_P_OF13_OXM & mf->usable_protocols && mf->oxm_header
+              && mf->writable) {
+            bitmap_set1(oxms_bitmap, i);
+        }
+    }
+
+    tf->bitmaps[type].map = oxms_bitmap;
+    tf->bitmaps[type].end = n_oxms_bitmap;
+}
+
+#define DEFINE_TFPROP(ENUM, STRUCT, TAG, NAME) \
+    static void table_features_init_##ENUM(struct ofputil_table_features *tf) \
+    { \
+        table_features_init_##TAG(tf, OVSTFPROP_##ENUM); \
+    }
+OVS_TABLE_FEATURE_PROPS
+#undef DEFINE_TFPROP
+
+static void
+table_features_init(struct ofputil_table_features *tf, int table_id)
+{
+    tf->length = 0;
+    tf->table_id = table_id;
+    snprintf(tf->name, OFP_MAX_TABLE_NAME_LEN, "%s%d", "table", table_id);
+
+    tf->metadata_match = UINT64_MAX;
+    tf->metadata_write = UINT64_MAX;
+    tf->config = OFPTC11_TABLE_MISS_MASK;
+    tf->max_entries = 1000000;
+
+#define DEFINE_TFPROP(ENUM, STRUCT, TAG, NAME) \
+    table_features_init_##ENUM(tf);
+OVS_TABLE_FEATURE_PROPS
+#undef DEFINE_TFPROP
+}
+
+static void
+table_features_destruct(struct ofputil_table_features *feature)
+{
+    int i;
+
+    for (i = 0; i < N_OVS_TFPROPS; i++) {
+        bitmap_free(feature->bitmaps[i].map);
+    }
+}
+
+static void
+table_feature_flush(struct ofputil_table_features *feature)
+{
+    table_features_destruct(feature);
+}
+
+static void
+ofproto_init_table_features(struct ofproto *ofproto)
+{
+    int i;
+
+    for (i = 0; i < ofproto->n_tables; i++) {
+        ofproto->tables[i].max_table_feature = xzalloc(
+            sizeof(struct ofputil_table_features));
+        ofproto->tables[i].real_table_feature = xzalloc(
+            sizeof(struct ofputil_table_features));
+        table_features_init(ofproto->tables[i].max_table_feature, i);
+        table_features_init(ofproto->tables[i].real_table_feature, i);
+    }
+}
+
 /* Must be called (only) by an ofproto implementation in its constructor
  * function.  See the large comment on 'construct' in struct ofproto_class for
  * details. */
@@ -606,6 +753,7 @@ ofproto_init_tables(struct ofproto *ofproto, int n_tables)
     OFPROTO_FOR_EACH_TABLE (table, ofproto) {
         oftable_init(table);
     }
+    ofproto_init_table_features(ofproto);
 }
 
 /* To be optionally called (only) by an ofproto implementation in its
@@ -5776,6 +5924,78 @@ handle_group_mod(struct ofconn *ofconn, const struct ofp_header *oh)
     }
 }
 
+static struct ofputil_table_features *
+table_features_get_by_id(struct ofproto *ofproto,
+                         int id)
+{
+    return ofproto->tables[id].max_table_feature;
+}
+
+static void table_features_set(struct ofproto *ofproto,
+                               struct ofputil_table_features *new_feature)
+    OVS_REQUIRES(ofproto_mutex)
+{
+    uint8_t table_id = new_feature->table_id;
+    struct ofputil_table_features *feature
+        = ofproto->tables[table_id].real_table_feature;
+
+    table_feature_flush(feature);
+    memcpy(feature, new_feature, sizeof *new_feature);
+
+    return ;
+}
+
+static enum ofperr
+handle_table_features_stats_request(struct ofconn *ofconn,
+                                    const struct ofp_header *oh)
+    OVS_EXCLUDED(ofproto_mutex)
+{
+
+    struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
+    struct ofputil_table_features request_features[ofproto->n_tables];
+    struct ofputil_table_features *reply_feature;
+    int features_num;
+    uint32_t request_flag = 0;
+    int error;
+    int i;
+
+    struct list replies;
+
+    error = ofputil_pull_table_features(oh, &features_num,
+                    request_features, &request_flag);
+    if (error) {
+        return error;
+    }
+
+    switch (request_flag) {
+    case OVS_TF_GET: {
+        ofpmp_init(&replies, oh);
+        for (i = 0; i < ofproto->n_tables; i++) {
+            reply_feature = table_features_get_by_id(ofproto, i);
+            ofputil_append_table_features_reply(reply_feature, &replies);
+        }
+        ofconn_send_replies(ofconn, &replies);
+        break;
+    }
+    case OVS_TF_SET: {
+
+        /* OFPMP_TABLE_FEATURES - handle set message is not implement yet.
+         *
+         * Currently we set the table-features in each table, but it doesn't
+         * use to restrict any running features.
+         * Future we should make all running features restricted to this
+         * message.
+         */
+        for (i = 0; i < features_num; i++) {
+            table_features_set(ofproto, &request_features[i]);
+        }
+        break;
+    }
+    }
+
+    return 0;
+}
+
 static enum ofperr
 handle_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
 {
@@ -5925,6 +6145,9 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
     case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
         return handle_group_features_stats_request(ofconn, oh);
 
+    case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
+        return handle_table_features_stats_request(ofconn, oh);
+
     case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
         return handle_queue_get_config_request(ofconn, oh);
 
@@ -5955,7 +6178,6 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
     case OFPTYPE_METER_STATS_REPLY:
     case OFPTYPE_METER_CONFIG_STATS_REPLY:
     case OFPTYPE_METER_FEATURES_STATS_REPLY:
-    case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
     case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
     case OFPTYPE_ROLE_STATUS:
     default:
@@ -6640,6 +6862,10 @@ oftable_destroy(struct oftable *table)
     oftable_disable_eviction(table);
     classifier_destroy(&table->cls);
     free(table->name);
+    table_features_destruct(table->max_table_feature);
+    table_features_destruct(table->real_table_feature);
+    free(table->max_table_feature);
+    free(table->real_table_feature);
 }
 
 /* Changes the name of 'table' to 'name'.  If 'name' is NULL or the empty
-- 
1.7.3.1.msysgit.0





More information about the dev mailing list