]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#260,!120] Addressed most of review comments
authorThomas Markwalder <tmark@isc.org>
Wed, 14 Nov 2018 16:14:15 +0000 (11:14 -0500)
committerThomas Markwalder <tmark@isc.org>
Tue, 20 Nov 2018 18:25:03 +0000 (13:25 -0500)
    Addressed all comments except parsing regen and
    refactor of watch sockets in IfaceMgr.  Doing those
    separately.

12 files changed:
doc/guide/congestion-handling.xml
src/bin/dhcp4/dhcp4_parser.cc
src/bin/dhcp4/dhcp4_parser.yy
src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp6/dhcp6_parser.cc
src/bin/dhcp6/dhcp6_parser.yy
src/bin/dhcp6/tests/config_parser_unittest.cc
src/bin/dhcp6/tests/get_config_unittest.cc
src/bin/perfdhcp/test_control.cc
src/lib/dhcp/iface_mgr.cc
src/lib/dhcp/iface_mgr.h
src/lib/dhcp/tests/iface_mgr_unittest.cc

index 2c11acc00436ae417042dd86a876ff31413980cb..46f793dacb7442afc699d1b5312e3b66ec38cf9b 100644 (file)
@@ -9,13 +9,38 @@
 <!-- Converted by db4-upgrade version 1.1 -->
 <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="congestion-handling">
   <title>Congestion Handling in DHCPv4 and DHCPv6</title>
+  <para>Congestion occurs when servers are subjected to client queries
+  faster than they can be fulfilled.  Subsequently, the servers begin
+  accumulating a backlog of pending queries.  The longer the high rate of
+  traffic continues the farther behind the servers fall.  Depending on the
+  client implementations, those that fail to get leases either give or simply
+  continue to retry forever.  In the former case, the server may eventually
+  recover.  The latter case is vicious cycle from which the server is unable
+  escape.
+  </para>
+
+  <para>
+  In a well-planned deployment, the number and capacity of servers is matched
+  to the maximum client loads expected.  As long as capacity is matched to
+  load, congestion does not occur. If the load is routinely too heavy, then
+  the deployment needs to be re-evaluated.  Congestion typically occurs when
+  there is a network event that causes overly large numbers of clients to
+  simultaneously need leases such as recovery after a network outage.
+  </para>
+
+  <para>
+  The goal of Congestion handling is to help the servers mitigate the peak
+  in traffic by fulfilling as many of the most relevant requests as possible
+  until it subsides.
+  </para>
+
   <para>Prior to Kea 1.5, kea-dhcp4 and kea-dhcp4 read inbound packets directly
   from the interface sockets in the main application thread.  This meant that
   packets waiting to be processed were held in socket buffers themselves. Once
   these buffers fill any new packets are discarded. Under swamped conditions
   the servers can end up processing client packets that may no longer be
   relevant, or worse are redundant. In other words, the packets waiting in
-  the FIFO socket buffers become more and more stale.
+  the FIFO socket buffers become increasingly stale.
   </para>
 
   <para>Kea 1.5 introduces a new feature referred to as Congestion Handling.
   always discarding the newest packets, we now always discard the oldest
   packets.  The capacity of the buffer, (i.e the maximum number of packets the
   buffer can contain) is configurable.  A reasonable starting point would be to
-  match the queue size to the number of leases per second your installation of
-  Kea can handle (Please note this figure varies widely depending on your
-  configuration).  We anticipate adding more knobs as we learn from experience,
-  testing, and user feedback.
+  match the capacity to the number of leases per second your installation of
+  Kea can handle. Please note this figure varies widely depending on the
+  specifics of your deployment.  We anticipate adding more knobs as we learn
+  from experience, testing, and user feedback.
   </para>
 
-  <para>As there is no one algorithm that will best handle the dynamncis of
+  <para>As there is no one algorithm that will best handle the dynamics of
   all sites, and because over time new approaches will evolve, the packet
   queue is implemented as plug-in, which can replaced by a custom queue
   implementation via hook library.  This should make it straight forward
@@ -53,7 +78,6 @@
   servers through an optional, top level configuration element,
   'dhcp-queue-control' (Omitting this element disables packet queueing):
 <screen>
-   ...
    "dhcp-queue-control": {
        "enable-queue": true|false,
        "queue-type": "queue type",
@@ -74,9 +98,9 @@
       <listitem>
         <simpara><command>queue-type</command> name of the queue implementation
         to use. This value exists such that custom implementations can be
-        registered (via hook lib) and then selected.  As mentioned earlier,
-        there is a default implementation registered: "kea-ring4" for kea-dhcp4
-        and "kea-ring6" for kea-dhcp6.
+        registered (via hook lib) and then selected.  There is a default
+        packet queue implementation that is pre-registered during server
+        start up: "kea-ring4" for kea-dhcp4 and "kea-ring6" for kea-dhcp6.
         </simpara>
       </listitem>
       <listitem>
     </itemizedlist>
   </para>
   <para>The following example enables the default packet queue for kea-dhcp4,
-  with a queue capactiy fo 250 packets:
+  with a queue capacity of 250 packets:
 <screen>
 "Dhcp4":
 {
 </screen>
   </para>
   <para> The following example enables the default packet queue for kea-dhcp6,
-  with a queue capactiy fo 300 packets:
+  with a queue capacity of 300 packets:
 <screen>
 "Dhcp6":
 {
index bb8ef6705d8e47fa0ba2d83dc49f47a519b01ed9..3177441deeeda87f0acf0305533f41d0167db7dc 100644 (file)
@@ -2985,666 +2985,659 @@ namespace isc { namespace dhcp {
     if (!qc->contains("enable-queue")) {
         std::stringstream msg;
         msg << "'enable-queue' is required: ";
-        msg  << qc->getPosition().str() << ")";
+        msg  << "(" << qc->getPosition().str() << ")";
         error(yystack_[3].location, msg.str());
     }
 
-     ConstElementPtr enable_queue = qc->get("enable-queue");
-     if (enable_queue->getType() != Element::boolean) {
+    ConstElementPtr enable_queue = qc->get("enable-queue");
+    if (enable_queue->getType() != Element::boolean) {
         std::stringstream msg;
         msg << "'enable-queue' must be boolean: ";
-        msg  << qc->getPosition().str() << ")";
+        msg  << "(" << qc->getPosition().str() << ")";
         error(yystack_[3].location, msg.str());
-     }
-
-    if (enable_queue->boolValue()) {
-        if (!qc->contains("queue-type")) {
-            std::stringstream msg;
-            msg << "'queue-type' is required, when 'enable-queue' is true: ";
-            msg  << qc->getPosition().str() << ")";
-            error(yystack_[3].location, msg.str());
-        }
+    }
 
+    if (qc->contains("queue-type")) {
         ConstElementPtr queue_type = qc->get("queue-type");
         if (queue_type->getType() != Element::string) {
             std::stringstream msg;
             msg << "'queue-type' must be a string: ";
-            msg  << qc->getPosition().str() << ")";
+            msg  << "(" << qc->getPosition().str() << ")";
             error(yystack_[3].location, msg.str());
         }
-     }
+    }
 
     ctx.leave();
 }
-#line 3020 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3013 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 535:
-#line 1886 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1879 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("dhcp-ddns", m);
     ctx.stack_.push_back(m);
     ctx.enter(ctx.DHCP_DDNS);
 }
-#line 3031 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3024 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 536:
-#line 1891 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1884 "dhcp4_parser.yy" // lalr1.cc:859
     {
     // The enable updates DHCP DDNS parameter is required.
     ctx.require("enable-updates", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3042 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3035 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 537:
-#line 1898 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1891 "dhcp4_parser.yy" // lalr1.cc:859
     {
     // Parse the dhcp-ddns map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3052 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3045 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 538:
-#line 1902 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1895 "dhcp4_parser.yy" // lalr1.cc:859
     {
     // The enable updates DHCP DDNS parameter is required.
     ctx.require("enable-updates", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     // parsing completed
 }
-#line 3062 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3055 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 559:
-#line 1932 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1925 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr b(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("enable-updates", b);
 }
-#line 3071 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3064 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 560:
-#line 1937 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1930 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3079 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3072 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 561:
-#line 1939 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1932 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("qualifying-suffix", s);
     ctx.leave();
 }
-#line 3089 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3082 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 562:
-#line 1945 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1938 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3097 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3090 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 563:
-#line 1947 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1940 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("server-ip", s);
     ctx.leave();
 }
-#line 3107 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3100 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 564:
-#line 1953 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1946 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("server-port", i);
 }
-#line 3116 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3109 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 565:
-#line 1958 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1951 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3124 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3117 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 566:
-#line 1960 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1953 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("sender-ip", s);
     ctx.leave();
 }
-#line 3134 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3127 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 567:
-#line 1966 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1959 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("sender-port", i);
 }
-#line 3143 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3136 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 568:
-#line 1971 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1964 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-queue-size", i);
 }
