/*
 * Copyright (C) 2021 iopsys Software Solutions AB
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation
 *
 *      Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
 *      Author: Nevadita Chatterjee <nevadita.chatterjee@iopsys.eu>
 */

#include "libbbfdm-api/dmcommon.h"

struct ieee1905_device_nonieee1905neighbor_args
{
	char *mac_addr;
	char *neighbor;
};

struct ieee1905_device_ieee1905neighbor_args
{
	char *mac_addr;
	char *neighbor_device_id;
	char *num_metrics;
};

/*************************************************************
* ENTRY METHOD
**************************************************************/
static int browseIEEE1905ALInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *res = NULL, *interface_obj = NULL, *arrobj = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmubus_call("ieee1905", "info", UBUS_ARGS{0}, 0, &res);
	dmjson_foreach_obj_in_array(res, arrobj, interface_obj, i, 1, "interface") {

		curr_data.json_object = interface_obj;

		inst = handle_instance_without_section(dmctx, parent_node, ++id);

		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905ALInterfaceLinkInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *arrobj = NULL, *link_obj = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, arrobj, link_obj, i, 1, "links") {

		curr_data.json_object = link_obj;

		inst = handle_instance_without_section(dmctx, parent_node, ++id);

		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905ALNetworkTopologyIEEE1905DeviceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *res = NULL, *device_obj = NULL, *arrobj = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmubus_call("ieee1905", "info", UBUS_ARGS{0}, 0, &res);
	if (!res)
		return 0;

	// Self node in the network
	curr_data.json_object = res;
	inst = handle_instance_without_section(dmctx, parent_node, ++id);
	if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
		return 0;

	// Discovered 1905 Devices in the network
	dmjson_foreach_obj_in_array(res, arrobj, device_obj, i, 2, "topology", "device") {
		curr_data.json_object = device_obj;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}

	return 0;
}

static int browseIEEE1905ALNetworkTopologyIEEE1905DeviceIPv4AddressInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *ip4arrobj = NULL, *ipv4_address = NULL, *ifacearrobj = NULL, *interface = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0, j = 0;

	if (DM_STRCMP(prev_instance, "1") == 0) { // Self node in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, ifacearrobj, interface, i, 1, "interface") {
			curr_data.additional_data = (void *)dmjson_get_value(interface, 1, "macaddress");
			dmjson_foreach_obj_in_array(interface, ip4arrobj, ipv4_address, j, 1, "ipv4_address") {
				curr_data.json_object = ipv4_address;
				inst = handle_instance_without_section(dmctx, parent_node, ++id);
				if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
					goto end;
			}
		}
	} else { // Discovered 1905 Devices in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, ip4arrobj, ipv4_address, i, 1, "ipv4_address") {
			curr_data.additional_data = (void *)dmjson_get_value(ipv4_address, 1, "macaddress");
			curr_data.json_object = ipv4_address;
			inst = handle_instance_without_section(dmctx, parent_node, ++id);
			if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
				break;
		}
	}

end:
	return 0;
}

static int browseIEEE1905ALNetworkTopologyIEEE1905DeviceIPv6AddressInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *ip6arrobj = NULL, *ipv6_address = NULL, *ifacearrobj = NULL, *interface = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0, j = 0;

	if (DM_STRCMP(prev_instance, "1") == 0) { // Self node in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, ifacearrobj, interface, i, 1, "interface") {
			curr_data.additional_data = (void *)dmjson_get_value(interface, 1, "macaddress");
			dmjson_foreach_obj_in_array(interface, ip6arrobj, ipv6_address, j, 1, "ipv6_address") {
				curr_data.json_object = ipv6_address;
				inst = handle_instance_without_section(dmctx, parent_node, ++id);
				if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
					goto end;
			}
		}
	} else { // Discovered 1905 Devices in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, ip6arrobj, ipv6_address, i, 1, "ipv6_address") {
			curr_data.additional_data = (void *)dmjson_get_value(ipv6_address, 1, "macaddress");
			curr_data.json_object = ipv6_address;
			inst = handle_instance_without_section(dmctx, parent_node, ++id);
			if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
				break;
		}
	}

end:
	return 0;
}

static int browseIEEE1905ALNetworkTopologyIEEE1905DeviceInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *arrobj = NULL, *interface = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, arrobj, interface, i, 1, "interface") {
		curr_data.json_object = interface;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905NeighborInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *non1905arrobj = NULL, *non1905 = NULL, *ifacearrobj = NULL, *interface = NULL, *neighbor_val = NULL;
	struct ieee1905_device_nonieee1905neighbor_args curr_nonieee1905neighbor_args = {0};
	struct dm_data curr_data = {0};
	char *inst = NULL, *neighbor = NULL;
	int id = 0, i = 0, j = 0;

	if (DM_STRCMP(prev_instance, "1") == 0) { // Self node in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, ifacearrobj, interface, i, 1, "interface") {
			curr_nonieee1905neighbor_args.mac_addr = dmjson_get_value(interface, 1, "macaddress");
			dmjson_foreach_value_in_array(interface, neighbor_val, neighbor, j, 1, "non1905_neighbors") {
				curr_nonieee1905neighbor_args.neighbor = neighbor;

				curr_data.additional_data = (void *)&curr_nonieee1905neighbor_args;

				inst = handle_instance_without_section(dmctx, parent_node, ++id);
				if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
					goto end;
			}
		}
	} else { // Discovered 1905 Devices in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, non1905arrobj, non1905, i, 1, "non1905_neighbors") {
			curr_nonieee1905neighbor_args.mac_addr = dmjson_get_value(non1905, 1, "interface_macaddress");
			dmjson_foreach_value_in_array(non1905, neighbor_val, neighbor, j, 1, "neighbors") {
				curr_nonieee1905neighbor_args.neighbor = neighbor;

				curr_data.additional_data = (void *)&curr_nonieee1905neighbor_args;

				inst = handle_instance_without_section(dmctx, parent_node, ++id);
				if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
					goto end;
			}
		}
	}

end:
	return 0;
}

static int browseIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *ieee1905_neighborsarrobj = NULL, *ieee1905_neighbors = NULL, *ifacearrobj = NULL, *interface = NULL;
	struct ieee1905_device_ieee1905neighbor_args curr_ieee1905_neighbors_args = {0};
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0, j = 0;

	if (DM_STRCMP(prev_instance, "1") == 0) { // Self node in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, ifacearrobj, interface, i, 1, "interface") {
			curr_ieee1905_neighbors_args.mac_addr = dmjson_get_value(interface, 1, "macaddress");
			dmjson_foreach_obj_in_array(interface, ieee1905_neighborsarrobj, ieee1905_neighbors, j, 1, "links") {
				bool direct = dmuci_string_to_boolean(dmjson_get_value(ieee1905_neighbors, 1, "direct"));

				if (direct == false)
					continue;

				curr_ieee1905_neighbors_args.neighbor_device_id = dmjson_get_value(ieee1905_neighbors, 1, "ieee1905id");
				curr_ieee1905_neighbors_args.num_metrics = "1";

				curr_data.json_object = ieee1905_neighbors;
				curr_data.additional_data = (void *)&curr_ieee1905_neighbors_args;

				inst = handle_instance_without_section(dmctx, parent_node, ++id);
				if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
					goto end;
			}
		}
	} else { // Discovered 1905 Devices in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, ieee1905_neighborsarrobj, ieee1905_neighbors, i, 1, "ieee1905_neighbors") {
			curr_ieee1905_neighbors_args.mac_addr = dmjson_get_value(ieee1905_neighbors, 1, "macaddress");
			curr_ieee1905_neighbors_args.neighbor_device_id = dmjson_get_value(ieee1905_neighbors, 1, "neighbor_device_id");
			curr_ieee1905_neighbors_args.num_metrics = dmjson_get_value(ieee1905_neighbors, 1, "num_metrics");

			curr_data.json_object = ieee1905_neighbors;
			curr_data.additional_data = (void *)&curr_ieee1905_neighbors_args;

			inst = handle_instance_without_section(dmctx, parent_node, ++id);
			if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
				break;
		}
	}

