diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 439c56a..dec9e3e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -347,6 +347,12 @@ Please follow the style used in the code that you are modifying.  The
 [CodingStyle.md] file describes the coding style used in most of Open
 vSwitch. Use Linux kernel coding style for Linux kernel code.
 
+If your code is non-datapath code, you may use the
+`utilities/checkpatch.py` utility as a quick check for certain commonly
+occuring mistakes (improper leading/trailing whitespace, missing signoffs,
+some improper formatted patch files).  For linux datapath code, it is
+a good idea to use the linux script `checkpatch.pl`.
+
 Example
 -------
 
diff --git a/utilities/automake.mk b/utilities/automake.mk
index 674d326..155de0e 100644
--- a/utilities/automake.mk
+++ b/utilities/automake.mk
@@ -56,7 +56,8 @@ EXTRA_DIST += \
 	utilities/ovs-test.in \
 	utilities/ovs-vlan-test.in \
 	utilities/ovs-vsctl-bashcomp.bash \
-	utilities/qemu-wrap.py
+	utilities/qemu-wrap.py \
+	utilities/checkpatch.py
 MAN_ROOTS += \
 	utilities/ovs-appctl.8.in \
 	utilities/ovs-testcontroller.8.in \
@@ -146,6 +147,7 @@ utilities_nlmon_SOURCES = utilities/nlmon.c
 utilities_nlmon_LDADD = lib/libopenvswitch.la
 endif
 
-FLAKE8_PYFILES += utilities/ovs-pcap.in
+FLAKE8_PYFILES += utilities/ovs-pcap.in \
+	utilities/checkpatch.py
 
 include utilities/bugtool/automake.mk