-#line 3152 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3145 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 569:
-#line 1976 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1969 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NCR_PROTOCOL);
 }
-#line 3160 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3153 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 570:
-#line 1978 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1971 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("ncr-protocol", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3169 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3162 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 571:
-#line 1984 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1977 "dhcp4_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("UDP", ctx.loc2pos(yystack_[0].location))); }
-#line 3175 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3168 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 572:
-#line 1985 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1978 "dhcp4_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("TCP", ctx.loc2pos(yystack_[0].location))); }
-#line 3181 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3174 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 573:
-#line 1988 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1981 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NCR_FORMAT);
 }
-#line 3189 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3182 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 574:
-#line 1990 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1983 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr json(new StringElement("JSON", ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ncr-format", json);
     ctx.leave();
 }
-#line 3199 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3192 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 575:
-#line 1996 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1989 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr b(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("override-no-update", b);
 }
-#line 3208 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3201 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 576:
-#line 2001 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1994 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr b(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("override-client-update", b);
 }
-#line 3217 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3210 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 577:
-#line 2006 "dhcp4_parser.yy" // lalr1.cc:859
+#line 1999 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.REPLACE_CLIENT_NAME);
 }
-#line 3225 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3218 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 578:
-#line 2008 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2001 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("replace-client-name", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3234 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3227 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 579:
-#line 2014 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2007 "dhcp4_parser.yy" // lalr1.cc:859
     {
       yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("when-present", ctx.loc2pos(yystack_[0].location)));
       }
-#line 3242 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3235 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 580:
-#line 2017 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2010 "dhcp4_parser.yy" // lalr1.cc:859
     {
       yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("never", ctx.loc2pos(yystack_[0].location)));
       }
-#line 3250 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3243 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 581:
-#line 2020 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2013 "dhcp4_parser.yy" // lalr1.cc:859
     {
       yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("always", ctx.loc2pos(yystack_[0].location)));
       }
-#line 3258 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3251 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 582:
-#line 2023 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2016 "dhcp4_parser.yy" // lalr1.cc:859
     {
       yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("when-not-present", ctx.loc2pos(yystack_[0].location)));
       }
-#line 3266 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3259 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 583:
-#line 2026 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2019 "dhcp4_parser.yy" // lalr1.cc:859
     {
       error(yystack_[0].location, "boolean values for the replace-client-name are "
                 "no longer supported");
       }
-#line 3275 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3268 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 584:
-#line 2032 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2025 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3283 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3276 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 585:
-#line 2034 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2027 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("generated-prefix", s);
     ctx.leave();
 }
-#line 3293 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3286 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 586:
-#line 2040 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2033 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3301 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3294 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 587:
-#line 2042 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2035 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hostname-char-set", s);
     ctx.leave();
 }
-#line 3311 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3304 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 588:
-#line 2048 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2041 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3319 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3312 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 589:
-#line 2050 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2043 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hostname-char-replacement", s);
     ctx.leave();
 }
-#line 3329 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3322 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 590:
-#line 2059 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2052 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3337 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3330 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 591:
-#line 2061 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2054 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("Dhcp6", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3346 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3339 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 592:
-#line 2066 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2059 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3354 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3347 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 593:
-#line 2068 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2061 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("DhcpDdns", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3363 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3356 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 594:
-#line 2073 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2066 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3371 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3364 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 595:
-#line 2075 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2068 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("Control-agent", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3380 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3373 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 596:
-#line 2080 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2073 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3390 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3383 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 597:
-#line 2084 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2077 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
 }
-#line 3398 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3391 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 598:
-#line 2089 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2082 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr i(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("config-control", i);
     ctx.stack_.push_back(i);
     ctx.enter(ctx.CONFIG_CONTROL);
 }
-#line 3409 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3402 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 599:
-#line 2094 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2087 "dhcp4_parser.yy" // lalr1.cc:859
     {
     // No config control params are required
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3419 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3412 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 600:
-#line 2100 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2093 "dhcp4_parser.yy" // lalr1.cc:859
     {
     // Parse the config-control map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3429 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3422 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 601:
-#line 2104 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2097 "dhcp4_parser.yy" // lalr1.cc:859
     {
     // No config_control params are required
     // parsing completed
 }
-#line 3438 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3431 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 606:
-#line 2119 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2112 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("config-databases", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.CONFIG_DATABASE);
 }
-#line 3449 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3442 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 607:
-#line 2124 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2117 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3458 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3451 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 608:
-#line 2134 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2127 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("Logging", m);
     ctx.stack_.push_back(m);
     ctx.enter(ctx.LOGGING);
 }
-#line 3469 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3462 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 609:
-#line 2139 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2132 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3478 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3471 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 610:
-#line 2144 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2137 "dhcp4_parser.yy" // lalr1.cc:859
     {
     // Parse the Logging map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3488 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3481 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 611:
-#line 2148 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2141 "dhcp4_parser.yy" // lalr1.cc:859
     {
     // parsing completed
 }
-#line 3496 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3489 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 615:
-#line 2164 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2157 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("loggers", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.LOGGERS);
 }
-#line 3507 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3500 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 616:
-#line 2169 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2162 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3516 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3509 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 619:
-#line 2181 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2174 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(l);
     ctx.stack_.push_back(l);
 }
-#line 3526 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3519 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 620:
-#line 2185 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2178 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
 }
-#line 3534 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3527 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 630:
-#line 2202 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2195 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr dl(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("debuglevel", dl);
 }
-#line 3543 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3536 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 631:
-#line 2207 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2200 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3551 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3544 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 632:
-#line 2209 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2202 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr sev(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("severity", sev);
     ctx.leave();
 }
-#line 3561 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3554 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 633:
-#line 2215 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2208 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("output_options", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.OUTPUT_OPTIONS);
 }
-#line 3572 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3565 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 634:
-#line 2220 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2213 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3581 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3574 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 637:
-#line 2229 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2222 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3591 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3584 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 638:
-#line 2233 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2226 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
 }
-#line 3599 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3592 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 645:
-#line 2247 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2240 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3607 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3600 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 646:
-#line 2249 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2242 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr sev(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("output", sev);
     ctx.leave();
 }
-#line 3617 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3610 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 647:
-#line 2255 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2248 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr flush(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("flush", flush);
 }
-#line 3626 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3619 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 648:
-#line 2260 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2253 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr maxsize(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("maxsize", maxsize);
 }
-#line 3635 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3628 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
   case 649:
-#line 2265 "dhcp4_parser.yy" // lalr1.cc:859
+#line 2258 "dhcp4_parser.yy" // lalr1.cc:859
     {
     ElementPtr maxver(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("maxver", maxver);
 }
-#line 3644 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3637 "dhcp4_parser.cc" // lalr1.cc:859
     break;
 
 
-#line 3648 "dhcp4_parser.cc" // lalr1.cc:859
+#line 3641 "dhcp4_parser.cc" // lalr1.cc:859
             default:
               break;
             }
