diff --git a/src/1905_tlvs.h b/src/1905_tlvs.h
index 616815854e4b6442f1ad3a2dcf74f38db923f3c7..268180ba77746e9f7f7133bf054f9e47afb743d4 100644
--- a/src/1905_tlvs.h
+++ b/src/1905_tlvs.h
@@ -1,17 +1,44 @@
 /*
- * 1905_tlvs.h: IEEE-1905 TLV related functions
+ * 1905_tlvs.h: 1905 tlvs definition in flat format.
  */
 
 #ifndef _1905_TLVS_H_
 #define _1905_TLVS_H_
 
 #include <stdint.h>
-#include <stdbool.h>
-#include <linux/types.h>
-
-
 
 
+/* 1905 CMDU types */
+#define CMDU_TYPE_TOPOLOGY_DISCOVERY               0x0000
+#define CMDU_TYPE_TOPOLOGY_NOTIFICATION            0x0001
+#define CMDU_TYPE_TOPOLOGY_QUERY                   0x0002
+#define CMDU_TYPE_TOPOLOGY_RESPONSE                0x0003
+#define CMDU_TYPE_VENDOR_SPECIFIC                  0x0004
+#define CMDU_TYPE_LINK_METRIC_QUERY                0x0005
+#define CMDU_TYPE_LINK_METRIC_RESPONSE             0x0006
+#define CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH      0x0007
+#define CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE    0x0008
+#define CMDU_TYPE_AP_AUTOCONFIGURATION_WSC         0x0009
+#define CMDU_TYPE_AP_AUTOCONFIGURATION_RENEW       0x000a
+#define CMDU_TYPE_PUSH_BUTTON_EVENT_NOTIFICATION   0x000b
+#define CMDU_TYPE_PUSH_BUTTON_JOIN_NOTIFICATION    0x000c
+#define CMDU_TYPE_HIGHER_LAYER_QUERY               0x000d
+#define CMDU_TYPE_HIGHER_LAYER_RESPONSE            0x000e
+#define CMDU_TYPE_INTERFACE_POWER_CHANGE_REQUEST   0x000f
+#define CMDU_TYPE_INTERFACE_POWER_CHANGE_RESPONSE  0x0010
+#define CMDU_TYPE_GENERIC_PHY_QUERY                0x0011
+#define CMDU_TYPE_GENERIC_PHY_RESPONSE             0x0012
+#define LAST_1905_CMDU                             CMDU_TYPE_GENERIC_PHY_RESPONSE
+
+#define CMDU_TYPE_MAX                              LAST_1905_CMDU
+#define CMDU_TYPE_NONE                             0xffff
+
+/* 1905 CMDU version */
+#define CMDU_MESSAGE_VERSION_1905_1_2013           0x00
+
+
+
+/* 1905 TLV types */
 #define TLV_TYPE_END_OF_MESSAGE                      (0)
 #define TLV_TYPE_AL_MAC_ADDRESS_TYPE                 (1)
 #define TLV_TYPE_MAC_ADDRESS_TYPE                    (2)
@@ -63,7 +90,6 @@
 #define MEDIA_TYPE_UNKNOWN                         (0xFFFF)
 
 
-
 /* IEEE802.11 frequency bands */
 #define IEEE80211_FREQUENCY_BAND_2_4_GHZ           (0x00)
 #define IEEE80211_FREQUENCY_BAND_5_GHZ             (0x01)
