#include "dynamic-string.h"
#include "flow.h"
#include "ofpbuf.h"
-#include "openflow.h"
+#include "openflow/openflow.h"
+#include "openflow/nicira-ext.h"
#include "packets.h"
#include "util.h"
}
rewind(pcap);
- snprintf(command, sizeof command, "tcpdump -n -r /dev/fd/%d 2>/dev/null",
+ snprintf(command, sizeof command, "/usr/sbin/tcpdump -e -n -r /dev/fd/%d 2>/dev/null",
fileno(pcap));
tcpdump = popen(command, "r");
fclose(pcap);
ds_put_cstr(string, name);
}
+static void
+ofp_print_nx_action(struct ds *string, const struct nx_action_header *nah)
+{
+
+ if (nah->subtype == htonl(NXAST_SNAT)) {
+ const struct nx_action_snat *nas = (struct nx_action_snat *)nah;
+ uint16_t port = ntohs(nas->port);
+
+ if (port < OFPP_MAX) {
+ ds_put_format(string, "nat:%"PRIu16, port);
+ } else {
+ ds_put_format(string, "nat:%"PRIu16" (invalid port)", port);
+ }
+ } else {
+ ds_put_format(string, "***unknown Nicira action:%d***\n",
+ ntohl(nah->subtype));
+ }
+}
+
static int
ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
size_t actions_len)
const struct openflow_action *act = &of_actions[type];
if ((len < act->min_size) || (len > act->max_size)) {
ds_put_format(string,
- "***action %"PRIu16" wrong length: %"PRIu16"***\n",
- type, len);
+ "***action %"PRIu16" wrong length: %zu***\n", type, len);
return -1;
}
}
case OFPAT_SET_NW_SRC: {
struct ofp_action_nw_addr *na = (struct ofp_action_nw_addr *)ah;
- ds_put_format(string, "mod_nw_src:"IP_FMT, IP_ARGS(na->nw_addr));
+ ds_put_format(string, "mod_nw_src:"IP_FMT, IP_ARGS(&na->nw_addr));
break;
}
case OFPAT_SET_NW_DST: {
struct ofp_action_nw_addr *na = (struct ofp_action_nw_addr *)ah;
- ds_put_format(string, "mod_nw_dst:"IP_FMT, IP_ARGS(na->nw_addr));
+ ds_put_format(string, "mod_nw_dst:"IP_FMT, IP_ARGS(&na->nw_addr));
break;
}
ds_put_format(string, "***ofpat_vendor truncated***\n");
return -1;
}
- ds_put_format(string, "vendor action:0x%x", ntohl(avh->vendor));
+ if (avh->vendor == htonl(NX_VENDOR_ID)) {
+ ofp_print_nx_action(string, (struct nx_action_header *)avh);
+ } else {
+ ds_put_format(string, "vendor action:0x%x", ntohl(avh->vendor));
+ }
break;
}
size_t actions_len)
{
uint8_t *p = (uint8_t *)action;
- size_t len = 0;
+ int len = 0;
ds_put_cstr(string, "actions=");
while (actions_len > 0) {
int verbosity)
{
const struct ofp_switch_features *osf = oh;
- struct ofp_phy_port port_list[OFPP_MAX];
+ struct ofp_phy_port *port_list;
int n_ports;
int i;
}
n_ports = (len - sizeof *osf) / sizeof *osf->ports;
- memcpy(port_list, osf->ports, (len - sizeof *osf));
- qsort(port_list, n_ports, sizeof port_list[0], compare_ports);
+ 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);
}
/* Pretty-print the struct ofp_switch_config of 'len' bytes at 'oh' to 'string'
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,
- "%d", ntohs(om->tp_dst));
+ if (om->nw_proto == IP_TYPE_ICMP) {
+ print_wild(f, "icmp_type=", w & OFPFW_ICMP_TYPE, verbosity,
+ "%d", ntohs(om->icmp_type));
+ print_wild(f, "icmp_code=", w & OFPFW_ICMP_CODE, verbosity,
+ "%d", ntohs(om->icmp_code));
+ } else {
+ 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,
+ "%d", ntohs(om->tp_dst));
+ }
}
/* Pretty-print the OFPT_FLOW_MOD packet of 'len' bytes at 'oh' to 'string'
ntohl(ofe->duration), ntohll(ofe->packet_count),
ntohll(ofe->byte_count));
}
+/* Pretty-print the NXT_FLOW_EXPIRED packet of 'len' bytes at 'oh' to 'string'
+ * at the given 'verbosity' level. */
+static void
+nx_print_flow_end(struct ds *string, const void *oh, size_t len,
+ int verbosity)
+{
+ const struct nx_flow_end *nfe = oh;
+
+ ds_put_cstr(string, "nx_flow_end: ");
+
+ if (len < sizeof(*nfe)) {
+ ds_put_format(string, " (***length=%zu < min_size=%zu***)\n",
+ len, sizeof(*nfe));
+ return;
+ }
+
+ ofp_print_match(string, &nfe->match, verbosity);
+ ds_put_cstr(string, " reason=");
+ switch (nfe->reason) {
+ case NXFER_IDLE_TIMEOUT:
+ ds_put_cstr(string, "idle");
+ break;
+ case NXFER_HARD_TIMEOUT:
+ ds_put_cstr(string, "hard");
+ break;
+ case NXFER_DELETE:
+ ds_put_cstr(string, "delete");
+ break;
+ case NXFER_EJECT:
+ ds_put_cstr(string, "eject");
+ break;
+ default:
+ ds_put_format(string, "**%"PRIu8"**", nfe->reason);
+ break;
+ }
+ ds_put_format(string,
+ " pri=%"PRIu16" init=%"PRIu64" used=%"PRIu64" end=%"PRIu64,
+ nfe->match.wildcards ? ntohs(nfe->priority) : (uint16_t)-1,
+ ntohll(nfe->init_time), ntohll(nfe->used_time),
+ ntohll(nfe->end_time));
+ ds_put_format(string,
+ " tflags=0x%x tos=0x%x pkts=%"PRIu64" bytes=%"PRIu64"\n",
+ nfe->tcp_flags, nfe->ip_tos, ntohll(nfe->packet_count),
+ ntohll(nfe->byte_count));
+}
+
+static void
+nx_print_msg(struct ds *string, const void *oh, size_t len, int verbosity)
+{
+ const struct nicira_header *nh = oh;
+
+ switch(ntohl(nh->subtype))
+ {
+ case NXT_FLOW_END:
+ nx_print_flow_end(string, oh, len, verbosity);
+ return;
+ }
+}
+
static void
ofp_print_port_mod(struct ds *string, const void *oh, size_t len,
ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR),
ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE),
ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT),
+
+ ERROR_TYPE(OFPET_FLOW_MOD_FAILED),
+ ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL)
};
#define N_ERROR_TYPES ARRAY_SIZE(error_types)
}
}
+static void
+ofp_vendor(struct ds *string, const void *oh, size_t len, int verbosity)
+{
+ const struct ofp_vendor_header *vh = oh;
+
+ switch(ntohl(vh->vendor))
+ {
+ case NX_VENDOR_ID:
+ return nx_print_msg(string, oh, len, verbosity);
+ break;
+ }
+}
+
struct openflow_packet {
uint8_t type;
const char *name;
sizeof (struct ofp_header),
ofp_echo,
},
+ {
+ OFPT_VENDOR,
+ "vendor",
+ sizeof (struct ofp_vendor_header),
+ ofp_vendor,
+ },
};
/* Composes and returns a string representing the OpenFlow packet of 'len'