Skip to content

Commit

Permalink
Implement OpenFlow 1.4+ OFPMP_TABLE_DESC message.
Browse files Browse the repository at this point in the history
Signed-off-by: Ben Pfaff <blp@nicira.com>
Co-authored-by: Saloni Jain <saloni.jain@tcs.com>
Signed-off-by: Saloni Jain <saloni.jain@tcs.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
  • Loading branch information
blp and salonijain12 committed Jul 3, 2015
1 parent 82c22d3 commit 03c7292
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 0 deletions.
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -8,6 +8,7 @@ Post-v2.4.0
now supported.
* OpenFlow 1.4+ "importance" is now considered for flow eviction.
* OpenFlow 1.4+ OFPTC_EVICTION is now implemented.
* OpenFlow 1.4+ OFPMP_TABLE_DESC is now implemented.
- Support for matching and generating options with Geneve tunnels.
- Support Multicast Listener Discovery (MLDv1 and MLDv2).

Expand Down
10 changes: 10 additions & 0 deletions include/openflow/openflow-1.4.h
Expand Up @@ -155,6 +155,16 @@ struct ofp14_table_mod {
};
OFP_ASSERT(sizeof(struct ofp14_table_mod) == 8);

/* Body of reply to OFPMP_TABLE_DESC request. */
struct ofp14_table_desc {
ovs_be16 length; /* Length is padded to 64 bits. */
uint8_t table_id; /* Identifier of table. Lower numbered tables
are consulted first. */
uint8_t pad[1]; /* Align to 32-bits. */
ovs_be32 config; /* Bitmap of OFPTC_* values. */
/* Followed by 0 or more OFPTMPT14_* properties. */
};
OFP_ASSERT(sizeof(struct ofp14_table_desc) == 8);

/* ## ---------------- ## */
/* ## ofp14_port_stats ## */
Expand Down
2 changes: 2 additions & 0 deletions lib/learning-switch.c
Expand Up @@ -447,6 +447,8 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg)
case OFPTYPE_METER_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_DESC_REQUEST:
case OFPTYPE_TABLE_DESC_REPLY:
case OFPTYPE_BUNDLE_CONTROL:
case OFPTYPE_BUNDLE_ADD_MESSAGE:
case OFPTYPE_NXT_GENEVE_TABLE_MOD:
Expand Down
10 changes: 10 additions & 0 deletions lib/ofp-msgs.h
Expand Up @@ -369,6 +369,12 @@ enum ofpraw {
/* OFPST 1.3+ (12): struct ofp13_table_features, uint8_t[8][]. */
OFPRAW_OFPST13_TABLE_FEATURES_REPLY,

/* OFPST 1.4+ (15): void. */
OFPRAW_OFPST14_TABLE_DESC_REQUEST,

/* OFPST 1.4+ (15): struct ofp14_table_desc, uint8_t[8][]. */
OFPRAW_OFPST14_TABLE_DESC_REPLY,

/* OFPST 1.0-1.4 (13): void. */
OFPRAW_OFPST10_PORT_DESC_REQUEST,
/* OFPST 1.5+ (13): ovs_be32. */
Expand Down Expand Up @@ -611,6 +617,10 @@ enum ofptype {

OFPTYPE_TABLE_FEATURES_STATS_REPLY, /* OFPRAW_OFPST13_TABLE_FEATURES_REPLY. */

OFPTYPE_TABLE_DESC_REQUEST, /* OFPRAW_OFPST14_TABLE_DESC_REQUEST. */

OFPTYPE_TABLE_DESC_REPLY, /* OFPRAW_OFPST14_TABLE_DESC_REPLY. */

OFPTYPE_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_DESC_REQUEST.
* OFPRAW_OFPST15_PORT_DESC_REQUEST. */

Expand Down
39 changes: 39 additions & 0 deletions lib/ofp-print.c
Expand Up @@ -1025,6 +1025,18 @@ ofp_print_table_mod(struct ds *string, const struct ofp_header *oh)
}
}

/* This function will print the Table description properties. */
static void
ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td)
{
ds_put_format(string, "\n table %"PRIu8, td->table_id);
ds_put_cstr(string, ":\n");
ds_put_format(string, " eviction=%s eviction_flags=",
ofputil_table_eviction_to_string(td->eviction));
ofputil_put_eviction_flags(string, td->eviction_flags);
ds_put_char(string, '\n');
}

static void
ofp_print_queue_get_config_request(struct ds *string,
const struct ofp_header *oh)
Expand Down Expand Up @@ -2607,6 +2619,28 @@ ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh)
}
}

static void
ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh)
{
struct ofpbuf b;

ofpbuf_use_const(&b, oh, ntohs(oh->length));

for (;;) {
struct ofputil_table_desc td;
int retval;

retval = ofputil_decode_table_desc(&b, &td, oh->version);
if (retval) {
if (retval != EOF) {
ofp_print_error(s, retval);
}
return;
}
ofp_print_table_desc(s, &td);
}
}

