From 176265ed070cb38314857d0e7c08269d73967e10 Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Wed, 10 Sep 2008 13:03:05 -0700 Subject: [PATCH] Use new method to describe table entries in OpenFlow wire protocol. Older versions of OpenFlow pre-defined a few different types of tables and the Features Reply message would indicate how many of those entries existed. This was very inflexible, so now the Features Reply just indicates how many tables there are. The controller now sends a Table Stats request to find out how many entries are supported and the fields that can be wildcarded. This change also removes the "buffer_mb" field from the Features Reply, since it was not being used and seemed to be of limited value. --- datapath/datapath.c | 15 +++++++-------- datapath/hwtable_dummy/hwtable_dummy.c | 4 +++- datapath/table-hash.c | 6 ++++-- datapath/table-linear.c | 3 ++- datapath/table.h | 4 +++- include/openflow.h | 23 +++++++++++------------ lib/ofp-print.c | 17 +++++++---------- switch/datapath.c | 14 ++++++-------- switch/table-hash.c | 6 ++++-- switch/table-linear.c | 3 ++- switch/table.h | 2 ++ 11 files changed, 51 insertions(+), 46 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 107ac1470..c2ffc4a16 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -741,15 +741,13 @@ fill_features_reply(struct datapath *dp, struct ofp_switch_features *ofr) struct net_bridge_port *p; int port_count = 0; - ofr->datapath_id = cpu_to_be64(dp->id); + ofr->datapath_id = cpu_to_be64(dp->id); - ofr->n_exact = htonl(2 * TABLE_HASH_MAX_FLOWS); - ofr->n_compression = 0; /* Not supported */ - ofr->n_general = htonl(TABLE_LINEAR_MAX_FLOWS); - ofr->buffer_mb = htonl(UINT32_MAX); - ofr->n_buffers = htonl(N_PKT_BUFFERS); - ofr->capabilities = htonl(OFP_SUPPORTED_CAPABILITIES); - ofr->actions = htonl(OFP_SUPPORTED_ACTIONS); + ofr->n_buffers = htonl(N_PKT_BUFFERS); + ofr->n_tables = dp->chain->n_tables; + ofr->capabilities = htonl(OFP_SUPPORTED_CAPABILITIES); + ofr->actions = htonl(OFP_SUPPORTED_ACTIONS); + memset(ofr->pad, 0, sizeof ofr->pad); list_for_each_entry_rcu (p, &dp->port_list, node) { fill_port_desc(p, &ofr->ports[port_count]); @@ -1401,6 +1399,7 @@ static int table_stats_dump(struct datapath *dp, void *state, dp->chain->tables[i]->stats(dp->chain->tables[i], &stats); strncpy(ots->name, stats.name, sizeof ots->name); ots->table_id = i; + ots->wildcards = htonl(stats.wildcards); memset(ots->pad, 0, sizeof ots->pad); ots->max_entries = htonl(stats.max_flows); ots->active_count = htonl(stats.n_flows); diff --git a/datapath/hwtable_dummy/hwtable_dummy.c b/datapath/hwtable_dummy/hwtable_dummy.c index 6f21e1de9..20f72a29d 100644 --- a/datapath/hwtable_dummy/hwtable_dummy.c +++ b/datapath/hwtable_dummy/hwtable_dummy.c @@ -213,8 +213,10 @@ static void table_dummy_stats(struct sw_table *swt, { struct sw_table_dummy *td = (struct sw_table_dummy *) swt; stats->name = "dummy"; - stats->n_flows = td->n_flows; + stats->wildcards = OFPFW_ALL; /* xxx Set this appropriately */ + stats->n_flows = td->n_flows; stats->max_flows = td->max_flows; + stats->n_matched = swt->n_matched; } diff --git a/datapath/table-hash.c b/datapath/table-hash.c index d87b51048..b0ce0b78f 100644 --- a/datapath/table-hash.c +++ b/datapath/table-hash.c @@ -186,7 +186,8 @@ static void table_hash_stats(struct sw_table *swt, { struct sw_table_hash *th = (struct sw_table_hash *) swt; stats->name = "hash"; - stats->n_flows = th->n_flows; + stats->wildcards = 0; /* No wildcards are supported. */ + stats->n_flows = th->n_flows; stats->max_flows = th->bucket_mask + 1; stats->n_matched = swt->n_matched; } @@ -310,7 +311,8 @@ static void table_hash2_stats(struct sw_table *swt, for (i = 0; i < 2; i++) table_hash_stats(t2->subtable[i], &substats[i]); stats->name = "hash2"; - stats->n_flows = substats[0].n_flows + substats[1].n_flows; + stats->wildcards = 0; /* No wildcards are supported. */ + stats->n_flows = substats[0].n_flows + substats[1].n_flows; stats->max_flows = substats[0].max_flows + substats[1].max_flows; stats->n_matched = swt->n_matched; } diff --git a/datapath/table-linear.c b/datapath/table-linear.c index e7c6e6739..80f07c209 100644 --- a/datapath/table-linear.c +++ b/datapath/table-linear.c @@ -157,7 +157,8 @@ static void table_linear_stats(struct sw_table *swt, { struct sw_table_linear *tl = (struct sw_table_linear *) swt; stats->name = "linear"; - stats->n_flows = tl->n_flows; + stats->wildcards = OFPFW_ALL; + stats->n_flows = tl->n_flows; stats->max_flows = tl->max_flows; stats->n_matched = swt->n_matched; } diff --git a/datapath/table.h b/datapath/table.h index 26fd466ca..c47e1e60c 100644 --- a/datapath/table.h +++ b/datapath/table.h @@ -12,7 +12,9 @@ struct datapath; /* Table statistics. */ struct sw_table_stats { - const char *name; /* Human-readable name. */ + const char *name; /* Human-readable name. */ + uint32_t wildcards; /* Bitmap of OFPFW_* wildcards that are + supported by the table. */ unsigned int n_flows; /* Number of active flows. */ unsigned int max_flows; /* Flow capacity. */ unsigned long int n_matched; /* Number of packets that have hit. */ diff --git a/include/openflow.h b/include/openflow.h index 69d785370..27550c56e 100644 --- a/include/openflow.h +++ b/include/openflow.h @@ -68,7 +68,7 @@ /* The most significant bit being set in the version field indicates an * experimental OpenFlow version. */ -#define OFP_VERSION 0x89 +#define OFP_VERSION 0x90 #define OFP_MAX_TABLE_NAME_LEN 32 #define OFP_MAX_PORT_NAME_LEN 16 @@ -222,26 +222,21 @@ struct ofp_switch_features { uint64_t datapath_id; /* Datapath unique ID. Only the lower 48-bits are meaningful. */ - /* Table info. */ - uint32_t n_exact; /* Max exact-match table entries. */ - uint32_t n_compression; /* Max entries compressed on service port. */ - uint32_t n_general; /* Max entries of arbitrary form. */ - - /* Buffer limits. A datapath that cannot buffer reports 0.*/ - uint32_t buffer_mb; /* Space for buffering packets, in MB. */ uint32_t n_buffers; /* Max packets buffered at once. */ + uint8_t n_tables; /* Number of tables supported by datapath. */ + uint8_t pad[3]; /* Align to 64-bits. */ + /* Features. */ uint32_t capabilities; /* Bitmap of support "ofp_capabilities". */ uint32_t actions; /* Bitmap of supported "ofp_action_type"s. */ - uint8_t pad[4]; /* Align to 64-bits. */ /* Port info.*/ struct ofp_phy_port ports[0]; /* Port definitions. The number of ports is inferred from the length field in the header. */ }; -OFP_ASSERT(sizeof(struct ofp_switch_features) == 48); +OFP_ASSERT(sizeof(struct ofp_switch_features) == 32); /* What changed about the physical port */ enum ofp_port_reason { @@ -345,6 +340,8 @@ OFP_ASSERT(sizeof(struct ofp_packet_out) == 16); enum ofp_flow_mod_command { OFPFC_ADD, /* New flow. */ + OFPFC_MODIFY, /* Modify all matching flows. */ + OFPFC_MODIFY_STRICT, /* Strictly match wildcards and priority. */ OFPFC_DELETE, /* Delete all matching flows. */ OFPFC_DELETE_STRICT /* Strictly match wildcards and priority. */ }; @@ -578,12 +575,14 @@ OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24); /* Body of reply to OFPST_TABLE request. */ struct ofp_table_stats { - uint8_t table_id; + uint8_t table_id; /* Identifier of table. Lower numbered tables + are consulted first. */ uint8_t pad[3]; /* Align to 32-bits */ char name[OFP_MAX_TABLE_NAME_LEN]; + uint32_t wildcards; /* Bitmap of OFPFW_* wildcards that are + supported by the table. */ uint32_t max_entries; /* Max number of entries supported */ uint32_t active_count; /* Number of active entries */ - uint8_t pad2[4]; /* Align to 64 bits. */ uint64_t matched_count; /* Number of packets that hit table */ }; OFP_ASSERT(sizeof(struct ofp_table_stats) == 56); diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 7cfe0a3dc..4bbcda235 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -411,11 +411,8 @@ ofp_print_switch_features(struct ds *string, const void *oh, size_t len, int i; ds_put_format(string, "dp id:%"PRIx64"\n", ntohll(osf->datapath_id)); - ds_put_format(string, "tables: exact:%d, compressed:%d, general:%d\n", - ntohl(osf->n_exact), - ntohl(osf->n_compression), ntohl(osf->n_general)); - ds_put_format(string, "buffers: size:%d, number:%d\n", - ntohl(osf->buffer_mb), ntohl(osf->n_buffers)); + ds_put_format(string, "n_tables:%d, n_buffers:%d\n", osf->n_tables, + ntohl(osf->n_buffers)); ds_put_format(string, "features: capabilities:%#x, actions:%#x\n", ntohl(osf->capabilities), ntohl(osf->actions)); @@ -807,11 +804,11 @@ ofp_table_stats_reply(struct ds *string, const void *body, size_t len, strncpy(name, ts->name, sizeof name); name[OFP_MAX_TABLE_NAME_LEN] = '\0'; - ds_put_format(string, " table %"PRIu8": ", ts->table_id); - ds_put_format(string, "name %-8s, ", name); - ds_put_format(string, "max %6"PRIu32", ", ntohl(ts->max_entries)); - ds_put_format(string, "active %6"PRIu32", ", ntohl(ts->active_count)); - ds_put_format(string, "matched %6"PRIu64"\n", + ds_put_format(string, " %d: %-8s: ", ts->table_id, name); + ds_put_format(string, "wild=0x%05"PRIx32", ", ntohl(ts->wildcards)); + ds_put_format(string, "max=%6"PRIu32", ", ntohl(ts->max_entries)); + ds_put_format(string, "active=%6"PRIu32", ", ntohl(ts->active_count)); + ds_put_format(string, "matched=%6"PRIu64"\n", ntohll(ts->matched_count)); } } diff --git a/switch/datapath.c b/switch/datapath.c index e91fc9982..1f705b84d 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -672,14 +672,11 @@ dp_send_features_reply(struct datapath *dp, const struct sender *sender) ofr = make_openflow_reply(sizeof *ofr, OFPT_FEATURES_REPLY, sender, &buffer); - ofr->datapath_id = htonll(dp->id); - ofr->n_exact = htonl(2 * TABLE_HASH_MAX_FLOWS); - ofr->n_compression = 0; /* Not supported */ - ofr->n_general = htonl(TABLE_LINEAR_MAX_FLOWS); - ofr->buffer_mb = htonl(UINT32_MAX); - ofr->n_buffers = htonl(N_PKT_BUFFERS); - ofr->capabilities = htonl(OFP_SUPPORTED_CAPABILITIES); - ofr->actions = htonl(OFP_SUPPORTED_ACTIONS); + ofr->datapath_id = htonll(dp->id); + ofr->n_tables = dp->chain->n_tables; + ofr->n_buffers = htonl(N_PKT_BUFFERS); + ofr->capabilities = htonl(OFP_SUPPORTED_CAPABILITIES); + ofr->actions = htonl(OFP_SUPPORTED_ACTIONS); LIST_FOR_EACH (p, struct sw_port, node, &dp->port_list) { struct ofp_phy_port *opp = buffer_put_uninit(buffer, sizeof *opp); memset(opp, 0, sizeof *opp); @@ -1388,6 +1385,7 @@ static int table_stats_dump(struct datapath *dp, void *state, dp->chain->tables[i]->stats(dp->chain->tables[i], &stats); strncpy(ots->name, stats.name, sizeof ots->name); ots->table_id = i; + ots->wildcards = htonl(stats.wildcards); memset(ots->pad, 0, sizeof ots->pad); ots->max_entries = htonl(stats.max_flows); ots->active_count = htonl(stats.n_flows); diff --git a/switch/table-hash.c b/switch/table-hash.c index 0076537e4..46060a2b2 100644 --- a/switch/table-hash.c +++ b/switch/table-hash.c @@ -198,7 +198,8 @@ static void table_hash_stats(struct sw_table *swt, { struct sw_table_hash *th = (struct sw_table_hash *) swt; stats->name = "hash"; - stats->n_flows = th->n_flows; + stats->wildcards = 0; /* No wildcards are supported. */ + stats->n_flows = th->n_flows; stats->max_flows = th->bucket_mask + 1; stats->n_matched = swt->n_matched; } @@ -323,7 +324,8 @@ static void table_hash2_stats(struct sw_table *swt, for (i = 0; i < 2; i++) table_hash_stats(t2->subtable[i], &substats[i]); stats->name = "hash2"; - stats->n_flows = substats[0].n_flows + substats[1].n_flows; + stats->wildcards = 0; /* No wildcards are supported. */ + stats->n_flows = substats[0].n_flows + substats[1].n_flows; stats->max_flows = substats[0].max_flows + substats[1].max_flows; stats->n_matched = swt->n_matched; } diff --git a/switch/table-linear.c b/switch/table-linear.c index ea3777f27..b1143c7ad 100644 --- a/switch/table-linear.c +++ b/switch/table-linear.c @@ -182,7 +182,8 @@ static void table_linear_stats(struct sw_table *swt, { struct sw_table_linear *tl = (struct sw_table_linear *) swt; stats->name = "linear"; - stats->n_flows = tl->n_flows; + stats->wildcards = OFPFW_ALL; + stats->n_flows = tl->n_flows; stats->max_flows = tl->max_flows; stats->n_matched = swt->n_matched; } diff --git a/switch/table.h b/switch/table.h index c31ffa69b..1068a48fa 100644 --- a/switch/table.h +++ b/switch/table.h @@ -46,6 +46,8 @@ struct list; /* Table statistics. */ struct sw_table_stats { const char *name; /* Human-readable name. */ + uint32_t wildcards; /* Bitmap of OFPFW_* wildcards that are + supported by the table. */ unsigned int n_flows; /* Number of active flows. */ unsigned int max_flows; /* Flow capacity. */ unsigned long int n_matched; /* Number of packets that have hit. */ -- 2.43.0