@@ -4874,18 +4867,18 @@ namespace isc { namespace dhcp {
     1754,  1755,  1758,  1759,  1762,  1763,  1764,  1765,  1766,  1767,
     1768,  1769,  1770,  1771,  1772,  1775,  1777,  1777,  1785,  1794,
     1801,  1801,  1811,  1812,  1815,  1816,  1817,  1818,  1819,  1822,
-    1822,  1830,  1830,  1841,  1841,  1886,  1886,  1898,  1898,  1908,
-    1909,  1912,  1913,  1914,  1915,  1916,  1917,  1918,  1919,  1920,
-    1921,  1922,  1923,  1924,  1925,  1926,  1927,  1928,  1929,  1932,
-    1937,  1937,  1945,  1945,  1953,  1958,  1958,  1966,  1971,  1976,
-    1976,  1984,  1985,  1988,  1988,  1996,  2001,  2006,  2006,  2014,
-    2017,  2020,  2023,  2026,  2032,  2032,  2040,  2040,  2048,  2048,
-    2059,  2059,  2066,  2066,  2073,  2073,  2080,  2080,  2089,  2089,
-    2100,  2100,  2110,  2111,  2115,  2116,  2119,  2119,  2134,  2134,
-    2144,  2144,  2155,  2156,  2160,  2164,  2164,  2176,  2177,  2181,
-    2181,  2189,  2190,  2193,  2194,  2195,  2196,  2197,  2198,  2199,
-    2202,  2207,  2207,  2215,  2215,  2225,  2226,  2229,  2229,  2237,
-    2238,  2241,  2242,  2243,  2244,  2247,  2247,  2255,  2260,  2265
+    1822,  1830,  1830,  1841,  1841,  1879,  1879,  1891,  1891,  1901,
+    1902,  1905,  1906,  1907,  1908,  1909,  1910,  1911,  1912,  1913,
+    1914,  1915,  1916,  1917,  1918,  1919,  1920,  1921,  1922,  1925,
+    1930,  1930,  1938,  1938,  1946,  1951,  1951,  1959,  1964,  1969,
+    1969,  1977,  1978,  1981,  1981,  1989,  1994,  1999,  1999,  2007,
+    2010,  2013,  2016,  2019,  2025,  2025,  2033,  2033,  2041,  2041,
+    2052,  2052,  2059,  2059,  2066,  2066,  2073,  2073,  2082,  2082,
+    2093,  2093,  2103,  2104,  2108,  2109,  2112,  2112,  2127,  2127,
+    2137,  2137,  2148,  2149,  2153,  2157,  2157,  2169,  2170,  2174,
+    2174,  2182,  2183,  2186,  2187,  2188,  2189,  2190,  2191,  2192,
+    2195,  2200,  2200,  2208,  2208,  2218,  2219,  2222,  2222,  2230,
+    2231,  2234,  2235,  2236,  2237,  2240,  2240,  2248,  2253,  2258
   };
 
   // Print the state stack on the debug stream.
@@ -4920,8 +4913,8 @@ namespace isc { namespace dhcp {
 
 #line 14 "dhcp4_parser.yy" // lalr1.cc:1167
 } } // isc::dhcp
-#line 4924 "dhcp4_parser.cc" // lalr1.cc:1167
-#line 2270 "dhcp4_parser.yy" // lalr1.cc:1168
+#line 4917 "dhcp4_parser.cc" // lalr1.cc:1167
+#line 2263 "dhcp4_parser.yy" // lalr1.cc:1168
 
 
 void
index ffe7a2b1b5bb90c0b289ef8fc21dac594b9ed67f..fe1f905fb5fb5f84244a755dba3763632b0f2f41 100644 (file)
@@ -1849,34 +1849,27 @@ dhcp_queue_control: DHCP_QUEUE_CONTROL {
     if (!qc->contains("enable-queue")) {
         std::stringstream msg;
         msg << "'enable-queue' is required: ";
-        msg  << qc->getPosition().str() << ")";
+        msg  << "(" << qc->getPosition().str() << ")";
         error(@1, msg.str());
     }
 
-     ConstElementPtr enable_queue = qc->get("enable-queue");
-     if (enable_queue->getType() != Element::boolean) {
+    ConstElementPtr enable_queue = qc->get("enable-queue");
+    if (enable_queue->getType() != Element::boolean) {
         std::stringstream msg;
         msg << "'enable-queue' must be boolean: ";
-        msg  << qc->getPosition().str() << ")";
+        msg  << "(" << qc->getPosition().str() << ")";
         error(@1, msg.str());
-     }
-
-    if (enable_queue->boolValue()) {
-        if (!qc->contains("queue-type")) {
-            std::stringstream msg;
-            msg << "'queue-type' is required, when 'enable-queue' is true: ";
-            msg  << qc->getPosition().str() << ")";
-            error(@1, msg.str());
-        }
+    }
 
+    if (qc->contains("queue-type")) {
         ConstElementPtr queue_type = qc->get("queue-type");
         if (queue_type->getType() != Element::string) {
             std::stringstream msg;
             msg << "'queue-type' must be a string: ";
-            msg  << qc->getPosition().str() << ")";
+            msg  << "(" << qc->getPosition().str() << ")";
             error(@1, msg.str());
         }
-     }
+    }
 
     ctx.leave();
 };
index 93d1baa6e5636c53a0129f2333b38cc158248e8c..7ba870597c874937d93f44dddd6df678d7d53b7e 100644 (file)
@@ -6591,21 +6591,14 @@ TEST_F(Dhcp4ParserTest, dhcpQueueControlInvalid) {
         "{ \n"
         "   \"enable-type\": \"some-type\" \n"
         "} \n",
-        "<string>:2.2-21: 'enable-queue' is required: <string>:2:24)"
+        "<string>:2.2-21: 'enable-queue' is required: (<string>:2:24)"
         },
         {
         "enable-queue not boolean",
         "{ \n"
         "   \"enable-queue\": \"always\" \n"
         "} \n",
-        "<string>:2.2-21: 'enable-queue' must be boolean: <string>:2:24)"
-        },
-        {
-        "queue enabled, type missing",
-        "{ \n"
-        "   \"enable-queue\": true \n"
-        "} \n",
-        "<string>:2.2-21: 'queue-type' is required, when 'enable-queue' is true: <string>:2:24)"
+        "<string>:2.2-21: 'enable-queue' must be boolean: (<string>:2:24)"
         },
         {
         "queue enabled, type not a string",
@@ -6613,7 +6606,7 @@ TEST_F(Dhcp4ParserTest, dhcpQueueControlInvalid) {
         "   \"enable-queue\": true, \n"
         "   \"queue-type\": 7777 \n"
         "} \n",
-        "<string>:2.2-21: 'queue-type' must be a string: <string>:2:24)"
+        "<string>:2.2-21: 'queue-type' must be a string: (<string>:2:24)"
         }
     };
 
index c4b64889495b30150b8307c8e7dd7dde3e443e72..2735633bce2a7865eba5aa4589a6f7fdbf0055bf 100644 (file)
@@ -3063,667 +3063,661 @@ namespace isc { namespace dhcp {
     if (!qc->contains("enable-queue")) {
         std::stringstream msg;
         msg << "'enable-queue' is required: ";
-        msg  << qc->getPosition().str() << ")";
+        msg  << "(" << qc->getPosition().str() << ")";
         error(yystack_[3].location, msg.str());
     }
 
-     ConstElementPtr enable_queue = qc->get("enable-queue");
-     if (enable_queue->getType() != Element::boolean) {
+    // queue-enable is mandatory
+    ConstElementPtr enable_queue = qc->get("enable-queue");
+    if (enable_queue->getType() != Element::boolean) {
         std::stringstream msg;
         msg << "'enable-queue' must be boolean: ";
-        msg  << qc->getPosition().str() << ")";
+        msg  << "(" << qc->getPosition().str() << ")";
         error(yystack_[3].location, msg.str());
      }
 
-    if (enable_queue->boolValue()) {
-        if (!qc->contains("queue-type")) {
-            std::stringstream msg;
-            msg << "'queue-type' is required, when 'enable-queue' is true: ";
-            msg  << qc->getPosition().str() << ")";
-            error(yystack_[3].location, msg.str());
-        }
-
+    // if queue-type is supplied make sure it's a string
+    if (qc->contains("queue-type")) {
         ConstElementPtr queue_type = qc->get("queue-type");
         if (queue_type->getType() != Element::string) {
             std::stringstream msg;
             msg << "'queue-type' must be a string: ";
-            msg  << qc->getPosition().str() << ")";
+            msg  << "(" << qc->getPosition().str() << ")";
             error(yystack_[3].location, msg.str());
         }
-     }
-
+    }
 
     ctx.leave();
 }
-#line 3099 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3093 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 556:
-#line 1976 "dhcp6_parser.yy" // lalr1.cc:859
+#line 1970 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("dhcp-ddns", m);
     ctx.stack_.push_back(m);
     ctx.enter(ctx.DHCP_DDNS);
 }
-#line 3110 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3104 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 557:
-#line 1981 "dhcp6_parser.yy" // lalr1.cc:859
+#line 1975 "dhcp6_parser.yy" // lalr1.cc:859
     {
     // The enable updates DHCP DDNS parameter is required.
     ctx.require("enable-updates", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3121 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3115 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 558:
-#line 1988 "dhcp6_parser.yy" // lalr1.cc:859
+#line 1982 "dhcp6_parser.yy" // lalr1.cc:859
     {
     // Parse the dhcp-ddns map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3131 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3125 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 559:
-#line 1992 "dhcp6_parser.yy" // lalr1.cc:859
+#line 1986 "dhcp6_parser.yy" // lalr1.cc:859
     {
     // The enable updates DHCP DDNS parameter is required.
     ctx.require("enable-updates", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     // parsing completed
 }
-#line 3141 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3135 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 580:
-#line 2022 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2016 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr b(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("enable-updates", b);
 }
-#line 3150 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3144 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 581:
-#line 2027 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2021 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3158 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3152 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 582:
-#line 2029 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2023 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("qualifying-suffix", s);
     ctx.leave();
 }
-#line 3168 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3162 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 583:
-#line 2035 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2029 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3176 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3170 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 584:
-#line 2037 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2031 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("server-ip", s);
     ctx.leave();
 }
-#line 3186 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3180 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 585:
-#line 2043 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2037 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("server-port", i);
 }
-#line 3195 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3189 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 586:
-#line 2048 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2042 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3203 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3197 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 587:
-#line 2050 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2044 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("sender-ip", s);
     ctx.leave();
 }
-#line 3213 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3207 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 588:
-#line 2056 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2050 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("sender-port", i);
 }
