Skip to content

Commit

Permalink
ofproto: Implement OF1.4 Set/Get asynchronous configuration messages.
Browse files Browse the repository at this point in the history
This patch adds support for Openflow1.4 set/get asynchronous configuration
messages. OpenVSwitch already supports set/get asynchronous configuration
messages for Openflow1.3. In this patch OFPT_SET_ASYNC_CONFIG message
allows the controllers to set the configuration for OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD in addition to the Openflow1.3
messages. In a OFPT_SET_ASYNC, only the properties that shall be changed
need to be included, properties that are omitted from the message are
unchanged.

The OFPT_GET_ASYNC_CONFIG is used to query the asynchronous configuration
of switch. In a OFPT_GET_ASYNC_REPLY message, all properties must be
included.

According to Openflow1.4 the initial configuration shall be:

   - In the “master” or “equal” role, enable all OFPT_PACKET_IN messages,
     except those with reason OFPR_INVALID_TTL, enable all OFPT_PORT_STATUS
     and OFPT_FLOW_REMOVED messages, and disable all OFPT_ROLE_STATUS,
     OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.

   - In the “slave” role, enable all OFPT_PORT_STATUS messages and disable
     all OFPT_PACKET_IN, OFPT_FLOW_REMOVED, OFPT_ROLE_STATUS,
     OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.

Signed-off-by: Niti Rohilla <niti.rohilla@tcs.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
  • Loading branch information
