summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
b5e9402)
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.
struct net_bridge_port *p;
int port_count = 0;
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]);
list_for_each_entry_rcu (p, &dp->port_list, node) {
fill_port_desc(p, &ofr->ports[port_count]);
dp->chain->tables[i]->stats(dp->chain->tables[i], &stats);
strncpy(ots->name, stats.name, sizeof ots->name);
ots->table_id = i;
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);
memset(ots->pad, 0, sizeof ots->pad);
ots->max_entries = htonl(stats.max_flows);
ots->active_count = htonl(stats.n_flows);
{
struct sw_table_dummy *td = (struct sw_table_dummy *) swt;
stats->name = "dummy";
{
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->max_flows = td->max_flows;
+ stats->n_matched = swt->n_matched;
{
struct sw_table_hash *th = (struct sw_table_hash *) swt;
stats->name = "hash";
{
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;
}
stats->max_flows = th->bucket_mask + 1;
stats->n_matched = swt->n_matched;
}
for (i = 0; i < 2; i++)
table_hash_stats(t2->subtable[i], &substats[i]);
stats->name = "hash2";
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;
}
stats->max_flows = substats[0].max_flows + substats[1].max_flows;
stats->n_matched = swt->n_matched;
}
{
struct sw_table_linear *tl = (struct sw_table_linear *) swt;
stats->name = "linear";
{
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;
}
stats->max_flows = tl->max_flows;
stats->n_matched = swt->n_matched;
}
/* Table statistics. */
struct sw_table_stats {
/* 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. */
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. */
/* The most significant bit being set in the version field indicates an
* experimental OpenFlow version.
*/
/* 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
#define OFP_MAX_TABLE_NAME_LEN 32
#define OFP_MAX_PORT_NAME_LEN 16
uint64_t datapath_id; /* Datapath unique ID. Only the lower 48-bits
are meaningful. */
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. */
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. */
/* 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. */
};
/* 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 {
/* What changed about the physical port */
enum ofp_port_reason {
enum ofp_flow_mod_command {
OFPFC_ADD, /* New flow. */
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. */
};
OFPFC_DELETE, /* Delete all matching flows. */
OFPFC_DELETE_STRICT /* Strictly match wildcards and priority. */
};
/* Body of reply to OFPST_TABLE request. */
struct ofp_table_stats {
/* Body of reply to OFPST_TABLE request. */
struct ofp_table_stats {
+ 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];
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 */
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);
uint64_t matched_count; /* Number of packets that hit table */
};
OFP_ASSERT(sizeof(struct ofp_table_stats) == 56);
int i;
ds_put_format(string, "dp id:%"PRIx64"\n", ntohll(osf->datapath_id));
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));
ds_put_format(string, "features: capabilities:%#x, actions:%#x\n",
ntohl(osf->capabilities), ntohl(osf->actions));
strncpy(name, ts->name, sizeof name);
name[OFP_MAX_TABLE_NAME_LEN] = '\0';
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));
}
}
ntohll(ts->matched_count));
}
}
ofr = make_openflow_reply(sizeof *ofr, OFPT_FEATURES_REPLY,
sender, &buffer);
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);
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);
dp->chain->tables[i]->stats(dp->chain->tables[i], &stats);
strncpy(ots->name, stats.name, sizeof ots->name);
ots->table_id = i;
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);
memset(ots->pad, 0, sizeof ots->pad);
ots->max_entries = htonl(stats.max_flows);
ots->active_count = htonl(stats.n_flows);
{
struct sw_table_hash *th = (struct sw_table_hash *) swt;
stats->name = "hash";
{
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;
}
stats->max_flows = th->bucket_mask + 1;
stats->n_matched = swt->n_matched;
}
for (i = 0; i < 2; i++)
table_hash_stats(t2->subtable[i], &substats[i]);
stats->name = "hash2";
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;
}
stats->max_flows = substats[0].max_flows + substats[1].max_flows;
stats->n_matched = swt->n_matched;
}
{
struct sw_table_linear *tl = (struct sw_table_linear *) swt;
stats->name = "linear";
{
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;
}
stats->max_flows = tl->max_flows;
stats->n_matched = swt->n_matched;
}
/* Table statistics. */
struct sw_table_stats {
const char *name; /* Human-readable name. */
/* 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. */
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. */