1©2015 Tail-f Systems all rights reservedFebruary 13, 2015
CDB Subscribers
2©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Triggers when
anything in
scope changes
Subscribe to Configuration Changes
subsock = socket(PF_INET, SOCK_STREAM, 0);
cdb_connect(subsock, CDB_SUBSCRIPTION_SOCKET, &confd, size);
cdb_subscribe(subsock, 3, dhcpd__ns, &spoint, "/dhcp");
cdb_subscribe_done(subsock);
/ dhcp/
aaa/
voip/
defaultLe…
maxLeas…
SubNets/ subNet/
mask
range
lowAddr
highAddr
logFacility
net
Managed Objects typically have
several subscription points
3©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Enter Event Loop
• Event loop needs to monitor subscription socket
• Typically using poll()/select()
while(1) {
set[0].fd = subsock;
set[0].events = POLLIN;
set[0].revents = 0;
poll(set, 1, -1); // Monitor one socket, wait forever
if (set[0].revents & POLLIN) {
cdb_read_subscription_socket(subsock, sub_points, &reslen);
// React on changes here…
// sub_points[] contains triggering subscription points,
// reslen how many
}
cdb_sync_subscription_socket(subsock, CDB_DONE_PRIORITY);
}
4©2015 Tail-f Systems all rights reservedFebruary 13, 2015
React to Configuration Changes
• Triggered subscription means something in scope changed, but will not tell us
what (nor to what value)
• To find out more, read all or start a diff walk
/ dhcp/
aaa/
voip/
defaultLe…
maxLeas…
SubNets/ subNet/
mask
range
lowAddr
highAddr
logFacility
net
?
?
5©2015 Tail-f Systems all rights reservedFebruary 13, 2015
React to Configuration Changes
Left extreme:
On any change, read all
configuration
• Linux daemon style
• Simple to program
• Simple to test
• Maximum code reuse
• Robust
Right extreme:
On any change, look at
every changed element
• NET-SNMP agent style
• In some cases very much
more efficient
6©2015 Tail-f Systems all rights reservedFebruary 13, 2015
React to Configuration Changes
Left extreme:
void startup() {
init_obj_A();
init_obj_B();
init_obj_C();
}
void handle_change() {
if(trigger_A) init_obj_A();
if(trigger_B) init_obj_B();
if(trigger_C) init_obj_C();
}
Right extreme:
void startup() {
init_obj_A();
init_obj_B();
init_obj_C();
}
void handle_change() {
cdb_diff_iterate(…iterator…);
}
void iterator(…keypath…) {
if(keypath is field /dhcp/logFacility)
...
if(keypath is field /…) …
7©2015 Tail-f Systems all rights reservedFebruary 13, 2015
React to Configuration Changes
No need to be extreme
Use balanced approach
Walk the diff when it makes sense, but not down to
individual leaf elements
Use multiple subscription points
• Simple to program with high degree of reuse
• Simple to test
• Robust
• Efficient
8©2015 Tail-f Systems all rights reservedFebruary 13, 2015
React to Configuration Changes
void startup() {
init_obj_A();
n = cdb_num_instances(“/B”);
for(i=0; i<n; i++)
init_obj_B(i);
init_obj_C();
}
void handle_change() {
if(trigger_A) init_obj_A();
if(trigger_B)
cdb_diff_iterate(…iterator_B…)
if(trigger_C) init_obj_C();
}
void iterator_B(…keypath…) {
table_row = extract_row(keypath);
init_obj_B(table_row);
return ITER_CONTINUE;
}
9©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Walking the Diff in a Balanced Way
Find the right level of granularity for your subscriptions and diff walks
/ dhcp/
aaa/
voip/
defaultLe…
maxLeas…
SubNets/ subNet/
mask
range
lowAddr
highAddr
logFacility
net
10©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Walking the Diff in a Balanced Way
Event loop with balanced approach
while(1) {
set[0].fd = subsock;
set[0].events = POLLIN;
set[0].revents = 0;
poll(set, 1, -1); // Monitor one socket, wait forever
if (set[0].revents & POLLIN) {
cdb_read_subscription_socket(subsock, sub_points, &reslen);
for(i=0; i<reslen; i++) {
if(…) cdb_diff_iterate(subsock, sub_points[i], iter, ITER_WANT_PREV, 0);
else if(…) init_A();
}
}
cdb_sync_subscription_socket(subsock, CDB_DONE_PRIORITY);
}
11©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Walking the Diff in a Balanced Way
An iterator function might look like this
static enum cdb_iter_ret iter(confd_hkeypath_t *kp, enum cdb_iter_op op,
confd_value_t *oldv, confd_value_t *newv, void *state)
{
switch (op) {
case MOP_CREATED: {
confd_value_t *ctag = &kp->v[1][0];
switch (CONFD_GET_XMLTAG(ctag)) {
case root_RFHead: { // an rfhead was created
// keypath is /root/NodeB/RFHead{$key}
// 3 2 1 0
confd_value_t *hkey = &kp->v[0][0];
read_head(cdbsock, hkey);
return ITER_CONTINUE;
12©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Walking the Diff in a Balanced Way
• Each item seen by the iterator function is one of
• MOP_CREATED – container or leaf created
• MOP_DELETED – container or leaf deleted
• MOP_MODIFIED – container where a child element has been
created/deleted/set
• MOP_VALUE_SET – leaf that has been set
• MOP_MOVED_AFTER – list element that was moved
• Each time iterator function returns
• ITER_RECURSE – examine changes to child elements
• ITER_CONTINUE – skip changes to child elements
• ITER_UP – skip changes to child and sibling elements
• ITER_SUSPEND – suspend the iteration temporarily
• ITER_STOP – stop iteration now
13©2015 Tail-f Systems all rights reservedFebruary 13, 2015
int main(…) {
cdb_subscribe(subsock, 3, root__ns,
&headpoint,"/root/NodeB/RFHead”);
…
if (set[0].revents & POLLIN) {
cdb_diff_iterate(…, iter, …);
}
}
static enum cdb_iter_ret iter(…) {
…
switch (op) {
case MOP_CREATED: {
fprintf(stderr, "Create: %sn",…);
…
return ITER_CONTINUE;
Diff Walk Example
container root {
container NodeB {
list RFHead {
key dn;
leaf dn { type int64; }
leaf SECTORID_ID {
type string; default "N/A";
}
list Child {
key cdn;
leaf cdn { type int64; }
leaf childAttr {
type string; default "N/A";
}
}
}
}
}
14©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Create Object with Attribute
% set root NodeB RFHead 2 SECTOR_ID 2
% commit
Create: /root/NodeB/RFHead{2}
ITER_CONTINUE
15©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Modify Attribute of Object
% set root NodeB RFHead 2 SECTOR_ID 5
% commit
Modified /root/NodeB/RFHead{2}
ITER_RECURSE
Value Set: /root/NodeB/RFHead{2}/SECTORID_ID --> (5)
ITER_CONTINUE
16©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Create Object with Child Object
% set root NodeB RFHead 3 Child 1 childAttr 1
% commit
Create: /root/NodeB/RFHead{3}
ITER_CONTINUE
17©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Create additional Child Object
% set root NodeB RFHead 3 Child 2 childAttr 2
% set root NodeB RFHead 4 Child 2 childAttr 2
% commit
Modified /root/NodeB/RFHead{3}
ITER_RECURSE
Create: /root/NodeB/RFHead{3}/Child{2}
ITER_CONTINUE
Create: /root/NodeB/RFHead{4}
ITER_CONTINUE
18©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Set Attribute of Child Object
% set root NodeB RFHead 3 Child 2 childAttr 32
% commit
Modified /root/NodeB/RFHead{3}
ITER_RECURSE
Modified /root/NodeB/RFHead{3}/Child{2}
ITER_RECURSE
Value Set: /root/NodeB/RFHead{3}/Child{2}/childAttr --> (32)
ITER_CONTINUE
19©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Delete Child Object
% delete root NodeB RFHead 3 Child 1
% commit
Modified /root/NodeB/RFHead{3}
ITER_RECURSE
Delete: /root/NodeB/RFHead{3}/Child{1}
ITER_CONTINUE
20©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Delete Everything
% delete root
% commit
Delete: /root/NodeB/RFHead{2}
ITER_CONTINUE
Delete: /root/NodeB/RFHead{3}
ITER_CONTINUE
21©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Hashed Key Path (hkeypath)
• To make it easy to program (not necessarily learn)
• To make it efficient
• Encoded as two dimensional array
/root/NodeB/RFHead{1} would be encoded
• kp[0][0] contains ‘1’
• kp[1][0] contains ‘RFHead’
[0][] [1][] [2][] [3][] [4][]
[][0] INT32
‘1’
XMLTAG ‘RFHead’ XMLTAG
‘NodeB’
XMLTAG
‘root’
NOEXISTS
[][1] NOEXISTS NOEXISTS NOEXISTS NOEXISTS NOEXISTS
22©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Hashed Key Path (hkeypath)
• The second index is for multiple keys
/routes/route{12.60.0.0 16}/enabled would be encoded
• kp[1][0] contains ’12.60.0.0’
• kp[1][1] contains ‘16’
• There may be up to 8 keys in any table
• I.e. second index ranges from 0 up to possibly 7
[0][] [1][] [2][] [3][] [4][]
[][0
]
XMLTAG
‘enabled’
IPV4
‘12.60.0.0’
XMLTAG
‘route’
XMLTAG
‘routes’
NOEXISTS
[][1
]
NOEXISTS INT8
’16’
NOEXISTS NOEXISTS NOEXISTS
23©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Hashed Key Path (hkeypath)
• Sequence of XMLTAG hash values
• An XMLTAG is encoded as a 31-bit integer
• Not as strings: variable length, inefficient with string compare
• Hash function ensures same string always gets same value
• Collisions are rare (we have never seen one to date)
• Use idValue attribute in data model in case of collision
• This allows efficient and easy switch-case statements
switch (CONFD_GET_XMLTAG(ctag)) {
case root_RFHead: { // an rfhead was created
• Header file contains all the hash-constants
• Header file generated from data model using confdc
24©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Ensuring Changes happen in Order
• Consider transaction A
• Add interface eth5
Add route 55.66.0.0/18 over interface eth5
• Transactions are all-at-once, there is no internal ordering
• Transaction A is therefore equivalent to
• Add route 55.66.0.0/24 over interface eth5
Add interface eth5
25©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Ensuring Changes happen in Order
• Consider transaction A
• Add interface eth5
Add route 55.66.0.0/18 over interface eth5
• Still, in our code, the interface subsystem must be informed of this change before the
routing subsystem
• The routing subsystem will call the interface subsystem referencing eth5
• This dependency information is encoded in
cdb_subscribe(subsock, 20, dhcpd__ns, &spoint, ”/interfaces");
cdb_subscribe(subsock, 30, dhcpd__ns, &spoint, ”/routes");
cdb_subscribe_done(subsock);
26©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Ensuring Changes happen in Order
• Consider then transaction B
• Delete interface eth5
Delete route 55.66.0.0/24 over interface eth5
• In this case the ordering must be reversed
• Again, the routing subsystem will call the interface subsystem and reference eth5
• This is handled by adding more subscription points
// This subscription handles additions and modification of interfaces
cdb_subscribe(subsock, 20, dhcpd__ns, &spoint1, ”/interfaces");
cdb_subscribe(subsock, 30, dhcpd__ns, &spoint2, ”/routes");
// This subscription handles deletes of interfaces
cdb_subscribe(subsock, 40, dhcpd__ns, &spoint3, ”/interfaces");
cdb_subscribe_done(subsock);
27©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Ensuring Changes happen in Order
Event loop with balanced approach
while(1) {
set[0].fd = subsock;
set[0].events = POLLIN;
set[0].revents = 0;
poll(set, 1, -1); // Monitor one socket, wait forever
if (set[0].revents & POLLIN) {
cdb_read_subscription_socket(subsock, sub_points, &reslen);
for(i=0; i<reslen; i++) {
if(…) cdb_diff_iterate(subsock, sub_points[i], iter, ITER_WANT_PREV, 0);
else if(…) init_A();
}
}
cdb_sync_subscription_socket(subsock, CDB_DONE_PRIORITY);
}
28©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Application Initialization / Start Order
• Read, Subscribe
• Protect using read session or operators locked out
• Potentially more efficient than trigger method
• Subscribe, Each application triggers its own subscriptions
• Must be able to handle all configuration changes anyway
• Subscribe, Startup process triggers all subscriptions
• Good at system start when all processes start at the same time
• Subscribe, System process triggers restarting app subscriptions
• Can handle all scenarios
29©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Yang
Validation
Application
Validation
Prepare
Phase
Notify
Applications
Commit
Phase
Point of No Return
After the Point of No Return the transaction cannot be aborted.
• Make sure you validate properly before Point of No Return
• If an application fails after this point, treat it the same regardless of it happening
2 ms/minutes/weeks after commit
Operator
types/clicks
commit
Operator gets OK
and next prompt
Point of
No Return
30©2015 Tail-f Systems all rights reservedFebruary 13, 2015
Yang
Validation
Application
Validation
Prepare
Phase
Notify
Applications
Commit
Phase
Validators and Two Phase Subscribers
Resource reservation can be handled by a
Two Phase Subscriber
• Called during Prepare Phase
• Will get an aborted
callback if transaction
aborted
• Uses cdb_subscribe() mechanism
with an extra flag
• Don’t activate, just check in prepare
MO
Changes that
might happen
Changes that did
happen
31©2015 Tail-f Systems all rights reservedFebruary 13, 2015
ConfD CDB Subscription Handling Examples
• examples.confd/intro/1-2-3-start-query-model
• examples.confd/cdb_subscription/iter
• examples.confd/cdb_subscription/trigger
• examples.confd/cdb_subscription/twophase
32©2015 Tail-f Systems all rights reservedFebruary 13, 2015

Module 10: CDB Subscribers

  • 1.
    1©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 CDB Subscribers
  • 2.
    2©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Triggers when anything in scope changes Subscribe to Configuration Changes subsock = socket(PF_INET, SOCK_STREAM, 0); cdb_connect(subsock, CDB_SUBSCRIPTION_SOCKET, &confd, size); cdb_subscribe(subsock, 3, dhcpd__ns, &spoint, "/dhcp"); cdb_subscribe_done(subsock); / dhcp/ aaa/ voip/ defaultLe… maxLeas… SubNets/ subNet/ mask range lowAddr highAddr logFacility net Managed Objects typically have several subscription points
  • 3.
    3©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Enter Event Loop • Event loop needs to monitor subscription socket • Typically using poll()/select() while(1) { set[0].fd = subsock; set[0].events = POLLIN; set[0].revents = 0; poll(set, 1, -1); // Monitor one socket, wait forever if (set[0].revents & POLLIN) { cdb_read_subscription_socket(subsock, sub_points, &reslen); // React on changes here… // sub_points[] contains triggering subscription points, // reslen how many } cdb_sync_subscription_socket(subsock, CDB_DONE_PRIORITY); }
  • 4.
    4©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 React to Configuration Changes • Triggered subscription means something in scope changed, but will not tell us what (nor to what value) • To find out more, read all or start a diff walk / dhcp/ aaa/ voip/ defaultLe… maxLeas… SubNets/ subNet/ mask range lowAddr highAddr logFacility net ? ?
  • 5.
    5©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 React to Configuration Changes Left extreme: On any change, read all configuration • Linux daemon style • Simple to program • Simple to test • Maximum code reuse • Robust Right extreme: On any change, look at every changed element • NET-SNMP agent style • In some cases very much more efficient
  • 6.
    6©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 React to Configuration Changes Left extreme: void startup() { init_obj_A(); init_obj_B(); init_obj_C(); } void handle_change() { if(trigger_A) init_obj_A(); if(trigger_B) init_obj_B(); if(trigger_C) init_obj_C(); } Right extreme: void startup() { init_obj_A(); init_obj_B(); init_obj_C(); } void handle_change() { cdb_diff_iterate(…iterator…); } void iterator(…keypath…) { if(keypath is field /dhcp/logFacility) ... if(keypath is field /…) …
  • 7.
    7©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 React to Configuration Changes No need to be extreme Use balanced approach Walk the diff when it makes sense, but not down to individual leaf elements Use multiple subscription points • Simple to program with high degree of reuse • Simple to test • Robust • Efficient
  • 8.
    8©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 React to Configuration Changes void startup() { init_obj_A(); n = cdb_num_instances(“/B”); for(i=0; i<n; i++) init_obj_B(i); init_obj_C(); } void handle_change() { if(trigger_A) init_obj_A(); if(trigger_B) cdb_diff_iterate(…iterator_B…) if(trigger_C) init_obj_C(); } void iterator_B(…keypath…) { table_row = extract_row(keypath); init_obj_B(table_row); return ITER_CONTINUE; }
  • 9.
    9©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Walking the Diff in a Balanced Way Find the right level of granularity for your subscriptions and diff walks / dhcp/ aaa/ voip/ defaultLe… maxLeas… SubNets/ subNet/ mask range lowAddr highAddr logFacility net
  • 10.
    10©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Walking the Diff in a Balanced Way Event loop with balanced approach while(1) { set[0].fd = subsock; set[0].events = POLLIN; set[0].revents = 0; poll(set, 1, -1); // Monitor one socket, wait forever if (set[0].revents & POLLIN) { cdb_read_subscription_socket(subsock, sub_points, &reslen); for(i=0; i<reslen; i++) { if(…) cdb_diff_iterate(subsock, sub_points[i], iter, ITER_WANT_PREV, 0); else if(…) init_A(); } } cdb_sync_subscription_socket(subsock, CDB_DONE_PRIORITY); }
  • 11.
    11©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Walking the Diff in a Balanced Way An iterator function might look like this static enum cdb_iter_ret iter(confd_hkeypath_t *kp, enum cdb_iter_op op, confd_value_t *oldv, confd_value_t *newv, void *state) { switch (op) { case MOP_CREATED: { confd_value_t *ctag = &kp->v[1][0]; switch (CONFD_GET_XMLTAG(ctag)) { case root_RFHead: { // an rfhead was created // keypath is /root/NodeB/RFHead{$key} // 3 2 1 0 confd_value_t *hkey = &kp->v[0][0]; read_head(cdbsock, hkey); return ITER_CONTINUE;
  • 12.
    12©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Walking the Diff in a Balanced Way • Each item seen by the iterator function is one of • MOP_CREATED – container or leaf created • MOP_DELETED – container or leaf deleted • MOP_MODIFIED – container where a child element has been created/deleted/set • MOP_VALUE_SET – leaf that has been set • MOP_MOVED_AFTER – list element that was moved • Each time iterator function returns • ITER_RECURSE – examine changes to child elements • ITER_CONTINUE – skip changes to child elements • ITER_UP – skip changes to child and sibling elements • ITER_SUSPEND – suspend the iteration temporarily • ITER_STOP – stop iteration now
  • 13.
    13©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 int main(…) { cdb_subscribe(subsock, 3, root__ns, &headpoint,"/root/NodeB/RFHead”); … if (set[0].revents & POLLIN) { cdb_diff_iterate(…, iter, …); } } static enum cdb_iter_ret iter(…) { … switch (op) { case MOP_CREATED: { fprintf(stderr, "Create: %sn",…); … return ITER_CONTINUE; Diff Walk Example container root { container NodeB { list RFHead { key dn; leaf dn { type int64; } leaf SECTORID_ID { type string; default "N/A"; } list Child { key cdn; leaf cdn { type int64; } leaf childAttr { type string; default "N/A"; } } } } }
  • 14.
    14©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Create Object with Attribute % set root NodeB RFHead 2 SECTOR_ID 2 % commit Create: /root/NodeB/RFHead{2} ITER_CONTINUE
  • 15.
    15©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Modify Attribute of Object % set root NodeB RFHead 2 SECTOR_ID 5 % commit Modified /root/NodeB/RFHead{2} ITER_RECURSE Value Set: /root/NodeB/RFHead{2}/SECTORID_ID --> (5) ITER_CONTINUE
  • 16.
    16©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Create Object with Child Object % set root NodeB RFHead 3 Child 1 childAttr 1 % commit Create: /root/NodeB/RFHead{3} ITER_CONTINUE
  • 17.
    17©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Create additional Child Object % set root NodeB RFHead 3 Child 2 childAttr 2 % set root NodeB RFHead 4 Child 2 childAttr 2 % commit Modified /root/NodeB/RFHead{3} ITER_RECURSE Create: /root/NodeB/RFHead{3}/Child{2} ITER_CONTINUE Create: /root/NodeB/RFHead{4} ITER_CONTINUE
  • 18.
    18©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Set Attribute of Child Object % set root NodeB RFHead 3 Child 2 childAttr 32 % commit Modified /root/NodeB/RFHead{3} ITER_RECURSE Modified /root/NodeB/RFHead{3}/Child{2} ITER_RECURSE Value Set: /root/NodeB/RFHead{3}/Child{2}/childAttr --> (32) ITER_CONTINUE
  • 19.
    19©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Delete Child Object % delete root NodeB RFHead 3 Child 1 % commit Modified /root/NodeB/RFHead{3} ITER_RECURSE Delete: /root/NodeB/RFHead{3}/Child{1} ITER_CONTINUE
  • 20.
    20©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Delete Everything % delete root % commit Delete: /root/NodeB/RFHead{2} ITER_CONTINUE Delete: /root/NodeB/RFHead{3} ITER_CONTINUE
  • 21.
    21©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Hashed Key Path (hkeypath) • To make it easy to program (not necessarily learn) • To make it efficient • Encoded as two dimensional array /root/NodeB/RFHead{1} would be encoded • kp[0][0] contains ‘1’ • kp[1][0] contains ‘RFHead’ [0][] [1][] [2][] [3][] [4][] [][0] INT32 ‘1’ XMLTAG ‘RFHead’ XMLTAG ‘NodeB’ XMLTAG ‘root’ NOEXISTS [][1] NOEXISTS NOEXISTS NOEXISTS NOEXISTS NOEXISTS
  • 22.
    22©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Hashed Key Path (hkeypath) • The second index is for multiple keys /routes/route{12.60.0.0 16}/enabled would be encoded • kp[1][0] contains ’12.60.0.0’ • kp[1][1] contains ‘16’ • There may be up to 8 keys in any table • I.e. second index ranges from 0 up to possibly 7 [0][] [1][] [2][] [3][] [4][] [][0 ] XMLTAG ‘enabled’ IPV4 ‘12.60.0.0’ XMLTAG ‘route’ XMLTAG ‘routes’ NOEXISTS [][1 ] NOEXISTS INT8 ’16’ NOEXISTS NOEXISTS NOEXISTS
  • 23.
    23©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Hashed Key Path (hkeypath) • Sequence of XMLTAG hash values • An XMLTAG is encoded as a 31-bit integer • Not as strings: variable length, inefficient with string compare • Hash function ensures same string always gets same value • Collisions are rare (we have never seen one to date) • Use idValue attribute in data model in case of collision • This allows efficient and easy switch-case statements switch (CONFD_GET_XMLTAG(ctag)) { case root_RFHead: { // an rfhead was created • Header file contains all the hash-constants • Header file generated from data model using confdc
  • 24.
    24©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Ensuring Changes happen in Order • Consider transaction A • Add interface eth5 Add route 55.66.0.0/18 over interface eth5 • Transactions are all-at-once, there is no internal ordering • Transaction A is therefore equivalent to • Add route 55.66.0.0/24 over interface eth5 Add interface eth5
  • 25.
    25©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Ensuring Changes happen in Order • Consider transaction A • Add interface eth5 Add route 55.66.0.0/18 over interface eth5 • Still, in our code, the interface subsystem must be informed of this change before the routing subsystem • The routing subsystem will call the interface subsystem referencing eth5 • This dependency information is encoded in cdb_subscribe(subsock, 20, dhcpd__ns, &spoint, ”/interfaces"); cdb_subscribe(subsock, 30, dhcpd__ns, &spoint, ”/routes"); cdb_subscribe_done(subsock);
  • 26.
    26©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Ensuring Changes happen in Order • Consider then transaction B • Delete interface eth5 Delete route 55.66.0.0/24 over interface eth5 • In this case the ordering must be reversed • Again, the routing subsystem will call the interface subsystem and reference eth5 • This is handled by adding more subscription points // This subscription handles additions and modification of interfaces cdb_subscribe(subsock, 20, dhcpd__ns, &spoint1, ”/interfaces"); cdb_subscribe(subsock, 30, dhcpd__ns, &spoint2, ”/routes"); // This subscription handles deletes of interfaces cdb_subscribe(subsock, 40, dhcpd__ns, &spoint3, ”/interfaces"); cdb_subscribe_done(subsock);
  • 27.
    27©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Ensuring Changes happen in Order Event loop with balanced approach while(1) { set[0].fd = subsock; set[0].events = POLLIN; set[0].revents = 0; poll(set, 1, -1); // Monitor one socket, wait forever if (set[0].revents & POLLIN) { cdb_read_subscription_socket(subsock, sub_points, &reslen); for(i=0; i<reslen; i++) { if(…) cdb_diff_iterate(subsock, sub_points[i], iter, ITER_WANT_PREV, 0); else if(…) init_A(); } } cdb_sync_subscription_socket(subsock, CDB_DONE_PRIORITY); }
  • 28.
    28©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Application Initialization / Start Order • Read, Subscribe • Protect using read session or operators locked out • Potentially more efficient than trigger method • Subscribe, Each application triggers its own subscriptions • Must be able to handle all configuration changes anyway • Subscribe, Startup process triggers all subscriptions • Good at system start when all processes start at the same time • Subscribe, System process triggers restarting app subscriptions • Can handle all scenarios
  • 29.
    29©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Yang Validation Application Validation Prepare Phase Notify Applications Commit Phase Point of No Return After the Point of No Return the transaction cannot be aborted. • Make sure you validate properly before Point of No Return • If an application fails after this point, treat it the same regardless of it happening 2 ms/minutes/weeks after commit Operator types/clicks commit Operator gets OK and next prompt Point of No Return
  • 30.
    30©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 Yang Validation Application Validation Prepare Phase Notify Applications Commit Phase Validators and Two Phase Subscribers Resource reservation can be handled by a Two Phase Subscriber • Called during Prepare Phase • Will get an aborted callback if transaction aborted • Uses cdb_subscribe() mechanism with an extra flag • Don’t activate, just check in prepare MO Changes that might happen Changes that did happen
  • 31.
    31©2015 Tail-f Systemsall rights reservedFebruary 13, 2015 ConfD CDB Subscription Handling Examples • examples.confd/intro/1-2-3-start-query-model • examples.confd/cdb_subscription/iter • examples.confd/cdb_subscription/trigger • examples.confd/cdb_subscription/twophase
  • 32.
    32©2015 Tail-f Systemsall rights reservedFebruary 13, 2015

Editor's Notes

  • #33 The closing slide may be used with no text or with a short phrase and company web address.