Move DeviceInfo to sysmngr package

This commit is contained in:
Amin Ben Romdhane 2024-10-28 11:26:50 +01:00
parent 67c094850f
commit 062c13e833
22 changed files with 128 additions and 2710 deletions

View file

@ -1,141 +0,0 @@
# Design For Firmware Activation
According to the TR181 data model, the Activate() command is an operation to activate the firmware image immediately or schedule it in another time.
In fact, the Linux system already provides us a cron to schedule some jobs. And since Openwrt is one of the Linux systems, so we can use a cron job as solution to handle the firmware activation.
The Activate() command has as arguments the TimeWindow object which is used to activate the required firmware in a specified time. For that, foreach TimeWindow instance a cron job will be created.
> Note: As per TR181 data model, max 5 instances of TimeWindow is supported.
Below is an example of an 'Activate()' command call with three TimeWindow instances. As a result, three jobs are created according to the defined TimeWindow.{i}.Start:
```bash
root@iopsys-44d43771aff0:~# ubus call bbfdm operate '{"path":"Device.DeviceInfo.FirmwareImage.2.", "action":"Activate()", "input":{"TimeWindow.1
.Start":"1800", "TimeWindow.1.End":"3600", "TimeWindow.1.Mode":"WhenIdle", "TimeWindow.2.Start":"5400", "TimeWindow.2.End":"9000", "TimeWindow
.2.Mode":"WhenIdle", "TimeWindow.3.Start":"86400", "TimeWindow.3.End":"172800", "TimeWindow.3.Mode":"Immediately"}}'
{
"Results": [
{
"path": "Device.DeviceInfo.FirmwareImage.2.Activate()",
"result": [
{
}
]
}
]
}
root@iopsys-44d43771aff0:~# crontab -l
52 22 21 2 * sh /usr/share/bbfdm/scripts/bbf_activate_handler.sh 'WhenIdle' '2' '1800' '0' '' ''
52 23 21 2 * sh /usr/share/bbfdm/scripts/bbf_activate_handler.sh 'WhenIdle' '2' '3600' '0' '' ''
22 22 22 2 * sh /usr/share/bbfdm/scripts/bbf_activate_handler.sh 'Immediately' '2' '86400' '1' '' ''
root@iopsys-44d43771aff0:~#
```
For those cron jobs it is required to give the handler script to be executed which is in our case [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh). And, it is located under '/usr/share/bbfdm/' in the device.
## Cron job specification
For each cron job related to the activated firmware, it is needed to define it as below:
```bash
* * * * * command to execute * * * * * *
- - - - - - - - - - - -
| | | | | | | | | | | |
| | | | | | | | | | | --- Message that informs the user of a new activation request
| | | | | | | | | | ----- Maximum number of retries
| | | | | | | | | ------- Force firmware activation when it's not idle (0 - 1)
| | | | | | | | --------- End of the time window
| | | | | | | ----------- Firmware Bank id to be activated
| | | | | | ------------- Mode (AnyTime, Immediately, WhenIdle, ConfirmationNeeded)
| | | | | -------------------------------- Activate firmware script 'bbf_activate_handler.sh'
| | | | ---------------------------------- Day of week (0 - 6) (Sunday =0)
| | | ------------------------------------ Month (1 - 12)
| | -------------------------------------- Day (1 - 31)
| ---------------------------------------- Hour (0 - 23)
------------------------------------------ Minute (0 - 59)
```
## Activate Handler script
As described, we create a cron job for each TimeWindow in order to activate the required firmware within a specified time by running the [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) handler script.
In fact, the aim of this script is to manage firmware images based on the **mode** and the other passed arguments.
### 1. Mode 'AnyTime' and 'Immediately':
For these modes and based on the firmware bank id, the required firmware image will be immediately activated at start time. The TimeWindow.{i}.End is ignored.
### 2. How to handle 'WhenIdle' mode:
Definition of WhenIdle may vary for each deployment and customer, to make it customizable [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) script is used. It is assumed that customer shall overwrite this file using customer-config to match with there requirement.
In this mode, [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) script calls this script [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) to determine the idle state of the device. [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) assumes the device as idle if the exit status of the above script is 0, or if the [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) is not present in the predefined path "ACTIVATE_HANDLER_FILE@dmcommon.h".
If the exit code from the idle script is zero then firmware image can be activated. Otherwise, it has to wait for next time slot which is defined by 'RETRY_TIME' variable.
> Note1: The time slot is set through 'RETRY_TIME' variable which is defined under '/usr/share/bbfdm/scripts/bbf_activate_handler.sh' script.
> Note2: The exit status of the script [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) is important because based on it, the '[bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) script will decide whether the image can be activated or not.
> Note3: Algorithm/Logic to determine the Idle state of device is out of scope of this document and it is expected that users overwrite this script with the logic to determine the same in actual deployment.
> Note4: If 1 or more TimeWindow.{i}.Mode is set to 'WhenIdle' and all of them fails to get the idle state. The latest TimeWindow instance will force the device to activate the firmware image.
> Note5: If the idle script [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) not present in the pre-defined path "ACTIVATE_HANDLER_FILE@dmcommon.h", then the device is assumed to be in ideal state and the firmware shall be activated instantly.
> Note6: It is very likely that TimeWindow with 'WhenIdle' mode might not find any suitable Idle state, in that case firmware shall not be activated. If users/operators want to make sure that firmware gets activated at the end, then they can add a TimeWindow with 'AnyTime/Immediate' mode at the end, to activate the firmware.
## Good to know
* TimeWindow instance arguments are optional.
* TimeWindow instances attributes must not overlap.
* If TimeWindow.{i}.Start is set, TimeWindow.{i}.End and TimeWindow.{i}.Mode become mondatory.
* The firmware activation is done by [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) script as per the defined Mode in TimeWindow, but if the TimeWindow is not defined, it will activate the requested FirmwareImage instance immediately.
* If the customer wants to be sure that the required firmware is getting activated at the end then they can define the TimeWindow.{i}.Mode as 'AnyTime' or 'Immediately' in the last TimeWindow instance.
* This document is only target for Firmware management using USP.
* TimeWindow.{i}.Mode = 'ConfirmationNeeded' is not supported.
## Vendor extension option to keep config while firmware download
It deployments for some customers, its required to do a factory reset after doing a firmware upgrade to start the CPE from clean state and then provision it from ACS/Controller.
As per standard datamodel, it's at-least 2 step time consuming process:
- Download the Firmware using 'Device.DeviceInfo.FirmwareImage.{i}.Download()' operate command with AutoActivate=1
- Wait for the 'Device.Boot!' event
- Factory reset the CPE using 'Device.FactoryReset()'
- Wait for the Boot event and then start provisioning.
We added an addition vendor specific input option which can be used by USP controller to factoryReset the CPE along with Firmware Upgrade, with this customer can save the cost of one additional reboot, which result into faster provisioning of the CPE.
Below are the current input options defined for Download operate command
```bash
Device.DeviceInfo.FirmwareImage.{i}.Download()
Device.DeviceInfo.FirmwareImage.{i}.Download() input:AutoActivate
Device.DeviceInfo.FirmwareImage.{i}.Download() input:CheckSum
Device.DeviceInfo.FirmwareImage.{i}.Download() input:CheckSumAlgorithm
Device.DeviceInfo.FirmwareImage.{i}.Download() input:CommandKey
Device.DeviceInfo.FirmwareImage.{i}.Download() input:FileSize
Device.DeviceInfo.FirmwareImage.{i}.Download() input:Password
Device.DeviceInfo.FirmwareImage.{i}.Download() input:URL
Device.DeviceInfo.FirmwareImage.{i}.Download() input:Username
Device.DeviceInfo.FirmwareImage.{i}.Download() input:X_IOPSYS_EU_KeepConfig
```
Customer can use X_IOPSYS_EU_KeepConfig=0, to do factory reset(not copy the current config to next firmware) while doing the download.
> Note: Default value of X_IOPSYS_EU_KeepConfig is 1, so in case this option not used, it keeps the config(as the default behavior of the CPE).

View file

@ -1,74 +0,0 @@
# Design for Reboot Data Model
In TR-181 version 2.18, a new object, Device.DeviceInfo.Reboots, was introduced to track and monitor reboot operations. This object provides details such as reboot reasons, counts, timestamps, and more, offering a comprehensive view of the device's state. It simplifies diagnostics and troubleshooting for applications and processes running on the device.
Currently, there is no standard configuration mapping to this object. However, we propose introducing a custom config called `deviceinfo` to manage this information effectively.
The idea is to maintain a 1-to-1 mapping between the parameters and UCI config. To achieve this, we need to create an `init.d` service script that generates a UCI section each time the boot() function is called. Essentially, when the boot() function is executed, it will check the `/tmp/reset_reason` file for specific markers, such as (reset reason) and (reset triggered), to identify the cause of the last boot. And based on these markers, it will calculate the required counter for data model parameters and commit the changes in `deviceinfo.globals` section. Furthermore, if necessary, it will create a UCI reboot section by checking `deviceinfo.globals.max_reboot_entries` and adjusting the config accordingly.
This approach ensures that the data model maps directly to UCI config as closely as possible, eliminating the need for any adjustments at the data model layer.
## Parameter Mapping Details
- Device.DeviceInfo.Reboots.BootCount: Maps to deviceinfo.globals.boot_count. This value is determined based on the marker (reset triggered: defaultreset) defined in `/tmp/reset_reason` file.
- Device.DeviceInfo.Reboots.CurrentVersionBootCount: Maps to deviceinfo.globals.curr_version_boot_count. This value is determined based on the marker (reset triggered: upgrade) defined in `/tmp/reset_reason` file.
- Device.DeviceInfo.Reboots.WatchdogBootCount: Maps to deviceinfo.globals.watchdog_boot_count. This value is determined based on the marker (reset reason: WATCHDOG) defined in `/tmp/reset_reason` file.
- Device.DeviceInfo.Reboots.ColdBootCount:
- Device.DeviceInfo.Reboots.WarmBootCount:
- Device.DeviceInfo.Reboots.MaxRebootEntries: Maps to deviceinfo.globals.max_reboot_entries. Possible values include {-1, 0, etc..}. Each case will be handled internally by bbfdm and default value is 3 and maximum reboot entry supported is 255.
- Device.DeviceInfo.Reboots.RebootNumberOfEntries: This is an internal bbfdm mechanism used to count the number of reboot entries.
- Device.DeviceInfo.Reboots.RemoveAllReboots(): An internal bbfdm API to remove all reboot sections.
- Device.DeviceInfo.Reboots.Reboot.{i}.: Each reboot entry is stored in a 'reboot' section.
- Device.DeviceInfo.Reboots.Reboot.{i}.Alias: Maps to deviceinfo.reboot[i].alias. This is managed internally by bbfdm.
- Device.DeviceInfo.Reboots.Reboot.{i}.TimeStamp: Maps to deviceinfo.reboot[i].time_stamp. This value is based on system uptime.
- Device.DeviceInfo.Reboots.Reboot.{i}.FirmwareUpdated: Maps to deviceinfo.reboot[i].firmware_updated.
- Device.DeviceInfo.Reboots.Reboot.{i}.Cause: Maps to deviceinfo.reboot[i].cause. Possible values include {LocalReboot, RemoteReboot, FactoryReset, LocalFactoryReset, RemoteFactoryReset}.
- Device.DeviceInfo.Reboots.Reboot.{i}.Reason: Maps to deviceinfo.reboot[i].reason. This value is determined based on the marker (reset reason) defined in `/tmp/reset_reason` file.
- Device.DeviceInfo.Reboots.Reboot.{i}.Remove(): An internal bbfdm API to remove the current 'reboot' section.
## Example Configuration
Below is an example of the configuration file:
```bash
cat /etc/config/deviceinfo
config globals 'globals'
option boot_count '2'
option curr_version_boot_count '4'
option watchdog_boot_count '3'
option cold_boot_count '2'
option warm_boot_count '2'
option max_reboot_entries '3'
config reboot 'reboot_1'
option alias 'cpe-1'
option time_stamp '2024-09-22T20:34:45Z'
option firmware_updated '0'
option cause 'RemoteReboot'
option reason 'REBOOT'
config reboot 'reboot_2'
option alias 'cpe-2'
option time_stamp '2024-09-22T21:55:09Z'
option firmware_updated '0'
option cause 'LocalReboot'
option reason 'POR_RESET'
config reboot 'reboot_3'
option alias 'cpe-3'
option time_stamp '2024-09-23T04:11:24Z'
option firmware_updated '1'
option cause 'LocalReboot'
option reason 'upgrade'
config reboot 'reboot_4'
option alias 'cpe-4'
option time_stamp '2024-09-23T04:15:53Z'
option firmware_updated '0'
option cause 'RemoteFactoryReset'
option reason 'REBOOT'
```

View file

@ -24,6 +24,15 @@ echo "Checking system resources"
free -h
df -h
# Check if the specified log file exists, which indicates errors during plugin loading
if [ -f ${BBFDM_LOG_FILE} ]; then
echo "Some plugins failed to load! Please check the errors below"
echo "*****************************************************"
cat "${BBFDM_LOG_FILE}"
echo "*****************************************************"
exit 1
fi
echo "## Running python based verification of functionalities ##"
echo > ./funl-result.log
num=0

View file

@ -1,6 +1,6 @@
#!/bin/bash
echo "install dependencies of bbf"
echo "install dependencies of bbfdm"
source ./gitlab-ci/shared.sh
@ -12,6 +12,7 @@ exec_cmd pip3 install pexpect ubus xlwt ValgrindCI
# Make sure that all plugins are removed
[ ! -d "${BBFDM_PLUGIN_DIR}" ] && mkdir -p "${BBFDM_PLUGIN_DIR}"
rm -f ${BBFDM_PLUGIN_DIR}/*
rm -f ${BBFDM_LOG_FILE}
# compile and install libbbf
install_libbbf ${1}

View file

@ -2,6 +2,7 @@
BBFDM_PLUGIN_DIR="/usr/share/bbfdm/plugins"
BBFDM_MS_DIR="/usr/share/bbfdm/micro_services"
BBFDM_LOG_FILE="/tmp/bbfdm.log"
if [ -z "${CI_PROJECT_PATH}" ]; then
CI_PROJECT_PATH=${PWD}
@ -64,7 +65,7 @@ function install_libbbf()
mkdir -p build
cd build
cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS -lm" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/
cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS -lm" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBF_SCHEMA_FULL_TREE=ON -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/
exec_cmd_verbose make
echo "installing libbbf"

View file

@ -153,7 +153,7 @@ struct dm_parameter {
};
typedef struct dm_map_obj {
char *path;
const char *path;
struct dm_obj_s *root_obj;
struct dm_leaf_s *root_leaf;
int (*init_module)(void *data);

View file

@ -69,6 +69,17 @@ static inline int DM_LINK_INST_OBJ(struct dmctx *dmctx, DMNODE *parent_node, voi
} while(0)
#endif
#ifndef TRACE_FILE
#define TRACE_FILE(MESSAGE, ...) do { \
FILE *log_file = fopen("/tmp/bbfdm.log", "a"); \
if (log_file) { \
fprintf(log_file, "[%s:%d] " MESSAGE "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
fclose(log_file); \
} \
} while(0)
#endif
// Macros for different log levels
#define BBF_ERR(MESSAGE, ...) do { \
syslog(LOG_ERR, "[%s:%d] " MESSAGE, __FUNCTION__, __LINE__, ##__VA_ARGS__); /* Flawfinder: ignore */ \

View file

@ -15,7 +15,6 @@
#include "dmcommon.h"
char *DiagnosticsState[] = {"None", "Requested", "Canceled", "Complete", "Error", NULL};
char *IPv4Address[] = {"^$", "^((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$", NULL};
@ -1704,6 +1703,23 @@ bool is_regular_file(const char *path)
return stat(path, &buffer) == 0 && S_ISREG(buffer.st_mode);
}
int create_empty_file(const char *file_name)
{
if (!file_name)
return -1;
// Skip creating the file if it already exists
if (file_exists(file_name))
return 0;
FILE *fp = fopen(file_name, "w");
if (fp == NULL)
return -1;
fclose(fp);
return 0;
}
unsigned long file_system_size(const char *path, const enum fs_size_type_enum type)
{
struct statvfs vfs;

View file

@ -217,6 +217,7 @@ void string_to_mac(const char *str, size_t str_len, char *out, size_t out_len);
bool folder_exists(const char *path);
bool file_exists(const char *path);
bool is_regular_file(const char *path);
int create_empty_file(const char *file_name);
unsigned long file_system_size(const char *path, const enum fs_size_type_enum type);
void remove_char(char *str, const char c);
char *replace_char(char *str, char find, char replace);

View file

@ -502,13 +502,9 @@ int dmuci_add_section(const char *package, const char *stype, struct uci_section
*s = NULL;
snprintf(fname, sizeof(fname), "%s/%s", uci_ctx->confdir, package);
if (!file_exists(fname)) {
FILE *fptr = fopen(fname, "w");
if (fptr)
fclose(fptr);
else
return -1;
}
if (create_empty_file(fname))
return -1;
if (dmuci_lookup_ptr(uci_ctx, &ptr, package, NULL, NULL, NULL))
return -1;

View file

@ -68,7 +68,11 @@ int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path)
void *handle = dlopen(plugin_path, RTLD_LAZY);
#endif
if (!handle) {
BBF_ERR("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, dlerror());
char *err_msg = dlerror();
#ifdef BBF_SCHEMA_FULL_TREE
TRACE_FILE("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, err_msg);
#endif
BBF_ERR("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, err_msg);
return 0;
}
@ -86,7 +90,10 @@ int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path)
DMOBJ *dm_entryobj = find_entry_obj(entryobj, dynamic_obj[i].path);
if (!dm_entryobj) {
BBF_ERR("Failed to add DotSo plugin '%s' to main tree with parent DM '%s'.", plugin_path, dynamic_obj[i].path);
#ifdef BBF_SCHEMA_FULL_TREE
TRACE_FILE("Failed to add DotSo plugin '%s' to main tree with parent DM index '%d' => '%s'", plugin_path, i, dynamic_obj[i].path);
#endif
BBF_ERR("Failed to add DotSo plugin '%s' to main tree with parent DM index '%d' => '%s'", plugin_path, i, dynamic_obj[i].path);
continue;
}

View file

@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 3.0)
PROJECT(libbbfdm)
OPTION(BBF_VENDOR_EXTENSION "build with vendor extension" ON)
ADD_DEFINITIONS(-Wall -Werror -g -D_GNU_SOURCE -DBBF_VENDOR_PREFIX="${BBF_VENDOR_PREFIX}")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR}")
@ -25,8 +23,3 @@ INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/plugins)
INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/micro_services)
INSTALL(DIRECTORY DESTINATION usr/libexec/rpcd)
IF(BBF_VENDOR_EXTENSION)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/vendor.json
DESTINATION usr/share/bbfdm/plugins
)
ENDIF(BBF_VENDOR_EXTENSION)

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 iopsys Software Solutions AB
* Copyright (C) 2019-2024 iopsys Software Solutions AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
@ -7,23 +7,39 @@
*
* Author: Imen Bhiri <imen.bhiri@pivasoftware.com>
* Author: Anis Ellouze <anis.ellouze@pivasoftware.com>
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
*/
#include "device.h"
#include "deviceinfo.h"
#include "lanconfigsecurity.h"
#include "security.h"
#include "gatewayinfo.h"
#include "schedules.h"
/*************************************************************
* GET & SET PARAM
* COMMON FUNCTIONS
**************************************************************/
static int get_Device_RootDataModelVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
static void _exec_reboot(const void *arg1, void *arg2)
{
*value = dmstrdup("2.18");
return 0;
char config_name[16] = {0};
snprintf(config_name, sizeof(config_name), "%s", "sysmngr");
// Set last_reboot_cause to 'RemoteReboot' because the upcoming reboot will be initiated by USP Operate
dmuci_set_value(config_name, "reboots", "last_reboot_cause", "RemoteReboot");
dmuci_commit_package(config_name);
sleep(3);
dmubus_call_set("rpc-sys", "reboot", UBUS_ARGS{0}, 0);
sleep(5); // Wait for reboot to happen
BBF_ERR("Reboot call failed with rpc-sys, trying again with system");
dmubus_call_set("system", "reboot", UBUS_ARGS{0}, 0);
sleep(5); // Wait for reboot
BBF_ERR("Reboot call failed!!!");
// Set last_reboot_cause to empty because there is a problem in the system reboot
dmuci_set_value(config_name, "reboots", "last_reboot_cause", "");
dmuci_commit_package(config_name);
}
static void _exec_factoryreset(const void *arg1, void *arg2)
@ -37,6 +53,15 @@ static void _exec_factoryreset(const void *arg1, void *arg2)
BBF_ERR("FactoryReset call failed!!!");
}
/*************************************************************
* GET & SET PARAM
**************************************************************/
static int get_Device_RootDataModelVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmstrdup("2.18");
return 0;
}
/*************************************************************
* OPERATE COMMANDS
*************************************************************/
@ -67,7 +92,6 @@ DM_MAP_OBJ tDynamicObj[] = {
/* *** Device. *** */
DMOBJ tDMRootObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoObj, tDeviceInfoParams, NULL, BBFDM_BOTH, NULL},
{"LANConfigSecurity", &DMREAD, NULL, NULL, "file:/etc/config/users", NULL, NULL, NULL, NULL, tLANConfigSecurityParams, NULL, BBFDM_BOTH, NULL},
{"Schedules", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSchedulesObj, tSchedulesParams, NULL, BBFDM_BOTH, NULL},
{"Security", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSecurityObj, tSecurityParams, NULL, BBFDM_BOTH, NULL},