end:
	return 0;
}

static int browseIEEE1905ALNetworkTopologyIEEE1905DeviceBridgingTupleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *arrobj = NULL, *bridge_tuple = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, arrobj, bridge_tuple, i, 1, "bridge_tuples") {
		curr_data.json_object = bridge_tuple;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetricInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *arrobj = NULL, *metric = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	json_object_object_get_ex(((struct dm_data *)prev_data)->json_object, "metric", &metric);
	if (metric && json_object_get_type(metric) == json_type_array) { // Discovered 1905 Devices in the network
		dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, arrobj, metric, i, 1, "metric") {
			curr_data.json_object = metric;
			curr_data.additional_data = (void *)dmjson_get_value(metric, 1, "neighbor_macaddress");

			inst = handle_instance_without_section(dmctx, parent_node, ++id);
			if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
				break;
		}
	} else { // Self node in the network
		curr_data.json_object = metric;
		curr_data.additional_data = (void *)dmjson_get_value(((struct dm_data *)prev_data)->json_object, 1, "macaddress");

		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			goto end;
	}

end:
	return 0;
}

static int browseIEEE1905NetworkALInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *res = NULL, *node_obj = NULL, *arrobj = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmubus_call("ieee1905.topology", "dump", UBUS_ARGS{0}, 0, &res);
	if (!res)
		return 0;

	dmjson_foreach_obj_in_array(res, arrobj, node_obj, i, 1, "nodes") {
		curr_data.json_object = node_obj;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905NetworkALIPv4AddressInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *arrobj = NULL, *ipv4 = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, arrobj, ipv4, i, 1, "ipv4_address") {
		curr_data.json_object = ipv4;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905NetworkALIPv6AddressInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *arrobj = NULL, *ipv6 = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, arrobj, ipv6, i, 1, "ipv6_address") {
		curr_data.json_object = ipv6;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905NetworkALInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *arrobj = NULL, *interface = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, arrobj, interface, i, 1, "interface") {
		curr_data.json_object = interface;
		curr_data.additional_data = (void *)((struct dm_data *)prev_data)->json_object;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905NetworkALBridgingTupleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *arrobj = NULL, *bridge_tuple = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	dmjson_foreach_obj_in_array(((struct dm_data *)prev_data)->json_object, arrobj, bridge_tuple, i, 1, "bridge_tuples") {
		curr_data.json_object = bridge_tuple;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

/* With bridged (duplicate-MAC) interfaces the same neighbor 'via' MAC matches
 * every interface that shares that MAC, so a link/neighbor would otherwise be
 * listed on each of them. Report it only on the first interface (in array order)
 * that carries the MAC and suppress it on the rest.
 */
static bool is_primary_iface_for_mac(json_object *node, json_object *interface, const char *ifmac)
{
	json_object *arrobj = NULL, *iface = NULL;
	int i = 0;

	if (!node || !interface || !ifmac || !*ifmac)
		return true;

	dmjson_foreach_obj_in_array(node, arrobj, iface, i, 1, "interface") {
		if (DM_STRCMP(dmjson_get_value(iface, 1, "macaddress"), ifmac) == 0)
			return (iface == interface);
	}

	return true;
}

static int browseIEEE1905NetworkALInterfaceLinkInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *node = (json_object *)((struct dm_data *)prev_data)->additional_data;
	json_object *interface = ((struct dm_data *)prev_data)->json_object;
	char *ifmac = dmjson_get_value(interface, 1, "macaddress");
	json_object *arrobj = NULL, *nbr = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	if (!is_primary_iface_for_mac(node, interface, ifmac))
		return 0;

	dmjson_foreach_obj_in_array(node, arrobj, nbr, i, 1, "ieee1905_neighbors") {
		char *via = dmjson_get_value(nbr, 1, "via");

		if (DM_STRCMP(via, ifmac) != 0)
			continue;

		curr_data.json_object = nbr;
		curr_data.additional_data = (void *)interface;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905NetworkALInterfaceNonIEEE1905NeighborInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *node = (json_object *)((struct dm_data *)prev_data)->additional_data;
	json_object *interface = ((struct dm_data *)prev_data)->json_object;
	char *ifmac = dmjson_get_value(interface, 1, "macaddress");
	json_object *arrobj = NULL, *nbr = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	if (!is_primary_iface_for_mac(node, interface, ifmac))
		return 0;

	dmjson_foreach_obj_in_array(node, arrobj, nbr, i, 1, "non1905_neighbors") {
		char *via = dmjson_get_value(nbr, 1, "via");

		if (DM_STRCMP(via, ifmac) != 0)
			continue;

		curr_data.json_object = nbr;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseIEEE1905NetworkALInterfaceIEEE1905NeighborInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *node = (json_object *)((struct dm_data *)prev_data)->additional_data;
	json_object *interface = ((struct dm_data *)prev_data)->json_object;
	char *ifmac = dmjson_get_value(interface, 1, "macaddress");
	json_object *arrobj = NULL, *nbr = NULL;
	struct dm_data curr_data = {0};
	char *inst = NULL;
	int id = 0, i = 0;

	if (!is_primary_iface_for_mac(node, interface, ifmac))
		return 0;

	dmjson_foreach_obj_in_array(node, arrobj, nbr, i, 1, "ieee1905_neighbors") {
		char *via = dmjson_get_value(nbr, 1, "via");

		if (DM_STRCMP(via, ifmac) != 0)
			continue;

		curr_data.json_object = nbr;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
			break;
	}
	return 0;
}

/*************************************************************
* COMMON FUNCTIONS
**************************************************************/
static int ubus_ieee1905_info(const char *option1, const char *option2, char **value)
{
	json_object *res = NULL;
	dmubus_call("ieee1905", "info", UBUS_ARGS{0}, 0, &res);
	DM_ASSERT(res, *value = "");
	*value = option2 ? dmjson_get_value(res, 2, option1, option2)
			 : dmjson_get_value(res, 1, option1);
	return 0;
}

static char *get_datamodel_media_type(struct json_object *json_data)
{
	char *media = NULL, *band = NULL;

	char *num_media = dmjson_get_value(json_data, 1, "num_mediainfo");

	if (DM_STRTOUL(num_media) > 0) {
		/* If the interface has multiple media, then get information from the first one */
		json_object *mediainfo_arr = NULL;

		json_object_object_get_ex(json_data, "mediainfo", &mediainfo_arr);
		if (mediainfo_arr && json_object_get_type(mediainfo_arr) == json_type_array) {
			json_object *mediainfo = json_object_array_get_idx(mediainfo_arr, 0);
			media = mediainfo ? dmjson_get_value(mediainfo, 1, "media") : "";
			band = mediainfo ? dmjson_get_value(mediainfo, 1, "band") : "";
		}
	} else {
		media = dmjson_get_value(json_data, 1, "media");
		band = dmjson_get_value(json_data, 1, "band");
	}

	if (media == NULL)
		return "";

	if (DM_LSTRSTR(media, "802_3U_FAST_ETHERNET"))
		return "IEEE 802.3u";
	else if (DM_LSTRSTR(media, "802_3AB_GIGABIT_ETHERNET"))
		return "IEEE 802.3ab";
#ifdef ETH_MEDIA_EXTENSION
	else if (DM_LSTRSTR(media, "802_3BZ"))
		return "IEEE 802.3bz";
	else if (DM_LSTRSTR(media, "802_3AE_10G_ETHERNET"))
		return "IEEE 802.3ae";
#endif
	else if (DM_LSTRSTR(media, "802_11B"))
		return "IEEE 802.11b";
	else if (DM_LSTRSTR(media, "802_11G"))
		return "IEEE 802.11g";
	else if (DM_LSTRSTR(media, "802_11A"))
		return "IEEE 802.11a";
	else if (DM_LSTRSTR(media, "802_11N")) {
		if (!DM_LSTRCMP(band, "2"))
			return "IEEE 802.11n 2.4";
		else if (!DM_LSTRCMP(band, "5"))
			return "IEEE 802.11n 5.0";
		return "IEEE 802.11n";
	} else if (DM_LSTRSTR(media, "802_11AC"))
		return "IEEE 802.11ac";
	else if (DM_LSTRSTR(media, "802_11AX"))
		return "IEEE 802.11ax";
	else if (DM_LSTRSTR(media, "802_11BE"))
		return "IEEE 802.11be";
	else if (DM_LSTRSTR(media, "802_11AD"))
		return "IEEE 802.11ad";
	else if (DM_LSTRSTR(media, "802_11AF"))
		return "IEEE 802.11af";
	else if (DM_LSTRSTR(media, "1901_WAVELET"))
		return "IEEE 1901 Wavelet";
	else if (DM_LSTRSTR(media, "1901_FFT"))
		return "IEEE 1901 FFT";
	else if (DM_LSTRSTR(media, "MOCA_V1_1"))
		return "MoCAv1.1";

	return (char *)media;
}

static char *get_iface_mediainfo_field(void *data, const char *key)
{
	json_object *arr = NULL, *mediainfo = NULL;

	json_object_object_get_ex(((struct dm_data *)data)->json_object, "mediainfo", &arr);
	if (arr && json_object_get_type(arr) == json_type_array) {
		mediainfo = json_object_array_get_idx(arr, 0);
		return mediainfo ? dmjson_get_value(mediainfo, 1, key) : "";
	}

	return "";
}

static uint8_t convert_rssi_str_to_uint8(const char *rssi_str)
{
	char *endptr = NULL;
	long rssi_long;

	if (!rssi_str)
		return 0;

	errno = 0;
	rssi_long = strtol(rssi_str, &endptr, 10);

	if (errno != 0 || endptr == rssi_str || *endptr != '\0')
		return 0;

	return (uint8_t)rssi_long;
}

/*************************************************************
* GET & SET PARAM
**************************************************************/
static int get_IEEE1905_Version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	ubus_ieee1905_info("version", NULL, value);
	if (DM_STRLEN(*value) == 0) {
		*value = "1905.1a";
	}
	return 0;
}

static int get_IEEE1905AL_IEEE1905Id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return ubus_ieee1905_info("ieee1905id", NULL, value);
}

static int get_IEEE1905AL_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = NULL;

	ubus_ieee1905_info("status", NULL, &val);
	if (!strcasecmp(val, "enabled"))
		*value = "Enabled";
	else if (!strcasecmp(val, "disabled"))
		*value = "Disabled";
	else if (!strcasecmp(val, "error_misconfigured"))
		*value = "Error_Misconfigured";
	else if (!strcasecmp(val, "error"))
		*value = "Error";
	else
		*value = "Error";

	return 0;
}

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

	dmubus_call("ieee1905", "info", UBUS_ARGS{0}, 0, &res);
	DM_ASSERT(res, *value = "");

	*value = dmjson_get_value_array_all(res, ",", 1, "registrar_band");

	return 0;
}

