X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Fofp-print.c;h=271b095b7f250c7a5a7cef97a1a5e047666246be;hb=6c6eedc5d6730835a0d9724e2e8cfe9cdf03b07d;hp=2ac11b1ea394996ebacfd52cf20b83235b129c37;hpb=f695ebfae56c981332b9030b9ed905f90de8b0c5;p=cascardo%2Fovs.git diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 2ac11b1ea..271b095b7 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,9 +52,6 @@ static void ofp_print_queue_name(struct ds *string, uint32_t port); static void ofp_print_error(struct ds *, enum ofperr); -static void ofp_print_table_features(struct ds *, - const struct ofputil_table_features *, - const struct ofputil_table_stats *); /* Returns a string that represents the contents of the Ethernet frame in the * 'len' bytes starting at 'data'. The caller must free the returned string.*/ @@ -97,58 +94,119 @@ ofp_packet_to_string(const void *data, size_t len) return ds_cstr(&ds); } +static void +format_hex_arg(struct ds *s, const uint8_t *data, size_t len) +{ + for (size_t i = 0; i < len; i++) { + if (i) { + ds_put_char(s, '.'); + } + ds_put_format(s, "%02"PRIx8, data[i]); + } +} + static void ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, int verbosity) { char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE]; - struct ofputil_packet_in pin; - int error; + struct ofputil_packet_in_private pin; + const struct ofputil_packet_in *public = &pin.public; + uint32_t buffer_id; + size_t total_len; + enum ofperr error; - error = ofputil_decode_packet_in(&pin, oh); + error = ofputil_decode_packet_in_private(oh, true, + &pin, &total_len, &buffer_id); if (error) { ofp_print_error(string, error); return; } - if (pin.table_id) { - ds_put_format(string, " table_id=%"PRIu8, pin.table_id); + if (public->table_id) { + ds_put_format(string, " table_id=%"PRIu8, public->table_id); } - if (pin.cookie != OVS_BE64_MAX) { - ds_put_format(string, " cookie=0x%"PRIx64, ntohll(pin.cookie)); + if (public->cookie != OVS_BE64_MAX) { + ds_put_format(string, " cookie=0x%"PRIx64, ntohll(public->cookie)); } - ds_put_format(string, " total_len=%"PRIuSIZE" ", pin.total_len); + ds_put_format(string, " total_len=%"PRIuSIZE" ", total_len); - match_format(&pin.flow_metadata, string, OFP_DEFAULT_PRIORITY); + match_format(&public->flow_metadata, string, OFP_DEFAULT_PRIORITY); ds_put_format(string, " (via %s)", - ofputil_packet_in_reason_to_string(pin.reason, reasonbuf, + ofputil_packet_in_reason_to_string(public->reason, + reasonbuf, sizeof reasonbuf)); - ds_put_format(string, " data_len=%"PRIuSIZE, pin.packet_len); - if (pin.buffer_id == UINT32_MAX) { + ds_put_format(string, " data_len=%"PRIuSIZE, public->packet_len); + if (buffer_id == UINT32_MAX) { ds_put_format(string, " (unbuffered)"); - if (pin.total_len != pin.packet_len) { + if (total_len != public->packet_len) { ds_put_format(string, " (***total_len != data_len***)"); } } else { - ds_put_format(string, " buffer=0x%08"PRIx32, pin.buffer_id); - if (pin.total_len < pin.packet_len) { + ds_put_format(string, " buffer=0x%08"PRIx32, buffer_id); + if (total_len < public->packet_len) { ds_put_format(string, " (***total_len < data_len***)"); } } ds_put_char(string, '\n'); + if (public->userdata_len) { + ds_put_cstr(string, " userdata="); + format_hex_arg(string, pin.public.userdata, pin.public.userdata_len); + ds_put_char(string, '\n'); + } + + if (!uuid_is_zero(&pin.bridge)) { + ds_put_format(string, " continuation.bridge="UUID_FMT"\n", + UUID_ARGS(&pin.bridge)); + } + + if (pin.n_stack) { + ds_put_cstr(string, " continuation.stack="); + for (size_t i = 0; i < pin.n_stack; i++) { + if (i) { + ds_put_char(string, ' '); + } + mf_subvalue_format(&pin.stack[i], string); + } + } + + if (pin.mirrors) { + ds_put_format(string, " continuation.mirrors=0x%"PRIx32"\n", + pin.mirrors); + } + + if (pin.conntracked) { + ds_put_cstr(string, " continuation.conntracked=true\n"); + } + + if (pin.actions_len) { + ds_put_cstr(string, " continuation.actions="); + ofpacts_format(pin.actions, pin.actions_len, string); + ds_put_char(string, '\n'); + } + + if (pin.action_set_len) { + ds_put_cstr(string, " continuation.action_set="); + ofpacts_format(pin.action_set, pin.action_set_len, string); + ds_put_char(string, '\n'); + } + if (verbosity > 0) { - char *packet = ofp_packet_to_string(pin.packet, pin.packet_len); + char *packet = ofp_packet_to_string(public->packet, + public->packet_len); ds_put_cstr(string, packet); free(packet); } if (verbosity > 2) { - ds_put_hex_dump(string, pin.packet, pin.packet_len, 0, false); + ds_put_hex_dump(string, public->packet, public->packet_len, 0, false); } + + ofputil_packet_in_private_destroy(&pin); } static void @@ -455,10 +513,8 @@ static void ofp_print_switch_features(struct ds *string, const struct ofp_header *oh) { struct ofputil_switch_features features; - enum ofperr error; - struct ofpbuf b; - - error = ofputil_decode_switch_features(oh, &features, &b); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); + enum ofperr error = ofputil_pull_switch_features(&b, &features); if (error) { ofp_print_error(string, error); return; @@ -499,25 +555,39 @@ ofp_print_switch_features(struct ds *string, const struct ofp_header *oh) } static void -ofp_print_switch_config(struct ds *string, const struct ofp_switch_config *osc) +ofp_print_switch_config(struct ds *string, + const struct ofputil_switch_config *config) { - enum ofp_config_flags flags; + ds_put_format(string, " frags=%s", + ofputil_frag_handling_to_string(config->frag)); - flags = ntohs(osc->flags); - - ds_put_format(string, " frags=%s", ofputil_frag_handling_to_string(flags)); - flags &= ~OFPC_FRAG_MASK; - - if (flags & OFPC_INVALID_TTL_TO_CONTROLLER) { + if (config->invalid_ttl_to_controller > 0) { ds_put_format(string, " invalid_ttl_to_controller"); - flags &= ~OFPC_INVALID_TTL_TO_CONTROLLER; } - if (flags) { - ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***", flags); + ds_put_format(string, " miss_send_len=%"PRIu16"\n", config->miss_send_len); +} + +static void +ofp_print_set_config(struct ds *string, const struct ofp_header *oh) +{ + struct ofputil_switch_config config; + enum ofperr error; + + error = ofputil_decode_set_config(oh, &config); + if (error) { + ofp_print_error(string, error); + return; } + ofp_print_switch_config(string, &config); +} - ds_put_format(string, " miss_send_len=%"PRIu16"\n", ntohs(osc->miss_send_len)); +static void +ofp_print_get_config_reply(struct ds *string, const struct ofp_header *oh) +{ + struct ofputil_switch_config config; + ofputil_decode_get_config_reply(oh, &config); + ofp_print_switch_config(string, &config); } static void print_wild(struct ds *string, const char *leader, int is_wild, @@ -923,7 +993,7 @@ ofp_print_port_mod(struct ds *string, const struct ofp_header *oh) return; } - ds_put_cstr(string, "port: "); + ds_put_cstr(string, " port: "); ofputil_format_port(pm.port_no, string); ds_put_format(string, ": addr:"ETH_ADDR_FMT"\n", ETH_ADDR_ARGS(pm.hw_addr)); @@ -942,26 +1012,69 @@ ofp_print_port_mod(struct ds *string, const struct ofp_header *oh) } } -static void -ofp_print_table_miss_config(struct ds *string, enum ofputil_table_miss miss) +static const char * +ofputil_table_miss_to_string(enum ofputil_table_miss miss) { switch (miss) { - case OFPUTIL_TABLE_MISS_CONTROLLER: - ds_put_cstr(string, "controller\n"); - break; - case OFPUTIL_TABLE_MISS_CONTINUE: - ds_put_cstr(string, "continue\n"); - break; - case OFPUTIL_TABLE_MISS_DROP: - ds_put_cstr(string, "drop\n"); - break; - case OFPUTIL_TABLE_MISS_DEFAULT: - default: - ds_put_format(string, "Unknown (%d)\n", miss); - break; + case OFPUTIL_TABLE_MISS_DEFAULT: return "default"; + case OFPUTIL_TABLE_MISS_CONTROLLER: return "controller"; + case OFPUTIL_TABLE_MISS_CONTINUE: return "continue"; + case OFPUTIL_TABLE_MISS_DROP: return "drop"; + default: return "***error***"; } } +static const char * +ofputil_table_eviction_to_string(enum ofputil_table_eviction eviction) +{ + switch (eviction) { + case OFPUTIL_TABLE_EVICTION_DEFAULT: return "default"; + case OFPUTIL_TABLE_EVICTION_ON: return "on"; + case OFPUTIL_TABLE_EVICTION_OFF: return "off"; + default: return "***error***"; + } + +} + +static const char * +ofputil_eviction_flag_to_string(uint32_t bit) +{ + enum ofp14_table_mod_prop_eviction_flag eviction_flag = bit; + + switch (eviction_flag) { + case OFPTMPEF14_OTHER: return "OTHER"; + case OFPTMPEF14_IMPORTANCE: return "IMPORTANCE"; + case OFPTMPEF14_LIFETIME: return "LIFETIME"; + } + + return NULL; +} + +/* Appends to 'string' a description of the bitmap of OFPTMPEF14_* values in + * 'eviction_flags'. */ +static void +ofputil_put_eviction_flags(struct ds *string, uint32_t eviction_flags) +{ + if (eviction_flags != UINT32_MAX) { + ofp_print_bit_names(string, eviction_flags, + ofputil_eviction_flag_to_string, '|'); + } else { + ds_put_cstr(string, "(default)"); + } +} + +static const char * +ofputil_table_vacancy_to_string(enum ofputil_table_vacancy vacancy) +{ + switch (vacancy) { + case OFPUTIL_TABLE_VACANCY_DEFAULT: return "default"; + case OFPUTIL_TABLE_VACANCY_ON: return "on"; + case OFPUTIL_TABLE_VACANCY_OFF: return "off"; + default: return "***error***"; + } + +} + static void ofp_print_table_mod(struct ds *string, const struct ofp_header *oh) { @@ -980,10 +1093,72 @@ ofp_print_table_mod(struct ds *string, const struct ofp_header *oh) ds_put_format(string, " table_id=%"PRIu8, pm.table_id); } - if (pm.miss_config != OFPUTIL_TABLE_MISS_DEFAULT) { - ds_put_cstr(string, ", flow_miss_config="); - ofp_print_table_miss_config(string, pm.miss_config); + if (pm.miss != OFPUTIL_TABLE_MISS_DEFAULT) { + ds_put_format(string, ", flow_miss_config=%s", + ofputil_table_miss_to_string(pm.miss)); + } + if (pm.eviction != OFPUTIL_TABLE_EVICTION_DEFAULT) { + ds_put_format(string, ", eviction=%s", + ofputil_table_eviction_to_string(pm.eviction)); + } + if (pm.eviction_flags != UINT32_MAX) { + ds_put_cstr(string, "eviction_flags="); + ofputil_put_eviction_flags(string, pm.eviction_flags); + } + if (pm.vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) { + ds_put_format(string, ", vacancy=%s", + ofputil_table_vacancy_to_string(pm.vacancy)); + if (pm.vacancy == OFPUTIL_TABLE_VACANCY_ON) { + ds_put_format(string, " vacancy:%"PRIu8"" + ",%"PRIu8"", pm.table_vacancy.vacancy_down, + pm.table_vacancy.vacancy_up); + } + } +} + +/* This function will print the Table description properties. */ +static void +ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td) +{ + ds_put_format(string, "\n table %"PRIu8, td->table_id); + ds_put_cstr(string, ":\n"); + ds_put_format(string, " eviction=%s eviction_flags=", + ofputil_table_eviction_to_string(td->eviction)); + ofputil_put_eviction_flags(string, td->eviction_flags); + ds_put_char(string, '\n'); + ds_put_format(string, " vacancy=%s", + ofputil_table_vacancy_to_string(td->vacancy)); + if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) { + ds_put_format(string, " vacancy_down=%"PRIu8"%%", + td->table_vacancy.vacancy_down); + ds_put_format(string, " vacancy_up=%"PRIu8"%%", + td->table_vacancy.vacancy_up); + ds_put_format(string, " vacancy=%"PRIu8"%%", + td->table_vacancy.vacancy); } + ds_put_char(string, '\n'); +} + +static void +ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh) +{ + struct ofputil_table_status ts; + enum ofperr error; + + error = ofputil_decode_table_status(oh, &ts); + if (error) { + ofp_print_error(string, error); + return; + } + + if (ts.reason == OFPTR_VACANCY_DOWN) { + ds_put_format(string, " reason=VACANCY_DOWN"); + } else if (ts.reason == OFPTR_VACANCY_UP) { + ds_put_format(string, " reason=VACANCY_UP"); + } + + ds_put_format(string, "\ntable_desc:-"); + ofp_print_table_desc(string, &ts.desc); } static void @@ -992,8 +1167,9 @@ ofp_print_queue_get_config_request(struct ds *string, { enum ofperr error; ofp_port_t port; + uint32_t queue; - error = ofputil_decode_queue_get_config_request(oh, &port); + error = ofputil_decode_queue_get_config_request(oh, &port, &queue); if (error) { ofp_print_error(string, error); return; @@ -1001,6 +1177,11 @@ ofp_print_queue_get_config_request(struct ds *string, ds_put_cstr(string, " port="); ofputil_format_port(port, string); + + if (queue != OFPQ_ALL) { + ds_put_cstr(string, " queue="); + ofp_print_queue_name(string, queue); + } } static void @@ -1017,21 +1198,10 @@ static void ofp_print_queue_get_config_reply(struct ds *string, const struct ofp_header *oh) { - enum ofperr error; - struct ofpbuf b; - ofp_port_t port; - - ofpbuf_use_const(&b, oh, ntohs(oh->length)); - error = ofputil_decode_queue_get_config_reply(&b, &port); - if (error) { - ofp_print_error(string, error); - return; - } - - ds_put_cstr(string, " port="); - ofputil_format_port(port, string); - ds_put_char(string, '\n'); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); + ofp_port_t port = 0; + ds_put_char(string, ' '); for (;;) { struct ofputil_queue_config queue; int retval; @@ -1041,10 +1211,19 @@ ofp_print_queue_get_config_reply(struct ds *string, if (retval != EOF) { ofp_print_error(string, retval); } + ds_chomp(string, ' '); break; } - ds_put_format(string, "queue %"PRIu32":", queue.queue_id); + if (queue.port != port) { + port = queue.port; + + ds_put_cstr(string, "port="); + ofputil_format_port(port, string); + ds_put_char(string, '\n'); + } + + ds_put_format(string, "queue %"PRIu32":", queue.queue); print_queue_rate(string, "min_rate", queue.min_rate); print_queue_rate(string, "max_rate", queue.max_rate); ds_put_char(string, '\n'); @@ -1137,21 +1316,9 @@ ofp_print_meter_config(struct ds *s, const struct ofputil_meter_config *mc) } static void -ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh) +ofp_print_meter_mod__(struct ds *s, const struct ofputil_meter_mod *mm) { - struct ofputil_meter_mod mm; - struct ofpbuf bands; - enum ofperr error; - - ofpbuf_init(&bands, 64); - error = ofputil_decode_meter_mod(oh, &mm, &bands); - if (error) { - ofpbuf_uninit(&bands); - ofp_print_error(s, error); - return; - } - - switch (mm.command) { + switch (mm->command) { case OFPMC13_ADD: ds_put_cstr(s, " ADD "); break; @@ -1162,10 +1329,26 @@ ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh) ds_put_cstr(s, " DEL "); break; default: - ds_put_format(s, " cmd:%d ", mm.command); + ds_put_format(s, " cmd:%d ", mm->command); } - ofp_print_meter_config(s, &mm.meter); + ofp_print_meter_config(s, &mm->meter); +} + +static void +ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh) +{ + struct ofputil_meter_mod mm; + struct ofpbuf bands; + enum ofperr error; + + ofpbuf_init(&bands, 64); + error = ofputil_decode_meter_mod(oh, &mm, &bands); + if (error) { + ofp_print_error(s, error); + } else { + ofp_print_meter_mod__(s, &mm); + } ofpbuf_uninit(&bands); } @@ -1230,10 +1413,9 @@ ofp_print_meter_features_reply(struct ds *s, const struct ofp_header *oh) static void ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh) { + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); struct ofpbuf bands; - struct ofpbuf b; - ofpbuf_use_const(&b, oh, ntohs(oh->length)); ofpbuf_init(&bands, 64); for (;;) { struct ofputil_meter_config mc; @@ -1255,10 +1437,9 @@ ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh) static void ofp_print_meter_stats_reply(struct ds *s, const struct ofp_header *oh) { + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); struct ofpbuf bands; - struct ofpbuf b; - ofpbuf_use_const(&b, oh, ntohs(oh->length)); ofpbuf_init(&bands, 64); for (;;) { struct ofputil_meter_stats ms; @@ -1437,10 +1618,9 @@ ofp_print_flow_stats(struct ds *string, struct ofputil_flow_stats *fs) static void ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh) { + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); struct ofpbuf ofpacts; - struct ofpbuf b; - ofpbuf_use_const(&b, oh, ntohs(oh->length)); ofpbuf_init(&ofpacts, 64); for (;;) { struct ofputil_flow_stats fs; @@ -1512,14 +1692,12 @@ static void ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, int verbosity) { - struct ofpbuf b; - ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh)); if (verbosity < 1) { return; } - ofpbuf_use_const(&b, oh, ntohs(oh->length)); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { struct ofputil_port_stats ps; int retval; @@ -1565,12 +1743,12 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, static void ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh) { - struct ofpbuf b; - - ofpbuf_use_const(&b, oh, ntohs(oh->length)); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); ofpraw_pull_assert(&b); - for (;;) { + struct ofputil_table_features prev_features; + struct ofputil_table_stats prev_stats; + for (int i = 0;; i++) { struct ofputil_table_features features; struct ofputil_table_stats stats; int retval; @@ -1583,7 +1761,12 @@ ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh) return; } - ofp_print_table_features(string, &features, &stats); + ds_put_char(string, '\n'); + ofp_print_table_features(string, + &features, i ? &prev_features : NULL, + &stats, i ? &prev_stats : NULL); + prev_features = features; + prev_stats = stats; } } @@ -1609,7 +1792,7 @@ ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh) return; } - ds_put_cstr(string, "port="); + ds_put_cstr(string, " port="); ofputil_format_port(oqsr.port_no, string); ds_put_cstr(string, " queue="); @@ -1620,14 +1803,12 @@ static void ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh, int verbosity) { - struct ofpbuf b; - ds_put_format(string, " %"PRIuSIZE" queues\n", ofputil_count_queue_stats(oh)); if (verbosity < 1) { return; } - ofpbuf_use_const(&b, oh, ntohs(oh->length)); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { struct ofputil_queue_stats qs; int retval; @@ -1681,9 +1862,7 @@ static void ofp_print_ofpst_port_desc_reply(struct ds *string, const struct ofp_header *oh) { - struct ofpbuf b; - - ofpbuf_use_const(&b, oh, ntohs(oh->length)); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); ofpraw_pull_assert(&b); ds_put_char(string, '\n'); ofp_print_phy_ports(string, oh->version, &b); @@ -1788,6 +1967,7 @@ ofp_print_role_status_message(struct ds *string, const struct ofp_header *oh) case OFPCRR_EXPERIMENTER: ds_put_cstr(string, "experimenter_data_changed"); break; + case OFPCRR_N_REASONS: default: OVS_NOT_REACHED(); } @@ -1846,70 +2026,149 @@ ofp_port_reason_to_string(enum ofp_port_reason reason, case OFPPR_MODIFY: return "modify"; + case OFPPR_N_REASONS: default: snprintf(reasonbuf, bufsize, "%d", (int) reason); return reasonbuf; } } -static void -ofp_print_nxt_set_async_config(struct ds *string, - const struct nx_async_config *nac) +/* 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) { - int i; + switch (reason) { + case OFPCRR_MASTER_REQUEST: + return "master_request"; - for (i = 0; i < 2; i++) { - int j; + case OFPCRR_CONFIG: + return "configuration_changed"; - ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave"); + case OFPCRR_EXPERIMENTER: + return "experimenter_data_changed"; - 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; + case OFPCRR_N_REASONS: + default: + snprintf(reasonbuf, bufsize, "%d", (int) reason); + return reasonbuf; + } +} - reason = ofputil_packet_in_reason_to_string(j, reasonbuf, - sizeof reasonbuf); - ds_put_format(string, " %s", reason); - } - } - if (!nac->packet_in_mask[i]) { - ds_put_cstr(string, " (off)"); - } - ds_put_char(string, '\n'); +/* 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"; - 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; + case OFPTR_VACANCY_UP: + return "vacancy_up"; - 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'); + 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"; + + case OFPRFR_N_REASONS: + 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); - 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; + case OAM_REQUESTFORWARD: + return ofp_requestforward_reason_to_string(reason, reasonbuf, bufsize); - reason = ofp_flow_removed_reason_to_string(j, reasonbuf, - sizeof reasonbuf); - ds_put_format(string, " %s", reason); + 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_set_async_config(struct ds *string, const struct ofp_header *oh, + enum ofptype type) +{ + struct ofputil_async_cfg basis = OFPUTIL_ASYNC_CFG_INIT; + struct ofputil_async_cfg ac; + + bool is_reply = type == OFPTYPE_GET_ASYNC_REPLY; + enum ofperr error = ofputil_decode_set_async_config(oh, is_reply, + &basis, &ac); + if (error) { + ofp_print_error(string, error); + return; + } + + for (int i = 0; i < 2; i++) { + ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave"); + for (uint32_t type = 0; type < OAM_N_TYPES; type++) { + ds_put_format(string, "%16s:", + ofputil_async_msg_type_to_string(type)); + + uint32_t role = i == 0 ? ac.master[type] : ac.slave[type]; + for (int j = 0; j < 32; j++) { + if (role & (1u << j)) { + char reasonbuf[OFP_ASYNC_CONFIG_REASON_BUFSIZE]; + const char *reason; + + reason = ofp_async_config_reason_to_string( + j, type, reasonbuf, sizeof reasonbuf); + if (reason[0]) { + ds_put_format(string, " %s", reason); + } + } } + if (!role) { + ds_put_cstr(string, " (off)"); + } + ds_put_char(string, '\n'); } - if (!nac->flow_removed_mask[i]) { - ds_put_cstr(string, " (off)"); - } - ds_put_char(string, '\n'); } } @@ -1949,9 +2208,7 @@ static void ofp_print_nxst_flow_monitor_request(struct ds *string, const struct ofp_header *oh) { - struct ofpbuf b; - - ofpbuf_use_const(&b, oh, ntohs(oh->length)); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { struct ofputil_flow_monitor_request request; int retval; @@ -1988,11 +2245,9 @@ ofp_print_nxst_flow_monitor_reply(struct ds *string, const struct ofp_header *oh) { uint64_t ofpacts_stub[1024 / 8]; - struct ofpbuf ofpacts; - struct ofpbuf b; + struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); - ofpbuf_use_const(&b, oh, ntohs(oh->length)); - ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub); for (;;) { char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE]; struct ofputil_flow_update update; @@ -2122,7 +2377,8 @@ ofp_print_bucket_id(struct ds *s, const char *label, uint32_t bucket_id, static void ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, - struct ovs_list *p_buckets, struct ofputil_group_props *props, + const struct ovs_list *p_buckets, + const struct ofputil_group_props *props, enum ofp_version ofp_version, bool suppress_type) { struct ofputil_bucket *bucket; @@ -2136,22 +2392,20 @@ ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, } if (props->selection_method[0]) { - size_t mark, start; - - ds_put_format(s, ",selection_method=%s,", props->selection_method); + ds_put_format(s, ",selection_method=%s", props->selection_method); if (props->selection_method_param) { - ds_put_format(s, "selection_method_param=%"PRIu64",", + ds_put_format(s, ",selection_method_param=%"PRIu64, props->selection_method_param); } - /* Allow rewinding to immediately before the trailing ',' */ - mark = s->length - 1; - - ds_put_cstr(s, "fields="); - start = s->length; - oxm_format_field_array(s, &props->fields); - if (s->length == start) { - ds_truncate(s, mark); + size_t n = bitmap_count1(props->fields.used.bm, MFF_N_IDS); + if (n == 1) { + ds_put_cstr(s, ",fields="); + oxm_format_field_array(s, &props->fields); + } else if (n > 1) { + ds_put_cstr(s, ",fields("); + oxm_format_field_array(s, &props->fields); + ds_put_char(s, ')'); } } @@ -2165,13 +2419,13 @@ ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, ds_put_cstr(s, "bucket="); ofp_print_bucket_id(s, "bucket_id:", bucket->bucket_id, ofp_version); - if (bucket->weight != 1) { + if (bucket->weight != (type == OFPGT11_SELECT ? 1 : 0)) { 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) { + if (bucket->watch_group != OFPG_ANY) { ds_put_format(s, "watch_group:%"PRIu32",", bucket->watch_group); } @@ -2195,9 +2449,7 @@ ofp_print_ofpst_group_desc_request(struct ds *string, 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)); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { struct ofputil_group_desc gd; int retval; @@ -2237,11 +2489,7 @@ ofp_print_ofpst_group_request(struct ds *string, const struct ofp_header *oh) 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)); - + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { struct ofputil_group_stats gs; int retval; @@ -2268,7 +2516,7 @@ ofp_print_group_stats(struct ds *s, const struct ofp_header *oh) 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++) { + for (uint32_t 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); @@ -2318,22 +2566,15 @@ ofp_print_group_features(struct ds *string, const struct ofp_header *oh) } static void -ofp_print_group_mod(struct ds *s, const struct ofp_header *oh) +ofp_print_group_mod__(struct ds *s, enum ofp_version ofp_version, + const struct ofputil_group_mod *gm) { - struct ofputil_group_mod gm; - int error; bool bucket_command = false; - 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) { + switch (gm->command) { case OFPGC11_ADD: ds_put_cstr(s, "ADD"); break; @@ -2357,17 +2598,31 @@ ofp_print_group_mod(struct ds *s, const struct ofp_header *oh) break; default: - ds_put_format(s, "cmd:%"PRIu16"", gm.command); + ds_put_format(s, "cmd:%"PRIu16"", gm->command); } ds_put_char(s, ' '); if (bucket_command) { ofp_print_bucket_id(s, "command_bucket_id:", - gm.command_bucket_id, oh->version); + gm->command_bucket_id, ofp_version); } - ofp_print_group(s, gm.group_id, gm.type, &gm.buckets, &gm.props, - oh->version, bucket_command); + ofp_print_group(s, gm->group_id, gm->type, &gm->buckets, &gm->props, + ofp_version, bucket_command); +} + +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; + } + ofp_print_group_mod__(s, oh->version, &gm); ofputil_bucket_list_destroy(&gm.buckets); } @@ -2408,7 +2663,9 @@ table_action_features_empty(const struct ofputil_table_action_features *taf) static void print_table_instruction_features( - struct ds *s, const struct ofputil_table_instruction_features *tif) + struct ds *s, + const struct ofputil_table_instruction_features *tif, + const struct ofputil_table_instruction_features *prev_tif) { int start, end; @@ -2431,19 +2688,28 @@ print_table_instruction_features( } if (tif->instructions) { - ds_put_cstr(s, " instructions: "); - int i; + if (prev_tif && tif->instructions == prev_tif->instructions) { + ds_put_cstr(s, " (same instructions)\n"); + } else { + ds_put_cstr(s, " instructions: "); + int i; - for (i = 0; i < 32; i++) { - if (tif->instructions & (1u << i)) { - ds_put_format(s, "%s,", ovs_instruction_name_from_type(i)); + for (i = 0; i < 32; i++) { + if (tif->instructions & (1u << i)) { + ds_put_format(s, "%s,", ovs_instruction_name_from_type(i)); + } } + ds_chomp(s, ','); + ds_put_char(s, '\n'); } - ds_chomp(s, ','); - ds_put_char(s, '\n'); } - if (!table_action_features_equal(&tif->write, &tif->apply)) { + if (prev_tif + && table_action_features_equal(&tif->write, &prev_tif->write) + && table_action_features_equal(&tif->apply, &prev_tif->apply) + && !bitmap_is_all_zeros(tif->write.set_fields.bm, MFF_N_IDS)) { + ds_put_cstr(s, " (same actions)\n"); + } else if (!table_action_features_equal(&tif->write, &tif->apply)) { ds_put_cstr(s, " Write-Actions features:\n"); print_table_action_features(s, &tif->write); ds_put_cstr(s, " Apply-Actions features:\n"); @@ -2476,61 +2742,143 @@ table_instruction_features_empty( && table_action_features_empty(&tif->apply)); } -static void +static bool +table_features_equal(const struct ofputil_table_features *a, + const struct ofputil_table_features *b) +{ + return (a->metadata_match == b->metadata_match + && a->metadata_write == b->metadata_write + && a->miss_config == b->miss_config + && a->supports_eviction == b->supports_eviction + && a->supports_vacancy_events == b->supports_vacancy_events + && a->max_entries == b->max_entries + && table_instruction_features_equal(&a->nonmiss, &b->nonmiss) + && table_instruction_features_equal(&a->miss, &b->miss) + && bitmap_equal(a->match.bm, b->match.bm, MFF_N_IDS)); +} + +static bool +table_features_empty(const struct ofputil_table_features *tf) +{ + return (!tf->metadata_match + && !tf->metadata_write + && tf->miss_config == OFPUTIL_TABLE_MISS_DEFAULT + && tf->supports_eviction < 0 + && tf->supports_vacancy_events < 0 + && !tf->max_entries + && table_instruction_features_empty(&tf->nonmiss) + && table_instruction_features_empty(&tf->miss) + && bitmap_is_all_zeros(tf->match.bm, MFF_N_IDS)); +} + +static bool +table_stats_equal(const struct ofputil_table_stats *a, + const struct ofputil_table_stats *b) +{ + return (a->active_count == b->active_count + && a->lookup_count == b->lookup_count + && a->matched_count == b->matched_count); +} + +void ofp_print_table_features(struct ds *s, const struct ofputil_table_features *features, - const struct ofputil_table_stats *stats) + const struct ofputil_table_features *prev_features, + const struct ofputil_table_stats *stats, + const struct ofputil_table_stats *prev_stats) { int i; - ds_put_format(s, "\n table %"PRIu8, features->table_id); + ds_put_format(s, " table %"PRIu8, features->table_id); if (features->name[0]) { ds_put_format(s, " (\"%s\")", features->name); } - ds_put_cstr(s, ":\n"); + ds_put_char(s, ':'); + + bool same_stats = prev_stats && table_stats_equal(stats, prev_stats); + bool same_features = prev_features && table_features_equal(features, + prev_features); + if ((!stats || same_stats) && same_features) { + ds_put_cstr(s, " ditto"); + return; + } + ds_put_char(s, '\n'); if (stats) { ds_put_format(s, " active=%"PRIu32", ", stats->active_count); ds_put_format(s, "lookup=%"PRIu64", ", stats->lookup_count); ds_put_format(s, "matched=%"PRIu64"\n", stats->matched_count); } - if (features->metadata_match || features->metadata_match) { + if (same_features) { + if (!table_features_empty(features)) { + ds_put_cstr(s, " (same features)\n"); + } + return; + } + if (features->metadata_match || features->metadata_write) { ds_put_format(s, " metadata: match=%#"PRIx64" write=%#"PRIx64"\n", ntohll(features->metadata_match), ntohll(features->metadata_write)); } if (features->miss_config != OFPUTIL_TABLE_MISS_DEFAULT) { - ds_put_cstr(s, " config="); - ofp_print_table_miss_config(s, features->miss_config); + ds_put_format(s, " config=%s\n", + ofputil_table_miss_to_string(features->miss_config)); + } + + if (features->supports_eviction >= 0) { + ds_put_format(s, " eviction: %ssupported\n", + features->supports_eviction ? "" : "not "); + + } + if (features->supports_vacancy_events >= 0) { + ds_put_format(s, " vacancy events: %ssupported\n", + features->supports_vacancy_events ? "" : "not "); + } if (features->max_entries) { ds_put_format(s, " max_entries=%"PRIu32"\n", features->max_entries); } - if (!table_instruction_features_equal(&features->nonmiss, - &features->miss)) { + const struct ofputil_table_instruction_features *prev_nonmiss + = prev_features ? &prev_features->nonmiss : NULL; + const struct ofputil_table_instruction_features *prev_miss + = prev_features ? &prev_features->miss : NULL; + if (prev_features + && table_instruction_features_equal(&features->nonmiss, prev_nonmiss) + && table_instruction_features_equal(&features->miss, prev_miss)) { + if (!table_instruction_features_empty(&features->nonmiss)) { + ds_put_cstr(s, " (same instructions)\n"); + } + } else if (!table_instruction_features_equal(&features->nonmiss, + &features->miss)) { ds_put_cstr(s, " instructions (other than table miss):\n"); - print_table_instruction_features(s, &features->nonmiss); + print_table_instruction_features(s, &features->nonmiss, prev_nonmiss); ds_put_cstr(s, " instructions (table miss):\n"); - print_table_instruction_features(s, &features->miss); + print_table_instruction_features(s, &features->miss, prev_miss); } else if (!table_instruction_features_empty(&features->nonmiss)) { ds_put_cstr(s, " instructions (table miss and others):\n"); - print_table_instruction_features(s, &features->nonmiss); + print_table_instruction_features(s, &features->nonmiss, prev_nonmiss); } - if (!bitmap_is_all_zeros(features->match.bm, MFF_N_IDS)){ - ds_put_cstr(s, " matching:\n"); - BITMAP_FOR_EACH_1 (i, MFF_N_IDS, features->match.bm) { - const struct mf_field *f = mf_from_id(i); - bool mask = bitmap_is_set(features->mask.bm, i); - bool wildcard = bitmap_is_set(features->wildcard.bm, i); - - ds_put_format(s, " %s: %s\n", - f->name, - (mask ? "arbitrary mask" - : wildcard ? "exact match or wildcard" - : "must exact match")); + if (!bitmap_is_all_zeros(features->match.bm, MFF_N_IDS)) { + if (prev_features + && bitmap_equal(features->match.bm, prev_features->match.bm, + MFF_N_IDS)) { + ds_put_cstr(s, " (same matching)\n"); + } else { + ds_put_cstr(s, " matching:\n"); + BITMAP_FOR_EACH_1 (i, MFF_N_IDS, features->match.bm) { + const struct mf_field *f = mf_from_id(i); + bool mask = bitmap_is_set(features->mask.bm, i); + bool wildcard = bitmap_is_set(features->wildcard.bm, i); + + ds_put_format(s, " %s: %s\n", + f->name, + (mask ? "arbitrary mask" + : wildcard ? "exact match or wildcard" + : "must exact match")); + } } } } @@ -2538,11 +2886,10 @@ ofp_print_table_features(struct ds *s, static void ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh) { - struct ofpbuf b; - - ofpbuf_use_const(&b, oh, ntohs(oh->length)); + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); - for (;;) { + struct ofputil_table_features prev; + for (int i = 0; ; i++) { struct ofputil_table_features tf; int retval; @@ -2553,7 +2900,29 @@ ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh) } return; } - ofp_print_table_features(s, &tf, NULL); + + ds_put_char(s, '\n'); + ofp_print_table_features(s, &tf, i ? &prev : NULL, NULL, NULL); + prev = tf; + } +} + +static void +ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh) +{ + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); + for (;;) { + struct ofputil_table_desc td; + int retval; + + retval = ofputil_decode_table_desc(&b, &td, oh->version); + if (retval) { + if (retval != EOF) { + ofp_print_error(s, retval); + } + return; + } + ofp_print_table_desc(s, &td); } } @@ -2621,7 +2990,6 @@ 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, NULL); if (error) { @@ -2635,12 +3003,122 @@ ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, int verbosity) 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); + char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), verbosity); + ds_put_and_free_cstr(s, msg); +} + +static void +print_tlv_table(struct ds *s, struct ovs_list *mappings) +{ + struct ofputil_tlv_map *map; + + ds_put_cstr(s, " mapping table:\n"); + ds_put_cstr(s, " class\ttype\tlength\tmatch field\n"); + ds_put_cstr(s, " -----\t----\t------\t-----------"); + + LIST_FOR_EACH (map, list_node, mappings) { + ds_put_char(s, '\n'); + ds_put_format(s, " 0x%"PRIx16"\t0x%"PRIx8"\t%"PRIu8"\ttun_metadata%"PRIu16, + map->option_class, map->option_type, map->option_len, + map->index); } } +static void +ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh) +{ + int error; + struct ofputil_tlv_table_mod ttm; + + error = ofputil_decode_tlv_table_mod(oh, &ttm); + if (error) { + ofp_print_error(s, error); + return; + } + + ds_put_cstr(s, "\n "); + + switch (ttm.command) { + case NXTTMC_ADD: + ds_put_cstr(s, "ADD"); + break; + case NXTTMC_DELETE: + ds_put_cstr(s, "DEL"); + break; + case NXTTMC_CLEAR: + ds_put_cstr(s, "CLEAR"); + break; + } + + if (ttm.command != NXTTMC_CLEAR) { + print_tlv_table(s, &ttm.mappings); + } + + ofputil_uninit_tlv_table(&ttm.mappings); +} + +static void +ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh) +{ + int error; + struct ofputil_tlv_table_reply ttr; + struct ofputil_tlv_map *map; + int allocated_space = 0; + + error = ofputil_decode_tlv_table_reply(oh, &ttr); + if (error) { + ofp_print_error(s, error); + return; + } + + ds_put_char(s, '\n'); + + LIST_FOR_EACH (map, list_node, &ttr.mappings) { + allocated_space += map->option_len; + } + + ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n", + ttr.max_option_space, ttr.max_fields); + ds_put_format(s, " allocated option space=%d\n", allocated_space); + ds_put_char(s, '\n'); + print_tlv_table(s, &ttr.mappings); + + ofputil_uninit_tlv_table(&ttr.mappings); +} + +/* This function will print the request forward message. The reason for + * request forward is taken from rf.request.type */ +static void +ofp_print_requestforward(struct ds *string, const struct ofp_header *oh) +{ + struct ofputil_requestforward rf; + enum ofperr error; + + error = ofputil_decode_requestforward(oh, &rf); + if (error) { + ofp_print_error(string, error); + return; + } + + ds_put_cstr(string, " reason="); + + switch (rf.reason) { + case OFPRFR_GROUP_MOD: + ds_put_cstr(string, "group_mod"); + ofp_print_group_mod__(string, oh->version, rf.group_mod); + break; + + case OFPRFR_METER_MOD: + ds_put_cstr(string, "meter_mod"); + ofp_print_meter_mod__(string, rf.meter_mod); + break; + + case OFPRFR_N_REASONS: + OVS_NOT_REACHED(); + } + ofputil_destroy_requestforward(&rf); +} + static void ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, struct ds *string, int verbosity) @@ -2648,8 +3126,9 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, const void *msg = oh; ofp_header_to_string__(oh, raw, string); - switch (ofptype_from_ofpraw(raw)) { + enum ofptype type = ofptype_from_ofpraw(raw); + switch (type) { case OFPTYPE_GROUP_STATS_REQUEST: ofp_print_stats(string, oh); ofp_print_ofpst_group_request(string, oh); @@ -2685,6 +3164,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, ofp_print_table_features_reply(string, oh); break; + case OFPTYPE_TABLE_DESC_REQUEST: + case OFPTYPE_TABLE_DESC_REPLY: + ofp_print_table_desc_reply(string, oh); + break; + case OFPTYPE_HELLO: ofp_print_hello(string, oh); break; @@ -2709,8 +3193,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_GET_CONFIG_REPLY: + ofp_print_get_config_reply(string, oh); + break; + case OFPTYPE_SET_CONFIG: - ofp_print_switch_config(string, ofpmsg_body(oh)); + ofp_print_set_config(string, oh); break; case OFPTYPE_PACKET_IN: @@ -2765,6 +3252,14 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, ofp_print_role_status_message(string, oh); break; + case OFPTYPE_REQUESTFORWARD: + ofp_print_requestforward(string, oh); + break; + + case OFPTYPE_TABLE_STATUS: + ofp_print_table_status_message(string, oh); + break; + case OFPTYPE_METER_STATS_REQUEST: case OFPTYPE_METER_CONFIG_STATS_REQUEST: ofp_print_stats(string, oh); @@ -2872,7 +3367,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_set_async_config(string, oh, type); break; case OFPTYPE_GET_ASYNC_REQUEST: break; @@ -2899,6 +3394,21 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, case OFPTYPE_BUNDLE_ADD_MESSAGE: ofp_print_bundle_add(string, msg, verbosity); break; + + case OFPTYPE_NXT_TLV_TABLE_MOD: + ofp_print_tlv_table_mod(string, msg); + break; + + case OFPTYPE_NXT_TLV_TABLE_REQUEST: + break; + + case OFPTYPE_NXT_TLV_TABLE_REPLY: + ofp_print_tlv_table_reply(string, msg); + break; + + case OFPTYPE_NXT_RESUME: + ofp_print_packet_in(string, msg, verbosity); + break; } }