From f5db3711b28db4e364ac01be8b124dd24d573782 Mon Sep 17 00:00:00 2001 From: Ole Troan Date: Wed, 20 May 2020 15:47:06 +0200 Subject: api: add new stream message convention Instead of having to wrap dump/detail calls in control ping, send details messages in between a normal reply / request pair. As expressed in the below service statement. Example: service { rpc map_domains_gets returns map_domains_get_reply stream map_domain_details; }; define map_domains_get { u32 client_index; u32 context; u32 cursor; }; define map_domains_get_reply { u32 context; i32 retval; u32 cursor; }; To avoid blocking the main thread for too long, the replies are now sent in client message queue size chunks. The reply message returns VNET_API_ERROR_EAGAIN when there is more to read. The API handler must also include a "cursor" that is used to the next call to the get function. API handler example: REPLY_AND_DETAILS_MACRO (VL_API_MAP_DOMAINS_GET_REPLY, mm->domains, ({ send_domain_details (cursor, rp, mp->context); })); The macro starts from cursor and iterates through the pool until vl_api_process_may_suspend() returns true or the iteration reaches the end of the list. Client Example: cursor = 0 d = [] while True: rv, details = map_domains_get(cursor=cursor) d += details if rv.retval == 0 or rv.retval != -165: break cursor = rv.cursor or the convenience iterator: for x in vpp.details_iter(vpp.api.map_domains_get): pass or list(details_iter(map_domains_get)) Change-Id: Iad9f6b41b0ef886adb584c97708dd91cf552749e Type: feature Signed-off-by: Ole Troan --- src/plugins/map/map_api.c | 87 +++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 29 deletions(-) (limited to 'src/plugins/map/map_api.c') diff --git a/src/plugins/map/map_api.c b/src/plugins/map/map_api.c index 7327732c6a7..13f05526afa 100644 --- a/src/plugins/map/map_api.c +++ b/src/plugins/map/map_api.c @@ -86,14 +86,48 @@ vl_api_map_add_del_rule_t_handler (vl_api_map_add_del_rule_t * mp) } static void -vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp) +send_domain_details (u32 map_domain_index, vl_api_registration_t * rp, + u32 context) { + map_main_t *mm = &map_main; vl_api_map_domain_details_t *rmp; + map_domain_t *d = pool_elt_at_index (mm->domains, map_domain_index); + + /* Make sure every field is initiated (or don't skip the clib_memset()) */ + map_domain_extra_t *de = + vec_elt_at_index (mm->domain_extras, map_domain_index); + int tag_len = clib_min (ARRAY_LEN (rmp->tag), vec_len (de->tag) + 1); + + /* *INDENT-OFF* */ + REPLY_MACRO_DETAILS4(VL_API_MAP_DOMAIN_DETAILS, rp, context, + ({ + rmp->domain_index = htonl (map_domain_index); + clib_memcpy (&rmp->ip6_prefix.address, &d->ip6_prefix, + sizeof (rmp->ip6_prefix.address)); + clib_memcpy (&rmp->ip4_prefix.address, &d->ip4_prefix, + sizeof (rmp->ip4_prefix.address)); + clib_memcpy (&rmp->ip6_src.address, &d->ip6_src, + sizeof (rmp->ip6_src.address)); + rmp->ip6_prefix.len = d->ip6_prefix_len; + rmp->ip4_prefix.len = d->ip4_prefix_len; + rmp->ip6_src.len = d->ip6_src_len; + rmp->ea_bits_len = d->ea_bits_len; + rmp->psid_offset = d->psid_offset; + rmp->psid_length = d->psid_length; + rmp->flags = d->flags; + rmp->mtu = htons (d->mtu); + memcpy (rmp->tag, de->tag, tag_len - 1); + rmp->tag[tag_len - 1] = '\0'; + })); + /* *INDENT-ON* */ +} + +static void +vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp) +{ map_main_t *mm = &map_main; - map_domain_t *d; - map_domain_extra_t *de; + int i; vl_api_registration_t *reg; - u32 map_domain_index; if (pool_elts (mm->domains) == 0) return; @@ -103,33 +137,28 @@ vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp) return; /* *INDENT-OFF* */ - pool_foreach(d, mm->domains, + pool_foreach_index(i, mm->domains, ({ - map_domain_index = d - mm->domains; - de = vec_elt_at_index(mm->domain_extras, map_domain_index); - int tag_len = clib_min(ARRAY_LEN(rmp->tag), vec_len(de->tag) + 1); - - /* Make sure every field is initiated (or don't skip the clib_memset()) */ - rmp = vl_msg_api_alloc (sizeof (*rmp) + tag_len); - - rmp->_vl_msg_id = htons(VL_API_MAP_DOMAIN_DETAILS + mm->msg_id_base); - rmp->context = mp->context; - rmp->domain_index = htonl(map_domain_index); - clib_memcpy(&rmp->ip6_prefix.address, &d->ip6_prefix, sizeof(rmp->ip6_prefix.address)); - clib_memcpy(&rmp->ip4_prefix.address, &d->ip4_prefix, sizeof(rmp->ip4_prefix.address)); - clib_memcpy(&rmp->ip6_src.address, &d->ip6_src, sizeof(rmp->ip6_src.address)); - rmp->ip6_prefix.len = d->ip6_prefix_len; - rmp->ip4_prefix.len = d->ip4_prefix_len; - rmp->ip6_src.len = d->ip6_src_len; - rmp->ea_bits_len = d->ea_bits_len; - rmp->psid_offset = d->psid_offset; - rmp->psid_length = d->psid_length; - rmp->flags = d->flags; - rmp->mtu = htons(d->mtu); - memcpy(rmp->tag, de->tag, tag_len-1); - rmp->tag[tag_len-1] = '\0'; + send_domain_details(i, reg, mp->context); + })); + /* *INDENT-ON* */ +} - vl_api_send_msg (reg, (u8 *) rmp); +static void +vl_api_map_domains_get_t_handler (vl_api_map_domains_get_t * mp) +{ + map_main_t *mm = &map_main; + vl_api_map_domains_get_reply_t *rmp; + + i32 rv = 0; + + if (pool_elts (mm->domains) == 0) + return; + + /* *INDENT-OFF* */ + REPLY_AND_DETAILS_MACRO (VL_API_MAP_DOMAINS_GET_REPLY, mm->domains, + ({ + send_domain_details (cursor, rp, mp->context); })); /* *INDENT-ON* */ } -- cgit 1.2.3-korg