@@ -86,7 +112,7 @@ typedef uint8_t macaddr_t[6];
 
 /* TLV: End of message */
 struct tlv_eom {
-};
+} __attribute__((packed));
 
 /* TLV: Vendor specific info */
 struct tlv_vendor_specific {
@@ -153,10 +179,9 @@ struct tlv_device_bridge_caps {
 } __attribute__((packed));
 
 
-
 struct non1905_neighbor {
 	uint8_t macaddr[6];
-};
+} __attribute__((packed));
 
 /* TLV: non-1905 neighbor devices */
 struct tlv_non1905_neighbor {
@@ -192,7 +217,7 @@ struct tlv_linkmetric_query {
 	uint8_t nbr_type;
 	uint8_t nbr_macaddr[6];
 	uint8_t query_type;
-};
+} __attribute__((packed));
 
 struct tx_link_info {
 	uint8_t local_macaddr[6];
@@ -293,401 +318,176 @@ struct tlv_pbc_join_notification {
 
 
 
-
-////////////////////////////////////////////////////////////////////////////////
-// Generic PHY device information TLV associated structures ("Section 6.4.21")
-////////////////////////////////////////////////////////////////////////////////
-//
-/* Generic phy common structure used in "Tables 6.29, 6.36 and 6.38" */
-struct _genericPhyCommonData {
+/* TLV: generic phy device information */
+struct generic_phy_data {
 	uint8_t oui[3];
 	uint8_t variant_index;
-	uint8_t media_specific_bytes_nr;
-	uint8_t *media_specific_bytes;
-};
-
-struct _genericPhyDeviceEntries {
-	uint8_t local_interface_address[6];
-	// MAC address of the local interface
-
-	struct _genericPhyCommonData generic_phy_common_data;
-	// This structure contains the OUI,
-	// variant index and media specific
-	// information of the local interface
-
-	uint8_t variant_name[32];	// Variant name UTF-8 string (NULL
-	// terminated)
-
-	uint8_t generic_phy_description_xml_url_len;
-	char *generic_phy_description_xml_url;
-	// URL to the "Generic Phy XML Description
-	// Document" of the variant.
-	// The string is
-	// 'generic_phy_description_xml_url_len'
-	// bytes long including the final NULL
-	// character.
-
-};
-struct genericPhyDeviceInformationTypeTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_GENERIC_PHY_DEVICE_INFORMATION
-
-	uint8_t al_mac_address[6];	// 1905 AL MAC address of the device
-
-	uint8_t local_interfaces_nr;
-	struct _genericPhyDeviceEntries *local_interfaces;
-	// List of local interfaces that are
-	// going to be reported as
-	// MEDIA_TYPE_UNKNOWN
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Device identification type TLV associated structures ("Section 6.4.22")
-////////////////////////////////////////////////////////////////////////////////
-struct deviceIdentificationTypeTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_DEVICE_IDENTIFICATION
-
-	char friendly_name[64];	// Friendly name UTF-8 string (NULL
-	// terminated)
-
-	char manufacturer_name[64];	// Manufacturer name UTF-8 string (NULL
-	// terminated)
-
-	char manufacturer_model[64];	// Manufacturer modem UTF-8 string (NULL
-	// terminated)
-
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Control URL type TLV associated structures ("Section 6.4.23")
-////////////////////////////////////////////////////////////////////////////////
-struct controlUrlTypeTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_CONTROL_URL
-
-	char *url;		// Pointer to a NULL terminated string
-	// containing the URL to a control or
-	// WebUI of the device
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// IPv4 type TLV associated structures ("Section 6.4.24")
-////////////////////////////////////////////////////////////////////////////////
-struct _ipv4Entries {
-#define IPV4_TYPE_UNKNOWN (0)
-#define IPV4_TYPE_DHCP    (1)
-#define IPV4_TYPE_STATIC  (2)
-#define IPV4_TYPE_AUTOIP  (3)
-	uint8_t type;		// One of the values from above
-
-	uint8_t ipv4_address[4];	// IPv4 address associated to the interface
-
-	uint8_t ipv4_dhcp_server[4];	// IPv4 address of the DHCP server (if
-	// known, otherwise set to all zeros)
-};
-struct _ipv4InterfaceEntries {
-	uint8_t mac_address[6];	// MAC address of the interface whose IPv4s
-	// are going to be reported.
-	//
-	//   NOTE: The standard says it can also
-	//   be an AL MAC address instead of an
-	//   interface MAC address.
-	//   In that case I guess *all* IPv4s of
-	//   the device (no matter the interface
-	//   they are "binded" to) are reported.
-
-	uint8_t ipv4_nr;
-	struct _ipv4Entries *ipv4;	// List of IPv4s associated to this
-	// interface
-};
-struct ipv4TypeTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_IPV4
-
-	uint8_t ipv4_interfaces_nr;
-	struct _ipv4InterfaceEntries *ipv4_interfaces;
-	// List of interfaces with at least one
-	// IPv4 assigned
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// IPv6 type TLV associated structures ("Section 6.4.25")
-////////////////////////////////////////////////////////////////////////////////
-struct _ipv6Entries {
-#define IPV6_TYPE_UNKNOWN (0)
-#define IPV6_TYPE_DHCP    (1)
-#define IPV6_TYPE_STATIC  (2)
-#define IPV6_TYPE_SLAAC   (3)
-	uint8_t type;		// One of the values from above
-
-	uint8_t ipv6_address[16];	// IPv6 address associated to the interface
-
-	uint8_t ipv6_address_origin[16];	// If type == IPV6_TYPE_DHCP, this field
-	// contains the IPv6 address of the DHCPv6
-	// server.
-	// If type == IPV6_TYPE_SLAAC, this field
-	// contains the IPv6 address of the router
-	// that provided the SLAAC address.
-	// In any other case this field is set to
-	// all zeros.
-};
-struct _ipv6InterfaceEntries {
-	uint8_t mac_address[6];	// MAC address of the interface whose IPv4s
-	// are going to be reported.
-	//
-	//   NOTE: The standard says it can also
-	//   be an AL MAC address instead of an
-	//   interface MAC address.
-	//   In that case I guess *all* IPv4s of
-	//   the device (no matter the interface
-	//   they are "binded" to) are reported.
-
-	uint8_t ipv6_link_local_address[16];
-	// IPv6 link local address corresponding to
-	// this interface
-
-	uint8_t ipv6_nr;
-	struct _ipv6Entries *ipv6;	// List of IPv4s associated to this
-	// interface
-};
+	uint8_t variant_name[32];
+	uint8_t sizeof_url;
+	uint8_t sizeof_mediainfo;
+	uint8_t url_plus_mediainfo[];
+} __attribute__((packed));
+
+struct generic_phy_interface {
+	uint8_t macaddr[6];
+	struct generic_phy_data data;
+} __attribute__((packed));
+
+struct tlv_generic_phy_devinfo {
+	uint8_t aladdr[6];
+	uint8_t num_interfaces;
+	struct generic_phy_interface interface[];
+} __attribute__((packed));
+
+
+/* TLV: device identification */
+struct tlv_device_identification {
+	uint8_t name[64];
+	uint8_t manufacturer[64];
+	uint8_t model[64];
+} __attribute__((packed));
+
+
+/* TLV: control URL */
+struct tlv_control_url {
+	uint8_t url[0];
+} __attribute__((packed));
+
+
+
+#define IPV4_TYPE_UNKNOWN	0
+#define IPV4_TYPE_DHCP		1
+#define IPV4_TYPE_STATIC	2
+#define IPV4_TYPE_AUTOIP	3
+
+struct ipv4_entry {
+	uint8_t type;
+	uint8_t address[4];
+	uint8_t dhcp_server[4];
+} __attribute__((packed));
+
+struct ipv4_interface {
+	uint8_t macaddr[6];
+	uint8_t num_ipv4;
+	struct ipv4_entry ipv4[];
+} __attribute__((packed));
+
+/* TLV: IPv4 TLV */
+struct tlv_ipv4 {
+	uint8_t num_interfaces;
+	struct ipv4_interface interface[];
+} __attribute__((packed));
+
+
+
+
+#define IPV6_TYPE_UNKNOWN	0
+#define IPV6_TYPE_DHCP		1
+#define IPV6_TYPE_STATIC	2
+#define IPV6_TYPE_SLAAC		3
+
+struct ipv6_entry {
+	uint8_t type;
+	uint8_t address[16];
+	uint8_t origin[16];
+} __attribute__((packed));
+
+struct ipv6_interface {
+	uint8_t macaddr[6];
+	uint8_t link_local_address[16];
+	uint8_t num_ipv6;
+	struct ipv6_entry ipv6[];
+} __attribute__((packed));
+
+/* TLV: IPv6 TLV */
 struct ipv6TypeTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_IPV6
-
-	uint8_t ipv6_interfaces_nr;
-	struct _ipv6InterfaceEntries *ipv6_interfaces;
-	// List of interfaces with at least one
-	// IPv6 assigned
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Push button generic PHY event notification TLV associated structures
-// ("Section 6.4.26")
-////////////////////////////////////////////////////////////////////////////////
-struct pushButtonGenericPhyEventNotificationTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_GENERIC_PHY_EVENT_NOTIFICATION
-
-	uint8_t local_interfaces_nr;
-	struct _genericPhyCommonData *local_interfaces;
-	// List of local interfaces of type
-	// MEDIA_TYPE_UNKNOWN for which a push button
-	// configuration method has been activated on
-	// the device that originates the push button
-	// event notification
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Profile version TLV associated structures ("Section 6.4.27")
-////////////////////////////////////////////////////////////////////////////////
-struct x1905ProfileVersionTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_1905_PROFILE_VERSION
+	uint8_t num_interfaces;
+	struct ipv6_interface interface[];
+} __attribute__((packed));
+
+
+
+/* TLV: Push button generic PHY event notification */
+struct tlv_pbc_generic_phy_notification {
+	uint8_t num_genphys;
+	struct {
+		uint8_t oui[3];
+		uint8_t variant_index;
+		uint8_t sizeof_mediainfo;
+		uint8_t mediainfo[];
+	} genphy[];
+} __attribute__((packed));
+
 
 #define PROFILE_1905_1   (0x00)
 #define PROFILE_1905_1A  (0x01)
-	uint8_t profile;		// One of the values from above
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Power off interface TLV associated structures ("Section 6.4.28")
-////////////////////////////////////////////////////////////////////////////////
-struct _powerOffInterfaceEntries {
-	uint8_t interface_address[6];	// MAC address of an interface in the
-	// "power off" state
-
-	uint16_t media_type;	// Underlaying network technology
-	// One of the MEDIA_TYPE_* values
-
-	struct _genericPhyCommonData generic_phy_common_data;
-	// If 'media_type' is MEDIA_TYPE_UNKNOWN,
-	// this structure contains the vendor OUI,
-	// variant index and media specific
-	// information of the interface
-	// Otherwise, it is set to all zeros
-};
-struct powerOffInterfaceTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_POWER_OFF_INTERFACE
-
-	uint8_t power_off_interfaces_nr;
-	struct _powerOffInterfaceEntries *power_off_interfaces;
-	// List of local interfaces in the "power
-	// off" state.
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Interface power change information TLV associated structures ("Section
-// 6.4.29")
-////////////////////////////////////////////////////////////////////////////////
-struct _powerChangeInformationEntries {
-	uint8_t interface_address[6];	// MAC address of an interface in the
-	// "power off" state
-
-#define POWER_STATE_REQUEST_OFF  (0x00)
-#define POWER_STATE_REQUEST_ON   (0x01)
-#define POWER_STATE_REQUEST_SAVE (0x02)
-	uint8_t requested_power_state;	// One of the values from above
-};
-struct interfacePowerChangeInformationTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_INTERFACE_POWER_CHANGE_INFORMATION
-
-	uint8_t power_change_interfaces_nr;
-	struct _powerChangeInformationEntries *power_change_interfaces;
-	// List of local interfaces for which a power
-	// status change is requested
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Interface power change status TLV associated structures ("Section 6.4.29")
-////////////////////////////////////////////////////////////////////////////////
-struct _powerChangeStatusEntries {
-	uint8_t interface_address[6];	// MAC address of an interface in the
-	// "power off" state
-
-#define POWER_STATE_RESULT_COMPLETED          (0x00)
-#define POWER_STATE_RESULT_NO_CHANGE          (0x01)
-#define POWER_STATE_RESULT_ALTERNATIVE_CHANGE (0x02)
-	uint8_t result;		// One of the values from above
-};
-struct interfacePowerChangeStatusTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_INTERFACE_POWER_CHANGE_STATUS
-
-	uint8_t power_change_interfaces_nr;
-	struct _powerChangeStatusEntries *power_change_interfaces;
-	// List of local interfaces whose power status
-	// change operation result is being reported
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// L2 neighbor device TLV associated structures ("Section 6.4.31")
-////////////////////////////////////////////////////////////////////////////////
-struct _l2NeighborsEntries {
-	uint8_t l2_neighbor_mac_address[6];	// MAC address of remote interface
-	// sharing the same L2 medium
-
-	uint16_t behind_mac_addresses_nr;
-	 uint8_t(*behind_mac_addresses)[6];	// List of MAC addresses the remote
-	// device (owner of the remote
-	// interface) "knows" and that are
-	// not visible on this interface.
-	// TODO: Define better !!!
-};
-struct _l2InterfacesEntries {
-	uint8_t local_mac_address[6];	// MAC address of the local interface whose
-	// L2 neighbors are going to be reported
-
-	uint16_t l2_neighbors_nr;
-	struct _l2NeighborsEntries *l2_neighbors;
-	// List of neighbors that share the same L2
-	// medium as the local interface
-};
-struct l2NeighborDeviceTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_L2_NEIGHBOR_DEVICE
-
-	uint8_t local_interfaces_nr;
-	struct _l2InterfacesEntries *local_interfaces;
-	// List of interfaces with at least one
-	// IPv4 assigned
-};
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Main API functions
-////////////////////////////////////////////////////////////////////////////////
-
-// This function receives a pointer to a stream of bytes representing a 1905
-// TLV according to "Section 6.4"
-//
-// It then returns a pointer to a structure whose fields have already been
-// filled with the appropiate values extracted from the parsed stream.
-//
-// The actual type of the returned pointer structure depends on the value of
-// the first byte pointed by "packet_stream" (ie. the "Type" field of the TLV):
-//
-//   TLV_TYPE_END_OF_MESSAGE                  -->  struct endOfMessageTLV *
-//   TLV_TYPE_VENDOR_SPECIFIC                 -->  struct vendorSpecificTLV *
-//   TLV_TYPE_AL_MAC_ADDRESS_TYPE             -->  struct alMacAddressTypeTLV *
-//   TLV_TYPE_MAC_ADDRESS_TYPE                -->  struct macAddressTypeTLV *
-//   TLV_TYPE_DEVICE_INFORMATION_TYPE         -->  struct deviceInformationTypeTLV *
-//   TLV_TYPE_DEVICE_BRIDGING_CAPABILITIES    -->  struct deviceBridgingCapabilityTLV *
-//   TLV_TYPE_NON_1905_NEIGHBOR_DEVICE_LIST   -->  struct non1905NeighborDeviceListTLV *
-//   TLV_TYPE_NEIGHBOR_DEVICE_LIST            -->  struct neighborDeviceListTLV *
-//   TLV_TYPE_LINK_METRIC_QUERY               -->  struct linkMetricQueryTLV *
-//   TLV_TYPE_TRANSMITTER_LINK_METRIC         -->  struct transmitterLinkMetricTLV *
-//   TLV_TYPE_RECEIVER_LINK_METRIC            -->  struct receiverLinkMetricTLV *
-//   TLV_TYPE_LINK_METRIC_RESULT_CODE         -->  struct linkMetricResultCodeTLV *
-//   TLV_TYPE_SEARCHED_ROLE                   -->  struct searchedRoleTLV *
-//   TLV_TYPE_AUTOCONFIG_FREQ_BAND            -->  struct autoconfigFreqBandTLV *
-//   TLV_TYPE_SUPPORTED_ROLE                  -->  struct supportedRoleTLV *
-//   TLV_TYPE_SUPPORTED_FREQ_BAND             -->  struct supportedFreqBandTLV *
-//   TLV_TYPE_WSC                             -->  struct wscTLV *
-//   TLV_TYPE_PUSH_BUTTON_EVENT_NOTIFICATION  -->  struct pushButtonEventNotificationTLV *
-//   TLV_TYPE_PUSH_BUTTON_JOIN_NOTIFICATION   -->  struct pushButtonJoinNotificationTLV *
-//
-// If an error was encountered while parsing the stream, a NULL pointer is
-// returned instead.
-// Otherwise, the returned structure is dynamically allocated, and once it is
-// no longer needed, the user must call the "free_1905_TLV_structure()" function
-//
-uint8_t *parse_1905_TLV_from_packet(uint8_t *packet_stream);
-
-// This is the opposite of "parse_1905_TLV_from_packet()": it receives a
-// pointer to a TLV structure and then returns a pointer to a buffer which:
-//   - is a packet representation of the TLV
-//
-// "memory_structure" must point to a structure of one of the types returned by
-// "parse_1905_TLV_from_packet()"
-//
-// If there is a problem this function returns NULL, otherwise the returned
-// buffer must be later freed by the caller (it is a regular, non-nested buffer,
-// so you just need to call "free()").
-//
-// Note that the input structure is *not* freed. You still need to later call
-// "free_1905_TLV_structure()"
-//
-uint8_t *forge_1905_TLV_from_structure(uint8_t *memory_structure);
-
-////////////////////////////////////////////////////////////////////////////////
-// Utility API functions
-////////////////////////////////////////////////////////////////////////////////
-
-// This function receives a pointer to a TLV structure and then traverses it
-// and all nested structures, calling "free()" on each one of them
-//
-// "memory_structure" must point to a structure of one of the types returned by
-// "parse_1905_TLV_from_packet()"
-//
-void free_1905_TLV_structure(uint8_t *memory_structure, bool all);
-
-// 'forge_1905_TLV_from_structure()' returns a regular buffer which can be freed
-// using this macro defined to be FREE
-//
-#define  free_1905_TLV_packet  FREE
-
-// This function returns '0' if the two given pointers represent TLV structures
-// of the same type and they contain the same data
-//
-// "memory_structure_1" and "memory_structure_2" must point (each) to a
-// structure of one of the types returned by "parse_1905_TLV_from_packet()"
-//
-uint8_t compare_1905_TLV_structures(uint8_t *memory_structure_1, uint8_t *memory_structure_2);
-
-// Use this function for debug purposes. It turns a TLV_TYPE_* variable into its
-// string representation.
-//
-// Example: TLV_TYPE_AL_MAC_ADDRESS_TYPE --> "TLV_TYPE_AL_MAC_ADDRESS_TYPE"
-//
-// Return "Unknown" if the provided type does not exist.
-//
-char *convert_1905_TLV_type_to_string(uint8_t tlv_type);
-
-char *convert_band_to_string(uint8_t freq_band);
-bool get_freq_band_from_media_type(uint16_t media_type, uint8_t *freq_band);
-
-#endif
+
+/* TLV: 1905 profile version */
+struct tlv_1905_profile {
+	uint8_t version;
+} __attribute__((packed));
+
+
+/* TLV: Power off interface */
+struct tlv_power_off {
+	uint8_t num_interfaces;
+	struct {
+		uint8_t macaddr[6];
+		uint16_t media_type;
+		uint8_t oui[3];
+		uint8_t variant_index;
+		uint8_t sizeof_mediainfo;
+		uint8_t mediainfo[];
+	} interface[];
+} __attribute__((packed));
+
+
+#define POWER_REQUEST_OFF	0x00
+#define POWER_REQUEST_ON	0x01
+#define POWER_REQUEST_SAVE	0x02
+
+/* TLV: interface power change information */
+struct tlv_powerchange_request {
+	uint8_t num_interfaces;
+	struct {
+		uint8_t macaddr[6];
+		uint8_t power;
+	} interface[];
+} __attribute__((packed));
+
+
+
+#define POWER_CHANGE_OK		0x00
+#define POWER_CHANGE_NOK	0x01
+#define POWER_CHANGE_ALT	0x02
+
+/* TLV: interface power change status */
+struct tlv_powerchange_status {
+	uint8_t num_interfaces;
+	struct {
+		uint8_t macaddr[6];
+		uint8_t status;
+	} interface[];
+} __attribute__((packed));
+
+
+/* TLV: L2 neighbor device */
+struct l2_interface_neighbor {
+	uint8_t macaddr[6];
+	uint16_t num_behind_macs;
+	uint8_t behind_macaddrs[];
+} __attribute__((packed));
+
+struct l2_interface {
+	uint8_t macaddr[6];
+	uint16_t num_l2_neighbors;
+	struct l2_interface_neighbor l2_nbr[];
+} __attribute__((packed));
+
+struct tlv_l2_neighbor {
+	uint8_t num_interfaces;
+	struct l2_interface interface[];
+} __attribute__((packed));
+
+
+#endif	/* _1905_TLVS_H_ */
diff --git a/src/Makefile b/src/Makefile
index 5796dccaaedf26e2605c0e4f57dfeca253c2ef58..6de4480bda7499022849cc71c8c9b5ad53e50a60 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -13,6 +13,7 @@ OBJS = cmdu.o \
        main.o \
        timer.o \
        util.o \
+       cmdu_ackq.o \
        cmduqueue.o \
        worker.o
 
diff --git a/src/cmdu.c b/src/cmdu.c
index 606d18848a7793aebfb29115c7b542692b6dc38e..9fd851e44f2f51ded0687b7d68fa5be9373fd12a 100644
--- a/src/cmdu.c
+++ b/src/cmdu.c
@@ -8,7 +8,8 @@
 
 #include "util.h"
 #include "bufutil.h"
-#include "1905_defs.h"
+//#include "1905_defs.h"
+#include "1905_tlvs.h"
 #include "cmdu.h"
 
 
@@ -61,10 +62,20 @@ uint16_t tlv_total_length(struct tlv *t)
 
 uint16_t g_mid;
 
+uint16_t cmdu_init_mid(void)
+{
+	uint8_t b[2];
+
+	get_random_bytes(2, b);
+	g_mid = *(uint16_t *)b;
+
+	return (g_mid == 0) ? g_mid = 1 : g_mid; 
+}
+
 
 uint16_t cmdu_get_next_mid(void)
 {
-	return g_mid++;
+	return (g_mid % 0xffff == 0) ? g_mid += 2: g_mid++;
 }
 
 int is_cmdu_type_valid(uint16_t type)
@@ -73,7 +84,7 @@ int is_cmdu_type_valid(uint16_t type)
 		type <= CMDU_TYPE_MAX);
 }
 
