X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-print.c;h=f1eeebb44aa98b735128b3ffc4c13270839b9999;hb=0e553d9c1063be047824c6f1afce9ffc6db6c671;hp=7bc26c9ddc3541c91a8d285fc5faf93399332cf0;hpb=f0fd1a1772665ea57662281d9cccadb0f0146196;p=sliver-openvswitch.git diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 7bc26c9dd..f1eeebb44 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -33,6 +33,7 @@ #include "flow.h" #include "learn.h" #include "multipath.h" +#include "meta-flow.h" #include "nx-match.h" #include "ofp-errors.h" #include "ofp-util.h" @@ -79,6 +80,24 @@ ofp_packet_to_string(const void *data, size_t len) return ds_cstr(&ds); } +static const char * +ofp_packet_in_reason_to_string(enum ofp_packet_in_reason reason) +{ + static char s[32]; + + switch (reason) { + case OFPR_NO_MATCH: + return "no_match"; + case OFPR_ACTION: + return "action"; + case OFPR_INVALID_TTL: + return "invalid_ttl"; + default: + sprintf(s, "%d", (int) reason); + return s; + } +} + static void ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, int verbosity) @@ -120,20 +139,8 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, } } - switch (pin.reason) { - case OFPR_NO_MATCH: - ds_put_cstr(string, " (via no_match)"); - break; - case OFPR_ACTION: - ds_put_cstr(string, " (via action)"); - break; - case OFPR_INVALID_TTL: - ds_put_cstr(string, " (via invalid_ttl)"); - break; - default: - ds_put_format(string, " (***reason %"PRIu8"***)", pin.reason); - break; - } + ds_put_format(string, " (via %s)", + ofp_packet_in_reason_to_string(pin.reason)); ds_put_format(string, " data_len=%zu", pin.packet_len); if (pin.buffer_id == UINT32_MAX) { @@ -187,6 +194,8 @@ ofp_print_action(struct ds *s, const union ofp_action *a, const struct nx_action_multipath *nam; const struct nx_action_autopath *naa; const struct nx_action_output_reg *naor; + const struct nx_action_fin_timeout *naft; + struct mf_subfield subfield; uint16_t port; switch (code) { @@ -319,9 +328,8 @@ ofp_print_action(struct ds *s, const union ofp_action *a, case OFPUTIL_NXAST_AUTOPATH: naa = (const struct nx_action_autopath *)a; ds_put_format(s, "autopath(%u,", ntohl(naa->id)); - nxm_format_field_bits(s, ntohl(naa->dst), - nxm_decode_ofs(naa->ofs_nbits), - nxm_decode_n_bits(naa->ofs_nbits)); + nxm_decode(&subfield, naa->dst, naa->ofs_nbits); + mf_format_subfield(&subfield, s); ds_put_char(s, ')'); break; @@ -333,9 +341,8 @@ ofp_print_action(struct ds *s, const union ofp_action *a, case OFPUTIL_NXAST_OUTPUT_REG: naor = (const struct nx_action_output_reg *) a; ds_put_cstr(s, "output:"); - nxm_format_field_bits(s, ntohl(naor->src), - nxm_decode_ofs(naor->ofs_nbits), - nxm_decode_n_bits(naor->ofs_nbits)); + nxm_decode(&subfield, naor->src, naor->ofs_nbits); + mf_format_subfield(&subfield, s); break; case OFPUTIL_NXAST_LEARN: @@ -350,6 +357,21 @@ ofp_print_action(struct ds *s, const union ofp_action *a, ds_put_cstr(s, "exit"); break; + case OFPUTIL_NXAST_FIN_TIMEOUT: + naft = (const struct nx_action_fin_timeout *) a; + ds_put_cstr(s, "fin_timeout("); + if (naft->fin_idle_timeout) { + ds_put_format(s, "idle_timeout=%"PRIu16",", + ntohs(naft->fin_idle_timeout)); + } + if (naft->fin_hard_timeout) { + ds_put_format(s, "hard_timeout=%"PRIu16",", + ntohs(naft->fin_hard_timeout)); + } + ds_chomp(s, ','); + ds_put_char(s, ')'); + break; + default: break; } @@ -388,36 +410,31 @@ static void ofp_print_packet_out(struct ds *string, const struct ofp_packet_out *opo, int verbosity) { - size_t len = ntohs(opo->header.length); - size_t actions_len = ntohs(opo->actions_len); - - ds_put_cstr(string, " in_port="); - ofputil_format_port(ntohs(opo->in_port), string); + struct ofputil_packet_out po; + enum ofperr error; - ds_put_format(string, " actions_len=%zu ", actions_len); - if (actions_len > (ntohs(opo->header.length) - sizeof *opo)) { - ds_put_format(string, "***packet too short for action length***\n"); + error = ofputil_decode_packet_out(&po, opo); + if (error) { + ofp_print_error(string, error); return; } - if (actions_len % sizeof(union ofp_action)) { - ds_put_format(string, "***action length not a multiple of %zu***\n", - sizeof(union ofp_action)); - } - ofp_print_actions(string, (const union ofp_action *) opo->actions, - actions_len / sizeof(union ofp_action)); - if (ntohl(opo->buffer_id) == UINT32_MAX) { - int data_len = len - sizeof *opo - actions_len; - ds_put_format(string, " data_len=%d", data_len); - if (verbosity > 0 && len > sizeof *opo) { - char *packet = ofp_packet_to_string( - (uint8_t *) opo->actions + actions_len, data_len); + ds_put_cstr(string, " in_port="); + ofputil_format_port(po.in_port, string); + + ds_put_char(string, ' '); + ofp_print_actions(string, po.actions, po.n_actions); + + if (po.buffer_id == UINT32_MAX) { + ds_put_format(string, " data_len=%zu", po.packet_len); + if (verbosity > 0 && po.packet_len > 0) { + char *packet = ofp_packet_to_string(po.packet, po.packet_len); ds_put_char(string, '\n'); ds_put_cstr(string, packet); free(packet); } } else { - ds_put_format(string, " buffer=0x%08"PRIx32, ntohl(opo->buffer_id)); + ds_put_format(string, " buffer=0x%08"PRIx32, po.buffer_id); } ds_put_char(string, '\n'); } @@ -841,7 +858,22 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, ds_put_format(s, "buf:0x%"PRIx32" ", fm.buffer_id); } if (fm.flags != 0) { - ds_put_format(s, "flags:0x%"PRIx16" ", fm.flags); + uint16_t flags = fm.flags; + + if (flags & OFPFF_SEND_FLOW_REM) { + ds_put_cstr(s, "send_flow_rem "); + } + if (flags & OFPFF_CHECK_OVERLAP) { + ds_put_cstr(s, "check_overlap "); + } + if (flags & OFPFF_EMERG) { + ds_put_cstr(s, "emerg "); + } + + flags &= ~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG); + if (flags) { + ds_put_format(s, "flags:0x%"PRIx16" ", flags); + } } ofp_print_actions(s, fm.actions, fm.n_actions); @@ -860,6 +892,24 @@ ofp_print_duration(struct ds *string, unsigned int sec, unsigned int nsec) ds_put_char(string, 's'); } +static const char * +ofp_flow_removed_reason_to_string(enum ofp_flow_removed_reason reason) +{ + static char s[32]; + + switch (reason) { + case OFPRR_IDLE_TIMEOUT: + return "idle"; + case OFPRR_HARD_TIMEOUT: + return "hard"; + case OFPRR_DELETE: + return "delete"; + default: + sprintf(s, "%d", (int) reason); + return s; + } +} + static void ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh) { @@ -875,21 +925,8 @@ ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh) ds_put_char(string, ' '); cls_rule_format(&fr.rule, string); - ds_put_cstr(string, " reason="); - switch (fr.reason) { - case OFPRR_IDLE_TIMEOUT: - ds_put_cstr(string, "idle"); - break; - case OFPRR_HARD_TIMEOUT: - ds_put_cstr(string, "hard"); - break; - case OFPRR_DELETE: - ds_put_cstr(string, "delete"); - break; - default: - ds_put_format(string, "**%"PRIu8"**", fr.reason); - break; - } + ds_put_format(string, " reason=%s", + ofp_flow_removed_reason_to_string(fr.reason)); if (fr.cookie != htonll(0)) { ds_put_format(string, " cookie:0x%"PRIx64, ntohll(fr.cookie)); @@ -1022,7 +1059,7 @@ ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh) struct ofputil_flow_stats fs; int retval; - retval = ofputil_decode_flow_stats_reply(&fs, &b); + retval = ofputil_decode_flow_stats_reply(&fs, &b, true); if (retval) { if (retval != EOF) { ds_put_cstr(string, " ***parse error***"); @@ -1044,6 +1081,12 @@ ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh) if (fs.hard_timeout != OFP_FLOW_PERMANENT) { ds_put_format(string, "hard_timeout=%"PRIu16",", fs.hard_timeout); } + if (fs.idle_age >= 0) { + ds_put_format(string, "idle_age=%d,", fs.idle_age); + } + if (fs.hard_age >= 0 && fs.hard_age != fs.duration_sec) { + ds_put_format(string, "hard_age=%d,", fs.hard_age); + } cls_rule_format(&fs.rule, string); if (string->string[string->length - 1] != ' ') { @@ -1297,6 +1340,75 @@ ofp_print_nxt_set_packet_in_format(struct ds *string, } } +static const char * +ofp_port_reason_to_string(enum ofp_port_reason reason) +{ + static char s[32]; + + switch (reason) { + case OFPPR_ADD: + return "add"; + + case OFPPR_DELETE: + return "delete"; + + case OFPPR_MODIFY: + return "modify"; + + default: + sprintf(s, "%d", (int) reason); + return s; + } +} + +static void +ofp_print_nxt_set_async_config(struct ds *string, + const struct nx_async_config *nac) +{ + int i; + + for (i = 0; i < 2; i++) { + int j; + + 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)) { + ds_put_format(string, " %s", + ofp_packet_in_reason_to_string(j)); + } + } + 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)) { + ds_put_format(string, " %s", ofp_port_reason_to_string(j)); + } + } + 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)) { + ds_put_format(string, " %s", + ofp_flow_removed_reason_to_string(j)); + } + } + if (!nac->flow_removed_mask[i]) { + ds_put_cstr(string, " (off)"); + } + ds_put_char(string, '\n'); + } +} + static void ofp_to_string__(const struct ofp_header *oh, const struct ofputil_msg_type *type, struct ds *string, @@ -1362,6 +1474,7 @@ ofp_to_string__(const struct ofp_header *oh, break; case OFPUTIL_OFPT_FLOW_MOD: + case OFPUTIL_NXT_FLOW_MOD: ofp_print_flow_mod(string, msg, code, verbosity); break; @@ -1452,8 +1565,11 @@ ofp_to_string__(const struct ofp_header *oh, ofp_print_nxt_set_packet_in_format(string, msg); break; - case OFPUTIL_NXT_FLOW_MOD: - ofp_print_flow_mod(string, msg, code, verbosity); + case OFPUTIL_NXT_FLOW_AGE: + break; + + case OFPUTIL_NXT_SET_ASYNC_CONFIG: + ofp_print_nxt_set_async_config(string, msg); break; case OFPUTIL_NXST_AGGREGATE_REPLY: