On Wed, Nov 06, 2013 at 10:46:04PM +0800, Alexander Wu wrote: > > 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. > > Simon Horman suggestions: > 1. Fix CodingStyle, some coding error. > 2. Fix the init functions to macros. - I'll fix it later. > > 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...@huawei.com> > --- > ofproto/ofproto.c | 388 > ++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 387 insertions(+), 1 deletions(-) > > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > index 0c66a59..9494925 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -590,6 +590,45 @@ 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]; > + memset(tf, 0, sizeof(*tf));
I think that you should either remove this memset or move it into table_features_init(). Likewise for ofproto_init_real_table_features() > + 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; > + memset(tf, 0, sizeof(*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,7 +645,277 @@ 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_instructions_init(struct ofputil_table_features *tf, > + enum ofputil_table_feature_prop_type type) > +{ > + int i; > + int olen; > + > + int OFPIT13_END = OFPIT13_METER; I still don't like OFPIT13_END. Can you either remove it or make it lowercase? > + struct ofputil_instruction *inst = NULL; > + int element_size = sizeof(struct ofputil_instruction); > + > + olen = OFPIT13_END * element_size; > + > + inst = (struct ofputil_instruction *)xmalloc(olen); > + memset(inst, 0, olen); > + > + tf->props[type].data = (uint8_t*)inst; > + for(i = 0 ; i < OFPIT13_END ; i++){ > + /* ofp11(3)_instruction_type */ > + inst[i].type = i + 1; > + inst[i].len = element_size; > + } > + > + tf->props[type].type = type; > + tf->props[type].length = olen > + + sizeof(struct ofp13_table_feature_prop_header); sizeof is an operator. You probably don't need the (). Likewise elsewhere in this patch. > + > + tf->n_property++; > +} > + > +static void > +table_features_INSTRUCTIONS_init(struct ofputil_table_features *tf) > +{ > + table_instructions_init(tf, OFPUTIL_INSTRUCTIONS); > +} > + > +static void > +table_features_INSTRUCTIONS_MISS_init(struct ofputil_table_features *tf) > +{ > + table_instructions_init(tf, OFPUTIL_INSTRUCTIONS_MISS); > + > +} > + > +static void > +table_next_table_init(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(uint8_t); > + > + /* last table */ > + if (olen == 0) > + return ; 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; > + } > + > + tf->props[type].type = type; > + tf->props[type].length = olen > + + sizeof(struct ofp13_table_feature_prop_header); > + tf->n_property++; > +} > + > +static void > +table_features_NEXT_TABLES_init(struct ofputil_table_features *tf) > +{ > + table_next_table_init(tf, OFPUTIL_NEXT_TABLES); > } > +static void > +table_features_NEXT_TABLES_MISS_init(struct ofputil_table_features *tf) > +{ > + table_next_table_init(tf, OFPUTIL_NEXT_TABLES_MISS); > +} > + > +static void > +table_action_init(struct ofputil_table_features *tf, > + enum ofputil_table_feature_prop_type type) > +{ > + int i; > + int olen; > + struct ofp_action_header *action; > + const int ACTION_NUM = OFPAT13_POP_PBB + 1; Could you make ACTION_NUM lowercase? > + > + olen = ACTION_NUM * sizeof(struct ofp_action_header); > + > + action = (struct ofp_action_header *)xzalloc(olen); > + > + tf->props[type].data = (uint8_t*)action; > + > + for(i = 0 ; i < ACTION_NUM; i++) { > + action[i].type = i; > + action[i].len = 8; > + } > + > + tf->props[type].length = olen > + + sizeof(struct ofp13_table_feature_prop_header); > + tf->props[type].type = type; > + tf->n_property++; > +} > + > + > +static void > +table_features_WRITE_ACTIONS_init(struct ofputil_table_features *tf) > +{ > + table_action_init(tf, OFPUTIL_WRITE_ACTIONS); > +} > + > +static void > +table_features_WRITE_ACTIONS_MISS_init(struct ofputil_table_features *tf) > +{ > + table_action_init(tf, OFPUTIL_WRITE_ACTIONS_MISS); > +} > + > +static void > +table_features_APPLY_ACTIONS_init(struct ofputil_table_features *tf) > +{ > + table_action_init(tf, OFPUTIL_APPLY_ACTIONS); > +} > + > +static void > +table_features_APPLY_ACTIONS_MISS_init(struct ofputil_table_features *tf) > +{ > + table_action_init(tf, OFPUTIL_APPLY_ACTIONS_MISS); > +} > + > +static void > +table_oxm_init(struct ofputil_table_features *tf, > + enum ofputil_table_feature_prop_type type) > +{ > + int i = 0 ,olen = 0; > + const int OXM_NUM = get_oxm_num(); Could you make OXM_NUM lowercase? > + uint32_t *oxm_ids = NULL; > + > + olen = sizeof(uint32_t) * OXM_NUM; > + 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; > + } > + > + tf->props[type].length = olen > + + sizeof(struct ofp13_table_feature_prop_header); > + tf->props[type].type = type; > + tf->n_property++; > +} > + > +static void > +table_features_MATCH_init(struct ofputil_table_features *tf) > +{ > + table_oxm_init(tf, OFPUTIL_MATCH); > + return ; > +} > + > + > +static void > +table_features_WILDCARDS_init(struct ofputil_table_features *tf) > +{ > + table_oxm_init(tf, OFPUTIL_WILDCARDS); > + return; > +} > + > +static void > +table_features_WRITE_SETFIELD_init(struct ofputil_table_features *tf) > +{ > + table_oxm_init(tf, OFPUTIL_WRITE_SETFIELD); > + return ; > +} > + > +static void > +table_features_WRITE_SETFIELD_MISS_init(struct ofputil_table_features *tf) > +{ > + table_oxm_init(tf, OFPUTIL_WRITE_SETFIELD_MISS); > + return ; > +} > + > +static void > +table_features_APPLY_SETFIELD_init(struct ofputil_table_features *tf) > +{ > + table_oxm_init(tf, OFPUTIL_APPLY_SETFIELD); > + return ; > +} > + > +static void > +table_features_APPLY_SETFIELD_MISS_init(struct ofputil_table_features *tf) > +{ > + table_oxm_init(tf, OFPUTIL_APPLY_SETFIELD_MISS); > + return; > +} > + > +static void > +table_features_EXPERIMENTER_init( > + struct ofputil_table_features *tf OVS_UNUSED) > +{ > + return; > +} > + > +static void > +table_features_EXPERIMENTER_MISS_init( > + struct ofputil_table_features *tf OVS_UNUSED) > +{ > + return; > +} > + > +static void > +table_features_init(struct ofputil_table_features *tf, int table_id) > +{ > + 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; > + > + tf->length = 0; /* useless now */ > + tf->n_property = 0; /* update when needed */ Please enhance or remove the comments above. > + > + /* CHECK the props are inited to 0. */ > + memset(tf->props, 0, sizeof(tf->props)); > + > + /* NOTE now the implement use ofp13_*, change it to ofputil_* later. */ > + table_features_INSTRUCTIONS_init(tf); > + table_features_INSTRUCTIONS_MISS_init(tf); > + table_features_NEXT_TABLES_init(tf); > + table_features_NEXT_TABLES_MISS_init(tf); > + table_features_WRITE_ACTIONS_init(tf); > + table_features_WRITE_ACTIONS_MISS_init(tf); > + table_features_APPLY_ACTIONS_init(tf); > + table_features_APPLY_ACTIONS_MISS_init(tf); > + table_features_MATCH_init(tf); > + table_features_WILDCARDS_init(tf); > + table_features_WRITE_SETFIELD_init(tf); > + table_features_WRITE_SETFIELD_MISS_init(tf); > + table_features_APPLY_SETFIELD_init(tf); > + table_features_APPLY_SETFIELD_MISS_init(tf); > + table_features_EXPERIMENTER_init(tf); > + table_features_EXPERIMENTER_MISS_init(tf); > + > + /* FIXME Now we search the array at last. */ Ditto. > + tf->n_property = 0xff; > +} > + > +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 > @@ -1247,6 +1556,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 +1583,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); > } > @@ -5766,6 +6080,73 @@ 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) > +{ > + uint8_t table_id = features->table_id; > + struct ofputil_table_features *tf = &ofproto->tables[table_id].tf; I think that you need to implement some locking to ensure exclusive access to tf here. > + > + /* > + * 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) > +{ > + > + 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: { > + /* NOT IMPLEMENT */ I think you should expand the comment above to explain how much is implemented and what is not implemented. I think that the basic situation is that set updates ofproto but nothing uses the settings: which I think is quite reasonable. > + 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) > { > @@ -5915,8 +6296,13 @@ 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); > + > + /* FIXME: Change the following once they are implemented: */ > case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: > return handle_queue_get_config_request(ofconn, oh); > + /* fallthrough */ But it doesn't fall-through. It returns. > > case OFPTYPE_HELLO: > case OFPTYPE_ERROR: > @@ -5945,7 +6331,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: > @@ -6630,6 +7015,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 > > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev