diff --git a/src/common.h b/src/common.h index 1823615..ae4ebd7 100644 --- a/src/common.h +++ b/src/common.h @@ -117,6 +117,7 @@ typedef struct config { time_t schedule_reboot; time_t time; time_t heart_time; + unsigned int active_notif_throttle; unsigned int periodic_entropy; bool periodic_enable; bool periodic_notify_enable; @@ -157,6 +158,7 @@ typedef struct cwmp { bool prev_heartbeat_enable; bool heart_session; bool diag_session; + bool throttle_session; int prev_periodic_interval; int prev_heartbeat_interval; int retry_count_session; @@ -182,6 +184,7 @@ typedef struct cwmp { bool cwmp_periodic_enable; bool custom_notify_active; struct ubus_event_handler *ev; + bool throttle_session_triggered; } cwmp; enum action { diff --git a/src/config.c b/src/config.c index 18db59f..33c88e1 100755 --- a/src/config.c +++ b/src/config.c @@ -486,6 +486,19 @@ int get_global_config() cwmp_main->conf.delay_reboot = -1; } + if (uci_get_value(UCI_CPE_ACTIVE_NOTIF_THROTTLE, &value) == CWMP_OK) { + int a = 0; + + if (value != NULL) { + a = atoi(value); + FREE(value); + } + + cwmp_main->conf.active_notif_throttle = a; + } else { + cwmp_main->conf.active_notif_throttle = 0; + } + cwmp_main->conf.custom_notify_json = NULL; if (uci_get_value(UCI_CPE_JSON_CUSTOM_NOTIFY_FILE, &value) == CWMP_OK) { FREE(cwmp_main->conf.custom_notify_json); diff --git a/src/cwmp.c b/src/cwmp.c index b3dc076..eb33ec4 100644 --- a/src/cwmp.c +++ b/src/cwmp.c @@ -245,6 +245,8 @@ static int cwmp_init() cwmp_main->prev_heartbeat_time = cwmp_main->conf.heart_time; cwmp_main->heart_session = false; cwmp_main->diag_session = false; + cwmp_main->throttle_session = false; + cwmp_main->throttle_session_triggered = false; if (cwmp_stop == true) return CWMP_GEN_ERR; diff --git a/src/cwmp_uci.h b/src/cwmp_uci.h index ef7f395..f0ed90f 100644 --- a/src/cwmp_uci.h +++ b/src/cwmp_uci.h @@ -41,6 +41,7 @@ #define UCI_CPE_NOTIFY_PERIOD "cwmp.cpe.periodic_notify_interval" #define UCI_CPE_SCHEDULE_REBOOT "cwmp.cpe.schedule_reboot" #define UCI_CPE_DELAY_REBOOT "cwmp.cpe.delay_reboot" +#define UCI_CPE_ACTIVE_NOTIF_THROTTLE "cwmp.cpe.active_notif_throttle" #define UCI_CPE_JSON_CUSTOM_NOTIFY_FILE "cwmp.cpe.custom_notify_json" #define LW_NOTIFICATION_ENABLE "cwmp.lwn.enable" #define LW_NOTIFICATION_HOSTNAME "cwmp.lwn.hostname" diff --git a/src/datamodel.c b/src/datamodel.c index 6b4ba29..e4333d0 100644 --- a/src/datamodel.c +++ b/src/datamodel.c @@ -847,6 +847,27 @@ static int get_manageable_device_number_of_entries(char *refparam, struct dmctx return 0; } +static int get_default_active_notification_throttle(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + *value = dmuci_get_option_value_fallback_def("cwmp", "cpe", "active_notif_throttle", "0"); + return 0; +} + +static int set_default_active_notification_throttle(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + switch (action) { + case VALUECHECK: + if (dm_validate_unsignedInt(value, RANGE_ARGS{{"1",NULL}}, 1)) + return FAULT_9007; + return 0; + case VALUESET: + dmuci_set_value("cwmp", "cpe", "active_notif_throttle", value); + cwmp_set_end_session_flag(ctx, BBF_END_SESSION_RELOAD); + return 0; + } + return 0; +} + static int get_heart_beat_policy_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { *value = dmuci_get_option_value_fallback_def("cwmp", "acs", "heartbeat_enable", "0"); @@ -1344,6 +1365,7 @@ DMLEAF tManagementServerParams[] = { {"NATDetected", &DMREAD, DMT_BOOL, get_nat_detected, NULL, BBFDM_CWMP, "2.0"}, {"InformParameterNumberOfEntries", &DMREAD, DMT_UNINT, get_inform_parameter_number_of_entries, NULL, BBFDM_CWMP, "2.0"}, {"ManageableDeviceNumberOfEntries", &DMREAD, DMT_UNINT, get_manageable_device_number_of_entries, NULL, BBFDM_CWMP, "2.0"}, +{"DefaultActiveNotificationThrottle", &DMWRITE, DMT_UNINT, get_default_active_notification_throttle, set_default_active_notification_throttle, BBFDM_CWMP, "2.0"}, {0} }; diff --git a/src/notifications.c b/src/notifications.c index a2e8071..7f30e1f 100644 --- a/src/notifications.c +++ b/src/notifications.c @@ -703,7 +703,16 @@ void periodic_check_notifiy(struct uloop_timeout *timeout __attribute__((unused cwmp_update_enabled_notify_file(); if (is_notify & NOTIF_ACTIVE) { send_active_value_change(); - trigger_cwmp_session_timer(); + int last_session_interval = time(NULL) - cwmp_main->session->session_status.last_end_time; + if (!cwmp_main->throttle_session_triggered && (cwmp_main->session->session_status.last_status == SESSION_SUCCESS) && (cwmp_main->conf.active_notif_throttle > 0)) { + cwmp_main->throttle_session_triggered = true; + if (last_session_interval < cwmp_main->conf.active_notif_throttle) + trigger_cwmp_throttle_session_timer(cwmp_main->conf.active_notif_throttle - last_session_interval); + else + trigger_cwmp_throttle_session_timer(0); + } + else if (cwmp_main->conf.active_notif_throttle == 0) + trigger_cwmp_session_timer(); } if (is_notify & NOTIF_LW_ACTIVE) diff --git a/src/session.c b/src/session.c index 3985f2c..39279fe 100644 --- a/src/session.c +++ b/src/session.c @@ -39,6 +39,7 @@ static void cwmp_periodic_session_timer(struct uloop_timeout *timeout); struct uloop_timeout session_timer = { .cb = cwmp_schedule_session }; struct uloop_timeout periodic_session_timer = { .cb = cwmp_periodic_session_timer }; struct uloop_timeout retry_session_timer = { .cb = cwmp_schedule_session }; +struct uloop_timeout throttle_session_timer = { .cb = cwmp_schedule_throttle_session }; //struct session_timer_event session_timer_evt = {.session_timer_evt = {.cb = cwmp_schedule_session_with_event}, .event = -1}; unsigned int end_session_flag = 0; @@ -404,6 +405,13 @@ void start_cwmp_session() remove_single_event(EVENT_IDX_14HEARTBEAT); cwmp_main->retry_count_session = 0; set_cwmp_session_status(SESSION_SUCCESS, 0); + if (cwmp_main->throttle_session_triggered == true) { + cwmp_main->throttle_session_triggered = false; + if (!cwmp_main->throttle_session) + uloop_timeout_cancel(&throttle_session_timer); + else + cwmp_main->throttle_session = false; + } rpc_exit(); } run_session_end_func(); @@ -426,9 +434,25 @@ void trigger_cwmp_session_timer() uloop_timeout_set(&session_timer, 10); } +void trigger_cwmp_throttle_session_timer(unsigned int delay) +{ + uloop_timeout_cancel(&retry_session_timer); + uloop_timeout_set(&throttle_session_timer, delay * 1000 + 10); +} + void cwmp_schedule_session(struct uloop_timeout *timeout __attribute__((unused))) { pthread_mutex_lock(&cwmp_session_mutex); + cwmp_main->throttle_session = false; + start_cwmp_session(); + pthread_mutex_unlock(&cwmp_session_mutex); +} + + +void cwmp_schedule_throttle_session(struct uloop_timeout *timeout __attribute__((unused))) +{ + pthread_mutex_lock(&cwmp_session_mutex); + cwmp_main->throttle_session = true; start_cwmp_session(); pthread_mutex_unlock(&cwmp_session_mutex); } diff --git a/src/session.h b/src/session.h index a68da39..6747aed 100644 --- a/src/session.h +++ b/src/session.h @@ -94,10 +94,12 @@ struct rpc *cwmp_add_session_rpc_acs(int type); struct rpc *cwmp_add_session_rpc_acs_head(int type); int cwmp_session_rpc_destructor(struct rpc *rpc); void trigger_cwmp_session_timer(); +void trigger_cwmp_throttle_session_timer(unsigned int delay); void trigger_session_by_ubus(char *event); void initiate_cwmp_periodic_session_feature(); int run_session_end_func(void); void cwmp_schedule_session(struct uloop_timeout *timeout); +void cwmp_schedule_throttle_session(struct uloop_timeout *timeout __attribute__((unused))); void cwmp_schedule_session_with_event(struct uloop_timeout *timeout); void trigger_cwmp_session_timer_with_event(struct uloop_timeout *timeout); void start_cwmp_session();