I can’t recreate your issue as you have described it so far. I added a leaf of type binary to the examples.confd/intro/5-c_stats/arpe.yang YANG model
$ diff -u arpe.yang.orig arpe.yang
--- arpe.yang.orig 2020-04-02 11:46:05.000000000 +0200
+++ arpe.yang 2020-04-02 11:21:58.000000000 +0200
@@ -54,6 +54,12 @@
type boolean;
mandatory true;
}
+ leaf value {
+ type binary;
+ description
+ "TLV value.";
+ tailf:display-hint '1x:';
+ }
}
}
}
Then added a get_next_value() callback to examples.confd/intro/5-c_stats/arpstat.c
$ diff -u arpstat.c.orig arpstat.c
--- arpstat.c.orig 2020-04-02 11:41:51.000000000 +0200
+++ arpstat.c 2020-04-02 11:39:22.000000000 +0200
@@ -307,7 +307,62 @@
confd_data_reply_value(tctx, &v);
return CONFD_OK;
}
+static int navals;
+static int max_nobjs = 100; // Chunk size hardcoded here to simplify
+static int get_next_object_tag(struct confd_trans_ctx *tctx,
+ confd_hkeypath_t *keypath, long next)
+{
+ int i;
+ confd_tag_value_t *tv;
+ struct confd_tag_next_object *tobj;
+ struct arpdata *dp = tctx->t_opaque;
+ struct aentry *curr;
+
+ if (next == -1) { /* first call */
+ if (need_arp(dp)) {
+ if (run_arp(dp) == CONFD_ERR)
+ return CONFD_ERR;
+ }
+ curr = dp->arp_entries;
+ } else {
+ curr = (struct aentry *)next;
+ }
+ if (curr == NULL) {
+ confd_data_reply_next_key(tctx, NULL, -1, -1);
+ return CONFD_OK;
+ }
+
+ tobj = malloc(sizeof(struct confd_tag_next_object) * (max_nobjs + 1));
+ tv = (confd_tag_value_t *) malloc(sizeof(confd_tag_value_t) * max_nobjs * navals);
+
+ for (i = 0; curr != NULL && i < max_nobjs; curr = curr->next, i++) { /* Collect max_nobjs or as many as there is rows in the table / list entries */
+ tobj[i].tv = &tv[i * navals];
+
+ CONFD_SET_TAG_IPV4(&(tobj[i].tv[0]), arpe_ip, curr->ip4);
+ CONFD_SET_TAG_STR(&(tobj[i].tv[1]), arpe_ifname, curr->iface);
+ if (curr->hwaddr == NULL) {
+ CONFD_SET_TAG_NOEXISTS(&(tobj[i].tv[2]), arpe_hwaddr);
+ } else {
+ CONFD_SET_TAG_STR(&(tobj[i].tv[2]), arpe_hwaddr, curr->hwaddr);
+ }
+ CONFD_SET_TAG_BOOL(&(tobj[i].tv[3]), arpe_permanent, curr->perm);
+ CONFD_SET_TAG_BOOL(&(tobj[i].tv[4]), arpe_published, curr->pub);
+ unsigned const char *ucs = (unsigned const char *)"hello world";
+ CONFD_SET_TAG_BINARY(&(tobj[i].tv[5]), arpe_value, ucs, strlen((char *)ucs));
+ tobj[i].n = navals;
+ tobj[i].next = (long)curr->next;
+ }
+
+ if (curr == NULL) {
+ tobj[i++].tv = NULL;
+ }
+
+ confd_data_reply_next_object_tag_value_arrays(tctx, tobj, i, 0); /* Reply with an array of object arrays. I.e. the whole table / list */
+ free(tv);
+ free(tobj);
+ return CONFD_OK;
+}
int main(int argc, char *argv[])
@@ -316,6 +371,7 @@
int debuglevel = CONFD_TRACE;
struct confd_trans_cbs trans;
struct confd_data_cbs data;
+ struct confd_cs_node *object;
memset(&trans, 0, sizeof (struct confd_trans_cbs));
trans.init = s_init;
@@ -324,6 +380,7 @@
memset(&data, 0, sizeof (struct confd_data_cbs));
data.get_elem = get_elem;
data.get_next = get_next;
+ data.get_next_object = get_next_object_tag;
strcpy(data.callpoint, arpe__callpointid_arpe);
/* initialize confd library */
@@ -336,7 +393,8 @@
if (confd_load_schemas((struct sockaddr*)&addr,
sizeof (struct sockaddr_in)) != CONFD_OK)
confd_fatal("Failed to load schemas from confd\n");
-
+ object = confd_cs_node_cd(NULL, "/arpe:arpentries/arpe");
+ navals = confd_max_object_size(object);
if ((dctx = confd_init_daemon("arpe_daemon")) == NULL)
confd_fatal("Failed to initialize confdlib\n");
Quick demo:
$ pwd
/Users/tailf/confd-7.3.1/examples.confd/intro/5-c_stats
$ make clean all start
$ confd_cli -u admin -C
# show arpentries
IP IFNAME HWADDR PERMANENT PUBLISHED VALUE
----------------------------------------------------------------------------------------------------
172.20.10.1 en0 d2:c5:f3:60:cf:64 false false 68:65:6C:6C:6F:20:77:6F:72:6C:64
224.0.0.251 en0 1:0:5e:0:0:fb true false 68:65:6C:6C:6F:20:77:6F:72:6C:64
239.255.255.250 en0 1:0:5e:7f:ff:fa true false 68:65:6C:6C:6F:20:77:6F:72:6C:64
# exit
$ confd_load -o -Fp -p /arpentries
<config xmlns="http://tail-f.com/ns/config/1.0">
<arpentries xmlns="http://tail-f.com/ns/example/arpe">
<arpe>
<ip>172.20.10.1</ip>
<ifname>en0</ifname>
<hwaddr>d2:c5:f3:60:cf:64</hwaddr>
<permanent>false</permanent>
<published>false</published>
<value>aGVsbG8gd29ybGQ=</value>
</arpe>
<arpe>
<ip>224.0.0.251</ip>
<ifname>en0</ifname>
<hwaddr>1:0:5e:0:0:fb</hwaddr>
<permanent>true</permanent>
<published>false</published>
<value>aGVsbG8gd29ybGQ=</value>
</arpe>
<arpe>
<ip>239.255.255.250</ip>
<ifname>en0</ifname>
<hwaddr>1:0:5e:7f:ff:fa</hwaddr>
<permanent>true</permanent>
<published>false</published>
<value>aGVsbG8gd29ybGQ=</value>
</arpe>
</arpentries>
</config>
$ confd_load -o -Fc -p /arpentries
arpentries arpe 172.20.10.1 en0
hwaddr d2:c5:f3:60:cf:64
permanent false
published false
value 68:65:6C:6C:6F:20:77:6F:72:6C:64
!
arpentries arpe 224.0.0.251 en0
hwaddr 1:0:5e:0:0:fb
permanent true
published false
value 68:65:6C:6C:6F:20:77:6F:72:6C:64
!
arpentries arpe 239.255.255.250 en0
hwaddr 1:0:5e:7f:ff:fa
permanent true
published false
value 68:65:6C:6C:6F:20:77:6F:72:6C:64
!