Commit 40df4358 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5351] Checkpoint: option-data ready

parent 071f6783
......@@ -583,6 +583,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
case isc::dhcp::Parser4Context::POOLS:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
case isc::dhcp::Parser4Context::OPTION_DEF:
case isc::dhcp::Parser4Context::OPTION_DATA:
return isc::dhcp::Dhcp4Parser::make_USER_CONTEXT(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("user-context", driver.loc_);
......@@ -596,6 +597,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
case isc::dhcp::Parser4Context::POOLS:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
case isc::dhcp::Parser4Context::OPTION_DEF:
case isc::dhcp::Parser4Context::OPTION_DATA:
return isc::dhcp::Dhcp4Parser::make_COMMENT(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("comment", driver.loc_);
......
......@@ -1261,6 +1261,8 @@ option_data_param: option_data_name
| option_data_space
| option_data_csv_format
| option_data_always_send
| user_context
| comment
| unknown_map_entry
;
......
......@@ -5619,6 +5619,12 @@ TEST_F(Dhcp4ParserTest, comments) {
" \"type\": \"ipv4-address\",\n"
" \"space\": \"isc\"\n"
" } ],\n"
"\"option-data\": [ {\n"
" \"name\": \"dhcp-message\",\n"
" \"comment\": \"Set option value\",\n"
" \"data\": \"ABCDEF0105\",\n"
" \"csv-format\": false\n"
" } ],\n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n,"
" \"comment\": \"A shared network\"\n,"
......@@ -5647,10 +5653,7 @@ TEST_F(Dhcp4ParserTest, comments) {
ASSERT_TRUE(ctx->get("comment"));
EXPECT_EQ("\"A DHCPv4 server\"", ctx->get("comment")->str());
// Make the option definition available.
LibDHCP::commitRuntimeOptionDefs();
// Get and verify the option definition.
// There is a global option definition.
OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100);
ASSERT_TRUE(opt_def);
EXPECT_EQ("foo", opt_def->getName());
......@@ -5659,13 +5662,27 @@ TEST_F(Dhcp4ParserTest, comments) {
EXPECT_EQ(OPT_IPV4_ADDRESS_TYPE, opt_def->getType());
EXPECT_TRUE(opt_def->getEncapsulatedSpace().empty());
// Check option definition user context
// Check option definition user context.
ConstElementPtr ctx_opt_def = opt_def->getContext();
ASSERT_TRUE(ctx_opt_def);
ASSERT_EQ(1, ctx_opt_def->size());
ASSERT_TRUE(ctx_opt_def->get("comment"));
EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str());
// There is an option descriptor aka option data.
OptionDescriptor opt_desc =
CfgMgr::instance().getStagingCfg()->getCfgOption()->
get(DHCP4_OPTION_SPACE, DHO_DHCP_MESSAGE);
ASSERT_TRUE(opt_desc.option_);
EXPECT_EQ(DHO_DHCP_MESSAGE, opt_desc.option_->getType());
// Check option descriptor user context.
ConstElementPtr ctx_opt_desc = opt_desc.getContext();
ASSERT_TRUE(ctx_opt_desc);
ASSERT_EQ(1, ctx_opt_desc->size());
ASSERT_TRUE(ctx_opt_desc->get("comment"));
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
// Now verify that the shared network was indeed configured.
CfgSharedNetworks4Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks4();
......@@ -5676,7 +5693,7 @@ TEST_F(Dhcp4ParserTest, comments) {
SharedNetwork4Ptr net = nets->at(0);
ASSERT_TRUE(net);
// Check shared network user context
// Check shared network user context.
ConstElementPtr ctx_net = net->getContext();
ASSERT_TRUE(ctx_net);
ASSERT_EQ(1, ctx_net->size());
......@@ -5690,20 +5707,20 @@ TEST_F(Dhcp4ParserTest, comments) {
Subnet4Ptr sub = subs->at(0);
ASSERT_TRUE(sub);
// Check subnet user context
// Check subnet user context.
ConstElementPtr ctx_sub = sub->getContext();
ASSERT_TRUE(ctx_sub);
ASSERT_EQ(1, ctx_sub->size());
ASSERT_TRUE(ctx_sub->get("comment"));
EXPECT_EQ("\"A subnet\"", ctx_sub->get("comment")->str());
// The subnet has a pool
// The subnet has a pool.
const PoolCollection& pools = sub->getPools(Lease::TYPE_V4);
ASSERT_EQ(1, pools.size());
PoolPtr pool = pools.at(0);
ASSERT_TRUE(pool);
// Check pool user context
// Check pool user context.
ConstElementPtr ctx_pool = pool->getContext();
ASSERT_TRUE(ctx_pool);
ASSERT_EQ(1, ctx_pool->size());
......
......@@ -814,6 +814,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
case isc::dhcp::Parser6Context::OPTION_DEF:
case isc::dhcp::Parser6Context::OPTION_DATA:
return isc::dhcp::Dhcp6Parser::make_USER_CONTEXT(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("user-context", driver.loc_);
......@@ -828,6 +829,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
case isc::dhcp::Parser6Context::OPTION_DEF:
case isc::dhcp::Parser6Context::OPTION_DATA:
return isc::dhcp::Dhcp6Parser::make_COMMENT(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("comment", driver.loc_);
......
......@@ -1225,6 +1225,8 @@ option_data_param: option_data_name
| option_data_space
| option_data_csv_format
| option_data_always_send
| user_context
| comment
| unknown_map_entry
;
......
......@@ -6061,6 +6061,12 @@ TEST_F(Dhcp6ParserTest, comments) {
" \"type\": \"ipv6-address\",\n"
" \"space\": \"isc\"\n"
" } ],\n"
"\"option-data\": [ {\n"
" \"name\": \"subscriber-id\",\n"
" \"comment\": \"Set option value\",\n"
" \"data\": \"ABCDEF0105\",\n"
" \"csv-format\": false\n"
" } ],\n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n,"
" \"comment\": \"A shared network\"\n,"
......@@ -6090,17 +6096,14 @@ TEST_F(Dhcp6ParserTest, comments) {
extractConfig(config);
configure(config, CONTROL_RESULT_SUCCESS, "");
// Check global user context
// Check global user context.
ConstElementPtr ctx = CfgMgr::instance().getStagingCfg()->getContext();
ASSERT_TRUE(ctx);
ASSERT_EQ(1, ctx->size());
ASSERT_TRUE(ctx->get("comment"));
EXPECT_EQ("\"A DHCPv6 server\"", ctx->get("comment")->str());
// Make the option definition available.
LibDHCP::commitRuntimeOptionDefs();
// Get and verify the option definition.
// There is a global option definition.
OptionDefinitionPtr opt_def = LibDHCP::getRuntimeOptionDef("isc", 100);
ASSERT_TRUE(opt_def);
EXPECT_EQ("foo", opt_def->getName());
......@@ -6109,13 +6112,27 @@ TEST_F(Dhcp6ParserTest, comments) {
EXPECT_EQ(OPT_IPV6_ADDRESS_TYPE, opt_def->getType());
EXPECT_TRUE(opt_def->getEncapsulatedSpace().empty());
// Check option definition user context
// Check option definition user context.
ConstElementPtr ctx_opt_def = opt_def->getContext();
ASSERT_TRUE(ctx_opt_def);
ASSERT_EQ(1, ctx_opt_def->size());
ASSERT_TRUE(ctx_opt_def->get("comment"));
EXPECT_EQ("\"An option definition\"", ctx_opt_def->get("comment")->str());
// There is an option descriptor aka option data.
OptionDescriptor opt_desc =
CfgMgr::instance().getStagingCfg()->getCfgOption()->
get(DHCP6_OPTION_SPACE, D6O_SUBSCRIBER_ID);
ASSERT_TRUE(opt_desc.option_);
EXPECT_EQ(D6O_SUBSCRIBER_ID, opt_desc.option_->getType());
// Check option descriptor user context.
ConstElementPtr ctx_opt_desc = opt_desc.getContext();
ASSERT_TRUE(ctx_opt_desc);
ASSERT_EQ(1, ctx_opt_desc->size());
ASSERT_TRUE(ctx_opt_desc->get("comment"));
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
// Now verify that the shared network was indeed configured.
CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks6();
......@@ -6126,7 +6143,7 @@ TEST_F(Dhcp6ParserTest, comments) {
SharedNetwork6Ptr net = nets->at(0);
ASSERT_TRUE(net);
// Check shared network user context
// Check shared network user context.
ConstElementPtr ctx_net = net->getContext();
ASSERT_TRUE(ctx_net);
ASSERT_EQ(1, ctx_net->size());
......@@ -6140,33 +6157,33 @@ TEST_F(Dhcp6ParserTest, comments) {
Subnet6Ptr sub = subs->at(0);
ASSERT_TRUE(sub);
// Check subnet user context
// Check subnet user context.
ConstElementPtr ctx_sub = sub->getContext();
ASSERT_TRUE(ctx_sub);
ASSERT_EQ(1, ctx_sub->size());
ASSERT_TRUE(ctx_sub->get("comment"));
EXPECT_EQ("\"A subnet\"", ctx_sub->get("comment")->str());
// The subnet has a pool
// The subnet has a pool.
const PoolCollection& pools = sub->getPools(Lease::TYPE_NA);
ASSERT_EQ(1, pools.size());
PoolPtr pool = pools.at(0);
ASSERT_TRUE(pool);
// Check pool user context
// Check pool user context.
ConstElementPtr ctx_pool = pool->getContext();
ASSERT_TRUE(ctx_pool);
ASSERT_EQ(1, ctx_pool->size());
ASSERT_TRUE(ctx_pool->get("comment"));
EXPECT_EQ("\"A pool\"", ctx_pool->get("comment")->str());
// The subnet has a prefix pool
// The subnet has a prefix pool.
const PoolCollection& pdpools = sub->getPools(Lease::TYPE_PD);
ASSERT_EQ(1, pdpools.size());
PoolPtr pdpool = pdpools.at(0);
ASSERT_TRUE(pdpool);
// Check prefix pool user context
// Check prefix pool user context.
ConstElementPtr ctx_pdpool = pdpool->getContext();
ASSERT_TRUE(ctx_pdpool);
ASSERT_EQ(1, ctx_pdpool->size());
......
......@@ -201,7 +201,9 @@ CfgOption::toElement() const {
opt != opts->end(); ++opt) {
// Get and fill the map for this option
ElementPtr map = Element::createMap();
// First set space from parent iterator
// Set user context
opt->contextToElement(map);
// Set space from parent iterator
map->set("space", Element::create(*name));
// Set the code
uint16_t code = opt->option_->getType();
......@@ -242,7 +244,9 @@ CfgOption::toElement() const {
opt != opts->end(); ++opt) {
// Get and fill the map for this option
ElementPtr map = Element::createMap();
// First set space from parent iterator
// Set user context
opt->contextToElement(map);
// Set space from parent iterator
std::ostringstream oss;
oss << "vendor-" << *id;
map->set("space", Element::create(oss.str()));
......
......@@ -10,6 +10,7 @@
#include <dhcp/option.h>
#include <dhcp/option_space_container.h>
#include <cc/cfg_to_element.h>
#include <cc/user_context.h>
#include <dhcpsrv/key_from_key.h>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
......@@ -30,7 +31,8 @@ namespace dhcp {
/// for this option. This information comprises whether this option is sent
/// to DHCP client only on request (persistent = false) or always
/// (persistent = true).
struct OptionDescriptor {
class OptionDescriptor : public UserContext {
public:
/// @brief Option instance.
OptionPtr option_;
......
......@@ -235,6 +235,7 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
OptionalValue<bool> persist_param = extractPersistent(option_data);
std::string data_param = extractData(option_data);
std::string space_param = extractSpace(option_data);
ConstElementPtr user_context = option_data->get("user-context");
// Require that option code or option name is specified.
if (!code_param.isSpecified() && !name_param.isSpecified()) {
......@@ -357,6 +358,11 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
}
}
// Add user context
if (user_context) {
desc.setContext(user_context);
}
// All went good, so we can set the option space name.
return make_pair(desc, space_param);
}
......
......@@ -600,6 +600,7 @@ TEST_F(CfgOptionTest, unparse) {
cfg.add(opt1, false, "dns");
OptionPtr opt2(new Option(Option::V6, 101, OptionBuffer(4, 12)));
OptionDescriptor desc2(opt2, false, "12, 12, 12, 12");
desc2.setContext(data::Element::fromJSON("{ \"comment\": \"foo\" }"));
cfg.add(desc2, "dns");
OptionPtr opt3(new Option(Option::V6, D6O_STATUS_CODE, OptionBuffer(2, 0)));
cfg.add(opt3, false, DHCP6_OPTION_SPACE);
......@@ -615,6 +616,7 @@ TEST_F(CfgOptionTest, unparse) {
" \"data\": \"12121212\",\n"
" \"always-send\": false\n"
"},{\n"
" \"comment\": \"foo\",\n"
" \"code\": 101,\n"
" \"space\": \"dns\",\n"
" \"csv-format\": true,\n"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment