/*
 * Copyright (C) 2019-2024 IOPSYS Software Solutions AB. All rights reserved.
 *
 * Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
 *
 * See LICENSE file for license related information.
 */


#include <libbbfdm-api/dmcommon.h>

#define TRACEROUTE_DIAGNOSTIC_PATH BBFDM_SCRIPTS_PATH"/traceroute"
#define DOWNLOAD_DIAGNOSTIC_PATH BBFDM_SCRIPTS_PATH"/download"
#define UPLOAD_DIAGNOSTIC_PATH BBFDM_SCRIPTS_PATH"/upload"

static int browseIPDiagnosticsDownloadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
static int browseIPDiagnosticsUploadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);

/*************************************************************
* COMMON FUNCTIONS
**************************************************************/
static int get_diag_enable_true(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmstrdup("1");
	return 0;
}

static void stop_traceroute_diagnostics(void)
{
	char output[256] = {0}, cmd[256] = {0};

	snprintf(cmd, sizeof(cmd), "sh %s '{\"proto\":\"both_proto\",\"cancel\":\"1\"}'", TRACEROUTE_DIAGNOSTIC_PATH);

	run_cmd(cmd, output, sizeof(output));
}

/*************************************************************
* GET & SET PARAM
**************************************************************/
/*
 * *** Device.IP.Diagnostics.IPPing. ***
 */

static int get_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = diagnostics_get_option_fallback_def("ipping", "DiagnosticState", "None");
	if (DM_STRSTR(val, "Requested") != NULL)
		*value = dmstrdup("Requested");
	else
		*value = dmstrdup(val);

	return 0;
}

static int set_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, DiagnosticsState, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			if (DM_LSTRCMP(value, "Requested") == 0) {
				diagnostics_set_option("ipping", "DiagnosticState", value);
			} else if (DM_LSTRCMP(value, "Canceled") == 0) {
				diagnostics_set_option("ipping", "DiagnosticState", "None");
				dmubus_call_set("bbf.diag", "ipping", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			}
			return 0;
	}
	return 0;
}

static int get_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *linker = diagnostics_get_option("ipping", "interface");
	_bbfdm_get_references(ctx, "Device.IP.Interface.", "Name", linker, value);
	return 0;
}

static int set_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
	struct dm_reference reference = {0};

	bbfdm_get_reference_linker(ctx, value, &reference);

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
				return FAULT_9007;

			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
				return FAULT_9007;

			return 0;
		case VALUESET:
			diagnostics_reset_state("ipping");
			dmubus_call_set("bbf.diag", "ipping", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("ipping", "interface", reference.value);
			return 0;
	}
	return 0;
}

static int get_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "ProtocolVersion", "Any");
	return 0;
}

static int set_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ProtocolVersion[] = {"Any", "IPv4", "IPv6", NULL};

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, ProtocolVersion, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("ipping");
			dmubus_call_set("bbf.diag", "ipping", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("ipping", "ProtocolVersion", value);
			return 0;
	}
	return 0;
}

static int get_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("ipping", "Host");
	return 0;
}

static int set_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("ipping");
			dmubus_call_set("bbf.diag", "ipping", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("ipping", "Host", value);
			return 0;
	}
	return 0;
}

static int get_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "NumberOfRepetitions", "3");
	return 0;
}

static int set_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("ipping");
			dmubus_call_set("bbf.diag", "ipping", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("ipping", "NumberOfRepetitions", value);
			return 0;
	}
	return 0;
}

static int get_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "Timeout", "1000");
	return 0;
}

static int set_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("ipping");
			dmubus_call_set("bbf.diag", "ipping", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("ipping", "Timeout", value);
			return 0;
	}
	return 0;
}

static int get_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "DataBlockSize", "64");
	return 0;
}

static int set_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("ipping");
			dmubus_call_set("bbf.diag", "ipping", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("ipping", "DataBlockSize", value);
			return 0;
	}
	return 0;
}

static int get_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "DSCP", "0");
	return 0;
}

static int set_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","63"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("ipping");
			dmubus_call_set("bbf.diag", "ipping", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("ipping", "DSCP", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsIPPing_IPAddressUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("ipping", "IPAddressUsed");
	return 0;
}

static int get_ip_ping_success_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "SuccessCount", "0");
	return 0;
}

static int get_ip_ping_failure_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "FailureCount", "0");
	return 0;
}

static int get_ip_ping_average_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "AverageResponseTime", "0");
	return 0;
}

static int get_ip_ping_min_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "MinimumResponseTime", "0");
	return 0;
}

static int get_ip_ping_max_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "MaximumResponseTime", "0");
	return 0;
}

static int get_ip_ping_AverageResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "AverageResponseTimeDetailed", "0");
	return 0;
}

static int get_ip_ping_MinimumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "MinimumResponseTimeDetailed", "0");
	return 0;
}

static int get_ip_ping_MaximumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("ipping", "MaximumResponseTimeDetailed", "0");
	return 0;
}

/*
 * *** Device.IP.Diagnostics.TraceRoute. ***
 */

static int get_IPDiagnosticsTraceRoute_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = diagnostics_get_option_fallback_def("traceroute", "DiagnosticState", "None");
	if (DM_STRSTR(val, "Requested") != NULL)
		*value = dmstrdup("Requested");
	else
		*value = dmstrdup(val);

	return 0;
}

static int set_IPDiagnosticsTraceRoute_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, DiagnosticsState, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			if (DM_LSTRCMP(value, "Requested") == 0) {
				diagnostics_set_option("traceroute", "DiagnosticState", value);
			} else if (DM_LSTRCMP(value, "Canceled") == 0) {
				diagnostics_set_option("traceroute", "DiagnosticState", "None");
				stop_traceroute_diagnostics();
			}
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *linker = diagnostics_get_option("traceroute", "interface");
	_bbfdm_get_references(ctx, "Device.IP.Interface.", "Name", linker, value);
	return 0;
}

static int set_IPDiagnosticsTraceRoute_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
	struct dm_reference reference = {0};

	bbfdm_get_reference_linker(ctx, value, &reference);

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
				return FAULT_9007;

			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
				return FAULT_9007;

			return 0;
		case VALUESET:
			diagnostics_reset_state("traceroute");
			stop_traceroute_diagnostics();
			diagnostics_set_option("traceroute", "interface", reference.value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("traceroute", "ProtocolVersion", "Any");
	return 0;
}

static int set_IPDiagnosticsTraceRoute_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ProtocolVersion[] = {"Any", "IPv4", "IPv6", NULL};

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, ProtocolVersion, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("traceroute");
			stop_traceroute_diagnostics();
			diagnostics_set_option("traceroute", "ProtocolVersion", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("traceroute", "Host");
	return 0;
}

static int set_IPDiagnosticsTraceRoute_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("traceroute");
			stop_traceroute_diagnostics();
			diagnostics_set_option("traceroute", "Host", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_NumberOfTries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("traceroute", "NumberOfTries", "3");
	return 0;
}

static int set_IPDiagnosticsTraceRoute_NumberOfTries(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","3"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("traceroute");
			stop_traceroute_diagnostics();
			diagnostics_set_option("traceroute", "NumberOfTries", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("traceroute", "Timeout", "5000");
	return 0;
}

static int set_IPDiagnosticsTraceRoute_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("traceroute");
			stop_traceroute_diagnostics();
			diagnostics_set_option("traceroute", "Timeout", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("traceroute", "DataBlockSize", "38");
	return 0;
}

static int set_IPDiagnosticsTraceRoute_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("traceroute");
			stop_traceroute_diagnostics();
			diagnostics_set_option("traceroute", "DataBlockSize", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("traceroute", "DSCP", "0");
	return 0;
}

static int set_IPDiagnosticsTraceRoute_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","63"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("traceroute");
			stop_traceroute_diagnostics();
			diagnostics_set_option("traceroute", "DSCP", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_MaxHopCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("traceroute", "MaxHops", "30");
	return 0;
}

static int set_IPDiagnosticsTraceRoute_MaxHopCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","64"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("traceroute");
			stop_traceroute_diagnostics();
			diagnostics_set_option("traceroute", "MaxHops", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsTraceRoute_ResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("traceroute", "ResponseTime", "0");
	return 0;
}

static int get_IPDiagnosticsTraceRoute_IPAddressUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("traceroute", "IPAddressUsed");
	return 0;
}

static int get_IPDiagnosticsTraceRoute_RouteHopsNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("traceroute", "NumberOfHops", "0");
	return 0;
}

static int get_IPDiagnosticsTraceRouteRouteHops_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmuci_get_value_by_section_string((struct uci_section *)data, "host", value);
	return 0;
}

static int get_IPDiagnosticsTraceRouteRouteHops_HostAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmuci_get_value_by_section_string((struct uci_section *)data, "ip", value);
	return 0;
}

static int get_IPDiagnosticsTraceRouteRouteHops_ErrorCode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmstrdup("0");
	return 0;
}

static int get_IPDiagnosticsTraceRouteRouteHops_RTTimes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmuci_get_value_by_section_string((struct uci_section *)data, "time", value);
	return 0;
}

/*
 * *** Device.IP.Diagnostics.DownloadDiagnostics. ***
 */

static int get_IPDiagnosticsDownloadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "DiagnosticState", "None");
	return 0;
}

static int set_IPDiagnosticsDownloadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, DiagnosticsState, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			if (DM_LSTRCMP(value, "Requested") == 0)
				diagnostics_set_option("download", "DiagnosticState", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *linker = diagnostics_get_option("download", "interface");
	_bbfdm_get_references(ctx, "Device.IP.Interface.", "Name", linker, value);
	return 0;
}

static int set_IPDiagnosticsDownloadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
	struct dm_reference reference = {0};

	bbfdm_get_reference_linker(ctx, value, &reference);

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
				return FAULT_9007;

			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
				return FAULT_9007;

			return 0;
		case VALUESET:
			diagnostics_reset_state("download");
			diagnostics_set_option("download", "interface", reference.value);
	}
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_DownloadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("download", "url");
	return 0;
}

static int set_IPDiagnosticsDownloadDiagnostics_DownloadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("download");
			diagnostics_set_option("download", "url", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_DownloadTransports(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmstrdup("HTTP,FTP");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_DownloadDiagnosticMaxConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "DownloadDiagnosticMaxConnections", "1");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "DSCP", "0");
	return 0;
}

static int set_IPDiagnosticsDownloadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","63"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("download");
			diagnostics_set_option("download", "DSCP", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "ethernetpriority", "0");
	return 0;
}

static int set_IPDiagnosticsDownloadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","7"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("download");
			diagnostics_set_option("download", "ethernetpriority", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "ProtocolVersion", "Any");
	return 0;
}

static int set_IPDiagnosticsDownloadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ProtocolVersion[] = {"Any", "IPv4", "IPv6", NULL};

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, ProtocolVersion, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("download");
			diagnostics_set_option("download", "ProtocolVersion", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *def_cons = diagnostics_get_option_fallback_def("download", "DefaultNumberOfConnections", "1");
	*value = diagnostics_get_option_fallback_def("download", "NumberOfConnections", def_cons);
	return 0;
}

static int set_IPDiagnosticsDownloadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *max_con = NULL;

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;

			max_con = diagnostics_get_option_fallback_def("download", "DownloadDiagnosticMaxConnections", "1");
			if (DM_STRTOUL(max_con) < DM_STRTOUL(value))
				return FAULT_9007;

			return 0;
		case VALUESET:
			diagnostics_reset_state("download");
			diagnostics_set_option("download", "NumberOfConnections", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_IPAddressUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("download", "IPAddressUsed");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "ROMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "BOMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "EOMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_TestBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "TestBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "TotalBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "TotalBytesSent", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_TestBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "TestBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "TotalBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_TotalBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "TotalBytesSent", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_PeriodOfFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "PeriodOfFullLoading", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "TCPOpenRequestTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "TCPOpenResponseTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_PerConnectionResultNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	bool b;
	char *tmp = diagnostics_get_option("download", "EnablePerConnection");
	string_to_bool(tmp, &b);

	if (b) {
		int count = get_number_of_entries(ctx, data, instance, browseIPDiagnosticsDownloadDiagnosticsPerConnectionResultInst);
		dmasprintf(value, "%d", count);
	} else {
		*value = dmstrdup("0");
	}

	return 0;
}

static int get_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("download", "EnablePerConnection", "0");
	return 0;
}

static int set_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("download");
			diagnostics_set_option("download", "EnablePerConnection", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "ROMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "BOMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "EOMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TestBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "TestBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "TotalBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "TotalBytesSent", "0");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "TCPOpenRequestTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "TCPOpenResponseTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

/*
 * *** Device.IP.Diagnostics.UploadDiagnostics. ***
 */

static int get_IPDiagnosticsUploadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "DiagnosticState", "None");
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, DiagnosticsState, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			if (DM_LSTRCMP(value, "Requested") == 0)
				diagnostics_set_option("upload", "DiagnosticState", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *linker = diagnostics_get_option("upload", "interface");
	_bbfdm_get_references(ctx, "Device.IP.Interface.", "Name", linker, value);
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
	struct dm_reference reference = {0};

	bbfdm_get_reference_linker(ctx, value, &reference);

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
				return FAULT_9007;

			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
				return FAULT_9007;

			return 0;
		case VALUESET:
			diagnostics_reset_state("upload");
			diagnostics_set_option("upload", "interface", reference.value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_UploadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("upload", "url");
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_UploadURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("upload");
			diagnostics_set_option("upload", "url", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_UploadTransports(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmstrdup("HTTP,FTP");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "DSCP", "0");
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","63"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("upload");
			diagnostics_set_option("upload", "DSCP", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "ethernetpriority", "0");
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_EthernetPriority(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","7"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("upload");
			diagnostics_set_option("upload", "ethernetpriority", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TestFileLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TestFileLength", "0");
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_TestFileLength(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedLong(ctx, value, RANGE_ARGS{{NULL,NULL}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("upload");
			diagnostics_set_option("upload", "TestFileLength", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "ProtocolVersion", "Any");
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ProtocolVersion[] = {"Any", "IPv4", "IPv6", NULL};

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, ProtocolVersion, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("upload");
			diagnostics_set_option("upload", "ProtocolVersion", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_UploadDiagnosticMaxConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "UploadDiagnosticMaxConnections", "1");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *def_cons = diagnostics_get_option_fallback_def("upload", "DefaultNumberOfConnections", "1");
	*value = diagnostics_get_option_fallback_def("upload", "NumberOfConnections", def_cons);
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_NumberOfConnections(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *max_con = NULL;

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;

			max_con = diagnostics_get_option_fallback_def("upload", "UploadDiagnosticMaxConnections", "1");
			if (DM_STRTOUL(max_con) < DM_STRTOUL(value))
				return FAULT_9007;

			return 0;
		case VALUESET:
			diagnostics_reset_state("upload");
			diagnostics_set_option("upload", "NumberOfConnections", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_IPAddressUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("upload", "IPAddressUsed");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "ROMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "BOMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "EOMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TestBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TestBytesSent", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TotalBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TotalBytesSent", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TestBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TestBytesSent", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TotalBytesReceivedUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TotalBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TotalBytesSentUnderFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TotalBytesSent", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_PeriodOfFullLoading(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload","PeriodOfFullLoading", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TCPOpenRequestTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TCPOpenResponseTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_PerConnectionResultNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	bool b;
	char *tmp = diagnostics_get_option("upload", "EnablePerConnection");
	string_to_bool(tmp, &b);

	if (b) {
		int count = get_number_of_entries(ctx, data, instance, browseIPDiagnosticsUploadDiagnosticsPerConnectionResultInst);
		dmasprintf(value, "%d", count);
	} else {
		*value = dmstrdup("0");
	}

	return 0;
}

static int get_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "EnablePerConnection", "0");
	return 0;
}

static int set_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("upload");
			diagnostics_set_option("upload", "EnablePerConnection", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_ROMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "ROMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_BOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "BOMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_EOMTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "EOMTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TestBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "TestBytesSent", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "TotalBytesReceived", "0");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "TotalBytesSent", "0");
	return 0;

}

static int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenRequestTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TCPOpenRequestTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

static int get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("upload", "TCPOpenResponseTime", "0001-01-01T00:00:00.000000Z");
	return 0;
}

/*
 * *** Device.IP.Diagnostics.UDPEchoDiagnostics. ***
 */

static int get_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = diagnostics_get_option_fallback_def("udpechodiag", "DiagnosticState", "None");
	if (DM_STRSTR(val, "Requested") != NULL)
		*value = dmstrdup("Requested");
	else
		*value = dmstrdup(val);

	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, DiagnosticsState, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			if (DM_LSTRCMP(value, "Requested") == 0) {
				diagnostics_set_option("udpechodiag", "DiagnosticState", value);
			} else if (DM_LSTRCMP(value, "Canceled") == 0) {
				diagnostics_set_option("udpechodiag", "DiagnosticState", "None");
				dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			}
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *linker = diagnostics_get_option("udpechodiag", "interface");
	_bbfdm_get_references(ctx, "Device.IP.Interface.", "Name", linker, value);
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
	struct dm_reference reference = {0};

	bbfdm_get_reference_linker(ctx, value, &reference);

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
				return FAULT_9007;

			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
				return FAULT_9007;

			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "interface", reference.value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("udpechodiag", "Host");
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "Host", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "port", "7");
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "port", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "NumberOfRepetitions", "1");
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "NumberOfRepetitions", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "Timeout", "5000");
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "Timeout", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "DataBlockSize", "24");
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "DataBlockSize", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "DSCP", "0");
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","63"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "DSCP", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "InterTransmissionTime", "1000");
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "InterTransmissionTime", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "ProtocolVersion", "Any");
	return 0;
}

static int set_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ProtocolVersion[] = {"Any", "IPv4", "IPv6", NULL};

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, ProtocolVersion, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("udpechodiag");
			dmubus_call_set("bbf.diag", "udpecho", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("udpechodiag", "ProtocolVersion", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_IPAddressUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("udpechodiag", "IPAddressUsed");
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_SuccessCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "SuccessCount", "0");
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_FailureCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "FailureCount", "0");
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_AverageResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "AverageResponseTime", "0");
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_MinimumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "MinimumResponseTime", "0");
	return 0;
}

static int get_IPDiagnosticsUDPEchoDiagnostics_MaximumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("udpechodiag", "MaximumResponseTime", "0");
	return 0;
}

/*
 * *** Device.IP.Diagnostics.ServerSelectionDiagnostics. ***
 */

static int get_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = diagnostics_get_option_fallback_def("serverselection", "DiagnosticState", "None");
	if (DM_STRSTR(val, "Requested") != NULL)
		*value = dmstrdup("Requested");
	else
		*value = dmstrdup(val);

	return 0;
}

static int set_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, DiagnosticsState, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			if (DM_LSTRCMP(value, "Requested") == 0) {
				diagnostics_set_option("serverselection", "DiagnosticState", value);
			} else if (DM_LSTRCMP(value, "Canceled") == 0) {
				diagnostics_set_option("serverselection", "DiagnosticState", "None");
				dmubus_call_set("bbf.diag", "serverselection", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			}
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *linker = diagnostics_get_option("serverselection", "interface");
	_bbfdm_get_references(ctx, "Device.IP.Interface.", "Name", linker, value);
	return 0;
}

