diff --git a/vppcfg/config/address.py b/vppcfg/config/address.py
index 2afa3d9..2e1fb48 100644
--- a/vppcfg/config/address.py
+++ b/vppcfg/config/address.py
@@ -113,3 +113,33 @@ def is_allowed(yaml, ifname, iface_addresses, ip_interface):
             return False
 
     return True
+
+
+def get_canonical(iface_address):
+    """Returns the canonical form of an interface address, which can be either an address
+    '2001:db8::1' or a prefix '2001:db8::1/64' for either IPv4 of IPv6.
+
+    This function the string representation of the canonical address."""
+
+    is_prefix = "/" in iface_address
+    if is_prefix:
+        iface_address, prefixlen = iface_address.split("/")
+
+    ip_address = ipaddress.ip_address(iface_address)
+    if is_prefix:
+        return str(ip_address) + "/" + prefixlen
+    return str(ip_address)
+
+
+def is_canonical(iface_address):
+    """Checks to see that the interface address is written in a canonical form, useful to
+    ensure that IPv6 addresses are written in such a way that they don't trigger spurious
+    diffs when comparing to VPP. As an example, '2001:DB8:0:0::1/64' is fine, but VPP will
+    show this as '2001:db8::1/64'.
+
+    Input can be either an address 2001:db8::1 or a prefix 2001:db8::1/128
+
+    This function returns False if the iface_address isn't canonical, and True otherwise.
+    """
+    can = get_canonical(iface_address)
+    return can == iface_address
diff --git a/vppcfg/config/interface.py b/vppcfg/config/interface.py
index 4755a93..5d73560 100644
--- a/vppcfg/config/interface.py
+++ b/vppcfg/config/interface.py
@@ -13,6 +13,7 @@
 #
 """ A vppcfg configuration module that validates interfaces """
 import logging
+import ipaddress
 from . import bondethernet
 from . import bridgedomain
 from . import loopback
@@ -500,6 +501,12 @@ def validate_interfaces(yaml):
                         f"interface {ifname} IP address {addr} conflicts with another"
                     )
                     result = False
+                if not address.is_canonical(addr):
+                    canonical = address.get_canonical(addr)
+                    msgs.append(
+                        f"interface {ifname} IP address {addr} is not canonical, use {canonical}"
+                    )
+                    result = False
 
         if "l2xc" in iface:
             if has_sub(yaml, ifname):
diff --git a/vppcfg/config/test_address.py b/vppcfg/config/test_address.py
new file mode 100644
index 0000000..dd4c354
--- /dev/null
+++ b/vppcfg/config/test_address.py
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2022 Pim van Pelt
+#
+# 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.
+#
+# -*- coding: utf-8 -*-
+""" Unit tests for addresses """
+import unittest
+import yaml
+from . import address
+
+
+class TestAddressMethods(unittest.TestCase):
+    def test_get_canonical(self):
+        self.assertEqual(address.get_canonical("0.0.0.0"), "0.0.0.0")
+        self.assertEqual(address.get_canonical("0.0.0.0/0"), "0.0.0.0/0")
+        self.assertEqual(address.get_canonical("192.168.1.1"), "192.168.1.1")
+        self.assertEqual(address.get_canonical("192.168.1.1/32"), "192.168.1.1/32")
+        self.assertEqual(address.get_canonical("2001:db8::1"), "2001:db8::1")
+        self.assertEqual(address.get_canonical("2001:db8::1/64"), "2001:db8::1/64")
+
+        self.assertEqual(address.get_canonical("2001:dB8::1/128"), "2001:db8::1/128")
+        self.assertEqual(address.get_canonical("2001:db8:0::1/128"), "2001:db8::1/128")
+        self.assertEqual(address.get_canonical("2001:db8::0:1"), "2001:db8::1")
+
+    def test_is_canonical(self):
+        self.assertTrue(address.is_canonical("0.0.0.0"))
+        self.assertTrue(address.is_canonical("0.0.0.0/0"))
+        self.assertTrue(address.is_canonical("192.168.1.1"))
+        self.assertTrue(address.is_canonical("192.168.1.1/32"))
+        self.assertTrue(address.is_canonical("2001:db8::1"))
+        self.assertTrue(address.is_canonical("2001:db8::1/64"))
+
+        self.assertFalse(address.is_canonical("2001:dB8::1/128"))  # Capitals
+        self.assertFalse(address.is_canonical("2001:db8:0::1/128"))  # Spurious 0
+        self.assertFalse(address.is_canonical("2001:db8::0:1"))  # Spurious 0
diff --git a/vppcfg/example.yaml b/vppcfg/example.yaml
index 22bfb43..d28b773 100644
--- a/vppcfg/example.yaml
+++ b/vppcfg/example.yaml
@@ -20,7 +20,7 @@ interfaces:
     lcp: "ice12-0-0"
     mac: f2:01:00:12:00:00
     mtu: 9000
-    addresses: [ 192.0.2.17/30, 2001:db8:3::1/64 ]
+    addresses: [ 192.0.2.17/30, 2001:DB8:3::1/64 ]
     sub-interfaces:
       1234:
         mtu: 1200
diff --git a/vppcfg/unittest/yaml/correct-example1.yaml b/vppcfg/unittest/yaml/correct-example1.yaml
index 41b8057..19214cf 100644
--- a/vppcfg/unittest/yaml/correct-example1.yaml
+++ b/vppcfg/unittest/yaml/correct-example1.yaml
@@ -13,7 +13,7 @@ interfaces:
   GigabitEthernet1/0/0:
     description: "Infra: nikhef-core-1.nl.switch.coloclue.net e1/34"
     lcp: e0-0
-    addresses: [ 94.142.244.85/24, 2A02:898::146:1/64 ]
+    addresses: [ 94.142.244.85/24, 2a02:898::146:1/64 ]
     sub-interfaces:
       100:
         description: "Cust: hvn0.nlams0.ipng.ch"
diff --git a/vppcfg/unittest/yaml/error-address1.yaml b/vppcfg/unittest/yaml/error-address1.yaml
index daf8701..b9645bd 100644
--- a/vppcfg/unittest/yaml/error-address1.yaml
+++ b/vppcfg/unittest/yaml/error-address1.yaml
@@ -5,7 +5,8 @@ test:
       - "interface .* IP address .* conflicts with another"
       - "sub-interface .* IP address .* conflicts with another"
       - "loopback .* IP address .* conflicts with another"
-    count: 14
+      - "interface .* IP address .* is not canonical, use .*"
+    count: 15
 ---
 interfaces:
   GigabitEthernet1/0/0:
@@ -15,7 +16,7 @@ interfaces:
 
   GigabitEthernet1/0/1:
     lcp: e1-0-1
-    addresses: [ 192.0.2.1/29, 2001:db8:1::1/64 ]
+    addresses: [ 192.0.2.1/29, 2001:DB8:1::1/64 ]
     sub-interfaces:
       100:
         description: "These addresses overlap with Gi1/0/1"
@@ -23,6 +24,9 @@ interfaces:
       101:
         description: "These addresses overlap with loop0"
         addresses: [ 192.0.2.10/29, 2001:db8:2::2/64 ]
+      102:
+        description: "This address is not canonical"
+        addresses: [ 2001:DB8:5::1/64 ]
 
   GigabitEthernet1/0/2:
     lcp: e0-2