static int get_IEEE1905AL_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return ubus_ieee1905_info("num_interfaces", NULL, value);
}

static int get_IEEE1905AL_LocalOnlyMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *enable = dmuci_get_option_value_fallback_def("ieee1905", "@al-iface[0]", "enabled", "1");

	*value = (DM_STRCMP(enable, "1") == 0) ? "0" : "1";
	return 0;
}

static int set_IEEE1905AL_LocalOnlyMode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	bool en;

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_boolean(ctx, value))
			return FAULT_9007;
		break;
	case VALUESET:
		en = dmuci_string_to_boolean(value);
		if (en) {
			dmuci_set_value("ieee1905", "@al-iface[0]", "enabled", "0");
		} else {
			dmuci_set_value("ieee1905", "@al-iface[0]", "enabled", "1");
		}
		break;
	}
	return 0;
}

static int get_IEEE1905ALInterface_InterfaceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905ALInterface_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *status = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "status");
	*value = !strcasecmp(status, "up") ? "Up" : "Down";
	return 0;
}

static int get_IEEE1905ALInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char buf[256] = {0};

	char *linker = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ifname");
	bbfdm_get_references(ctx, MATCH_FIRST, "Device.Ethernet.Interface.", "Name", linker, buf, sizeof(buf));

	struct uci_section *s = get_dup_section_in_config_opt("wireless", "wifi-iface", "ifname", linker);
	dmuci_get_value_by_section_string(s, "device", &linker);
	bbfdm_get_references(ctx, MATCH_FIRST, "Device.WiFi.Radio.", "Name", linker, buf, sizeof(buf));

	*value = dmstrdup(buf);
	return 0;
}

static int get_IEEE1905ALInterface_MediaType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = get_datamodel_media_type(((struct dm_data *)data)->json_object);
	return 0;
}

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

static int set_IEEE1905ALInterface_PowerState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *Power_State[] = {"On", "Power_Save", "Off", "Unsupported", NULL};

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_string(ctx, value, -1, -1, Power_State, NULL))
		      return FAULT_9007;
		break;
	case VALUESET:
		//TODO
		break;
	}
	return 0;
}

static int get_IEEE1905ALInterface_LinkNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "num_links");
	return 0;
}

static int get_IEEE1905ALInterfaceLink_InterfaceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905ALInterfaceLink_IEEE1905Id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ieee1905id");
	return 0;
}

static int get_IEEE1905ALInterfaceLink_MediaType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = get_datamodel_media_type(((struct dm_data *)data)->json_object);
	return 0;
}

static int get_IEEE1905ALInterfaceLinkMetric_IEEE802dot1Bridge(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "has_bridge");
	return 0;
}

static int get_IEEE1905ALInterfaceLinkMetric_PacketErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "tx_errors");
	return 0;
}

static int get_IEEE1905ALInterfaceLinkMetric_PacketErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "rx_errors");
	return 0;
}

static int get_IEEE1905ALInterfaceLinkMetric_TransmittedPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "tx_packets");
	return 0;
}

static int get_IEEE1905ALInterfaceLinkMetric_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "rx_packets");
	return 0;
}

static int get_IEEE1905ALInterfaceLinkMetric_MACThroughputCapacity(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "max_macrate");
	return 0;
}

static int get_IEEE1905ALInterfaceLinkMetric_PHYRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "max_phyrate");
	return 0;
}

static int get_IEEE1905ALInterfaceLinkMetric_RSSI(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *rssi = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "rssi");
	dmasprintf(value, "%u", convert_rssi_str_to_uint8(rssi));
	return 0;
}

static int get_IEEE1905ALNetworkTopology_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return ubus_ieee1905_info("topology", "enabled", value);
}

static int set_IEEE1905ALNetworkTopology_Enable(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;
		break;
	case VALUESET:
		//TODO
		break;
	}
	return 0;
}

static int get_IEEE1905ALNetworkTopology_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *status = NULL;
	ubus_ieee1905_info("topology", "status", &status);
	*value = !strcasecmp(status, "available") ? "Available" : "Incomplete";
	return 0;
}