-static int cmdu_should_relay(uint16_t type)
+int cmdu_should_relay(uint16_t type)
 {
 	return (type == CMDU_TYPE_TOPOLOGY_NOTIFICATION ||
 		type == CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH ||
@@ -82,6 +93,41 @@ static int cmdu_should_relay(uint16_t type)
 		type == CMDU_TYPE_PUSH_BUTTON_JOIN_NOTIFICATION);
 }
 
+int is_cmdu_type_response(uint16_t type)
+{
+	return (type == CMDU_TYPE_TOPOLOGY_RESPONSE ||
+		type == CMDU_TYPE_LINK_METRIC_RESPONSE ||
+		type == CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE ||
+		type == CMDU_TYPE_HIGHER_LAYER_RESPONSE ||
+		type == CMDU_TYPE_INTERFACE_POWER_CHANGE_RESPONSE);
+}
+
+uint16_t cmdu_expect_response(uint16_t req_type)
+{
+	switch (req_type) {
+		case CMDU_TYPE_TOPOLOGY_QUERY:
+			return CMDU_TYPE_TOPOLOGY_RESPONSE;
+		case CMDU_TYPE_LINK_METRIC_QUERY:
+			return CMDU_TYPE_LINK_METRIC_RESPONSE;
+		case CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH:
+			return CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE;
+		case CMDU_TYPE_AP_AUTOCONFIGURATION_WSC:
+			return CMDU_TYPE_AP_AUTOCONFIGURATION_WSC;
+		case CMDU_TYPE_AP_AUTOCONFIGURATION_RENEW:
+			return CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE;
+		case CMDU_TYPE_HIGHER_LAYER_QUERY:
+			return CMDU_TYPE_HIGHER_LAYER_RESPONSE;
+		case CMDU_TYPE_INTERFACE_POWER_CHANGE_REQUEST:
+			return CMDU_TYPE_INTERFACE_POWER_CHANGE_RESPONSE;
+		case CMDU_TYPE_GENERIC_PHY_QUERY:
+			return CMDU_TYPE_GENERIC_PHY_RESPONSE;
+		default:
+			break;
+	}
+
+	return CMDU_TYPE_NONE;
+}
+
 struct cmdu_buff *cmdu_alloc(int size)
 {
 #define CMDU_RESERVE_HEADSPACE	32
diff --git a/src/cmdu.h b/src/cmdu.h
index 5792134fa1bb48feb3d231d07c8686bff7812f52..7d33b4a3505189d86ca2ad57675c04e9efb99f9b 100644
--- a/src/cmdu.h
+++ b/src/cmdu.h
@@ -24,6 +24,8 @@ struct cmdu_header {
 #define CMDU_SET_LAST_FRAGMENT(c)	(c)->hdr.flag |= 0x80
 #define CMDU_SET_RELAY_MCAST(c)		(c)->hdr.flag |= 0x40
 
+#define CMDU_DEFAULT_TIMEOUT		2000
+
 
 struct cmdu_linear {
 	struct cmdu_header hdr;
@@ -83,6 +85,11 @@ void cmdu_free(struct cmdu_buff *c);
 
 int cmdu_size(struct cmdu_buff *c);
 uint16_t cmdu_get_next_mid(void);
+uint16_t cmdu_init_mid(void);
+uint16_t cmdu_expect_response(uint16_t req_type);
+int cmdu_should_relay(uint16_t type);
+int is_cmdu_type_valid(uint16_t type);
+int is_cmdu_type_response(uint16_t type);
 
 int cmdu_validate(struct cmdu_buff *c, int max_tlvtype,
 		       struct tlv_policy *policy);
diff --git a/src/cmdu_ackq.c b/src/cmdu_ackq.c
new file mode 100644
index 0000000000000000000000000000000000000000..9dd93d54ab8a4389b1eb7617c14a1866a1689703
--- /dev/null
+++ b/src/cmdu_ackq.c
@@ -0,0 +1,291 @@
+/*
+ * delm_cmdu_ackq.c
+ * CMDU response and ack queue management
+ *
+ * Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved.
+ *
+ * Author: anjan.chanda@iopsys.eu
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+#include <easy/easy.h>
+
+#include "timer.h"
+#include "cmdu_ackq.h"
+
+static int timeradd_msecs(struct timeval *a, unsigned long msecs,
+			  struct timeval *res)
+{
+	if (res) {
+		struct timeval t = { 0 };
+
+		if (msecs > 1000) {
+			t.tv_sec += msecs / 1000;
+			t.tv_usec = (msecs % 1000) * 1000;
+		} else {
+			t.tv_usec = msecs * 1000;
+		}
+
+		timeradd(a, &t, res);
+		return 0;
+	}
+
+	return -1;
+}
+
+struct cmdu_ackq_entry *cmdu_ackq_create_msg(uint16_t type, uint16_t mid,
+					     uint8_t *dest, uint32_t timeout)
+{
+	struct cmdu_ackq_entry *msg;
+	struct timeval tsp = { 0 };
+
+	msg = calloc(1, sizeof(*msg));
+	if (!msg) {
+		fprintf(stderr, "calloc failed. err = NOMEM\n");
+		return NULL;
+	}
+
+	msg->type = type;
+	msg->mid = mid;
+	gettimeofday(&tsp, NULL);
+	msg->ageing_time = timeout;
+	timeradd_msecs(&tsp, msg->ageing_time, &msg->ageing_tmo);
+
+	//msg->ageing_tmo.tv_usec = roundup(msg->ageing_tmo.tv_usec, 1000);
+	msg->ageing_tmo.tv_usec = (msg->ageing_tmo.tv_usec / 1000) * 1000;
+	memcpy(msg->origin, dest, 6);
+	fprintf(stderr,
+		"    CREATE msg: type = 0x%04x  mid = %hu origin = " MACFMT " timeout = { %u (%lu:%lu) }\n",
+		type, mid, MAC2STR(dest), msg->ageing_time, msg->ageing_tmo.tv_sec, msg->ageing_tmo.tv_usec / 1000);
+
+	return msg;
+}
+
+static void cmdu_ackq_delete_msg(struct cmdu_ackq_entry *msg)
+{
+	if (msg)
+		free(msg);
+}
+
+static void cmdu_ackq_ageout_entry(struct cmdu_ackq *st, struct hlist_head *head,
+				   struct timeval *min_next_tmo)
+{
+	struct cmdu_ackq_entry *msg;
+	struct hlist_node *tmp;
+	struct timeval now = { 0 };
+
+
+	gettimeofday(&now, NULL);
+	now.tv_usec = (now.tv_usec / 1000) * 1000;
+
+
+	hlist_for_each_entry_safe(msg, tmp, head, hlist) {
+		fprintf(stderr, "%s(): Entry msg->ageout = (%lu.%lu), now = (%lu.%lu)\n",
+				__func__,
+				msg->ageing_tmo.tv_sec, msg->ageing_tmo.tv_usec,
+				now.tv_sec, now.tv_usec);
+
+		if (timercmp(&msg->ageing_tmo, &now, <=)) {
+			st->pending_cnt--;
+			hlist_del(&msg->hlist, head);
+			fprintf(stderr, "No response from " MACFMT " for CMDU 0x%x with mid = %hu\n",
+				MAC2STR(msg->origin), msg->mid, msg->type);
+			cmdu_ackq_delete_msg(msg);
+		} else {
+			struct timeval new_next_tmo = { 0 };
+
+			timersub(&msg->ageing_tmo, &now, &new_next_tmo);
+			if (!timercmp(min_next_tmo, &new_next_tmo, <)) {
+				min_next_tmo->tv_sec = new_next_tmo.tv_sec;
+				min_next_tmo->tv_usec = new_next_tmo.tv_usec;
+				/* fprintf("next-tmo = (%lu.%lu)\n",
+				 *	   min_next_tmo->tv_sec,
+				 *	   min_next_tmo->tv_usec);
+				 */
+			}
+		}
+	}
+}
+
+static void cmdu_ackq_ageing_timer_run(atimer_t *t)
+{
+	struct cmdu_ackq *st = container_of(t, struct cmdu_ackq, ageing_timer);
+	//struct timeval *next_tmo = &st->next_tmo;
+	struct timeval min_next_tmo = { .tv_sec = 999999 };
+	int remain_cnt = 0;
+	int i;
+	struct timeval nu;
+
+	gettimeofday(&nu, NULL);
+
+	fprintf(stderr, "\n ----Timer now = %lu.%lu  --- cnt = %d---\n",
+		nu.tv_sec, nu.tv_usec, st->pending_cnt);
+
+	//spin_lock(&st->hash_lock);
+	for (i = 0; i < CMDU_BACKLOG_MAX; i++) {
+		if (hlist_empty(&st->table[i]))
+			continue;
+
+		fprintf(stderr, "i = %d\t", i);
+		cmdu_ackq_ageout_entry(st, &st->table[i], &min_next_tmo);
+	}
+
+	remain_cnt = st->pending_cnt;
+	st->next_tmo.tv_sec = min_next_tmo.tv_sec;
+	st->next_tmo.tv_usec = min_next_tmo.tv_usec;
+
+	//spin_unlock(&st->hash_lock);
+	if (remain_cnt) {
+		uint32_t tmo_msecs =
+			st->next_tmo.tv_sec * 1000 + st->next_tmo.tv_usec / 1000;
+
+		/* printf("%s(): remain = %d next_tmo = {(%lu s, %lu us) %u}\n",
+		       __func__, remain_cnt, next_tmo->tv_sec, next_tmo->tv_usec, tmo_msecs); */
+
+		if (tmo_msecs > 0)
+			timer_set(&st->ageing_timer, tmo_msecs);
+	}
+}
+
+int cmdu_ackq_init(void *cmdu_q)
+{
+	struct cmdu_ackq *q = (struct cmdu_ackq *)cmdu_q;
+
+	memset(q, 0, sizeof(*q));
+	pthread_mutex_init(&q->qlock, NULL);
+	timer_init(&q->ageing_timer, cmdu_ackq_ageing_timer_run);
+
+	return 0;
+}
+
+struct cmdu_ackq_entry *cmdu_ackq_lookup(void *cmdu_q, uint16_t type,
+					 uint16_t mid, uint8_t *dest)
+{
+	struct cmdu_ackq *q = (struct cmdu_ackq *)cmdu_q;
+	int idx = cmdu_ackq_hash(type, mid, dest);
+	struct cmdu_ackq_entry *msg = NULL;
+
+	pthread_mutex_lock(&q->qlock);
+	hlist_for_each_entry(msg, &q->table[idx], hlist) {
+		if (msg->type == type && msg->mid == mid &&
+		    !memcmp(msg->origin, dest, 6)) {
+
+			pthread_mutex_unlock(&q->qlock);
+			return msg;
+		}
+	}
+	pthread_mutex_unlock(&q->qlock);
+
+	return NULL;
+}
+
+void cmdu_ackq_reset(void *cmdu_q)
+{
+	struct cmdu_ackq *q = (struct cmdu_ackq *)cmdu_q;
+	struct cmdu_ackq_entry *msg = NULL;
+	int idx = 0;
+
+	fprintf(stderr, "Resetting CMDU Message Queue..\n");
+	fprintf(stderr, "*****************************************\n");
+	pthread_mutex_lock(&q->qlock);
+	for (idx = 0; idx < CMDU_BACKLOG_MAX; idx++) {
+		hlist_for_each_entry(msg, &q->table[idx], hlist) {
+			fprintf(stderr, "idx:%d, type:%d, mid:%d\n", idx, msg->type, msg->mid);
+			cmdu_ackq_delete_msg(msg);
+		}
+		q->table[idx].first = NULL;
+	}
+	fprintf(stderr, "*****************************************\n");
+
+	q->pending_cnt = 0;
+	pthread_mutex_unlock(&q->qlock);
+}
+
+
+/* In this function, type = cmdutype that is expected with 'mid' from 'dest' */
+int cmdu_ackq_enqueue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *dest,
+		      uint32_t timeout)
+{
+	struct cmdu_ackq *q = (struct cmdu_ackq *)cmdu_q;
+	struct cmdu_ackq_entry *msg = NULL;
+
+	msg = cmdu_ackq_lookup(cmdu_q, type, mid, dest);
+	if (msg) {
+		fprintf(stderr,
+			"Duplicate: type = 0x%04x  mid = %hu origin = " MACFMT "\n",
+			type, mid, MAC2STR(dest));
+
+		return -1;
+	}
+
+	msg = cmdu_ackq_create_msg(type, mid, dest, timeout);
+	if (msg) {
+		int idx = cmdu_ackq_hash(type, mid, dest);
+
+		pthread_mutex_lock(&q->qlock);
+		hlist_add_head(&msg->hlist, &q->table[idx]);
+
+		q->pending_cnt++;
+		fprintf(stderr,
+			"ENQ: type = 0x%04x  mid = %hu origin = " MACFMT "\n",
+			type, mid, MAC2STR(dest));
+
+
+		if (timer_pending(&q->ageing_timer)) {
+			if (timercmp(&q->next_tmo, &msg->ageing_tmo, >)) {
+				q->next_tmo.tv_sec = msg->ageing_tmo.tv_sec;
+				q->next_tmo.tv_usec = msg->ageing_tmo.tv_usec;
+
+				timer_set(&q->ageing_timer, msg->ageing_time);
+				fprintf(stderr, "Adjust ageout timer ========>\n");
+			}
+		} else {
+			fprintf(stderr, "Start ageout timer ========>\n");
+			q->next_tmo.tv_sec = msg->ageing_tmo.tv_sec;
+			q->next_tmo.tv_usec = msg->ageing_tmo.tv_usec;
+			timer_set(&q->ageing_timer, msg->ageing_time);
+		}
+
+		pthread_mutex_unlock(&q->qlock);
+		return 0;
+	}
+
+	return -1;
+}
+
+int cmdu_ackq_dequeue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *src)
+{
+	struct cmdu_ackq *q = (struct cmdu_ackq *)cmdu_q;
+	struct cmdu_ackq_entry *msg = NULL;
+	int idx;
+
+	msg = cmdu_ackq_lookup(cmdu_q, type, mid, src);
+	if (!msg) {
+		fprintf(stderr,
+			"DROP! CMDU not found: type = 0x%04x  mid = %hu origin = " MACFMT "\n",
+			type, mid, MAC2STR(src));
+
+		return -1;
+	}
+
+	idx = cmdu_ackq_hash(type, mid, src);
+
+	pthread_mutex_lock(&q->qlock);
+	hlist_del(&msg->hlist, &q->table[idx]);
+	q->pending_cnt--;
+	pthread_mutex_unlock(&q->qlock);
+
+	fprintf(stderr,
+		"DEQ: type = 0x%04x  mid = %hu origin = " MACFMT "\n",
+		type, mid, MAC2STR(src));
+
+	cmdu_ackq_delete_msg(msg);
+
+	return 0;
+}
diff --git a/src/cmdu_ackq.h b/src/cmdu_ackq.h
new file mode 100644
index 0000000000000000000000000000000000000000..6adb61df1efa0248f0d6e70eabc18424d8f95601
--- /dev/null
+++ b/src/cmdu_ackq.h
@@ -0,0 +1,55 @@
+/*
+ * cmdu_ackq.h
+ * CMDU pending response and ack queue management
+ *
+ * Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved.
+ *
+ * Author: anjan.chanda@iopsys.eu
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+
+#ifndef CMDU_ACKQ_H
+#define CMDU_ACKQ_H
+
+
+#include "hlist.h"
+
+#define CMDU_BACKLOG_MAX	128
+#define MAC_ADDR_HASH(a)	(a[0] ^ a[1] ^ a[2] ^ a[3] ^ a[4] ^ a[5])
+// TODO: improve hash func
+#define cmdu_ackq_hash(t, m, o)		\
+	((MAC_ADDR_HASH(o) ^ (t) ^ (m)) & (CMDU_BACKLOG_MAX - 1))
+
+/* struct holds a pending cmdu with 'mid' from 'origin' */
+struct cmdu_ackq_entry {
+	uint16_t type;
+	uint16_t mid;
+	uint8_t origin[6];
+	struct hlist_node hlist;
+
+	uint32_t ageing_time;    /* in msecs */
+	struct timeval ageing_tmo;
+};
+
+/* queue of cmdus for which response is pending */
+struct cmdu_ackq {
+	pthread_mutex_t qlock;
+
+	/* hashtable of pending cmdu_ackq_entry */
+	struct hlist_head table[CMDU_BACKLOG_MAX];
+
+	int pending_cnt;
+	atimer_t ageing_timer;
+	struct timeval next_tmo;
+};
+
+extern int cmdu_ackq_init(void *q);
+extern void cmdu_ackq_reset(void *q);
+extern int cmdu_ackq_dequeue(void *q, uint16_t type, uint16_t mid, uint8_t *src);
+extern int cmdu_ackq_enqueue(void *q, uint16_t type, uint16_t mid, uint8_t *dest,
+			     uint32_t timeout);
+
+
+#endif /* CMDU_ACKQ_H */
diff --git a/src/cmdu_input.c b/src/cmdu_input.c
index 58d17f407161e63755202871dc602250aecfd424..db6b4867a33489f0a4b6fe3f4c932d7a3b3a449e 100644
--- a/src/cmdu_input.c
+++ b/src/cmdu_input.c
@@ -34,13 +34,13 @@
 #include "timer.h"
 #include "config.h"
 #include "cmdu.h"
