diff --git a/docs/config-guide.md b/docs/config-guide.md
index 947fad4..3beaaac 100644
--- a/docs/config-guide.md
+++ b/docs/config-guide.md
@@ -359,6 +359,39 @@ interfaces:
            exact-match: False
 ```
 
+### Prefix Lists
+
+This construct allows to enumerate a list of IPv4 or IPv6 host addresses and/or networks. Each
+prefixlist has a name which consists of anywhere between 1 and 56 characters, and it must start
+with a letter. The syntax is straight forward:
+
+*   ***description***: A string, no longer than 64 characters, and excluding the single quote '
+    and double quote ". This string is currently not used anywhere, and serves for enduser
+    documentation purposes.
+*   ***members***: A list of zero or more entries which can take the form:
+    *    ***IPv4 Host***: an IPv4 address, eg. `192.0.2.1`
+    *    ***IPv4 Prefix***: an IPv6 prefix, eg. `192.0.2.0/24`
+    *    ***IPv6 Host***: an IPv4 address, eg. `2001:db8::1`
+    *    ***IPv6 Prefix***: an IPv6 prefix, eg. `2001:db8::0/64`
+
+***NOTE***: It is valid to have host addresses with prefixlen, for example `192.168.1.1/24`
+in other words, the prefix can be either a network or a host.
+
+A few examples:
+```
+prefixlists:
+  example:
+    description: "An example prefixlist with hosts and prefixes"
+    members:
+      - 192.0.2.1
+      - 192.0.2.0/24
+      - 2001:db8::1
+      - 2001:db8::/64
+  empty:
+    description: "An empty prefixlist"
+    members: []
+```
+
 ### Access Control Lists
 
 In VPP, a common firewall function is provided by the `acl-plugin`. The anatomy of this plugin
@@ -377,8 +410,10 @@ packets then either perform an action of `permit` or `deny` (for stateless) or `
     *   ***family***: Which IP address family to match, can be either `ipv4`, or `ipv6` or `any`,
         which is the default. If `any` is used, this term will also operate on any source and
         destination addresses, and it will emit two ACEs, one for each address family.
-    *   ***source***: The IPv4 or IPv6 source prefix, eg. `192.0.2.0/24` or `2001:db8::/64`. If
-        left empty, this means any (ie. `0.0.0.0/0` or `::/0`).
+    *   ***source***: Either an IPv4 or IPv6 host (without prefixlen, eg. `192.0.2.1` or
+        `2001:db8::1`), an IPv4 or IPv6 prefix (with prefixlen, eg. `192.0.2.0/24` or
+        `2001:db8::/64`), or a reference to the name of an existing _prefixlist_ (eg. `trusted`).
+        If left empty, this means all IPv4 and IPv6 (ie. `[ 0.0.0.0/0, ::/0 ]`).
     *   ***destination***: Similar to `source`, but for the destination field of the packets.
     *   ***protocol***: The L4 protocol, can be either a numeric value (eg. `6`), or a symbolic
         string value from `/etc/protocols` (eg. `tcp`). If omitted, only L3 matches are performed.
diff --git a/vppcfg/config/acl.py b/vppcfg/config/acl.py
index 8aef561..68d9e74 100644
--- a/vppcfg/config/acl.py
+++ b/vppcfg/config/acl.py
@@ -15,6 +15,7 @@
 import logging
 import socket
 import ipaddress
+from . import prefixlist
 
 
 def get_acls(yaml):
@@ -151,6 +152,32 @@ def get_port_low_high(portstring):
     return None, None
 
 
+def is_ip(ip_string):
+    """Return True if the given ip_string is either an IPv4/IPv6 address or prefix."""
+    if not isinstance(ip_string, str):
+        return False
+
+    try:
+        ipn = ipaddress.ip_network(ip_string, strict=False)
+        return True
+    except:
+        pass
+    return False
+
+
+def get_network_list(yaml, network_string):
+    """Return the full list of source or destination address(es). This function resolves the
+    'source' or 'destination' field, which can either be an IP address, a Prefix, or the name
+    of a Prefix List. It returns a list of ip_network() objects, including prefix. IP addresses
+    will receive prefixlen /32 or /128."""
+
+    if is_ip(network_string):
+        ipn = ipaddress.ip_network(network_string, strict=False)
+        return [ipn]
+
+    return prefixlist.get_network_list(yaml, network_string)
+
+
 def get_protocol(protostring):
     """For a given protocol string, which can be either an integer or a symbolic port
     name in /etc/protocols, return the protocol number as integer, or None if it cannot
diff --git a/vppcfg/config/test_acl.py b/vppcfg/config/test_acl.py
index 984b7b1..d307849 100644
--- a/vppcfg/config/test_acl.py
+++ b/vppcfg/config/test_acl.py
@@ -113,3 +113,30 @@ class TestACLMethods(unittest.TestCase):
         lo, hi = acl.get_icmp_low_high("10-20")
         self.assertEqual(10, lo)
         self.assertEqual(20, hi)
+
+    def test_is_ip(self):
+        self.assertTrue(acl.is_ip("192.0.2.1"))
+        self.assertTrue(acl.is_ip("192.0.2.1/24"))
+        self.assertTrue(acl.is_ip("192.0.2.0/24"))
+        self.assertTrue(acl.is_ip("2001:db8::1"))
+        self.assertTrue(acl.is_ip("2001:db8::1/64"))
+        self.assertTrue(acl.is_ip("2001:db8::/64"))
+        self.assertFalse(acl.is_ip(True))
+        self.assertFalse(acl.is_ip("String"))
+        self.assertFalse(acl.is_ip([]))
+        self.assertFalse(acl.is_ip({}))
+
+    def test_get_network_list(self):
+        for s in ["192.0.2.1", "192.0.2.1/24", "2001:db8::1", "2001:db8::1/64"]:
+            l = acl.get_network_list(self.cfg, s)
+            self.assertIsInstance(l, list)
+            self.assertEquals(1, len(l))
+            n = l[0]
+
+        l = acl.get_network_list(self.cfg, "trusted")
+        self.assertIsInstance(l, list)
+        self.assertEquals(4, len(l))
+
+        l = acl.get_network_list(self.cfg, "pl-notexist")
+        self.assertIsInstance(l, list)
+        self.assertEquals(0, len(l))