static int get_IEEE1905ALNetworkTopology_IEEE1905DeviceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905ALNetworkTopologyIEEE1905DeviceInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_IEEE1905Id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ieee1905id");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_Version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "version");
	if (DM_STRLEN(*value) == 0)
		*value = "1905.1a";
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_FriendlyName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "name");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_ManufacturerName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "manufacturer");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_ManufacturerModel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "model");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_ControlURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "url");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_IPv4AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905ALNetworkTopologyIEEE1905DeviceIPv4AddressInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_IPv6AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905ALNetworkTopologyIEEE1905DeviceIPv6AddressInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905ALNetworkTopologyIEEE1905DeviceInterfaceInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_NonIEEE1905NeighborNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905NeighborInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_IEEE1905NeighborNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905Device_BridgingTupleNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905ALNetworkTopologyIEEE1905DeviceBridgingTupleInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv4Address_MACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)((struct dm_data *)data)->additional_data;
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv4Address_IPv4Address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ip");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv4Address_IPv4AddressType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "type");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv4Address_DHCPServer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "dhcpserver");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv6Address_MACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)((struct dm_data *)data)->additional_data;
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv6Address_IPv6Address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ip");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv6Address_IPv6AddressType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "type");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv6Address_IPv6AddressOrigin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "dhcpserver");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_InterfaceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_MediaType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = get_datamodel_media_type(((struct dm_data *)data)->json_object);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_PowerState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *power = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "power");
	*value = !strcasecmp(power, "on") ? "On" : "Off";
	return 0;
}

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

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_Role(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *role = get_iface_mediainfo_field(data, "role");

	if (!DM_LSTRCMP(role, "ap"))
		*value = "AP";
	else if (!DM_LSTRCMP(role, "sta"))
		*value = "non-AP/non-PCP STA";
	else if (!DM_LSTRCMP(role, "p2p_client"))
		*value = "Wi-Fi P2P Client";
	else if (!DM_LSTRCMP(role, "p2p_go"))
		*value = "Wi-Fi P2P Group Owner";
	else if (!DM_LSTRCMP(role, "pcp"))
		*value = "802.11adPCP";
	else
		*value = role;

	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_APChannelBand(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = get_iface_mediainfo_field(data, "bandwidth");
	int bw = DM_STRTOL(val);

	switch (bw) {
		case 20:
			*value = "00";
			break;
		case 40:
			*value = "01";
			break;
		case 80:
			*value = "02";
			break;
		case 160:
			*value = "03";
			break;
		case 8080:
			*value = "04";
			break;
		default:
			*value = "";
	}

	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_FrequencyIndex1(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = get_iface_mediainfo_field(data, "freq_seg0_idx");
	char freq_str[3] = {0};
	int freq = DM_STRTOL(val);

	snprintf(freq_str, 3, "%02x", freq);

	*value = dmstrdup(freq_str);

	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_FrequencyIndex2(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = get_iface_mediainfo_field(data, "freq_seg1_idx");
	char freq_str[3] = {0};
	int freq = DM_STRTOL(val);

	snprintf(freq_str, 3, "%02x", freq);
	*value = dmstrdup(freq_str);

	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905Neighbor_LocalInterface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *mac_addr = ((struct ieee1905_device_nonieee1905neighbor_args *)((struct dm_data *)data)->additional_data)->mac_addr;
	_bbfdm_get_references(ctx, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.*.Interface.", "InterfaceId", mac_addr, value);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905Neighbor_NeighborInterfaceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *neighbor = ((struct ieee1905_device_nonieee1905neighbor_args *)((struct dm_data *)data)->additional_data)->neighbor;
	*value = neighbor ? neighbor : "";
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905Neighbor_LocalInterface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *linker = ((struct ieee1905_device_ieee1905neighbor_args *)((struct dm_data *)data)->additional_data)->mac_addr;
	_bbfdm_get_references(ctx, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.*.Interface.", "InterfaceId", linker, value);
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905Neighbor_NeighborDeviceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = ((struct ieee1905_device_ieee1905neighbor_args *)((struct dm_data *)data)->additional_data)->neighbor_device_id;
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905Neighbor_MetricNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = ((struct ieee1905_device_ieee1905neighbor_args *)((struct dm_data *)data)->additional_data)->num_metrics;
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_NeighborMACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)((struct dm_data *)data)->additional_data;
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_IEEE802dot1Bridge(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "has_bridge");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_PacketErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "tx_errors");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_PacketErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "rx_errors");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_TransmittedPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "tx_packets");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "rx_packets");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_MACThroughputCapacity(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "max_macrate");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_LinkAvailability(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "link_available");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_PHYRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "max_phyrate");
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_RSSI(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *rssi = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "rssi");
	dmasprintf(value, "%u", convert_rssi_str_to_uint8(rssi));
	return 0;
}

static int get_IEEE1905ALNetworkTopologyIEEE1905DeviceBridgingTuple_InterfaceList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	json_object *json_obj = NULL;
	char *mac_addr = NULL;
	char buf[4096] = {0};
	int idx = 0;

	dmjson_foreach_value_in_array(((struct dm_data *)data)->json_object, json_obj, mac_addr, idx, 1, "tuple") {
		bbfdm_get_references(ctx, MATCH_ALL, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.*.Interface.", "InterfaceId", mac_addr, buf, sizeof(buf));
	}

	*value = dmstrdup(buf);
	return 0;
}

static int get_IEEE1905ALSecurity_SetupMethod(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmuci_get_option_value_fallback_def("ieee1905", "security", "method", "PBC");
	return 0;
}

static int set_IEEE1905ALSecurity_SetupMethod(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, -1, 1024, -1, -1, NULL, NULL))
			return FAULT_9007;
		break;
	case VALUESET:
		dmuci_set_value("ieee1905", "security", "method", value);
		break;
	}
	return 0;
}

static int get_IEEE1905ALSecurity_Password(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmuci_get_option_value_string("ieee1905", "security", "key", value);
	return 0;
}

static int set_IEEE1905ALSecurity_Password(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, NULL, NULL))
			return FAULT_9007;
		break;
	case VALUESET:
		dmuci_set_value("ieee1905", "security", "key", value);
		break;
	}
	return 0;
}

static int get_IEEE1905ALNetworkingRegistrar_Registrar2dot4(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return ubus_ieee1905_info("network_registrars", "registrar_2", value);
}

static int get_IEEE1905ALNetworkingRegistrar_Registrar5(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return ubus_ieee1905_info("network_registrars", "registrar_5", value);
}

static int get_IEEE1905ALNetworkingRegistrar_Registrar60(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return ubus_ieee1905_info("network_registrars", "registrar_60", value);
}

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

static int set_IEEE1905Network_Enable(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;
		break;
	case VALUESET:
		//TODO
		break;
	}
	return 0;
}

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

static int get_IEEE1905Network_ALNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905NetworkALInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905NetworkAL_IEEE1905Id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ieee1905id");
	return 0;
}

static int get_IEEE1905NetworkAL_Version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "version");
	return 0;
}

static int get_IEEE1905NetworkAL_RegistrarFreqBand(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	//TODO: not reported by 'ieee1905.topology dump'
	return 0;
}

static int get_IEEE1905NetworkAL_FriendlyName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "name");
	return 0;
}

static int get_IEEE1905NetworkAL_ManufacturerName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "manufacturer");
	return 0;
}

static int get_IEEE1905NetworkAL_ManufacturerModel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "model");
	return 0;
}

static int get_IEEE1905NetworkAL_ControlURL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "url");
	return 0;
}

