X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-print.c;h=e4d0303ee972ede28fc744d4e850785692046628;hb=2431be1b68d386bd616378d2c528242775c4d54a;hp=1d8b98ccabb2cc970fb05f49ed849debcdcb52fd;hpb=bbb8dee92d639331e8bd81823638267dcc895396;p=sliver-openvswitch.git diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 1d8b98cca..e4d0303ee 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -74,6 +74,10 @@ ofp_packet_to_string(const void *data, size_t len) struct udp_header *uh = buf.l4; ds_put_format(&ds, " udp_csum:%"PRIx16, ntohs(uh->udp_csum)); + } else if (flow.nw_proto == IPPROTO_SCTP) { + struct sctp_header *sh = buf.l4; + ds_put_format(&ds, " sctp_csum:%"PRIx32, + ntohl(sh->sctp_csum)); } } @@ -101,11 +105,11 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, ds_put_format(string, " table_id=%"PRIu8, pin.table_id); } - if (pin.cookie) { + if (pin.cookie != OVS_BE64_MAX) { ds_put_format(string, " cookie=0x%"PRIx64, ntohll(pin.cookie)); } - ds_put_format(string, " total_len=%"PRIu16" in_port=", pin.total_len); + ds_put_format(string, " total_len=%zu in_port=", pin.total_len); ofputil_format_port(pin.fmd.in_port, string); if (pin.fmd.tun_id != htonll(0)) { @@ -130,6 +134,10 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, } } + if (pin.fmd.pkt_mark != 0) { + ds_put_format(string, " pkt_mark=0x%"PRIx32, pin.fmd.pkt_mark); + } + ds_put_format(string, " (via %s)", ofputil_packet_in_reason_to_string(pin.reason, reasonbuf, sizeof reasonbuf)); @@ -177,7 +185,7 @@ ofp_print_packet_out(struct ds *string, const struct ofp_header *oh, ds_put_cstr(string, " in_port="); ofputil_format_port(po.in_port, string); - ds_put_char(string, ' '); + ds_put_cstr(string, " actions="); ofpacts_format(po.ofpacts, po.ofpacts_len, string); if (po.buffer_id == UINT32_MAX) { @@ -645,6 +653,8 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity) ds_put_cstr(&f, "tcp,"); } else if (om->nw_proto == IPPROTO_UDP) { ds_put_cstr(&f, "udp,"); + } else if (om->nw_proto == IPPROTO_SCTP) { + ds_put_cstr(&f, "sctp,"); } else { ds_put_cstr(&f, "ip,"); skip_proto = false; @@ -714,30 +724,23 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity) } static void -ofp_print_flow_flags(struct ds *s, uint16_t flags) +ofp_print_flow_flags(struct ds *s, enum ofputil_flow_mod_flags flags) { - if (flags & OFPFF_SEND_FLOW_REM) { + if (flags & OFPUTIL_FF_SEND_FLOW_REM) { ds_put_cstr(s, "send_flow_rem "); } - if (flags & OFPFF_CHECK_OVERLAP) { + if (flags & OFPUTIL_FF_CHECK_OVERLAP) { ds_put_cstr(s, "check_overlap "); } - if (flags & OFPFF12_RESET_COUNTS) { + if (flags & OFPUTIL_FF_RESET_COUNTS) { ds_put_cstr(s, "reset_counts "); } - if (flags & OFPFF13_NO_PKT_COUNTS) { + if (flags & OFPUTIL_FF_NO_PKT_COUNTS) { ds_put_cstr(s, "no_packet_counts "); } - if (flags & OFPFF13_NO_BYT_COUNTS) { + if (flags & OFPUTIL_FF_NO_BYT_COUNTS) { ds_put_cstr(s, "no_byte_counts "); } - - flags &= ~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP - | OFPFF12_RESET_COUNTS - | OFPFF13_NO_PKT_COUNTS | OFPFF13_NO_BYT_COUNTS); - if (flags) { - ds_put_format(s, "flags:0x%"PRIx16" ", flags); - } } static void @@ -814,7 +817,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity) if (ds_last(s) != ' ') { ds_put_char(s, ' '); } - if (fm.new_cookie != htonll(0) && fm.new_cookie != htonll(UINT64_MAX)) { + if (fm.new_cookie != htonll(0) && fm.new_cookie != OVS_BE64_MAX) { ds_put_format(s, "cookie:0x%"PRIx64" ", ntohll(fm.new_cookie)); } if (fm.cookie_mask != htonll(0)) { @@ -838,10 +841,16 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity) ofputil_format_port(fm.out_port, s); ds_put_char(s, ' '); } - if (fm.flags != 0) { - ofp_print_flow_flags(s, fm.flags); + + if (oh->version == OFP10_VERSION || oh->version == OFP11_VERSION) { + /* Don't print the reset_counts flag for OF1.0 and OF1.1 because those + * versions don't really have such a flag and printing one is likely to + * confuse people. */ + fm.flags &= ~OFPUTIL_FF_RESET_COUNTS; } + ofp_print_flow_flags(s, fm.flags); + ds_put_cstr(s, "actions="); ofpacts_format(fm.ofpacts, fm.ofpacts_len, s); ofpbuf_uninit(&ofpacts); } @@ -956,6 +965,49 @@ ofp_print_port_mod(struct ds *string, const struct ofp_header *oh) } } +static void +ofp_print_table_miss_config(struct ds *string, const uint32_t config) +{ + uint32_t table_miss_config = config & OFPTC11_TABLE_MISS_MASK; + + switch (table_miss_config) { + case OFPTC11_TABLE_MISS_CONTROLLER: + ds_put_cstr(string, "controller\n"); + break; + case OFPTC11_TABLE_MISS_CONTINUE: + ds_put_cstr(string, "continue\n"); + break; + case OFPTC11_TABLE_MISS_DROP: + ds_put_cstr(string, "drop\n"); + break; + default: + ds_put_cstr(string, "Unknown\n"); + break; + } +} + +static void +ofp_print_table_mod(struct ds *string, const struct ofp_header *oh) +{ + struct ofputil_table_mod pm; + enum ofperr error; + + error = ofputil_decode_table_mod(oh, &pm); + if (error) { + ofp_print_error(string, error); + return; + } + + if (pm.table_id == 0xff) { + ds_put_cstr(string, " table_id: ALL_TABLES"); + } else { + ds_put_format(string, " table_id=%"PRIu8, pm.table_id); + } + + ds_put_cstr(string, ", flow_miss_config="); + ofp_print_table_miss_config(string, pm.config); +} + static void ofp_print_meter_flags(struct ds *s, uint16_t flags) { @@ -1102,13 +1154,9 @@ ofputil_meter_capabilities_to_name(uint32_t bit) static const char * ofputil_meter_band_types_to_name(uint32_t bit) { - /* - * Note: Meter band types start from 1. We assume that the lowest bit - * in the band_types corresponds to DROP band type (1). - */ switch (bit) { - case 1 << (OFPMBT13_DROP - 1): return "drop"; - case 1 << (OFPMBT13_DSCP_REMARK - 1): return "dscp_remark"; + case 1 << OFPMBT13_DROP: return "drop"; + case 1 << OFPMBT13_DSCP_REMARK: return "dscp_remark"; } return NULL; @@ -1335,6 +1383,7 @@ ofp_print_flow_stats(struct ds *string, struct ofputil_flow_stats *fs) ds_put_char(string, ' '); } + ds_put_cstr(string, "actions="); ofpacts_format(fs->ofpacts, fs->ofpacts_len, string); } @@ -1737,9 +1786,17 @@ ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh, ofp_print_queue_name(string, qs.queue_id); ds_put_cstr(string, ": "); - print_port_stat(string, "bytes=", qs.stats.tx_bytes, 1); - print_port_stat(string, "pkts=", qs.stats.tx_packets, 1); - print_port_stat(string, "errors=", qs.stats.tx_errors, 0); + print_port_stat(string, "bytes=", qs.tx_bytes, 1); + print_port_stat(string, "pkts=", qs.tx_packets, 1); + print_port_stat(string, "errors=", qs.tx_errors, 1); + + ds_put_cstr(string, "duration="); + if (qs.duration_sec != UINT32_MAX) { + ofp_print_duration(string, qs.duration_sec, qs.duration_nsec); + } else { + ds_put_char(string, '?'); + } + ds_put_char(string, '\n'); } } @@ -2086,6 +2143,7 @@ ofp_print_nxst_flow_monitor_reply(struct ds *string, if (string->string[string->length - 1] != ' ') { ds_put_char(string, ' '); } + ds_put_cstr(string, "actions="); ofpacts_format(update.ofpacts, update.ofpacts_len, string); } } @@ -2128,6 +2186,201 @@ ofp_print_not_implemented(struct ds *string) ds_put_cstr(string, "NOT IMPLEMENTED YET!\n"); } +static void +ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, + struct list *p_buckets) +{ + static const char *type_str[] = { "all", "select", "indirect", + "ff", "unknown" }; + struct ofputil_bucket *bucket; + + ds_put_format(s, "group_id=%"PRIu32",type=%s", + group_id, type_str[type > 4 ? 4 : type]); + if (!p_buckets) { + return; + } + + LIST_FOR_EACH (bucket, list_node, p_buckets) { + ds_put_cstr(s, ",bucket="); + + if (bucket->weight != 1) { + ds_put_format(s, "weight:%"PRIu16",", bucket->weight); + } + if (bucket->watch_port != OFPP_NONE) { + ds_put_format(s, "watch_port:%"PRIu32",", bucket->watch_port); + } + if (bucket->watch_group != OFPG11_ANY) { + ds_put_format(s, "watch_group:%"PRIu32",", bucket->watch_group); + } + + ds_put_cstr(s, "actions="); + ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, s); + } +} + +static void +ofp_print_group_desc(struct ds *s, const struct ofp_header *oh) +{ + struct ofpbuf b; + + ofpbuf_use_const(&b, oh, ntohs(oh->length)); + for (;;) { + struct ofputil_group_desc gd; + int retval; + + retval = ofputil_decode_group_desc_reply(&gd, &b, oh->version); + if (retval) { + if (retval != EOF) { + ds_put_cstr(s, " ***parse error***"); + } + break; + } + + ds_put_char(s, '\n'); + ds_put_char(s, ' '); + ofp_print_group(s, gd.group_id, gd.type, &gd.buckets); + } +} + +static void +ofp_print_ofpst_group_request(struct ds *string, const struct ofp_header *oh) +{ + enum ofperr error; + uint32_t group_id; + + error = ofputil_decode_group_stats_request(oh, &group_id); + if (error) { + ofp_print_error(string, error); + return; + } + + ds_put_cstr(string, " group_id="); + ofputil_format_group(group_id, string); +} + +static void +ofp_print_group_stats(struct ds *s, const struct ofp_header *oh) +{ + struct ofpbuf b; + uint32_t bucket_i; + + ofpbuf_use_const(&b, oh, ntohs(oh->length)); + + for (;;) { + struct ofputil_group_stats gs; + int retval; + + retval = ofputil_decode_group_stats_reply(&b, &gs); + if (retval) { + if (retval != EOF) { + ds_put_cstr(s, " ***parse error***"); + } + break; + } + + ds_put_char(s, '\n'); + + ds_put_char(s, ' '); + ds_put_format(s, "group_id=%"PRIu32",", gs.group_id); + + if (gs.duration_sec != UINT32_MAX) { + ds_put_cstr(s, "duration="); + ofp_print_duration(s, gs.duration_sec, gs.duration_nsec); + ds_put_char(s, ','); + } + ds_put_format(s, "ref_count=%"PRIu32",", gs.ref_count); + ds_put_format(s, "packet_count=%"PRIu64",", gs.packet_count); + ds_put_format(s, "byte_count=%"PRIu64"", gs.byte_count); + + for (bucket_i = 0; bucket_i < gs.n_buckets; bucket_i++) { + if (gs.bucket_stats[bucket_i].packet_count != UINT64_MAX) { + ds_put_format(s, ",bucket%"PRIu32":", bucket_i); + ds_put_format(s, "packet_count=%"PRIu64",", gs.bucket_stats[bucket_i].packet_count); + ds_put_format(s, "byte_count=%"PRIu64"", gs.bucket_stats[bucket_i].byte_count); + } + } + + free(gs.bucket_stats); + } +} + +static void +ofp_print_group_features(struct ds *string, const struct ofp_header *oh) +{ + struct ofputil_group_features features; + + ofputil_decode_group_features_reply(oh, &features); + + ds_put_format(string, "\n Group table:\n"); + ds_put_format(string, " Types: 0x%"PRIx32"\n", features.types); + ds_put_format(string, " Capabilities: 0x%"PRIx32"\n", + features.capabilities); + + if (features.types & (1u << OFPGT11_ALL)) { + ds_put_format(string, " All group :\n"); + ds_put_format(string, + " max_groups = %#"PRIx32" actions=0x%08"PRIx32"\n", + features.max_groups[0], features.actions[0]); + } + + if (features.types & (1u << OFPGT11_SELECT)) { + ds_put_format(string, " Select group :\n"); + ds_put_format(string, " max_groups = %#"PRIx32" " + "actions=0x%08"PRIx32"\n", + features.max_groups[1], features.actions[1]); + } + + if (features.types & (1u << OFPGT11_INDIRECT)) { + ds_put_format(string, " Indirect group :\n"); + ds_put_format(string, " max_groups = %#"PRIx32" " + "actions=0x%08"PRIx32"\n", + features.max_groups[2], features.actions[2]); + } + + if (features.types & (1u << OFPGT11_FF)) { + ds_put_format(string, " Fast Failover group :\n"); + ds_put_format(string, " max_groups = %#"PRIx32" " + "actions=0x%08"PRIx32"\n", + features.max_groups[3], features.actions[3]); + } +} + +static void +ofp_print_group_mod(struct ds *s, const struct ofp_header *oh) +{ + struct ofputil_group_mod gm; + int error; + + error = ofputil_decode_group_mod(oh, &gm); + if (error) { + ofp_print_error(s, error); + return; + } + + ds_put_char(s, '\n'); + + ds_put_char(s, ' '); + switch (gm.command) { + case OFPGC11_ADD: + ds_put_cstr(s, "ADD"); + break; + + case OFPGC11_MODIFY: + ds_put_cstr(s, "MOD"); + break; + + case OFPGC11_DELETE: + ds_put_cstr(s, "DEL"); + break; + + default: + ds_put_format(s, "cmd:%"PRIu16"", gm.command); + } + ds_put_char(s, ' '); + + ofp_print_group(s, gm.group_id, gm.type, &gm.buckets); +} + static void ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, struct ds *string, int verbosity) @@ -2137,17 +2390,37 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, ofp_header_to_string__(oh, raw, string); switch (ofptype_from_ofpraw(raw)) { - /* FIXME: Change the following once they are implemented: */ - case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: - case OFPTYPE_QUEUE_GET_CONFIG_REPLY: - case OFPTYPE_GET_ASYNC_REQUEST: - case OFPTYPE_GET_ASYNC_REPLY: case OFPTYPE_GROUP_STATS_REQUEST: + ofp_print_stats_request(string, oh); + ofp_print_ofpst_group_request(string, oh); + break; + case OFPTYPE_GROUP_STATS_REPLY: + ofp_print_group_stats(string, oh); + break; + case OFPTYPE_GROUP_DESC_STATS_REQUEST: + ofp_print_stats_request(string, oh); + break; + case OFPTYPE_GROUP_DESC_STATS_REPLY: + ofp_print_group_desc(string, oh); + break; + case OFPTYPE_GROUP_FEATURES_STATS_REQUEST: + ofp_print_stats_request(string, oh); + break; + case OFPTYPE_GROUP_FEATURES_STATS_REPLY: + ofp_print_group_features(string, oh); + break; + + case OFPTYPE_GROUP_MOD: + ofp_print_group_mod(string, oh); + break; + + case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: + case OFPTYPE_QUEUE_GET_CONFIG_REPLY: case OFPTYPE_TABLE_FEATURES_STATS_REQUEST: case OFPTYPE_TABLE_FEATURES_STATS_REPLY: ofp_print_not_implemented(string); @@ -2205,6 +2478,10 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, ofp_print_port_mod(string, oh); break; + case OFPTYPE_TABLE_MOD: + ofp_print_table_mod(string, oh); + break; + case OFPTYPE_METER_MOD: ofp_print_meter_mod(string, oh); break; @@ -2319,10 +2596,12 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, ofp_print_nxt_set_controller_id(string, ofpmsg_body(oh)); break; + case OFPTYPE_GET_ASYNC_REPLY: case OFPTYPE_SET_ASYNC_CONFIG: ofp_print_nxt_set_async_config(string, ofpmsg_body(oh)); break; - + case OFPTYPE_GET_ASYNC_REQUEST: + break; case OFPTYPE_FLOW_MONITOR_CANCEL: ofp_print_nxt_flow_monitor_cancel(string, msg); break;