static const char *
bundle_flags_to_name(uint32_t bit)
{
Expand Down Expand Up @@ -2814,6 +2848,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
ofp_print_table_features_reply(string, oh);
break;

case OFPTYPE_TABLE_DESC_REQUEST:
case OFPTYPE_TABLE_DESC_REPLY:
ofp_print_table_desc_reply(string, oh);
break;

case OFPTYPE_HELLO:
ofp_print_hello(string, oh);
break;
Expand Down
135 changes: 135 additions & 0 deletions lib/ofp-util.c
Expand Up @@ -4886,6 +4886,139 @@ ofputil_append_table_features_reply(const struct ofputil_table_features *tf,
ofpmp_postappend(replies, start_ofs);
}

static enum ofperr
parse_table_desc_eviction_property(struct ofpbuf *property,
struct ofputil_table_desc *td)
{
struct ofp14_table_mod_prop_eviction *ote = property->data;

if (property->size != sizeof *ote) {
return OFPERR_OFPBPC_BAD_LEN;
}

td->eviction_flags = ntohl(ote->flags);
return 0;
}

/* Decodes the next OpenFlow "table desc" message (of possibly several) from
* 'msg' into an abstract form in '*td'. Returns 0 if successful, EOF if the
* last "table desc" in 'msg' was already decoded, otherwise an OFPERR_*
* value. */
int
ofputil_decode_table_desc(struct ofpbuf *msg,
struct ofputil_table_desc *td,
enum ofp_version version)
{
struct ofp14_table_desc *otd;
struct ofpbuf properties;
size_t length;

memset(td, 0, sizeof *td);

if (!msg->header) {
ofpraw_pull_assert(msg);
}

if (!msg->size) {
return EOF;
}

otd = ofpbuf_try_pull(msg, sizeof *otd);
if (!otd) {
VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC reply has %"PRIu32" "
"leftover bytes at end", msg->size);
return OFPERR_OFPBRC_BAD_LEN;
}

td->table_id = otd->table_id;
length = ntohs(otd->length);
if (length < sizeof *otd || length - sizeof *otd > msg->size) {
VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC reply claims invalid "
"length %"PRIuSIZE, length);
return OFPERR_OFPBRC_BAD_LEN;
}
length -= sizeof *otd;
ofpbuf_use_const(&properties, ofpbuf_pull(msg, length), length);

td->eviction = ofputil_decode_table_eviction(otd->config, version);
td->eviction_flags = UINT32_MAX;

while (properties.size > 0) {
struct ofpbuf payload;
enum ofperr error;
uint16_t type;

error = ofputil_pull_property(&properties, &payload, &type);
if (error) {
return error;
}

switch (type) {
case OFPTMPT14_EVICTION:
error = parse_table_desc_eviction_property(&payload, td);
break;

default:
log_property(true, "unknown table_desc property %"PRIu16, type);
error = 0;
break;
}

if (error) {
return error;
}
}

return 0;
}

/* Encodes and returns a request to obtain description of tables of a switch.
* The message is encoded for OpenFlow version 'ofp_version'. */
struct ofpbuf *
ofputil_encode_table_desc_request(enum ofp_version ofp_version)
{
struct ofpbuf *request = NULL;

if (ofp_version >= OFP14_VERSION) {
request = ofpraw_alloc(OFPRAW_OFPST14_TABLE_DESC_REQUEST,
ofp_version, 0);
} else {
ovs_fatal(0, "dump-table-desc needs OpenFlow 1.4 or later "
"(\'-O OpenFlow14\')");
}

return request;
}

/* Function to append Table desc information in a reply list. */
void
ofputil_append_table_desc_reply(const struct ofputil_table_desc *td,
struct ovs_list *replies,
enum ofp_version version)
{
struct ofpbuf *reply = ofpbuf_from_list(list_back(replies));
size_t start_otd;
struct ofp14_table_desc *otd;

start_otd = reply->size;
ofpbuf_put_zeros(reply, sizeof *otd);
if (td->eviction_flags != UINT32_MAX) {
struct ofp14_table_mod_prop_eviction *ote;

ote = ofpbuf_put_zeros(reply, sizeof *ote);
ote->type = htons(OFPTMPT14_EVICTION);
ote->length = htons(sizeof *ote);
ote->flags = htonl(td->eviction_flags);
}

otd = ofpbuf_at_assert(reply, start_otd, sizeof *otd);
otd->length = htons(reply->size - start_otd);
otd->table_id = td->table_id;
otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
td->eviction, version);
ofpmp_postappend(replies, start_otd);
}

static enum ofperr
parse_table_mod_eviction_property(struct ofpbuf *property,
struct ofputil_table_mod *tm)
Expand Down Expand Up @@ -8890,6 +9023,7 @@ ofputil_is_bundlable(enum ofptype type)
case OFPTYPE_AGGREGATE_STATS_REQUEST:
case OFPTYPE_TABLE_STATS_REQUEST:
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
case OFPTYPE_TABLE_DESC_REQUEST:
case OFPTYPE_PORT_STATS_REQUEST:
case OFPTYPE_QUEUE_STATS_REQUEST:
case OFPTYPE_PORT_DESC_STATS_REQUEST:
Expand Down Expand Up @@ -8931,6 +9065,7 @@ ofputil_is_bundlable(enum ofptype type)
case OFPTYPE_METER_CONFIG_STATS_REPLY:
case OFPTYPE_METER_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_DESC_REPLY:
case OFPTYPE_ROLE_STATUS:
case OFPTYPE_NXT_GENEVE_TABLE_REQUEST:
case OFPTYPE_NXT_GENEVE_TABLE_REPLY:
Expand Down
21 changes: 21 additions & 0 deletions lib/ofp-util.h
Expand Up @@ -638,6 +638,13 @@ struct ofputil_table_mod {
uint32_t eviction_flags; /* OFPTMPEF14_*. */
};