static int get_IEEE1905NetworkAL_AssocWiFiNetworkDeviceRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *ieee1905id = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ieee1905id");
	_bbfdm_get_references(ctx, "Device.WiFi.DataElements.Network.Device.", "ID", ieee1905id, value);
	return 0;
}

static int get_IEEE1905NetworkAL_IPv4AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905NetworkALIPv4AddressInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905NetworkAL_IPv6AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905NetworkALIPv6AddressInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905NetworkAL_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905NetworkALInterfaceInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905NetworkAL_BridgingTupleNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905NetworkALBridgingTupleInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905NetworkALIPv4Address_MACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905NetworkALIPv4Address_IPv4Address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ip");
	return 0;
}

static int get_IEEE1905NetworkALIPv4Address_IPv4AddressType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "type");
	return 0;
}

static int get_IEEE1905NetworkALIPv4Address_DHCPServer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "dhcpserver");
	return 0;
}

static int get_IEEE1905NetworkALIPv6Address_MACAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905NetworkALIPv6Address_IPv6Address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "ip");
	return 0;
}

static int get_IEEE1905NetworkALIPv6Address_IPv6AddressType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "type");
	return 0;
}

static int get_IEEE1905NetworkALIPv6Address_IPv6AddressOrigin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "dhcpserver");
	return 0;
}

static int get_IEEE1905NetworkALInterface_InterfaceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905NetworkALInterface_MediaType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = get_datamodel_media_type(((struct dm_data *)data)->json_object);
	return 0;
}

static int get_IEEE1905NetworkALInterface_PowerState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *power = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "power");
	*value = !strcasecmp(power, "on") ? "On" : "Off";
	return 0;
}

static int get_IEEE1905NetworkALInterface_NetworkMembership(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "bssid");
	return 0;
}

static int get_IEEE1905NetworkALInterface_Role(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *role = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "role");

	if (!DM_LSTRCMP(role, "ap"))
		*value = "AP";
	else if (!DM_LSTRCMP(role, "sta"))
		*value = "non-AP/non-PCP STA";
	else if (!DM_LSTRCMP(role, "p2p_client"))
		*value = "Wi-Fi P2P Client";
	else if (!DM_LSTRCMP(role, "p2p_go"))
		*value = "Wi-Fi P2P Group Owner";
	else if (!DM_LSTRCMP(role, "pcp"))
		*value = "802.11adPCP";
	else
		*value = role;

	return 0;
}

static int get_IEEE1905NetworkALInterface_APChannelBand(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "bandwidth");
	int bw = DM_STRTOL(val);

	switch (bw) {
		case 20:
			*value = "00";
			break;
		case 40:
			*value = "01";
			break;
		case 80:
			*value = "02";
			break;
		case 160:
			*value = "03";
			break;
		case 8080:
			*value = "04";
			break;
		default:
			*value = "";
	}

	return 0;
}

static int get_IEEE1905NetworkALInterface_FrequencyIndex1(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "freq_seg0_idx");
	char freq_str[3] = {0};
	int freq = DM_STRTOL(val);

	snprintf(freq_str, 3, "%02x", freq);
	*value = dmstrdup(freq_str);
	return 0;
}

static int get_IEEE1905NetworkALInterface_FrequencyIndex2(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *val = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "freq_seg1_idx");
	char freq_str[3] = {0};
	int freq = DM_STRTOL(val);

	snprintf(freq_str, 3, "%02x", freq);
	*value = dmstrdup(freq_str);
	return 0;
}

static int get_IEEE1905NetworkALInterface_LinkNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905NetworkALInterfaceLinkInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905NetworkALInterface_NonIEEE1905NeighborNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905NetworkALInterfaceNonIEEE1905NeighborInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905NetworkALInterface_IEEE1905NeighborNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseIEEE1905NetworkALInterfaceIEEE1905NeighborInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLink_InterfaceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "remote_via");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLink_IEEE1905Id(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLink_MediaType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = get_datamodel_media_type((json_object *)((struct dm_data *)data)->additional_data);
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_IEEE802dot1Bridge(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *has_bridge = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "has_bridge");
	*value = dmuci_string_to_boolean(has_bridge) ? "1" : "0";
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_PacketErrors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "tx_errors");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_PacketErrorsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "rx_errors");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_TransmittedPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "tx_packets");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "rx_packets");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_MACThroughputCapacity(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "max_macrate");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_LinkAvailability(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "link_available");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_PHYRate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "max_phyrate");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceLinkMetric_RSSI(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *rssi = dmjson_get_value(((struct dm_data *)data)->json_object, 2, "metric", "rssi");
	dmasprintf(value, "%u", convert_rssi_str_to_uint8(rssi));
	return 0;
}

static int get_IEEE1905NetworkALInterfaceNonIEEE1905Neighbor_NeighborInterfaceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceIEEE1905Neighbor_NeighborDeviceId(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	return 0;
}

static int get_IEEE1905NetworkALInterfaceIEEE1905Neighbor_IEEE1905DeviceRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *mac_addr = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "macaddress");
	_bbfdm_get_references(ctx, "Device.IEEE1905.Network.AL.", "IEEE1905Id", mac_addr, value);
	return 0;
}

static int get_IEEE1905NetworkALInterfaceIEEE1905Neighbor_IEEE802dot1Bridge(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *has_bridge = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "has_bridge");
	*value = dmuci_string_to_boolean(has_bridge) ? "1" : "0";
	return 0;
}

static int get_IEEE1905NetworkALBridgingTuple_InterfaceList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	json_object *json_obj = NULL;
	char *mac_addr = NULL;
	char buf[4096] = {0};
	int idx = 0;

	dmjson_foreach_value_in_array(((struct dm_data *)data)->json_object, json_obj, mac_addr, idx, 1, "tuple") {
		bbfdm_get_references(ctx, MATCH_ALL, "Device.IEEE1905.Network.AL.*.Interface.", "InterfaceId", mac_addr, buf, sizeof(buf));
	}

	*value = dmstrdup(buf);
	return 0;
}

