X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-print.c;h=03de5f1e58a6f2840f06e22ab3c8a890fed11e9b;hb=1d31ece9c09ecd31ed524f0f83573e8780774abb;hp=eb4548057bdb485e49fff30392504235aae3434b;hpb=3370cd3c3c2a421a9ce21bd5a60b389ffb8734ca;p=openvswitch diff --git a/lib/ofp-print.c b/lib/ofp-print.c index eb454805..03de5f1e 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,9 @@ #include "learn.h" #include "multipath.h" #include "meta-flow.h" +#include "netdev.h" #include "nx-match.h" +#include "ofp-actions.h" #include "ofp-errors.h" #include "ofp-util.h" #include "ofpbuf.h" @@ -112,6 +114,13 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, } } + if (pin.fmd.metadata_mask) { + ds_put_format(string, " metadata=0x%"PRIx64, ntohll(pin.fmd.metadata)); + if (pin.fmd.metadata_mask != htonll(UINT64_MAX)) { + ds_put_format(string, "/0x%"PRIx64, ntohll(pin.fmd.metadata_mask)); + } + } + for (i = 0; i < FLOW_N_REGS; i++) { if (pin.fmd.reg_masks[i]) { ds_put_format(string, " reg%d=0x%"PRIx32, i, pin.fmd.regs[i]); @@ -121,20 +130,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)", + ofputil_packet_in_reason_to_string(pin.reason)); ds_put_format(string, " data_len=%zu", pin.packet_len); if (pin.buffer_id == UINT32_MAX) { @@ -157,366 +154,176 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, } } -static void -print_note(struct ds *string, const struct nx_action_note *nan) -{ - size_t len; - size_t i; - - ds_put_cstr(string, "note:"); - len = ntohs(nan->len) - offsetof(struct nx_action_note, note); - for (i = 0; i < len; i++) { - if (i) { - ds_put_char(string, '.'); - } - ds_put_format(string, "%02"PRIx8, nan->note[i]); - } -} - -static void -ofp_print_action(struct ds *s, const union ofp_action *a, - enum ofputil_action_code code) -{ - const struct ofp_action_enqueue *oae; - const struct ofp_action_dl_addr *oada; - const struct nx_action_set_tunnel64 *nast64; - const struct nx_action_set_tunnel *nast; - const struct nx_action_set_queue *nasq; - const struct nx_action_resubmit *nar; - const struct nx_action_reg_move *move; - const struct nx_action_reg_load *load; - const struct nx_action_multipath *nam; - const struct nx_action_autopath *naa; - const struct nx_action_output_reg *naor; - struct mf_subfield subfield; - uint16_t port; - - switch (code) { - case OFPUTIL_OFPAT_OUTPUT: - port = ntohs(a->output.port); - if (port < OFPP_MAX) { - ds_put_format(s, "output:%"PRIu16, port); - } else { - ofputil_format_port(port, s); - if (port == OFPP_CONTROLLER) { - if (a->output.max_len != htons(0)) { - ds_put_format(s, ":%"PRIu16, ntohs(a->output.max_len)); - } else { - ds_put_cstr(s, ":all"); - } - } - } - break; - - case OFPUTIL_OFPAT_ENQUEUE: - oae = (const struct ofp_action_enqueue *) a; - ds_put_format(s, "enqueue:"); - ofputil_format_port(ntohs(oae->port), s); - ds_put_format(s, "q%"PRIu32, ntohl(oae->queue_id)); - break; - - case OFPUTIL_OFPAT_SET_VLAN_VID: - ds_put_format(s, "mod_vlan_vid:%"PRIu16, - ntohs(a->vlan_vid.vlan_vid)); - break; - - case OFPUTIL_OFPAT_SET_VLAN_PCP: - ds_put_format(s, "mod_vlan_pcp:%"PRIu8, a->vlan_pcp.vlan_pcp); - break; - - case OFPUTIL_OFPAT_STRIP_VLAN: - ds_put_cstr(s, "strip_vlan"); - break; - - case OFPUTIL_OFPAT_SET_DL_SRC: - oada = (const struct ofp_action_dl_addr *) a; - ds_put_format(s, "mod_dl_src:"ETH_ADDR_FMT, - ETH_ADDR_ARGS(oada->dl_addr)); - break; - - case OFPUTIL_OFPAT_SET_DL_DST: - oada = (const struct ofp_action_dl_addr *) a; - ds_put_format(s, "mod_dl_dst:"ETH_ADDR_FMT, - ETH_ADDR_ARGS(oada->dl_addr)); - break; - - case OFPUTIL_OFPAT_SET_NW_SRC: - ds_put_format(s, "mod_nw_src:"IP_FMT, IP_ARGS(&a->nw_addr.nw_addr)); - break; - - case OFPUTIL_OFPAT_SET_NW_DST: - ds_put_format(s, "mod_nw_dst:"IP_FMT, IP_ARGS(&a->nw_addr.nw_addr)); - break; - - case OFPUTIL_OFPAT_SET_NW_TOS: - ds_put_format(s, "mod_nw_tos:%d", a->nw_tos.nw_tos); - break; - - case OFPUTIL_OFPAT_SET_TP_SRC: - ds_put_format(s, "mod_tp_src:%d", ntohs(a->tp_port.tp_port)); - break; - - case OFPUTIL_OFPAT_SET_TP_DST: - ds_put_format(s, "mod_tp_dst:%d", ntohs(a->tp_port.tp_port)); - break; - - case OFPUTIL_NXAST_RESUBMIT: - nar = (struct nx_action_resubmit *)a; - ds_put_format(s, "resubmit:"); - ofputil_format_port(ntohs(nar->in_port), s); - break; - - case OFPUTIL_NXAST_RESUBMIT_TABLE: - nar = (struct nx_action_resubmit *)a; - ds_put_format(s, "resubmit("); - if (nar->in_port != htons(OFPP_IN_PORT)) { - ofputil_format_port(ntohs(nar->in_port), s); - } - ds_put_char(s, ','); - if (nar->table != 255) { - ds_put_format(s, "%"PRIu8, nar->table); - } - ds_put_char(s, ')'); - break; - - case OFPUTIL_NXAST_SET_TUNNEL: - nast = (struct nx_action_set_tunnel *)a; - ds_put_format(s, "set_tunnel:%#"PRIx32, ntohl(nast->tun_id)); - break; - - case OFPUTIL_NXAST_SET_QUEUE: - nasq = (struct nx_action_set_queue *)a; - ds_put_format(s, "set_queue:%u", ntohl(nasq->queue_id)); - break; - - case OFPUTIL_NXAST_POP_QUEUE: - ds_put_cstr(s, "pop_queue"); - break; - - case OFPUTIL_NXAST_NOTE: - print_note(s, (const struct nx_action_note *) a); - break; - - case OFPUTIL_NXAST_REG_MOVE: - move = (const struct nx_action_reg_move *) a; - nxm_format_reg_move(move, s); - break; - - case OFPUTIL_NXAST_REG_LOAD: - load = (const struct nx_action_reg_load *) a; - nxm_format_reg_load(load, s); - break; - - case OFPUTIL_NXAST_SET_TUNNEL64: - nast64 = (const struct nx_action_set_tunnel64 *) a; - ds_put_format(s, "set_tunnel64:%#"PRIx64, - ntohll(nast64->tun_id)); - break; - - case OFPUTIL_NXAST_MULTIPATH: - nam = (const struct nx_action_multipath *) a; - multipath_format(nam, s); - break; - - case OFPUTIL_NXAST_AUTOPATH: - naa = (const struct nx_action_autopath *)a; - ds_put_format(s, "autopath(%u,", ntohl(naa->id)); - nxm_decode(&subfield, naa->dst, naa->ofs_nbits); - mf_format_subfield(&subfield, s); - ds_put_char(s, ')'); - break; - - case OFPUTIL_NXAST_BUNDLE: - case OFPUTIL_NXAST_BUNDLE_LOAD: - bundle_format((const struct nx_action_bundle *) a, s); - break; - - case OFPUTIL_NXAST_OUTPUT_REG: - naor = (const struct nx_action_output_reg *) a; - ds_put_cstr(s, "output:"); - nxm_decode(&subfield, naor->src, naor->ofs_nbits); - mf_format_subfield(&subfield, s); - break; - - case OFPUTIL_NXAST_LEARN: - learn_format((const struct nx_action_learn *) a, s); - break; - - case OFPUTIL_NXAST_DEC_TTL: - ds_put_cstr(s, "dec_ttl"); - break; - - case OFPUTIL_NXAST_EXIT: - ds_put_cstr(s, "exit"); - break; - - default: - break; - } -} - -void -ofp_print_actions(struct ds *string, const union ofp_action *actions, - size_t n_actions) -{ - const union ofp_action *a; - size_t left; - - ds_put_cstr(string, "actions="); - if (!n_actions) { - ds_put_cstr(string, "drop"); - } - - OFPUTIL_ACTION_FOR_EACH (a, left, actions, n_actions) { - int code = ofputil_decode_action(a); - if (code >= 0) { - if (a != actions) { - ds_put_cstr(string, ","); - } - ofp_print_action(string, a, code); - } else { - ofp_print_error(string, -code); - } - } - if (left > 0) { - ds_put_format(string, " ***%zu leftover bytes following actions", - left * sizeof *a); - } -} - 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; + struct ofpbuf ofpacts; + 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"); + ofpbuf_init(&ofpacts, 64); + error = ofputil_decode_packet_out(&po, opo, &ofpacts); + if (error) { + ofpbuf_uninit(&ofpacts); + 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, ' '); + ofpacts_format(po.ofpacts, po.ofpacts_len, string); + + 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'); + + ofpbuf_uninit(&ofpacts); } /* qsort comparison function. */ static int compare_ports(const void *a_, const void *b_) { - const struct ofp_phy_port *a = a_; - const struct ofp_phy_port *b = b_; - uint16_t ap = ntohs(a->port_no); - uint16_t bp = ntohs(b->port_no); + const struct ofputil_phy_port *a = a_; + const struct ofputil_phy_port *b = b_; + uint16_t ap = a->port_no; + uint16_t bp = b->port_no; return ap < bp ? -1 : ap > bp; } -struct bit_name { - uint32_t bit; - const char *name; -}; - static void ofp_print_bit_names(struct ds *string, uint32_t bits, - const struct bit_name bit_names[]) + const char *(*bit_to_name)(uint32_t bit), + char separator) { int n = 0; + int i; if (!bits) { ds_put_cstr(string, "0"); return; } - for (; bits && bit_names->name; bit_names++) { - if (bits & bit_names->bit) { - if (n++) { - ds_put_char(string, ' '); + for (i = 0; i < 32; i++) { + uint32_t bit = UINT32_C(1) << i; + + if (bits & bit) { + const char *name = bit_to_name(bit); + if (name) { + if (n++) { + ds_put_char(string, separator); + } + ds_put_cstr(string, name); + bits &= ~bit; } - ds_put_cstr(string, bit_names->name); - bits &= ~bit_names->bit; } } if (bits) { - if (n++) { - ds_put_char(string, ' '); + if (n) { + ds_put_char(string, separator); } ds_put_format(string, "0x%"PRIx32, bits); } } +static const char * +netdev_feature_to_name(uint32_t bit) +{ + enum netdev_features f = bit; + + switch (f) { + case NETDEV_F_10MB_HD: return "10MB-HD"; + case NETDEV_F_10MB_FD: return "10MB-FD"; + case NETDEV_F_100MB_HD: return "100MB-HD"; + case NETDEV_F_100MB_FD: return "100MB-FD"; + case NETDEV_F_1GB_HD: return "1GB-HD"; + case NETDEV_F_1GB_FD: return "1GB-FD"; + case NETDEV_F_10GB_FD: return "10GB-FD"; + case NETDEV_F_40GB_FD: return "40GB-FD"; + case NETDEV_F_100GB_FD: return "100GB-FD"; + case NETDEV_F_1TB_FD: return "1TB-FD"; + case NETDEV_F_OTHER: return "OTHER"; + case NETDEV_F_COPPER: return "COPPER"; + case NETDEV_F_FIBER: return "FIBER"; + case NETDEV_F_AUTONEG: return "AUTO_NEG"; + case NETDEV_F_PAUSE: return "AUTO_PAUSE"; + case NETDEV_F_PAUSE_ASYM: return "AUTO_PAUSE_ASYM"; + } + + return NULL; +} + static void -ofp_print_port_features(struct ds *string, uint32_t features) +ofp_print_port_features(struct ds *string, enum netdev_features features) { - static const struct bit_name feature_bits[] = { - { OFPPF_10MB_HD, "10MB-HD" }, - { OFPPF_10MB_FD, "10MB-FD" }, - { OFPPF_100MB_HD, "100MB-HD" }, - { OFPPF_100MB_FD, "100MB-FD" }, - { OFPPF_1GB_HD, "1GB-HD" }, - { OFPPF_1GB_FD, "1GB-FD" }, - { OFPPF_10GB_FD, "10GB-FD" }, - { OFPPF_COPPER, "COPPER" }, - { OFPPF_FIBER, "FIBER" }, - { OFPPF_AUTONEG, "AUTO_NEG" }, - { OFPPF_PAUSE, "AUTO_PAUSE" }, - { OFPPF_PAUSE_ASYM, "AUTO_PAUSE_ASYM" }, - { 0, NULL }, - }; - - ofp_print_bit_names(string, features, feature_bits); + ofp_print_bit_names(string, features, netdev_feature_to_name, ' '); ds_put_char(string, '\n'); } +static const char * +ofputil_port_config_to_name(uint32_t bit) +{ + enum ofputil_port_config pc = bit; + + switch (pc) { + case OFPUTIL_PC_PORT_DOWN: return "PORT_DOWN"; + case OFPUTIL_PC_NO_STP: return "NO_STP"; + case OFPUTIL_PC_NO_RECV: return "NO_RECV"; + case OFPUTIL_PC_NO_RECV_STP: return "NO_RECV_STP"; + case OFPUTIL_PC_NO_FLOOD: return "NO_FLOOD"; + case OFPUTIL_PC_NO_FWD: return "NO_FWD"; + case OFPUTIL_PC_NO_PACKET_IN: return "NO_PACKET_IN"; + } + + return NULL; +} + static void -ofp_print_port_config(struct ds *string, uint32_t config) +ofp_print_port_config(struct ds *string, enum ofputil_port_config config) { - static const struct bit_name config_bits[] = { - { OFPPC_PORT_DOWN, "PORT_DOWN" }, - { OFPPC_NO_STP, "NO_STP" }, - { OFPPC_NO_RECV, "NO_RECV" }, - { OFPPC_NO_RECV_STP, "NO_RECV_STP" }, - { OFPPC_NO_FLOOD, "NO_FLOOD" }, - { OFPPC_NO_FWD, "NO_FWD" }, - { OFPPC_NO_PACKET_IN, "NO_PACKET_IN" }, - { 0, NULL }, - }; - - ofp_print_bit_names(string, config, config_bits); + ofp_print_bit_names(string, config, ofputil_port_config_to_name, ' '); ds_put_char(string, '\n'); } +static const char * +ofputil_port_state_to_name(uint32_t bit) +{ + enum ofputil_port_state ps = bit; + + switch (ps) { + case OFPUTIL_PS_LINK_DOWN: return "LINK_DOWN"; + case OFPUTIL_PS_BLOCKED: return "BLOCKED"; + case OFPUTIL_PS_LIVE: return "LIVE"; + + case OFPUTIL_PS_STP_LISTEN: + case OFPUTIL_PS_STP_LEARN: + case OFPUTIL_PS_STP_FORWARD: + case OFPUTIL_PS_STP_BLOCK: + /* Handled elsewhere. */ + return NULL; + } + + return NULL; +} + static void -ofp_print_port_state(struct ds *string, uint32_t state) +ofp_print_port_state(struct ds *string, enum ofputil_port_state state) { - static const struct bit_name state_bits[] = { - { OFPPS_LINK_DOWN, "LINK_DOWN" }, - { 0, NULL }, - }; - uint32_t stp_state; + enum ofputil_port_state stp_state; /* The STP state is a 2-bit field so it doesn't fit in with the bitmask * pattern. We have to special case it. @@ -525,25 +332,27 @@ ofp_print_port_state(struct ds *string, uint32_t state) * talking to OVS, so we'd always print STP_LISTEN in that case. * Therefore, we don't print anything at all if the value is STP_LISTEN, to * avoid confusing users. */ - stp_state = state & OFPPS_STP_MASK; + stp_state = state & OFPUTIL_PS_STP_MASK; if (stp_state) { - ds_put_cstr(string, (stp_state == OFPPS_STP_LEARN ? "STP_LEARN" - : stp_state == OFPPS_STP_FORWARD ? "STP_FORWARD" - : "STP_BLOCK")); - state &= ~OFPPS_STP_MASK; + ds_put_cstr(string, + (stp_state == OFPUTIL_PS_STP_LEARN ? "STP_LEARN" + : stp_state == OFPUTIL_PS_STP_FORWARD ? "STP_FORWARD" + : "STP_BLOCK")); + state &= ~OFPUTIL_PS_STP_MASK; if (state) { - ofp_print_bit_names(string, state, state_bits); + ofp_print_bit_names(string, state, ofputil_port_state_to_name, + ' '); } } else { - ofp_print_bit_names(string, state, state_bits); + ofp_print_bit_names(string, state, ofputil_port_state_to_name, ' '); } ds_put_char(string, '\n'); } static void -ofp_print_phy_port(struct ds *string, const struct ofp_phy_port *port) +ofp_print_phy_port(struct ds *string, const struct ofputil_phy_port *port) { - char name[OFP_MAX_PORT_NAME_LEN]; + char name[sizeof port->name]; int j; memcpy(name, port->name, sizeof name); @@ -555,58 +364,155 @@ ofp_print_phy_port(struct ds *string, const struct ofp_phy_port *port) name[j] = '\0'; ds_put_char(string, ' '); - ofputil_format_port(ntohs(port->port_no), string); + ofputil_format_port(port->port_no, string); ds_put_format(string, "(%s): addr:"ETH_ADDR_FMT"\n", name, ETH_ADDR_ARGS(port->hw_addr)); ds_put_cstr(string, " config: "); - ofp_print_port_config(string, ntohl(port->config)); + ofp_print_port_config(string, port->config); ds_put_cstr(string, " state: "); - ofp_print_port_state(string, ntohl(port->state)); + ofp_print_port_state(string, port->state); if (port->curr) { ds_put_format(string, " current: "); - ofp_print_port_features(string, ntohl(port->curr)); + ofp_print_port_features(string, port->curr); } if (port->advertised) { ds_put_format(string, " advertised: "); - ofp_print_port_features(string, ntohl(port->advertised)); + ofp_print_port_features(string, port->advertised); } if (port->supported) { ds_put_format(string, " supported: "); - ofp_print_port_features(string, ntohl(port->supported)); + ofp_print_port_features(string, port->supported); } if (port->peer) { ds_put_format(string, " peer: "); - ofp_print_port_features(string, ntohl(port->peer)); + ofp_print_port_features(string, port->peer); + } + ds_put_format(string, " speed: %"PRIu32" Mbps now, " + "%"PRIu32" Mbps max\n", + port->curr_speed / UINT32_C(1000), + port->max_speed / UINT32_C(1000)); +} + +/* Given a buffer 'b' that contains an array of OpenFlow ports of type + * 'ofp_version', writes a detailed description of each port into + * 'string'. */ +static void +ofp_print_phy_ports(struct ds *string, uint8_t ofp_version, + struct ofpbuf *b) +{ + size_t n_ports; + struct ofputil_phy_port *ports; + enum ofperr error; + size_t i; + + n_ports = ofputil_count_phy_ports(ofp_version, b); + + ports = xmalloc(n_ports * sizeof *ports); + for (i = 0; i < n_ports; i++) { + error = ofputil_pull_phy_port(ofp_version, b, &ports[i]); + if (error) { + ofp_print_error(string, error); + goto exit; + } } + qsort(ports, n_ports, sizeof *ports, compare_ports); + for (i = 0; i < n_ports; i++) { + ofp_print_phy_port(string, &ports[i]); + } + +exit: + free(ports); +} + +static const char * +ofputil_capabilities_to_name(uint32_t bit) +{ + enum ofputil_capabilities capabilities = bit; + + switch (capabilities) { + case OFPUTIL_C_FLOW_STATS: return "FLOW_STATS"; + case OFPUTIL_C_TABLE_STATS: return "TABLE_STATS"; + case OFPUTIL_C_PORT_STATS: return "PORT_STATS"; + case OFPUTIL_C_IP_REASM: return "IP_REASM"; + case OFPUTIL_C_QUEUE_STATS: return "QUEUE_STATS"; + case OFPUTIL_C_ARP_MATCH_IP: return "ARP_MATCH_IP"; + case OFPUTIL_C_STP: return "STP"; + case OFPUTIL_C_GROUP_STATS: return "GROUP_STATS"; + } + + return NULL; +} + +static const char * +ofputil_action_bitmap_to_name(uint32_t bit) +{ + enum ofputil_action_bitmap action = bit; + + switch (action) { + case OFPUTIL_A_OUTPUT: return "OUTPUT"; + case OFPUTIL_A_SET_VLAN_VID: return "SET_VLAN_VID"; + case OFPUTIL_A_SET_VLAN_PCP: return "SET_VLAN_PCP"; + case OFPUTIL_A_STRIP_VLAN: return "STRIP_VLAN"; + case OFPUTIL_A_SET_DL_SRC: return "SET_DL_SRC"; + case OFPUTIL_A_SET_DL_DST: return "SET_DL_DST"; + case OFPUTIL_A_SET_NW_SRC: return "SET_NW_SRC"; + case OFPUTIL_A_SET_NW_DST: return "SET_NW_DST"; + case OFPUTIL_A_SET_NW_ECN: return "SET_NW_ECN"; + case OFPUTIL_A_SET_NW_TOS: return "SET_NW_TOS"; + case OFPUTIL_A_SET_TP_SRC: return "SET_TP_SRC"; + case OFPUTIL_A_SET_TP_DST: return "SET_TP_DST"; + case OFPUTIL_A_ENQUEUE: return "ENQUEUE"; + case OFPUTIL_A_COPY_TTL_OUT: return "COPY_TTL_OUT"; + case OFPUTIL_A_COPY_TTL_IN: return "COPY_TTL_IN"; + case OFPUTIL_A_SET_MPLS_LABEL: return "SET_MPLS_LABEL"; + case OFPUTIL_A_SET_MPLS_TC: return "SET_MPLS_TC"; + case OFPUTIL_A_SET_MPLS_TTL: return "SET_MPLS_TTL"; + case OFPUTIL_A_DEC_MPLS_TTL: return "DEC_MPLS_TTL"; + case OFPUTIL_A_PUSH_VLAN: return "PUSH_VLAN"; + case OFPUTIL_A_POP_VLAN: return "POP_VLAN"; + case OFPUTIL_A_PUSH_MPLS: return "PUSH_MPLS"; + case OFPUTIL_A_POP_MPLS: return "POP_MPLS"; + case OFPUTIL_A_SET_QUEUE: return "SET_QUEUE"; + case OFPUTIL_A_GROUP: return "GROUP"; + case OFPUTIL_A_SET_NW_TTL: return "SET_NW_TTL"; + case OFPUTIL_A_DEC_NW_TTL: return "DEC_NW_TTL"; + } + + return NULL; } static void ofp_print_switch_features(struct ds *string, const struct ofp_switch_features *osf) { - size_t len = ntohs(osf->header.length); - struct ofp_phy_port *port_list; - int n_ports; - int i; + struct ofputil_switch_features features; + enum ofperr error; + struct ofpbuf b; - ds_put_format(string, " ver:0x%x, dpid:%016"PRIx64"\n", - osf->header.version, ntohll(osf->datapath_id)); - ds_put_format(string, "n_tables:%d, n_buffers:%d\n", osf->n_tables, - ntohl(osf->n_buffers)); - ds_put_format(string, "features: capabilities:%#x, actions:%#x\n", - ntohl(osf->capabilities), ntohl(osf->actions)); + error = ofputil_decode_switch_features(osf, &features, &b); + if (error) { + ofp_print_error(string, error); + return; + } - n_ports = (len - sizeof *osf) / sizeof *osf->ports; + ds_put_format(string, " dpid:%016"PRIx64"\n", features.datapath_id); + ds_put_format(string, "n_tables:%"PRIu8", n_buffers:%"PRIu32"\n", + features.n_tables, features.n_buffers); - port_list = xmemdup(osf->ports, len - sizeof *osf); - qsort(port_list, n_ports, sizeof *port_list, compare_ports); - for (i = 0; i < n_ports; i++) { - ofp_print_phy_port(string, &port_list[i]); - } - free(port_list); + ds_put_cstr(string, "capabilities: "); + ofp_print_bit_names(string, features.capabilities, + ofputil_capabilities_to_name, ' '); + ds_put_char(string, '\n'); + + ds_put_cstr(string, "actions: "); + ofp_print_bit_names(string, features.actions, + ofputil_action_bitmap_to_name, ' '); + ds_put_char(string, '\n'); + + ofp_print_phy_ports(string, osf->header.version, &b); } static void @@ -674,25 +580,25 @@ print_ip_netmask(struct ds *string, const char *leader, ovs_be32 ip, } void -ofp_print_match(struct ds *f, const struct ofp_match *om, int verbosity) +ofp10_match_print(struct ds *f, const struct ofp10_match *om, int verbosity) { - char *s = ofp_match_to_string(om, verbosity); + char *s = ofp10_match_to_string(om, verbosity); ds_put_cstr(f, s); free(s); } char * -ofp_match_to_string(const struct ofp_match *om, int verbosity) +ofp10_match_to_string(const struct ofp10_match *om, int verbosity) { struct ds f = DS_EMPTY_INITIALIZER; uint32_t w = ntohl(om->wildcards); bool skip_type = false; bool skip_proto = false; - if (!(w & OFPFW_DL_TYPE)) { + if (!(w & OFPFW10_DL_TYPE)) { skip_type = true; if (om->dl_type == htons(ETH_TYPE_IP)) { - if (!(w & OFPFW_NW_PROTO)) { + if (!(w & OFPFW10_NW_PROTO)) { skip_proto = true; if (om->nw_proto == IPPROTO_ICMP) { ds_put_cstr(&f, "icmp,"); @@ -713,44 +619,46 @@ ofp_match_to_string(const struct ofp_match *om, int verbosity) skip_type = false; } } - print_wild(&f, "in_port=", w & OFPFW_IN_PORT, verbosity, + print_wild(&f, "in_port=", w & OFPFW10_IN_PORT, verbosity, "%d", ntohs(om->in_port)); - print_wild(&f, "dl_vlan=", w & OFPFW_DL_VLAN, verbosity, + print_wild(&f, "dl_vlan=", w & OFPFW10_DL_VLAN, verbosity, "%d", ntohs(om->dl_vlan)); - print_wild(&f, "dl_vlan_pcp=", w & OFPFW_DL_VLAN_PCP, verbosity, + print_wild(&f, "dl_vlan_pcp=", w & OFPFW10_DL_VLAN_PCP, verbosity, "%d", om->dl_vlan_pcp); - print_wild(&f, "dl_src=", w & OFPFW_DL_SRC, verbosity, + print_wild(&f, "dl_src=", w & OFPFW10_DL_SRC, verbosity, ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src)); - print_wild(&f, "dl_dst=", w & OFPFW_DL_DST, verbosity, + print_wild(&f, "dl_dst=", w & OFPFW10_DL_DST, verbosity, ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_dst)); if (!skip_type) { - print_wild(&f, "dl_type=", w & OFPFW_DL_TYPE, verbosity, + print_wild(&f, "dl_type=", w & OFPFW10_DL_TYPE, verbosity, "0x%04x", ntohs(om->dl_type)); } print_ip_netmask(&f, "nw_src=", om->nw_src, - (w & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT, verbosity); + (w & OFPFW10_NW_SRC_MASK) >> OFPFW10_NW_SRC_SHIFT, + verbosity); print_ip_netmask(&f, "nw_dst=", om->nw_dst, - (w & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT, verbosity); + (w & OFPFW10_NW_DST_MASK) >> OFPFW10_NW_DST_SHIFT, + verbosity); if (!skip_proto) { if (om->dl_type == htons(ETH_TYPE_ARP)) { - print_wild(&f, "arp_op=", w & OFPFW_NW_PROTO, verbosity, + print_wild(&f, "arp_op=", w & OFPFW10_NW_PROTO, verbosity, "%u", om->nw_proto); } else { - print_wild(&f, "nw_proto=", w & OFPFW_NW_PROTO, verbosity, + print_wild(&f, "nw_proto=", w & OFPFW10_NW_PROTO, verbosity, "%u", om->nw_proto); } } - print_wild(&f, "nw_tos=", w & OFPFW_NW_TOS, verbosity, + print_wild(&f, "nw_tos=", w & OFPFW10_NW_TOS, verbosity, "%u", om->nw_tos); if (om->nw_proto == IPPROTO_ICMP) { - print_wild(&f, "icmp_type=", w & OFPFW_ICMP_TYPE, verbosity, + print_wild(&f, "icmp_type=", w & OFPFW10_ICMP_TYPE, verbosity, "%d", ntohs(om->tp_src)); - print_wild(&f, "icmp_code=", w & OFPFW_ICMP_CODE, verbosity, + print_wild(&f, "icmp_code=", w & OFPFW10_ICMP_CODE, verbosity, "%d", ntohs(om->tp_dst)); } else { - print_wild(&f, "tp_src=", w & OFPFW_TP_SRC, verbosity, + print_wild(&f, "tp_src=", w & OFPFW10_TP_SRC, verbosity, "%d", ntohs(om->tp_src)); - print_wild(&f, "tp_dst=", w & OFPFW_TP_DST, verbosity, + print_wild(&f, "tp_dst=", w & OFPFW10_TP_DST, verbosity, "%d", ntohs(om->tp_dst)); } if (ds_last(&f) == ',') { @@ -764,11 +672,14 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, enum ofputil_msg_code code, int verbosity) { struct ofputil_flow_mod fm; + struct ofpbuf ofpacts; bool need_priority; enum ofperr error; - error = ofputil_decode_flow_mod(&fm, oh, true); + ofpbuf_init(&ofpacts, 64); + error = ofputil_decode_flow_mod(&fm, oh, OFPUTIL_P_OF10_TID, &ofpacts); if (error) { + ofpbuf_uninit(&ofpacts); ofp_print_error(s, error); return; } @@ -800,7 +711,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, 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); + ofp10_match_print(s, &ofm->match, verbosity); /* ofp_print_match() doesn't print priority. */ need_priority = true; @@ -825,8 +736,12 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, if (ds_last(s) != ' ') { ds_put_char(s, ' '); } - if (fm.cookie != htonll(0)) { - ds_put_format(s, "cookie:0x%"PRIx64" ", ntohll(fm.cookie)); + if (fm.new_cookie != htonll(0)) { + ds_put_format(s, "cookie:0x%"PRIx64" ", ntohll(fm.new_cookie)); + } + if (fm.cookie_mask != htonll(0)) { + ds_put_format(s, "cookie:0x%"PRIx64"/0x%"PRIx64" ", + ntohll(fm.cookie), ntohll(fm.cookie_mask)); } if (fm.idle_timeout != OFP_FLOW_PERMANENT) { ds_put_format(s, "idle:%"PRIu16" ", fm.idle_timeout); @@ -840,11 +755,32 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, if (fm.buffer_id != UINT32_MAX) { ds_put_format(s, "buf:0x%"PRIx32" ", fm.buffer_id); } + if (fm.out_port != OFPP_NONE) { + ds_put_format(s, "out_port:"); + ofputil_format_port(fm.out_port, s); + ds_put_char(s, ' '); + } 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); + ofpacts_format(fm.ofpacts, fm.ofpacts_len, s); + ofpbuf_uninit(&ofpacts); } static void @@ -860,6 +796,28 @@ 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"; + case OFPRR_GROUP_DELETE: + return "group_delete"; + case OFPRR_EVICTION: + return "eviction"; + default: + sprintf(s, "%d", (int) reason); + return s; + } +} + static void ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh) { @@ -875,21 +833,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)); @@ -901,14 +846,29 @@ ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh) } static void -ofp_print_port_mod(struct ds *string, const struct ofp_port_mod *opm) +ofp_print_port_mod(struct ds *string, const struct ofp_header *oh) { - ds_put_format(string, "port: %d: addr:"ETH_ADDR_FMT", config: %#x, mask:%#x\n", - ntohs(opm->port_no), ETH_ADDR_ARGS(opm->hw_addr), - ntohl(opm->config), ntohl(opm->mask)); + struct ofputil_port_mod pm; + enum ofperr error; + + error = ofputil_decode_port_mod(oh, &pm); + if (error) { + ofp_print_error(string, error); + return; + } + + ds_put_format(string, "port: %"PRIu16": addr:"ETH_ADDR_FMT"\n", + pm.port_no, ETH_ADDR_ARGS(pm.hw_addr)); + + ds_put_format(string, " config: "); + ofp_print_port_config(string, pm.config); + + ds_put_format(string, " mask: "); + ofp_print_port_config(string, pm.mask); + ds_put_format(string, " advertise: "); - if (opm->advertise) { - ofp_print_port_features(string, ntohl(opm->advertise)); + if (pm.advertise) { + ofp_print_port_features(string, pm.advertise); } else { ds_put_format(string, "UNCHANGED\n"); } @@ -955,15 +915,24 @@ ofp_print_error_msg(struct ds *string, const struct ofp_error_msg *oem) static void ofp_print_port_status(struct ds *string, const struct ofp_port_status *ops) { - if (ops->reason == OFPPR_ADD) { + struct ofputil_port_status ps; + enum ofperr error; + + error = ofputil_decode_port_status(ops, &ps); + if (error) { + ofp_print_error(string, error); + return; + } + + if (ps.reason == OFPPR_ADD) { ds_put_format(string, " ADD:"); - } else if (ops->reason == OFPPR_DELETE) { + } else if (ps.reason == OFPPR_DELETE) { ds_put_format(string, " DEL:"); - } else if (ops->reason == OFPPR_MODIFY) { + } else if (ps.reason == OFPPR_MODIFY) { ds_put_format(string, " MOD:"); } - ofp_print_phy_port(string, &ops->desc); + ofp_print_phy_port(string, &ps.desc); } static void @@ -1012,44 +981,58 @@ ofp_print_flow_stats_request(struct ds *string, cls_rule_format(&fsr.match, string); } +void +ofp_print_flow_stats(struct ds *string, struct ofputil_flow_stats *fs) +{ + ds_put_format(string, " cookie=0x%"PRIx64", duration=", + ntohll(fs->cookie)); + + ofp_print_duration(string, fs->duration_sec, fs->duration_nsec); + ds_put_format(string, ", table=%"PRIu8", ", fs->table_id); + ds_put_format(string, "n_packets=%"PRIu64", ", fs->packet_count); + ds_put_format(string, "n_bytes=%"PRIu64", ", fs->byte_count); + if (fs->idle_timeout != OFP_FLOW_PERMANENT) { + ds_put_format(string, "idle_timeout=%"PRIu16", ", fs->idle_timeout); + } + 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] != ' ') { + ds_put_char(string, ' '); + } + + ofpacts_format(fs->ofpacts, fs->ofpacts_len, string); +} + static void ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh) { + struct ofpbuf ofpacts; struct ofpbuf b; ofpbuf_use_const(&b, oh, ntohs(oh->length)); + ofpbuf_init(&ofpacts, 64); for (;;) { struct ofputil_flow_stats fs; int retval; - retval = ofputil_decode_flow_stats_reply(&fs, &b); + retval = ofputil_decode_flow_stats_reply(&fs, &b, true, &ofpacts); if (retval) { if (retval != EOF) { ds_put_cstr(string, " ***parse error***"); } break; } - ds_put_char(string, '\n'); - - ds_put_format(string, " cookie=0x%"PRIx64", duration=", - ntohll(fs.cookie)); - ofp_print_duration(string, fs.duration_sec, fs.duration_nsec); - ds_put_format(string, ", table=%"PRIu8", ", fs.table_id); - ds_put_format(string, "n_packets=%"PRIu64", ", fs.packet_count); - ds_put_format(string, "n_bytes=%"PRIu64", ", fs.byte_count); - if (fs.idle_timeout != OFP_FLOW_PERMANENT) { - ds_put_format(string, "idle_timeout=%"PRIu16",", fs.idle_timeout); - } - if (fs.hard_timeout != OFP_FLOW_PERMANENT) { - ds_put_format(string, "hard_timeout=%"PRIu16",", fs.hard_timeout); - } - - cls_rule_format(&fs.rule, string); - if (string->string[string->length - 1] != ' ') { - ds_put_char(string, ' '); - } - ofp_print_actions(string, fs.actions, fs.n_actions); + ofp_print_flow_stats(string, &fs); } } @@ -1202,6 +1185,18 @@ ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh, } } +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)); + ofpbuf_pull(&b, sizeof(struct ofp_stats_msg)); + ds_put_char(string, '\n'); + ofp_print_phy_ports(string, oh->version, &b); +} + static void ofp_print_stats_request(struct ds *string, const struct ofp_header *oh) { @@ -1276,8 +1271,8 @@ ofp_print_nxt_set_flow_format(struct ds *string, 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)); + if (ofputil_nx_flow_format_is_valid(format)) { + ds_put_cstr(string, ofputil_nx_flow_format_to_string(format)); } else { ds_put_format(string, "%"PRIu32, format); } @@ -1297,6 +1292,102 @@ 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", + ofputil_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_print_nxt_set_controller_id(struct ds *string, + const struct nx_controller_id *nci) +{ + ds_put_format(string, " id=%"PRIu16, ntohs(nci->controller_id)); +} + +void +ofp_print_version(const struct ofp_header *oh, + struct ds *string) +{ + switch (oh->version) { + case OFP10_VERSION: + break; + case OFP11_VERSION: + ds_put_cstr(string, " (OF1.1)"); + break; + case OFP12_VERSION: + ds_put_cstr(string, " (OF1.2)"); + break; + default: + ds_put_format(string, " (OF 0x%02"PRIx8")", oh->version); + break; + } + ds_put_format(string, " (xid=0x%"PRIx32"):", ntohl(oh->xid)); +} + static void ofp_to_string__(const struct ofp_header *oh, const struct ofputil_msg_type *type, struct ds *string, @@ -1305,9 +1396,8 @@ ofp_to_string__(const struct ofp_header *oh, 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)); - + ds_put_cstr(string, ofputil_msg_type_name(type)); + ofp_print_version(oh, string); code = ofputil_msg_type_code(type); switch (code) { case OFPUTIL_MSG_INVALID: @@ -1380,6 +1470,7 @@ ofp_to_string__(const struct ofp_header *oh, break; case OFPUTIL_OFPST_DESC_REQUEST: + case OFPUTIL_OFPST_PORT_DESC_REQUEST: ofp_print_stats_request(string, oh); break; @@ -1436,6 +1527,11 @@ ofp_to_string__(const struct ofp_header *oh, ofp_print_ofpst_aggregate_reply(string, msg); break; + case OFPUTIL_OFPST_PORT_DESC_REPLY: + ofp_print_stats_reply(string, oh); + ofp_print_ofpst_port_desc_reply(string, oh); + break; + case OFPUTIL_NXT_ROLE_REQUEST: case OFPUTIL_NXT_ROLE_REPLY: ofp_print_nxt_role_message(string, msg); @@ -1453,6 +1549,15 @@ ofp_to_string__(const struct ofp_header *oh, ofp_print_nxt_set_packet_in_format(string, msg); break; + case OFPUTIL_NXT_FLOW_AGE: + break; + + case OFPUTIL_NXT_SET_CONTROLLER_ID: + ofp_print_nxt_set_controller_id(string, msg); + break; + + case OFPUTIL_NXT_SET_ASYNC_CONFIG: + ofp_print_nxt_set_async_config(string, msg); break; case OFPUTIL_NXST_AGGREGATE_REPLY: @@ -1509,91 +1614,6 @@ ofp_to_string(const void *oh_, size_t len, int verbosity) ds_put_hex_dump(&string, oh, len, 0, true); return ds_steal_cstr(&string); } - -/* Returns the name for the specified OpenFlow message type as a string, - * e.g. "OFPT_FEATURES_REPLY". If no name is known, the string returned is a - * hex number, e.g. "0x55". - * - * The caller must free the returned string when it is no longer needed. */ -char * -ofp_message_type_to_string(uint8_t type) -{ - const char *name; - - switch (type) { - case OFPT_HELLO: - name = "HELLO"; - break; - case OFPT_ERROR: - name = "ERROR"; - break; - case OFPT_ECHO_REQUEST: - name = "ECHO_REQUEST"; - break; - case OFPT_ECHO_REPLY: - name = "ECHO_REPLY"; - break; - case OFPT_VENDOR: - name = "VENDOR"; - break; - case OFPT_FEATURES_REQUEST: - name = "FEATURES_REQUEST"; - break; - case OFPT_FEATURES_REPLY: - name = "FEATURES_REPLY"; - break; - case OFPT_GET_CONFIG_REQUEST: - name = "GET_CONFIG_REQUEST"; - break; - case OFPT_GET_CONFIG_REPLY: - name = "GET_CONFIG_REPLY"; - break; - case OFPT_SET_CONFIG: - name = "SET_CONFIG"; - break; - case OFPT_PACKET_IN: - name = "PACKET_IN"; - break; - case OFPT_FLOW_REMOVED: - name = "FLOW_REMOVED"; - break; - case OFPT_PORT_STATUS: - name = "PORT_STATUS"; - break; - case OFPT_PACKET_OUT: - name = "PACKET_OUT"; - break; - case OFPT_FLOW_MOD: - name = "FLOW_MOD"; - break; - case OFPT_PORT_MOD: - name = "PORT_MOD"; - break; - case OFPT_STATS_REQUEST: - name = "STATS_REQUEST"; - break; - case OFPT_STATS_REPLY: - name = "STATS_REPLY"; - break; - case OFPT_BARRIER_REQUEST: - name = "BARRIER_REQUEST"; - break; - case OFPT_BARRIER_REPLY: - name = "BARRIER_REPLY"; - break; - case OFPT_QUEUE_GET_CONFIG_REQUEST: - name = "QUEUE_GET_CONFIG_REQUEST"; - break; - case OFPT_QUEUE_GET_CONFIG_REPLY: - name = "QUEUE_GET_CONFIG_REPLY"; - break; - default: - name = NULL; - break; - } - - return name ? xasprintf("OFPT_%s", name) : xasprintf("0x%02"PRIx8, type); -} static void print_and_free(FILE *stream, char *string)