]> The Tcpdump Group git mirrors - tcpdump/commitdiff
add minimal OpenFlow decoding framework
authorDenis Ovsienko <[email protected]>
Tue, 21 May 2013 16:44:07 +0000 (20:44 +0400)
committerDenis Ovsienko <[email protected]>
Wed, 29 May 2013 09:03:23 +0000 (13:03 +0400)
This change registers OpenFlow TCP port number and adds processing of
respective packets with openflow_print(), a new function that
understands the minimal OpenFlow header format and can iterate over
messages within a snapshot that starts with the header.

Makefile.in
interface.h
print-openflow.c [new file with mode: 0644]
print-tcp.c
tcp.h

index b91e35072bf602a57580b8a872af1ea5dab38a5a..36561a3dd1a09d73ca9cd8131397b429574787b9 100644 (file)
@@ -87,7 +87,8 @@ CSRC =        addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c
        print-l2tp.c print-lane.c print-ldp.c print-lldp.c print-llc.c \
         print-lmp.c print-lspping.c print-lwapp.c \
        print-lwres.c print-mobile.c print-mpcp.c print-mpls.c print-mptcp.c print-msdp.c \
-       print-msnlb.c print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \
+       print-msnlb.c print-nfs.c print-ntp.c print-null.c print-olsr.c \
+       print-openflow.c print-ospf.c \
        print-pgm.c print-pim.c \
        print-ppi.c print-ppp.c print-pppoe.c print-pptp.c \
        print-radius.c print-raw.c print-rip.c print-rpki-rtr.c print-rrcp.c print-rsvp.c \
index bb79414977d70a2963fb6a4144a572c6ff64fd11..5c598e6c0dc533b62a0734bd0651f6480949ac57 100644 (file)
@@ -223,6 +223,7 @@ extern void ns_print(const u_char *, u_int, int);
 extern const u_char * ns_nprint (register const u_char *, register const u_char *);
 extern void ntp_print(const u_char *, u_int);
 extern u_int null_if_print(const struct pcap_pkthdr *, const u_char *);
+extern void openflow_print(const u_char *, u_int);
 extern void ospf_print(const u_char *, u_int, const u_char *);
 extern void olsr_print (const u_char *, u_int, int);
 extern void pimv1_print(const u_char *, u_int);
diff --git a/print-openflow.c b/print-openflow.c
new file mode 100644 (file)
index 0000000..9da3597
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * This module implements printing of the very basic (version-independent)
+ * OpenFlow header and iteration over OpenFlow messages. It is intended for
+ * dispatching of version-specific OpenFlow message decoding.
+ *
+ *
+ * Copyright (c) 2013 The TCPDUMP project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include "interface.h"
+#include "extract.h"
+
+#define OF_HEADER_LEN 8
+
+static void
+of_header_print(const uint8_t version, const uint8_t type,
+                      const uint16_t length, const uint32_t xid) {
+       printf("\n\tversion unknown (0x%02x), type 0x%02x, length %u, xid 0x%08x",
+              version, type, length, xid);
+}
+
+/* Print a single OpenFlow message. */
+static const u_char *
+of_header_body_print(const u_char *cp, const u_char *ep) {
+       uint8_t version, type;
+       uint16_t length;
+       uint32_t xid;
+
+       if (ep < cp + OF_HEADER_LEN)
+               goto corrupt;
+       /* version */
+       TCHECK2(*cp, 1);
+       version = *cp;
+       cp += 1;
+       /* type */
+       TCHECK2(*cp, 1);
+       type = *cp;
+       cp += 1;
+       /* length */
+       TCHECK2(*cp, 2);
+       length = EXTRACT_16BITS(cp);
+       cp += 2;
+       /* xid */
+       TCHECK2(*cp, 4);
+       xid = EXTRACT_32BITS(cp);
+       cp += 4;
+       /* Message length includes the header length and a message always includes
+        * the basic header. A message length underrun fails decoding of the rest of
+        * the current packet. At the same time, try decoding as much of the current
+        * message as possible even when it does not end within the current TCP
+        * segment. */
+       if (length < OF_HEADER_LEN) {
+               of_header_print(version, type, length, xid);
+               goto corrupt;
+       }
+       /* Decode known protocol versions further without printing the header (the
+        * type decoding is version-specific. */
+       switch (version) {
+       default:
+               of_header_print(version, type, length, xid);
+               TCHECK2(*cp, length - OF_HEADER_LEN);
+               return cp + length - OF_HEADER_LEN; /* done with current message */
+       }
+
+corrupt: /* fail current packet */
+       printf(" (corrupt)");
+       TCHECK2(*cp, ep - cp);
+       return ep;
+trunc:
+       printf(" [|openflow]");
+       return ep;
+}
+
+/* Print a TCP segment worth of OpenFlow messages presuming the segment begins
+ * on a message boundary. */
+void
+openflow_print(const u_char *cp, const u_int len) {
+       const u_char *ep = cp + len;
+
+       printf(": OpenFlow");
+       while (cp < ep)
+               cp = of_header_body_print(cp, ep);
+}
index 5f13fae1b57af18a823a0023f63fe11649c3589c..032001d1564c88cac98746b47dd39228e882409f 100644 (file)
@@ -671,6 +671,8 @@ tcp_print(register const u_char *bp, register u_int length,
 #endif
         else if (sport == BEEP_PORT || dport == BEEP_PORT)
                 beep_print(bp, length);
+        else if (sport == OPENFLOW_PORT || dport == OPENFLOW_PORT)
+                openflow_print(bp, length);
         else if (length > 2 &&
                  (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT ||
                   sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) {
diff --git a/tcp.h b/tcp.h
index 6b206feb81f728b26f0be28ad15e65bdead984a0..79b67ec5df628e2aa97b0224ee19e76beb15ca7e 100644 (file)
--- a/tcp.h
+++ b/tcp.h
@@ -97,6 +97,9 @@ struct tcphdr {
 #define BGP_PORT                179
 #endif
 #define NETBIOS_SSN_PORT        139
+#ifndef OPENFLOW_PORT
+#define OPENFLOW_PORT           6633
+#endif
 #ifndef PPTP_PORT
 #define PPTP_PORT              1723
 #endif