nitirohilla authored and blp committed Jul 27, 2015
1 parent ad2e649 commit 9809048
Show file tree
Hide file tree
Showing 13 changed files with 653 additions and 80 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ Natasha Gude natasha@nicira.com
Neil McKee neil.mckee@inmon.com
Neil Zhu zhuj@centecnetworks.com
Nithin Raju nithin@vmware.com
Niti Rohilla niti.rohilla@tcs.com
Padmanabhan Krishnan kprad1@yahoo.com
Paraneetharan Chandrasekaran paraneetharanc@gmail.com
Paul Fazzone pfazzone@nicira.com
Expand Down
16 changes: 16 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,27 @@ sent, an entry labeled "---" means that the message is suppressed.
OFPRR_IDLE_TIMEOUT yes ---
OFPRR_HARD_TIMEOUT yes ---
OFPRR_DELETE yes ---
OFPRR_GROUP_DELETE (OF1.4+) yes ---
OFPRR_METER_DELETE (OF1.4+) yes ---
OFPRR_EVICTION (OF1.4+) yes ---
OFPT_PORT_STATUS
OFPPR_ADD yes yes
OFPPR_DELETE yes yes
OFPPR_MODIFY yes yes
OFPT_ROLE_REQUEST / OFPT_ROLE_REPLY (OF1.4+)
OFPCRR_MASTER_REQUEST --- ---
OFPCRR_CONFIG --- ---
OFPCRR_EXPERIMENTER --- ---
OFPT_TABLE_STATUS (OF1.4+)
OFPTR_VACANCY_DOWN --- ---
OFPTR_VACANCY_UP --- ---
OFPT_REQUESTFORWARD (OF1.4+)
OFPRFR_GROUP_MOD --- ---
OFPRFR_METER_MOD --- ---
```

The NXT_SET_ASYNC_CONFIG message directly sets all of the values in
Expand Down
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Post-v2.4.0
- Support Multicast Listener Discovery (MLDv1 and MLDv2).
- Add 'symmetric_l3l4' and 'symmetric_l3l4+udp' hash functions.
- sFlow agent now reports tunnel and MPLS structures.
- Added OpenFlow 1.4+ OFPT_SET_ASYNC_CONFIG and OFPT_GET_ASYNC_CONFIG
that allows controllers to have more precise control over OpenFlow1.4
asynchronous messages.


v2.4.0 - xx xxx xxxx
Expand Down
12 changes: 12 additions & 0 deletions include/openflow/openflow-1.4.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ enum ofp14_table_mod_prop_eviction_flag {
OFPTMPEF14_LIFETIME = 1 << 2, /* Using flow entry lifetime. */
};

/* What changed about the table */
enum ofp14_table_reason {
OFPTR_VACANCY_DOWN = 3, /* Vacancy down threshold event. */
OFPTR_VACANCY_UP = 4, /* Vacancy up threshold event. */
};

struct ofp14_table_mod_prop_eviction {
ovs_be16 type; /* OFPTMPT14_EVICTION. */
ovs_be16 length; /* Length in bytes of this property. */
Expand Down Expand Up @@ -249,6 +255,12 @@ struct ofp14_async_config {
};
OFP_ASSERT(sizeof(struct ofp14_async_config) == 8);

/* Request forward reason */
enum ofp14_requestforward_reason {
OFPRFR_GROUP_MOD = 0, /* Forward group mod requests. */
OFPRFR_METER_MOD = 1, /* Forward meter mod requests. */
};

/* Async Config property types.
* Low order bit cleared indicates a property for the slave role.
* Low order bit set indicates a property for the master/equal role.
Expand Down
21 changes: 15 additions & 6 deletions lib/ofp-msgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,20 @@ enum ofpraw {
/* NXT 1.0+ (11): struct nx_role_request. */
OFPRAW_NXT_ROLE_REPLY,

/* OFPT 1.3+ (26): void. */
/* OFPT 1.3 (26): void. */
OFPRAW_OFPT13_GET_ASYNC_REQUEST,
/* OFPT 1.3+ (27): struct ofp13_async_config. */
/* OFPT 1.4+ (26): void. */
OFPRAW_OFPT14_GET_ASYNC_REQUEST,
/* OFPT 1.3 (27): struct ofp13_async_config. */
OFPRAW_OFPT13_GET_ASYNC_REPLY,
/* OFPT 1.3+ (28): struct ofp13_async_config. */
/* OFPT 1.4+ (27): struct ofp14_async_config, uint8_t[8][]. */
OFPRAW_OFPT14_GET_ASYNC_REPLY,
/* OFPT 1.3 (28): struct ofp13_async_config. */
OFPRAW_OFPT13_SET_ASYNC,
/* NXT 1.0+ (19): struct nx_async_config. */
OFPRAW_NXT_SET_ASYNC_CONFIG,
/* OFPT 1.4+ (28): struct ofp14_async_config, uint8_t[8][]. */
OFPRAW_OFPT14_SET_ASYNC,

/* OFPT 1.3+ (29): struct ofp13_meter_mod, uint8_t[8][]. */
OFPRAW_OFPT13_METER_MOD,
Expand Down Expand Up @@ -539,10 +545,13 @@ enum ofptype {
* OFPRAW_NXT_ROLE_REPLY. */

/* Asynchronous message configuration. */
OFPTYPE_GET_ASYNC_REQUEST, /* OFPRAW_OFPT13_GET_ASYNC_REQUEST. */
OFPTYPE_GET_ASYNC_REPLY, /* OFPRAW_OFPT13_GET_ASYNC_REPLY. */
OFPTYPE_GET_ASYNC_REQUEST, /* OFPRAW_OFPT13_GET_ASYNC_REQUEST.
* OFPRAW_OFPT14_GET_ASYNC_REQUEST. */
OFPTYPE_GET_ASYNC_REPLY, /* OFPRAW_OFPT13_GET_ASYNC_REPLY.
* OFPRAW_OFPT14_GET_ASYNC_REPLY. */
OFPTYPE_SET_ASYNC_CONFIG, /* OFPRAW_NXT_SET_ASYNC_CONFIG.
* OFPRAW_OFPT13_SET_ASYNC. */
* OFPRAW_OFPT13_SET_ASYNC.
* OFPRAW_OFPT14_SET_ASYNC. */

/* Meters and rate limiters configuration messages. */
OFPTYPE_METER_MOD, /* OFPRAW_OFPT13_METER_MOD. */
Expand Down
238 changes: 197 additions & 41 deletions lib/ofp-print.c
Original file line number Diff line number Diff line change
Expand Up @@ -1903,64 +1903,220 @@ ofp_port_reason_to_string(enum ofp_port_reason reason,
}
}

/* Returns a string form of 'reason'. The return value is either a statically
* allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
* 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
static const char*
ofp_role_reason_to_string(enum ofp14_controller_role_reason reason,
char *reasonbuf, size_t bufsize)
{
switch (reason) {
case OFPCRR_MASTER_REQUEST:
return "master_request";

case OFPCRR_CONFIG:
return "configuration_changed";

case OFPCRR_EXPERIMENTER:
return "experimenter_data_changed";

default:
snprintf(reasonbuf, bufsize, "%d", (int) reason);
return reasonbuf;
}
}

/* Returns a string form of 'reason'. The return value is either a statically
* allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
* 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
static const char*
ofp_table_reason_to_string(enum ofp14_table_reason reason,
char *reasonbuf, size_t bufsize)
{
switch (reason) {
case OFPTR_VACANCY_DOWN:
return "vacancy_down";

case OFPTR_VACANCY_UP:
return "vacancy_up";

default:
snprintf(reasonbuf, bufsize, "%d", (int) reason);
return reasonbuf;
}
}

/* Returns a string form of 'reason'. The return value is either a statically
* allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
* 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
static const char*
ofp_requestforward_reason_to_string(enum ofp14_requestforward_reason reason,
char *reasonbuf, size_t bufsize)
{
switch (reason) {
case OFPRFR_GROUP_MOD:
return "group_mod_request";

case OFPRFR_METER_MOD:
return "meter_mod_request";

default:
snprintf(reasonbuf, bufsize, "%d", (int) reason);
return reasonbuf;
}
}

static const char *
ofp_async_config_reason_to_string(uint32_t reason,
enum ofputil_async_msg_type type,
char *reasonbuf, size_t bufsize)
{
switch (type) {
case OAM_PACKET_IN:
return ofputil_packet_in_reason_to_string(reason, reasonbuf, bufsize);

case OAM_PORT_STATUS:
return ofp_port_reason_to_string(reason, reasonbuf, bufsize);

case OAM_FLOW_REMOVED:
return ofp_flow_removed_reason_to_string(reason, reasonbuf, bufsize);

case OAM_ROLE_STATUS:
return ofp_role_reason_to_string(reason, reasonbuf, bufsize);

case OAM_TABLE_STATUS:
return ofp_table_reason_to_string(reason, reasonbuf, bufsize);

case OAM_REQUESTFORWARD:
return ofp_requestforward_reason_to_string(reason, reasonbuf, bufsize);

case OAM_N_TYPES:
default:
return "Unknown asynchronous configuration message type";
}
}


#define OFP_ASYNC_CONFIG_REASON_BUFSIZE (INT_STRLEN(int) + 1)
static void
ofp_print_nxt_set_async_config(struct ds *string,
const struct nx_async_config *nac)
const struct ofp_header *oh)
{
int i;
int i, j;
enum ofpraw raw;

for (i = 0; i < 2; i++) {
int j;
ofpraw_decode(&raw, oh);

if (raw == OFPRAW_OFPT13_SET_ASYNC ||
raw == OFPRAW_NXT_SET_ASYNC_CONFIG ||
raw == OFPRAW_OFPT13_GET_ASYNC_REPLY) {
const struct nx_async_config *nac = ofpmsg_body(oh);

for (i = 0; i < 2; i++) {

ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave");
ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave");

ds_put_cstr(string, " PACKET_IN:");
for (j = 0; j < 32; j++) {
if (nac->packet_in_mask[i] & htonl(1u << j)) {
char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
const char *reason;
ds_put_cstr(string, " PACKET_IN:");
for (j = 0; j < 32; j++) {
if (nac->packet_in_mask[i] & htonl(1u << j)) {
char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
const char *reason;

reason = ofputil_packet_in_reason_to_string(j, reasonbuf,
reason = ofputil_packet_in_reason_to_string(j, reasonbuf,
sizeof reasonbuf);
ds_put_format(string, " %s", reason);
ds_put_format(string, " %s", reason);
}
}
}
if (!nac->packet_in_mask[i]) {
ds_put_cstr(string, " (off)");
}
ds_put_char(string, '\n');
if (!nac->packet_in_mask[i]) {
ds_put_cstr(string, " (off)");
}
ds_put_char(string, '\n');

ds_put_cstr(string, " PORT_STATUS:");
for (j = 0; j < 32; j++) {
if (nac->port_status_mask[i] & htonl(1u << j)) {
char reasonbuf[OFP_PORT_REASON_BUFSIZE];
const char *reason;
ds_put_cstr(string, " PORT_STATUS:");
for (j = 0; j < 32; j++) {
if (nac->port_status_mask[i] & htonl(1u << j)) {
char reasonbuf[OFP_PORT_REASON_BUFSIZE];
const char *reason;

reason = ofp_port_reason_to_string(j, reasonbuf,
sizeof reasonbuf);
ds_put_format(string, " %s", reason);
reason = ofp_port_reason_to_string(j, reasonbuf,
sizeof reasonbuf);
ds_put_format(string, " %s", reason);
}
}
}
if (!nac->port_status_mask[i]) {
ds_put_cstr(string, " (off)");
}
ds_put_char(string, '\n');
if (!nac->port_status_mask[i]) {
ds_put_cstr(string, " (off)");
}
ds_put_char(string, '\n');

ds_put_cstr(string, " FLOW_REMOVED:");
for (j = 0; j < 32; j++) {
if (nac->flow_removed_mask[i] & htonl(1u << j)) {
char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE];
const char *reason;
ds_put_cstr(string, " FLOW_REMOVED:");
for (j = 0; j < 32; j++) {
if (nac->flow_removed_mask[i] & htonl(1u << j)) {
char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE];
const char *reason;

reason = ofp_flow_removed_reason_to_string(j, reasonbuf,
reason = ofp_flow_removed_reason_to_string(j, reasonbuf,
sizeof reasonbuf);
ds_put_format(string, " %s", reason);
ds_put_format(string, " %s", reason);
}
}
if (!nac->flow_removed_mask[i]) {
ds_put_cstr(string, " (off)");
}
ds_put_char(string, '\n');
}
if (!nac->flow_removed_mask[i]) {
ds_put_cstr(string, " (off)");
} else if (raw == OFPRAW_OFPT14_SET_ASYNC ||
raw == OFPRAW_OFPT14_GET_ASYNC_REPLY) {
uint32_t role[2][OAM_N_TYPES] = {{0}};
uint32_t type;

ofputil_decode_set_async_config(oh, role[0], role[1], true);
for (i = 0; i < 2; i++) {

ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave");
for (type = 0; type < OAM_N_TYPES; type++) {
switch (type) {
case OAM_PACKET_IN:
ds_put_cstr(string, " PACKET_IN:");
break;

case OAM_PORT_STATUS:
ds_put_cstr(string, " PORT_STATUS:");
break;

case OAM_FLOW_REMOVED:
ds_put_cstr(string, " FLOW_REMOVED:");
break;

case OAM_ROLE_STATUS:
ds_put_cstr(string, " ROLE_STATUS:");
break;

case OAM_TABLE_STATUS:
ds_put_cstr(string, " TABLE_STATUS:");
break;

case OAM_REQUESTFORWARD:
ds_put_cstr(string, " REQUESTFORWARD:");
break;
}

for (j = 0; j < 32; j++) {
if (role[i][type] & (1u << j)) {
char reasonbuf[OFP_ASYNC_CONFIG_REASON_BUFSIZE];
const char *reason;

reason = ofp_async_config_reason_to_string(j, type,
reasonbuf,
sizeof reasonbuf);
ds_put_format(string, " %s", reason);
}
}
if (!role[i][type]) {
ds_put_cstr(string, " (off)");
}
ds_put_char(string, '\n');
}
}
ds_put_char(string, '\n');
}
}

Expand Down Expand Up @@ -3040,7 +3196,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,

case OFPTYPE_GET_ASYNC_REPLY:
case OFPTYPE_SET_ASYNC_CONFIG:
ofp_print_nxt_set_async_config(string, ofpmsg_body(oh));
ofp_print_nxt_set_async_config(string, oh);
break;
case OFPTYPE_GET_ASYNC_REQUEST:
break;
Expand Down

0 comments on commit 9809048

Please sign in to comment.