For SNAT, don't store the pre-fragment L2 header before actions are applied.
[sliver-openvswitch.git] / lib / ofp-print.c
index 96dd4c6..2057473 100644 (file)
@@ -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) {
@@ -740,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'
@@ -810,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,
@@ -1278,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;
@@ -1388,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'