/**********************************************************************************************************************************
*                                            OBJ & PARAM DEFINITION
***********************************************************************************************************************************/
/* *** Device.IEEE1905.Network.AL.{i}.Interface.{i}.Link.{i}.Metric. *** */
DMLEAF tIEEE1905NetworkALInterfaceLinkMetricParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"IEEE802dot1Bridge", &DMREAD, DMT_BOOL, get_IEEE1905NetworkALInterfaceLinkMetric_IEEE802dot1Bridge, NULL, BBFDM_BOTH},
{"PacketErrors", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterfaceLinkMetric_PacketErrors, NULL, BBFDM_BOTH},
{"PacketErrorsReceived", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterfaceLinkMetric_PacketErrorsReceived, NULL, BBFDM_BOTH},
{"TransmittedPackets", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterfaceLinkMetric_TransmittedPackets, NULL, BBFDM_BOTH},
{"PacketsReceived", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterfaceLinkMetric_PacketsReceived, NULL, BBFDM_BOTH},
{"MACThroughputCapacity", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterfaceLinkMetric_MACThroughputCapacity, NULL, BBFDM_BOTH},
{"LinkAvailability", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterfaceLinkMetric_LinkAvailability, NULL, BBFDM_BOTH},
{"PHYRate", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterfaceLinkMetric_PHYRate, NULL, BBFDM_BOTH},
{"RSSI", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterfaceLinkMetric_RSSI, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network.AL.{i}.Interface.{i}.Link.{i}. *** */
DMOBJ tIEEE1905NetworkALInterfaceLinkObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"Metric", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIEEE1905NetworkALInterfaceLinkMetricParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tIEEE1905NetworkALInterfaceLinkParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"InterfaceId", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterfaceLink_InterfaceId, NULL, BBFDM_BOTH},
{"IEEE1905Id", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterfaceLink_IEEE1905Id, NULL, BBFDM_BOTH},
{"MediaType", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterfaceLink_MediaType, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network.AL.{i}.Interface.{i}.NonIEEE1905Neighbor.{i}. *** */
DMLEAF tIEEE1905NetworkALInterfaceNonIEEE1905NeighborParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"NeighborInterfaceId", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterfaceNonIEEE1905Neighbor_NeighborInterfaceId, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network.AL.{i}.Interface.{i}.IEEE1905Neighbor.{i}. *** */
DMLEAF tIEEE1905NetworkALInterfaceIEEE1905NeighborParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"NeighborDeviceId", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterfaceIEEE1905Neighbor_NeighborDeviceId, NULL, BBFDM_BOTH},
{"IEEE1905DeviceRef", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterfaceIEEE1905Neighbor_IEEE1905DeviceRef, NULL, BBFDM_BOTH},
{"IEEE802dot1Bridge", &DMREAD, DMT_BOOL, get_IEEE1905NetworkALInterfaceIEEE1905Neighbor_IEEE802dot1Bridge, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network.AL.{i}.IPv4Address.{i}. *** */
DMLEAF tIEEE1905NetworkALIPv4AddressParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"MACAddress", &DMREAD, DMT_STRING, get_IEEE1905NetworkALIPv4Address_MACAddress, NULL, BBFDM_BOTH},
{"IPv4Address", &DMREAD, DMT_STRING, get_IEEE1905NetworkALIPv4Address_IPv4Address, NULL, BBFDM_BOTH},
{"IPv4AddressType", &DMREAD, DMT_STRING, get_IEEE1905NetworkALIPv4Address_IPv4AddressType, NULL, BBFDM_BOTH},
{"DHCPServer", &DMREAD, DMT_STRING, get_IEEE1905NetworkALIPv4Address_DHCPServer, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network.AL.{i}.IPv6Address.{i}. *** */
DMLEAF tIEEE1905NetworkALIPv6AddressParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"MACAddress", &DMREAD, DMT_STRING, get_IEEE1905NetworkALIPv6Address_MACAddress, NULL, BBFDM_BOTH},
{"IPv6Address", &DMREAD, DMT_STRING, get_IEEE1905NetworkALIPv6Address_IPv6Address, NULL, BBFDM_BOTH},
{"IPv6AddressType", &DMREAD, DMT_STRING, get_IEEE1905NetworkALIPv6Address_IPv6AddressType, NULL, BBFDM_BOTH},
{"IPv6AddressOrigin", &DMREAD, DMT_STRING, get_IEEE1905NetworkALIPv6Address_IPv6AddressOrigin, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network.AL.{i}.Interface.{i}. *** */
DMOBJ tIEEE1905NetworkALInterfaceObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"Link", &DMREAD, NULL, NULL, NULL, browseIEEE1905NetworkALInterfaceLinkInst, NULL, NULL, tIEEE1905NetworkALInterfaceLinkObj, tIEEE1905NetworkALInterfaceLinkParams, NULL, BBFDM_BOTH, NULL},
{"NonIEEE1905Neighbor", &DMREAD, NULL, NULL, NULL, browseIEEE1905NetworkALInterfaceNonIEEE1905NeighborInst, NULL, NULL, NULL, tIEEE1905NetworkALInterfaceNonIEEE1905NeighborParams, NULL, BBFDM_BOTH, NULL},
{"IEEE1905Neighbor", &DMREAD, NULL, NULL, NULL, browseIEEE1905NetworkALInterfaceIEEE1905NeighborInst, NULL, NULL, NULL, tIEEE1905NetworkALInterfaceIEEE1905NeighborParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tIEEE1905NetworkALInterfaceParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"InterfaceId", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterface_InterfaceId, NULL, BBFDM_BOTH},
{"MediaType", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterface_MediaType, NULL, BBFDM_BOTH},
{"PowerState", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterface_PowerState, NULL, BBFDM_BOTH},
{"NetworkMembership", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterface_NetworkMembership, NULL, BBFDM_BOTH},
{"Role", &DMREAD, DMT_STRING, get_IEEE1905NetworkALInterface_Role, NULL, BBFDM_BOTH},
{"APChannelBand", &DMREAD, DMT_HEXBIN, get_IEEE1905NetworkALInterface_APChannelBand, NULL, BBFDM_BOTH},
{"FrequencyIndex1", &DMREAD, DMT_HEXBIN, get_IEEE1905NetworkALInterface_FrequencyIndex1, NULL, BBFDM_BOTH},
{"FrequencyIndex2", &DMREAD, DMT_HEXBIN, get_IEEE1905NetworkALInterface_FrequencyIndex2, NULL, BBFDM_BOTH},
{"LinkNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterface_LinkNumberOfEntries, NULL, BBFDM_BOTH},
{"NonIEEE1905NeighborNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterface_NonIEEE1905NeighborNumberOfEntries, NULL, BBFDM_BOTH},
{"IEEE1905NeighborNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905NetworkALInterface_IEEE1905NeighborNumberOfEntries, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network.AL.{i}.BridgingTuple.{i}. *** */
DMLEAF tIEEE1905NetworkALBridgingTupleParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"InterfaceList", &DMREAD, DMT_STRING, get_IEEE1905NetworkALBridgingTuple_InterfaceList, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network.AL.{i}. *** */
DMOBJ tIEEE1905NetworkALObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"IPv4Address", &DMREAD, NULL, NULL, NULL, browseIEEE1905NetworkALIPv4AddressInst, NULL, NULL, NULL, tIEEE1905NetworkALIPv4AddressParams, NULL, BBFDM_BOTH, NULL},
{"IPv6Address", &DMREAD, NULL, NULL, NULL, browseIEEE1905NetworkALIPv6AddressInst, NULL, NULL, NULL, tIEEE1905NetworkALIPv6AddressParams, NULL, BBFDM_BOTH, NULL},
{"Interface", &DMREAD, NULL, NULL, NULL, browseIEEE1905NetworkALInterfaceInst, NULL, NULL, tIEEE1905NetworkALInterfaceObj, tIEEE1905NetworkALInterfaceParams, NULL, BBFDM_BOTH, NULL},
{"BridgingTuple", &DMREAD, NULL, NULL, NULL, browseIEEE1905NetworkALBridgingTupleInst, NULL, NULL, NULL, tIEEE1905NetworkALBridgingTupleParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tIEEE1905NetworkALParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"IEEE1905Id", &DMREAD, DMT_STRING, get_IEEE1905NetworkAL_IEEE1905Id, NULL, BBFDM_BOTH},
{"Version", &DMREAD, DMT_STRING, get_IEEE1905NetworkAL_Version, NULL, BBFDM_BOTH},
{"RegistrarFreqBand", &DMREAD, DMT_STRING, get_IEEE1905NetworkAL_RegistrarFreqBand, NULL, BBFDM_BOTH},
{"FriendlyName", &DMREAD, DMT_STRING, get_IEEE1905NetworkAL_FriendlyName, NULL, BBFDM_BOTH},
{"ManufacturerName", &DMREAD, DMT_STRING, get_IEEE1905NetworkAL_ManufacturerName, NULL, BBFDM_BOTH},
{"ManufacturerModel", &DMREAD, DMT_STRING, get_IEEE1905NetworkAL_ManufacturerModel, NULL, BBFDM_BOTH},
{"ControlURL", &DMREAD, DMT_STRING, get_IEEE1905NetworkAL_ControlURL, NULL, BBFDM_BOTH},
{"AssocWiFiNetworkDeviceRef", &DMREAD, DMT_STRING, get_IEEE1905NetworkAL_AssocWiFiNetworkDeviceRef, NULL, BBFDM_BOTH},
{"IPv4AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905NetworkAL_IPv4AddressNumberOfEntries, NULL, BBFDM_BOTH},
{"IPv6AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905NetworkAL_IPv6AddressNumberOfEntries, NULL, BBFDM_BOTH},
{"InterfaceNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905NetworkAL_InterfaceNumberOfEntries, NULL, BBFDM_BOTH},
{"BridgingTupleNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905NetworkAL_BridgingTupleNumberOfEntries, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.Network. *** */
DMOBJ tIEEE1905NetworkObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"AL", &DMREAD, NULL, NULL, NULL, browseIEEE1905NetworkALInst, NULL, NULL, tIEEE1905NetworkALObj, tIEEE1905NetworkALParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tIEEE1905NetworkParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Enable", &DMWRITE, DMT_BOOL, get_IEEE1905Network_Enable, set_IEEE1905Network_Enable, BBFDM_BOTH},
{"Status", &DMREAD, DMT_STRING, get_IEEE1905Network_Status, NULL, BBFDM_BOTH},
{"ALNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905Network_ALNumberOfEntries, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.NetworkingRegistrar. *** */
DMLEAF tIEEE1905ALNetworkingRegistrarParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"Registrar2dot4", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkingRegistrar_Registrar2dot4, NULL, BBFDM_BOTH},
{"Registrar5", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkingRegistrar_Registrar5, NULL, BBFDM_BOTH},
{"Registrar60", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkingRegistrar_Registrar60, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.Security. *** */
DMLEAF tIEEE1905ALSecurityParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"SetupMethod", &DMWRITE, DMT_STRING, get_IEEE1905ALSecurity_SetupMethod, set_IEEE1905ALSecurity_SetupMethod, BBFDM_BOTH},
{"Password", &DMWRITE, DMT_STRING, get_IEEE1905ALSecurity_Password, set_IEEE1905ALSecurity_Password, BBFDM_BOTH, DM_FLAG_SECURE},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.BridgingTuple.{i}. *** */
DMLEAF tIEEE1905ALNetworkTopologyIEEE1905DeviceBridgingTupleParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"InterfaceList", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceBridgingTuple_InterfaceList, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.IEEE1905Neighbor.{i}.Metric.{i}. *** */
DMLEAF tIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetricParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"NeighborMACAddress", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_NeighborMACAddress, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"IEEE802dot1Bridge", &DMREAD, DMT_BOOL, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_IEEE802dot1Bridge, NULL, BBFDM_BOTH},
{"PacketErrors", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_PacketErrors, NULL, BBFDM_BOTH},
{"PacketErrorsReceived", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_PacketErrorsReceived, NULL, BBFDM_BOTH},
{"TransmittedPackets", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_TransmittedPackets, NULL, BBFDM_BOTH},
{"PacketsReceived", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_PacketsReceived, NULL, BBFDM_BOTH},
{"MACThroughputCapacity", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_MACThroughputCapacity, NULL, BBFDM_BOTH},
{"LinkAvailability", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_LinkAvailability, NULL, BBFDM_BOTH},
{"PHYRate", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_PHYRate, NULL, BBFDM_BOTH},
{"RSSI", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetric_RSSI, NULL, BBFDM_BOTH},
{0}
};

DMLEAF tIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"LocalInterface", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905Neighbor_LocalInterface, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_REFERENCE},
{"NeighborDeviceId", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905Neighbor_NeighborDeviceId, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"MetricNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905Neighbor_MetricNumberOfEntries, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.IEEE1905Neighbor.{i}. *** */
DMOBJ tIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"Metric", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetricInst, NULL, NULL, NULL, tIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborMetricParams, NULL, BBFDM_BOTH, NULL},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.NonIEEE1905Neighbor.{i}. *** */
DMLEAF tIEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905NeighborParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"LocalInterface", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905Neighbor_LocalInterface, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_REFERENCE},
{"NeighborInterfaceId", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905Neighbor_NeighborInterfaceId, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.Interface.{i}. *** */
DMLEAF tIEEE1905ALNetworkTopologyIEEE1905DeviceInterfaceParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"InterfaceId", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_InterfaceId, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"MediaType", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_MediaType, NULL, BBFDM_BOTH},
{"PowerState", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_PowerState, NULL, BBFDM_BOTH},
{"NetworkMembership", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_NetworkMembership, NULL, BBFDM_BOTH},
{"Role", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_Role, NULL, BBFDM_BOTH},
{"APChannelBand", &DMREAD, DMT_HEXBIN, get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_APChannelBand, NULL, BBFDM_BOTH},
{"FrequencyIndex1", &DMREAD, DMT_HEXBIN, get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_FrequencyIndex1, NULL, BBFDM_BOTH},
{"FrequencyIndex2", &DMREAD, DMT_HEXBIN, get_IEEE1905ALNetworkTopologyIEEE1905DeviceInterface_FrequencyIndex2, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.IPv6Address.{i}. *** */
DMLEAF tIEEE1905ALNetworkTopologyIEEE1905DeviceIPv6AddressParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"MACAddress", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv6Address_MACAddress, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"IPv6Address", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv6Address_IPv6Address, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"IPv6AddressType", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv6Address_IPv6AddressType, NULL, BBFDM_BOTH},
{"IPv6AddressOrigin", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv6Address_IPv6AddressOrigin, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.IPv4Address.{i}. *** */
DMLEAF tIEEE1905ALNetworkTopologyIEEE1905DeviceIPv4AddressParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"MACAddress", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv4Address_MACAddress, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"IPv4Address", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv4Address_IPv4Address, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"IPv4AddressType", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv4Address_IPv4AddressType, NULL, BBFDM_BOTH},
{"DHCPServer", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905DeviceIPv4Address_DHCPServer, NULL, BBFDM_BOTH},
{0}
};

DMLEAF tIEEE1905ALNetworkTopologyIEEE1905DeviceParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"IEEE1905Id", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905Device_IEEE1905Id, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_LINKER},
{"Version", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905Device_Version, NULL, BBFDM_BOTH},
{"FriendlyName", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905Device_FriendlyName, NULL, BBFDM_BOTH},
{"ManufacturerName", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905Device_ManufacturerName, NULL, BBFDM_BOTH},
{"ManufacturerModel", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905Device_ManufacturerModel, NULL, BBFDM_BOTH},
{"ControlURL", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopologyIEEE1905Device_ControlURL, NULL, BBFDM_BOTH},
{"IPv4AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905Device_IPv4AddressNumberOfEntries, NULL, BBFDM_BOTH},
{"IPv6AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905Device_IPv6AddressNumberOfEntries, NULL, BBFDM_BOTH},
{"InterfaceNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905Device_InterfaceNumberOfEntries, NULL, BBFDM_BOTH},
{"NonIEEE1905NeighborNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905Device_NonIEEE1905NeighborNumberOfEntries, NULL, BBFDM_BOTH},
{"IEEE1905NeighborNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905Device_IEEE1905NeighborNumberOfEntries, NULL, BBFDM_BOTH},
{"BridgingTupleNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopologyIEEE1905Device_BridgingTupleNumberOfEntries, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}. *** */
DMOBJ tIEEE1905ALNetworkTopologyIEEE1905DeviceObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"IPv4Address", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALNetworkTopologyIEEE1905DeviceIPv4AddressInst, NULL, NULL, NULL, tIEEE1905ALNetworkTopologyIEEE1905DeviceIPv4AddressParams, NULL, BBFDM_BOTH, NULL},
{"IPv6Address", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALNetworkTopologyIEEE1905DeviceIPv6AddressInst, NULL, NULL, NULL, tIEEE1905ALNetworkTopologyIEEE1905DeviceIPv6AddressParams, NULL, BBFDM_BOTH, NULL},
{"Interface", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALNetworkTopologyIEEE1905DeviceInterfaceInst, NULL, NULL, NULL, tIEEE1905ALNetworkTopologyIEEE1905DeviceInterfaceParams, NULL, BBFDM_BOTH, NULL},
{"NonIEEE1905Neighbor", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905NeighborInst, NULL, NULL, NULL, tIEEE1905ALNetworkTopologyIEEE1905DeviceNonIEEE1905NeighborParams, NULL, BBFDM_BOTH, NULL},
{"IEEE1905Neighbor", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborInst, NULL, NULL, tIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborObj, tIEEE1905ALNetworkTopologyIEEE1905DeviceIEEE1905NeighborParams, NULL, BBFDM_BOTH, NULL},
{"BridgingTuple", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALNetworkTopologyIEEE1905DeviceBridgingTupleInst, NULL, NULL, NULL, tIEEE1905ALNetworkTopologyIEEE1905DeviceBridgingTupleParams, NULL, BBFDM_BOTH, NULL},
{0}
};

/* *** Device.IEEE1905.AL.NetworkTopology. *** */
DMOBJ tIEEE1905ALNetworkTopologyObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"IEEE1905Device", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALNetworkTopologyIEEE1905DeviceInst, NULL, NULL, tIEEE1905ALNetworkTopologyIEEE1905DeviceObj, tIEEE1905ALNetworkTopologyIEEE1905DeviceParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tIEEE1905ALNetworkTopologyParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"Enable", &DMWRITE, DMT_BOOL, get_IEEE1905ALNetworkTopology_Enable, set_IEEE1905ALNetworkTopology_Enable, BBFDM_BOTH},
{"Status", &DMREAD, DMT_STRING, get_IEEE1905ALNetworkTopology_Status, NULL, BBFDM_BOTH},
{"IEEE1905DeviceNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALNetworkTopology_IEEE1905DeviceNumberOfEntries, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.Interface.{i}.Link.{i}.Metric. *** */
DMLEAF tIEEE1905ALInterfaceLinkMetricParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"IEEE802dot1Bridge", &DMREAD, DMT_BOOL, get_IEEE1905ALInterfaceLinkMetric_IEEE802dot1Bridge, NULL, BBFDM_BOTH},
{"PacketErrors", &DMREAD, DMT_UNINT, get_IEEE1905ALInterfaceLinkMetric_PacketErrors, NULL, BBFDM_BOTH},
{"PacketErrorsReceived", &DMREAD, DMT_UNINT, get_IEEE1905ALInterfaceLinkMetric_PacketErrorsReceived, NULL, BBFDM_BOTH},
{"TransmittedPackets", &DMREAD, DMT_UNINT, get_IEEE1905ALInterfaceLinkMetric_TransmittedPackets, NULL, BBFDM_BOTH},
{"PacketsReceived", &DMREAD, DMT_UNINT, get_IEEE1905ALInterfaceLinkMetric_PacketsReceived, NULL, BBFDM_BOTH},
{"MACThroughputCapacity", &DMREAD, DMT_UNINT, get_IEEE1905ALInterfaceLinkMetric_MACThroughputCapacity, NULL, BBFDM_BOTH},
{"PHYRate", &DMREAD, DMT_UNINT, get_IEEE1905ALInterfaceLinkMetric_PHYRate, NULL, BBFDM_BOTH},
{"RSSI", &DMREAD, DMT_UNINT, get_IEEE1905ALInterfaceLinkMetric_RSSI, NULL, BBFDM_BOTH},
{0}
};

DMLEAF tIEEE1905ALInterfaceLinkParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"InterfaceId", &DMREAD, DMT_STRING, get_IEEE1905ALInterfaceLink_InterfaceId, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"IEEE1905Id", &DMREAD, DMT_STRING, get_IEEE1905ALInterfaceLink_IEEE1905Id, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"MediaType", &DMREAD, DMT_STRING, get_IEEE1905ALInterfaceLink_MediaType, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.Interface.{i}.Link.{i}. *** */
DMOBJ tIEEE1905ALInterfaceLinkObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"Metric", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIEEE1905ALInterfaceLinkMetricParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tIEEE1905ALInterfaceParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"InterfaceId", &DMREAD, DMT_STRING, get_IEEE1905ALInterface_InterfaceId, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"Status", &DMREAD, DMT_STRING, get_IEEE1905ALInterface_Status, NULL, BBFDM_BOTH},
{"LowerLayers", &DMREAD, DMT_STRING, get_IEEE1905ALInterface_LowerLayers, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"MediaType", &DMREAD, DMT_STRING, get_IEEE1905ALInterface_MediaType, NULL, BBFDM_BOTH},
{"PowerState", &DMWRITE, DMT_STRING, get_IEEE1905ALInterface_PowerState, set_IEEE1905ALInterface_PowerState, BBFDM_BOTH},
{"LinkNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905ALInterface_LinkNumberOfEntries, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL.Interface.{i}. *** */
DMOBJ tIEEE1905ALInterfaceObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"Link", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALInterfaceLinkInst, NULL, NULL, tIEEE1905ALInterfaceLinkObj, tIEEE1905ALInterfaceLinkParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tIEEE1905ALParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"IEEE1905Id", &DMREAD, DMT_STRING, get_IEEE1905AL_IEEE1905Id, NULL, BBFDM_BOTH},
{"Status", &DMREAD, DMT_STRING, get_IEEE1905AL_Status, NULL, BBFDM_BOTH},
{"RegistrarFreqBand", &DMREAD, DMT_STRING, get_IEEE1905AL_RegistrarFreqBand, NULL, BBFDM_BOTH},
{"InterfaceNumberOfEntries", &DMREAD, DMT_UNINT, get_IEEE1905AL_InterfaceNumberOfEntries, NULL, BBFDM_BOTH},
{BBF_VENDOR_PREFIX"LocalOnlyMode", &DMWRITE, DMT_BOOL, get_IEEE1905AL_LocalOnlyMode, set_IEEE1905AL_LocalOnlyMode, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905.AL. *** */
DMOBJ tIEEE1905ALObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"Interface", &DMREAD, NULL, NULL, NULL, browseIEEE1905ALInterfaceInst, NULL, NULL, tIEEE1905ALInterfaceObj, tIEEE1905ALInterfaceParams, NULL, BBFDM_BOTH, NULL},
{"NetworkTopology", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIEEE1905ALNetworkTopologyObj, tIEEE1905ALNetworkTopologyParams, NULL, BBFDM_BOTH, NULL},
{"Security", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIEEE1905ALSecurityParams, NULL, BBFDM_BOTH, NULL},
{"NetworkingRegistrar", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIEEE1905ALNetworkingRegistrarParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tIEEE1905Params[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
{"Version", &DMREAD, DMT_STRING, get_IEEE1905_Version, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.IEEE1905. *** */
DMOBJ tIEEE1905Obj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"AL", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIEEE1905ALObj, tIEEE1905ALParams, NULL, BBFDM_BOTH, NULL},
{"Network", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIEEE1905NetworkObj, tIEEE1905NetworkParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMOBJ tDeviceObjs[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"IEEE1905", &DMREAD, NULL, NULL, "file:/etc/config/ieee1905", NULL, NULL, NULL, tIEEE1905Obj, tIEEE1905Params, NULL, BBFDM_BOTH, NULL},
{0}
};

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