File diff suppressed because it is too large Load diff

View file

@ -1,32 +0,0 @@
/*
* Copyright (C) 2019 iopsys Software Solutions AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation
*
* Author: Imen Bhiri <imen.bhiri@pivasoftware.com>
* Author: Feten Besbes <feten.besbes@pivasoftware.com>
* Author: Anis Ellouze <anis.ellouze@pivasoftware.com>
*/
#ifndef __DEVICE_INFO_H
#define __DEVICE_INFO_H
#include "libbbfdm-api/dmcommon.h"
extern DMLEAF tDeviceInfoParams[];
extern DMLEAF tDeviceInfoVendorConfigFileParams[];
extern DMLEAF tDeviceInfoMemoryStatusParams[];
extern DMOBJ tDeviceInfoProcessStatusObj[];
extern DMLEAF tDeviceInfoProcessStatusParams[];
extern DMOBJ tDeviceInfoObj[];
extern DMLEAF tDeviceInfoProcessStatusProcessParams[];
extern DMLEAF tDeviceInfoSupportedDataModelParams[];
extern DMLEAF tDeviceInfoFirmwareImageParams[];
extern DMOBJ tDeviceInfoRebootsObj[];
extern DMLEAF tDeviceInfoRebootsParams[];
extern DMLEAF tDeviceInfoRebootsRebootParams[];
void _exec_reboot(const void *arg1, void *arg2);
#endif

View file