+#include "cmdu_ackq.h"
 #include "i1905_dm.h"
 #include "i1905.h"
 #include "i1905_extension.h"
 
 
-// TODO: combine 3 following headers into one
-#include "1905_defs.h"
+// TODO: combine following headers into one
 #include "1905_tlvs.h"
 #include "lldp_tlvs.h"
 
@@ -166,6 +166,10 @@ int i1905_handle_topology_response(struct i1905_interface_private *pif,
 
 			return -1;
 		}
+
+		memcpy(aladdr_origin, devinfo->aladdr, 6);
+		ret = i1905_dm_neighbor_update(i1905_interface_priv(pif),
+					       aladdr_origin, tv[0][0]);
 	}
 
 	if (tv[1][0]) {
@@ -175,7 +179,10 @@ int i1905_handle_topology_response(struct i1905_interface_private *pif,
 			struct tlv_device_bridge_caps *brcaps =
 				(struct tlv_device_bridge_caps *)tv[1][num]->data;
 
-			//i1905_dm_neighbor_update(pif, );	//TODO
+			ret = i1905_dm_neighbor_update(i1905_interface_priv(pif),
+						       aladdr_origin, tv[1][num]);
+			if (ret)
+				break;
 			num++;
 		}
 	}
@@ -187,7 +194,11 @@ int i1905_handle_topology_response(struct i1905_interface_private *pif,
 			struct tlv_non1905_neighbor *non1905 =
 				(struct tlv_non1905_neighbor *)tv[2][num]->data;
 
-			//i1905_dm_neighbor_update(pif, );	//TODO
+
+			ret = i1905_dm_neighbor_update(i1905_interface_priv(pif),
+						       aladdr_origin, tv[2][num]);
+			if (ret)
+				break;
 			num++;
 		}
 	}