-#line 3222 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3216 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 589:
-#line 2061 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2055 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-queue-size", i);
 }
-#line 3231 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3225 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 590:
-#line 2066 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2060 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NCR_PROTOCOL);
 }
-#line 3239 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3233 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 591:
-#line 2068 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2062 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("ncr-protocol", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3248 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3242 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 592:
-#line 2074 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2068 "dhcp6_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("UDP", ctx.loc2pos(yystack_[0].location))); }
-#line 3254 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3248 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 593:
-#line 2075 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2069 "dhcp6_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("TCP", ctx.loc2pos(yystack_[0].location))); }
-#line 3260 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3254 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 594:
-#line 2078 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2072 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NCR_FORMAT);
 }
-#line 3268 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3262 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 595:
-#line 2080 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2074 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr json(new StringElement("JSON", ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ncr-format", json);
     ctx.leave();
 }
-#line 3278 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3272 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 596:
-#line 2086 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2080 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr b(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("override-no-update", b);
 }
-#line 3287 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3281 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 597:
-#line 2091 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2085 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr b(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("override-client-update", b);
 }
-#line 3296 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3290 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 598:
-#line 2096 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2090 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.REPLACE_CLIENT_NAME);
 }
-#line 3304 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3298 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 599:
-#line 2098 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2092 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("replace-client-name", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3313 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3307 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 600:
-#line 2104 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2098 "dhcp6_parser.yy" // lalr1.cc:859
     {
       yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("when-present", ctx.loc2pos(yystack_[0].location)));
       }
-#line 3321 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3315 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 601:
-#line 2107 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2101 "dhcp6_parser.yy" // lalr1.cc:859
     {
       yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("never", ctx.loc2pos(yystack_[0].location)));
       }
-#line 3329 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3323 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 602:
-#line 2110 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2104 "dhcp6_parser.yy" // lalr1.cc:859
     {
       yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("always", ctx.loc2pos(yystack_[0].location)));
       }
-#line 3337 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3331 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 603:
-#line 2113 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2107 "dhcp6_parser.yy" // lalr1.cc:859
     {
       yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("when-not-present", ctx.loc2pos(yystack_[0].location)));
       }
-#line 3345 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3339 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 604:
-#line 2116 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2110 "dhcp6_parser.yy" // lalr1.cc:859
     {
       error(yystack_[0].location, "boolean values for the replace-client-name are "
                 "no longer supported");
       }
-#line 3354 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3348 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 605:
-#line 2122 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2116 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3362 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3356 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 606:
-#line 2124 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2118 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("generated-prefix", s);
     ctx.leave();
 }
-#line 3372 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3366 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 607:
-#line 2130 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2124 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3380 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3374 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 608:
-#line 2132 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2126 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hostname-char-set", s);
     ctx.leave();
 }
-#line 3390 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3384 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 609:
-#line 2138 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2132 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3398 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3392 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 610:
-#line 2140 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2134 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hostname-char-replacement", s);
     ctx.leave();
 }
-#line 3408 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3402 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 611:
-#line 2148 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2142 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3416 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3410 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 612:
-#line 2150 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2144 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("Dhcp4", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3425 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3419 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 613:
-#line 2155 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2149 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3433 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3427 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 614:
-#line 2157 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2151 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("DhcpDdns", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3442 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3436 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 615:
-#line 2162 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2156 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3450 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3444 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 616:
-#line 2164 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2158 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("Control-agent", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 3459 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3453 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 617:
-#line 2171 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2165 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3469 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3463 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 618:
-#line 2175 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2169 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
 }
-#line 3477 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3471 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 619:
-#line 2180 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2174 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr i(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("config-control", i);
     ctx.stack_.push_back(i);
     ctx.enter(ctx.CONFIG_CONTROL);
 }
-#line 3488 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3482 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 620:
-#line 2185 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2179 "dhcp6_parser.yy" // lalr1.cc:859
     {
     // No config control params are required
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3498 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3492 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 621:
-#line 2191 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2185 "dhcp6_parser.yy" // lalr1.cc:859
     {
     // Parse the config-control map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3508 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3502 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 622:
-#line 2195 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2189 "dhcp6_parser.yy" // lalr1.cc:859
     {
     // No config_control params are required
     // parsing completed
 }
-#line 3517 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3511 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 627:
-#line 2210 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2204 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("config-databases", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.CONFIG_DATABASE);
 }
-#line 3528 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3522 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 628:
-#line 2215 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2209 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3537 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3531 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 629:
-#line 2225 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2219 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("Logging", m);
     ctx.stack_.push_back(m);
     ctx.enter(ctx.LOGGING);
 }
-#line 3548 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3542 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 630:
-#line 2230 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2224 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3557 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3551 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 631:
-#line 2235 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2229 "dhcp6_parser.yy" // lalr1.cc:859
     {
     // Parse the Logging map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3567 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3561 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 632:
-#line 2239 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2233 "dhcp6_parser.yy" // lalr1.cc:859
     {
     // parsing completed
 }
-#line 3575 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3569 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 636:
-#line 2255 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2249 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("loggers", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.LOGGERS);
 }