@ -1,47 +0,0 @@
{
"json_plugin_version": 2,
"Device.DeviceInfo.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"description": "This object contains general device information.",
"access": false,
"array": false,
"{BBF_VENDOR_PREFIX}BaseMACAddress": {
"type": "string",
"read": true,
"write": false,
"protocols": [
"cwmp",
"usp"
],
"description": "The MAC Address of the device.",
"datatype": "MACAddress",
"range": [
{
"max": 17
}
],
"pattern": [
"",
"([0-9A-Fa-f][0-9A-Fa-f]:){5}([0-9A-Fa-f][0-9A-Fa-f])"
],
"mapping": [
{
"type": "uci",
"uci": {
"file": "/etc/board-db/config/device",
"section": {
"name": "deviceinfo"
},
"option": {
"name":"BaseMACAddress"
}
}
}
]
}
}
}

View file

@ -1,5 +1,5 @@
config globals 'globals'
config reboots 'reboots'
option boot_count '2'
option curr_version_boot_count '4'
option watchdog_boot_count '3'
@ -7,28 +7,28 @@ config globals 'globals'
option warm_boot_count '2'
option max_reboot_entries '3'
config reboot
config reboot 'reboot_1730818192'
option alias 'cpe-1'
option time_stamp '2024-09-22T20:34:45Z'
option firmware_updated '0'
option cause 'RemoteReboot'
option reason 'REBOOT'
config reboot
config reboot 'reboot_2541818178'
option alias 'cpe-2'
option time_stamp '2024-09-22T21:55:09Z'
option firmware_updated '0'
option cause 'LocalReboot'
option reason 'POR_RESET'
config reboot
config reboot 'reboot_4512818130'
option alias 'cpe-3'
option time_stamp '2024-09-23T04:11:24Z'
option firmware_updated '1'
option cause 'LocalReboot'
option reason 'upgrade'
config reboot
config reboot 'reboot_9874811423'
option alias 'cpe-4'
option time_stamp '2024-09-23T04:15:53Z'
option firmware_updated '0'

View file

@ -411,7 +411,7 @@ def download_and_build_plugins(plugins, vendor_prefix):
BBF_ERROR_CODE += 1
if len(LIST_FILES) > 0:
if not generate_shared_library(f"{name}{plugin_index}.so", LIST_FILES, vendor_prefix, extra_dependencies, is_microservice):
if not generate_shared_library(f"{plugin_index}_{name}.so", LIST_FILES, vendor_prefix, extra_dependencies, is_microservice):
BBF_ERROR_CODE += 1
clear_list(LIST_FILES)

View file

@ -6,11 +6,37 @@
"model_name": "DG400PRIME-A",
"software_version": "1.2.3.4",
"dm_json_files": [
"tools/datamodel.json",
"libbbfdm/vendor/vendor.json"
"tools/datamodel.json"
],
"vendor_prefix": "X_IOPSYS_EU_",
"plugins": [
{
"repo": "https://dev.iopsys.eu/system/sysmngr.git",
"proto": "git",
"version": "devel",
"dm_info_file": "src/datamodel_description.json",
"extra_dependencies": [
"-DSYSMNGR_VENDOR_CONFIG_FILE",
"-DSYSMNGR_MEMORY_STATUS",
"-DSYSMNGR_PROCESS_STATUS",
"-DSYSMNGR_SUPPORTED_DATA_MODEL",
"-DSYSMNGR_FIRMWARE_IMAGE",
"-DSYSMNGR_REBOOTS",
"-DSYSMNGR_NETWORK_PROPERTIES",
"-DSYSMNGR_VENDOR_EXTENSIONS"
],
"dm_files": [
"src/deviceinfo.c",
"src/configs.c",
"src/fw_images.c",
"src/memory.c",
"src/processes.c",
"src/reboots.c",
"src/supported_dm.c",
"src/network.c",
"src/utils.c"
]
},
{
"repo": "https://dev.iopsys.eu/bbf/icwmp.git",
"proto": "git",
@ -23,6 +49,9 @@
"repo": "https://dev.iopsys.eu/bbf/bulkdata.git",
"proto": "git",
"version": "devel",
"extra_dependencies": [
"-D_GNU_SOURCE"
],
"dm_files": [
"src/datamodel.c",
"src/utils.c"
@ -330,7 +359,8 @@
"dm_files": [
"bbf_plugin/mcast_bbf.c",
"bbf_plugin/x_iopsys_eu_igmp.c",
"bbf_plugin/x_iopsys_eu_mld.c"
"bbf_plugin/x_iopsys_eu_mld.c",
"bbf_plugin/x_iopsys_eu_common.c"
]
},
{
@ -382,7 +412,7 @@
"libdm/tr104/*.c"
],
"extra_dependencies": [
"-I libdmtree",
"-I /builds/bbf/bbfdm/libbbfdm-api",
"-I libdm/common"
]
},
@ -421,7 +451,7 @@
"libdm/extensions/iowrt/*.c"
],
"extra_dependencies": [
"-I libdmtree",
"-I /builds/bbf/bbfdm/libbbfdm-api",
"-I libdm/common"
]
}

