Skip to content

Commit

Permalink
Merge branch 'over-v6' into vita (fix up oversights in snabbco#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
eugeneia committed Jan 26, 2019
2 parents f67cdde + 1da3b4f commit 56a66b9
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 22 deletions.
89 changes: 81 additions & 8 deletions src/lib/yang/data.lua
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,12 @@ function data_grammar_from_schema(schema, is_config)
function handlers.choice(node)
local choices = {}
for choice, n in pairs(node.body) do
local members = visit_body(n)
if not is_empty(members) then choices[choice] = members end
if n.kind == 'case' then
local members = visit_body(n)
if not is_empty(members) then choices[choice] = members end
else
choices[choice] = { [choice] = visit(n) }
end
end
if is_empty(choices) then return end
return {type="choice", default=node.default, mandatory=node.mandatory,
Expand Down Expand Up @@ -501,19 +505,23 @@ function choice_parser(keyword, choices, members, default, mandatory)
-- using different leaves from different case statements.
local chosen

-- keep track of initialzed members
local inits = {}

local function init() return {} end
local function parse(P, out, k)
if chosen and choice_map[k] ~= chosen then
error("Only one choice set can exist at one time: "..keyword)
else
chosen = choice_map[k]
end
return members[chosen][k].parse(P, members[chosen][k].init(), k)
inits[k] = inits[k] or members[chosen][k].init()
return members[chosen][k].parse(P, inits[k], k)
end

-- This holds a copy of all the nodes so we know when we've hit the last one.
local function finish(out, k)
if out ~= nil then return out end
if out ~= nil then return members[chosen][k].finish(out) end
if mandatory and chosen == nil then error("missing choice value: "..keyword) end
if default and default == choice_map[k] then
return members[default][k].finish()
Expand Down Expand Up @@ -659,22 +667,39 @@ function data_parser_from_grammar(production)
function top_parsers.struct(production)
local struct_t = production.ctype and typeof(production.ctype)
local members = visitn(production.members)
local keys = {}
for k,v in pairs(members) do table.insert(keys, k) end
return function(stream)
local P = parser_mod.Parser.new(stream)
local ret = {}
for k,sub in pairs(members) do ret[normalize_id(k)] = sub.init() end
local expanded_members = {}
for _,k in ipairs(keys) do
if members[k].represents then
-- Choice fields don't include the name of the choice block in the data. They
-- need to be able to provide the parser for the leaves it represents.
local member_parser = members[k].stateful_parser()
for _, node in pairs(members[k].represents()) do
-- Choice fields need to keep state around as they're called multiple times
-- and need to do some validation to comply with spec.
expanded_members[node] = member_parser
end
else
ret[normalize_id(k)] = members[k].init()
expanded_members[k] = members[k]
end
end
while true do
P:skip_whitespace()
if P:is_eof() then break end
local k = P:parse_identifier()
if k == '' then P:error("Expected a keyword") end
local sub = members[k] or P:error('unrecognized parameter: '..k)
local sub = expanded_members[k] or P:error('unrecognized parameter: '..k)
local id = normalize_id(k)
ret[id] = sub.parse(P, ret[id], k)
end
for k,sub in pairs(members) do
for k,sub in pairs(expanded_members) do
local id = normalize_id(k)
ret[id] = sub.finish(ret[id])
ret[id] = sub.finish(ret[id], k)
end
if struct_t then return struct_t(ret) else return ret end
end
Expand Down Expand Up @@ -1878,6 +1903,54 @@ function selftest()
]])
assert(success == false)

-- Test top-level choice with list member.
local choice_schema = schema.load_schema([[module toplevel-choice-schema {
namespace "urn:ietf:params:xml:ns:yang:toplevel-choice-schema";
prefix "test";
choice test {
case this {
leaf foo { type string; }
leaf bar { type string; }
}
case that {
leaf baz { type uint32; }
list qu-x { key id; leaf id { type string; } leaf v { type string; } }
}
}
}]])
local choice_data = load_config_for_schema(choice_schema,
mem.open_input_string [[
foo "hello";
bar "world";
]])
assert(choice_data.foo == "hello")
assert(choice_data.bar == "world")
local choice_data = load_config_for_schema(choice_schema,
mem.open_input_string [[
baz 1;
qu-x { id "me"; v "hey"; }
qu-x { id "you"; v "hi"; }
]])
assert(choice_data.baz == 1)
assert(choice_data.qu_x.me.v == "hey")
assert(choice_data.qu_x.you.v == "hi")

-- Test choice with case short form.
local choice_schema = schema.load_schema([[module shortform-choice-schema {
namespace "urn:ietf:params:xml:ns:yang:shortform-choice-schema";
prefix "test";
choice test {
default foo;
leaf foo { type string; default "something"; }
leaf bar { type string; }
}
}]])
local choice_data = load_config_for_schema(choice_schema,
mem.open_input_string "")
assert(choice_data.foo == "something")

-- Check native number key.
local native_number_key_schema = schema.load_schema([[module native-number-key {
namespace "urn:ietf:params:xml:ns:yang:native-number-key";
Expand Down
9 changes: 4 additions & 5 deletions src/program/vita/vita-esp-gateway.yang
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,17 @@ module vita-esp-gateway {
leaf preshared-key { type key32; mandatory true; }
}

choice router {
case v4-over-v4 {
container private-interface4 { uses interface4; }
container private-interface4 { uses interface4; }
choice public-router {
case over-v4 {
container public-interface4 { uses interface4; }
list route4 {
key id; unique "net-cidr4"; unique "preshared-key"; unique "spi"; uses route;
leaf net-cidr4 { type inet:ipv4-prefix; mandatory true; }
leaf gw-ip4 { type inet:ipv4-address-no-zone; }
}
}
case v4-over-v6 {
container private-interface4 { uses interface4; }
case over-v6 {
container public-interface6 { uses interface6; }
list route46 {
key id; unique "net-cidr4"; unique "preshared-key"; unique "spi"; uses route;
Expand Down
13 changes: 4 additions & 9 deletions src/program/vita/vita-gentest.yang
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@ module vita-gentest {

import vita-esp-gateway { prefix vita; }

choice router {
case v4-over-v4 {
container private-interface4 { uses vita:interface4; }
container public-interface4 { uses vita:interface4; }
}
case v4-over-v6 {
container private-interface4 { uses vita:interface4; }
container public-interface6 { uses vita:interface6; }
}
container private-interface4 { uses vita:interface4; }
choice public-router {
container public-interface4 { uses vita:interface4; }
container public-interface6 { uses vita:interface6; }
}

leaf negotiation-ttl { type vita:time-to-live; }
Expand Down

0 comments on commit 56a66b9

Please sign in to comment.