#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 -e -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;
}
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'
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)