Browse Source

[5357] Dhcp{4,6} grammar extended, sample configs added.

Tomek Mrugalski 7 years ago
parent
commit
0a90abf2ed

+ 76 - 0
doc/examples/kea4/shared-network.json

@@ -0,0 +1,76 @@
+
+{
+    "Dhcp4": {
+        "interfaces-config": {
+            "interfaces": [ "eth0" ]
+        },
+
+        "lease-database": {
+            "type": "memfile",
+            "lfc-interval": 3600
+        },
+
+        "shared-networks": [
+        {
+            "interface": "eth1",
+            "match-client-id": false,
+            "name": "frog",
+            "option-data": [ ],
+            "rebind-timer": 150,
+            "relay": {
+                "ip-address": "0.0.0.0"
+            },
+            "renew-timer": 100,
+            "reservation-mode": "all",
+            "subnet4": [
+                {
+                    "4o6-interface": "",
+                    "4o6-interface-id": "",
+                    "4o6-subnet": "",
+                    "id": 1,
+                    "match-client-id": true,
+                    "next-server": "0.0.0.0",
+                    "option-data": [ ],
+                    "pools": [ ],
+                    "rebind-timer": 20,
+                    "relay": {
+                        "ip-address": "0.0.0.0"
+                    },
+                    "renew-timer": 10,
+                    "reservation-mode": "all",
+                    "subnet": "10.0.0.0/8",
+                    "valid-lifetime": 30
+                },
+                {
+                    "4o6-interface": "",
+                    "4o6-interface-id": "",
+                    "4o6-subnet": "",
+                    "id": 2,
+                    "match-client-id": true,
+                    "next-server": "0.0.0.0",
+                    "option-data": [ ],
+                    "pools": [ ],
+                    "rebind-timer": 20,
+                    "relay": {
+                        "ip-address": "0.0.0.0"
+                    },
+                    "renew-timer": 10,
+                    "reservation-mode": "all",
+                    "subnet": "192.0.2.0/24",
+                    "valid-lifetime": 30
+                }
+            ],
+            "valid-lifetime": 200
+        } ], // end of shared-networks
+
+        // This is regular subnet. It's not part of any shared-network.
+        "subnet4": [
+            {
+                "pools": [ { "pool":  "192.0.3.1 - 192.0.3.200" } ],
+                "subnet": "192.0.3.0/24",
+                "interface": "eth0"
+            }
+        ]
+        
+    } // end of Dhcp4
+}

+ 74 - 0
doc/examples/kea6/shared-network.json

@@ -0,0 +1,74 @@
+{
+    "Dhcp6": {
+// Kea is told to listen on ethX interface only.
+        "interfaces-config": {
+            "interfaces": [ "eth0" ]
+        },
+
+// We need to specify the the database used to store leases. As of
+// September 2016, four database backends are supported: MySQL,
+// PostgreSQL, Cassandra, and the in-memory database, Memfile.
+// We'll use memfile  because it doesn't require any prior set up.
+        "lease-database": {
+            "type": "memfile",
+            "lfc-interval": 3600
+        },
+
+        "subnet6": [
+            {
+                "pools": [ { "pool": "2001:db8:1::/80" } ],
+                "subnet": "2001:db8:1::/64",
+                "interface": "eth0"
+            }
+        ],
+
+        "shared-networks": [ 
+        {
+            "interface": "eth1",
+            "name": "frog",
+            "option-data": [ ],
+            "preferred-lifetime": 200,
+            "rapid-commit": true,
+            "rebind-timer": 150,
+            "relay": {
+                "ip-address": "::"
+            },
+            "renew-timer": 100,
+            "reservation-mode": "all",    "subnet6": [
+                {
+                    "id": 1,
+                    "option-data": [ ],
+                    "pd-pools": [ ],
+                    "pools": [ ],
+                    "preferred-lifetime": 30,
+                    "rapid-commit": false,
+                    "rebind-timer": 20,
+                    "relay": {
+                        "ip-address": "2001:db8:1::1"
+                    },
+                    "renew-timer": 10,
+                    "reservation-mode": "all",
+                    "subnet": "2001:db8:1::/64",
+                    "valid-lifetime": 40
+                },
+                {
+                    "id": 2,
+                    "option-data": [ ],
+                    "pd-pools": [ ],
+                    "pools": [ ],
+                    "preferred-lifetime": 30,
+                    "rapid-commit": false,
+                    "rebind-timer": 20,
+                    "relay": {
+                        "ip-address": "3000::1"
+                    },
+                    "renew-timer": 10,
+                    "reservation-mode": "all",
+                    "subnet": "3000::/16",
+                    "valid-lifetime": 40
+                }
+            ],
+            "valid-lifetime": 300
+        } ]
+    }
+}

