From: Justin Pettit Date: Wed, 10 Sep 2008 20:03:05 +0000 (-0700) Subject: Use new method to describe table entries in OpenFlow wire protocol. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=176265ed070cb38314857d0e7c08269d73967e10;p=openvswitch 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. --- diff --git a/datapath/datapath.c b/datapath/datapath.c index 107ac147..c2ffc4a1 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 6f21e1de..20f72a29 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 d87b5104..b0ce0b78 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 e7c6e673..80f07c20 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 26fd466c..c47e1e60 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 69d78537..27550c56 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 7cfe0a3d..4bbcda23 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 e91fc998..1f705b84 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 0076537e..46060a2b 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 ea3777f2..b1143c7a 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 c31ffa69..1068a48f 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. */