net: lwm2m: Add LwM2M 1.1 discovery support

LwM2M adds Resource Instance reporting in Discovery response, along with
attributes assinged at the Resource Instance level.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2022-02-02 15:39:59 +01:00 committed by Marti Bolivar
commit 3e861c04e9
3 changed files with 132 additions and 8 deletions

View file

@ -3399,6 +3399,54 @@ move_forward:
return ret; return ret;
} }
static int lwm2m_discover_add_res(struct lwm2m_message *msg,
struct lwm2m_engine_obj_inst *obj_inst,
struct lwm2m_engine_res *res)
{
int ret;
struct lwm2m_obj_path path = {
.obj_id = obj_inst->obj->obj_id,
.obj_inst_id = obj_inst->obj_inst_id,
.res_id = res->res_id,
.level = LWM2M_PATH_LEVEL_RESOURCE,
};
ret = engine_put_corelink(&msg->out, &path);
if (ret < 0) {
return ret;
}
/* Report resource instances, if applicable. */
if (IS_ENABLED(CONFIG_LWM2M_VERSION_1_1) &&
msg->path.level == LWM2M_PATH_LEVEL_RESOURCE &&
res->multi_res_inst) {
for (int i = 0; i < res->res_inst_count; i++) {
struct lwm2m_engine_res_inst *res_inst =
&res->res_instances[i];
if (res_inst->res_inst_id ==
RES_INSTANCE_NOT_CREATED) {
continue;
}
path = (struct lwm2m_obj_path){
.obj_id = obj_inst->obj->obj_id,
.obj_inst_id = obj_inst->obj_inst_id,
.res_id = res->res_id,
.res_inst_id = res_inst->res_inst_id,
.level = LWM2M_PATH_LEVEL_RESOURCE_INST,
};
ret = engine_put_corelink(&msg->out, &path);
if (ret < 0) {
return ret;
}
}
}
return 0;
}
int lwm2m_discover_handler(struct lwm2m_message *msg, bool is_bootstrap) int lwm2m_discover_handler(struct lwm2m_message *msg, bool is_bootstrap)
{ {
struct lwm2m_engine_obj *obj; struct lwm2m_engine_obj *obj;
@ -3515,14 +3563,8 @@ int lwm2m_discover_handler(struct lwm2m_message *msg, bool is_bootstrap)
continue; continue;
} }
struct lwm2m_obj_path path = { ret = lwm2m_discover_add_res(msg, obj_inst,
.obj_id = obj_inst->obj->obj_id, &obj_inst->resources[i]);
.obj_inst_id = obj_inst->obj_inst_id,
.res_id = obj_inst->resources[i].res_id,
.level = LWM2M_PATH_LEVEL_RESOURCE,
};
ret = engine_put_corelink(&msg->out, &path);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -3646,6 +3688,24 @@ struct lwm2m_engine_res *lwm2m_engine_get_res(
return res; return res;
} }
struct lwm2m_engine_res_inst *lwm2m_engine_get_res_inst(
const struct lwm2m_obj_path *path)
{
struct lwm2m_engine_res_inst *res_inst = NULL;
int ret;
if (path->level != LWM2M_PATH_LEVEL_RESOURCE_INST) {
return NULL;
}
ret = path_to_objs(path, NULL, NULL, NULL, &res_inst);
if (ret < 0) {
return NULL;
}
return res_inst;
}
bool lwm2m_engine_shall_report_obj_version(const struct lwm2m_engine_obj *obj) bool lwm2m_engine_shall_report_obj_version(const struct lwm2m_engine_obj *obj)
{ {
if (obj->is_core) { if (obj->is_core) {

View file

@ -87,6 +87,8 @@ struct lwm2m_engine_obj_inst *lwm2m_engine_get_obj_inst(
const struct lwm2m_obj_path *path); const struct lwm2m_obj_path *path);
struct lwm2m_engine_res *lwm2m_engine_get_res( struct lwm2m_engine_res *lwm2m_engine_get_res(
const struct lwm2m_obj_path *path); const struct lwm2m_obj_path *path);
struct lwm2m_engine_res_inst *lwm2m_engine_get_res_inst(
const struct lwm2m_obj_path *path);
bool lwm2m_engine_shall_report_obj_version(const struct lwm2m_engine_obj *obj); bool lwm2m_engine_shall_report_obj_version(const struct lwm2m_engine_obj *obj);

View file

@ -436,6 +436,55 @@ static int put_res_corelink(struct lwm2m_output_context *out,
return len; return len;
} }
static int put_res_inst_corelink(struct lwm2m_output_context *out,
const struct lwm2m_obj_path *path,
struct link_format_out_formatter_data *fd)
{
char obj_buf[CORELINK_BUF_SIZE];
int len = 0;
int ret;
if (fd->mode != LINK_FORMAT_MODE_DISCOVERY) {
/* Report resources instances only in device management
* discovery.
*/
return 0;
}
ret = snprintk(obj_buf, sizeof(obj_buf), "</%u/%u/%u/%u>", path->obj_id,
path->obj_inst_id, path->res_id, path->res_inst_id);
if (ret < 0 || ret >= sizeof(obj_buf)) {
return -ENOMEM;
}
len += ret;
ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), obj_buf, len);
if (ret < 0) {
return ret;
}
/* Report resource instance attrs only when resource was specified. */
if (fd->request_level == LWM2M_PATH_LEVEL_RESOURCE) {
struct lwm2m_engine_res_inst *res_inst =
lwm2m_engine_get_res_inst(path);
if (res_inst == NULL) {
return -EINVAL;
}
ret = put_corelink_attributes(out, res_inst, obj_buf,
sizeof(obj_buf));
if (ret < 0) {
return ret;
}
len += ret;
}
return len;
}
static int put_corelink(struct lwm2m_output_context *out, static int put_corelink(struct lwm2m_output_context *out,
const struct lwm2m_obj_path *path) const struct lwm2m_obj_path *path)
{ {
@ -487,6 +536,19 @@ static int put_corelink(struct lwm2m_output_context *out,
len += ret; len += ret;
break; break;
case LWM2M_PATH_LEVEL_RESOURCE_INST:
if (IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) {
ret = put_res_inst_corelink(out, path, fd);
if (ret < 0) {
return ret;
}
len += ret;
break;
}
__fallthrough;
default: default:
LOG_ERR("Invalid corelink path level: %d", path->level); LOG_ERR("Invalid corelink path level: %d", path->level);
return -EINVAL; return -EINVAL;