+ 23 - 0
src/bin/dhcp4/dhcp4_lexer.ll

@@ -30,6 +30,8 @@ bool start_token_flag = false;
 isc::dhcp::Parser4Context::ParserType start_token_value;
 isc::dhcp::Parser4Context::ParserType start_token_value;
 unsigned int comment_start_line = 0;
 unsigned int comment_start_line = 0;
 
 
+using namespace isc::dhcp;
+
 };
 };
 
 
 /* To avoid the call to exit... oops! */
 /* To avoid the call to exit... oops! */
@@ -405,6 +407,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_VALID_LIFETIME(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_VALID_LIFETIME(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("valid-lifetime", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("valid-lifetime", driver.loc_);
@@ -415,6 +418,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_RENEW_TIMER(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_RENEW_TIMER(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("renew-timer", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("renew-timer", driver.loc_);
@@ -425,6 +429,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_REBIND_TIMER(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_REBIND_TIMER(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("rebind-timer", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("rebind-timer", driver.loc_);
@@ -443,12 +448,22 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"subnet4\" {
 \"subnet4\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::DHCP4:
+    case isc::dhcp::Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_SUBNET4(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_SUBNET4(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("subnet4", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("subnet4", driver.loc_);
     }
     }
 }
 }
 
 
+\"shared-networks\" {
+    switch (driver.ctx_) {
+    case Parser4Context::DHCP4:
+        return Dhcp4Parser::make_SHARED_NETWORKS(driver.loc_);
+    default:
+        return Dhcp4Parser::make_STRING("shared-networks", driver.loc_);
+    }
+}
+
 \"option-def\" {
 \"option-def\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::DHCP4:
@@ -466,6 +481,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     case isc::dhcp::Parser4Context::RESERVATIONS:
     case isc::dhcp::Parser4Context::RESERVATIONS:
     case isc::dhcp::Parser4Context::CLIENT_CLASSES:
     case isc::dhcp::Parser4Context::CLIENT_CLASSES:
     case isc::dhcp::Parser4Context::CLIENT_CLASS:
     case isc::dhcp::Parser4Context::CLIENT_CLASS:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_OPTION_DATA(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_OPTION_DATA(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("option-data", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("option-data", driver.loc_);
@@ -480,6 +496,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     case isc::dhcp::Parser4Context::OPTION_DATA:
     case isc::dhcp::Parser4Context::OPTION_DATA:
     case isc::dhcp::Parser4Context::CLIENT_CLASSES:
     case isc::dhcp::Parser4Context::CLIENT_CLASSES:
     case isc::dhcp::Parser4Context::CLIENT_CLASS:
     case isc::dhcp::Parser4Context::CLIENT_CLASS:
+    case Parser4Context::SHARED_NETWORK:
     case isc::dhcp::Parser4Context::LOGGERS:
     case isc::dhcp::Parser4Context::LOGGERS:
         return isc::dhcp::Dhcp4Parser::make_NAME(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_NAME(driver.loc_);
     default:
     default:
@@ -544,6 +561,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"interface\" {
 \"interface\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_INTERFACE(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_INTERFACE(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("interface", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("interface", driver.loc_);
@@ -580,6 +598,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"reservation-mode\" {
 \"reservation-mode\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
+    case isc::dhcp::Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_RESERVATION_MODE(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_RESERVATION_MODE(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("reservation-mode", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("reservation-mode", driver.loc_);
@@ -869,6 +888,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"relay\" {
 \"relay\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_RELAY(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_RELAY(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("relay", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("relay", driver.loc_);
@@ -1295,6 +1315,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_ECHO_CLIENT_ID(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_ECHO_CLIENT_ID(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("echo-client-id", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("echo-client-id", driver.loc_);
@@ -1305,6 +1326,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_MATCH_CLIENT_ID(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_MATCH_CLIENT_ID(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("match-client-id", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("match-client-id", driver.loc_);
@@ -1317,6 +1339,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::RESERVATIONS:
     case isc::dhcp::Parser4Context::RESERVATIONS:
     case isc::dhcp::Parser4Context::CLIENT_CLASSES:
     case isc::dhcp::Parser4Context::CLIENT_CLASSES:
+    case Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_NEXT_SERVER(driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_NEXT_SERVER(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp4Parser::make_STRING("next-server", driver.loc_);
         return isc::dhcp::Dhcp4Parser::make_STRING("next-server", driver.loc_);

+ 47 - 0
src/bin/dhcp4/dhcp4_parser.yy

@@ -101,6 +101,8 @@ using namespace std;
   ENCAPSULATE "encapsulate"
   ENCAPSULATE "encapsulate"
   ARRAY "array"
   ARRAY "array"
 
 
+  SHARED_NETWORKS "shared-networks"
+
   POOLS "pools"
   POOLS "pools"
   POOL "pool"
   POOL "pool"
   USER_CONTEXT "user-context"
   USER_CONTEXT "user-context"
@@ -404,6 +406,7 @@ global_param: valid_lifetime
             | rebind_timer
             | rebind_timer
             | decline_probation_period
             | decline_probation_period
             | subnet4_list
             | subnet4_list
+            | shared_networks
             | interfaces_config
             | interfaces_config
             | lease_database
             | lease_database
             | hosts_database
             | hosts_database
@@ -955,6 +958,50 @@ rapid_commit: RAPID_COMMIT COLON BOOLEAN {
     ctx.stack_.back()->set("rapid-commit", rc);
     ctx.stack_.back()->set("rapid-commit", rc);
 };
 };
 
 
+// ---- shared-networks ---------------------
+
+shared_networks: SHARED_NETWORKS {
+    ElementPtr l(new ListElement(ctx.loc2pos(@1)));
+    ctx.stack_.back()->set("shared-networks", l);
+    ctx.stack_.push_back(l);
+    ctx.enter(ctx.SHARED_NETWORK);
+} COLON LSQUARE_BRACKET shared_networks_list RSQUARE_BRACKET {
+    ctx.stack_.pop_back();
+    ctx.leave();
+};
+
+shared_networks_list: shared_network
+                    | shared_networks_list COMMA shared_network
+                    ;
+
+shared_network: LCURLY_BRACKET {
+    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+    ctx.stack_.back()->add(m);
+    ctx.stack_.push_back(m);
+} shared_network_params RCURLY_BRACKET {
+    ctx.stack_.pop_back();
+}
+
+shared_network_params: shared_network_param
+                     | shared_network_params COMMA shared_network_param
+                     ;
+
+shared_network_param: name
+                    | subnet4_list
+                    | interface
+                    | renew_timer
+                    | rebind_timer
+                    | option_data_list
+                    | match_client_id
+                    | next_server
+                    | relay
+                    | reservation_mode
+                    | echo_client_id
+                    | client_classes
+                    | valid_lifetime
+                    | unknown_map_entry
+                    ;
+
 // ---- option-def --------------------------
 // ---- option-def --------------------------
 
 
 // This defines the "option-def": [ ... ] entry that may appear
 // This defines the "option-def": [ ... ] entry that may appear

+ 2 - 0
src/bin/dhcp4/parser_context.cc

@@ -175,6 +175,8 @@ Parser4Context::contextName()
         return ("ncr-format");
         return ("ncr-format");
     case REPLACE_CLIENT_NAME:
     case REPLACE_CLIENT_NAME:
         return ("replace-client-name");
         return ("replace-client-name");
+    case SHARED_NETWORK:
+        return ("shared-networks");
     default:
     default:
         return ("__unknown__");
         return ("__unknown__");
     }
     }

+ 3 - 0
src/bin/dhcp4/parser_context.h

@@ -216,6 +216,9 @@ public:
         /// Used while parsing Dhcp4/Subnet4 structures.
         /// Used while parsing Dhcp4/Subnet4 structures.
         SUBNET4,
         SUBNET4,
 
 
+        /// Used while parsing shared-networks structures.
+        SHARED_NETWORK,
+
         /// Used while parsing Dhcp4/Subnet4/reservation-mode.
         /// Used while parsing Dhcp4/Subnet4/reservation-mode.
         RESERVATION_MODE,
         RESERVATION_MODE,
 
 

+ 1 - 0
src/bin/dhcp4/tests/parser_unittest.cc

@@ -252,6 +252,7 @@ TEST(ParserTest, file) {
                                "pgsql-reservations.json",
                                "pgsql-reservations.json",
                                "reservations.json",
                                "reservations.json",
                                "several-subnets.json",
                                "several-subnets.json",
+                               "shared-network.json",
                                "single-subnet.json",
                                "single-subnet.json",
                                "with-ddns.json" };
                                "with-ddns.json" };
 
 

+ 23 - 0
src/bin/dhcp6/dhcp6_lexer.ll

@@ -30,6 +30,8 @@ bool start_token_flag = false;
 isc::dhcp::Parser6Context::ParserType start_token_value;
 isc::dhcp::Parser6Context::ParserType start_token_value;
 unsigned int comment_start_line = 0;
 unsigned int comment_start_line = 0;
 
 
+using namespace isc::dhcp;
+
 };
 };
 
 
 /* To avoid the call to exit... oops! */
 /* To avoid the call to exit... oops! */
@@ -597,6 +599,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_PREFERRED_LIFETIME(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_PREFERRED_LIFETIME(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("preferred-lifetime", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("preferred-lifetime", driver.loc_);
@@ -607,6 +610,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_VALID_LIFETIME(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_VALID_LIFETIME(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("valid-lifetime", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("valid-lifetime", driver.loc_);
@@ -617,6 +621,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_RENEW_TIMER(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_RENEW_TIMER(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("renew-timer", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("renew-timer", driver.loc_);
@@ -627,6 +632,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_REBIND_TIMER(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_REBIND_TIMER(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("rebind-timer", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("rebind-timer", driver.loc_);
@@ -645,12 +651,22 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"subnet6\" {
 \"subnet6\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::DHCP6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_SUBNET6(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_SUBNET6(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("subnet6", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("subnet6", driver.loc_);
     }
     }
 }
 }
 
 
+\"shared-networks\" {
+    switch (driver.ctx_) {
+    case Parser6Context::DHCP6:
+        return Dhcp6Parser::make_SHARED_NETWORKS(driver.loc_);
+    default:
+        return Dhcp6Parser::make_STRING("shared-networks", driver.loc_);
+    }
+}
+
 \"option-def\" {
 \"option-def\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::DHCP6:
@@ -669,6 +685,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     case isc::dhcp::Parser6Context::RESERVATIONS:
     case isc::dhcp::Parser6Context::RESERVATIONS:
     case isc::dhcp::Parser6Context::CLIENT_CLASSES:
     case isc::dhcp::Parser6Context::CLIENT_CLASSES:
     case isc::dhcp::Parser6Context::CLIENT_CLASS:
     case isc::dhcp::Parser6Context::CLIENT_CLASS:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_OPTION_DATA(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_OPTION_DATA(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("option-data", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("option-data", driver.loc_);
@@ -684,6 +701,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     case isc::dhcp::Parser6Context::CLIENT_CLASSES:
     case isc::dhcp::Parser6Context::CLIENT_CLASSES:
     case isc::dhcp::Parser6Context::CLIENT_CLASS:
     case isc::dhcp::Parser6Context::CLIENT_CLASS:
     case isc::dhcp::Parser6Context::LOGGERS:
     case isc::dhcp::Parser6Context::LOGGERS:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_NAME(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_NAME(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("name", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("name", driver.loc_);
@@ -802,6 +820,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"interface\" {
 \"interface\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_INTERFACE(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_INTERFACE(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("interface", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("interface", driver.loc_);
@@ -811,6 +830,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"interface-id\" {
 \"interface-id\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_INTERFACE_ID(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_INTERFACE_ID(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("interface-id", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("interface-id", driver.loc_);
@@ -829,6 +849,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"rapid-commit\" {
 \"rapid-commit\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_RAPID_COMMIT(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_RAPID_COMMIT(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("rapid-commit", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("rapid-commit", driver.loc_);
@@ -838,6 +859,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"reservation-mode\" {
 \"reservation-mode\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_RESERVATION_MODE(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_RESERVATION_MODE(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("reservation-mode", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("reservation-mode", driver.loc_);
@@ -1145,6 +1167,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"relay\" {
 \"relay\" {
     switch(driver.ctx_) {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SUBNET6:
+    case Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_RELAY(driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_RELAY(driver.loc_);
     default:
     default:
         return isc::dhcp::Dhcp6Parser::make_STRING("relay", driver.loc_);
         return isc::dhcp::Dhcp6Parser::make_STRING("relay", driver.loc_);

+ 46 - 0
src/bin/dhcp6/dhcp6_parser.yy

@@ -109,6 +109,7 @@ using namespace std;
   DISABLED "disabled"
   DISABLED "disabled"
   OUT_OF_POOL "out-of-pool"
   OUT_OF_POOL "out-of-pool"
   ALL "all"
   ALL "all"
+  SHARED_NETWORKS "shared-networks"
 
 
   MAC_SOURCES "mac-sources"
   MAC_SOURCES "mac-sources"
   RELAY_SUPPLIED_OPTIONS "relay-supplied-options"
   RELAY_SUPPLIED_OPTIONS "relay-supplied-options"
@@ -413,6 +414,7 @@ global_param: preferred_lifetime
             | rebind_timer
             | rebind_timer
             | decline_probation_period
             | decline_probation_period
             | subnet6_list
             | subnet6_list
+            | shared_networks
             | interfaces_config
             | interfaces_config
             | lease_database
             | lease_database
             | hosts_database
             | hosts_database
@@ -942,6 +944,50 @@ rapid_commit: RAPID_COMMIT COLON BOOLEAN {
     ctx.stack_.back()->set("rapid-commit", rc);
     ctx.stack_.back()->set("rapid-commit", rc);
 };
 };
 
 
+
+// ---- shared-networks ---------------------
+
+shared_networks: SHARED_NETWORKS {
+    ElementPtr l(new ListElement(ctx.loc2pos(@1)));
+    ctx.stack_.back()->set("shared-networks", l);
+    ctx.stack_.push_back(l);
+    ctx.enter(ctx.SHARED_NETWORK);
+} COLON LSQUARE_BRACKET shared_networks_list RSQUARE_BRACKET {
+    ctx.stack_.pop_back();
+    ctx.leave();
+};
+
+shared_networks_list: shared_network
+                    | shared_networks_list COMMA shared_network
+                    ;
+
+shared_network: LCURLY_BRACKET {
+    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+    ctx.stack_.back()->add(m);
+    ctx.stack_.push_back(m);
+} shared_network_params RCURLY_BRACKET {
+    ctx.stack_.pop_back();
+}
+
+shared_network_params: shared_network_param
+                     | shared_network_params COMMA shared_network_param
+                     ;
+
+shared_network_param: name
+                    | subnet6_list
+                    | interface
+                    | renew_timer
+                    | rebind_timer
+                    | option_data_list
+                    | relay
+                    | reservation_mode
+                    | client_classes
+                    | preferred_lifetime
+                    | rapid_commit
+                    | valid_lifetime
+                    | unknown_map_entry
+                    ;
+
 // ---- option-def --------------------------
 // ---- option-def --------------------------
 
 
 // This defines the "option-def": [ ... ] entry that may appear
 // This defines the "option-def": [ ... ] entry that may appear

+ 3 - 1
src/bin/dhcp6/parser_context.cc

@@ -179,7 +179,9 @@ Parser6Context::contextName()
         return ("ncr-format");
         return ("ncr-format");
     case REPLACE_CLIENT_NAME:
     case REPLACE_CLIENT_NAME:
         return ("replace-client-name");
         return ("replace-client-name");
-    default:
+    case SHARED_NETWORK:
+        return ("shared-networks");
+     default:
         return ("__unknown__");
         return ("__unknown__");
     }
     }
 }
 }

+ 3 - 0
src/bin/dhcp6/parser_context.h

@@ -219,6 +219,9 @@ public:
         /// Used while parsing Dhcp6/Subnet6 structures.
         /// Used while parsing Dhcp6/Subnet6 structures.
         SUBNET6,
         SUBNET6,
 
 
+        /// Used while parsing shared-networks structures.
+        SHARED_NETWORK,
+
         /// Used while parsing Dhcp6/Subnet6/reservation-mode.
         /// Used while parsing Dhcp6/Subnet6/reservation-mode.
         RESERVATION_MODE,
         RESERVATION_MODE,
 
 

+ 1 - 0
src/bin/dhcp6/tests/parser_unittest.cc

@@ -256,6 +256,7 @@ TEST(ParserTest, file) {
     configs.push_back("pgsql-reservations.json");
     configs.push_back("pgsql-reservations.json");
     configs.push_back("reservations.json");
     configs.push_back("reservations.json");
     configs.push_back("several-subnets.json");
     configs.push_back("several-subnets.json");
+    configs.push_back("shared-network.json");
     configs.push_back("simple.json");
     configs.push_back("simple.json");
     configs.push_back("stateless.json");
     configs.push_back("stateless.json");
     configs.push_back("with-ddns.json");
     configs.push_back("with-ddns.json");