View file

@ -1,94 +0,0 @@
#!/bin/sh
# Script to activate image in specified time.
#
# Copyright © 2022 IOPSYS Software Solutions AB
# Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
#
ROOT="$(dirname "${0}")"
CHECK_IDLE_FILE="${ROOT}/bbf_check_idle.sh"
RETRY_TIME=300
START_TIME=$(date +%s)
MODE="${1}"
log() {
echo "${@}"|logger -t bbf.activate_firmware -p info
}
activate_and_reboot_device() {
local bank_id="${1}"
local success
success=$(ubus call fwbank set_bootbank "{'bank':${bank_id}}" | jsonfilter -e @.success)
if [ "${success}" != "true" ]; then
log "Can't activate the bank id ${bank_id}"
exit 1
fi
log "The device will restart after a few seconds"
ubus call rpc-sys reboot
exit 0
}
handle_whenidle_mode() {
local bank_id="${1}"
local end_time="${2}"
local force_activation="${3}"
local diff=0
[ ! -x "${CHECK_IDLE_FILE}" ] && {
activate_and_reboot_device "${bank_id}"
}
sh "${CHECK_IDLE_FILE}"
if [ "$?" = "0" ]; then
activate_and_reboot_device "${bank_id}"
else
[ "${end_time}" -gt "$((diff + RETRY_TIME))" ] && {
sleep "${RETRY_TIME}"
}
diff=$(($(date +%s) - START_TIME))
fi
while [ "${end_time}" -gt "${diff}" ]; do
sh "${CHECK_IDLE_FILE}"
if [ "$?" = "0" ]; then
activate_and_reboot_device "${bank_id}"
else
if [ "${end_time}" -gt "$((diff + RETRY_TIME))" ]; then
sleep "${RETRY_TIME}"
else
break
fi
diff=$(($(date +%s) - START_TIME))
fi
done
[ "${force_activation}" = "1" ] && {
activate_and_reboot_device "${bank_id}"
}
}
handle_confirmation_needed_mode() {
log "[ConfirmationNeeded] mode is not implemented"
exit 0
}
######################## main ########################
if [ "${MODE}" = "Immediately" ] || [ "${MODE}" = "AnyTime" ]; then
activate_and_reboot_device "${2}"
elif [ "${MODE}" = "WhenIdle" ]; then
handle_whenidle_mode "${2}" "${3}" "${4}"
elif [ "${MODE}" = "ConfirmationNeeded" ]; then
handle_confirmation_needed_mode "${2}" "${3}" "${4}" "${5}" "${6}"
else
log "[${MODE}] mode is not supported"
exit 1
fi

View file

@ -1,11 +0,0 @@
#!/bin/sh
# Script to check idle state
#
# This script is used to determine if the device is in idle state or not
# And any idle state checking should be implemented here
# The value returned by this script is more important because based on it, will decide whether the image can be activated or not
# If (returned idle state == '0'), device is in idle state and can be activated. Otherwise, '1'
exit 0

View file

