)
)
else:
-
write(
' cJSON_AddStringToObject(o, "{n}", (char *)a->{n});\n'.format(
n=o.fieldname
write(" char *p = cJSON_GetStringValue(item);\n")
write(" size_t plen = strlen(p);\n")
write(
- " {msgvar} = cJSON_realloc({msgvar}, {msgsize} + plen, {msgsize});\n".format(
+ " {msgvar} = cJSON_realloc({msgvar}, {msgsize} + plen);\n".format(
msgvar=msgvar, msgsize=msgsize
)
)
cJSON *array = cJSON_GetObjectItem(o, "{n}");
int size = cJSON_GetArraySize(array);
{lfield} = size;
- {realloc} = cJSON_realloc({realloc}, {msgsize} + sizeof({t}) * size, {msgsize});
+ {realloc} = cJSON_realloc({realloc}, {msgsize} + sizeof({t}) * size);
{t} *d = (void *){realloc} + {msgsize};
{msgsize} += sizeof({t}) * size;
for (i = 0; i < size; i++) {{
write(
" {realloc} = cJSON_realloc({realloc}, {msgsize} + "
- "vec_len(s), {msgsize});\n".format(
+ "vec_len(s));\n".format(
msgvar=msgvar, msgsize=msgsize, realloc=realloc
)
)
write(
- " memcpy((void *){realloc} + {msgsize}, s, "
+ " clib_memcpy((void *){realloc} + {msgsize}, s, "
"vec_len(s));\n".format(realloc=realloc, msgsize=msgsize)
)
write(" {msgsize} += vec_len(s);\n".format(msgsize=msgsize))
#endif
#define VL_API_PACKED(x) x __attribute__ ((packed))
+
+/*
+ * Note: VL_API_MAX_ARRAY_SIZE is set to an arbitrarily large limit.
+ *
+ * However, any message with a ~2 billion element array is likely to break the
+ * api handling long before this limit causes array element endian issues.
+ *
+ * Applications should be written to create reasonable api messages.
+ */
+#define VL_API_MAX_ARRAY_SIZE 0x7fffffff
+
"""
BOTTOM_BOILERPLATE = """\
}
+def get_endian_string(o, fieldtype):
+ """Return proper endian string conversion function"""
+ return ENDIAN_STRINGS[fieldtype]
+
+
def endianfun_array(o):
"""Generate endian functions for arrays"""
forloop = """\
+ ASSERT((u32){length} <= (u32)VL_API_MAX_ARRAY_SIZE);
for (i = 0; i < {length}; i++) {{
a->{name}[i] = {format}(a->{name}[i]);
}}
forloop_format = """\
for (i = 0; i < {length}; i++) {{
- {type}_endian(&a->{name}[i]);
+ {type}_endian(&a->{name}[i], to_net);
}}
"""
output += " /* a->{n} = a->{n} (no-op) */\n".format(n=o.fieldname)
else:
lfield = "a->" + o.lengthfield if o.lengthfield else o.length
+ if o.lengthfield:
+ output += (
+ f" u32 count = to_net ? clib_host_to_net_u32(a->{o.lengthfield}) : "
+ f"a->{o.lengthfield};\n"
+ )
+ lfield = "count"
+ else:
+ lfield = o.length
+
if o.fieldtype in ENDIAN_STRINGS:
output += forloop.format(
- length=lfield, format=ENDIAN_STRINGS[o.fieldtype], name=o.fieldname
+ length=lfield,
+ format=get_endian_string(o, o.fieldtype),
+ name=o.fieldname,
)
else:
output += forloop_format.format(
return output
if o.fieldtype in ENDIAN_STRINGS:
output += " a->{name} = {format}(a->{name});\n".format(
- name=o.fieldname, format=ENDIAN_STRINGS[o.fieldtype]
+ name=o.fieldname, format=get_endian_string(o, o.fieldtype)
)
elif o.fieldtype.startswith("vl_api_"):
- output += " {type}_endian(&a->{name});\n".format(
+ output += " {type}_endian(&a->{name}, to_net);\n".format(
type=o.fieldtype, name=o.fieldname
)
else:
#define included_{module}_endianfun
#undef clib_net_to_host_uword
+#undef clib_host_to_net_uword
#ifdef LP64
#define clib_net_to_host_uword clib_net_to_host_u64
+#define clib_host_to_net_uword clib_host_to_net_u64
#else
#define clib_net_to_host_uword clib_net_to_host_u32
+#define clib_host_to_net_uword clib_host_to_net_u32
#endif
"""
output = output.format(module=modulename)
signature = """\
-static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a)
+static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a, bool to_net)
{{
int i __attribute__((unused));
"""
if t.__class__.__name__ == "Enum" or t.__class__.__name__ == "EnumFlag":
output += signature.format(name=t.name)
if t.enumtype in ENDIAN_STRINGS:
- output += " *a = {}(*a);\n".format(ENDIAN_STRINGS[t.enumtype])
+ output += " *a = {}(*a);\n".format(get_endian_string(t, t.enumtype))
else:
output += " /* a->{name} = a->{name} (no-op) */\n".format(
name=t.name
name=t.name
)
elif t.alias["type"] in FORMAT_STRINGS:
- output += " *a = {}(*a);\n".format(ENDIAN_STRINGS[t.alias["type"]])
+ output += " *a = {}(*a);\n".format(
+ get_endian_string(t, t.alias["type"])
+ )
else:
output += " /* Not Implemented yet {} */".format(t.name)
output += "}\n\n"
)
lf = m[0]
if lf.fieldtype in ENDIAN_STRINGS:
- output += f" + {ENDIAN_STRINGS[lf.fieldtype]}(a->{b.lengthfield}) * sizeof(a->{b.fieldname}[0])"
+ output += f" + {get_endian_string(b, lf.fieldtype)}(a->{b.lengthfield}) * sizeof(a->{b.fieldname}[0])"
elif lf.fieldtype == "u8":
output += (
f" + a->{b.lengthfield} * sizeof(a->{b.fieldname}[0])"
#include "{module}.api.h"
#undef vl_printfun
+#include "{module}.api_json.h"
"""
write(hdr.format(module=module))
- write("static u16\n")
- write("setup_message_id_table (void) {\n")
- write(" api_main_t *am = my_api_main;\n")
- write(" vl_msg_api_msg_config_t c;\n")
- write(
- ' u16 msg_id_base = vl_msg_api_get_msg_ids ("{}_{crc:08x}", '
- "VL_MSG_{m}_LAST);\n".format(module, crc=file_crc, m=module.upper())
- )
+ if len(defines) > 0:
+ write("static u16\n")
+ write("setup_message_id_table (void) {\n")
+ write(" api_main_t *am = my_api_main;\n")
+ write(" vl_msg_api_msg_config_t c;\n")
+ write(
+ ' u16 msg_id_base = vl_msg_api_get_msg_ids ("{}_{crc:08x}", '
+ "VL_MSG_{m}_LAST);\n".format(module, crc=file_crc, m=module.upper())
+ )
+ write(f" vec_add1(am->json_api_repr, (u8 *)json_api_repr_{module});\n")
for d in defines:
write(
except KeyError:
pass
- write(" return msg_id_base;\n")
- write("}\n")
+ try:
+ if s.stream:
+ d = define_hash[s.stream_message]
+ write(
+ " c = (vl_msg_api_msg_config_t) "
+ "{{.id = VL_API_{ID} + msg_id_base,\n"
+ ' .name = "{n}",\n'
+ " .handler = 0,\n"
+ " .endian = vl_api_{n}_t_endian,\n"
+ " .format_fn = vl_api_{n}_t_format,\n"
+ " .traced = 1,\n"
+ " .replay = 1,\n"
+ " .tojson = vl_api_{n}_t_tojson,\n"
+ " .fromjson = vl_api_{n}_t_fromjson,\n"
+ " .calc_size = vl_api_{n}_t_calc_size,\n"
+ " .is_autoendian = {auto}}};\n".format(
+ n=s.stream_message,
+ ID=s.stream_message.upper(),
+ auto=d.autoendian,
+ )
+ )
+ write(" vl_msg_api_config (&c);\n")
+ except KeyError:
+ pass
+ if len(defines) > 0:
+ write(" return msg_id_base;\n")
+ write("}\n")
severity = {
"error": "VL_COUNTER_SEVERITY_ERROR",
}}
mp->_vl_msg_id = vac_get_msg_index(VL_API_{N}_CRC);
- vl_api_{n}_t_endian(mp);
+ vl_api_{n}_t_endian(mp, 1);
vac_write((char *)mp, len);
cJSON_free(mp);
return 0;
}}
vl_api_{r}_t *rmp = (vl_api_{r}_t *)p;
- vl_api_{r}_t_endian(rmp);
+ vl_api_{r}_t_endian(rmp, 0);
return vl_api_{r}_t_tojson(rmp);
}}
return 0;
}}
mp->_vl_msg_id = msg_id;
- vl_api_{n}_t_endian(mp);
+ vl_api_{n}_t_endian(mp, 1);
vac_write((char *)mp, len);
cJSON_free(mp);
return 0;
}}
vl_api_{r}_t *rmp = (vl_api_{r}_t *)p;
- vl_api_{r}_t_endian(rmp);
+ vl_api_{r}_t_endian(rmp, 0);
cJSON_AddItemToArray(reply, vl_api_{r}_t_tojson(rmp));
}}
}}
}}
mp->_vl_msg_id = msg_id;
- vl_api_{n}_t_endian(mp);
+ vl_api_{n}_t_endian(mp, 1);
vac_write((char *)mp, len);
cJSON_free(mp);
u16 msg_id = ntohs(*((u16 *)p));
if (msg_id == reply_msg_id) {{
vl_api_{r}_t *rmp = (vl_api_{r}_t *)p;
- vl_api_{r}_t_endian(rmp);
+ vl_api_{r}_t_endian(rmp, 0);
cJSON_AddItemToArray(reply, vl_api_{r}_t_tojson(rmp));
break;
}}
if (msg_id == details_msg_id) {{
vl_api_{d}_t *rmp = (vl_api_{d}_t *)p;
- vl_api_{d}_t_endian(rmp);
+ vl_api_{d}_t_endian(rmp, 0);
cJSON_AddItemToArray(reply, vl_api_{d}_t_tojson(rmp));
}}
}}