[ovs-dev] [PATCH 4/9] ofproto: handle OFPMP_TABLE_FEATURES msgs and its lifecycle.
Alexander Wu
alexander.wu at huawei.com
Thu Nov 21 09:04:31 UTC 2013
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.
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 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.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 274 insertions(+), 1 deletions(-)
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 2ccbcee..896b028 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -590,6 +590,43 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
return 0;
}
+static void
+table_features_init(struct ofputil_table_features *tf, int table_id);
+
+static void
+ofproto_init_max_table_features(struct ofproto *ofproto)
+{
+ int i;
+ struct ofputil_table_features *tf;
+
+ for (i = 0; i < ofproto->n_tables; i++) {
+ tf = &ofproto->otf[i];
+ table_features_init(tf, i);
+ }
+}
+
+static void
+ofproto_init_real_table_features(struct ofproto *ofproto)
+{
+ int i;
+ struct ofputil_table_features *tf;
+
+ for (i = 0; i < ofproto->n_tables; i++) {
+ tf = &ofproto->tables[i].tf;
+ table_features_init(tf, i);
+ }
+}
+
+static void
+ofproto_init_table_features(struct ofproto *ofproto)
+{
+ /* init the max table features for get */
+ ofproto_init_max_table_features(ofproto);
+
+ /* set the real one */
+ ofproto_init_real_table_features(ofproto);
+}
+
/* 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,8 +643,159 @@ ofproto_init_tables(struct ofproto *ofproto, int n_tables)
OFPROTO_FOR_EACH_TABLE (table, ofproto) {
oftable_init(table);
}
+ ofproto_init_table_features(ofproto);
+}
+
+static void table_feature_prop_update(struct ofputil_table_features *tf,
+ enum ofputil_table_feature_prop_type type,
+ int length)
+{
+ tf->props[type].type = type;
+ tf->props[type].length = length
+ + sizeof(struct ofp13_table_feature_prop_header);
+
+ tf->n_property++;
}
+static void
+table_features_init_instruction_array(struct ofputil_table_features *tf,
+ enum ofputil_table_feature_prop_type type)
+{
+ int i;
+ int olen;
+
+ struct ofputil_instruction *inst = NULL;
+ int element_size = sizeof *inst;
+ olen = OFPIT13_METER * element_size;
+ inst = xzalloc(olen);
+
+ tf->props[type].data = (uint8_t*)inst;
+ for (i = 0 ; i < OFPIT13_METER; i++){
+ /* ofp11(3)_instruction_type */
+ inst[i].type = i + 1;
+ inst[i].len = element_size;
+ }
+
+ table_feature_prop_update(tf, type, olen);
+}
+
+static void
+table_features_init_next_table_array(struct ofputil_table_features *tf,
+ enum ofputil_table_feature_prop_type type)
+{
+ int olen;
+ uint8_t i;
+ uint8_t *next_table;
+ uint8_t cursor = 0;
+
+ olen = (OFTABLE_NUM - tf->table_id - 1) * sizeof *next_table;
+
+ /* If olen is 0, then it's last table */
+ if (olen == 0) {
+ return ;
+ }
+
+ next_table = xzalloc(olen);
+
+ tf->props[type].data = next_table;
+
+ for (i = tf->table_id; i < OFTABLE_NUM - 1; i++) {
+ next_table[cursor++] = i + 1;
+ }
+
+ table_feature_prop_update(tf, type, olen);
+}
+
+static void
+table_features_init_action_array(struct ofputil_table_features *tf,
+ enum ofputil_table_feature_prop_type type)
+{
+ int i;
+ int olen;
+ struct ofp_action_header *action;
+
+ /* Now we support OpenFlow actions to OFPAT12_SET_FIELD,
+ * OFPAT13_PUSH_PBB/OFPAT13_POP_PBB is not support yet.
+ * And NOTE action features are protocol-version-sensitive */
+ const int action_num = get_action_num();
+
+ olen = action_num * sizeof *action;
+ action = xzalloc(olen);
+ tf->props[type].data = (uint8_t*)action;
+
+ for (i = 0 ; i < action_num; i++) {
+ action[i].type = action_info[i].type;
+ action[i].len = 8;
+ }
+
+ table_feature_prop_update(tf, type, olen);
+}
+
+static void
+table_features_init_oxm_array(struct ofputil_table_features *tf,
+ enum ofputil_table_feature_prop_type type)
+{
+ int i = 0 ,olen = 0;
+ const int oxm_num = get_oxm_num();
+ uint32_t *oxm_ids = NULL;
+
+ olen = oxm_num * sizeof *oxm_ids;
+ oxm_ids = xzalloc(olen);
+ tf->props[type].data = (uint8_t*)oxm_ids;
+
+ for (i = 0; i < oxm_num; i++) {
+ oxm_ids[i] = oxm_info[i].type;
+ }
+
+ table_feature_prop_update(tf, type, olen);
+}
+
+#define DEFINE_TFPROP(ENUM, STRUCT, TAG, NAME) \
+ static void table_features_init_##ENUM(struct ofputil_table_features *tf) \
+ { \
+ table_features_init_##TAG(tf, 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;
+
+ /* Ensure the props are inited to 0. */
+ memset(tf->props, 0, sizeof tf->props);
+ tf->n_property = N_OVS_TFPROPS;
+
+#define DEFINE_TFPROP(ENUM, STRUCT, TAG, NAME) \
+ table_features_init_##ENUM(tf);
+OVS_TABLE_FEATURE_PROPS
+#undef DEFINE_TFPROP
+}
+
+static void
+table_features_destroy(struct ofputil_table_features *tf)
+{
+ int i = 0;
+ int n = tf->n_property;
+ struct ofputil_table_feature_prop_header *props = tf->props;
+
+ for (i = 0; i < n; i++) {
+ if (props[i].data) {
+ free(props[i].data);
+ props[i].data = NULL;
+ }
+ }
+}
+
+
/* To be optionally called (only) by an ofproto implementation in its
* constructor function. See the large comment on 'construct' in struct
* ofproto_class for details.
@@ -1247,6 +1435,7 @@ static void
ofproto_destroy__(struct ofproto *ofproto)
OVS_EXCLUDED(ofproto_mutex)
{
+ int i;
struct oftable *table;
ovs_assert(list_is_empty(&ofproto->pending));
@@ -1273,6 +1462,10 @@ ofproto_destroy__(struct ofproto *ofproto)
shash_destroy(&ofproto->port_by_name);
simap_destroy(&ofproto->ofp_requests);
+ for (i = 0; i < ofproto->n_tables; i++) {
+ table_features_destroy(&ofproto->otf[i]);
+ }
+
OFPROTO_FOR_EACH_TABLE (table, ofproto) {
oftable_destroy(table);
}
@@ -5776,6 +5969,83 @@ handle_group_mod(struct ofconn *ofconn, const struct ofp_header *oh)
}
}
+static void
+table_features_get_by_id(struct ofproto *ofproto,
+ int id, struct ofputil_table_features *features)
+{
+ /* CHECK if it doesn't need copy */
+ memcpy(features, &ofproto->tables[id].tf, sizeof *features);
+}
+
+static void table_features_set(struct ofproto *ofproto,
+ struct ofputil_table_features *features)
+ OVS_REQUIRES(ofproto_mutex)
+
+{
+ uint8_t table_id = features->table_id;
+ struct ofputil_table_features *tf = &ofproto->tables[table_id].tf;
+
+ /*
+ * NOTE the props' pointers have been copied, so we free the olds
+ * Currently we use table_features_destroy func, FIXME with a specified
+ */
+ table_features_destroy(tf);
+ memcpy(tf, features, sizeof *features);
+
+ 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_features[ofproto->n_tables];
+ 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++) {
+ table_features_get_by_id(ofproto, i, &reply_features[0]);
+ ofputil_append_table_features_reply(reply_features, &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 +6195,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 +6228,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 +6912,7 @@ oftable_destroy(struct oftable *table)
oftable_disable_eviction(table);
classifier_destroy(&table->cls);
free(table->name);
+ table_features_destroy(&table->tf);
}
/* 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