From 8b07e1e36412256b531e122e3eaf6350f4e38ad2 Mon Sep 17 00:00:00 2001 From: Jessica Tallon Date: Sun, 25 Jun 2017 11:14:52 +0200 Subject: [PATCH 1/4] Add YANG binary data emitter for choice statements --- src/lib/yang/binary.lua | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/lib/yang/binary.lua b/src/lib/yang/binary.lua index c951163d60..22d5916626 100644 --- a/src/lib/yang/binary.lua +++ b/src/lib/yang/binary.lua @@ -102,16 +102,39 @@ end local function data_emitter(production) local handlers = {} + local translators = {} local function visit1(production) return assert(handlers[production.type])(production) end local function visitn(productions) local ret = {} - for keyword,production in pairs(productions) do + local expanded_production = productions + for keyword, production in pairs(productions) do + if translators[production.type] ~= nil then + expanded_production = translators[production.type]( + expanded_production, keyword, production + ) + end + end + for keyword,production in pairs(expanded_production) do ret[keyword] = visit1(production) end return ret end + function translators.choice(productions, keyword, production) + local rtn = {} + -- First, do a shallow copy. + for k,v in pairs(productions) do rtn[k] = v end + + -- Now bring the choice statements up to the same level replacing it. + for case, block in pairs(production.choices) do + for name, body in pairs(block) do rtn[name] = body end + end + + -- Finally remove the choice statement entirely. + rtn[keyword] = nil + return rtn + end function handlers.struct(production) local member_names = {} for k,_ in pairs(production.members) do table.insert(member_names, k) end From 725a9156069c2c1361b30b81df84797082897e7a Mon Sep 17 00:00:00 2001 From: Jessica Tallon Date: Mon, 26 Jun 2017 16:34:09 +0200 Subject: [PATCH 2/4] Add test for choice support for YANG binary compilation This adds a test to verify that the choice field can be compiled and then read back out correctly. --- src/lib/yang/binary.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/lib/yang/binary.lua b/src/lib/yang/binary.lua index 22d5916626..da0a07f472 100644 --- a/src/lib/yang/binary.lua +++ b/src/lib/yang/binary.lua @@ -455,6 +455,7 @@ function selftest() prefix simple-router; import ietf-inet-types {prefix inet;} + import ietf-yang-types { prefix yang; } leaf is-active { type boolean; default true; } @@ -483,6 +484,20 @@ function selftest() type severity; } } + + container next-hop { + choice address { + case mac { + leaf mac { type yang:mac-address; } + } + case ipv4 { + leaf ipv4 { type inet:ipv4-address; } + } + case ipv6 { + leaf ipv6 { type inet:ipv6-address; } + } + } + } }]]) local data = data.load_data_for_schema(test_schema, [[ is-active true; @@ -497,6 +512,9 @@ function selftest() route { addr 3.4.5.6; port 2; } severity minor; } + next-hop { + ipv4 5.6.7.8; + } ]]) local ipv4 = require('lib.protocol.ipv4') @@ -518,6 +536,7 @@ function selftest() assert(routing_table:lookup_ptr(key).value.port == 10) key.addr = util.ipv4_pton('3.4.5.6') assert(routing_table:lookup_ptr(key).value.port == 2) + assert(data.next_hop.ipv4 == util.ipv4_pton('5.6.7.8')) local tmp = os.tmpname() compile_data_for_schema(test_schema, data, tmp) From acb67077d81560b4e0e558ed0b6ca5dae1f47ceb Mon Sep 17 00:00:00 2001 From: Jessica Tallon Date: Tue, 27 Jun 2017 15:27:39 +0200 Subject: [PATCH 3/4] Include the round which binary choice test fails --- src/lib/yang/binary.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/yang/binary.lua b/src/lib/yang/binary.lua index da0a07f472..28722e5a54 100644 --- a/src/lib/yang/binary.lua +++ b/src/lib/yang/binary.lua @@ -536,7 +536,10 @@ function selftest() assert(routing_table:lookup_ptr(key).value.port == 10) key.addr = util.ipv4_pton('3.4.5.6') assert(routing_table:lookup_ptr(key).value.port == 2) - assert(data.next_hop.ipv4 == util.ipv4_pton('5.6.7.8')) + assert( + data.next_hop.ipv4 == util.ipv4_pton('5.6.7.8'), + "Choice type test failed (round: "..i..")" + ) local tmp = os.tmpname() compile_data_for_schema(test_schema, data, tmp) From 0eb00d3cc5b4d10a0a0a22d325be93551222aae8 Mon Sep 17 00:00:00 2001 From: Jessica Tallon Date: Mon, 3 Jul 2017 05:02:34 +0200 Subject: [PATCH 4/4] Fix bug where choice statements where not being written out correctly --- src/lib/yang/binary.lua | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/lib/yang/binary.lua b/src/lib/yang/binary.lua index 28722e5a54..86a62df44f 100644 --- a/src/lib/yang/binary.lua +++ b/src/lib/yang/binary.lua @@ -106,15 +106,23 @@ local function data_emitter(production) local function visit1(production) return assert(handlers[production.type])(production) end + local function expand(production) + if production.type ~= "struct" then return production end + local expanded = {} + for keyword,prod in pairs(production.members) do + if translators[prod.type] ~= nil then + translators[prod.type](expanded, keyword, prod) + else + expanded[keyword] = prod + end + end + return {type="struct", members=expanded} + end local function visitn(productions) local ret = {} local expanded_production = productions for keyword, production in pairs(productions) do - if translators[production.type] ~= nil then - expanded_production = translators[production.type]( - expanded_production, keyword, production - ) - end + expanded_production[keyword] = expand(production) end for keyword,production in pairs(expanded_production) do ret[keyword] = visit1(production) @@ -122,18 +130,10 @@ local function data_emitter(production) return ret end function translators.choice(productions, keyword, production) - local rtn = {} - -- First, do a shallow copy. - for k,v in pairs(productions) do rtn[k] = v end - -- Now bring the choice statements up to the same level replacing it. for case, block in pairs(production.choices) do - for name, body in pairs(block) do rtn[name] = body end + for name, body in pairs(block) do productions[name] = body end end - - -- Finally remove the choice statement entirely. - rtn[keyword] = nil - return rtn end function handlers.struct(production) local member_names = {}