Commit 924a4f46 authored by Thomas Markwalder's avatar Thomas Markwalder

[#260,!120] Addressed most of review comments

    Addressed all comments except parsing regen and
    refactor of watch sockets in IfaceMgr.  Doing those
    separately.
parent 1f31a082
......@@ -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.
......@@ -34,13 +59,13 @@
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>
......@@ -89,7 +113,7 @@
</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":
{
......@@ -104,7 +128,7 @@
</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":
{
......
......@@ -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