Parcourir la source

[master] Merge branch 'trac5396' (docs for shared network commands)

Tomek Mrugalski il y a 7 ans
Parent
commit
b9e652574d

+ 0 - 0
.gitmodules


+ 4 - 6
doc/examples/kea6/iPXE.json

@@ -1,13 +1,11 @@
-// This is and example configuration for iPXE boot in Kea6.
+// This is an example configuration for iPXE boot in Kea6.
 
 {
    "Dhcp6": {
-   // mandatory part of the config that list interfaces on which
-   //  kea will listen to incoming traffic
+   // Mandatory part of the config that list interfaces on which
+   // Kea will listen for incoming traffic.
       "interfaces-config": {
-         "interfaces": [
-            "ethX"
-         ]
+         "interfaces": [ "ethX" ]
       },
 
 // Two classes are migrated form ISC-DHCP example:

+ 27 - 13
doc/guide/ctrl-channel.xml

@@ -175,7 +175,7 @@
     the form:
 <screen>
 {
-    "result": 0|1,
+    "result": 0|1|2|3,
     "text": "textual description",
     "arguments": {
         "argument1": "value1",
@@ -185,14 +185,26 @@
 }
 </screen>
     <command>result</command> indicates the outcome of the command. A value of 0
-    means success while any non-zero value designates an error. Currently 1 is
-    used as a generic error, but additional error codes may be added in the
-    future. The <command>text</command> field typically appears when result is
-    non-zero and contains a description of the error encountered, but it may
-    also appear for successful results (that is command specific).
-    <command>arguments</command> is a map of additional data values returned by
-    the server which is specific to the command issued. The map is always present, even
-    if it contains no data values.</para>
+    means success while any non-zero value designates an error or at least a
+    failure to complete the requested action. Currently 1 is used as a generic
+    error, 2 means that a command is not supported and 3 means that the
+    requested operation was completed, but the requested object was not
+    found. Additional error codes may be added in the future. For example a well
+    formed command that requests a subnet that exists in server's configuration
+    would return result 0. If the server encounters an error condition, it would
+    return 1. If the command was asking for IPv6 subnet, but was sent to DHCPv4
+    server, it would return 2. If the query was asking for a subnet-id and there
+    is no subnet with such id, the result would be set to 3.</para>
+
+    <para>
+    The <command>text</command> field typically appears when result is non-zero
+    and contains a description of the error encountered, but it often also appears
+    for successful outcomes. The exact text is command specific, but in general
+    uses plain English to describe the outcome of the command.
+    <command>arguments</command> is a map of additional data values
+    returned by the server which is specific to the command issued. The map is
+    may be present, but that depends on specific command.
+    </para>
 
     <note>
       <simpara>
@@ -211,7 +223,7 @@
     <para>Kea development team is actively working on providing client applications
     which can be used to control the servers. These applications are, however, in the
     early stages of development and as of Kea 1.2.0 release have certain limitations.
-    The easiest way to start playing with the control API is to use common Unix/Linux tools
+    The easiest way to start interacting with the control API is to use common Unix/Linux tools
     such as <command>socat</command> and <command>curl</command>.</para>
 
     <para>In order to control the given Kea service via unix domain socket, use
@@ -222,14 +234,16 @@ $ socat UNIX:/path/to/the/kea/socket -
 where <command>/path/to/the/kea/socket</command> is the path specified in the
 <command>Dhcp4/control-socket/socket-name</command> parameter in the Kea
 configuration file. Text passed to <command>socat</command>
-will be sent to Kea and the responses received from Kea printed to standard output.</para>
+will be sent to Kea and the responses received from Kea printed to standard
+    output. This approach communicates with the specific server directly and
+    bypasses Control Agent.</para>
 
     <para>It is also easy to open UNIX socket programmatically. An example of
     such a simplistic client written in C is available in the Kea Developer's
     Guide, chapter Control Channel Overview, section Using Control Channel.</para>
 
-    <para>In order to use Kea's RESTful API with <command>curl</command> try the
-    following:
+    <para>In order to use Kea's RESTful API with <command>curl</command> you may
+    use the following:
 <screen>
 $ curl -X POST -H "Content-Type: application/json" -d '{ "command": "config-get", "service": [ "dhcp4" ] }' http://ca.example.org:8000/
 </screen>

+ 359 - 8
doc/guide/hooks.xml

@@ -1721,12 +1721,15 @@ An example IPv4 lease deletion by "hw-address" looks as follows:
         <title>subnet_cmds: Subnet Commands</title>
         <para>
           This section describes a hook application that offers a number of new
-          commands used to query and manipulate subnet configurations in Kea.
-          This application is very useful in deployments with a large number of
-          subnets being managed by the DHCP servers and when the subnets are
-          frequently updated. The commands offer lightweight approach for
-          manipulating subnets without a need to fully reconfigure the server
-          and without affecting existing servers' configurations.
+          commands used to query and manipulate subnet and shared network
+          configurations in Kea.  This application is very useful in deployments
+          with a large number of subnets being managed by the DHCP servers and
+          when the subnets are frequently updated. The commands offer
+          lightweight approach for manipulating subnets without a need to fully
+          reconfigure the server and without affecting existing servers'
+          configurations. An ability to manage shared networks (listing,
+          retrieving details, adding new ones, removing existing ones, adding
+          subnets to and removing from shared networks) is also provided.
         </para>
 
         <para>Currently this library is only available to ISC customers with a
@@ -1740,7 +1743,7 @@ An example IPv4 lease deletion by "hw-address" looks as follows:
           </listitem>
           <listitem>
           <simpara>
-            <command>subnet4-get/subnet6-get</command>: retrieves detailed information about a selected subnet
+            <command>subnet4-get/subnet6-get</command>: retrieves detailed information about a specified subnet
           </simpara>
           </listitem>
           <listitem>
@@ -1753,6 +1756,45 @@ An example IPv4 lease deletion by "hw-address" looks as follows:
             <command>subnet4-del/subnet6-del</command>: removes a subnet from the server's configuration
           </simpara>
           </listitem>
+
+          <listitem>
+          <simpara>
+            <command>network4-list/network6-list</command>: lists all configured
+            shared networks
+          </simpara>
+          </listitem>
+          <listitem>
+          <simpara>
+            <command>network4-get/network6-get</command>: retrieves detailed
+            information about specified shared network
+          </simpara>
+          </listitem>
+          <listitem>
+          <simpara>
+            <command>network4-add/network6-add</command>: adds a new shared
+            network to the server's configuration
+          </simpara>
+          </listitem>
+          <listitem>
+          <simpara>
+            <command>network4-del/network6-del</command>: removes a shared
+            network from the server's configuration
+          </simpara>
+          </listitem>
+          <listitem>
+          <simpara>
+            <command>network4-subnet-add/network6-subnet-add</command>: adds
+            existing subnet to existing shared network
+          </simpara>
+          </listitem>
+          <listitem>
+          <simpara>
+            <command>network4-subnet-del/network6-subnet-del</command>: removes
+            a subnet from existing shared network and demotes it to a plain
+            subnet.
+          </simpara>
+          </listitem>
+
         </itemizedlist>
         </para>
 
@@ -2094,6 +2136,12 @@ If the subnet exists the response will be similar to this:
           new subnet. Thus, we recommend that this command is used with extreme
           caution.
         </para>
+        <para>
+          This command can also be used to completely delete an IPv4 subnet that
+          is part of a shared network. If you want to simply remove the subnet
+          from a shared network and keep the subnet configuration, use
+          <command>network4-subnet-del</command> command instead.
+        </para>
 
         <para>The command has the following structure:
 <screen>
@@ -2148,6 +2196,12 @@ If the subnet exists the response will be similar to this:
           new subnet. Thus, we recommend that this command is used with extreme
           caution.
         </para>
+        <para>
+          This command can also be used to completely delete an IPv6 subnet that
+          is part of a shared network. If you want to simply remove the subnet
+          from a shared network and keep the subnet configuration, use
+          <command>network6-subnet-del</command> command instead.
+        </para>
 
         <para>The command has the following structure:
 <screen>
@@ -2176,8 +2230,305 @@ If the subnet exists the response will be similar to this:
         </para>
       </section>
 
+      <section>
+        <title>network4-list, network6-list commands</title>
+        <para>
+          These commands are used to retrieve full list of currently configured
+          shared networks. The list contains only very basic information about
+          each shared network. If more details are needed, please use
+          <command>network4-get</command> or <command>network6-get</command> to
+          retrieve all information available. This command does not require any
+          parameters and its invocation is very simple:
+<screen>
+{
+    "command": "network4-list"
+}
+</screen>
+An example response for <command>network4-list</command> looks as follows:
+<screen>
+{
+    "arguments": {
+        "shared-networks": [
+            { "name": "floor1" },
+            { "name": "office" }
+        ]
+    },
+    "result": 0,
+    "text": "2 IPv4 network(s) found"
+}</screen>
+<command>network6-list</command> follows exactly the same syntax for
+both the query and the response.
+        </para>
+    </section>
+
+    <section>
+        <title>network4-get, network6-get commands</title>
+        <para>
+          These commands are used to retrieve detailed information
+          about shared networks, including subnets currently
+          being part of a given network. Both commands take one
+          mandatory parameter <command>name</command>, which specify
+          the name of shared network. An example command to retrieve
+          details about IPv4 shared network with a name "floor13"
+          looks as follows:
+<screen>
+{
+    "command": "network4-get",
+    "arguments": {
+        "name": "floor13"
+    }
+}</screen>
+An example response could look as follows:
+<screen>
+{
+    "result": 0,
+    "text": "Info about IPv4 shared network 'floor13' returned",
+    "arguments": {
+        "shared-networks": [
+        {
+            "match-client-id": true,
+            "name": "floor13",
+            "option-data": [ ],
+            "rebind-timer": 90,
+            "relay": {
+                "ip-address": "0.0.0.0"
+            },
+            "renew-timer": 60,
+            "reservation-mode": "all",
+            "subnet4": [
+                {
+                    "subnet": "192.0.2.0/24",
+                    "id": 5,
+                    // many other subnet specific details here
+                },
+                {
+                    "id": 6,
+                    "subnet": "192.0.3.0/31",
+                    // many other subnet specific details here
+                }
+            ],
+            "valid-lifetime": 120
+        }
+        ]
+    }
+}
+</screen>
+Note that actual response contains many additional fields that are
+omitted here for clarity. The response format is exactly the same as
+used in <command>config-get</command>, just is limited to returning
+shared networks information.
+        </para>
+    </section>
+
+    <section>
+        <title>network4-add, network6-add commands</title>
+        <para>
+          These commands are used to add a new shared network. New
+          network has to have unique name. This command requires one parameter
+          <command>shared-networks</command>, which is a list and
+          should contain exactly one entry that defines the
+          network. The only mandatory element for a network is its
+          name. Although it does not make operational sense, it is
+          allowed to add an empty shared network that does not have
+          any subnets in it. That is allowed for testing purposes, but
+          having empty networks (or with only one subnet) is
+          discouraged in production environments. For details regarding
+          syntax, see <xref linkend="shared-network4"/> and <xref
+          linkend="shared-network6"/>.
+        </para>
+        <note><para>As opposed to parameter inheritance during full
+          new configuration processing, this command does not fully handle
+          parameter inheritance and any missing parameters will be
+          filled with default values, rather than inherited from
+          global scope.</para></note>
+        <para>
+          An example that showcases how to add a new IPv4 shared network looks
+          as follows:
+<screen>
+{
+    "command": "network4-add",
+    "arguments": {
+        "shared-networks": [ {
+            "name": "floor13",
+            "subnet4": [
+            {
+                "id": 100,
+                "pools": [ { "pool": "192.0.2.2-192.0.2.99" } ],
+                "subnet": "192.0.2.0/24",
+                "option-data": [
+                    {
+                        "name": "routers",
+                        "data": "192.0.2.1"
+                    }
+                ]
+            },
+            {
+                "id": 101,
+                "pools": [ { "pool": "192.0.3.2-192.0.3.99" } ],
+                "subnet": "192.0.3.0/24",
+                "option-data": [
+                    {
+                        "name": "routers",
+                        "data": "192.0.3.1"
+                    }
+                ]
+            } ]
+        } ]
+    }
+}
+</screen>
+Assuming there was no shared network with a name floor13 and no subnets with id
+100 and 101 previously configured, the command will be successful and will
+return the following response:
+<screen>
+{
+    "arguments": {
+        "shared-networks": [ { "name": "floor13" } ]
+    },
+    "result": 0,
+    "text": "A new IPv4 shared network 'floor13' added"
+}
+</screen>
+The <command>network6-add</command> uses the same syntax for both the query and
+the response. However, there are some parameters that are IPv4-only
+(e.g. match-client-id) and some are IPv6-only (e.g. interface-id). The same
+applies to subnets within the network.
+        </para>
+    </section>
+    <section>
+        <title>network4-del, network6-del commands</title>
+        <para>
+          These commands are used to delete existing shared networks. Each
+          subnet within the network being removed will be demoted to a plain
+          subnet. If you want to completely remove the subnets, please use
+          <command>subnet4-del</command> or <command>subnet6-del</command>
+          commands. Both commands take exactly one parameter 'name' that
+          specifies the name of the network to be removed. An example invocation
+          of <command>network4-del</command> command looks as follows:
+<screen>
+{
+    "command": "network4-del",
+    "arguments": {
+        "name": "floor13"
+    }
+}
+</screen>
+Assuming there was such a network configured, the response will look similar to
+the following:
+<screen>
+{
+    "arguments": {
+        "shared-networks": [
+            {
+                "name": "floor1"
+            }
+        ]
+    },
+    "result": 0,
+    "text": "IPv4 shared network 'floor13' deleted"
+}</screen>
+The <command>network6-del</command> command uses exactly the same syntax for
+both the command and the response.
+        </para>
+
+    </section>
+    <section>
+        <title>network4-subnet-add, network6-subnet-add commands</title>
+        <para>
+          These commands are used to add existing subnets to existing shared
+          networks. There are several ways to add new shared network. System
+          administrator can add the whole shared network at once, either by
+          editing a configuration file or by calling
+          <command>network4-add</command> or <command>network6-add</command>
+          commands with desired subnets in it. This approach works better for completely
+          new shared subnets. However, there may be cases when an existing
+          subnet is running out of addresses and needs to be extended with
+          additional address space. In other words another subnet has to be
+          added on top of it. For this scenario, a system administrator can use
+          <command>network4-add</command> or <command>network6-add</command> and
+          then add existing subnet to this newly created shared network  using
+          <command>network4-subnet-add</command> or
+          <command>network6-subnet-add</command>.
+        </para>
+        <para>
+          The <command>network4-subnet-add</command> and
+          <command>network6-subnet-add</command> commands take two parameters:
+          <command>id</command>, which is an integer and specifies subnet-id of existing subnet to
+          be added to a shared network; and <command>name</command>, which
+          specifies name of the shared network the subnet will be added to. The
+          subnet must not belong to any existing network. In case you want to
+          reassign a subnet from one shared network to another, please use
+          <command>network4-subnet-del</command> or
+          <command>network6-subnet-del</command> commands first.
+        </para>
+        <para>
+          An example invocation of <command>network4-subnet-add</command>
+          command looks as follows:
+<screen>
+{
+    "command": "network4-subnet-add",
+    "arguments": {
+        "name": "floor13",
+        "id": 5
+    }
+}</screen>
+Assuming there is a network named 'floor13', there is a subnet with subnet-id 5
+and it is not a part of existing network, the command will return a response
+similar to the following:
+<screen>
+{
+    "result": 0,
+    "text": "IPv4 subnet 10.0.0.0/8 (id 5) is now part of shared network 'floor1'"
+}</screen>
+        The <command>network6-subnet-add</command> command uses exactly the same syntax for
+both the command and the response.
+        </para>
+
+        <note><para>As opposed to parameter inheritance during full
+          new configuration processing or when adding a new shared network with
+          new subnets, this command does not fully handle
+          parameter inheritance and any missing parameters will be
+          filled with default values, rather than inherited from
+          global scope or from the shared network.</para></note>
+    </section>
+    <section>
+        <title>network4-subnet-del, network6-subnet-del commands</title>
+        <para>
+          These commands are used to remove a subnet that is part of existing shared
+          network and demote it to a plain, stand-alone subnet. If you want to
+          remove a subnet completely, use <command>subnet4-del</command> or
+          <command>subnet6-del</command> commands instead.
+          The <command>network4-subnet-del</command> and
+          <command>network6-subnet-del</command> commands take two parameters:
+          <command>id</command>, which is an integer and specifies subnet-id of
+          existing subnet to be removed from a shared network; and
+          <command>name</command>, which specifies name of the shared network
+          the subnet will be removed from.
+        </para>
+        <para>An example invocation of the
+        <command>network4-subnet-del</command> command looks as follows:
+ <screen>
+ {
+    "command": "network4-subnet-del",
+    "arguments": {
+        "name": "floor13",
+        "id": 5
+    }
+ }</screen>
+ Assuming there was a subnet with subnet-id equal to 5 that was part of a shared
+ network named 'floor13', the response would look similar to the following:
+<screen>
+{
+    "result": 0,
+    "text": "IPv4 subnet 10.0.0.0/8 (id 5) is now removed from shared network 'floor13'"
+}</screen>
+The <command>network6-subnet-del</command> command uses exactly the same syntax for
+both the command and the response.
+        </para>
+    </section>
+
     </section>
-</section> <!-- end of subnet commands -->
+  </section> <!-- end of subnet commands -->
 
     <section id="user-context">
       <title>User contexts</title>

+ 1 - 0
premium

@@ -0,0 +1 @@
+Subproject commit 133a3165f244adb0ed50cc3a59e3e4a86f1e10bc

+ 4 - 1
src/lib/dhcpsrv/cfg_shared_networks.h

@@ -58,8 +58,11 @@ public:
         auto& index = networks_.template get<SharedNetworkNameIndexTag>();
         auto shared_network = index.find(name);
         if (shared_network != index.end()) {
-            index.erase(shared_network);
+            // Delete all subnets from the network
+            (*shared_network)->delAll();
 
+            // Then delete the network from the networks list.
+            index.erase(shared_network);
         } else {
             isc_throw(BadValue, "unable to delete non-existing network '"
                       << name << "' from shared networks configuration");

+ 15 - 0
src/lib/dhcpsrv/shared_network.cc

@@ -219,6 +219,14 @@ SharedNetwork4::del(const SubnetID& subnet_id) {
     clearSharedNetwork(subnet);
 }
 
+void
+SharedNetwork4::delAll() {
+    for (auto subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) {
+        clearSharedNetwork(*subnet);
+    }
+    subnets_.clear();
+}
+
 Subnet4Ptr
 SharedNetwork4::getSubnet(const SubnetID& subnet_id) const {
     return (Impl::getSubnet<Subnet4Ptr>(subnets_, subnet_id));
@@ -267,6 +275,13 @@ SharedNetwork6::del(const SubnetID& subnet_id) {
     clearSharedNetwork(subnet);
 }
 
+void
+SharedNetwork6::delAll() {
+    for (auto subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) {
+        clearSharedNetwork(*subnet);
+    }
+    subnets_.clear();
+}
 Subnet6Ptr
 SharedNetwork6::getSubnet(const SubnetID& subnet_id) const {
     return (Impl::getSubnet<Subnet6Ptr>(subnets_, subnet_id));

+ 6 - 0
src/lib/dhcpsrv/shared_network.h

@@ -86,6 +86,9 @@ public:
     /// @throw BadValue When specified subnet doesn't exist.
     void del(const SubnetID& subnet_id);
 
+    /// @brief Removes all subnets from a shared network.
+    void delAll();
+
     /// @brief Returns a pointer to the collection of subnets within this
     /// shared network.
     const Subnet4Collection* getAllSubnets() const {
@@ -217,6 +220,9 @@ public:
     /// @throw BadValue When specified subnet doesn't exist.
     void del(const SubnetID& subnet_id);
 
+    /// @brief Removes all subnets from a shared network.
+    void delAll();
+
     /// @brief Returns a pointer to the collection of subnets within this
     /// shared network.
     const Subnet6Collection* getAllSubnets() const {

+ 33 - 0
src/lib/dhcpsrv/tests/cfg_shared_networks4_unittest.cc

@@ -8,10 +8,12 @@
 #include <exceptions/exceptions.h>
 #include <dhcpsrv/cfg_shared_networks.h>
 #include <testutils/test_to_element.h>
+#include <asiolink/io_address.h>
 #include <gtest/gtest.h>
 
 using namespace isc;
 using namespace isc::dhcp;
+using namespace asiolink;
 
 namespace {
 
@@ -62,6 +64,37 @@ TEST(CfgSharedNetworks4Test, deleteByName) {
     ASSERT_THROW(cfg.del(network2->getName()), BadValue);
 }
 
+// Checks that subnets have their shared network pointers updated when
+// the network is deleted. This is used when the shared network is deleted
+// by admin commands.
+TEST(CfgSharedNetworks4Test, deleteNetworkWithSubnets) {
+    CfgSharedNetworks4 cfg;
+    SharedNetwork4Ptr network(new SharedNetwork4("frog"));
+    SubnetID id1(100);
+    SubnetID id2(101);
+    Subnet4Ptr sub1(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3, id1));
+    Subnet4Ptr sub2(new Subnet4(IOAddress("192.0.3.0"), 24, 1, 2, 3, id2));
+    network->add(sub1);
+    network->add(sub2);
+    cfg.add(network);
+
+    // Make sure the subnets are part of the network.
+    SharedNetwork4Ptr test;
+    sub1->getSharedNetwork(test);
+    EXPECT_TRUE(test);
+    EXPECT_EQ(network->toElement()->str(), test->toElement()->str());
+    sub2->getSharedNetwork(test);
+    EXPECT_TRUE(test);
+    EXPECT_EQ(network->toElement()->str(), test->toElement()->str());
+
+    // Now remove the network. Subnets should be disassociated with the network.
+    cfg.del("frog");
+    sub1->getSharedNetwork(test);
+    EXPECT_FALSE(test);
+    sub2->getSharedNetwork(test);
+    EXPECT_FALSE(test);
+}
+
 // This test verifies that shared networks must have unique names.
 TEST(CfgSharedNetworks4Test, duplicateName) {
     SharedNetwork4Ptr network1(new SharedNetwork4("frog"));

+ 33 - 0
src/lib/dhcpsrv/tests/cfg_shared_networks6_unittest.cc

@@ -7,11 +7,13 @@
 #include <config.h>
 #include <exceptions/exceptions.h>
 #include <dhcpsrv/cfg_shared_networks.h>
+#include <asiolink/io_address.h>
 #include <testutils/test_to_element.h>
 #include <gtest/gtest.h>
 
 using namespace isc;
 using namespace isc::dhcp;
+using namespace asiolink;
 
 namespace {
 
@@ -62,6 +64,37 @@ TEST(CfgSharedNetworks6Test, deleteByName) {
     ASSERT_THROW(cfg.del(network2->getName()), BadValue);
 }
 
+// Checks that subnets have their shared network pointers updated when
+// the network is deleted. This is used when the shared network is deleted
+// by admin commands.
+TEST(CfgSharedNetworks6Test, deleteNetworkWithSubnets) {
+    CfgSharedNetworks6 cfg;
+    SharedNetwork6Ptr network(new SharedNetwork6("frog"));
+    SubnetID id1(100);
+    SubnetID id2(101);
+    Subnet6Ptr sub1(new Subnet6(IOAddress("2001:db8::"), 48, 1, 2, 3, 4, id1));
+    Subnet6Ptr sub2(new Subnet6(IOAddress("fec0::"), 12, 1, 2, 3, 4, id2));
+    network->add(sub1);
+    network->add(sub2);
+    cfg.add(network);
+
+    // Make sure the subnets are part of the network.
+    SharedNetwork6Ptr test;
+    sub1->getSharedNetwork(test);
+    EXPECT_TRUE(test);
+    EXPECT_EQ(network->toElement()->str(), test->toElement()->str());
+    sub2->getSharedNetwork(test);
+    EXPECT_TRUE(test);
+    EXPECT_EQ(network->toElement()->str(), test->toElement()->str());
+
+    // Now remove the network. Subnets should be disassociated with the network.
+    cfg.del("frog");
+    sub1->getSharedNetwork(test);
+    EXPECT_FALSE(test);
+    sub2->getSharedNetwork(test);
+    EXPECT_FALSE(test);
+}
+
 // This test verifies that shared networks must have unique names.
 TEST(CfgSharedNetworks6Test, duplicateName) {
     SharedNetwork6Ptr network1(new SharedNetwork6("frog"));

+ 42 - 0
src/lib/dhcpsrv/tests/shared_network_unittest.cc

@@ -288,6 +288,27 @@ TEST(SharedNetwork4Test, destructSharedNetwork) {
     ASSERT_FALSE(subnet_to_network);
 }
 
+// This test verifies that it is possible to remove all subnets.
+TEST(SharedNetwork4Test, delAll) {
+    // Create two subnets and add them to the shared network.
+    Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.0"), 8, 10, 20, 30,
+                                   SubnetID(1)));
+    Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.0"), 24, 10, 20, 30,
+                                   SubnetID(2)));
+
+    SharedNetwork4Ptr network(new SharedNetwork4("frog"));
+    ASSERT_NO_THROW(network->add(subnet1));
+    ASSERT_NO_THROW(network->add(subnet2));
+
+    // Make sure they have been added successfully.
+    ASSERT_EQ(2, network->getAllSubnets()->size());
+
+    ASSERT_NO_THROW(network->delAll());
+
+    // Now check that there are no subnets.
+    ASSERT_EQ(0, network->getAllSubnets()->size());
+}
+
 // This test verifies that shared network can be given a name and that
 // this name can be retrieved.
 TEST(SharedNetwork6Test, getName) {
@@ -545,5 +566,26 @@ TEST(SharedNetwork6Test, destructSharedNetwork) {
     ASSERT_FALSE(subnet_to_network);
 }
 
+// This test verifies that it is possible to remove all subnets.
+TEST(SharedNetwork6Test, delAll) {
+    // Create two subnets and add them to the shared network.
+    Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 64, 10, 20, 30,
+                                   40, SubnetID(1)));
+    Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 16, 10, 20, 30, 40,
+                                   SubnetID(2)));
+
+    SharedNetwork6Ptr network(new SharedNetwork6("frog"));
+    ASSERT_NO_THROW(network->add(subnet1));
+    ASSERT_NO_THROW(network->add(subnet2));
+
+    // Make sure they have been added successfully.
+    ASSERT_EQ(2, network->getAllSubnets()->size());
+
+    ASSERT_NO_THROW(network->delAll());
+
+    // Now check that there are no subnets.
+    ASSERT_EQ(0, network->getAllSubnets()->size());
+}
+
 
 } // end of anonymous namespace