@ -1,206 +0,0 @@
#!/bin/sh
# Script to handle Reboots Object
#
# Copyright © 2024 IOPSYS Software Solutions AB
# Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
#
. /lib/functions.sh
RESET_REASON_PATH="/tmp/reset_reason"
MAX_RETRIES=3
RETRY_DELAY=1
log() {
echo "$@" | logger -t bbf_reboot -p info
}
reset_option_counter() {
local option_name=$1
local option_value=$2
uci_set "deviceinfo" "globals" "${option_name}" "${option_value}"
}
increment_option_counter() {
local option_name=$1
local option_value=$(uci_get "deviceinfo" "globals" "${option_name}" "0")
local counter=$((option_value + 1))
uci_set "deviceinfo" "globals" "${option_name}" "$counter"
}
get_boot_trigger() {
local trigger
trigger=$(grep "triggered" ${RESET_REASON_PATH} | cut -d ':' -f2 | xargs)
echo "${trigger}"
}
get_boot_reason() {
local reason
reason=$(grep "reason" ${RESET_REASON_PATH} | cut -d ':' -f2 | xargs)
echo "${reason}"
}
calculate_boot_time() {
# Get current time and uptime in seconds
local current_time uptime_seconds boot_time boot_time_formatted
current_time=$(date +%s)
uptime_seconds=$(awk '{print $1}' /proc/uptime | cut -d. -f1)
# Calculate the boot time by subtracting the uptime from the current time
boot_time=$((current_time - uptime_seconds))
# Convert the boot time to a human-readable format
boot_time_formatted=$(date -d "@$boot_time" +"%Y-%m-%dT%H:%M:%SZ")
echo "${boot_time_formatted}"
}
boot_reason_message() {
# Generate a human-readable message based on the boot reason and trigger
local trigger reason
trigger=$(get_boot_trigger)
if [ -n "${trigger}" ]; then
case "${trigger}" in
"defaultreset")
echo "FACTORY RESET"
;;
"upgrade")
echo "FIRMWARE UPGRADE"
;;
*)
echo "${trigger}"
;;
esac
else
reason=$(get_boot_reason)
case "${reason}" in
"POR_RESET")
echo "POWER ON RESET"
;;
*)
echo "${reason}"
;;
esac
fi
}
create_reboot_section() {
local trigger=$1
local reboot_sec
reboot_sec="reboot_$(date +%Y%m%d%H%M%S)"
uci_add "deviceinfo" "reboot" "${reboot_sec}"
uci_set "deviceinfo" "${reboot_sec}" "time_stamp" "$(calculate_boot_time)"
if [ "${trigger}" = "upgrade" ]; then
uci_set "deviceinfo" "${reboot_sec}" "firmware_updated" "1"
else
uci_set "deviceinfo" "${reboot_sec}" "firmware_updated" "0"
fi
if [ "${trigger}" = "defaultreset" ]; then
uci_set "deviceinfo" "${reboot_sec}" "cause" "FactoryReset"
else
local last_reboot_cause
last_reboot_cause=$(uci_get "deviceinfo" "globals" "last_reboot_cause" "LocalReboot")
uci_set "deviceinfo" "${reboot_sec}" "cause" "${last_reboot_cause}"
uci_set "deviceinfo" "globals" "last_reboot_cause" ""
fi
uci_set "deviceinfo" "${reboot_sec}" "reason" "$(boot_reason_message)"
}
handle_reboot_action() {
local trigger reason max_reboot_entries retry_count reboot_sec_num
retry_count=0
# Retry fetching the reset reason file
while [ ! -f "${RESET_REASON_PATH}" ] && [ $retry_count -lt $MAX_RETRIES ]; do
log "Warning: '${RESET_REASON_PATH}' not found. Attempt $((retry_count + 1)) of ${MAX_RETRIES}"
sleep $RETRY_DELAY
retry_count=$((retry_count + 1))
done
if [ ! -f "${RESET_REASON_PATH}" ]; then
log "Error: '${RESET_REASON_PATH}' is not generated after ${MAX_RETRIES} attempts!!!"
return 1
fi
uci_load "deviceinfo"
trigger=$(get_boot_trigger)
reason=$(get_boot_reason)
# Reset or increment boot counter based on trigger
if [ "${trigger}" = "defaultreset" ]; then
## Reset all counters ##
reset_option_counter "boot_count" "1"
reset_option_counter "curr_version_boot_count" "0"
reset_option_counter "watchdog_boot_count" "0"
reset_option_counter "cold_boot_count" "0"
reset_option_counter "warm_boot_count" "0"
else
# Incrementing boot counter
increment_option_counter "boot_count"
fi
# Reset or increment current version boot counter based on trigger
if [ "${trigger}" = "upgrade" ]; then
# Resetting current version boot counter
reset_option_counter "curr_version_boot_count" "1"
else
# Incrementing current version boot counter
increment_option_counter "curr_version_boot_count"
fi
# Increment watchdog boot counter if the reason indicates a watchdog reset
if echo "${reason}" | grep -qi "watchdog"; then
# Incrementing watchdog boot counter
increment_option_counter "watchdog_boot_count"
fi
# Increment cold or warm boot counter based on the reason
if [ "${reason}" = "POR_RESET" ]; then
increment_option_counter "cold_boot_count"
else
increment_option_counter "warm_boot_count"
fi
# Get the max reboot entries
max_reboot_entries=$(uci_get "deviceinfo" "globals" "max_reboot_entries" "3")
if [ "${max_reboot_entries}" -eq 0 ]; then
# Commit the UCI changes to persist the configuration
uci_commit "deviceinfo"
return 0
fi
if [ $max_reboot_entries -gt 0 ]; then
# Calculate the number of reboot sections in the config
reboot_sec_num=$(uci -q show deviceinfo | grep "=reboot" | wc -l)
# Delete excess reboot sections if they exceed the max reboot entries
if [ "${reboot_sec_num}" -ge "${max_reboot_entries}" ]; then
local diff=$((reboot_sec_num - max_reboot_entries + 1))
for i in $(seq 1 $diff); do
uci_remove "deviceinfo" "@reboot[0]"
done
fi
fi
# Create a new reboot section with the current boot information
create_reboot_section "${trigger}"
# Commit the UCI changes to persist the configuration
uci_commit "deviceinfo"
}
# Run the main function
handle_reboot_action
exit 0