diff --git a/utilities/checkpatch.py b/utilities/checkpatch.py
new file mode 100755
index 0000000..20863ef
--- /dev/null
+++ b/utilities/checkpatch.py
@@ -0,0 +1,217 @@
+#!/usr/bin/env python
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import print_function
+
+import email
+import getopt
+import re
+import sys
+
+__errors = 0
+__warnings = 0
+
+
+def print_error(message, lineno=None):
+    global __errors
+    if lineno is not None:
+        print("E(%d): %s" % (lineno, message))
+    else:
+        print("E: %s" % (message))
+
+    __errors = __errors + 1
+
+
+def print_warning(message, lineno=None):
+    global __warnings
+    if lineno:
+        print("W(%d): %s" % (lineno, message))
+    else:
+        print("W: %s" % (message))
+
+    __warnings = __warnings + 1
+
+
+__regex_added_line = re.compile(r'^\+{1,2}[^\+][\w\W]*')
+__regex_leading_with_whitespace_at_all = re.compile(r'^\s+')
+__regex_leading_with_spaces = re.compile(r'^ +[\S]+')
+__regex_trailing_whitespace = re.compile(r'[^\S]+$')
+__regex_for_if_missing_whitespace = re.compile(r'(if|for|while)[\(]')
+__regex_for_if_too_much_whitespace = re.compile(r'(if|for|while)  +[\(]')
+__regex_for_if_parens_whitespace = re.compile(r'(if|for|while) \( +[\s\S]+\)')
+
+skip_leading_whitespace_check = False
+skip_trailing_whitespace_check = False
+skip_block_whitespace_check = False
+skip_signoff_check = False
+
+
+def is_added_line(line):
+    """Returns TRUE if the line in question is an added line.
+    """
+    return __regex_added_line.search(line) is not None
+
+
+def leading_whitespace_is_spaces(line):
+    """Returns TRUE if the leading whitespace in added lines is spaces
+    """
+    if skip_leading_whitespace_check:
+        return True
+    if __regex_leading_with_whitespace_at_all.search(line) is not None:
+        return __regex_leading_with_spaces.search(line) is not None
+    return True
+
+
+def trailing_whitespace_or_crlf(line):
+    """Returns TRUE if the trailing characters is whitespace
+    """
+    if skip_trailing_whitespace_check:
+        return False
+    return __regex_trailing_whitespace.search(line) is not None
+
+
+def if_and_for_whitespace_checks(line):
+    """Return TRUE if there is appropriate whitespace after if, for, while
+    """
+    if skip_block_whitespace_check:
+        return True
+    if (__regex_for_if_missing_whitespace.search(line) is not None or
+            __regex_for_if_too_much_whitespace.search(line) is not None or
+            __regex_for_if_parens_whitespace.search(line)):
+        return False
+    return True
+
+
+def ovs_checkpatch_parse(text):
+    lineno = 0
+    signatures = 0
+    extra_people = 0
+    parse = 0
+    current_file = ''
+    scissors = re.compile(r'^[\w]*---[\w]*')
+    hunks = re.compile('^(---|\+\+\+) (\S+)')
+    is_signature = re.compile(r'Signed-off-by: .*$', re.I | re.M | re.S)
+
+    is_extra_people = re.compile(
+        r'^(Suggested|Tested|Reviewed|Acked|Nacked|Reported)-by: .*$',
+        re.M | re.I)
+
+    for line in text.split('\n'):
+        lineno = lineno + 1
+        if len(line) <= 0:
+            continue
+
+        if parse == 1:
+            match = hunks.match(line)
+            if match:
+                parse = parse + 1
+                current_file = match.group(2)
+            continue
+        elif parse == 0:
+            if scissors.match(line):
+                parse = parse + 1
+                if signatures == 0 and not skip_signoff_check:
+                    print_error("No signatures found.")
+            elif is_signature.match(line):
+                signatures = signatures + 1
+            elif is_extra_people.match(line):
+                extra_people = extra_people + 1
+        elif parse == 2:
+            print_line = False
+            newfile = hunks.match(line)
+            if newfile:
+                current_file = newfile.group(2)
+                continue
+            if not is_added_line(line):
+                continue
+            if (not current_file.endswith('.mk') and
+                    not leading_whitespace_is_spaces(line[1:])):
+                print_line = True
+                print_warning("Line has non-spaces leading whitespace",
+                              lineno)
+            if trailing_whitespace_or_crlf(line[1:]):
+                print_line = True
+                print_warning("Line has trailing whitespace", lineno)
+            if len(line[1:]) > 80:
+                print_line = True
+                print_warning("Line is greater than 80-characters long",
+                              lineno)
+            if not if_and_for_whitespace_checks(line[1:]):
+                print_line = True
+                print_warning("Improper whitespace around control block",
+                              lineno)
+            if print_line:
+                print(line)
+    if __errors or __warnings:
+        return -1
+    return 0
+
+
+def ovs_checkpatch_file(filename):
+    try:
+        mail = email.message_from_file(open(filename, 'r'))
+    except:
+        print_error("Unable to parse file '%s'. Is it a patch?" % filename)
+        return -1
+
+    for part in mail.walk():
+        if part.get_content_maintype() == 'multipart':
+            continue
+        return ovs_checkpatch_parse(part.get_payload(decode=True))
+
+if __name__ == '__main__':
+    try:
+        optlist, args = getopt.getopt(sys.argv[1:], 'bhlst',
+                                      ["help",
+                                       "skip-block-whitespace",
+                                       "skip-leading-whitespace",
+                                       "skip-signoff-lines",
+                                       "skip-trailing-whitespace"])
+    except:
+        print("Unknown option encountered. Please rerun with -h for help.")
+        sys.exit(-1)
+
+    for o, a in optlist:
+        if o in ("-h", "--help"):
+            print("Open vSwitch checkpatch.py")
+            print("Checks a patch for trivial mistakes.")
+            print("usage:")
+            print("%s [options] [patch file]" % sys.argv[0])
+            print("options:")
+            print("-h|--help\t\t\t\tThis help message")
+            print("-b|--skip-block-whitespace\t"
+                  "Skips the if/while/for whitespace tests")
+            print("-l|--skip-leading-whitespace\t"
+                  "Skips the leading whitespace test")
+            print("-s|--skip-signoff-lines\t"
+                  "Do not emit an error if no Signed-off-by line is present")
+            print("-t|--skip-trailing-whitespace\t"
+                  "Skips the trailing whitespace test")
+            sys.exit(0)
+        elif o in ("-b", "--skip-block-whitespace"):
+            skip_block_whitespace_check = True
+        elif o in ("-l", "--skip-leading-whitespace"):
+            skip_leading_whitespace_check = True
+        elif o in ("-s", "--skip-signoff-lines"):
+            skip_signoff_check = True
+        elif o in ("-t", "--skip-trailing-whitespace"):
+            skip_trailing_whitespace_check = True
+        else:
+            print("Unknown option '%s'" % o)
+            sys.exit(-1)
+    try:
+        filename = args[0]
+    except:
+        sys.exit(ovs_checkpatch_parse(sys.stdin.read()))
+    sys.exit(ovs_checkpatch_file(filename))