@@ -199,7 +210,11 @@ int i1905_handle_topology_response(struct i1905_interface_private *pif,
 			struct tlv_1905neighbor *nbrs =
 				(struct tlv_1905neighbor *)tv[3][num]->data;
 
-			//i1905_dm_neighbor_update(pif, );	//TODO
+
+			ret = i1905_dm_neighbor_update(i1905_interface_priv(pif),
+						       aladdr_origin, tv[3][num]);
+			if (ret)
+				break;
 			num++;
 		}
 	}
@@ -343,23 +358,39 @@ static const cmdu_handler_t i1905ftable[] = {
 
 int i1905_process_cmdu(struct i1905_interface_private *pif, struct cmdu_buff *rxf)
 {
-	uint16_t type;
+	uint16_t type, mid;
+	uint8_t *src;
 	int ret;
 
+
 	if (!rxf->cdata)
 		return -1;
 
-	// TODO: discard duplicates
-
 	type = buf_get_be16((uint8_t *)&rxf->cdata->hdr.type);
+	mid = buf_get_be16((uint8_t *)&rxf->cdata->hdr.mid);
+	src = rxf->head + 6;
 
-	if (i1905ftable[type]) {
-		ret = i1905ftable[type](pif, rxf);
+	fprintf(stderr, "%s: from src " MACFMT ", type = %hu\n",
+			__func__, MAC2STR(src), type);
+
+	if (type >= CMDU_TYPE_1905_END) {
+		fprintf(stderr, "%s: Unknown cmdu!\n", __func__);
+		return -1;
 	}
 
-	fprintf(stderr, "%s: ----->\n", __func__);
+	if (is_cmdu_type_response(type)) {
+		/* discard responses with no matching request awaiting */
+		ret = cmdu_ackq_dequeue(&pif->txack_q, type, mid, src);
+		if (ret) {
+			fprintf(stderr, "%s: drop unexpected CMDU (mid = %d)\n",
+				__func__, mid);
+			return -1;
+		}
+	}
 
-	return ret;
-}
+	if (i1905ftable[type])
+		ret = i1905ftable[type](pif, rxf);
 
 
+	return ret;
+}
diff --git a/src/i1905.c b/src/i1905.c
index c1b3f5b2541341b41c0e0a5f3835f6975cf38a7a..2541564cd89595e219ad84fa50cec5aa6817d716 100644
--- a/src/i1905.c
+++ b/src/i1905.c
@@ -31,14 +31,14 @@
 #include "timer.h"
 #include "config.h"
 #include "cmdu.h"
+#include "cmdu_ackq.h"
 #include "i1905_dm.h"
 #include "i1905.h"
 #include "i1905_extension.h"
 
 
-// TODO: combine 3 following headers into one
-#include "1905_defs.h"
-#include "i1905_tlvs.h"
+// TODO: combine following headers into one
+#include "1905_tlvs.h"
 #include "lldp_tlvs.h"
 
 
@@ -125,18 +125,6 @@ int i1905_stop(struct i1905_private *p)
 	return 0;
 }
 
-int i1905_get_dm(struct i1905_private *p)
-{
-	//TODO
-	return 0;
-}
-
-int i1905_free_dm(struct i1905_private *p)
-{
-	//TODO
-	return 0;
-}
-
 int i1905_cmdu_rxq_handler(void *data)
 {
 	struct i1905_interface_private *pif =
@@ -173,12 +161,11 @@ static struct i1905_interface *i1905_alloc_interface(const char *ifname,
 
 	INIT_LIST_HEAD(&n->vendorlist);
 	INIT_LIST_HEAD(&n->nbrlist);
+	INIT_LIST_HEAD(&n->non1905_nbrlist);
 	INIT_LIST_HEAD(&n->iflinklist);
 
 	n->priv = (void *)(n + 1);
 
-	fprintf(stderr, "%s: %d\n", __func__, __LINE__);
-
 	return n;
 }
 
@@ -199,6 +186,7 @@ int i1905_cmdu_tx(struct i1905_interface_private *ifp,
 	struct i1905_interface *iface = i1905_interface_priv(ifp);
 	struct ether_header *eh;
 	struct sockaddr_ll sa;
+	uint16_t resp_type;
 	int ret;
 
 
@@ -235,11 +223,18 @@ int i1905_cmdu_tx(struct i1905_interface_private *ifp,
 	ret = sendto(ifp->sock_1905, data, datalen, 0, (struct sockaddr*)&sa,
 		     sizeof(struct sockaddr_ll));
 	if (ret < 0) {
-		printf("%s: failed!!!!!!!\n", __func__);
+		fprintf(stderr, "%s: failed!!!!!!!\n", __func__);
 		return -1;
 	}
 
-	*mid = 1000;	/* TODO: generate mid */
+	if (*mid == 0)
+		*mid = cmdu_get_next_mid();
+
+	resp_type = cmdu_expect_response(type);
+	if (resp_type != CMDU_TYPE_NONE) {
+		cmdu_ackq_enqueue(&ifp->txack_q, resp_type, *mid, dst,
+				  CMDU_DEFAULT_TIMEOUT);
+	}
 
 	return 0;
 }
@@ -317,7 +312,6 @@ static void i1905_recv_1905(struct uloop_fd *fd, unsigned int events)
 			return;
 		}
 
-		fprintf(stderr, "%s: before receive\n", __func__);
 		res = recvfrom(pif->sock_1905, rxf->head, 1518,
 				0, NULL, NULL);
 		if (res == -1) {
@@ -431,7 +425,6 @@ static void i1905_recv_lldp(struct uloop_fd *fd, unsigned int events)
 		}
 
 
-		fprintf(stderr, "%s: before receive\n", __func__);
 		res = recvfrom(pif->sock_lldp, rxf->head, 1518,
 				0, NULL, NULL);
 		if (res == -1) {
@@ -537,6 +530,8 @@ static int i1905_setup_interface_priv(struct i1905_interface *n)
 	p->rxwork.func = i1905_cmdu_rxq_handler;
 	worker_init(&p->rxwork);
 
+	cmdu_ackq_init(&p->txack_q);
+
 	i1905_init_interface_socket_1905(n, p);
 	i1905_init_interface_socket_lldp(n, p);
 
@@ -635,9 +630,9 @@ int i1905_run_bridge_discovery(struct i1905_private *p)
 			return -1;
 		}
 
-		lldpbuf[0] = (TLV_TYPE_CHASSIS_ID << 1) | ((7 & 0x80) >> 7);
+		lldpbuf[0] = (LLDP_TLV_CHASSIS_ID << 1) | ((7 & 0x80) >> 7);
 		lldpbuf[1] = 7 & 0x7f;
-		lldpbuf[2] = CHASSIS_ID_TLV_SUBTYPE_MAC_ADDRESS;
+		lldpbuf[2] = LLDP_CHASSIS_ID_SUBTYPE_MAC_ADDRESS;
 		memcpy(&lldpbuf[3], iface->aladdr, 6);
 
 		ret = cmdu_put(frm, lldpbuf, 9);
@@ -649,9 +644,9 @@ int i1905_run_bridge_discovery(struct i1905_private *p)
 		}
 
 		memset(lldpbuf, 0, 256);
-		lldpbuf[0] = (TLV_TYPE_PORT_ID << 1) | ((7 & 0x80) >> 7);
+		lldpbuf[0] = (LLDP_TLV_PORT_ID << 1) | ((7 & 0x80) >> 7);
 		lldpbuf[1] = 7 & 0x7f;
-		lldpbuf[2] = PORT_ID_TLV_SUBTYPE_MAC_ADDRESS;
+		lldpbuf[2] = LLDP_PORT_ID_SUBTYPE_MAC_ADDRESS;
 		memcpy(&lldpbuf[3], iface->macaddr, 6);
 
 		ret = cmdu_put(frm, lldpbuf, 9);
@@ -663,9 +658,9 @@ int i1905_run_bridge_discovery(struct i1905_private *p)
 		}
 
 		memset(lldpbuf, 0, 256);