/* Abstract ofp14_table_desc. */
struct ofputil_table_desc {
uint8_t table_id; /* ID of the table. */
enum ofputil_table_eviction eviction;
uint32_t eviction_flags; /* UINT32_MAX if not present. */
};

enum ofperr ofputil_decode_table_mod(const struct ofp_header *,
struct ofputil_table_mod *);
struct ofpbuf *ofputil_encode_table_mod(const struct ofputil_table_mod *,
Expand Down Expand Up @@ -726,11 +733,22 @@ struct ofputil_table_features {

int ofputil_decode_table_features(struct ofpbuf *,
struct ofputil_table_features *, bool loose);

int ofputil_decode_table_desc(struct ofpbuf *,
struct ofputil_table_desc *,
enum ofp_version);

struct ofpbuf *ofputil_encode_table_features_request(enum ofp_version);

struct ofpbuf *ofputil_encode_table_desc_request(enum ofp_version);

void ofputil_append_table_features_reply(
const struct ofputil_table_features *tf, struct ovs_list *replies);

void ofputil_append_table_desc_reply(const struct ofputil_table_desc *td,
struct ovs_list *replies,
enum ofp_version);

/* Meter band configuration for all supported band types. */
struct ofputil_meter_band {
uint16_t type;
Expand Down Expand Up @@ -857,6 +875,9 @@ struct ofputil_table_stats {
};

struct ofpbuf *ofputil_encode_table_stats_reply(const struct ofp_header *rq);

struct ofpbuf *ofputil_encode_table_desc_reply(const struct ofp_header *rq);

void ofputil_append_table_stats_reply(struct ofpbuf *reply,
const struct ofputil_table_stats *,
const struct ofputil_table_features *);
Expand Down
2 changes: 2 additions & 0 deletions lib/rconn.c
Expand Up @@ -1365,6 +1365,8 @@ is_admitted_msg(const struct ofpbuf *b)
case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_DESC_REQUEST:
case OFPTYPE_TABLE_DESC_REPLY:
return false;

case OFPTYPE_PACKET_IN:
Expand Down
45 changes: 45 additions & 0 deletions ofproto/ofproto.c
Expand Up @@ -3576,6 +3576,47 @@ handle_table_features_request(struct ofconn *ofconn,
return 0;
}

/* This function queries the database for dumping table-desc. */
static void
query_tables_desc(struct ofproto *ofproto, struct ofputil_table_desc **descp)
{
struct ofputil_table_desc *table_desc;
size_t i;

table_desc = *descp = xcalloc(ofproto->n_tables, sizeof *table_desc);
for (i = 0; i < ofproto->n_tables; i++) {
struct ofputil_table_desc *td = &table_desc[i];
td->table_id = i;
td->eviction = (ofproto->tables[i].eviction & EVICTION_OPENFLOW
? OFPUTIL_TABLE_EVICTION_ON
: OFPUTIL_TABLE_EVICTION_OFF);
td->eviction_flags = OFPROTO_EVICTION_FLAGS;
}
}

/* Function to handle dump-table-desc request. */
static enum ofperr
handle_table_desc_request(struct ofconn *ofconn,
const struct ofp_header *request)
{
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
struct ofputil_table_desc *table_desc;
struct ovs_list replies;
size_t i;

query_tables_desc(ofproto, &table_desc);
ofpmp_init(&replies, request);
for (i = 0; i < ofproto->n_tables; i++) {
if (!(ofproto->tables[i].flags & OFTABLE_HIDDEN)) {
ofputil_append_table_desc_reply(&table_desc[i], &replies,
request->version);
}
}
ofconn_send_replies(ofconn, &replies);
free(table_desc);
return 0;
}

static void
append_port_stat(struct ofport *port, struct ovs_list *replies)
{
Expand Down Expand Up @@ -7105,6 +7146,9 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
return handle_table_features_request(ofconn, oh);

case OFPTYPE_TABLE_DESC_REQUEST:
return handle_table_desc_request(ofconn, oh);

case OFPTYPE_PORT_STATS_REQUEST:
return handle_port_stats_request(ofconn, oh);

Expand Down Expand Up @@ -7176,6 +7220,7 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
case OFPTYPE_METER_CONFIG_STATS_REPLY:
case OFPTYPE_METER_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_DESC_REPLY:
case OFPTYPE_ROLE_STATUS:
case OFPTYPE_NXT_GENEVE_TABLE_REPLY:
default:
Expand Down

0 comments on commit 03c7292

Please sign in to comment.