#include <stdlib.h>
#include <ctype.h>
+#include "buffer.h"
#include "compiler.h"
#include "dynamic-string.h"
+#include "flow.h"
#include "util.h"
#include "openflow.h"
#include "packets.h"
static void ofp_print_port_name(struct ds *string, uint16_t port);
+static void ofp_print_match(struct ds *, const struct ofp_match *,
+ int verbosity);
/* Returns a string that represents the contents of the Ethernet frame in the
* 'len' bytes starting at 'data' to 'stream' as output by tcpdump.
ds_put_char(string, '\n');
if (verbosity > 0) {
+ struct flow flow;
+ struct buffer packet;
+ struct ofp_match match;
+ packet.data = (void *) op->data;
+ packet.size = data_len;
+ flow_extract(&packet, ntohs(op->in_port), &flow);
+ match.wildcards = 0;
+ match.in_port = flow.in_port;
+ memcpy(match.dl_src, flow.dl_src, ETH_ADDR_LEN);
+ memcpy(match.dl_dst, flow.dl_dst, ETH_ADDR_LEN);
+ match.dl_vlan = flow.dl_vlan;
+ match.dl_type = flow.dl_type;
+ match.nw_proto = flow.nw_proto;
+ match.pad = 0;
+ match.nw_src = flow.nw_src;
+ match.nw_dst = flow.nw_dst;
+ match.tp_src = flow.tp_src;
+ match.tp_dst = flow.tp_dst;
+ ofp_print_match(string, &match, verbosity);
+ ds_put_char(string, '\n');
+ }
+ if (verbosity > 1) {
char *packet = ofp_packet_to_string(op->data, data_len,
ntohs(op->total_len));
ds_put_cstr(string, packet);
ds_put_char(string, ',');
}
+static void
+print_ip_netmask(struct ds *string, const char *leader, uint32_t ip,
+ uint32_t wild_bits, int verbosity)
+{
+ if (wild_bits >= 32 && verbosity < 2) {
+ return;
+ }
+ ds_put_cstr(string, leader);
+ if (wild_bits < 32) {
+ ds_put_format(string, IP_FMT, IP_ARGS(&ip));
+ if (wild_bits) {
+ ds_put_format(string, "/%d", 32 - wild_bits);
+ }
+ } else {
+ ds_put_char(string, '*');
+ }
+ ds_put_char(string, ',');
+}
+
/* Pretty-print the ofp_match structure */
static void ofp_print_match(struct ds *f, const struct ofp_match *om,
int verbosity)
{
- uint16_t w = ntohs(om->wildcards);
-
+ uint32_t w = ntohl(om->wildcards);
+ bool skip_type = false;
+ bool skip_proto = false;
+
+ if (!(w & OFPFW_DL_TYPE)) {
+ skip_type = true;
+ if (om->dl_type == htons(ETH_TYPE_IP)) {
+ if (!(w & OFPFW_NW_PROTO)) {
+ skip_proto = true;
+ if (om->nw_proto == IP_TYPE_ICMP) {
+ ds_put_cstr(f, "icmp,");
+ } else if (om->nw_proto == IP_TYPE_TCP) {
+ ds_put_cstr(f, "tcp,");
+ } else if (om->nw_proto == IP_TYPE_UDP) {
+ ds_put_cstr(f, "udp,");
+ } else {
+ ds_put_cstr(f, "ip,");
+ skip_proto = false;
+ }
+ } else {
+ ds_put_cstr(f, "ip,");
+ }
+ } else if (om->dl_type == htons(ETH_TYPE_ARP)) {
+ ds_put_cstr(f, "arp,");
+ } else {
+ skip_type = false;
+ }
+ }
print_wild(f, "in_port=", w & OFPFW_IN_PORT, verbosity,
"%d", ntohs(om->in_port));
print_wild(f, "dl_vlan=", w & OFPFW_DL_VLAN, verbosity,
ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src));
print_wild(f, "dl_dst=", w & OFPFW_DL_DST, verbosity,
ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_dst));
- print_wild(f, "dl_type=", w & OFPFW_DL_TYPE, verbosity,
- "0x%04x", ntohs(om->dl_type));
- print_wild(f, "nw_src=", w & OFPFW_NW_SRC, verbosity,
- IP_FMT, IP_ARGS(&om->nw_src));
- print_wild(f, "nw_dst=", w & OFPFW_NW_DST, verbosity,
- IP_FMT, IP_ARGS(&om->nw_dst));
- print_wild(f, "nw_proto=", w & OFPFW_NW_PROTO, verbosity,
- "%u", om->nw_proto);
+ if (!skip_type) {
+ print_wild(f, "dl_type=", w & OFPFW_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);
+ print_ip_netmask(f, "nw_dst=", om->nw_dst,
+ (w & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT, verbosity);
+ if (!skip_proto) {
+ print_wild(f, "nw_proto=", w & OFPFW_NW_PROTO, verbosity,
+ "%u", om->nw_proto);
+ }
print_wild(f, "tp_src=", w & OFPFW_TP_SRC, verbosity,
"%d", ntohs(om->tp_src));
print_wild(f, "tp_dst=", w & OFPFW_TP_DST, verbosity,
}
}
+static void
+switch_status_reply(struct ds *string, const void *body, size_t len,
+ int verbosity UNUSED)
+{
+ char *save_ptr = NULL;
+ char *s, *line;
+
+ s = xmemdup0(body, len);
+ for (line = strtok_r(s, "\n\n", &save_ptr); line != NULL;
+ line = strtok_r(NULL, "\n\n", &save_ptr)) {
+ ds_put_printable(string, line, strlen(line));
+ ds_put_char(string, '\n');
+ }
+ free(s);
+}
+
enum stats_direction {
REQUEST,
REPLY
{ 0, 0, NULL, },
{ 0, SIZE_MAX, ofp_port_stats_reply },
},
+ [OFPST_SWITCH] = {
+ "switch status",
+ { 0, 0, NULL, },
+ { 0, SIZE_MAX, switch_status_reply },
+ },
};
const struct stats_type *s;