1 /*
2 * Copyright (c) 2019 Foundries.io
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define LOG_MODULE_NAME net_lwm2m_obj_conn_mon
8 #define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
9
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
12
13 #include <string.h>
14 #include <zephyr/init.h>
15 #include <zephyr/net/net_if.h>
16 #include <zephyr/net/net_ip.h>
17
18 #include "lwm2m_object.h"
19 #include "lwm2m_engine.h"
20
21 #define CONNMON_VERSION_MAJOR 1
22 #if defined(CONFIG_LWM2M_CONNMON_OBJECT_VERSION_1_3)
23 #define CONNMON_VERSION_MINOR 3
24 #define CONNMON_MAX_ID 14
25 #elif defined(CONFIG_LWM2M_CONNMON_OBJECT_VERSION_1_2)
26 #define CONNMON_VERSION_MINOR 2
27 #define CONNMON_MAX_ID 13
28 #else
29 #define CONNMON_VERSION_MINOR 0
30 #define CONNMON_MAX_ID 11
31 #endif
32
33 /* Connectivity Monitoring resource IDs */
34 #define CONNMON_NETWORK_BEARER_ID 0
35 #define CONNMON_AVAIL_NETWORK_BEARER_ID 1
36 #define CONNMON_RADIO_SIGNAL_STRENGTH 2
37 #define CONNMON_LINK_QUALITY 3
38 #define CONNMON_IP_ADDRESSES 4
39 #define CONNMON_ROUTER_IP_ADDRESSES 5
40 #define CONNMON_LINK_UTILIZATION 6
41 #define CONNMON_APN 7
42 #define CONNMON_CELLID 8
43 #define CONNMON_SMNC 9
44 #define CONNMON_SMCC 10
45 #if CONNMON_VERSION_MINOR > 0
46 #define CONNMON_SIGNAL_SNR 11
47 #endif
48 #if CONNMON_VERSION_MINOR > 1
49 #define CONNMON_LAC 12
50 #endif
51 #if CONNMON_VERSION_MINOR > 2
52 #define CONNMON_COVERAGE_ENHANCEMENT_LEVEL 13
53 #endif
54
55 #define CONNMON_STRING_SHORT 8
56
57 #define CONNMON_AVAIL_BEARER_MAX CONFIG_LWM2M_CONN_MON_BEARER_MAX
58 #define CONNMON_APN_MAX CONFIG_LWM2M_CONN_MON_APN_MAX
59
60 #if defined(CONFIG_NET_IF_MAX_IPV6_COUNT) \
61 && defined(CONFIG_NET_IF_MAX_IPV4_COUNT)
62 #define CONNMON_IP_ADDRESS_MAX (CONFIG_NET_IF_MAX_IPV6_COUNT + \
63 CONFIG_NET_IF_MAX_IPV4_COUNT)
64 #elif defined(CONFIG_NET_IF_MAX_IPV6_COUNT)
65 #define CONNMON_IP_ADDRESS_MAX CONFIG_NET_IF_MAX_IPV6_COUNT
66 #elif defined(CONFIG_NET_IF_MAX_IPV4_COUNT)
67 #define CONNMON_IP_ADDRESS_MAX CONFIG_NET_IF_MAX_IPV4_COUNT
68 #else
69 #define CONNMON_IP_ADDRESS_MAX 1
70 #endif
71
72 #if defined(CONFIG_NET_MAX_ROUTERS)
73 #define CONNMON_ROUTER_IP_ADDRESS_MAX CONFIG_NET_MAX_ROUTERS
74 #else
75 #define CONNMON_ROUTER_IP_ADDRESS_MAX 1
76 #endif
77
78 /*
79 * Calculate resource instances as follows:
80 * start with CONNMON_MAX_ID
81 * subtract MULTI resources because their counts include 0 resource (4)
82 * add CONNMON_AVAIL_BEARER_MAX resource instances
83 * add CONNMON_APN_MAX resource instances
84 * add CONNMON_IP_ADDRESS_MAX resource instances
85 * add CONNMON_ROUTER_IP_ADDRESS_MAX resource instances
86 */
87 #define RESOURCE_INSTANCE_COUNT (CONNMON_MAX_ID - 4 + \
88 CONNMON_AVAIL_BEARER_MAX + \
89 CONNMON_APN_MAX + \
90 CONNMON_IP_ADDRESS_MAX + \
91 CONNMON_ROUTER_IP_ADDRESS_MAX)
92
93 /* resource state variables */
94 static int8_t net_bearer;
95 static int16_t rss;
96 static int16_t link_quality;
97 static uint32_t cellid;
98 static uint16_t mnc;
99 static uint16_t mcc;
100 #if CONNMON_VERSION_MINOR > 0
101 static int32_t snr;
102 #endif
103 #if CONNMON_VERSION_MINOR > 1
104 static uint16_t lac;
105 #endif
106 #if CONNMON_VERSION_MINOR > 2
107 static uint8_t cel;
108 #endif
109
110 /* only 1 instance of Connection Monitoring object exists */
111 static struct lwm2m_engine_obj connmon;
112 static struct lwm2m_engine_obj_field fields[] = {
113 OBJ_FIELD_DATA(CONNMON_NETWORK_BEARER_ID, R, U8),
114 OBJ_FIELD_DATA(CONNMON_AVAIL_NETWORK_BEARER_ID, R, U8),
115 OBJ_FIELD_DATA(CONNMON_RADIO_SIGNAL_STRENGTH, R, S16),
116 OBJ_FIELD_DATA(CONNMON_LINK_QUALITY, R, S16),
117 OBJ_FIELD_DATA(CONNMON_IP_ADDRESSES, R, STRING),
118 OBJ_FIELD_DATA(CONNMON_ROUTER_IP_ADDRESSES, R_OPT, STRING),
119 OBJ_FIELD_DATA(CONNMON_LINK_UTILIZATION, R_OPT, U8),
120 OBJ_FIELD_DATA(CONNMON_APN, R_OPT, STRING),
121 OBJ_FIELD_DATA(CONNMON_CELLID, R_OPT, U32),
122 OBJ_FIELD_DATA(CONNMON_SMNC, R_OPT, U16),
123 OBJ_FIELD_DATA(CONNMON_SMCC, R_OPT, U16),
124 #if CONNMON_VERSION_MINOR > 0
125 OBJ_FIELD_DATA(CONNMON_SIGNAL_SNR, R_OPT, S32),
126 #endif
127 #if CONNMON_VERSION_MINOR > 1
128 OBJ_FIELD_DATA(CONNMON_LAC, R_OPT, U16),
129 #endif
130 #if CONNMON_VERSION_MINOR > 2
131 OBJ_FIELD_DATA(CONNMON_COVERAGE_ENHANCEMENT_LEVEL, R_OPT, U8),
132 #endif
133 };
134
135 static struct lwm2m_engine_obj_inst inst;
136 static struct lwm2m_engine_res res[CONNMON_MAX_ID];
137 static struct lwm2m_engine_res_inst res_inst[RESOURCE_INSTANCE_COUNT];
138
connmon_create(uint16_t obj_inst_id)139 static struct lwm2m_engine_obj_inst *connmon_create(uint16_t obj_inst_id)
140 {
141 int i = 0, j = 0;
142
143 /* Set default values */
144 net_bearer = 42U; /* Ethernet */
145 rss = 0;
146 link_quality = 0U;
147 mnc = 0U;
148 mcc = 0U;
149 #if CONNMON_VERSION_MINOR > 0
150 snr = 0U;
151 #endif
152 #if CONNMON_VERSION_MINOR > 1
153 lac = 0U;
154 #endif
155 #if CONNMON_VERSION_MINOR > 2
156 cel = 0U;
157 #endif
158
159 init_res_instance(res_inst, ARRAY_SIZE(res_inst));
160
161 /* initialize instance resource data */
162 INIT_OBJ_RES_DATA(CONNMON_NETWORK_BEARER_ID, res, i, res_inst, j,
163 &net_bearer, sizeof(net_bearer));
164 INIT_OBJ_RES_MULTI_OPTDATA(CONNMON_AVAIL_NETWORK_BEARER_ID, res, i,
165 res_inst, j, CONNMON_AVAIL_BEARER_MAX,
166 false);
167 INIT_OBJ_RES_DATA(CONNMON_RADIO_SIGNAL_STRENGTH, res, i, res_inst, j,
168 &rss, sizeof(rss));
169 INIT_OBJ_RES_DATA(CONNMON_LINK_QUALITY, res, i, res_inst, j,
170 &link_quality, sizeof(link_quality));
171 INIT_OBJ_RES_MULTI_OPTDATA(CONNMON_IP_ADDRESSES, res, i,
172 res_inst, j, CONNMON_IP_ADDRESS_MAX, false);
173 INIT_OBJ_RES_MULTI_OPTDATA(CONNMON_ROUTER_IP_ADDRESSES, res, i,
174 res_inst, j, CONNMON_ROUTER_IP_ADDRESS_MAX,
175 false);
176 INIT_OBJ_RES_MULTI_OPTDATA(CONNMON_APN, res, i, res_inst, j,
177 CONNMON_APN_MAX, false);
178 INIT_OBJ_RES_DATA(CONNMON_CELLID, res, i, res_inst, j, &cellid,
179 sizeof(cellid));
180 INIT_OBJ_RES_DATA(CONNMON_SMNC, res, i, res_inst, j, &mnc, sizeof(mnc));
181 INIT_OBJ_RES_DATA(CONNMON_SMCC, res, i, res_inst, j, &mcc, sizeof(mcc));
182 #if CONNMON_VERSION_MINOR > 0
183 INIT_OBJ_RES_DATA(CONNMON_SIGNAL_SNR, res, i, res_inst, j, &snr, sizeof(snr));
184 #endif
185 #if CONNMON_VERSION_MINOR > 1
186 INIT_OBJ_RES_DATA(CONNMON_LAC, res, i, res_inst, j, &lac, sizeof(lac));
187 #endif
188 #if CONNMON_VERSION_MINOR > 2
189 INIT_OBJ_RES_DATA(CONNMON_COVERAGE_ENHANCEMENT_LEVEL, res, i, res_inst, j, &cel,
190 sizeof(cel));
191 #endif
192 inst.resources = res;
193 inst.resource_count = i;
194 LOG_DBG("Create LWM2M connectivity monitoring instance: %d",
195 obj_inst_id);
196 return &inst;
197 }
198
lwm2m_connmon_init(void)199 static int lwm2m_connmon_init(void)
200 {
201 struct lwm2m_engine_obj_inst *obj_inst = NULL;
202 int ret = 0;
203
204 /* initialize the Connection Monitoring field data */
205 connmon.obj_id = LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID;
206 connmon.version_major = CONNMON_VERSION_MAJOR;
207 connmon.version_minor = CONNMON_VERSION_MINOR;
208 connmon.is_core = true;
209 connmon.fields = fields;
210 connmon.field_count = ARRAY_SIZE(fields);
211 connmon.max_instance_count = 1U;
212 connmon.create_cb = connmon_create;
213 lwm2m_register_obj(&connmon);
214
215 /* auto create the only instance */
216 ret = lwm2m_create_obj_inst(LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID,
217 0, &obj_inst);
218 if (ret < 0) {
219 LOG_DBG("Create LWM2M instance 0 error: %d", ret);
220 }
221
222 return ret;
223 }
224
225 LWM2M_CORE_INIT(lwm2m_connmon_init);
226