static int set_IPDiagnosticsServerSelectionDiagnostics_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
	struct dm_reference reference = {0};

	bbfdm_get_reference_linker(ctx, value, &reference);

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
				return FAULT_9007;

			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
				return FAULT_9007;

			return 0;
		case VALUESET:
			diagnostics_reset_state("serverselection");
			dmubus_call_set("bbf.diag", "serverselection", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("serverselection", "interface", reference.value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("serverselection", "ProtocolVersion", "Any");
	return 0;
}

static int set_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ProtocolVersion[] = {"Any", "IPv4", "IPv6", NULL};

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, ProtocolVersion, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("serverselection");
			dmubus_call_set("bbf.diag", "serverselection", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("serverselection", "ProtocolVersion", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("serverselection", "Protocol", "ICMP");
	return 0;
}

static int set_IPDiagnosticsServerSelectionDiagnostics_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ServerSelectionProtocol[] = {"ICMP", "UDP Echo", NULL};

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, ServerSelectionProtocol, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("serverselection");
			dmubus_call_set("bbf.diag", "serverselection", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("serverselection", "Protocol", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_HostList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("serverselection", "HostList");
	return 0;
}

static int set_IPDiagnosticsServerSelectionDiagnostics_HostList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string_list(ctx, value, -1, 10, -1, -1, 256, NULL, NULL))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("serverselection");
			dmubus_call_set("bbf.diag", "serverselection", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("serverselection", "HostList", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("serverselection", "NumberOfRepetitions", "3");
	return 0;
}

static int set_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("serverselection");
			dmubus_call_set("bbf.diag", "serverselection", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("serverselection", "NumberOfRepetitions", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("serverselection", "Timeout", "1000");
	return 0;
}

static int set_IPDiagnosticsServerSelectionDiagnostics_Timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
				return FAULT_9007;
			return 0;
		case VALUESET:
			diagnostics_reset_state("serverselection");
			dmubus_call_set("bbf.diag", "serverselection", UBUS_ARGS{{"cancel", "1", String},{"proto", "both_proto", String}}, 2);
			diagnostics_set_option("serverselection", "Timeout", value);
			return 0;
	}
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_FastestHost(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("serverselection", "FastestHost");
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_MinimumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("serverselection", "MinimumResponseTime", "0");
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_AverageResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("serverselection", "AverageResponseTime", "0");
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_MaximumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option_fallback_def("serverselection", "MaximumResponseTime", "0");
	return 0;
}

static int get_IPDiagnosticsServerSelectionDiagnostics_IPAddressUsed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = diagnostics_get_option("serverselection", "IPAddressUsed");
	return 0;
}

/*************************************************************
* ENTRY METHOD
**************************************************************/
static int browseIPDiagnosticsTraceRouteRouteHopsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	struct uci_section *s = NULL;
	char *inst = NULL;

	uci_path_foreach_sections(bbfdm, DMMAP_DIAGNOSTIGS, "RouteHops", s) {
		inst = handle_instance(dmctx, parent_node, s, "routehop_instance", "routehop_alias");
		if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIPDiagnosticsDownloadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	struct uci_section *s = NULL;
	char *inst = NULL;

	uci_path_foreach_sections(bbfdm, DMMAP_DIAGNOSTIGS, "DownloadPerConnection", s) {
		inst = handle_instance(dmctx, parent_node, s, "perconnection_instance", "perconnection_alias");
		if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIPDiagnosticsUploadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	struct uci_section *s = NULL;
	char *inst = NULL;

	uci_path_foreach_sections(bbfdm, DMMAP_DIAGNOSTIGS, "UploadPerConnection", s) {
		inst = handle_instance(dmctx, parent_node, s, "perconnection_instance", "perconnection_alias");
		if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, inst) == DM_STOP)
			break;
	}
	return 0;
}

/*************************************************************
 * OPERATE COMMANDS
 *************************************************************/
static operation_args ip_diagnostics_ipping_args = {
	.in = (const char *[]) {
		"Interface",
		"ProtocolVersion",
		"Host",
		"NumberOfRepetitions",
		"Timeout",
		"DataBlockSize",
		"DSCP",
		NULL
	},
	.out = (const char *[]) {
		"Status",
		"IPAddressUsed",
		"SuccessCount",
		"FailureCount",
		"AverageResponseTime",
		"MinimumResponseTime",
		"MaximumResponseTime",
		"AverageResponseTimeDetailed",
		"MinimumResponseTimeDetailed",
		"MaximumResponseTimeDetailed",
		NULL
	}
};

static int get_operate_args_IPDiagnostics_IPPing(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&ip_diagnostics_ipping_args;
	return 0;
}

static int operate_IPDiagnostics_IPPing(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	json_object *res = NULL;

	char *ipping_host = dmjson_get_value((json_object *)value, 1, "Host");
	if (ipping_host[0] == '\0') {
		bbfdm_set_fault_message(ctx, "IPPing: 'Host' input should be defined");
		return USP_FAULT_INVALID_ARGUMENT;
	}

	char *ip_interface = dmjson_get_value((json_object *)value, 1, "Interface");
	char *ipping_interface = diagnostics_get_interface_name(ctx, ip_interface);
	char *ipping_proto = dmjson_get_value((json_object *)value, 1, "ProtocolVersion");
	char *ipping_nbofrepetition = dmjson_get_value((json_object *)value, 1, "NumberOfRepetitions");
	char *ipping_timeout = dmjson_get_value((json_object *)value, 1, "Timeout");
	char *ipping_datablocksize = dmjson_get_value((json_object *)value, 1, "DataBlockSize");
	char *ipping_dscp = dmjson_get_value((json_object *)value, 1, "DSCP");
	char *proto = (ctx->dm_type == BBFDM_USP) ? "usp" : "both_proto";

	dmubus_call_blocking("bbf.diag", "ipping",
			UBUS_ARGS{
				{"host", ipping_host, String},
				{"iface", ipping_interface, String},
				{"ip_proto", ipping_proto, String},
				{"nbr_of_rep", ipping_nbofrepetition, String},
				{"timeout", ipping_timeout, String},
				{"data_size", ipping_datablocksize, String},
				{"dscp", ipping_dscp, String},
				{"proto", proto, String}
			},
			8, &res);

	if (res == NULL) {
		bbfdm_set_fault_message(ctx, "IPPing: ubus 'bbf.diag ipping' method doesn't exist");
		return USP_FAULT_COMMAND_FAILURE;
	}

	char *ipping_status = dmjson_get_value(res, 1, "Status");
	char *ipping_ip_address_used = dmjson_get_value(res, 1, "IPAddressUsed");
	char *ipping_success_count = dmjson_get_value(res, 1, "SuccessCount");
	char *ipping_failure_count = dmjson_get_value(res, 1, "FailureCount");
	char *ipping_average_response_time = dmjson_get_value(res, 1, "AverageResponseTime");
	char *ipping_minimum_response_time = dmjson_get_value(res, 1, "MinimumResponseTime");
	char *ipping_maximum_response_time = dmjson_get_value(res, 1, "MaximumResponseTime");
	char *ipping_average_response_time_detailed = dmjson_get_value(res, 1, "AverageResponseTimeDetailed");
	char *ipping_minimum_response_time_detailed = dmjson_get_value(res, 1, "MinimumResponseTimeDetailed");
	char *ipping_maximum_response_time_detailed = dmjson_get_value(res, 1, "MaximumResponseTimeDetailed");

	fill_blob_param(&ctx->bb, "Status", ipping_status, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "IPAddressUsed", ipping_ip_address_used, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "SuccessCount", ipping_success_count, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "FailureCount", ipping_failure_count, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "AverageResponseTime", ipping_average_response_time, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "MinimumResponseTime", ipping_minimum_response_time, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "MaximumResponseTime", ipping_maximum_response_time, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "AverageResponseTimeDetailed", ipping_average_response_time_detailed, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "MinimumResponseTimeDetailed", ipping_minimum_response_time_detailed, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "MaximumResponseTimeDetailed", ipping_maximum_response_time_detailed, DMT_TYPE[DMT_UNINT], 0);

	if (res != NULL)
		json_object_put(res);

	return 0;
}

static operation_args ip_diagnostics_trace_route_args = {
	.in = (const char *[]) {
		"Interface",
		"ProtocolVersion",
		"Host",
		"NumberOfTries",
		"Timeout",
		"DataBlockSize",
		"DSCP",
		"MaxHopCount",
		NULL
	},
	.out = (const char *[]) {
		"Status",
		"IPAddressUsed",
		"ResponseTime",
		"RouteHops.{i}.Host",
		"RouteHops.{i}.HostAddress",
		"RouteHops.{i}.ErrorCode",
		"RouteHops.{i}.RTTimes",
		NULL
	}
};

static int get_operate_args_IPDiagnostics_TraceRoute(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&ip_diagnostics_trace_route_args;
	return 0;
}

static int operate_IPDiagnostics_TraceRoute(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	json_object *arr_route_hops = NULL, *route_hops_obj = NULL;
	char input[2048] = {0};
	char output[2048] = {0};
	char cmd[2096] = {0};
	char buf[256] = {0};
	int idx = 0;

	char *host = dmjson_get_value((json_object *)value, 1, "Host");
	if (host[0] == '\0') {
		bbfdm_set_fault_message(ctx, "TraceRoute: 'Host' input should be defined");
		return USP_FAULT_INVALID_ARGUMENT;
	}

	char *ip_interface = dmjson_get_value((json_object *)value, 1, "Interface");
	char *interface = diagnostics_get_interface_name(ctx, ip_interface);
	char *ip_proto = dmjson_get_value((json_object *)value, 1, "ProtocolVersion");
	char *nboftries = dmjson_get_value((json_object *)value, 1, "NumberOfTries");
	char *timeout = dmjson_get_value((json_object *)value, 1, "Timeout");
	char *datablocksize = dmjson_get_value((json_object *)value, 1, "DataBlockSize");
	char *dscp = dmjson_get_value((json_object *)value, 1, "DSCP");
	char *maxhops = dmjson_get_value((json_object *)value, 1, "MaxHopCount");

	snprintf(input, sizeof(input), "'{\"host\": \"%s\",\"iface\":\"%s\",\"ip_proto\":\"%s\",\"nbr_of_tries\":\"%s\",\"timeout\":\"%s\",\"data_size\":\"%s\",\"dscp\":\"%s\",\"max_hop_cnt\":\"%s\",\"proto\":\"%s\"}'",
									host,
									interface,
									ip_proto,
									nboftries,
									timeout,
									datablocksize,
									dscp,
									maxhops,
									(ctx->dm_type == BBFDM_USP) ? "usp" : "both_proto");

	snprintf(cmd, sizeof(cmd), "sh %s %s", TRACEROUTE_DIAGNOSTIC_PATH, input);

	if (run_cmd(cmd, output, sizeof(output)) != 0) {
		bbfdm_set_fault_message(ctx, "TraceRoute: 'sh %s {input}' command failed to run", TRACEROUTE_DIAGNOSTIC_PATH);
		return USP_FAULT_COMMAND_FAILURE;
	}

	json_object *res = (DM_STRLEN(output)) ? json_tokener_parse(output) : NULL;

	if (res == NULL) {
		bbfdm_set_fault_message(ctx, "TraceRoute: there is no output from '%s' script", TRACEROUTE_DIAGNOSTIC_PATH);
		return USP_FAULT_COMMAND_FAILURE;
	}

	char *status = dmjson_get_value(res, 1, "Status");
	char *ip_address_used = dmjson_get_value(res, 1, "IPAddressUsed");
	char *response_time = dmjson_get_value(res, 1, "ResponseTime");
	fill_blob_param(&ctx->bb, "Status", status, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "IPAddressUsed", ip_address_used, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "ResponseTime", response_time, DMT_TYPE[DMT_UNINT], 0);

	dmjson_foreach_obj_in_array(res, arr_route_hops, route_hops_obj, idx, 1, "RouteHops") {
		int i = idx + 1;

		snprintf(buf, sizeof(buf), "RouteHops.%d.Host", i);
		char *route_hops_host = dmjson_get_value(route_hops_obj, 1, "Host");
		fill_blob_param(&ctx->bb, buf, route_hops_host, DMT_TYPE[DMT_STRING], 0);

		snprintf(buf, sizeof(buf), "RouteHops.%d.HostAddress", i);
		char *route_hops_host_address = dmjson_get_value(route_hops_obj, 1, "HostAddress");
		fill_blob_param(&ctx->bb, buf, route_hops_host_address, DMT_TYPE[DMT_STRING], 0);

		snprintf(buf, sizeof(buf), "RouteHops.%d.RTTimes", i);
		char *route_hops_rttimes = dmjson_get_value(route_hops_obj, 1, "RTTimes");
		fill_blob_param(&ctx->bb, buf, route_hops_rttimes, DMT_TYPE[DMT_STRING], 0);

		snprintf(buf, sizeof(buf), "RouteHops.%d.ErrorCode", i);
		fill_blob_param(&ctx->bb, buf, "0", DMT_TYPE[DMT_UNINT], 0);
	}

	if (res != NULL)
		json_object_put(res);

	return 0;
}

static operation_args ip_diagnostics_download_args = {
	.in = (const char *[]) {
		"Interface",
		"DownloadURL",
		"DSCP",
		"EthernetPriority",
		"TimeBasedTestDuration",
		"TimeBasedTestMeasurementInterval",
		"TimeBasedTestMeasurementOffset",
		"ProtocolVersion",
		"NumberOfConnections",
		"EnablePerConnectionResults",
		NULL
	},
	.out = (const char *[]) {
		"Status",
		"IPAddressUsed",
		"ROMTime",
		"BOMTime",
		"EOMTime",
		"TestBytesReceived",
		"TotalBytesReceived",
		"TotalBytesSent",
		"TestBytesReceivedUnderFullLoading",
		"TotalBytesReceivedUnderFullLoading",
		"TotalBytesSentUnderFullLoading",
		"PeriodOfFullLoading",
		"TCPOpenRequestTime",
		"TCPOpenResponseTime",
		"PerConnectionResult.{i}.ROMTime",
		"PerConnectionResult.{i}.BOMTime",
		"PerConnectionResult.{i}.EOMTime",
		"PerConnectionResult.{i}.TestBytesReceived",
		"PerConnectionResult.{i}.TotalBytesReceived",
		"PerConnectionResult.{i}.TotalBytesSent",
		"PerConnectionResult.{i}.TCPOpenRequestTime",
		"PerConnectionResult.{i}.TCPOpenResponseTime",
		"IncrementalResult.{i}.TestBytesReceived",
		"IncrementalResult.{i}.TotalBytesReceived",
		"IncrementalResult.{i}.TotalBytesSent",
		"IncrementalResult.{i}.StartTime",
		"IncrementalResult.{i}.EndTime",
		NULL
	}
};

static int get_operate_args_IPDiagnostics_DownloadDiagnostics(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&ip_diagnostics_download_args;
	return 0;
}

static int operate_IPDiagnostics_DownloadDiagnostics(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char input[2048] = {0};
	char output[4096] = {0};
	char cmd[2096] = {0};
	char *download_url = dmjson_get_value((json_object *)value, 1, "DownloadURL");

	if (download_url[0] == '\0') {
		bbfdm_set_fault_message(ctx, "DownloadDiagnostics: 'DownloadURL' input should be defined");
		return USP_FAULT_INVALID_ARGUMENT;
	}

	if (strncmp(download_url, HTTP_URI, strlen(HTTP_URI)) != 0 &&
		strncmp(download_url, FTP_URI, strlen(FTP_URI)) != 0 &&
		strchr(download_url,'@') != NULL) {
		bbfdm_set_fault_message(ctx, "DownloadDiagnostics: '%s' DownloadURL is not a correct url value", download_url);
		return USP_FAULT_INVALID_ARGUMENT;
	}

	char *ip_interface = dmjson_get_value((json_object *)value, 1, "Interface");
	char *download_interface = diagnostics_get_interface_name(ctx, ip_interface);
	char *download_dscp = dmjson_get_value((json_object *)value, 1, "DSCP");
	char *download_ethernet_priority = dmjson_get_value((json_object *)value, 1, "EthernetPriority");
	char *download_proto = dmjson_get_value((json_object *)value, 1, "ProtocolVersion");

	char *download_num_of_connections = dmjson_get_value((json_object *)value, 1, "NumberOfConnections");
	if (DM_STRLEN(download_num_of_connections) == 0 || DM_STRTOL(download_num_of_connections) == 0) {
		download_num_of_connections = diagnostics_get_option_fallback_def("download", "DefaultNumberOfConnections", "1");
	} else {
		char *max_con = diagnostics_get_option_fallback_def("download", "DownloadDiagnosticMaxConnections", "1");

		if (DM_STRTOUL(max_con) < DM_STRTOUL(download_num_of_connections)) {
			bbfdm_set_fault_message(ctx, "DownloadDiagnostics: NumberOfConnection should not greater than Max supported");
			return USP_FAULT_INVALID_ARGUMENT;
		}
	}

	char *download_enable_per_connection_results = dmjson_get_value((json_object *)value, 1, "EnablePerConnectionResults");

	snprintf(input, sizeof(input), "'{\"url\": \"%s\",\"iface\":\"%s\",\"dscp\":\"%s\",\"eth_prio\":\"%s\",\"ip_proto\":\"%s\",\"num_of_con\":\"%s\",\"enable_per_con\":\"%s\",\"proto\":\"%s\"}'",
									download_url,
									download_interface,
									download_dscp,
									download_ethernet_priority,
									download_proto,
									download_num_of_connections,
									download_enable_per_connection_results,
									(ctx->dm_type == BBFDM_USP) ? "usp" : "both_proto");

	snprintf(cmd, sizeof(cmd), "sh %s %s", DOWNLOAD_DIAGNOSTIC_PATH, input);

	if (run_cmd(cmd, output, sizeof(output)) != 0) {
		bbfdm_set_fault_message(ctx, "DownloadDiagnostics: 'sh %s {input}' command failed to run", DOWNLOAD_DIAGNOSTIC_PATH);
		return USP_FAULT_COMMAND_FAILURE;
	}

	json_object *res = (DM_STRLEN(output)) ? json_tokener_parse(output) : NULL;

	if (res == NULL) {
		bbfdm_set_fault_message(ctx, "DownloadDiagnostics: there is no output from '%s' script", DOWNLOAD_DIAGNOSTIC_PATH);
		return USP_FAULT_COMMAND_FAILURE;
	}

	char *status = dmjson_get_value(res, 1, "Status");
	char *ip_address_used = dmjson_get_value(res, 1, "IPAddressUsed");
	char *rom_time = dmjson_get_value(res, 1, "ROMTime");
	char *bom_time = dmjson_get_value(res, 1, "BOMTime");
	char *eom_time = dmjson_get_value(res, 1, "EOMTime");
	char *test_bytes_received = dmjson_get_value(res, 1, "TestBytesReceived");
	char *total_bytes_received = dmjson_get_value(res, 1, "TotalBytesReceived");
	char *total_bytes_sent = dmjson_get_value(res, 1, "TotalBytesSent");
	char *period_of_full_loading = dmjson_get_value(res, 1, "PeriodOfFullLoading");
	char *tcp_open_request_time = dmjson_get_value(res, 1, "TCPOpenRequestTime");
	char *tcp_open_response_time = dmjson_get_value(res, 1, "TCPOpenResponseTime");

	fill_blob_param(&ctx->bb, "Status", status, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "IPAddressUsed", ip_address_used, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "ROMTime", rom_time[0] != 0 ? rom_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);
	fill_blob_param(&ctx->bb, "BOMTime", bom_time[0] != 0 ? bom_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);
	fill_blob_param(&ctx->bb, "EOMTime", eom_time[0] != 0 ? eom_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);
	fill_blob_param(&ctx->bb, "TestBytesReceived", test_bytes_received, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TotalBytesReceived", total_bytes_received, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TotalBytesSent", total_bytes_sent, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TestBytesReceivedUnderFullLoading", test_bytes_received, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TotalBytesReceivedUnderFullLoading", total_bytes_received, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TotalBytesSentUnderFullLoading", total_bytes_sent, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "PeriodOfFullLoading", period_of_full_loading, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TCPOpenRequestTime", tcp_open_request_time[0] != 0 ? tcp_open_request_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);
	fill_blob_param(&ctx->bb, "TCPOpenResponseTime", tcp_open_response_time[0] != 0 ? tcp_open_response_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);

	json_object *json_arr = NULL, *json_obj = NULL;
	int idx = 0;
	bool per_con_res = false;

	string_to_bool(download_enable_per_connection_results, &per_con_res);
	if (per_con_res) {
		const char *params[] = { "ROMTime", "BOMTime", "EOMTime", "TestBytesReceived", "TotalBytesReceived", "TotalBytesSent", "TCPOpenRequestTime", "TCPOpenResponseTime", NULL };
		int types[] = { DMT_TIME, DMT_TIME, DMT_TIME, DMT_UNINT, DMT_UNINT, DMT_UNINT, DMT_TIME, DMT_TIME};
		dmjson_foreach_obj_in_array(res, json_arr, json_obj, idx, 1, "DownloadPerConnection") {
			char buffer[128] = {0};
			const char *itr = NULL, *val = NULL;
			if (json_obj == NULL) {
				break;
			}

			for (int i = 0; i < ARRAY_SIZE(types); i++) {
				itr = params[i];
				snprintf(buffer, sizeof(buffer), "PerConnectionResult.%d.%s", idx + 1, itr);
				val = dmjson_get_value(json_obj, 1, itr);
				if (DM_STRLEN(val) == 0) {
					continue;
				}
				fill_blob_param(&ctx->bb, buffer, val, DMT_TYPE[types[i]], 0);
			}
		}
	}

	if (res != NULL)
		json_object_put(res);

	return 0;
}

static operation_args ip_diagnostics_upload_args = {
	.in = (const char *[]) {
		"Interface",
		"UploadURL",
		"DSCP",
		"EthernetPriority",
		"TestFileLength",
		"TimeBasedTestDuration",
		"TimeBasedTestMeasurementInterval",
		"TimeBasedTestMeasurementOffset",
		"ProtocolVersion",
		"NumberOfConnections",
		"EnablePerConnectionResults",
		NULL
	},
	.out = (const char *[]) {
		"Status",
		"IPAddressUsed",
		"ROMTime",
		"BOMTime",
		"EOMTime",
		"TestBytesSent",
		"TotalBytesReceived",
		"TotalBytesSent",
		"TestBytesSentUnderFullLoading",
		"TotalBytesReceivedUnderFullLoading",
		"TotalBytesSentUnderFullLoading",
		"PeriodOfFullLoading",
		"TCPOpenRequestTime",
		"TCPOpenResponseTime",
		"PerConnectionResult.{i}.ROMTime",
		"PerConnectionResult.{i}.BOMTime",
		"PerConnectionResult.{i}.EOMTime",
		"PerConnectionResult.{i}.TestBytesSent",
		"PerConnectionResult.{i}.TotalBytesReceived",
		"PerConnectionResult.{i}.TotalBytesSent",
		"PerConnectionResult.{i}.TCPOpenRequestTime",
		"PerConnectionResult.{i}.TCPOpenResponseTime",
		"IncrementalResult.{i}.TestBytesSent",
		"IncrementalResult.{i}.TotalBytesReceived",
		"IncrementalResult.{i}.TotalBytesSent",
		"IncrementalResult.{i}.StartTime",
		"IncrementalResult.{i}.EndTime",
		NULL
	}
};

static int get_operate_args_IPDiagnostics_UploadDiagnostics(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&ip_diagnostics_upload_args;
	return 0;
}

static int operate_IPDiagnostics_UploadDiagnostics(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char input[2048] = {0};
	char output[2048] = {0};
	char cmd[2096] = {0};
	char *upload_url = dmjson_get_value((json_object *)value, 1, "UploadURL");

	if (upload_url[0] == '\0') {
		bbfdm_set_fault_message(ctx, "UploadDiagnostics: 'UploadURL' input should be defined");
		return USP_FAULT_INVALID_ARGUMENT;
	}

	if (strncmp(upload_url, HTTP_URI, strlen(HTTP_URI)) != 0 &&
		strncmp(upload_url, FTP_URI, strlen(FTP_URI)) != 0 &&
		strchr(upload_url,'@') != NULL)
		return USP_FAULT_INVALID_ARGUMENT;

	char *upload_test_file_length = dmjson_get_value((json_object *)value, 1, "TestFileLength");
	if (upload_test_file_length[0] == '\0') {
		bbfdm_set_fault_message(ctx, "UploadDiagnostics: 'TestFileLength' input should be defined");
		return USP_FAULT_INVALID_ARGUMENT;
	}

	char *ip_interface = dmjson_get_value((json_object *)value, 1, "Interface");
	char *upload_interface = diagnostics_get_interface_name(ctx, ip_interface);
	char *upload_dscp = dmjson_get_value((json_object *)value, 1, "DSCP");
	char *upload_ethernet_priority = dmjson_get_value((json_object *)value, 1, "EthernetPriority");
	char *upload_proto = dmjson_get_value((json_object *)value, 1, "ProtocolVersion");

	char *upload_num_of_connections = dmjson_get_value((json_object *)value, 1, "NumberOfConnections");
	if (DM_STRLEN(upload_num_of_connections) == 0 || DM_STRTOL(upload_num_of_connections) == 0) {
		upload_num_of_connections = diagnostics_get_option_fallback_def("upload", "DefaultNumberOfConnections", "1");
	} else {
		char *max_con = diagnostics_get_option_fallback_def("upload", "UploadDiagnosticMaxConnections", "1");

		if (DM_STRTOUL(max_con) < DM_STRTOUL(upload_num_of_connections)) {
			bbfdm_set_fault_message(ctx, "UploadDiagnostics: NumberOfConnection should not greater than Max supported");
			return USP_FAULT_INVALID_ARGUMENT;
		}
	}

	char *upload_enable_per_connection_results = dmjson_get_value((json_object *)value, 1, "EnablePerConnectionResults");

	snprintf(input, sizeof(input), "'{\"url\": \"%s\",\"iface\":\"%s\",\"dscp\":\"%s\",\"eth_prio\":\"%s\",\"file_length\":\"%s\",\"ip_proto\":\"%s\",\"num_of_con\":\"%s\",\"enable_per_con\":\"%s\",\"proto\":\"%s\"}'",
			upload_url,
									upload_interface,
									upload_dscp,
									upload_ethernet_priority,
									upload_test_file_length,
									upload_proto,
									upload_num_of_connections,
									upload_enable_per_connection_results,
									(ctx->dm_type == BBFDM_USP) ? "usp" : "both_proto");

	snprintf(cmd, sizeof(cmd), "sh %s %s", UPLOAD_DIAGNOSTIC_PATH, input);

	if (run_cmd(cmd, output, sizeof(output)) != 0) {
		bbfdm_set_fault_message(ctx, "UploadDiagnostics: 'sh %s {input}' command failed to run", UPLOAD_DIAGNOSTIC_PATH);
		return USP_FAULT_COMMAND_FAILURE;
	}

	json_object *res = (DM_STRLEN(output)) ? json_tokener_parse(output) : NULL;

	if (res == NULL) {
		bbfdm_set_fault_message(ctx, "UploadDiagnostics: there is no output from '%s' script", UPLOAD_DIAGNOSTIC_PATH);
		return USP_FAULT_COMMAND_FAILURE;
	}

	char *upload_status = dmjson_get_value(res, 1, "Status");
	char *upload_ip_address_used = dmjson_get_value(res, 1, "IPAddressUsed");
	char *upload_rom_time = dmjson_get_value(res, 1, "ROMTime");
	char *upload_bom_time = dmjson_get_value(res, 1, "BOMTime");
	char *upload_eom_time = dmjson_get_value(res, 1, "EOMTime");
	char *upload_test_bytes_sent = dmjson_get_value(res, 1, "TestBytesSent");
	char *upload_total_bytes_received = dmjson_get_value(res, 1, "TotalBytesReceived");
	char *upload_total_bytes_sent = dmjson_get_value(res, 1, "TotalBytesSent");
	char *upload_period_of_full_loading = dmjson_get_value(res, 1, "PeriodOfFullLoading");
	char *upload_tcp_open_request_time = dmjson_get_value(res, 1, "TCPOpenRequestTime");
	char *upload_tcp_open_response_time = dmjson_get_value(res, 1, "TCPOpenResponseTime");

	fill_blob_param(&ctx->bb, "Status", upload_status, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "IPAddressUsed", upload_ip_address_used, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "ROMTime", upload_rom_time[0] != 0 ? upload_rom_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);
	fill_blob_param(&ctx->bb, "BOMTime", upload_bom_time[0] != 0 ? upload_bom_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);
	fill_blob_param(&ctx->bb, "EOMTime", upload_eom_time[0] != 0 ? upload_eom_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);
	fill_blob_param(&ctx->bb, "TestBytesSent", upload_test_bytes_sent, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TotalBytesReceived", upload_total_bytes_received, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TotalBytesSent", upload_total_bytes_sent, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TestBytesSentUnderFullLoading", upload_test_bytes_sent, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TotalBytesReceivedUnderFullLoading", upload_total_bytes_received, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TotalBytesSentUnderFullLoading", upload_total_bytes_sent, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "PeriodOfFullLoading", upload_period_of_full_loading, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "TCPOpenRequestTime", upload_tcp_open_request_time[0] != 0 ? upload_tcp_open_request_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);
	fill_blob_param(&ctx->bb, "TCPOpenResponseTime", upload_tcp_open_response_time[0] != 0 ? upload_tcp_open_response_time : "0001-01-01T00:00:00.000000Z", DMT_TYPE[DMT_TIME], 0);

	json_object *json_arr = NULL, *json_obj = NULL;
	int idx = 0;
	bool per_con_res = false;

	string_to_bool(upload_enable_per_connection_results, &per_con_res);
	if (per_con_res) {
		const char *params[] = { "ROMTime", "BOMTime", "EOMTime", "TestBytesSent", "TotalBytesReceived", "TotalBytesSent", "TCPOpenRequestTime", "TCPOpenResponseTime", NULL };
		int types[] = { DMT_TIME, DMT_TIME, DMT_TIME, DMT_UNINT, DMT_UNINT, DMT_UNINT, DMT_TIME, DMT_TIME};
		dmjson_foreach_obj_in_array(res, json_arr, json_obj, idx, 1, "UploadPerConnection") {
			char buffer[128] = {0};
			const char *itr = NULL, *val = NULL;
			if (json_obj == NULL) {
				break;
			}

			for (int i = 0; i < ARRAY_SIZE(types); i++) {
				itr = params[i];
				snprintf(buffer, sizeof(buffer), "PerConnectionResult.%d.%s", idx + 1, itr);
				val = dmjson_get_value(json_obj, 1, itr);
				if (DM_STRLEN(val) == 0) {
					continue;
				}
				fill_blob_param(&ctx->bb, buffer, val, DMT_TYPE[types[i]], 0);
			}
		}
	}

	if (res != NULL)
		json_object_put(res);

	return 0;
}

static operation_args ip_diagnostics_udpecho_args = {
	.in = (const char *[]) {
		"Interface",
		"Host",
		"Port",
		"NumberOfRepetitions",
		"Timeout",
		"DataBlockSize",
		"DSCP",
		"InterTransmissionTime",
		"ProtocolVersion",
		"EnableIndividualPacketResults",
		NULL
	},
	.out = (const char *[]) {
		"Status",
		"IPAddressUsed",
		"SuccessCount",
		"FailureCount",
		"AverageResponseTime",
		"MinimumResponseTime",
		"MaximumResponseTime",
		"IndividualPacketResult.{i}.PacketSuccess",
		"IndividualPacketResult.{i}.PacketSendTime",
		"IndividualPacketResult.{i}.PacketReceiveTime",
		"IndividualPacketResult.{i}.TestGenSN",
		"IndividualPacketResult.{i}.TestRespSN",
		"IndividualPacketResult.{i}.TestRespRcvTimeStamp",
		"IndividualPacketResult.{i}.TestRespReplyTimeStamp",
		"IndividualPacketResult.{i}.TestRespReplyFailureCount",
		NULL
	}
};

static int get_operate_args_IPDiagnostics_UDPEchoDiagnostics(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&ip_diagnostics_udpecho_args;
	return 0;
}

static int operate_IPDiagnostics_UDPEchoDiagnostics(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	json_object *res = NULL;

	char *udpecho_host = dmjson_get_value((json_object *)value, 1, "Host");
	if (udpecho_host[0] == '\0') {
		bbfdm_set_fault_message(ctx, "UDPEchoDiagnostics: 'Host' input should be defined");
		return USP_FAULT_INVALID_ARGUMENT;
	}

	char *udpecho_port = dmjson_get_value((json_object *)value, 1, "Port");
	char *ip_interface = dmjson_get_value((json_object *)value, 1, "Interface");
	char *udpecho_interface = diagnostics_get_interface_name(ctx, ip_interface);
	char *udpecho_proto = dmjson_get_value((json_object *)value, 1, "ProtocolVersion");
	char *udpecho_nbofrepetition = dmjson_get_value((json_object *)value, 1, "NumberOfRepetitions");
	char *udpecho_timeout = dmjson_get_value((json_object *)value, 1, "Timeout");
	char *udpecho_datablocksize = dmjson_get_value((json_object *)value, 1, "DataBlockSize");
	char *udpecho_dscp = dmjson_get_value((json_object *)value, 1, "DSCP");
	char *udpecho_inter_transmission_time = dmjson_get_value((json_object *)value, 1, "InterTransmissionTime");
	char *proto = (ctx->dm_type == BBFDM_USP) ? "usp" : "both_proto";

	dmubus_call_blocking("bbf.diag", "udpecho",
			UBUS_ARGS{
				{"host", udpecho_host, String},
				{"port", udpecho_port, String},
				{"iface", udpecho_interface, String},
				{"ip_proto", udpecho_proto, String},
				{"nbr_of_rep", udpecho_nbofrepetition, String},
				{"timeout", udpecho_timeout, String},
				{"data_size", udpecho_datablocksize, String},
				{"dscp", udpecho_dscp, String},
				{"inter_trans_time", udpecho_inter_transmission_time, String},
				{"proto", proto, String}
			},
			10, &res);

	if (res == NULL) {
		bbfdm_set_fault_message(ctx, "UDPEchoDiagnostics: ubus 'bbf.diag udpecho' method doesn't exist");
		return USP_FAULT_COMMAND_FAILURE;
	}

	char *status = dmjson_get_value(res, 1, "Status");
	char *ip_address_used = dmjson_get_value(res, 1, "IPAddressUsed");
	char *udpecho_success_count = dmjson_get_value(res, 1, "SuccessCount");
	char *udpecho_failure_count = dmjson_get_value(res, 1, "FailureCount");
	char *udpecho_average_response_time = dmjson_get_value(res, 1, "AverageResponseTime");
	char *udpecho_minimum_response_time = dmjson_get_value(res, 1, "MinimumResponseTime");
	char *udpecho_maximum_response_time = dmjson_get_value(res, 1, "MaximumResponseTime");

	fill_blob_param(&ctx->bb, "Status", status, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "IPAddressUsed", ip_address_used, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "SuccessCount", udpecho_success_count, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "FailureCount", udpecho_failure_count, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "AverageResponseTime", udpecho_average_response_time, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "MinimumResponseTime", udpecho_minimum_response_time, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "MaximumResponseTime", udpecho_maximum_response_time, DMT_TYPE[DMT_UNINT], 0);

	if (res != NULL)
		json_object_put(res);

	return 0;
}

static operation_args ip_diagnostics_server_selection_args = {
	.in = (const char *[]) {
		"Interface",
		"ProtocolVersion",
		"Protocol",
		"HostList",
		"NumberOfRepetitions",
		"Timeout",
		NULL
	},
	.out = (const char *[]) {
		"Status",
		"FastestHost",
		"MinimumResponseTime",
		"AverageResponseTime",
		"MaximumResponseTime",
		"IPAddressUsed",
		NULL
	}
};

static int get_operate_args_IPDiagnostics_ServerSelectionDiagnostics(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&ip_diagnostics_server_selection_args;
	return 0;
}

static int operate_IPDiagnostics_ServerSelectionDiagnostics(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	json_object *res = NULL;

	char *hostlist = dmjson_get_value((json_object *)value, 1, "HostList");
	if (hostlist[0] == '\0') {
		bbfdm_set_fault_message(ctx, "ServerSelectionDiagnostics: 'HostList' input should be defined");
		return USP_FAULT_INVALID_ARGUMENT;
	}

	char *port = dmjson_get_value((json_object *)value, 1, "Port");
	char *protocol_used = dmjson_get_value((json_object *)value, 1, "Protocol");
	char *protocol_version = dmjson_get_value((json_object *)value, 1, "ProtocolVersion");
	char *ip_interface = dmjson_get_value((json_object *)value, 1, "Interface");
	char *interface = diagnostics_get_interface_name(ctx, ip_interface);
	char *nbofrepetition = dmjson_get_value((json_object *)value, 1, "NumberOfRepetitions");
	char *timeout = dmjson_get_value((json_object *)value, 1, "Timeout");
	char *proto = (ctx->dm_type == BBFDM_USP) ? "usp" : "both_proto";

	dmubus_call_blocking("bbf.diag", "serverselection",
			UBUS_ARGS{
				{"hostlist", hostlist, String},
				{"port", port, String},
				{"iface", interface, String},
				{"ip_proto", protocol_version, String},
				{"nbr_of_rep", nbofrepetition, String},
				{"timeout", timeout, String},
				{"protocol_used", protocol_used, String},
				{"proto", proto, String}
			},
			8, &res);

	if (res == NULL) {
		bbfdm_set_fault_message(ctx, "ServerSelectionDiagnostics: ubus 'bbf.diag serverselection' method doesn't exist");
		return USP_FAULT_COMMAND_FAILURE;
	}

	char *status = dmjson_get_value(res, 1, "Status");
	char *fasthost = dmjson_get_value(res, 1, "FastestHost");
	char *average_response_time = dmjson_get_value(res, 1, "AverageResponseTime");
	char *minimum_response_time = dmjson_get_value(res, 1, "MinimumResponseTime");
	char *maximum_response_time = dmjson_get_value(res, 1, "MaximumResponseTime");
	char *ip_address_used = dmjson_get_value(res, 1, "IPAddressUsed");

	fill_blob_param(&ctx->bb, "Status", status, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "FastestHost", fasthost, DMT_TYPE[DMT_STRING], 0);
	fill_blob_param(&ctx->bb, "AverageResponseTime", average_response_time, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "MinimumResponseTime", minimum_response_time, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "MaximumResponseTime", maximum_response_time, DMT_TYPE[DMT_UNINT], 0);
	fill_blob_param(&ctx->bb, "IPAddressUsed", ip_address_used, DMT_TYPE[DMT_STRING], 0);

	if (res != NULL)
		json_object_put(res);

	return 0;
}

/**********************************************************************************************************************************
*                                            OBJ & LEAF DEFINITION
***********************************************************************************************************************************/

/* *** Device.IP.Diagnostics.IPPing. *** */
DMLEAF tIPDiagnosticsIPPingParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"DiagnosticsState", &DMWRITE, DMT_STRING, get_ip_ping_diagnostics_state, set_ip_ping_diagnostics_state, BBFDM_CWMP},
{"Interface", &DMWRITE, DMT_STRING, get_ip_ping_interface, set_ip_ping_interface, BBFDM_CWMP, DM_FLAG_REFERENCE},
{"ProtocolVersion", &DMWRITE, DMT_STRING, get_ip_ping_protocolversion, set_ip_ping_protocolversion, BBFDM_CWMP},
{"Host", &DMWRITE, DMT_STRING, get_ip_ping_host, set_ip_ping_host, BBFDM_CWMP},
{"NumberOfRepetitions", &DMWRITE, DMT_UNINT, get_ip_ping_repetition_number, set_ip_ping_repetition_number, BBFDM_CWMP},
{"Timeout", &DMWRITE, DMT_UNINT, get_ip_ping_timeout, set_ip_ping_timeout, BBFDM_CWMP},
{"DataBlockSize", &DMWRITE, DMT_UNINT, get_ip_ping_block_size, set_ip_ping_block_size, BBFDM_CWMP},
{"DSCP", &DMWRITE, DMT_UNINT, get_ip_ping_DSCP, set_ip_ping_DSCP, BBFDM_CWMP},
{"IPAddressUsed", &DMREAD, DMT_STRING, get_IPDiagnosticsIPPing_IPAddressUsed, NULL, BBFDM_CWMP},
{"SuccessCount", &DMREAD, DMT_UNINT, get_ip_ping_success_count, NULL, BBFDM_CWMP},
{"FailureCount", &DMREAD, DMT_UNINT, get_ip_ping_failure_count, NULL, BBFDM_CWMP},
{"AverageResponseTime", &DMREAD, DMT_UNINT, get_ip_ping_average_response_time, NULL, BBFDM_CWMP},
{"MinimumResponseTime", &DMREAD, DMT_UNINT, get_ip_ping_min_response_time, NULL, BBFDM_CWMP},
{"MaximumResponseTime", &DMREAD, DMT_UNINT, get_ip_ping_max_response_time, NULL, BBFDM_CWMP},
{"AverageResponseTimeDetailed", &DMREAD, DMT_UNINT, get_ip_ping_AverageResponseTimeDetailed, NULL, BBFDM_CWMP},
{"MinimumResponseTimeDetailed", &DMREAD, DMT_UNINT, get_ip_ping_MinimumResponseTimeDetailed, NULL, BBFDM_CWMP},
{"MaximumResponseTimeDetailed", &DMREAD, DMT_UNINT, get_ip_ping_MaximumResponseTimeDetailed, NULL, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics.TraceRoute.RouteHops.{i}. *** */
DMLEAF tIPDiagnosticsTraceRouteRouteHopsParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"Host", &DMREAD, DMT_STRING, get_IPDiagnosticsTraceRouteRouteHops_Host, NULL, BBFDM_CWMP},
{"HostAddress", &DMREAD, DMT_STRING, get_IPDiagnosticsTraceRouteRouteHops_HostAddress, NULL, BBFDM_CWMP},
{"ErrorCode", &DMREAD, DMT_UNINT, get_IPDiagnosticsTraceRouteRouteHops_ErrorCode, NULL, BBFDM_CWMP},
{"RTTimes", &DMREAD, DMT_STRING, get_IPDiagnosticsTraceRouteRouteHops_RTTimes, NULL, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics.TraceRoute. *** */
DMOBJ tIPDiagnosticsTraceRouteObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"RouteHops", &DMREAD, NULL, NULL, NULL, browseIPDiagnosticsTraceRouteRouteHopsInst, NULL, NULL, NULL, tIPDiagnosticsTraceRouteRouteHopsParams, NULL, BBFDM_CWMP},
{0}
};

