X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-print.c;h=48b8daa964570c52e3a0c3e894c1bdb9e727def7;hb=b592e72628c025ee0cc850127b90c96409c395df;hp=79e23a933ef4e6bf65014f1a3e84d358f78f5ee1;hpb=9e1fd49b0cf494315c82f27c651486ef82e83446;p=openvswitch diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 79e23a93..48b8daa9 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. @@ -36,6 +36,7 @@ #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" @@ -113,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]); @@ -146,276 +154,18 @@ 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; - const struct nx_action_fin_timeout *naft; - const struct nx_action_controller *nac; - struct mf_subfield subfield; - uint16_t port; - - switch (code) { - case OFPUTIL_OFPAT10_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_OFPAT10_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_OFPAT10_SET_VLAN_VID: - ds_put_format(s, "mod_vlan_vid:%"PRIu16, - ntohs(a->vlan_vid.vlan_vid)); - break; - - case OFPUTIL_OFPAT10_SET_VLAN_PCP: - ds_put_format(s, "mod_vlan_pcp:%"PRIu8, a->vlan_pcp.vlan_pcp); - break; - - case OFPUTIL_OFPAT10_STRIP_VLAN: - ds_put_cstr(s, "strip_vlan"); - break; - - case OFPUTIL_OFPAT10_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_OFPAT10_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_OFPAT10_SET_NW_SRC: - ds_put_format(s, "mod_nw_src:"IP_FMT, IP_ARGS(&a->nw_addr.nw_addr)); - break; - - case OFPUTIL_OFPAT10_SET_NW_DST: - ds_put_format(s, "mod_nw_dst:"IP_FMT, IP_ARGS(&a->nw_addr.nw_addr)); - break; - - case OFPUTIL_OFPAT10_SET_NW_TOS: - ds_put_format(s, "mod_nw_tos:%d", a->nw_tos.nw_tos); - break; - - case OFPUTIL_OFPAT10_SET_TP_SRC: - ds_put_format(s, "mod_tp_src:%d", ntohs(a->tp_port.tp_port)); - break; - - case OFPUTIL_OFPAT10_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; - - case OFPUTIL_NXAST_FIN_TIMEOUT: - naft = (const struct nx_action_fin_timeout *) a; - ds_put_cstr(s, "fin_timeout("); - if (naft->fin_idle_timeout) { - ds_put_format(s, "idle_timeout=%"PRIu16",", - ntohs(naft->fin_idle_timeout)); - } - if (naft->fin_hard_timeout) { - ds_put_format(s, "hard_timeout=%"PRIu16",", - ntohs(naft->fin_hard_timeout)); - } - ds_chomp(s, ','); - ds_put_char(s, ')'); - break; - - case OFPUTIL_NXAST_CONTROLLER: - nac = (const struct nx_action_controller *) a; - ds_put_cstr(s, "controller("); - if (nac->reason != OFPR_ACTION) { - ds_put_format(s, "reason=%s,", - ofputil_packet_in_reason_to_string(nac->reason)); - } - if (nac->max_len != htons(UINT16_MAX)) { - ds_put_format(s, "max_len=%"PRIu16",", ntohs(nac->max_len)); - } - if (nac->controller_id != htons(0)) { - ds_put_format(s, "id=%"PRIu16",", ntohs(nac->controller_id)); - } - ds_chomp(s, ','); - ds_put_char(s, ')'); - 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) { struct ofputil_packet_out po; + struct ofpbuf ofpacts; enum ofperr error; - error = ofputil_decode_packet_out(&po, opo); + ofpbuf_init(&ofpacts, 64); + error = ofputil_decode_packet_out(&po, opo, &ofpacts); if (error) { + ofpbuf_uninit(&ofpacts); ofp_print_error(string, error); return; } @@ -424,7 +174,7 @@ ofp_print_packet_out(struct ds *string, const struct ofp_packet_out *opo, ofputil_format_port(po.in_port, string); ds_put_char(string, ' '); - ofp_print_actions(string, po.actions, po.n_actions); + ofpacts_format(po.ofpacts, po.ofpacts_len, string); if (po.buffer_id == UINT32_MAX) { ds_put_format(string, " data_len=%zu", po.packet_len); @@ -438,6 +188,8 @@ ofp_print_packet_out(struct ds *string, const struct ofp_packet_out *opo, ds_put_format(string, " buffer=0x%08"PRIx32, po.buffer_id); } ds_put_char(string, '\n'); + + ofpbuf_uninit(&ofpacts); } /* qsort comparison function. */ @@ -454,7 +206,8 @@ compare_ports(const void *a_, const void *b_) static void ofp_print_bit_names(struct ds *string, uint32_t bits, - const char *(*bit_to_name)(uint32_t bit)) + const char *(*bit_to_name)(uint32_t bit), + char separator) { int n = 0; int i; @@ -471,7 +224,7 @@ ofp_print_bit_names(struct ds *string, uint32_t bits, const char *name = bit_to_name(bit); if (name) { if (n++) { - ds_put_char(string, ' '); + ds_put_char(string, separator); } ds_put_cstr(string, name); bits &= ~bit; @@ -480,8 +233,8 @@ ofp_print_bit_names(struct ds *string, uint32_t bits, } if (bits) { - if (n++) { - ds_put_char(string, ' '); + if (n) { + ds_put_char(string, separator); } ds_put_format(string, "0x%"PRIx32, bits); } @@ -517,7 +270,7 @@ netdev_feature_to_name(uint32_t bit) static void ofp_print_port_features(struct ds *string, enum netdev_features features) { - ofp_print_bit_names(string, features, netdev_feature_to_name); + ofp_print_bit_names(string, features, netdev_feature_to_name, ' '); ds_put_char(string, '\n'); } @@ -542,7 +295,7 @@ ofputil_port_config_to_name(uint32_t bit) static void ofp_print_port_config(struct ds *string, enum ofputil_port_config config) { - ofp_print_bit_names(string, config, ofputil_port_config_to_name); + ofp_print_bit_names(string, config, ofputil_port_config_to_name, ' '); ds_put_char(string, '\n'); } @@ -587,10 +340,11 @@ ofp_print_port_state(struct ds *string, enum ofputil_port_state state) : "STP_BLOCK")); state &= ~OFPUTIL_PS_STP_MASK; if (state) { - ofp_print_bit_names(string, state, ofputil_port_state_to_name); + ofp_print_bit_names(string, state, ofputil_port_state_to_name, + ' '); } } else { - ofp_print_bit_names(string, state, ofputil_port_state_to_name); + ofp_print_bit_names(string, state, ofputil_port_state_to_name, ' '); } ds_put_char(string, '\n'); } @@ -642,6 +396,37 @@ ofp_print_phy_port(struct ds *string, const struct ofputil_phy_port *port) 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) { @@ -704,11 +489,8 @@ ofp_print_switch_features(struct ds *string, const struct ofp_switch_features *osf) { struct ofputil_switch_features features; - struct ofputil_phy_port *ports; enum ofperr error; struct ofpbuf b; - size_t n_ports; - size_t i; error = ofputil_decode_switch_features(osf, &features, &b); if (error) { @@ -722,29 +504,15 @@ ofp_print_switch_features(struct ds *string, ds_put_cstr(string, "capabilities: "); ofp_print_bit_names(string, features.capabilities, - ofputil_capabilities_to_name); + 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); + ofputil_action_bitmap_to_name, ' '); ds_put_char(string, '\n'); - n_ports = ofputil_count_phy_ports(osf); - - ports = xmalloc(n_ports * sizeof *ports); - for (i = 0; i < n_ports; i++) { - error = ofputil_pull_switch_features_port(&b, &ports[i]); - if (error) { - ofp_print_error(string, error); - return; - } - } - qsort(ports, n_ports, sizeof *ports, compare_ports); - for (i = 0; i < n_ports; i++) { - ofp_print_phy_port(string, &ports[i]); - } - free(ports); + ofp_print_phy_ports(string, osf->header.version, &b); } static void @@ -812,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,"); @@ -851,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) == ',') { @@ -902,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, OFPUTIL_P_OF10_TID); + 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; } @@ -938,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; @@ -963,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); @@ -978,6 +755,11 @@ 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) { uint16_t flags = fm.flags; @@ -997,7 +779,8 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, } } - ofp_print_actions(s, fm.actions, fm.n_actions); + ofpacts_format(fm.ofpacts, fm.ofpacts_len, s); + ofpbuf_uninit(&ofpacts); } static void @@ -1025,6 +808,10 @@ ofp_flow_removed_reason_to_string(enum ofp_flow_removed_reason reason) 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; @@ -1194,50 +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, true); + 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); - } - 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, ' '); - } - ofp_print_actions(string, fs.actions, fs.n_actions); + ofp_print_flow_stats(string, &fs); } } @@ -1390,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) { @@ -1562,26 +1369,166 @@ ofp_print_nxt_set_controller_id(struct ds *string, } static void -ofp_to_string__(const struct ofp_header *oh, - const struct ofputil_msg_type *type, struct ds *string, - int verbosity) +ofp_print_nxt_flow_monitor_cancel(struct ds *string, + const struct ofp_header *oh) { - enum ofputil_msg_code code; - const void *msg = oh; + ds_put_format(string, " id=%"PRIu32, + ofputil_decode_flow_monitor_cancel(oh)); +} - ds_put_cstr(string, ofputil_msg_type_name(type)); +static const char * +nx_flow_monitor_flags_to_name(uint32_t bit) +{ + enum nx_flow_monitor_flags fmf = bit; + + switch (fmf) { + case NXFMF_INITIAL: return "initial"; + case NXFMF_ADD: return "add"; + case NXFMF_DELETE: return "delete"; + case NXFMF_MODIFY: return "modify"; + case NXFMF_ACTIONS: return "actions"; + case NXFMF_OWN: return "own"; + } + + return NULL; +} + +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)); + for (;;) { + struct ofputil_flow_monitor_request request; + int retval; + + retval = ofputil_decode_flow_monitor_request(&request, &b); + if (retval) { + if (retval != EOF) { + ofp_print_error(string, retval); + } + return; + } + + ds_put_format(string, "\n id=%"PRIu32" flags=", request.id); + ofp_print_bit_names(string, request.flags, + nx_flow_monitor_flags_to_name, ','); + + if (request.out_port != OFPP_NONE) { + ds_put_cstr(string, " out_port="); + ofputil_format_port(request.out_port, string); + } + + if (request.table_id != 0xff) { + ds_put_format(string, " table=%"PRIu8, request.table_id); + } + + ds_put_char(string, ' '); + cls_rule_format(&request.match, string); + ds_chomp(string, ' '); + } +} + +static void +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; + + ofpbuf_use_const(&b, oh, ntohs(oh->length)); + ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub); + for (;;) { + struct ofputil_flow_update update; + struct cls_rule match; + int retval; + + update.match = &match; + retval = ofputil_decode_flow_update(&update, &b, &ofpacts); + if (retval) { + if (retval != EOF) { + ofp_print_error(string, retval); + } + ofpbuf_uninit(&ofpacts); + return; + } + + ds_put_cstr(string, "\n event="); + switch (update.event) { + case NXFME_ADDED: + ds_put_cstr(string, "ADDED"); + break; + + case NXFME_DELETED: + ds_put_format(string, "DELETED reason=%s", + ofp_flow_removed_reason_to_string(update.reason)); + break; + + case NXFME_MODIFIED: + ds_put_cstr(string, "MODIFIED"); + break; + + case NXFME_ABBREV: + ds_put_format(string, "ABBREV xid=0x%"PRIx32, ntohl(update.xid)); + continue; + } + + ds_put_format(string, " table=%"PRIu8, update.table_id); + if (update.idle_timeout != OFP_FLOW_PERMANENT) { + ds_put_format(string, " idle_timeout=%"PRIu16, + update.idle_timeout); + } + if (update.hard_timeout != OFP_FLOW_PERMANENT) { + ds_put_format(string, " hard_timeout=%"PRIu16, + update.hard_timeout); + } + ds_put_format(string, " cookie=%#"PRIx64, ntohll(update.cookie)); + + ds_put_char(string, ' '); + cls_rule_format(update.match, string); + + if (update.ofpacts_len) { + if (string->string[string->length - 1] != ' ') { + ds_put_char(string, ' '); + } + ofpacts_format(update.ofpacts, update.ofpacts_len, string); + } + } +} + +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, + int verbosity) +{ + enum ofputil_msg_code code; + const void *msg = oh; + + 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: @@ -1654,6 +1601,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; @@ -1710,6 +1658,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); @@ -1742,6 +1695,22 @@ ofp_to_string__(const struct ofp_header *oh, ofp_print_stats_reply(string, oh); ofp_print_nxst_aggregate_reply(string, msg); break; + + case OFPUTIL_NXT_FLOW_MONITOR_CANCEL: + ofp_print_nxt_flow_monitor_cancel(string, msg); + break; + + case OFPUTIL_NXT_FLOW_MONITOR_PAUSED: + case OFPUTIL_NXT_FLOW_MONITOR_RESUMED: + break; + + case OFPUTIL_NXST_FLOW_MONITOR_REQUEST: + ofp_print_nxst_flow_monitor_request(string, msg); + break; + + case OFPUTIL_NXST_FLOW_MONITOR_REPLY: + ofp_print_nxst_flow_monitor_reply(string, msg); + break; } }