-#line 3586 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3580 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 637:
-#line 2260 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2254 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3595 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3589 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 640:
-#line 2272 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2266 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(l);
     ctx.stack_.push_back(l);
 }
-#line 3605 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3599 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 641:
-#line 2276 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2270 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
 }
-#line 3613 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3607 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 651:
-#line 2293 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2287 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr dl(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("debuglevel", dl);
 }
-#line 3622 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3616 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 652:
-#line 2298 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2292 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3630 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3624 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 653:
-#line 2300 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2294 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr sev(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("severity", sev);
     ctx.leave();
 }
-#line 3640 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3634 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 654:
-#line 2306 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2300 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("output_options", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.OUTPUT_OPTIONS);
 }
-#line 3651 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3645 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 655:
-#line 2311 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2305 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3660 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3654 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 658:
-#line 2320 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2314 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3670 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3664 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 659:
-#line 2324 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2318 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
 }
-#line 3678 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3672 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 666:
-#line 2338 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2332 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3686 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3680 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 667:
-#line 2340 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2334 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr sev(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("output", sev);
     ctx.leave();
 }
-#line 3696 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3690 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 668:
-#line 2346 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2340 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr flush(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("flush", flush);
 }
-#line 3705 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3699 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 669:
-#line 2351 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2345 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr maxsize(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("maxsize", maxsize);
 }
-#line 3714 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3708 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
   case 670:
-#line 2356 "dhcp6_parser.yy" // lalr1.cc:859
+#line 2350 "dhcp6_parser.yy" // lalr1.cc:859
     {
     ElementPtr maxver(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("maxver", maxver);
 }
-#line 3723 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3717 "dhcp6_parser.cc" // lalr1.cc:859
     break;
 
 
-#line 3727 "dhcp6_parser.cc" // lalr1.cc:859
+#line 3721 "dhcp6_parser.cc" // lalr1.cc:859
             default:
               break;
             }
@@ -4986,19 +4980,19 @@ namespace isc { namespace dhcp {
     1833,  1836,  1837,  1838,  1839,  1840,  1841,  1842,  1843,  1844,
     1847,  1847,  1854,  1855,  1856,  1859,  1864,  1864,  1872,  1877,
     1884,  1891,  1891,  1901,  1902,  1905,  1906,  1907,  1908,  1909,
-    1912,  1912,  1920,  1920,  1930,  1930,  1976,  1976,  1988,  1988,
-    1998,  1999,  2002,  2003,  2004,  2005,  2006,  2007,  2008,  2009,
-    2010,  2011,  2012,  2013,  2014,  2015,  2016,  2017,  2018,  2019,
-    2022,  2027,  2027,  2035,  2035,  2043,  2048,  2048,  2056,  2061,
-    2066,  2066,  2074,  2075,  2078,  2078,  2086,  2091,  2096,  2096,
-    2104,  2107,  2110,  2113,  2116,  2122,  2122,  2130,  2130,  2138,
-    2138,  2148,  2148,  2155,  2155,  2162,  2162,  2171,  2171,  2180,
-    2180,  2191,  2191,  2201,  2202,  2206,  2207,  2210,  2210,  2225,
-    2225,  2235,  2235,  2246,  2247,  2251,  2255,  2255,  2267,  2268,
-    2272,  2272,  2280,  2281,  2284,  2285,  2286,  2287,  2288,  2289,
-    2290,  2293,  2298,  2298,  2306,  2306,  2316,  2317,  2320,  2320,
-    2328,  2329,  2332,  2333,  2334,  2335,  2338,  2338,  2346,  2351,
-    2356
+    1912,  1912,  1920,  1920,  1930,  1930,  1970,  1970,  1982,  1982,
+    1992,  1993,  1996,  1997,  1998,  1999,  2000,  2001,  2002,  2003,
+    2004,  2005,  2006,  2007,  2008,  2009,  2010,  2011,  2012,  2013,
+    2016,  2021,  2021,  2029,  2029,  2037,  2042,  2042,  2050,  2055,
+    2060,  2060,  2068,  2069,  2072,  2072,  2080,  2085,  2090,  2090,
+    2098,  2101,  2104,  2107,  2110,  2116,  2116,  2124,  2124,  2132,
+    2132,  2142,  2142,  2149,  2149,  2156,  2156,  2165,  2165,  2174,
+    2174,  2185,  2185,  2195,  2196,  2200,  2201,  2204,  2204,  2219,
+    2219,  2229,  2229,  2240,  2241,  2245,  2249,  2249,  2261,  2262,
+    2266,  2266,  2274,  2275,  2278,  2279,  2280,  2281,  2282,  2283,
+    2284,  2287,  2292,  2292,  2300,  2300,  2310,  2311,  2314,  2314,
+    2322,  2323,  2326,  2327,  2328,  2329,  2332,  2332,  2340,  2345,
+    2350
   };
 
   // Print the state stack on the debug stream.
@@ -5033,8 +5027,8 @@ namespace isc { namespace dhcp {
 
 #line 14 "dhcp6_parser.yy" // lalr1.cc:1167
 } } // isc::dhcp
-#line 5037 "dhcp6_parser.cc" // lalr1.cc:1167
-#line 2361 "dhcp6_parser.yy" // lalr1.cc:1168
+#line 5031 "dhcp6_parser.cc" // lalr1.cc:1167
+#line 2355 "dhcp6_parser.yy" // lalr1.cc:1168
 
 
 void
index 232476e8977279caff1e1969c4c539a6bc780249..d29a2975d4d74e8f4425746738d112e878f1ebee 100644 (file)
@@ -1938,35 +1938,29 @@ dhcp_queue_control: DHCP_QUEUE_CONTROL {
     if (!qc->contains("enable-queue")) {
         std::stringstream msg;
         msg << "'enable-queue' is required: ";
-        msg  << qc->getPosition().str() << ")";
+        msg  << "(" << qc->getPosition().str() << ")";
         error(@1, msg.str());
     }
 
-     ConstElementPtr enable_queue = qc->get("enable-queue");
-     if (enable_queue->getType() != Element::boolean) {
+    // queue-enable is mandatory
+    ConstElementPtr enable_queue = qc->get("enable-queue");
+    if (enable_queue->getType() != Element::boolean) {
         std::stringstream msg;
         msg << "'enable-queue' must be boolean: ";
-        msg  << qc->getPosition().str() << ")";
+        msg  << "(" << qc->getPosition().str() << ")";
         error(@1, msg.str());
      }
 
-    if (enable_queue->boolValue()) {
-        if (!qc->contains("queue-type")) {
-            std::stringstream msg;
-            msg << "'queue-type' is required, when 'enable-queue' is true: ";
-            msg  << qc->getPosition().str() << ")";
-            error(@1, msg.str());
-        }
-
+    // if queue-type is supplied make sure it's a string
+    if (qc->contains("queue-type")) {
         ConstElementPtr queue_type = qc->get("queue-type");
         if (queue_type->getType() != Element::string) {
             std::stringstream msg;
             msg << "'queue-type' must be a string: ";
-            msg  << qc->getPosition().str() << ")";
+            msg  << "(" << qc->getPosition().str() << ")";
             error(@1, msg.str());
         }
-     }
-
+    }
 
     ctx.leave();
 };
index d7583ad4aeb387c207c753bf4da527a3d06d1d29..f2f96d9c4720efc2133241af8474e4d37e2d0314 100644 (file)
@@ -7096,29 +7096,22 @@ TEST_F(Dhcp6ParserTest, dhcpQueueControlInvalid) {
         "{ \n"
         "   \"enable-type\": \"some-type\" \n"
         "} \n",
-        "<string>:2.2-21: 'enable-queue' is required: <string>:2:24)"
+        "<string>:2.2-21: 'enable-queue' is required: (<string>:2:24)"
         },
         {
         "enable-queue not boolean",
         "{ \n"
         "   \"enable-queue\": \"always\" \n"
         "} \n",
-        "<string>:2.2-21: 'enable-queue' must be boolean: <string>:2:24)"
+        "<string>:2.2-21: 'enable-queue' must be boolean: (<string>:2:24)"
         },
         {
-        "queue enabled, type missing",
-        "{ \n"
-        "   \"enable-queue\": true \n"
-        "} \n",
-        "<string>:2.2-21: 'queue-type' is required, when 'enable-queue' is true: <string>:2:24)"
-        },
-        {
-        "queue enabled, type not a string",
+        "queue type not a string",
         "{ \n"
         "   \"enable-queue\": true, \n"
         "   \"queue-type\": 7777 \n"
         "} \n",
-        "<string>:2.2-21: 'queue-type' must be a string: <string>:2:24)"
+        "<string>:2.2-21: 'queue-type' must be a string: (<string>:2:24)"
         }
     };
 
index 2f2bf24fe276623e9e36a4c9e3f9dbb7d02cfb1a..9375c3321a5d75d39acff7e34ebd3645865f1416 100644 (file)
@@ -78,7 +78,8 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"preferred-lifetime\": 3000,\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"renew-timer\": 1000,\n"
-"        \"subnet6\": [ ],\n" "        \"valid-lifetime\": 4000\n"
+"        \"subnet6\": [ ],\n"
+"        \"valid-lifetime\": 4000\n"
 "    }\n",
     // CONFIGURATION 1
 "{\n"
index c1dc0c044aaa0c2e6fc12def7b16bc6d2a1ac6da..9a302840d96950f14c5314e01c328e388dc57df4 100644 (file)
@@ -1485,8 +1485,12 @@ TestControl::run() {
         isc_throw(InvalidOperation,
                   "command options must be parsed before running a test");
     } else if (options.getIpVersion() == 4) {
+        // Turn off packet queueing.
+        IfaceMgr::instance().configureDHCPPacketQueue(AF_INET, data::ElementPtr());
         setTransidGenerator(NumberGeneratorPtr(new SequentialGenerator()));
     } else {
+        // Turn off packet queueing.
+        IfaceMgr::instance().configureDHCPPacketQueue(AF_INET6, data::ElementPtr());
         setTransidGenerator(NumberGeneratorPtr(new SequentialGenerator(0x00FFFFFF)));
     }
 
index c56cdd607677d54769d3ba152590fb7282648ba0..2618f3a59e3f4a4e4e305e06e9b2a84fe8f7cbdc 100644 (file)
@@ -314,7 +314,6 @@ IfaceMgr::~IfaceMgr() {
     // control_buf_ is deleted automatically (scoped_ptr)
     control_buf_len_ = 0;
 
-    stopDHCPReceiver();
     closeSockets();
 
     // Explicitly delete PQM singletons.
@@ -595,8 +594,9 @@ IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast,
         }
     }
 
