diff options
author | Alexandru Copot <alex.mihai.c@gmail.com> | 2014-05-02 09:54:27 +0300 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2014-05-02 09:41:33 -0700 |
commit | 777af88d50b8271a8cc8f0a79d17022944481506 (patch) | |
tree | 3f6d419d949582706c3771a9d33dfe5be521c998 /lib | |
parent | 17a40d3404df4aa6393dd126cb6f0ae99b72031a (diff) | |
download | openvswitch-777af88d50b8271a8cc8f0a79d17022944481506.tar.gz |
Add basic implementation for OpenFlow 1.4 bundles
This is only the communication part of the bundles functionality.
The actual message pre-validation and commits are not implemented.
We also enable OF1.4 for all the tests.
Signed-off-by: Alexandru Copot <alex.mihai.c@gmail.com>
Cc: Daniel Baluta <dbaluta@ixiacom.com>
[blp@nicira.com made ofputil_decode_bundle_add() more obviously correct]
Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/learning-switch.c | 2 | ||||
-rw-r--r-- | lib/ofp-errors.h | 52 | ||||
-rw-r--r-- | lib/ofp-msgs.h | 10 | ||||
-rw-r--r-- | lib/ofp-print.c | 92 | ||||
-rw-r--r-- | lib/ofp-util.c | 80 | ||||
-rw-r--r-- | lib/ofp-util.h | 23 | ||||
-rw-r--r-- | lib/rconn.c | 2 |
7 files changed, 261 insertions, 0 deletions
diff --git a/lib/learning-switch.c b/lib/learning-switch.c index c818a3213..ca579116f 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -398,6 +398,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_BUNDLE_CONTROL: + case OFPTYPE_BUNDLE_ADD_MESSAGE: default: if (VLOG_IS_DBG_ENABLED()) { char *s = ofp_to_string(ofpbuf_data(msg), ofpbuf_size(msg), 2); diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h index c80a75eb0..b1bcf7cc1 100644 --- a/lib/ofp-errors.h +++ b/lib/ofp-errors.h @@ -557,6 +557,58 @@ enum ofperr { /* OF1.3+(13,5). Permissions error. */ OFPERR_OFPTFFC_EPERM, +/* ## -------------------- ## */ +/* ## OFPET_BUNDLE_FAILED ## */ +/* ## -------------------- ## */ + + /* OF1.4+(17,0). Unspecified error. */ + OFPERR_OFPBFC_UNKNOWN, + + /* OF1.4+(17,1). Permissions error. */ + OFPERR_OFPBFC_EPERM, + + /* OF1.4+(17,2). Bundle ID doesn't exist. */ + OFPERR_OFPBFC_BAD_ID, + + /* OF1.4+(17,3). Bundle ID already exists. */ + OFPERR_OFPBFC_BUNDLE_EXIST, + + /* OF1.4+(17,4). Bundle ID is closed. */ + OFPERR_OFPBFC_BUNDLE_CLOSED, + + /* OF1.4+(17,5). Too many bundle IDs. */ + OFPERR_OFPBFC_OUT_OF_BUNDLES, + + /* OF1.4+(17,6). Unsupported of unknown message control type. */ + OFPERR_OFPBFC_BAD_TYPE, + + /* OF1.4+(17,7). Unsupported, unknown, or inconsistent flags. */ + OFPERR_OFPBFC_BAD_FLAGS, + + /* OF1.4+(17,8). Length problem in included message. */ + OFPERR_OFPBFC_MSG_BAD_LEN, + + /* OF1.4+(17,9). Inconsistent or duplicate XID. */ + OFPERR_OFPBFC_MSG_BAD_XID, + + /* OF1.4+(17,10). Unsupported message in this bundle. */ + OFPERR_OFPBFC_MSG_UNSUP, + + /* OF1.4+(17,11). Unsupported message combination in this bundle. */ + OFPERR_OFPBFC_MSG_CONFLICT, + + /* OF1.4+(17,12). Cant handle this many messages in bundle. */ + OFPERR_OFPBFC_MSG_TOO_MANY, + + /* OF1.4+(17,13). One message in bundle failed. */ + OFPERR_OFPBFC_MSG_FAILED, + + /* OF1.4+(17,14). Bundle is taking too long. */ + OFPERR_OFPBFC_TIMEOUT, + + /* OF1.4+(17,15). Bundle is locking the resource. */ + OFPERR_OFPBFC_BUNDLE_IN_PROGRESS, + /* ## ------------------ ## */ /* ## OFPET_EXPERIMENTER ## */ /* ## ------------------ ## */ diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h index d8dee5b53..ded904265 100644 --- a/lib/ofp-msgs.h +++ b/lib/ofp-msgs.h @@ -233,6 +233,12 @@ enum ofpraw { /* OFPT 1.4+ (30): struct ofp14_role_status, uint8_t[8][]. */ OFPRAW_OFPT14_ROLE_STATUS, + /* OFPT 1.4+ (33): struct ofp14_bundle_ctrl_msg, uint8_t[8][]. */ + OFPRAW_OFPT14_BUNDLE_CONTROL, + + /* OFPT 1.4+ (34): struct ofp14_bundle_ctrl_msg, uint8_t[]. */ + OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE, + /* Standard statistics. */ /* OFPST 1.0+ (0): void. */ @@ -508,6 +514,10 @@ enum ofptype { /* Controller role change event messages. */ OFPTYPE_ROLE_STATUS, /* OFPRAW_OFPT14_ROLE_STATUS. */ + OFPTYPE_BUNDLE_CONTROL, /* OFPRAW_OFPT14_BUNDLE_CONTROL. */ + + OFPTYPE_BUNDLE_ADD_MESSAGE, /* OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE. */ + /* Statistics. */ OFPTYPE_DESC_STATS_REQUEST, /* OFPRAW_OFPST_DESC_REQUEST. */ OFPTYPE_DESC_STATS_REPLY, /* OFPRAW_OFPST_DESC_REPLY. */ diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 38e228c9d..a2e515d2d 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -2668,6 +2668,90 @@ ofp_print_table_features(struct ds *s, const struct ofp_header *oh) } } +static const char * +bundle_flags_to_name(uint32_t bit) +{ + switch (bit) { + case OFPBF_ATOMIC: + return "atomic"; + case OFPBF_ORDERED: + return "ordered"; + default: + return NULL; + } +} + +static void +ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh) +{ + int error; + struct ofputil_bundle_ctrl_msg bctrl; + + error = ofputil_decode_bundle_ctrl(oh, &bctrl); + if (error) { + ofp_print_error(s, error); + return; + } + + ds_put_char(s, '\n'); + + ds_put_format(s, " bundle_id=%#"PRIx32" type=", bctrl.bundle_id); + switch (bctrl.type) { + case OFPBCT_OPEN_REQUEST: + ds_put_cstr(s, "OPEN_REQUEST"); + break; + case OFPBCT_OPEN_REPLY: + ds_put_cstr(s, "OPEN_REPLY"); + break; + case OFPBCT_CLOSE_REQUEST: + ds_put_cstr(s, "CLOSE_REQUEST"); + break; + case OFPBCT_CLOSE_REPLY: + ds_put_cstr(s, "CLOSE_REPLY"); + break; + case OFPBCT_COMMIT_REQUEST: + ds_put_cstr(s, "COMMIT_REQUEST"); + break; + case OFPBCT_COMMIT_REPLY: + ds_put_cstr(s, "COMMIT_REPLY"); + break; + case OFPBCT_DISCARD_REQUEST: + ds_put_cstr(s, "DISCARD_REQUEST"); + break; + case OFPBCT_DISCARD_REPLY: + ds_put_cstr(s, "DISCARD_REPLY"); + break; + } + + ds_put_cstr(s, " flags="); + ofp_print_bit_names(s, bctrl.flags, bundle_flags_to_name, ' '); +} + +static void +ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, int verbosity) +{ + int error; + struct ofputil_bundle_add_msg badd; + char *msg; + + error = ofputil_decode_bundle_add(oh, &badd); + if (error) { + ofp_print_error(s, error); + return; + } + + ds_put_char(s, '\n'); + ds_put_format(s, " bundle_id=%#"PRIx32, badd.bundle_id); + ds_put_cstr(s, " flags="); + ofp_print_bit_names(s, badd.flags, bundle_flags_to_name, ' '); + + ds_put_char(s, '\n'); + msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), verbosity); + if (msg) { + ds_put_cstr(s, msg); + } +} + static void ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, struct ds *string, int verbosity) @@ -2913,6 +2997,14 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, case OFPTYPE_FLOW_MONITOR_STATS_REPLY: ofp_print_nxst_flow_monitor_reply(string, msg); break; + + case OFPTYPE_BUNDLE_CONTROL: + ofp_print_bundle_ctrl(string, msg); + break; + + case OFPTYPE_BUNDLE_ADD_MESSAGE: + ofp_print_bundle_add(string, msg, verbosity); + break; } } diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 3484394c5..d17811348 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -7054,3 +7054,83 @@ ofputil_append_queue_stat(struct list *replies, OVS_NOT_REACHED(); } } + +enum ofperr +ofputil_decode_bundle_ctrl(const struct ofp_header *oh, + struct ofputil_bundle_ctrl_msg *msg) +{ + struct ofpbuf b; + enum ofpraw raw; + const struct ofp14_bundle_ctrl_msg *m; + + ofpbuf_use_const(&b, oh, ntohs(oh->length)); + raw = ofpraw_pull_assert(&b); + ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_CONTROL); + + m = ofpbuf_l3(&b); + msg->bundle_id = ntohl(m->bundle_id); + msg->type = ntohs(m->type); + msg->flags = ntohs(m->flags); + + return 0; +} + +struct ofpbuf * +ofputil_encode_bundle_ctrl_reply(const struct ofp_header *oh, + struct ofputil_bundle_ctrl_msg *msg) +{ + struct ofpbuf *buf; + struct ofp14_bundle_ctrl_msg *m; + + buf = ofpraw_alloc_reply(OFPRAW_OFPT14_BUNDLE_CONTROL, oh, 0); + m = ofpbuf_put_zeros(buf, sizeof *m); + + m->bundle_id = htonl(msg->bundle_id); + m->type = htons(msg->type); + m->flags = htons(msg->flags); + + return buf; +} + +enum ofperr +ofputil_decode_bundle_add(const struct ofp_header *oh, + struct ofputil_bundle_add_msg *msg) +{ + const struct ofp14_bundle_ctrl_msg *m; + struct ofpbuf b; + enum ofpraw raw; + size_t inner_len; + + ofpbuf_use_const(&b, oh, ntohs(oh->length)); + raw = ofpraw_pull_assert(&b); + ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE); + + m = ofpbuf_pull(&b, sizeof *m); + msg->bundle_id = ntohl(m->bundle_id); + msg->flags = ntohs(m->flags); + + msg->msg = ofpbuf_data(&b); + inner_len = ntohs(msg->msg->length); + if (inner_len < sizeof(struct ofp_header) || inner_len > ofpbuf_size(&b)) { + return OFPERR_OFPBFC_MSG_BAD_LEN; + } + + return 0; +} + +struct ofpbuf * +ofputil_encode_bundle_add(enum ofp_version ofp_version, + struct ofputil_bundle_add_msg *msg) +{ + struct ofpbuf *request; + struct ofp14_bundle_ctrl_msg *m; + + request = ofpraw_alloc(OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE, ofp_version, 0); + m = ofpbuf_put_zeros(request, sizeof *m); + + m->bundle_id = htonl(msg->bundle_id); + m->flags = htons(msg->flags); + ofpbuf_put(request, msg->msg, ntohs(msg->msg->length)); + + return request; +} diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 7c2803461..782e512a2 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -1137,4 +1137,27 @@ void ofputil_append_group_desc_reply(const struct ofputil_group_desc *, struct list *replies); struct ofpbuf *ofputil_encode_group_desc_request(enum ofp_version); +struct ofputil_bundle_ctrl_msg { + uint32_t bundle_id; + uint16_t type; + uint16_t flags; +}; + +struct ofputil_bundle_add_msg { + uint32_t bundle_id; + uint16_t flags; + const struct ofp_header *msg; +}; + +enum ofperr ofputil_decode_bundle_ctrl(const struct ofp_header *, + struct ofputil_bundle_ctrl_msg *); + +struct ofpbuf *ofputil_encode_bundle_ctrl_reply(const struct ofp_header *, + struct ofputil_bundle_ctrl_msg *); + +struct ofpbuf *ofputil_encode_bundle_add(enum ofp_version ofp_version, + struct ofputil_bundle_add_msg *msg); + +enum ofperr ofputil_decode_bundle_add(const struct ofp_header *, + struct ofputil_bundle_add_msg *); #endif /* ofp-util.h */ diff --git a/lib/rconn.c b/lib/rconn.c index cb3cdd5d4..2c49ca850 100644 --- a/lib/rconn.c +++ b/lib/rconn.c @@ -1350,6 +1350,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_BUNDLE_CONTROL: + case OFPTYPE_BUNDLE_ADD_MESSAGE: return false; case OFPTYPE_PACKET_IN: |