From 7fa9111326e440a56dff41e0d4571716032a1de7 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 7 Dec 2010 13:22:46 -0800 Subject: [PATCH] ofp-print: Implement printing for OFPUTIL_NXT_FLOW_MOD. --- lib/ofp-print.c | 157 +++++++++++++++++++++++++++++++++++------------- lib/ofp-util.c | 40 +++++++++++- lib/ofp-util.h | 4 ++ 3 files changed, 157 insertions(+), 44 deletions(-) diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 6ac09591..eba194e4 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -30,6 +30,7 @@ #include "compiler.h" #include "dynamic-string.h" #include "flow.h" +#include "nx-match.h" #include "ofp-util.h" #include "ofpbuf.h" #include "openflow/openflow.h" @@ -40,6 +41,8 @@ static void ofp_print_port_name(struct ds *string, uint16_t port); static void ofp_print_queue_name(struct ds *string, uint32_t port); +static void ofp_print_error(struct ds *, int error); + /* Returns a string that represents the contents of the Ethernet frame in the * 'len' bytes starting at 'data' to 'stream' as output by tcpdump. @@ -766,62 +769,85 @@ ofp_match_to_string(const struct ofp_match *om, int verbosity) print_wild(&f, "tp_dst=", w & OFPFW_TP_DST, verbosity, "%d", ntohs(om->tp_dst)); } + if (ds_last(&f) == ',') { + f.length--; + } return ds_cstr(&f); } static void -ofp_print_flow_mod(struct ds *string, const struct ofp_flow_mod *ofm, - int verbosity) +ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, + enum ofputil_msg_code code, int verbosity) { - size_t len = ntohs(ofm->header.length); + struct flow_mod fm; + int error; - ds_put_char(string, ' '); - ofp_print_match(string, &ofm->match, verbosity); - if (ds_last(string) != ' ') { - ds_put_char(string, ' '); + error = ofputil_decode_flow_mod(&fm, oh, NXFF_OPENFLOW10); + if (error) { + ofp_print_error(s, error); + return; } - switch (ntohs(ofm->command)) { + ds_put_char(s, ' '); + switch (fm.command) { case OFPFC_ADD: - ds_put_cstr(string, "ADD:"); + ds_put_cstr(s, "ADD"); break; case OFPFC_MODIFY: - ds_put_cstr(string, "MOD:"); + ds_put_cstr(s, "MOD"); break; case OFPFC_MODIFY_STRICT: - ds_put_cstr(string, "MOD_STRICT:"); + ds_put_cstr(s, "MOD_STRICT"); break; case OFPFC_DELETE: - ds_put_cstr(string, "DEL:"); + ds_put_cstr(s, "DEL"); break; case OFPFC_DELETE_STRICT: - ds_put_cstr(string, "DEL_STRICT:"); + ds_put_cstr(s, "DEL_STRICT"); break; default: - ds_put_format(string, "cmd:%d", ntohs(ofm->command)); + ds_put_format(s, "cmd:%d", fm.command); + } + + ds_put_char(s, ' '); + if (verbosity >= 3 && code == OFPUTIL_OFPT_FLOW_MOD) { + const struct ofp_flow_mod *ofm = (const struct ofp_flow_mod *) oh; + + ofp_print_match(s, &ofm->match, verbosity); + } else if (verbosity >= 3 && code == OFPUTIL_NXT_FLOW_MOD) { + const struct nx_flow_mod *nfm = (const struct nx_flow_mod *) oh; + const void *nxm = nfm + 1; + char *nxm_s = nx_match_to_string(nxm, ntohs(nfm->match_len)); + ds_put_cstr(s, nxm_s); + free(nxm_s); + } else { + cls_rule_format(&fm.cr, s); } - if (ofm->cookie != htonll(0)) { - ds_put_format(string, " cookie:0x%"PRIx64, ntohll(ofm->cookie)); + + if (ds_last(s) != ' ') { + ds_put_char(s, ' '); } - if (ofm->idle_timeout != htons(OFP_FLOW_PERMANENT)) { - ds_put_format(string, " idle:%d", ntohs(ofm->idle_timeout)); + if (fm.cookie != htonll(0)) { + ds_put_format(s, "cookie:0x%"PRIx64" ", ntohll(fm.cookie)); } - if (ofm->hard_timeout != htons(OFP_FLOW_PERMANENT)) { - ds_put_format(string, " hard:%d", ntohs(ofm->hard_timeout)); + if (fm.idle_timeout != OFP_FLOW_PERMANENT) { + ds_put_format(s, "idle:%"PRIu16" ", fm.idle_timeout); } - if (ofm->priority != htons(32768)) { - ds_put_format(string, " pri:%"PRIu16, ntohs(ofm->priority)); + if (fm.hard_timeout != OFP_FLOW_PERMANENT) { + ds_put_format(s, "hard:%"PRIu16" ", fm.hard_timeout); } - if (ofm->buffer_id != htonl(UINT32_MAX)) { - ds_put_format(string, " buf:%#"PRIx32, ntohl(ofm->buffer_id)); + if (fm.cr.priority != OFP_DEFAULT_PRIORITY && verbosity >= 3) { + ds_put_format(s, "pri:%"PRIu16" ", fm.cr.priority); } - if (ofm->flags != htons(0)) { - ds_put_format(string, " flags:%"PRIx16, ntohs(ofm->flags)); + if (fm.buffer_id != UINT32_MAX) { + ds_put_format(s, "buf:0x%"PRIx32" ", fm.buffer_id); } - ds_put_cstr(string, " "); - ofp_print_actions(string, ofm->actions, - len - offsetof(struct ofp_flow_mod, actions)); - ds_put_char(string, '\n'); + if (fm.flags != 0) { + ds_put_format(s, "flags:0x%"PRIx16" ", fm.flags); + } + + ofp_print_actions(s, (const struct ofp_action_header *) fm.actions, + fm.n_actions * sizeof *fm.actions); } static void @@ -945,6 +971,19 @@ lookup_error_code(int type, int code) return "?"; } +static void +ofp_print_error(struct ds *string, int error) +{ + int type = get_ofp_err_type(error); + int code = get_ofp_err_code(error); + if (string->length) { + ds_put_char(string, ' '); + } + ds_put_format(string, " ***decode error type:%d(%s) code:%d(%s)***", + type, lookup_error_type(type), + code, lookup_error_code(type, code)); +} + static void ofp_print_error_msg(struct ds *string, const struct ofp_error_msg *oem) { @@ -953,7 +992,7 @@ ofp_print_error_msg(struct ds *string, const struct ofp_error_msg *oem) int code = ntohs(oem->code); char *s; - ds_put_format(string, " type%d(%s) code%d(%s) payload:\n", + ds_put_format(string, " type:%d(%s) code:%d(%s) payload:\n", type, lookup_error_type(type), code, lookup_error_code(type, code)); @@ -1284,17 +1323,40 @@ ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity) } } +static void +ofp_print_nxt_tun_id_from_cookie(struct ds *string, + const struct nxt_tun_id_cookie *ntic) +{ + ds_put_format(string, " set=%"PRIu8, ntic->set); +} + +static void +ofp_print_nxt_set_flow_format(struct ds *string, + const struct nxt_set_flow_format *nsff) +{ + uint32_t format = ntohl(nsff->format); + + ds_put_cstr(string, " format="); + if (ofputil_flow_format_is_valid(format)) { + ds_put_cstr(string, ofputil_flow_format_to_string(format)); + } else { + ds_put_format(string, "%"PRIu32, format); + } +} + static void ofp_to_string__(const struct ofp_header *oh, const struct ofputil_msg_type *type, struct ds *string, int verbosity) { + enum ofputil_msg_code code; const void *msg = oh; ds_put_format(string, "%s (xid=0x%"PRIx32"):", ofputil_msg_type_name(type), ntohl(oh->xid)); - switch (ofputil_msg_type_code(type)) { + code = ofputil_msg_type_code(type); + switch (code) { case OFPUTIL_INVALID: break; @@ -1342,7 +1404,7 @@ ofp_to_string__(const struct ofp_header *oh, break; case OFPUTIL_OFPT_FLOW_MOD: - ofp_print_flow_mod(string, msg, verbosity); + ofp_print_flow_mod(string, msg, code, verbosity); break; case OFPUTIL_OFPT_PORT_MOD: @@ -1418,11 +1480,26 @@ ofp_to_string__(const struct ofp_header *oh, case OFPUTIL_NXT_STATUS_REQUEST: case OFPUTIL_NXT_STATUS_REPLY: + /* XXX */ + break; + case OFPUTIL_NXT_TUN_ID_FROM_COOKIE: + ofp_print_nxt_tun_id_from_cookie(string, msg); + break; + case OFPUTIL_NXT_ROLE_REQUEST: case OFPUTIL_NXT_ROLE_REPLY: + /* XXX */ + break; + case OFPUTIL_NXT_SET_FLOW_FORMAT: + ofp_print_nxt_set_flow_format(string, msg); + break; + case OFPUTIL_NXT_FLOW_MOD: + ofp_print_flow_mod(string, msg, code, verbosity); + break; + case OFPUTIL_NXT_FLOW_REMOVED: case OFPUTIL_NXST_FLOW_REQUEST: case OFPUTIL_NXST_AGGREGATE_REQUEST: @@ -1458,26 +1535,24 @@ ofp_to_string(const void *oh_, size_t len, int verbosity) ntohs(oh->length), len); } else { const struct ofputil_msg_type *type; - int err_type, err_code; int error; error = ofputil_decode_msg_type(oh, &type); if (!error) { ofp_to_string__(oh, type, &string, verbosity); - if (verbosity >= 3) { + if (verbosity >= 5) { + if (ds_last(&string) != '\n') { + ds_put_char(&string, '\n'); + } ds_put_hex_dump(&string, oh, len, 0, true); } - if (string.string[string.length - 1] != '\n') { + if (ds_last(&string) != '\n') { ds_put_char(&string, '\n'); } return ds_steal_cstr(&string); } - err_type = get_ofp_err_type(error); - err_code = get_ofp_err_code(error); - ds_put_format(&string, "Bad OpenFlow message (%s, %s)\n", - lookup_error_type(err_type), - lookup_error_code(err_type, err_code)); + ofp_print_error(&string, error); } ds_put_hex_dump(&string, oh, len, 0, true); return ds_steal_cstr(&string); diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 8cf269a4..331a8fd5 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -756,9 +756,43 @@ ofputil_msg_type_code(const struct ofputil_msg_type *type) return type->code; } -/* Converts an OFPT_FLOW_MOD or NXT_FLOW_MOD message 'oh', received when the - * current flow format was 'flow_format', into an abstract flow_mod in 'fm'. - * Returns 0 if successful, otherwise an OpenFlow error code. +/* Flow formats. */ + +bool +ofputil_flow_format_is_valid(enum nx_flow_format flow_format) +{ + switch (flow_format) { + case NXFF_OPENFLOW10: + case NXFF_TUN_ID_FROM_COOKIE: + case NXFF_NXM: + return true; + } + + return false; +} + +const char * +ofputil_flow_format_to_string(enum nx_flow_format flow_format) +{ + switch (flow_format) { + case NXFF_OPENFLOW10: + return "openflow10"; + case NXFF_TUN_ID_FROM_COOKIE: + return "tun_id_from_cookie"; + case NXFF_NXM: + return "nxm"; + default: + NOT_REACHED(); + } +} + +/* Converts an OFPT_FLOW_MOD or NXT_FLOW_MOD message 'oh' into an abstract + * flow_mod in 'fm'. Returns 0 if successful, otherwise an OpenFlow error + * code. + * + * For OFPT_FLOW_MOD messages, 'flow_format' should be the current flow format + * at the time when the message was received. Otherwise 'flow_format' is + * ignored. * * Does not validate the flow_mod actions. */ int diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 4666a88f..f91e7622 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -112,6 +112,10 @@ void ofputil_cls_rule_to_match(const struct cls_rule *, enum nx_flow_format, void normalize_match(struct ofp_match *); char *ofp_match_to_literal_string(const struct ofp_match *match); +/* Flow formats. */ +bool ofputil_flow_format_is_valid(enum nx_flow_format); +const char *ofputil_flow_format_to_string(enum nx_flow_format); + /* Flow format independent flow_mod. */ struct flow_mod { struct cls_rule cr; -- 2.30.2