[ovs-dev] [PATCH 3/4] Add init/destroy funcs and handle Table Features msgs.
Alexander Wu
alexander.wu at huawei.com
Sat Oct 26 10:15:30 UTC 2013
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.
And now the cli we implement is very crude. Maybe it could
display better.
Signed-off-by: Alexander Wu <alexander.wu at huawei.com>
---
lib/rconn.c | 4 +-
ofproto/ofproto.c | 384 ++++++++++++++++++++++++++++++++++++++++++++++++-
utilities/ovs-ofctl.c | 17 +++
3 files changed, 402 insertions(+), 3 deletions(-)
diff --git a/lib/rconn.c b/lib/rconn.c
index 96b3579..c441962 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -1381,8 +1381,6 @@ is_admitted_msg(const struct ofpbuf *b)
case OFPTYPE_GROUP_DESC_STATS_REPLY:
case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
- case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
- case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
return false;
case OFPTYPE_PACKET_IN:
@@ -1429,6 +1427,8 @@ is_admitted_msg(const struct ofpbuf *b)
case OFPTYPE_FLOW_MONITOR_CANCEL:
case OFPTYPE_FLOW_MONITOR_PAUSED:
case OFPTYPE_FLOW_MONITOR_RESUMED:
+ case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
+ case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
default:
return true;
}
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 91a39ef..03f6e14 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -559,6 +559,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));
+ 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. */
@@ -575,8 +614,274 @@ 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)
+{
+ const int OFPIT13_END = OFPIT13_METER;
+ int i = 0;
+ int olen = 0;
+
+ 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);
+
+ 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)
+{
+ const int MAX_TABLE = OFTABLE_NUM;
+
+ int olen = 0;
+ uint8_t i = 0;
+ uint8_t cursor = 0;
+ uint8_t *next_table = NULL;
+
+ olen = (MAX_TABLE - tf->table_id - 1) * sizeof(uint8_t);
+
+ /* last table */
+ if (0 == olen)
+ return ;
+
+ next_table = xmalloc(olen);
+ memset(next_table, 0, olen);
+
+ tf->props[type].data = next_table;
+
+ for(i = tf->table_id; i < MAX_TABLE - 1; i++)
+ next_table[cursor++] = i + 1;
+
+ tf->props[type].type = OFPUTIL_NEXT_TABLES;
+ 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 = 0 ,olen = 0;
+ struct ofp_action_header *action = NULL;
+ const int ACTION_NUM = OFPAT13_POP_PBB + 1;
+
+ 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();
+ 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_variables[i].data;
+ }
+
+ 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 = OVS_BE64_MAX;
+ tf->metadata_write = OVS_BE64_MAX;
+ tf->config = OFPTC11_TABLE_MISS_MASK;
+ tf->max_entries = 1000000;
+
+ tf->length = 0; /* useless now */
+ tf->n_property = 0; /* update when needed */
+
+ /* 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. */
+ 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
* ofproto_class for details.
@@ -1216,6 +1521,7 @@ static void
ofproto_destroy__(struct ofproto *ofproto)
OVS_EXCLUDED(ofproto_mutex)
{
+ int i;
struct oftable *table;
ovs_assert(list_is_empty(&ofproto->pending));
@@ -1242,6 +1548,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);
}
@@ -5648,6 +5958,74 @@ 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;
+
+ /*
+ * 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;
+
+ /* decode request */
+ error = ofputil_decode_table_features_request(oh, &features_num, request_features,
+ &request_flag);
+ if (error) {
+ return error;
+ }
+
+ switch (request_flag) {
+ case OTF_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 OTF_SET: {
+ 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)
{
@@ -5680,6 +6058,7 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
if (error) {
return error;
}
+
if (oh->version >= OFP13_VERSION && ofpmsg_is_stat_request(oh)
&& ofpmp_more(oh)) {
/* We have no buffer implementation for multipart requests.
@@ -5797,9 +6176,11 @@ 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:
- case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
/* fallthrough */
case OFPTYPE_HELLO:
@@ -6512,6 +6893,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
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 1a1d423..5970731 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -281,6 +281,7 @@ usage(void)
" show SWITCH show OpenFlow information\n"
" dump-desc SWITCH print switch description\n"
" dump-tables SWITCH print table stats\n"
+ " dump-table-features SWITCH print table features\n"
" mod-port SWITCH IFACE ACT modify port behavior\n"
" mod-table SWITCH MOD modify flow table behavior\n"
" get-frags SWITCH print fragment handling behavior\n"
@@ -649,6 +650,21 @@ ofctl_dump_tables(int argc OVS_UNUSED, char *argv[])
dump_trivial_stats_transaction(argv[1], OFPRAW_OFPST_TABLE_REQUEST);
}
+static void
+ofctl_dump_table_features(int argc OVS_UNUSED, char *argv[])
+{
+ struct ofpbuf *request;
+ struct vconn *vconn;
+
+ open_vconn(argv[1], &vconn);
+ request = ofputil_encode_table_features_request(vconn_get_version(vconn));
+ if (request) {
+ dump_stats_transaction(vconn, request);
+ }
+
+ vconn_close(vconn);
+}
+
static bool
fetch_port_by_features(const char *vconn_name,
const char *port_name, ofp_port_t port_no,
@@ -3323,6 +3339,7 @@ static const struct command all_commands[] = {
{ "snoop", 1, 1, ofctl_snoop },
{ "dump-desc", 1, 1, ofctl_dump_desc },
{ "dump-tables", 1, 1, ofctl_dump_tables },
+ { "dump-table-features", 1, 1, ofctl_dump_table_features },
{ "dump-flows", 1, 2, ofctl_dump_flows },
{ "dump-aggregate", 1, 2, ofctl_dump_aggregate },
{ "queue-stats", 1, 3, ofctl_queue_stats },
--
1.7.3.1.msysgit.0
More information about the dev
mailing list