-		lldpbuf[0] = (TLV_TYPE_TIME_TO_LIVE << 1) | ((2 & 0x80) >> 7);
+		lldpbuf[0] = (LLDP_TLV_TTL << 1) | ((2 & 0x80) >> 7);
 		lldpbuf[1] = 2 & 0x7f;
-		buf_put_be16(&lldpbuf[2], TIME_TO_LIVE_TLV_1905_DEFAULT_VALUE);
+		buf_put_be16(&lldpbuf[2], LLDP_TTL_1905_DEFAULT_VALUE);
 
 		ret = cmdu_put(frm, lldpbuf, 4);
 		if (ret) {
diff --git a/src/i1905.h b/src/i1905.h
index e73c2de760a86baac0c5c0e1e9c82ff6edf3b8e4..cd6d049dca35c3dae0bcf8502420a0dc6d57e4fc 100644
--- a/src/i1905.h
+++ b/src/i1905.h
@@ -29,6 +29,7 @@ struct i1905_interface_private {
 	struct uloop_fd uloop_lldp;
 	struct cmdu_queue rxqueue;
 	struct worker rxwork;
+	struct cmdu_ackq txack_q;
 
 	void *iface;	/* points to i1905_interface */
 	struct ubus_object obj;
@@ -72,14 +73,14 @@ extern struct i1905_dm *i1905_dm_get();
 extern int i1905_dm_init(struct i1905_dm *dm);
 extern int i1905_dm_free(struct i1905_dm *dm);
 
-extern int i1905_dm_neighour_discovered(struct i1905_interface *iface,
+extern int i1905_dm_neighbor_discovered(struct i1905_interface *iface,
 					uint8_t *aladdr, uint8_t *macaddr);
 
 
-extern int i1905_dm_neighour_changed(struct i1905_interface *iface,
+extern int i1905_dm_neighbor_changed(struct i1905_interface *iface,
 				     uint8_t *aladdr);
 
-extern int i1905_dm_neighour_update(struct i1905_interface *iface,
+extern int i1905_dm_neighbor_update(struct i1905_interface *iface,
 				    uint8_t *aladdr, struct tlv *t);
 
 #endif /* I1905_H */
diff --git a/src/i1905_dm.c b/src/i1905_dm.c
index 02c782ecf19f8fc5b78e950b45c7fe8e4f45bd60..ee778cd0d1f2f9fb5e2e0a4643d06b7d9df37cd3 100644
--- a/src/i1905_dm.c
+++ b/src/i1905_dm.c
@@ -26,14 +26,57 @@
 #include <easy/easy.h>
 
 
+#include "util.h"
+#include "bufutil.h"
 #include "cmdu.h"
 #include "i1905_dm.h"
 
-#include "1905_defs.h"
-#include "i1905_tlvs.h"
+#include "1905_tlvs.h"
 #include "lldp_tlvs.h"
 
 
+struct i1905_bridge_tuple *i1905_dm_neighbor_brtuple_create(void)
+{
+	struct i1905_bridge_tuple *br;
+
+	br = calloc(1, sizeof(*br));
+	if (!br) {
+		fprintf(stderr, "-ENOMEM\n");
+		return NULL;
+	}
+
+	return br;
+}
+
+struct i1905_net_non1905_neighbor *i1905_dm_neighbor_non1905_nbr_create(void)
+{
+	struct i1905_net_non1905_neighbor *xnbr;
+
+	xnbr = calloc(1, sizeof(*xnbr));
+	if (!xnbr) {
+		fprintf(stderr, "-ENOMEM\n");
+		return NULL;
+	}
+
+	return xnbr;
+}
+
+struct i1905_net_neighbor *i1905_dm_neighbor_nbr_create(void)
+{
+	struct i1905_net_neighbor *rnbr;
+
+	rnbr = calloc(1, sizeof(*rnbr));
+	if (!rnbr) {
+		fprintf(stderr, "-ENOMEM\n");
+		return NULL;
+	}
+
+	//INIT_LIST_HEAD(&rnbr->riflist);
+	INIT_LIST_HEAD(&rnbr->metriclist);
+
+	return rnbr;
+}
+
 struct i1905_interface *i1905_dm_neighbor_interface_create(void)
 {
 	struct i1905_interface *rif;
@@ -46,6 +89,7 @@ struct i1905_interface *i1905_dm_neighbor_interface_create(void)
 
 	INIT_LIST_HEAD(&rif->vendorlist);
 	INIT_LIST_HEAD(&rif->nbrlist);
+	INIT_LIST_HEAD(&rif->non1905_nbrlist);
 	INIT_LIST_HEAD(&rif->iflinklist);
 
 	return rif;
@@ -65,7 +109,7 @@ struct i1905_device *i1905_dm_neighbor_create(void)
 	INIT_LIST_HEAD(&rdev->ipv6list);
 	INIT_LIST_HEAD(&rdev->vendorlist);
 	INIT_LIST_HEAD(&rdev->iflist);
-	INIT_LIST_HEAD(&rdev->non1905_nbrlist);
+	//INIT_LIST_HEAD(&rdev->non1905_nbrlist);
 	INIT_LIST_HEAD(&rdev->nbrlist);
 	INIT_LIST_HEAD(&rdev->l2_nbrlist);
 	INIT_LIST_HEAD(&rdev->brlist);
@@ -74,6 +118,19 @@ struct i1905_device *i1905_dm_neighbor_create(void)
 	return rdev;
 }
 
+struct i1905_interface *i1905_dm_neighbor_interface_lookup(struct i1905_device *rdev,
+							   uint8_t *ifmacaddr)
+{
+	struct i1905_interface *rif = NULL;
+
+
+	list_for_each_entry(rif, &rdev->iflist, list) {
+		if (hwaddr_equal(rif->macaddr, ifmacaddr))
+			break;
+	}
+
+	return rif;
+}
 
 struct i1905_device *i1905_dm_neighbor_lookup(struct i1905_interface *iface,
 					      uint8_t *aladdr)
@@ -91,15 +148,184 @@ struct i1905_device *i1905_dm_neighbor_lookup(struct i1905_interface *iface,
 	return rdev;
 }
 
+
+
+
+int i1905_dm_neighbor_update_non1905_nbrlist(struct i1905_device *rdev, struct tlv *t)
+{
+	struct tlv_non1905_neighbor *non1905_nbr =
+				(struct tlv_non1905_neighbor *)t->data;
+	struct i1905_interface *rif;
+	int j;
+
+
+	rif = i1905_dm_neighbor_interface_lookup(rdev, non1905_nbr->local_macaddr);
+	if (!rif) {
+		rif = i1905_dm_neighbor_interface_create();
+		if (!rif) {
+			fprintf(stderr, "-ENOMEM\n");
+			return -1;
+		}
+
+		memcpy(rif->macaddr, non1905_nbr->local_macaddr, 6);
+		memcpy(rif->aladdr, rdev->aladdr, 6);
+		rif->device = rdev;
+		rif->priv = NULL;
+		list_add_tail(&rif->list, &rdev->iflist);
+	}
+
+	/* XXX: replace old non-1905 nbrlist with this one */
+	list_flush(&rif->non1905_nbrlist, struct i1905_net_non1905_neighbor, list);
+
+	for (j = 0; j < non1905_nbr->num_non1905_nbrs; j++) {
+		struct i1905_net_non1905_neighbor *rdev_xnbr = NULL;
+
+		rdev_xnbr = i1905_dm_neighbor_non1905_nbr_create();
+		if (rdev_xnbr) {
+			memcpy(rdev_xnbr->macaddr, non1905_nbr->non1905_nbr[j].macaddr, 6);
+			list_add_tail(&rdev_xnbr->list, &rif->non1905_nbrlist);
+		}
+	}
+
+	return 0;
+}
+
+int i1905_dm_neighbor_update_nbrlist(struct i1905_device *rdev, struct tlv *t)
+{
+	struct tlv_1905neighbor *nbr =
+				(struct tlv_1905neighbor *)t->data;
+	struct i1905_interface *rif;
+	int j;
+
+
+	rif = i1905_dm_neighbor_interface_lookup(rdev, nbr->local_macaddr);
+	if (!rif) {
+		rif = i1905_dm_neighbor_interface_create();
+		if (!rif) {
+			fprintf(stderr, "-ENOMEM\n");
+			return -1;
+		}
+
+		memcpy(rif->macaddr, nbr->local_macaddr, 6);
+		memcpy(rif->aladdr, rdev->aladdr, 6);
+		rif->device = rdev;
+		rif->priv = NULL;
+		list_add_tail(&rif->list, &rdev->iflist);
+	}
+
+	/* XXX: quickest way is to replace old nbrlist with this one */
+	list_flush(&rif->nbrlist, struct i1905_net_neighbor, list);
+
+	for (j = 0; j < nbr->num_1905nbrs; j++) {
+		struct i1905_net_neighbor *rdev_nbr = NULL;
+
+		rdev_nbr = i1905_dm_neighbor_nbr_create();
+		if (rdev_nbr) {
+			memcpy(rdev_nbr->aladdr, nbr->nbr[j].aladdr, 6);
+			rdev_nbr->br_present = nbr->nbr[j].has_bridge;
+			list_add_tail(&rdev_nbr->list, &rif->nbrlist);
+		}
+	}
+
+	return 0;
+}
+
+int i1905_dm_neighbor_update_brlist(struct i1905_device *rdev, struct tlv *t)
+{
+	struct tlv_device_bridge_caps *brcaps =
+				(struct tlv_device_bridge_caps *)t->data;
+	struct i1905_bridge_tuple *bp, *tmp;
+	int i;
+
+
+
+	/* replace old brlist with this one */
+	list_for_each_entry_safe(bp, tmp, &rdev->brlist, list) {
+		list_del(&bp->list);
+		if (bp->num_macs)
+			free(bp->macaddrs);
+		free(bp);
+	}
+
+	for (i = 0; i < brcaps->num_tuples; i++) {
+		struct i1905_bridge_tuple *br = NULL;
+
+		br = i1905_dm_neighbor_brtuple_create();
+		if (!br) {
+			fprintf(stderr, "-ENOMEM\n");
+			return -1;
+		}
+
+		br->num_macs = brcaps->tuple[i].num_macaddrs;
+		memcpy(br->macaddrs, brcaps->tuple[i].addr, brcaps->tuple[i].num_macaddrs);
+		list_add_tail(&br->list, &rdev->brlist);
+	}
+
+	return 0;
+}
+
+int i1905_dm_neighbor_update_devinfo(struct i1905_device *rdev, struct tlv *t)
+{
+	struct tlv_device_info *devinfo =
+				(struct tlv_device_info *)t->data;
+	int i;
+
+
+	for (i = 0; i < devinfo->num_interface; i++) {
+		struct local_interface *tif = devinfo->interface;
+		struct i1905_interface *rif;
+
+		rif = i1905_dm_neighbor_interface_lookup(rdev, tif->macaddr);
+		if (!rif) {
+			rif = i1905_dm_neighbor_interface_create();
+			if (!rif) {
+				fprintf(stderr, "-ENOMEM\n");
+				return -1;
+			}
+
+			memcpy(rif->macaddr, tif->macaddr, 6);
+			memcpy(rif->aladdr, rdev->aladdr, 6);
+			rif->device = rdev;
+			rif->priv = NULL;
+			rif->media = buf_get_be16((uint8_t *)&tif->mediatype);
+			if (tif->sizeof_mediainfo > 0) {
+				rif->mediainfo = calloc(1, tif->sizeof_mediainfo);
+				if (!rif->mediainfo) {
+					fprintf(stderr, "-ENOMEM\n");
+				}
+
+				memcpy(rif->mediainfo, tif->mediainfo,
+							tif->sizeof_mediainfo);
+			}
+
+			list_add_tail(&rif->list, &rdev->iflist);
+		} else {
+			memcpy(rif->aladdr, rdev->aladdr, 6);
+			rif->media = buf_get_be16((uint8_t *)&tif->mediatype);
+			if (tif->sizeof_mediainfo > 0) {
+				if (rif->mediainfo)
+					free(rif->mediainfo);
+
+				rif->mediainfo = calloc(1, tif->sizeof_mediainfo);
+				if (!rif->mediainfo) {
+					fprintf(stderr, "-ENOMEM\n");
+				}
+
+				memcpy(rif->mediainfo, tif->mediainfo,
+							tif->sizeof_mediainfo);
+			}
+		}
+	}
+
+	return 0;
+}
+
 int i1905_dm_neighbor_update(struct i1905_interface *iface, uint8_t *aladdr,
 			     struct tlv *t)
 {
 	struct i1905_selfdevice *self = (struct i1905_selfdevice *)iface->device;
-	struct i1905_interface *rif = NULL;
 	struct i1905_device *rdev = NULL;
-	int origin = 0;
-	int found = 0;
-	int ret;
+	int ret = 0;
 
 	rdev = i1905_dm_neighbor_lookup(iface, aladdr);
 	if (!rdev) {
@@ -109,12 +335,16 @@ int i1905_dm_neighbor_update(struct i1905_interface *iface, uint8_t *aladdr,
 
 	switch (t->type) {
 	case TLV_TYPE_DEVICE_INFORMATION_TYPE:
+		ret = i1905_dm_neighbor_update_devinfo(rdev, t);
 		break;
 	case TLV_TYPE_DEVICE_BRIDGING_CAPABILITIES:
+		ret = i1905_dm_neighbor_update_brlist(rdev, t);
 		break;
 	case TLV_TYPE_NON_1905_NEIGHBOR_DEVICE_LIST:
+		ret = i1905_dm_neighbor_update_non1905_nbrlist(rdev, t);
 		break;
 	case TLV_TYPE_NEIGHBOR_DEVICE_LIST:
+		ret = i1905_dm_neighbor_update_nbrlist(rdev, t);
 		break;
 	case TLV_TYPE_POWER_OFF_INTERFACE:
 		break;
@@ -125,7 +355,7 @@ int i1905_dm_neighbor_update(struct i1905_interface *iface, uint8_t *aladdr,
 		break;
 	}
 
-	return 0;
+	return ret;
 }
 
 int i1905_dm_neighbor_discovered(struct i1905_interface *iface, uint8_t *aladdr,
diff --git a/src/i1905_dm.h b/src/i1905_dm.h
index 55b5b2c857d542bd8de3893247a92d0e9caaf015..fcd630d4731f70ed81d8bb756b553d048977367c 100644
--- a/src/i1905_dm.h
+++ b/src/i1905_dm.h
@@ -49,6 +49,18 @@ struct i1905_registrar {
 	struct list_head list;
 };
 
+struct i1905_metric {
+	bool br_present;
+	uint32_t tx_errors;
+	uint32_t rx_errors;
+	uint32_t tx_packets;
+	uint32_t rx_packets;
+	uint32_t available;		/* in percentage */
+	uint32_t max_rate;		/* max throughput at MAC layer */
+	uint32_t max_phyrate;
+	uint8_t rssi;			/* FIXME: average rssi */
+};
+
 /* remote interface */
 struct i1905_rinterface {
 	uint8_t macaddr[6];
@@ -57,13 +69,28 @@ struct i1905_rinterface {
 	struct list_head list;
 };
 
+struct i1905_net_neighbor_metric {
+	uint8_t peer_macaddr[6];
+	struct i1905_metric m;
+	struct list_head list;
+};
+
 struct i1905_net_neighbor {
-	uint8_t macaddr[6];
+	uint8_t local_macaddr[6];
+	uint8_t aladdr[6];
+	bool br_present;
 	uint8_t num_ifaces;
-	struct list_head riflist;	/* list of struct i1905_rinterface */
+	//struct list_head riflist;	/* list of struct i1905_rinterface */
+	uint8_t num_metrics;
+	struct list_head metriclist;	/* list of i1905_net_neighbor_metric*/
 	struct list_head list;
 };
 
+struct i1905_net_non1905_neighbor {
+	//uint8_t local_macaddr[6];
+	uint8_t macaddr[6];
+	struct list_head list;
+};
 
 struct i1905_genphy {
 	uint8_t oui[3];
@@ -77,17 +104,6 @@ struct i1905_vendor_info {
 	struct list_head list;
 };
 
-struct i1905_metric {
-	bool br_present;
-	uint32_t tx_errors;
-	uint32_t rx_errors;
-	uint32_t tx;
-	uint32_t rx;
-	uint32_t available;		/* in percentage */
-	uint32_t max_rate;		/* max throughput at MAC layer */
-	uint32_t max_phyrate;
-	uint8_t rssi;			/* FIXME: average rssi */
-};
 
 enum i1905_fwdrule_mask {
 	I1905_FWDRULE_SRC     = 1 << 0,
@@ -165,6 +181,7 @@ struct i1905_interface {
 	struct list_head iflinklist;	/* list of interface links */
 
 
+	struct list_head non1905_nbrlist; // XXX: moved from device due to TLV
 	struct list_head nbrlist;       /* TODO: needed ? */
 
 	struct list_head list;
@@ -208,6 +225,12 @@ struct i1905_ipv6 {
 	struct list_head list;
 };
 
+struct i1905_bridge_tuple {
+	uint8_t num_macs;
+	uint8_t *macaddrs;	/* array of interface macaddress */
+	struct list_head list;
+};
+
 /* represents another 1905 device in the network */
 struct i1905_device {
 	uint32_t tsp;
@@ -235,10 +258,10 @@ struct i1905_device {
 	struct list_head ipv6list;	/* list of i1905_ipv6 */
 	struct list_head vendorlist;	/* list of i1905_vendor_info */
 	struct list_head iflist;	/* list of i1905_interface */
-	struct list_head non1905_nbrlist;
+	//struct list_head non1905_nbrlist;
 	struct list_head nbrlist;       /* list of struct i1905_net_neighbor */
 	struct list_head l2_nbrlist;
-	struct list_head brlist;	/* list of  */
+	struct list_head brlist;	/* list of i1905_bridge_tuple */
 
 	struct i1905_security security;
 	struct list_head reglist;	/* list of i1905_registrar in network */
diff --git a/src/i1905_ubus.c b/src/i1905_ubus.c
index 9916cfb1b71615158dab10c0c4e27e55448ace24..6289688f252f8aaa59ccd55116e399d2e42de1f4 100644
--- a/src/i1905_ubus.c
+++ b/src/i1905_ubus.c
@@ -23,6 +23,7 @@
 #include "worker.h"
 #include "config.h"
 #include "cmdu.h"
+#include "cmdu_ackq.h"
 #include "i1905_dm.h"
 #include "i1905.h"
 
diff --git a/src/lldp_tlvs.h b/src/lldp_tlvs.h
index a1aa3ca20579e29ae335c8744c460baa89a9a08a..d5f048a0b8b162f4c83e6acb9c177fcadaa2957e 100644
--- a/src/lldp_tlvs.h
+++ b/src/lldp_tlvs.h
@@ -1,209 +1,61 @@
 /*
- * lldp_tlvs.h: IEEE-1905 lldp tlvs handling
+ * lldp_tlvs.h: LLDP tlvs definition
  */
 
-#ifndef _LLDP_TLVS_H_
-#define _LLDP_TLVS_H_
-
-
-#define TLV_TYPE_END_OF_LLDPPDU             (0)
-#define TLV_TYPE_CHASSIS_ID                 (1)
-#define TLV_TYPE_PORT_ID                    (2)
-#define TLV_TYPE_TIME_TO_LIVE               (3)
-
-////////////////////////////////////////////////////////////////////////////////
-// End of LLDPPDU TLV associated structures ("Section 8.5.1")
-////////////////////////////////////////////////////////////////////////////////
-struct endOfLldppduTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_END_OF_LLDPPDU
-
-	// This structure does not contain anything at all
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Chassis ID TLV associated structures ("Section 8.5.2")
-////////////////////////////////////////////////////////////////////////////////
-struct chassisIdTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_CHASSIS_ID
-
-#define CHASSIS_ID_TLV_SUBTYPE_CHASSIS_COMPONENT   (1)
-#define CHASSIS_ID_TLV_SUBTYPE_INTERFACE_ALIAS     (2)
-#define CHASSIS_ID_TLV_SUBTYPE_PORT_COMPONENT      (3)
-#define CHASSIS_ID_TLV_SUBTYPE_MAC_ADDRESS         (4)
-#define CHASSIS_ID_TLV_SUBTYPE_NETWORK_ADDRESS     (5)
-#define CHASSIS_ID_TLV_SUBTYPE_INTERFACE_NAME      (6)
-#define CHASSIS_ID_TLV_SUBTYPE_LOGICALLY_ASSIGNED  (7)
-	uint8_t chassis_id_subtype;	// One of the values from above
-
-	uint8_t chassis_id[256];	// Specific identifier for the particular
-	// chassis.
-	// NOTE: In our case (1905 context) we are
-	//       only interested in generating/
-	//       consuming chassis subtype "4" (MAC
-	//       address), thus "chassis_id" will
-	//       hold a six bytes array representing
-	//       the MAC address of the transmitting
-	//       AL entity (as explained in
-	//       "IEEE Std 1905.1-2013 Section 6.1")
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Port ID TLV associated structures ("Section 8.5.3")
-////////////////////////////////////////////////////////////////////////////////
-struct portIdTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_PORT_ID
-
-#define PORT_ID_TLV_SUBTYPE_INTERFACE_ALIAS     (1)
-#define PORT_ID_TLV_SUBTYPE_PORT_COMPONENT      (2)
-#define PORT_ID_TLV_SUBTYPE_MAC_ADDRESS         (3)
-#define PORT_ID_TLV_SUBTYPE_NETWORK_ADDRESS     (4)
-#define PORT_ID_TLV_SUBTYPE_INTERFACE_NAME      (5)
-#define PORT_ID_TLV_SUBTYPE_AGENT_CIRCUIT_ID    (6)
-#define PORT_ID_TLV_SUBTYPE_LOGICALLY_ASSIGNED  (7)
-	uint8_t port_id_subtype;	// One of the values from above
-
-	uint8_t port_id[256];	// Alpha-numeric string that contains the
-	// specific identifier for the port from which
-	// this LLDPPDU was transmitted
-	// NOTE: In our case (1905 context) we are
-	//       only interested in generating/
-	//       consuming port subtype "3" (MAC
-	//       address), thus "port_id" will hold a
-	//       six bytes array representing the MAC
-	//       address of the transmitting interface
-	//       (as explained in "IEEE Std
-	//       1905.1-2013 Section 6.1")
-	// NOTE2: The standard says "alpha-numeric"
-	//        string... but the implementations I
-	//        have checked store a 6 bytes MAC
-	//        address and not its string
-	//        representation... So we are also
-	//        storing 6 bytes here.
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Time to live TLV associated structures ("Section 8.5.4")
-////////////////////////////////////////////////////////////////////////////////
-struct timeToLiveTypeTLV {
-	uint8_t tlv_type;		// Must always be set to
-	// TLV_TYPE_TIME_TO_LIVE
-
-#define TIME_TO_LIVE_TLV_1905_DEFAULT_VALUE  (180)
-	uint16_t ttl;		// Time (in seconds)
-	// NOTE: In our case (1905 context) we are
-	//       always setting this parameter to
-	//       "180" (as explained in "IEEE Std
-	//       1905.1-2013 Section 6.1")
-};
-
-#if 0
-////////////////////////////////////////////////////////////////////////////////
-// Main API functions
-////////////////////////////////////////////////////////////////////////////////
-
-// This function receives a pointer to a stream of bytes representing an LLPD
-// TLV according to "Section 8.5"
-//
-// It then returns a pointer to a structure whose fields have already been
-// filled with the appropiate values extracted from the parsed stream.
-//
-// The actual type of the returned pointer structure depends on the value of
-// the first byte pointed by "packet_stream" (ie. the "Type" field of the TLV):
-//
-//   TLV_TYPE_END_OF_LLDPPDU   -->  struct endOfLldppduTLV *
-//   TLV_TYPE_CHASSIS_ID       -->  struct chassisIdTLV *
-//   TLV_TYPE_PORT_ID          -->  struct portIdTLV *
-//   TLV_TYPE_TIME_TO_LIVE     -->  struct timeToLiveTypeTLV *
-//
-// If an error was encountered while parsing the stream, a NULL pointer is
-// returned instead.
-// Otherwise, the returned structure is dynamically allocated, and once it is
-// no longer needed, the user must call the "free_lldp_TLV_structure()" function
-//
-uint8_t *parse_lldp_TLV_from_packet(INT8U *packet_stream);
-
-// This is the opposite of "parse_lldp_TLV_from_packet()": it receives a
-// pointer to a TLV structure and then returns a pointer to a buffer which:
-//   - is a packet representation of the TLV
-//   - has a length equal to the value returned in the "len" output argument
-//
-// "memory_structure" must point to a structure of one of the types returned by
-// "parse_lldp_TLV_from_packet()"
-//
-// If there is a problem this function returns NULL, otherwise the returned
-// buffer must be later freed by the caller (it is a regular, non-nested buffer,
-// so you just need to call "free()").
-//
-// Note that the input structure is *not* freed. You still need to later call
-// "free_lldp_TLV_structure()"
-//
-uint8_t *forge_lldp_TLV_from_structure(INT8U *memory_structure, uint16_t *len);
-
-////////////////////////////////////////////////////////////////////////////////
-// Utility API functions
-////////////////////////////////////////////////////////////////////////////////
-
-// This function receives a pointer to a TLV structure and then traverses it
-// and all nested structures, calling "free()" on each one of them
-//
-// "memory_structure" must point to a structure of one of the types returned by
-// "parse_lldp_TLV_from_packet()"
-//
-void free_lldp_TLV_structure(uint8_t *memory_structure);
-
-// 'forge_lldp_TLV_from_structure()' returns a regular buffer which can be freed
-// using this macro defined to be FREE
-//
-#define  free_lldp_TLV_packet  FREE
-
-// This function returns '0' if the two given pointers represent TLV structures
-// of the same type and they contain the same data
-//
-// "memory_structure_1" and "memory_structure_2" must point (each) to a
-// structure of one of the types returned by "parse_lldp_TLV_from_packet()"
-//
-uint8_t compare_lldp_TLV_structures(INT8U *memory_structure_1, INT8U *memory_structure_2);
-
-// The next function is used to call function "callback()" on each element of
-// the "memory_structure" structure
-//
-// "memory_structure" must point to a structure of one of the types returned by
-// "parse_lldp_TLV_from_packet()"
-//
-// It takes four arguments:
-//   - The structure whose elements are going to be visited
-//   - A callback function that will be executed on each element with the
-//     following arguments:
-//      * A pointer to the "write()" function that will be used to dump text.
-//        This is always the "write_function()" pointer provided as third
-//        argument to the "visit_lldp_TLV_structure()" function.
-//      * The size of the element to print (1, 2, 4, n bytes)
-//      * A prefix string.
-//        This is always the "prefix" value provided as fourth argument to the
-//        "visit_lldp_TLV_structure()" function/
-//      * The name of the element (ex: "mac_address")
-//      * A 'fmt' string which must be used to print the contents of the element
-//      * A pointer to the element itself
-//   - The "write()" function that will be used when the callback is executed
-//   - A "prefix" string argument that will be used when the callback is
-//     executed (it usually contains "context" information that the callback
-//     function prints before anything else to make it easy to follow the
-//     structure traversing order)
-//
-void visit_lldp_TLV_structure(uint8_t *memory_structure, PRINT_CALLBACK callback, PRINT_WRITER write_function, const char *prefix, struct blob_buf *bb);
-
-// Use this function for debug purposes. It turns a TLV_TYPE_* variable into its
-// string representation.
-//
-// Example: TLV_TYPE_CHASSIS_ID --> "TLV_TYPE_CHASSIS_ID"
-//
-// Return "Unknown" if the provided type does not exist.
-//
-char *convert_lldp_TLV_type_to_string(uint8_t tlv_type);
-
-#endif	// 0
-
-#endif
+#ifndef LLDP_TLVS_H
+#define LLDP_TLVS_H
+
+
+/* Tlv types */
+#define LLDP_TLV_EOL			0
+#define LLDP_TLV_CHASSIS_ID		1
+#define LLDP_TLV_PORT_ID		2
+#define LLDP_TLV_TTL			3
+
+
+/* TLV: end of LLDPPDU */
+struct tlv_eol {
+} __attribute__((packed));
+
+
+#define LLDP_CHASSIS_ID_SUBTYPE_CHASSIS_COMPONENT	1
+#define LLDP_CHASSIS_ID_SUBTYPE_INTERFACE_ALIAS		2
+#define LLDP_CHASSIS_ID_SUBTYPE_PORT_COMPONENT		3
+#define LLDP_CHASSIS_ID_SUBTYPE_MAC_ADDRESS		4
+#define LLDP_CHASSIS_ID_SUBTYPE_NETWORK_ADDRESS		5
+#define LLDP_CHASSIS_ID_SUBTYPE_INTERFACE_NAME		6
+#define LLDP_CHASSIS_ID_SUBTYPE_LOGICALLY_ASSIGNED	7
+
+/* TLV: chassis-id */
+struct tlv_chassis_id {
+	uint8_t subtype;
+	uint8_t id[256];
+} __attribute__((packed));
+
+
+
+#define LLDP_PORT_ID_SUBTYPE_INTERFACE_ALIAS		1
+#define LLDP_PORT_ID_SUBTYPE_PORT_COMPONENT		2
+#define LLDP_PORT_ID_SUBTYPE_MAC_ADDRESS		3
+#define LLDP_PORT_ID_SUBTYPE_NETWORK_ADDRESS		4
+#define LLDP_PORT_ID_SUBTYPE_INTERFACE_NAME		5
+#define LLDP_PORT_ID_SUBTYPE_AGENT_CIRCUIT_ID		6
+#define LLDP_PORT_ID_SUBTYPE_LOGICALLY_ASSIGNED		7
+
+/* TLV: port-id */
+struct tlv_port_id {
+	uint8_t subtype;
+	uint8_t id[256];
+} __attribute__((packed));
+
+
+
+#define LLDP_TTL_1905_DEFAULT_VALUE	180	/* in secs */
+
+/* TLV: ttl */
+struct tlv_ttl {
+	uint16_t ttl;	/* in secs */
+} __attribute__((packed));
+
+
+#endif	/* LLDP_TLVS_H */
diff --git a/src/main.c b/src/main.c
index 57ee1bd8b7a1764755e438bec04e3b794850788b..833db5aa7c79f7762404b007e88c0833bc597fce 100644
--- a/src/main.c
+++ b/src/main.c
@@ -28,6 +28,7 @@
 #include "worker.h"
 #include "config.h"
 #include "cmdu.h"
+#include "cmdu_ackq.h"
 #include "i1905_dm.h"
 #include "i1905.h"
 
diff --git a/src/util.h b/src/util.h
index 76b6e7d3a400d9fa8fc2927050074d5ff38a25cd..70bc0e4a54a986df5c975c51af8a6010cd19ca9d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -3,6 +3,7 @@
 #define NETIF_UTIL_H
 
 
+#include <libubox/list.h>
 
 void get_random_bytes(int num, uint8_t *buf);
 void bufprintf(uint8_t *buf, int len, const char *label);
@@ -39,4 +40,19 @@ extern int br_get_iflist(const char *brname, int *num, char ifs[][16]);
 #define MAC2STR(_m)	(_m)[0], (_m)[1], (_m)[2], (_m)[3], (_m)[4], (_m)[5]
 
 
+
+
+#ifndef list_flush
+#define list_flush(head, type, member)					\
+do {									\
+	type *__p, *__tmp;						\
+									\
+	if (!list_empty(head))						\
+		list_for_each_entry_safe(__p, __tmp, head, member) {	\
+			list_del(&__p->member);				\
+			free(__p);					\
+		}							\
+} while (0)
+#endif
+
 #endif /* NETIF_UTIL_H */