DMLEAF tIPDiagnosticsTraceRouteParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsTraceRoute_DiagnosticsState, set_IPDiagnosticsTraceRoute_DiagnosticsState, BBFDM_CWMP},
{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsTraceRoute_Interface, set_IPDiagnosticsTraceRoute_Interface, BBFDM_CWMP, DM_FLAG_REFERENCE},
{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsTraceRoute_ProtocolVersion, set_IPDiagnosticsTraceRoute_ProtocolVersion, BBFDM_CWMP},
{"Host", &DMWRITE, DMT_STRING, get_IPDiagnosticsTraceRoute_Host, set_IPDiagnosticsTraceRoute_Host, BBFDM_CWMP},
{"NumberOfTries", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_NumberOfTries, set_IPDiagnosticsTraceRoute_NumberOfTries, BBFDM_CWMP},
{"Timeout", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_Timeout, set_IPDiagnosticsTraceRoute_Timeout, BBFDM_CWMP},
{"DataBlockSize", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_DataBlockSize, set_IPDiagnosticsTraceRoute_DataBlockSize, BBFDM_CWMP},
{"DSCP", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_DSCP, set_IPDiagnosticsTraceRoute_DSCP, BBFDM_CWMP},
{"MaxHopCount", &DMWRITE, DMT_UNINT, get_IPDiagnosticsTraceRoute_MaxHopCount, set_IPDiagnosticsTraceRoute_MaxHopCount, BBFDM_CWMP},
{"ResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsTraceRoute_ResponseTime, NULL, BBFDM_CWMP},
{"IPAddressUsed", &DMREAD, DMT_STRING, get_IPDiagnosticsTraceRoute_IPAddressUsed, NULL, BBFDM_CWMP},
{"RouteHopsNumberOfEntries", &DMREAD, DMT_UNINT, get_IPDiagnosticsTraceRoute_RouteHopsNumberOfEntries, NULL, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics.DownloadDiagnostics.PerConnectionResult.{i}. *** */
DMLEAF tIPDiagnosticsDownloadDiagnosticsPerConnectionResultParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"ROMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_ROMTime, NULL, BBFDM_CWMP},
{"BOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_BOMTime, NULL, BBFDM_CWMP},
{"EOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_EOMTime, NULL, BBFDM_CWMP},
{"TestBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TestBytesReceived, NULL, BBFDM_CWMP},
{"TotalBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesReceived, NULL, BBFDM_CWMP},
{"TotalBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TotalBytesSent, NULL, BBFDM_CWMP},
{"TCPOpenRequestTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenRequestTime, NULL, BBFDM_CWMP},
{"TCPOpenResponseTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnosticsPerConnectionResult_TCPOpenResponseTime, NULL, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics.DownloadDiagnostics. *** */
DMOBJ tIPDiagnosticsDownloadDiagnosticsObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"PerConnectionResult", &DMREAD, NULL, NULL, NULL, browseIPDiagnosticsDownloadDiagnosticsPerConnectionResultInst, NULL, NULL, NULL, tIPDiagnosticsDownloadDiagnosticsPerConnectionResultParams, NULL, BBFDM_CWMP},
{0}
};

DMLEAF tIPDiagnosticsDownloadDiagnosticsParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_DiagnosticsState, set_IPDiagnosticsDownloadDiagnostics_DiagnosticsState, BBFDM_CWMP},
{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_Interface, set_IPDiagnosticsDownloadDiagnostics_Interface, BBFDM_CWMP, DM_FLAG_REFERENCE},
{"DownloadURL", &DMWRITE, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_DownloadURL, set_IPDiagnosticsDownloadDiagnostics_DownloadURL, BBFDM_CWMP},
{"DownloadTransports", &DMREAD, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_DownloadTransports, NULL, BBFDM_CWMP},
{"DownloadDiagnosticMaxConnections", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_DownloadDiagnosticMaxConnections,NULL, BBFDM_CWMP},
{"DSCP", &DMWRITE, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_DSCP, set_IPDiagnosticsDownloadDiagnostics_DSCP, BBFDM_CWMP},
{"EthernetPriority", &DMWRITE, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_EthernetPriority, set_IPDiagnosticsDownloadDiagnostics_EthernetPriority, BBFDM_CWMP},
{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_ProtocolVersion, set_IPDiagnosticsDownloadDiagnostics_ProtocolVersion, BBFDM_CWMP},
{"NumberOfConnections", &DMWRITE, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_NumberOfConnections, set_IPDiagnosticsDownloadDiagnostics_NumberOfConnections, BBFDM_CWMP},
{"IPAddressUsed", &DMREAD, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_IPAddressUsed, NULL, BBFDM_CWMP},
{"ROMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_ROMTime, NULL, BBFDM_CWMP},
{"BOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_BOMTime, NULL, BBFDM_CWMP},
{"EOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_EOMTime, NULL, BBFDM_CWMP},
{"TestBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TestBytesReceived, NULL, BBFDM_CWMP},
{"TotalBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceived, NULL, BBFDM_CWMP},
{"TotalBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TotalBytesSent, NULL, BBFDM_CWMP},
{"TestBytesReceivedUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TestBytesReceivedUnderFullLoading, NULL, BBFDM_CWMP},
{"TotalBytesReceivedUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TotalBytesReceivedUnderFullLoading, NULL, BBFDM_CWMP},
{"TotalBytesSentUnderFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_TotalBytesSentUnderFullLoading, NULL, BBFDM_CWMP},
{"PeriodOfFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_PeriodOfFullLoading, NULL, BBFDM_CWMP},
{"TCPOpenRequestTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_TCPOpenRequestTime, NULL, BBFDM_CWMP},
{"TCPOpenResponseTime", &DMREAD, DMT_TIME, get_IPDiagnosticsDownloadDiagnostics_TCPOpenResponseTime, NULL, BBFDM_CWMP},
{"PerConnectionResultNumberOfEntries", &DMREAD, DMT_UNINT, get_IPDiagnosticsDownloadDiagnostics_PerConnectionResultNumberOfEntries, NULL, BBFDM_CWMP},
{"EnablePerConnectionResults", &DMWRITE, DMT_BOOL, get_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults, set_IPDiagnosticsDownloadDiagnostics_EnablePerConnectionResults, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics.UploadDiagnostics.PerConnectionResult.{i}. *** */
DMLEAF tIPDiagnosticsUploadDiagnosticsPerConnectionResultParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"ROMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_ROMTime, NULL, BBFDM_CWMP},
{"BOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_BOMTime, NULL, BBFDM_CWMP},
{"EOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_EOMTime, NULL, BBFDM_CWMP},
{"TestBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TestBytesSent, NULL, BBFDM_CWMP},
{"TotalBytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesReceived, NULL, BBFDM_CWMP},
{"TotalBytesSent", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TotalBytesSent, NULL, BBFDM_CWMP},
{"TCPOpenRequestTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenRequestTime, NULL, BBFDM_CWMP},
{"TCPOpenResponseTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnosticsPerConnectionResult_TCPOpenResponseTime, NULL, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics.UploadDiagnostics. *** */
DMOBJ tIPDiagnosticsUploadDiagnosticsObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"PerConnectionResult", &DMREAD, NULL, NULL, NULL, browseIPDiagnosticsUploadDiagnosticsPerConnectionResultInst, NULL, NULL, NULL, tIPDiagnosticsUploadDiagnosticsPerConnectionResultParams, NULL, BBFDM_CWMP},
{0}
};

DMLEAF tIPDiagnosticsUploadDiagnosticsParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_DiagnosticsState, set_IPDiagnosticsUploadDiagnostics_DiagnosticsState, BBFDM_CWMP},
{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_Interface, set_IPDiagnosticsUploadDiagnostics_Interface, BBFDM_CWMP, DM_FLAG_REFERENCE},
{"UploadURL", &DMWRITE, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_UploadURL, set_IPDiagnosticsUploadDiagnostics_UploadURL, BBFDM_CWMP},
{"UploadTransports", &DMREAD, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_UploadTransports, NULL, BBFDM_CWMP},
{"DSCP", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_DSCP, set_IPDiagnosticsUploadDiagnostics_DSCP, BBFDM_CWMP},
{"EthernetPriority", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_EthernetPriority, set_IPDiagnosticsUploadDiagnostics_EthernetPriority, BBFDM_CWMP},
{"TestFileLength", &DMWRITE, DMT_UNLONG, get_IPDiagnosticsUploadDiagnostics_TestFileLength, set_IPDiagnosticsUploadDiagnostics_TestFileLength, BBFDM_CWMP},
{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_ProtocolVersion, set_IPDiagnosticsUploadDiagnostics_ProtocolVersion, BBFDM_CWMP},
{"NumberOfConnections", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_NumberOfConnections, set_IPDiagnosticsUploadDiagnostics_NumberOfConnections, BBFDM_CWMP},
{"UploadDiagnosticsMaxConnections", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_UploadDiagnosticMaxConnections,NULL, BBFDM_CWMP},
{"IPAddressUsed", &DMREAD, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_IPAddressUsed, NULL, BBFDM_CWMP},
{"ROMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_ROMTime, NULL, BBFDM_CWMP},
{"BOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_BOMTime, NULL, BBFDM_CWMP},
{"EOMTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_EOMTime, NULL, BBFDM_CWMP},
{"TestBytesSent", &DMREAD, DMT_UNLONG, get_IPDiagnosticsUploadDiagnostics_TestBytesSent, NULL, BBFDM_CWMP},
{"TotalBytesReceived", &DMREAD, DMT_UNLONG, get_IPDiagnosticsUploadDiagnostics_TotalBytesReceived, NULL, BBFDM_CWMP},
{"TotalBytesSent", &DMREAD, DMT_UNLONG, get_IPDiagnosticsUploadDiagnostics_TotalBytesSent, NULL, BBFDM_CWMP},
{"TestBytesSentUnderFullLoading", &DMREAD, DMT_UNLONG, get_IPDiagnosticsUploadDiagnostics_TestBytesSentUnderFullLoading, NULL, BBFDM_CWMP},
{"TotalBytesReceivedUnderFullLoading", &DMREAD, DMT_UNLONG, get_IPDiagnosticsUploadDiagnostics_TotalBytesReceivedUnderFullLoading, NULL, BBFDM_CWMP},
{"TotalBytesSentUnderFullLoading", &DMREAD, DMT_UNLONG, get_IPDiagnosticsUploadDiagnostics_TotalBytesSentUnderFullLoading, NULL, BBFDM_CWMP},
{"PeriodOfFullLoading", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_PeriodOfFullLoading, NULL, BBFDM_CWMP},
{"TCPOpenRequestTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_TCPOpenRequestTime, NULL, BBFDM_CWMP},
{"TCPOpenResponseTime", &DMREAD, DMT_TIME, get_IPDiagnosticsUploadDiagnostics_TCPOpenResponseTime, NULL, BBFDM_CWMP},
{"PerConnectionResultNumberOfEntries", &DMREAD, DMT_UNINT, get_IPDiagnosticsUploadDiagnostics_PerConnectionResultNumberOfEntries, NULL, BBFDM_CWMP},
{"EnablePerConnectionResults", &DMWRITE, DMT_BOOL, get_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults, set_IPDiagnosticsUploadDiagnostics_EnablePerConnectionResults, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics.UDPEchoDiagnostics. *** */
DMLEAF tIPDiagnosticsUDPEchoDiagnosticsParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState, set_IPDiagnosticsUDPEchoDiagnostics_DiagnosticsState, BBFDM_CWMP},
{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_Interface, set_IPDiagnosticsUDPEchoDiagnostics_Interface, BBFDM_CWMP, DM_FLAG_REFERENCE},
{"Host", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_Host, set_IPDiagnosticsUDPEchoDiagnostics_Host, BBFDM_CWMP},
{"Port", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_Port, set_IPDiagnosticsUDPEchoDiagnostics_Port, BBFDM_CWMP},
{"NumberOfRepetitions", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions, set_IPDiagnosticsUDPEchoDiagnostics_NumberOfRepetitions, BBFDM_CWMP},
{"Timeout", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_Timeout, set_IPDiagnosticsUDPEchoDiagnostics_Timeout, BBFDM_CWMP},
{"DataBlockSize", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize, set_IPDiagnosticsUDPEchoDiagnostics_DataBlockSize, BBFDM_CWMP},
{"DSCP", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_DSCP, set_IPDiagnosticsUDPEchoDiagnostics_DSCP, BBFDM_CWMP},
{"InterTransmissionTime", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime, set_IPDiagnosticsUDPEchoDiagnostics_InterTransmissionTime, BBFDM_CWMP},
{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion, set_IPDiagnosticsUDPEchoDiagnostics_ProtocolVersion, BBFDM_CWMP},
{"IPAddressUsed", &DMREAD, DMT_STRING, get_IPDiagnosticsUDPEchoDiagnostics_IPAddressUsed, NULL, BBFDM_CWMP},
{"SuccessCount", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_SuccessCount, NULL, BBFDM_CWMP},
{"FailureCount", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_FailureCount, NULL, BBFDM_CWMP},
{"AverageResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_AverageResponseTime, NULL, BBFDM_CWMP},
{"MinimumResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_MinimumResponseTime, NULL, BBFDM_CWMP},
{"MaximumResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoDiagnostics_MaximumResponseTime, NULL, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics.ServerSelectionDiagnostics. *** */
DMLEAF tIPDiagnosticsServerSelectionDiagnosticsParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"DiagnosticsState", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState, set_IPDiagnosticsServerSelectionDiagnostics_DiagnosticsState, BBFDM_CWMP},
{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_Interface, set_IPDiagnosticsServerSelectionDiagnostics_Interface, BBFDM_CWMP, DM_FLAG_REFERENCE},
{"ProtocolVersion", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion, set_IPDiagnosticsServerSelectionDiagnostics_ProtocolVersion, BBFDM_CWMP},
{"Protocol", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_Protocol, set_IPDiagnosticsServerSelectionDiagnostics_Protocol, BBFDM_CWMP},
{"HostList", &DMWRITE, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_HostList, set_IPDiagnosticsServerSelectionDiagnostics_HostList, BBFDM_CWMP},
{"NumberOfRepetitions", &DMWRITE, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions, set_IPDiagnosticsServerSelectionDiagnostics_NumberOfRepetitions, BBFDM_CWMP},
{"Timeout", &DMWRITE, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_Timeout, set_IPDiagnosticsServerSelectionDiagnostics_Timeout, BBFDM_CWMP},
{"FastestHost", &DMREAD, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_FastestHost, NULL, BBFDM_CWMP},
{"MinimumResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_MinimumResponseTime, NULL, BBFDM_CWMP},
{"AverageResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_AverageResponseTime, NULL, BBFDM_CWMP},
{"MaximumResponseTime", &DMREAD, DMT_UNINT, get_IPDiagnosticsServerSelectionDiagnostics_MaximumResponseTime, NULL, BBFDM_CWMP},
{"IPAddressUsed", &DMREAD, DMT_STRING, get_IPDiagnosticsServerSelectionDiagnostics_IPAddressUsed, NULL, BBFDM_CWMP},
{0}
};

/* *** Device.IP.Diagnostics. *** */
DMOBJ tDeviceIPDiagnosticsObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"IPPing", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsIPPingParams, NULL, BBFDM_CWMP},
{"TraceRoute", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsTraceRouteObj, tIPDiagnosticsTraceRouteParams, NULL, BBFDM_CWMP},
{"DownloadDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsDownloadDiagnosticsObj, tIPDiagnosticsDownloadDiagnosticsParams, NULL, BBFDM_CWMP},
{"UploadDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsUploadDiagnosticsObj, tIPDiagnosticsUploadDiagnosticsParams, NULL, BBFDM_CWMP},
{"UDPEchoDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsUDPEchoDiagnosticsParams, NULL, BBFDM_CWMP},
{"ServerSelectionDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsServerSelectionDiagnosticsParams, NULL, BBFDM_CWMP},
{0}
};

DMLEAF tDeviceIPDiagnosticsParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"IPv4PingSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv6PingSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv4TraceRouteSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv6TraceRouteSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv4DownloadDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv6DownloadDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv4UploadDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv6UploadDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true,  NULL, BBFDM_BOTH},
{"IPv4UDPEchoDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv6UDPEchoDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv4ServerSelectionDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPv6ServerSelectionDiagnosticsSupported", &DMREAD, DMT_BOOL, get_diag_enable_true, NULL, BBFDM_BOTH},
{"IPPing()", &DMASYNC, DMT_COMMAND, get_operate_args_IPDiagnostics_IPPing, operate_IPDiagnostics_IPPing, BBFDM_USP},
{"TraceRoute()", &DMASYNC, DMT_COMMAND, get_operate_args_IPDiagnostics_TraceRoute, operate_IPDiagnostics_TraceRoute, BBFDM_USP},
{"DownloadTransports", &DMREAD, DMT_STRING, get_IPDiagnosticsDownloadDiagnostics_DownloadTransports, NULL, BBFDM_USP},
{"DownloadDiagnostics()", &DMASYNC, DMT_COMMAND, get_operate_args_IPDiagnostics_DownloadDiagnostics, operate_IPDiagnostics_DownloadDiagnostics, BBFDM_USP},
{"UploadTransports", &DMREAD, DMT_STRING, get_IPDiagnosticsUploadDiagnostics_UploadTransports, NULL, BBFDM_USP},
{"UploadDiagnostics()", &DMASYNC, DMT_COMMAND, get_operate_args_IPDiagnostics_UploadDiagnostics, operate_IPDiagnostics_UploadDiagnostics, BBFDM_USP},
{"UDPEchoDiagnostics()", &DMASYNC, DMT_COMMAND, get_operate_args_IPDiagnostics_UDPEchoDiagnostics, operate_IPDiagnostics_UDPEchoDiagnostics, BBFDM_USP},
{"ServerSelectionDiagnostics()", &DMASYNC, DMT_COMMAND, get_operate_args_IPDiagnostics_ServerSelectionDiagnostics, operate_IPDiagnostics_ServerSelectionDiagnostics, BBFDM_USP},
{0}
};

/* *** Device.IP. *** */
DMOBJ tDeviceIPObjs[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"Diagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceIPDiagnosticsObj, tDeviceIPDiagnosticsParams, NULL, BBFDM_BOTH, NULL},
{0}
};

/* ********** DynamicObj ********** */
DM_MAP_OBJ tDynamicObj[] = {
/* parentobj, nextobject, parameter */
{"Device.IP.", tDeviceIPObjs, NULL},
{0}
};