+    // If we have open sockets, start the receiver.
     if (count > 0) {
-        // starts the receiver thread (if queueing is enabled);
+        // starts the receiver thread (if queueing is enabled).
         startDHCPReceiver(AF_INET);
     }
 
@@ -679,8 +679,9 @@ IfaceMgr::openSockets6(const uint16_t port,
         }
     }
 
+    // If we have open sockets, start the receiver.
     if (count > 0) {
-        // starts the receiver thread (if queueing is enabled);
+        // starts the receiver thread (if queueing is enabled).
         startDHCPReceiver(AF_INET6);
     }
     return (count > 0);
@@ -694,6 +695,7 @@ IfaceMgr::startDHCPReceiver(const uint16_t family) {
 
     switch (family) {
     case AF_INET:
+        // If there's no queue, then has been disabled, simply return.
         if(!getPacketQueue4()) {
             return;
         }
@@ -701,6 +703,7 @@ IfaceMgr::startDHCPReceiver(const uint16_t family) {
         receiver_thread_.reset(new Thread(boost::bind(&IfaceMgr::receiveDHCP4Packets, this)));
         break;
     case AF_INET6:
+        // If there's no queue, then has been disabled, simply return.
         if(!getPacketQueue6()) {
             return;
         }
@@ -964,7 +967,7 @@ IfaceMgr::send(const Pkt4Ptr& pkt) {
 }
 
 Pkt4Ptr IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
-    if (receiver_thread_) {
+    if (isReceiverRunning()) {
         return (receive4Indirect(timeout_sec, timeout_usec));
     }
 
@@ -1189,7 +1192,7 @@ Pkt4Ptr IfaceMgr::receive4Direct(uint32_t timeout_sec, uint32_t timeout_usec /*
 }
 
 Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
-    if (receiver_thread_) {
+    if (isReceiverRunning()) {
         return (receive6Indirect(timeout_sec, timeout_usec));
     }
 
index 9d4ffbb5193b1c68539e9ee016838970eca42378..310a52f227fe4800ece6db1eb70e0b9d22e8689f 100644 (file)
@@ -677,56 +677,32 @@ public:
     /// @return true if sending was successful
     bool send(const Pkt4Ptr& pkt);
 
-    /// @brief Tries to receive DHCPv6 message over open IPv6 sockets.
+    /// @brief Receive IPv4 packets or data from external sockets
     ///
-    /// Attempts to receive a single DHCPv6 message over any of the open IPv6
-    /// sockets. If reception is successful and all information about its
-    /// sender is obtained, Pkt6 object is created and returned.
-    ///
-    /// This method also checks if data arrived over registered external socket.
-    /// This data may be of a different protocol family than AF_INET6.
+    /// Wrapper around calls to either @c receive4Direct or @c
+    /// receive4Indirect.  The former is called when packet queuing is
+    /// disabled, the latter when it is enabled.
     ///
     /// @param timeout_sec specifies integral part of the timeout (in seconds)
     /// @param timeout_usec specifies fractional part of the timeout
     /// (in microseconds)
     ///
-    /// @throw isc::BadValue if timeout_usec is greater than one million
-    /// @throw isc::dhcp::SocketReadError if error occurred when receiving a
-    /// packet.
-    /// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
-    /// interrupted by a signal.
-    ///
-    /// @return Pkt6 object representing received packet (or NULL)
+    /// @return Pkt4 object representing received packet (or NULL)
     Pkt6Ptr receive6(uint32_t timeout_sec, uint32_t timeout_usec = 0);
 
-    Pkt6Ptr receive6Direct(uint32_t timeout_sec, uint32_t timeout_usec = 0);
-    Pkt6Ptr receive6Indirect(uint32_t timeout_sec, uint32_t timeout_usec = 0);
-
-    /// @brief Tries to receive IPv4 packet over open IPv4 sockets.
+    /// @brief Receive IPv4 packets or data from external sockets
     ///
-    /// Attempts to receive a single DHCPv4 message over any of the open
-    /// IPv4 sockets. If reception is successful and all information about
-    /// its sender is obtained, Pkt4 object is created and returned.
-    ///
-    /// This method also checks if data arrived over registered external socket.
-    /// This data may be of a different protocol family than AF_INET.
+    /// Wrapper around calls to either @c receive4Direct or @c
+    /// receive4Indirect.  The former is called when packet queuing is
+    /// disabled, the latter when it is enabled.
     ///
     /// @param timeout_sec specifies integral part of the timeout (in seconds)
     /// @param timeout_usec specifies fractional part of the timeout
     /// (in microseconds)
     ///
-    /// @throw isc::BadValue if timeout_usec is greater than one million
-    /// @throw isc::dhcp::SocketReadError if error occurred when receiving a
-    /// packet.
-    /// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
-    /// interrupted by a signal.
-    ///
     /// @return Pkt4 object representing received packet (or NULL)
     Pkt4Ptr receive4(uint32_t timeout_sec, uint32_t timeout_usec = 0);
 
-    Pkt4Ptr receive4Direct(uint32_t timeout_sec, uint32_t timeout_usec = 0);
-    Pkt4Ptr receive4Indirect(uint32_t timeout_sec, uint32_t timeout_usec = 0);
-
     /// Opens UDP/IP socket and binds it to address, interface and port.
     ///
     /// Specific type of socket (UDP/IPv4 or UDP/IPv6) depends on passed addr
@@ -1125,6 +1101,50 @@ protected:
                     const uint16_t port, const bool receive_bcast = false,
                     const bool send_bcast = false);
 
+    /// @brief Receive IPv4 packets directly or data from external sockets.
+    ///
+    /// Attempts to receive a single DHCPv4 message over any of the open
+    /// IPv4 sockets. If reception is successful and all information about
+    /// its sender is obtained, an Pkt4 object is created and returned.
+    ///
+    /// This method also checks if data arrived over registered external socket.
+    /// This data may be of a different protocol family than AF_INET.
+    ///
+    /// @param timeout_sec specifies integral part of the timeout (in seconds)
+    /// @param timeout_usec specifies fractional part of the timeout
+    /// (in microseconds)
+    ///
+    /// @throw isc::BadValue if timeout_usec is greater than one million
+    /// @throw isc::dhcp::SocketReadError if error occurred when receiving a
+    /// packet.
+    /// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
+    /// interrupted by a signal.
+    ///
+    /// @return Pkt4 object representing received packet (or NULL)
+    Pkt4Ptr receive4Direct(uint32_t timeout_sec, uint32_t timeout_usec = 0);
+
+    /// @brief Receive IPv4 packets indirectly or data from external sockets.
+    ///
+    /// Attempts to receive a single DHCPv4 message from the packet queue.
+    /// The queue is populated by the receiver thread.  If a packet is waiting
+    /// in the queue, a Pkt4 returned.
+    ///
+    /// This method also checks if data arrived over registered external socket.
+    /// This data may be of a different protocol family than AF_INET.
+    ///
+    /// @param timeout_sec specifies integral part of the timeout (in seconds)
+    /// @param timeout_usec specifies fractional part of the timeout
+    /// (in microseconds)
+    ///
+    /// @throw isc::BadValue if timeout_usec is greater than one million
+    /// @throw isc::dhcp::SocketReadError if error occurred when receiving a
+    /// packet.
+    /// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
+    /// interrupted by a signal.
+    ///
+    /// @return Pkt4 object representing received packet (or NULL)
+    Pkt4Ptr receive4Indirect(uint32_t timeout_sec, uint32_t timeout_usec = 0);
+
     /// @brief Opens IPv6 socket.
     ///
     /// Please do not use this method directly. Use openSocket instead.
@@ -1142,6 +1162,51 @@ protected:
     int openSocket6(Iface& iface, const isc::asiolink::IOAddress& addr,
                     uint16_t port, const bool join_multicast);
 
+    /// @brief Receive IPv6 packets directly or data from external sockets.
+    ///
+    /// Attempts to receive a single DHCPv6 message over any of the open
+    /// IPv6 sockets. If reception is successful and all information about
+    /// its sender is obtained, an Pkt6 object is created and returned.
+    ///
+    /// This method also checks if data arrived over registered external socket.
+    /// This data may be of a different protocol family than AF_INET.
+    ///
+    /// @param timeout_sec specifies integral part of the timeout (in seconds)
+    /// @param timeout_usec specifies fractional part of the timeout
+    /// (in microseconds)
+    ///
+    /// @throw isc::BadValue if timeout_usec is greater than one million
+    /// @throw isc::dhcp::SocketReadError if error occurred when receiving a
+    /// packet.
+    /// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
+    /// interrupted by a signal.
+    ///
+    /// @return Pkt6 object representing received packet (or NULL)
+    Pkt6Ptr receive6Direct(uint32_t timeout_sec, uint32_t timeout_usec = 0);
+
+    /// @brief Receive IPv6 packets indirectly or data from external sockets.
+    ///
+    /// Attempts to receive a single DHCPv6 message from the packet queue.
+    /// The queue is populated by the receiver thread.  If a packet is waiting
+    /// in the queue, a Pkt6 returned.
+    ///
+    /// This method also checks if data arrived over registered external socket.
+    /// This data may be of a different protocol family than AF_INET.
+    ///
+    /// @param timeout_sec specifies integral part of the timeout (in seconds)
+    /// @param timeout_usec specifies fractional part of the timeout
+    /// (in microseconds)
+    ///
+    /// @throw isc::BadValue if timeout_usec is greater than one million
+    /// @throw isc::dhcp::SocketReadError if error occurred when receiving a
+    /// packet.
+    /// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
+    /// interrupted by a signal.
+    ///
+    /// @return Pkt6 object representing received packet (or NULL)
+    Pkt6Ptr receive6Indirect(uint32_t timeout_sec, uint32_t timeout_usec = 0);
+
+
     /// @brief Stub implementation of network interface detection.
     ///
     /// This implementations reads a single line from interfaces.txt file
index e4225c9cc4f1f9aa699aee0c92b7d662c9328ce4..edad39271f2f811cb133c1fcaa1aa48f239efc38 100644 (file)
@@ -449,7 +449,7 @@ public:
 
     /// @brief Tests the ability to send and receive DHCPv6 packets
     ///
-    /// This test calls @r IfaceMgr::configureDHCPqueue, passing int the
+    /// This test calls @r IfaceMgr::configureDHCPPacketQueue, passing in the
     /// given queue configuration.  It then calls IfaceMgr::startDHCPReceiver
     /// and verifies whether or not the receive thread has been started as
     /// expected.  Next it creates a generic DHCPv6 packet and sends it over
@@ -465,11 +465,11 @@ public:
         // Testing socket operation in a portable way is tricky
         // without interface detection implemented
         // let's assume that every supported OS have lo interface
-        IOAddress loAddr("::1");
+        IOAddress lo_addr("::1");
         int socket1 = 0, socket2 = 0;
         EXPECT_NO_THROW(
-            socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
-            socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10546);
+            socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10547);
+            socket2 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10546);
         );
 
         EXPECT_GE(socket1, 0);
@@ -537,7 +537,7 @@ public:
 
     /// @brief Tests the ability to send and receive DHCPv4 packets
     ///
-    /// This test calls @r IfaceMgr::configureDHCPqueue, passing int the
+    /// This test calls @r IfaceMgr::configureDHCPPacketQueue, passing in the
     /// given queue configuration.  It then calls IfaceMgr::startDHCPReceiver
     /// and verifies whether or not the receive thread has been started as
     /// expected.  Next it creates a DISCOVER packet and sends it over
@@ -553,10 +553,10 @@ public:
         // Testing socket operation in a portable way is tricky
         // without interface detection implemented.
         // Let's assume that every supported OS has lo interface
-        IOAddress loAddr("127.0.0.1");
+        IOAddress lo_addr("127.0.0.1");
         int socket1 = 0;
         EXPECT_NO_THROW(
-            socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
+            socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, DHCP4_SERVER_PORT + 10000);
         );
 
         EXPECT_GE(socket1, 0);
@@ -901,10 +901,10 @@ TEST_F(IfaceMgrTest, receiveTimeout6) {
 
     scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
     // Open socket on the lo interface.
-    IOAddress loAddr("::1");
+    IOAddress lo_addr("::1");
     int socket1 = 0;
     ASSERT_NO_THROW(
-        socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547)
+        socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10547)
     );
     // Socket is open if result is non-negative.
     ASSERT_GE(socket1, 0);
@@ -958,10 +958,10 @@ TEST_F(IfaceMgrTest, receiveTimeout4) {
 
     scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
     // Open socket on the lo interface.
-    IOAddress loAddr("127.0.0.1");
+    IOAddress lo_addr("127.0.0.1");
     int socket1 = 0;
     ASSERT_NO_THROW(
-        socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10067)
+        socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10067)
     );
     // Socket is open if returned value is non-negative.
     ASSERT_GE(socket1, 0);
@@ -1023,10 +1023,10 @@ TEST_F(IfaceMgrTest, multipleSockets) {
     init_sockets.push_back(socket1);
 
     // Create socket #2
-    IOAddress loAddr("127.0.0.1");
+    IOAddress lo_addr("127.0.0.1");
     int socket2 = 0;
     ASSERT_NO_THROW(
-        socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, PORT2);
+        socket2 = ifacemgr->openSocketFromRemoteAddress(lo_addr, PORT2);
     );
     ASSERT_GE(socket2, 0);
     init_sockets.push_back(socket2);
@@ -1102,19 +1102,19 @@ TEST_F(IfaceMgrTest, sockets6) {
 
     scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
 
-    IOAddress loAddr("::1");
+    IOAddress lo_addr("::1");
 
     Pkt6 pkt6(DHCPV6_SOLICIT, 123);
     pkt6.setIface(LOOPBACK);
 
     // Bind multicast socket to port 10547
-    int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
+    int socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10547);
     EXPECT_GE(socket1, 0); // socket >= 0
 
     EXPECT_EQ(socket1, ifacemgr->getSocket(pkt6));
 
     // Bind unicast socket to port 10548
-    int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
+    int socket2 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10548);
     EXPECT_GE(socket2, 0);
 
     // Removed code for binding socket twice to the same address/port
@@ -1133,7 +1133,7 @@ TEST_F(IfaceMgrTest, sockets6) {
 
     // Use non-existing interface name.
     EXPECT_THROW(
-        ifacemgr->openSocket("non_existing_interface", loAddr, 10548),
+        ifacemgr->openSocket("non_existing_interface", lo_addr, 10548),
         BadValue
     );
 
@@ -1182,18 +1182,18 @@ TEST_F(IfaceMgrTest, socketsFromAddress) {
 
     // Open v6 socket on loopback interface and bind to port
     int socket1 = 0;
-    IOAddress loAddr6("::1");
+    IOAddress lo_addr6("::1");
     EXPECT_NO_THROW(
-        socket1 = ifacemgr->openSocketFromAddress(loAddr6, PORT1);
+        socket1 = ifacemgr->openSocketFromAddress(lo_addr6, PORT1);
     );
     // socket descriptor must be non-negative integer
     EXPECT_GE(socket1, 0);
 
     // Open v4 socket on loopback interface and bind to different port
     int socket2 = 0;
-    IOAddress loAddr("127.0.0.1");
+    IOAddress lo_addr("127.0.0.1");
     EXPECT_NO_THROW(
-        socket2 = ifacemgr->openSocketFromAddress(loAddr, PORT2);
+        socket2 = ifacemgr->openSocketFromAddress(lo_addr, PORT2);
     );
     // socket descriptor must be positive integer
     EXPECT_GE(socket2, 0);
@@ -1219,17 +1219,17 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
     // Loopback address is the only one that we know
     // so let's treat it as remote address.
     int socket1 = 0;
-    IOAddress loAddr6("::1");
+    IOAddress lo_addr6("::1");
     EXPECT_NO_THROW(
-        socket1 = ifacemgr->openSocketFromRemoteAddress(loAddr6, PORT1);
+        socket1 = ifacemgr->openSocketFromRemoteAddress(lo_addr6, PORT1);
     );
     EXPECT_GE(socket1, 0);
 
     // Open v4 socket to connect to remote address.
     int socket2 = 0;
-    IOAddress loAddr("127.0.0.1");
+    IOAddress lo_addr("127.0.0.1");
     EXPECT_NO_THROW(
-        socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, PORT2);
+        socket2 = ifacemgr->openSocketFromRemoteAddress(lo_addr, PORT2);
     );
     EXPECT_GE(socket2, 0);
 
@@ -1255,7 +1255,7 @@ TEST_F(IfaceMgrTest, DISABLED_sockets6Mcast) {
 
     scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
 
-    IOAddress loAddr("::1");
+    IOAddress lo_addr("::1");
     IOAddress mcastAddr("ff02::1:2");
 
     // bind multicast socket to port 10547
@@ -1334,10 +1334,10 @@ TEST_F(IfaceMgrTest, setPacketFilter) {
 
     // Try to open socket using IfaceMgr. It should call the openSocket() function
     // on the packet filter object we have set.
-    IOAddress loAddr("127.0.0.1");
+    IOAddress lo_addr("127.0.0.1");
     int socket1 = 0;
     EXPECT_NO_THROW(
-        socket1 = iface_mgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
+        socket1 = iface_mgr->openSocket(LOOPBACK, lo_addr, DHCP4_SERVER_PORT + 10000);
     );
 
     // Check that openSocket function was called.
@@ -1374,10 +1374,10 @@ TEST_F(IfaceMgrTest, setPacketFilter6) {
 
     // Try to open socket using IfaceMgr. It should call the openSocket()
     // function on the packet filter object we have set.
-    IOAddress loAddr("::1");
+    IOAddress lo_addr("::1");
     int socket1 = 0;
     EXPECT_NO_THROW(
-        socket1 = iface_mgr->openSocket(LOOPBACK, loAddr,
+        socket1 = iface_mgr->openSocket(LOOPBACK, lo_addr,
                                         DHCP6_SERVER_PORT + 10000);
     );
     // Check that openSocket function has been actually called on the packet
@@ -1433,7 +1433,7 @@ TEST_F(IfaceMgrTest, setMatchingPacketFilter) {
 // socket bound to the same address and port. Failing to open the fallback
 // socket should preclude the raw socket from being open.
 TEST_F(IfaceMgrTest, checkPacketFilterRawSocket) {
-    IOAddress loAddr("127.0.0.1");
+    IOAddress lo_addr("127.0.0.1");
     int socket1 = -1, socket2 = -1;
     // Create two instances of IfaceMgr.
     boost::scoped_ptr<NakedIfaceMgr> iface_mgr1(new NakedIfaceMgr());
@@ -1446,7 +1446,7 @@ TEST_F(IfaceMgrTest, checkPacketFilterRawSocket) {
     // PktFilterInet.
     EXPECT_NO_THROW(iface_mgr1->setMatchingPacketFilter(false));
     // Let's open a loopback socket with handy unpriviliged port number
-    socket1 = iface_mgr1->openSocket(LOOPBACK, loAddr,
+    socket1 = iface_mgr1->openSocket(LOOPBACK, lo_addr,
                                      DHCP4_SERVER_PORT + 10000);
 
     EXPECT_GE(socket1, 0);
@@ -1457,7 +1457,7 @@ TEST_F(IfaceMgrTest, checkPacketFilterRawSocket) {
     // The socket is open and bound. Another attempt to open socket and
     // bind to the same address and port should result in an exception.
     EXPECT_THROW(
-        socket2 = iface_mgr2->openSocket(LOOPBACK, loAddr,
+        socket2 = iface_mgr2->openSocket(LOOPBACK, lo_addr,
                                          DHCP4_SERVER_PORT + 10000),
         isc::dhcp::SocketConfigError
     );
@@ -1515,12 +1515,12 @@ TEST_F(IfaceMgrTest, socket4) {
     scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
 
     // Let's assume that every supported OS have lo interface.
-    IOAddress loAddr("127.0.0.1");
+    IOAddress lo_addr("127.0.0.1");
     // Use unprivileged port (it's convenient for running tests as non-root).
     int socket1 = 0;
 
     EXPECT_NO_THROW(
-        socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
+        socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, DHCP4_SERVER_PORT + 10000);
     );
 
     EXPECT_GE(socket1, 0);