For SNAT, don't store the pre-fragment L2 header before actions are applied.
[sliver-openvswitch.git] / lib / ofp-print.c
index 75f5b5c..2057473 100644 (file)
@@ -47,8 +47,8 @@
 #include "dynamic-string.h"
 #include "flow.h"
 #include "ofpbuf.h"
-#include "openflow.h"
-#include "nicira-ext.h"
+#include "openflow/openflow.h"
+#include "openflow/nicira-ext.h"
 #include "packets.h"
 #include "util.h"
 
@@ -126,7 +126,7 @@ ofp_packet_to_string(const void *data, size_t len, size_t total_len)
     }
     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);
@@ -342,8 +342,7 @@ ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
         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;
         }
     }
@@ -399,13 +398,13 @@ ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
 
     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;
     }
 
@@ -449,7 +448,7 @@ ofp_print_actions(struct ds *string, const struct ofp_action_header *action,
                   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) {
@@ -601,7 +600,7 @@ ofp_print_switch_features(struct ds *string, const void *oh, size_t len,
                           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;
 
@@ -617,11 +616,12 @@ ofp_print_switch_features(struct ds *string, const void *oh, size_t len,
     }
     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'
@@ -739,10 +739,17 @@ static void ofp_print_match(struct ds *f, const struct ofp_match *om,
         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'
@@ -809,6 +816,65 @@ ofp_print_flow_expired(struct ds *string, const void *oh, size_t len,
          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,
@@ -1277,6 +1343,19 @@ ofp_echo(struct ds *string, const void *oh, size_t len, int verbosity)
     }
 }
 
+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;
@@ -1387,6 +1466,12 @@ static const struct openflow_packet packets[] = {
         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'