]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
snmp: add unit tests
authorVincent Bernat <bernat@luffy.cx>
Thu, 19 Jan 2012 19:26:31 +0000 (20:26 +0100)
committerVincent Bernat <bernat@luffy.cx>
Fri, 20 Jan 2012 09:37:17 +0000 (10:37 +0100)
This also happens to fix some minor issues with SNMP implementation.

CHANGELOG
src/Makefile.am
src/agent.c
src/agent.h [new file with mode: 0644]
tests/Makefile.am
tests/check_snmp.c [new file with mode: 0644]

index 49744f2be53762216c96af69f81880f18be74ca9..8c2cf7b8a14a87644a0a6f646185cdb87d6b7de2 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,8 @@
+lldpd (0.6)
+  * Fixes:
+    + Partial rewrite of the SNMP part. Less redundancy.
+    + Several small SNMP fixes (discovered by unit tests).
+
 lldpd (0.5.6)
   * Features:
     + Send and receive native VLAN TLV with CDP
index f3a8182b257a684ae9be8b118064b738117aa8c1..953c124dc1bf5cdb024683dd77e855bfb29d66e4 100644 (file)
@@ -20,7 +20,7 @@ lldpctl_LDADD = libcommon.la
 
 ## With SNMP...
 if USE_SNMP
-liblldpd_la_SOURCES += agent.c agent_priv.c
+liblldpd_la_SOURCES += agent.c agent_priv.c agent.h
 liblldpd_la_CFLAGS = @NETSNMP_CFLAGS@
 lldpd_LDADD += @NETSNMP_LIBS@
 endif
index 13a8e7a4b2c6af636808cfc976527c9a896168c9..fba56ee8d8bbc701d1e239c35ff51071fc33c44d 100644 (file)
  */
 
 #include "lldpd.h"
+#include "agent.h"
 #include "frame.h"
 
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-#include <net-snmp/agent/net-snmp-agent-includes.h>
-#include <net-snmp/agent/snmp_vars.h>
 #if HAVE_NET_SNMP_AGENT_UTIL_FUNCS_H
 #include <net-snmp/agent/util_funcs.h>
 #else
@@ -29,15 +26,14 @@ int header_generic(struct variable *, oid *, size_t *, int,
                   size_t *, WriteMethod **);
 #endif
 
-static oid lldp_oid[] = {1, 0, 8802, 1, 1, 2};
-
 /* For net-snmp */
 extern int register_sysORTable(oid *, size_t, const char *);
 extern int unregister_sysORTable(oid *, size_t);
 
 /* Global variable because no way to pass it as argument. Should not be used
  * elsewhere. */
-static struct lldpd *scfg;
+#define scfg agent_scfg
+struct lldpd *agent_scfg;
 
 static inline uint8_t
 swap_bits(uint8_t n)
@@ -73,14 +69,23 @@ struct header_index {
 };
 static struct header_index header_idx;
 
-static void
+static int
 header_index_init(struct variable *vp, oid *name, size_t *length,
     int exact, size_t *var_len, WriteMethod **write_method)
 {
+       /* If the requested OID name is less than OID prefix we
+          handle, adjust it to our prefix. */
         if ((snmp_oid_compare(name, *length, vp->name, vp->namelen)) < 0) {
                 memcpy(name, vp->name, sizeof(oid) * vp->namelen);
                 *length = vp->namelen;
         }
+       /* Now, we can only handle OID matching our prefix. Those two
+          tests are not really necessary since NetSNMP won't give us
+          OID "above" our prefix. But this makes unit tests
+          easier.  */
+       if (*length < vp->namelen) return 0;
+       if (memcmp(name, vp->name, vp->namelen * sizeof(oid))) return 0;
+
        if(write_method != NULL) *write_method = 0;
        *var_len = sizeof(long);
 
@@ -91,6 +96,7 @@ header_index_init(struct variable *vp, oid *name, size_t *length,
        header_idx.exact = exact;
        header_idx.best_len = 0;
        header_idx.entity = NULL;
+       return 1;
 }
 
 static int
@@ -137,7 +143,7 @@ header_portindexed_table(struct variable *vp, oid *name, size_t *length,
 {
        struct lldpd_hardware *hardware;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                oid index[1] = { hardware->h_ifindex };
                if (header_index_add(index, 1,
@@ -155,7 +161,7 @@ header_pmedindexed_policy_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_hardware *hardware;
        int i;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                for (i = 0; i < LLDPMED_APPTYPE_LAST; i++) {
                        if (hardware->h_lport.p_med_policy[i].type != i+1)
@@ -177,13 +183,13 @@ header_pmedindexed_location_table(struct variable *vp, oid *name, size_t *length
        struct lldpd_hardware *hardware;
        int i;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                for (i = 0; i < LLDPMED_LOCFORMAT_LAST; i++) {
                        if (hardware->h_lport.p_med_location[i].format != i+1)
                                continue;
                        oid index[2] = { hardware->h_ifindex,
-                                        i + 1 };
+                                        i + 2 };
                        if (header_index_add(index, 2,
                                             &hardware->h_lport.p_med_location[i]))
                                return &hardware->h_lport.p_med_location[i];
@@ -201,7 +207,7 @@ header_tprindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_hardware *hardware;
        struct lldpd_port *port;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
                        if (SMART_HIDDEN(scfg, port)) continue;
@@ -223,7 +229,7 @@ header_ipindexed_table(struct variable *vp, oid *name, size_t *length,
 {
        struct lldpd_chassis *chassis = LOCAL_CHASSIS(scfg);
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        oid index[6] = {
                1, 4,
                ((u_int8_t*)&chassis->c_mgmt.s_addr)[0],
@@ -244,7 +250,7 @@ header_tpripindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_hardware *hardware;
        struct lldpd_port *port;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
                        if (SMART_HIDDEN(scfg, port)) continue;
@@ -276,7 +282,7 @@ header_tprmedindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_port *port;
        int j;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
                        if (SMART_HIDDEN(scfg, port)) continue;
@@ -294,7 +300,7 @@ header_tprmedindexed_table(struct variable *vp, oid *name, size_t *length,
                                                         j+1 };
                                        if (header_index_add(index, 4,
                                                             &port->p_med_policy[j]))
-                                               return port;
+                                               return &port->p_med_policy[j];
                                }
                                break;
                        case TPR_VARIANT_MED_LOCATION:
@@ -306,10 +312,10 @@ header_tprmedindexed_table(struct variable *vp, oid *name, size_t *length,
                                        oid index[4] = { lastchange(port),
                                                         hardware->h_ifindex,
                                                         port->p_chassis->c_index,
-                                                        j+1 };
+                                                        j+2 };
                                        if (header_index_add(index, 4,
                                                             &port->p_med_location[j]))
-                                               return port;
+                                               return &port->p_med_location[j];
                                }
                                break;
                        }
@@ -326,7 +332,7 @@ header_pvindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_hardware *hardware;
         struct lldpd_vlan *vlan;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(vlan, &hardware->h_lport.p_vlans, v_entries) {
                        oid index[2] = { hardware->h_ifindex,
@@ -346,7 +352,7 @@ header_tprvindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_port *port;
         struct lldpd_vlan *vlan;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
                        if (SMART_HIDDEN(scfg, port)) continue;
@@ -371,7 +377,7 @@ header_pppvidindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_hardware *hardware;
         struct lldpd_ppvid *ppvid;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(ppvid, &hardware->h_lport.p_ppvids, p_entries) {
                        oid index[2] = { hardware->h_ifindex,
@@ -392,7 +398,7 @@ header_tprppvidindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_port *port;
         struct lldpd_ppvid *ppvid;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
                        if (SMART_HIDDEN(scfg, port)) continue;
@@ -417,7 +423,7 @@ header_ppiindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_hardware *hardware;
         struct lldpd_pi *pi;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(pi, &hardware->h_lport.p_pids, p_entries) {
                        oid index[2] = { hardware->h_ifindex,
@@ -439,7 +445,7 @@ header_tprpiindexed_table(struct variable *vp, oid *name, size_t *length,
        struct lldpd_port *port;
         struct lldpd_pi *pi;
 
-       header_index_init(vp, name, length, exact, var_len, write_method);
+       if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL;
        TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) {
                TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
                        if (SMART_HIDDEN(scfg, port)) continue;
@@ -478,9 +484,7 @@ header_tprpiindexed_table(struct variable *vp, oid *name, size_t *length,
 #define LLDP_SNMP_SYSCAP_SUP 5
 #define LLDP_SNMP_SYSCAP_ENA 6
 /* Stats */
-#define LLDP_SNMP_STATS_TX_PORTNUM 1
 #define LLDP_SNMP_STATS_TX 2
-#define LLDP_SNMP_STATS_RX_PORTNUM 3
 #define LLDP_SNMP_STATS_RX_DISCARDED 4
 #define LLDP_SNMP_STATS_RX_ERRORS 5
 #define LLDP_SNMP_STATS_RX 6
@@ -488,7 +492,6 @@ header_tprpiindexed_table(struct variable *vp, oid *name, size_t *length,
 #define LLDP_SNMP_STATS_RX_TLVUNRECOGNIZED 8
 #define LLDP_SNMP_STATS_RX_AGEOUTS 9
 /* Ports */
-#define LLDP_SNMP_LOCAL_PORTNUM 1
 #define LLDP_SNMP_PIDSUBTYPE 2
 #define LLDP_SNMP_PID 3
 #define LLDP_SNMP_PORTDESC 4
@@ -513,9 +516,7 @@ header_tprpiindexed_table(struct variable *vp, oid *name, size_t *length,
 #define LLDP_SNMP_DOT1_PVID 23
 /* Vlans */
 #define LLDP_SNMP_DOT1_VLANNAME 1
-#define LLDP_SNMP_DOT1_VLANID 2
 /* Protocol VLAN IDs */
-#define LLDP_SNMP_DOT1_PPVID           1
 #define LLDP_SNMP_DOT1_PPVLAN_SUPPORTED        2
 #define LLDP_SNMP_DOT1_PPVLAN_ENABLED  3
 /* Protocol Identity */
@@ -1037,15 +1038,10 @@ agent_h_stats(struct variable *vp, oid *name, size_t *length,
 static u_char*
 agent_v_vlan(struct variable *vp, size_t *var_len, struct lldpd_vlan *vlan)
 {
-       static unsigned long long_ret;
-
        switch (vp->magic) {
        case LLDP_SNMP_DOT1_VLANNAME:
                *var_len = strlen(vlan->v_name);
                return (u_char *)vlan->v_name;
-       case LLDP_SNMP_DOT1_VLANID:
-               long_ret = vlan->v_vid;
-               return (u_char *)&long_ret;
        default:
                break;
         }
@@ -1082,9 +1078,6 @@ agent_v_ppvid(struct variable *vp, size_t *var_len, struct lldpd_ppvid *ppvid)
        static unsigned long long_ret;
 
        switch (vp->magic) {
-       case LLDP_SNMP_DOT1_PPVID:
-               long_ret = ppvid->p_ppvid;
-               return (u_char *)&long_ret;
        case LLDP_SNMP_DOT1_PPVLAN_SUPPORTED:
                long_ret = (ppvid->p_cap_status & LLDPD_PPVID_CAP_SUPPORTED)?1:2;
                return (u_char *)&long_ret;
@@ -1164,6 +1157,7 @@ static u_char*
 agent_v_port(struct variable *vp, size_t *var_len, struct lldpd_port *port)
 {
 #ifdef ENABLE_DOT3
+       static uint16_t short_ret;
        static uint8_t bit;
 #endif
         static unsigned long long_ret;
@@ -1187,7 +1181,8 @@ agent_v_port(struct variable *vp, size_t *var_len, struct lldpd_port *port)
                 return (u_char *)&long_ret;
         case LLDP_SNMP_DOT3_AUTONEG_ADVERTISED:
                 *var_len = 2;
-                return (u_char *)&port->p_macphy.autoneg_advertised;
+               short_ret = htons(port->p_macphy.autoneg_advertised);
+                return (u_char *)&short_ret;
         case LLDP_SNMP_DOT3_AUTONEG_MAU:
                 long_ret = port->p_macphy.mau_type;
                 return (u_char *)&long_ret;
@@ -1199,8 +1194,11 @@ agent_v_port(struct variable *vp, size_t *var_len, struct lldpd_port *port)
                 long_ret = port->p_aggregid;
                 return (u_char *)&long_ret;
         case LLDP_SNMP_DOT3_MFS:
-                long_ret = port->p_mfs;
-                return (u_char *)&long_ret;
+               if (port->p_mfs) {
+                       long_ret = port->p_mfs;
+                       return (u_char *)&long_ret;
+               }
+               break;
        case LLDP_SNMP_DOT3_POWER_DEVICETYPE:
                if (port->p_power.devicetype) {
                        long_ret = (port->p_power.devicetype == LLDP_DOT3_POWER_PSE)?1:2;
@@ -1242,7 +1240,7 @@ agent_v_port(struct variable *vp, size_t *var_len, struct lldpd_port *port)
                    port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
                        *var_len = 1;
                        bit = (((port->p_power.powertype ==
-                                   LLDP_DOT3_POWER_8023AT_TYPE1)?1:0) << 7) |
+                                   LLDP_DOT3_POWER_8023AT_TYPE1)?0:1) << 7) |
                            (((port->p_power.devicetype ==
                                    LLDP_DOT3_POWER_PSE)?0:1) << 6);
                        return (u_char *)&bit;
@@ -1259,7 +1257,8 @@ agent_v_port(struct variable *vp, size_t *var_len, struct lldpd_port *port)
        case LLDP_SNMP_DOT3_POWER_PRIORITY:
                if (port->p_power.devicetype &&
                    port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
-                       long_ret = port->p_power.priority;
+                       /* See 30.12.2.1.16. This seems defined in reverse order... */
+                       long_ret = 4 - port->p_power.priority;
                        return (u_char *)&long_ret;
                }
                break;
@@ -1384,7 +1383,8 @@ agent_h_remote_management(struct variable *vp, oid *name, size_t *length,
   are the same for both version.
 */
 
-static struct variable8 lldp_vars[] = {
+/* For testing purposes, keep this structure ordered by increasing OID! */
+struct variable8 agent_lldp_vars[] = {
        /* Scalars */
        {LLDP_SNMP_TXINTERVAL, ASN_INTEGER, RONLY, agent_h_scalars, 3, {1, 1, 1}},
        {LLDP_SNMP_TXMULTIPLIER, ASN_INTEGER, RONLY, agent_h_scalars, 3, {1, 1, 2}},
@@ -1396,13 +1396,6 @@ static struct variable8 lldp_vars[] = {
        {LLDP_SNMP_STATS_DELETES, ASN_GAUGE, RONLY, agent_h_scalars, 3, {1, 2, 3}},
        {LLDP_SNMP_STATS_DROPS, ASN_GAUGE, RONLY, agent_h_scalars, 3, {1, 2, 4}},
        {LLDP_SNMP_STATS_AGEOUTS, ASN_GAUGE, RONLY, agent_h_scalars, 3, {1, 2, 5}},
-       /* Local chassis */
-       {LLDP_SNMP_CIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_local_chassis, 3, {1, 3, 1}},
-       {LLDP_SNMP_CID, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 2}},
-       {LLDP_SNMP_SYSNAME, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 3}},
-       {LLDP_SNMP_SYSDESCR, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 4}},
-       {LLDP_SNMP_SYSCAP_SUP, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 5}},
-       {LLDP_SNMP_SYSCAP_ENA, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 6}},
        /* Stats */
        {LLDP_SNMP_STATS_TX, ASN_COUNTER, RONLY, agent_h_stats, 5, {1, 2, 6, 1, 2}},
        {LLDP_SNMP_STATS_RX_DISCARDED, ASN_COUNTER, RONLY, agent_h_stats, 5, {1, 2, 7, 1, 2}},
@@ -1411,10 +1404,44 @@ static struct variable8 lldp_vars[] = {
        {LLDP_SNMP_STATS_RX_TLVDISCARDED, ASN_COUNTER, RONLY, agent_h_stats, 5, {1, 2, 7, 1, 5}},
        {LLDP_SNMP_STATS_RX_TLVUNRECOGNIZED, ASN_COUNTER, RONLY, agent_h_stats, 5, {1, 2, 7, 1, 6}},
        {LLDP_SNMP_STATS_RX_AGEOUTS, ASN_GAUGE, RONLY, agent_h_stats, 5, {1, 2, 7, 1, 7}},
+       /* Local chassis */
+       {LLDP_SNMP_CIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_local_chassis, 3, {1, 3, 1}},
+       {LLDP_SNMP_CID, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 2}},
+       {LLDP_SNMP_SYSNAME, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 3}},
+       {LLDP_SNMP_SYSDESCR, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 4}},
+       {LLDP_SNMP_SYSCAP_SUP, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 5}},
+       {LLDP_SNMP_SYSCAP_ENA, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, {1, 3, 6}},
        /* Local ports */
        {LLDP_SNMP_PIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_local_port, 5, {1, 3, 7, 1, 2}},
        {LLDP_SNMP_PID, ASN_OCTET_STR, RONLY, agent_h_local_port, 5, {1, 3, 7, 1, 3}},
        {LLDP_SNMP_PORTDESC, ASN_OCTET_STR, RONLY, agent_h_local_port, 5, {1, 3, 7, 1, 4}},
+        /* Local management address */
+        {LLDP_SNMP_ADDR_LEN, ASN_INTEGER, RONLY, agent_h_local_management, 5,
+         {1, 3, 8, 1, 3}},
+        {LLDP_SNMP_ADDR_IFSUBTYPE, ASN_INTEGER, RONLY, agent_h_local_management, 5,
+         {1, 3, 8, 1, 4}},
+        {LLDP_SNMP_ADDR_IFID, ASN_INTEGER, RONLY, agent_h_local_management, 5,
+         {1, 3, 8, 1, 5}},
+        {LLDP_SNMP_ADDR_OID, ASN_OBJECT_ID, RONLY, agent_h_local_management, 5,
+         {1, 3, 8, 1, 6}},
+        /* Remote ports */
+        {LLDP_SNMP_CIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 4}},
+        {LLDP_SNMP_CID, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 5}},
+        {LLDP_SNMP_PIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_port, 5, {1, 4, 1, 1, 6}},
+        {LLDP_SNMP_PID, ASN_OCTET_STR, RONLY, agent_h_remote_port, 5, {1, 4, 1, 1, 7}},
+        {LLDP_SNMP_PORTDESC, ASN_OCTET_STR, RONLY, agent_h_remote_port, 5, {1, 4, 1, 1, 8}},
+        {LLDP_SNMP_SYSNAME, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 9}},
+        {LLDP_SNMP_SYSDESCR, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 10}},
+        {LLDP_SNMP_SYSCAP_SUP, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 11}},
+        {LLDP_SNMP_SYSCAP_ENA, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 12}},
+       /* Remote management address */
+        {LLDP_SNMP_ADDR_IFSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_management, 5,
+         {1, 4, 2, 1, 3}},
+        {LLDP_SNMP_ADDR_IFID, ASN_INTEGER, RONLY, agent_h_remote_management, 5,
+         {1, 4, 2, 1, 4}},
+        {LLDP_SNMP_ADDR_OID, ASN_OBJECT_ID, RONLY, agent_h_remote_management, 5,
+         {1, 4, 2, 1, 5}},
+       /* Dot3, local ports */
 #ifdef ENABLE_DOT3
         {LLDP_SNMP_DOT3_AUTONEG_SUPPORT, ASN_INTEGER, RONLY, agent_h_local_port, 8,
          {1, 5, 4623, 1, 2, 1, 1, 1}},
@@ -1453,32 +1480,7 @@ static struct variable8 lldp_vars[] = {
         {LLDP_SNMP_DOT3_MFS, ASN_INTEGER, RONLY, agent_h_local_port, 8,
          {1, 5, 4623, 1, 2, 4, 1, 1}},
 #endif
-#ifdef ENABLE_DOT1
-        {LLDP_SNMP_DOT1_PVID, ASN_INTEGER, RONLY, agent_h_local_port, 8,
-         {1, 5, 32962, 1, 2, 1, 1, 1}},
-        {LLDP_SNMP_DOT1_PPVID, ASN_INTEGER, RONLY, agent_h_local_ppvid, 8,
-         {1, 5, 32962, 1, 2, 2, 1, 1}},
-        {LLDP_SNMP_DOT1_PPVLAN_SUPPORTED, ASN_INTEGER, RONLY, agent_h_local_ppvid, 8,
-         {1, 5, 32962, 1, 2, 2, 1, 2}},
-        {LLDP_SNMP_DOT1_PPVLAN_ENABLED, ASN_INTEGER, RONLY, agent_h_local_ppvid, 8,
-         {1, 5, 32962, 1, 2, 2, 1, 3}},
-        {LLDP_SNMP_DOT1_VLANID, ASN_INTEGER, RONLY, agent_h_local_vlan, 8,
-         {1, 5, 32962, 1, 2, 3, 1, 1}},
-        {LLDP_SNMP_DOT1_VLANNAME, ASN_OCTET_STR, RONLY, agent_h_local_vlan, 8,
-         {1, 5, 32962, 1, 2, 3, 1, 2}},
-       {LLDP_SNMP_DOT1_PI, ASN_OCTET_STR, RONLY, agent_h_local_pi, 8,
-        {1, 5, 32962, 1, 2, 4, 1, 2}},
-#endif
-        /* Remote ports */
-        {LLDP_SNMP_CIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 4}},
-        {LLDP_SNMP_CID, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 5}},
-        {LLDP_SNMP_PIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_port, 5, {1, 4, 1, 1, 6}},
-        {LLDP_SNMP_PID, ASN_OCTET_STR, RONLY, agent_h_remote_port, 5, {1, 4, 1, 1, 7}},
-        {LLDP_SNMP_PORTDESC, ASN_OCTET_STR, RONLY, agent_h_remote_port, 5, {1, 4, 1, 1, 8}},
-        {LLDP_SNMP_SYSNAME, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 9}},
-        {LLDP_SNMP_SYSDESCR, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 10}},
-        {LLDP_SNMP_SYSCAP_SUP, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 11}},
-        {LLDP_SNMP_SYSCAP_ENA, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5, {1, 4, 1, 1, 12}},
+       /* Dot3, remote ports */
 #ifdef ENABLE_DOT3
         {LLDP_SNMP_DOT3_AUTONEG_SUPPORT, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
          {1, 5, 4623, 1, 3, 1, 1, 1}},
@@ -1517,39 +1519,6 @@ static struct variable8 lldp_vars[] = {
         {LLDP_SNMP_DOT3_MFS, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
          {1, 5, 4623, 1, 3, 4, 1, 1}},
 #endif
-#ifdef ENABLE_DOT1
-        {LLDP_SNMP_DOT1_PVID, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
-         {1, 5, 32962, 1, 3, 1, 1, 1}},
-        {LLDP_SNMP_DOT1_PPVID, ASN_INTEGER, RONLY, agent_h_remote_ppvid, 8,
-         {1, 5, 32962, 1, 3, 2, 1, 1}},
-        {LLDP_SNMP_DOT1_PPVLAN_SUPPORTED, ASN_INTEGER, RONLY, agent_h_remote_ppvid, 8,
-         {1, 5, 32962, 1, 3, 2, 1, 2}},
-        {LLDP_SNMP_DOT1_PPVLAN_ENABLED, ASN_INTEGER, RONLY, agent_h_remote_ppvid, 8,
-         {1, 5, 32962, 1, 3, 2, 1, 3}},
-        /* Remote vlans */
-        {LLDP_SNMP_DOT1_VLANID, ASN_INTEGER, RONLY, agent_h_remote_vlan, 8,
-         {1, 5, 32962, 1, 3, 3, 1, 1}},
-        {LLDP_SNMP_DOT1_VLANNAME, ASN_OCTET_STR, RONLY, agent_h_remote_vlan, 8,
-         {1, 5, 32962, 1, 3, 3, 1, 2}},
-       /* Protocol identity */
-       {LLDP_SNMP_DOT1_PI, ASN_OCTET_STR, RONLY, agent_h_remote_pi, 8,
-        {1, 5, 32962, 1, 3, 4, 1, 2}},
-#endif
-        /* Management address */
-        {LLDP_SNMP_ADDR_LEN, ASN_INTEGER, RONLY, agent_h_local_management, 5,
-         {1, 3, 8, 1, 3}},
-        {LLDP_SNMP_ADDR_IFSUBTYPE, ASN_INTEGER, RONLY, agent_h_local_management, 5,
-         {1, 3, 8, 1, 4}},
-        {LLDP_SNMP_ADDR_IFID, ASN_INTEGER, RONLY, agent_h_local_management, 5,
-         {1, 3, 8, 1, 5}},
-        {LLDP_SNMP_ADDR_OID, ASN_OBJECT_ID, RONLY, agent_h_local_management, 5,
-         {1, 3, 8, 1, 6}},
-        {LLDP_SNMP_ADDR_IFSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_management, 5,
-         {1, 4, 2, 1, 3}},
-        {LLDP_SNMP_ADDR_IFID, ASN_INTEGER, RONLY, agent_h_remote_management, 5,
-         {1, 4, 2, 1, 4}},
-        {LLDP_SNMP_ADDR_OID, ASN_OBJECT_ID, RONLY, agent_h_remote_management, 5,
-         {1, 4, 2, 1, 5}},
 #ifdef ENABLE_LLDPMED
        /* LLDP-MED local */
        {LLDP_SNMP_MED_CLASS, ASN_INTEGER, RONLY, agent_h_local_med, 6,
@@ -1601,6 +1570,16 @@ static struct variable8 lldp_vars[] = {
         {1, 5, 4795, 1, 3, 1, 1, 2}},
        {LLDP_SNMP_MED_CLASS, ASN_INTEGER, RONLY, agent_h_remote_med, 8,
         {1, 5, 4795, 1, 3, 1, 1, 3}},
+       {LLDP_SNMP_MED_POLICY_VID, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
+        {1, 5, 4795, 1, 3, 2, 1, 2}},
+       {LLDP_SNMP_MED_POLICY_PRIO, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
+        {1, 5, 4795, 1, 3, 2, 1, 3}},
+       {LLDP_SNMP_MED_POLICY_DSCP, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
+        {1, 5, 4795, 1, 3, 2, 1, 4}},
+       {LLDP_SNMP_MED_POLICY_UNKNOWN, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
+        {1, 5, 4795, 1, 3, 2, 1, 5}},
+       {LLDP_SNMP_MED_POLICY_TAGGED, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
+        {1, 5, 4795, 1, 3, 2, 1, 6}},
        {LLDP_SNMP_MED_HW, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
         {1, 5, 4795, 1, 3, 3, 1, 1}},
        {LLDP_SNMP_MED_FW, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
@@ -1615,16 +1594,6 @@ static struct variable8 lldp_vars[] = {
         {1, 5, 4795, 1, 3, 3, 1, 6}},
        {LLDP_SNMP_MED_ASSET, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
         {1, 5, 4795, 1, 3, 3, 1, 7}},
-       {LLDP_SNMP_MED_POLICY_VID, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
-        {1, 5, 4795, 1, 3, 2, 1, 2}},
-       {LLDP_SNMP_MED_POLICY_PRIO, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
-        {1, 5, 4795, 1, 3, 2, 1, 3}},
-       {LLDP_SNMP_MED_POLICY_DSCP, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
-        {1, 5, 4795, 1, 3, 2, 1, 4}},
-       {LLDP_SNMP_MED_POLICY_UNKNOWN, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
-        {1, 5, 4795, 1, 3, 2, 1, 5}},
-       {LLDP_SNMP_MED_POLICY_TAGGED, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
-        {1, 5, 4795, 1, 3, 2, 1, 6}},
        {LLDP_SNMP_MED_LOCATION, ASN_OCTET_STR, RONLY, agent_h_remote_med_location, 8,
         {1, 5, 4795, 1, 3, 4, 1, 2}},
        {LLDP_SNMP_MED_POE_DEVICETYPE, ASN_INTEGER, RONLY, agent_h_remote_med_power, 8,
@@ -1641,8 +1610,39 @@ static struct variable8 lldp_vars[] = {
         {1, 5, 4795, 1, 3, 7, 1, 2}},
        {LLDP_SNMP_MED_POE_PD_POWERPRIORITY, ASN_INTEGER, RONLY, agent_h_remote_med_power, 8,
         {1, 5, 4795, 1, 3, 7, 1, 3}},
+#endif
+       /* Dot1, local and remote ports */
+#ifdef ENABLE_DOT1
+        {LLDP_SNMP_DOT1_PVID, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+         {1, 5, 32962, 1, 2, 1, 1, 1}},
+        {LLDP_SNMP_DOT1_PPVLAN_SUPPORTED, ASN_INTEGER, RONLY, agent_h_local_ppvid, 8,
+         {1, 5, 32962, 1, 2, 2, 1, 2}},
+        {LLDP_SNMP_DOT1_PPVLAN_ENABLED, ASN_INTEGER, RONLY, agent_h_local_ppvid, 8,
+         {1, 5, 32962, 1, 2, 2, 1, 3}},
+        {LLDP_SNMP_DOT1_VLANNAME, ASN_OCTET_STR, RONLY, agent_h_local_vlan, 8,
+         {1, 5, 32962, 1, 2, 3, 1, 2}},
+       {LLDP_SNMP_DOT1_PI, ASN_OCTET_STR, RONLY, agent_h_local_pi, 8,
+        {1, 5, 32962, 1, 2, 4, 1, 2}},
+#endif
+#ifdef ENABLE_DOT1
+        {LLDP_SNMP_DOT1_PVID, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
+         {1, 5, 32962, 1, 3, 1, 1, 1}},
+        {LLDP_SNMP_DOT1_PPVLAN_SUPPORTED, ASN_INTEGER, RONLY, agent_h_remote_ppvid, 8,
+         {1, 5, 32962, 1, 3, 2, 1, 2}},
+        {LLDP_SNMP_DOT1_PPVLAN_ENABLED, ASN_INTEGER, RONLY, agent_h_remote_ppvid, 8,
+         {1, 5, 32962, 1, 3, 2, 1, 3}},
+        /* Remote vlans */
+        {LLDP_SNMP_DOT1_VLANNAME, ASN_OCTET_STR, RONLY, agent_h_remote_vlan, 8,
+         {1, 5, 32962, 1, 3, 3, 1, 2}},
+       /* Protocol identity */
+       {LLDP_SNMP_DOT1_PI, ASN_OCTET_STR, RONLY, agent_h_remote_pi, 8,
+        {1, 5, 32962, 1, 3, 4, 1, 2}},
 #endif
 };
+size_t agent_lldp_vars_size(void) {
+       return sizeof(agent_lldp_vars)/sizeof(struct variable8);
+}
+
 
 void
 agent_init(struct lldpd *cfg, char *agentx, int debug)
@@ -1677,7 +1677,7 @@ agent_init(struct lldpd *cfg, char *agentx, int debug)
                netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                                      NETSNMP_DS_AGENT_X_SOCKET, agentx);
        init_agent("lldpAgent");
-       REGISTER_MIB("lldp", lldp_vars, variable8, lldp_oid);
+       REGISTER_MIB("lldp", agent_lldp_vars, variable8, lldp_oid);
        init_snmp("lldpAgent");
 
        if ((rc = register_sysORTable(lldp_oid, OID_LENGTH(lldp_oid),
diff --git a/src/agent.h b/src/agent.h
new file mode 100644 (file)
index 0000000..46b7f90
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/snmp_vars.h>
+
+static oid lldp_oid[] = {1, 0, 8802, 1, 1, 2};
+size_t agent_lldp_vars_size(void);
index 8822856c80d4e21ce6b920395911b9e05e73b1db..873c548cbe55918aaf3f93abd78ba303e2455701 100644 (file)
@@ -1,4 +1,4 @@
-TESTS = check_pack check_lldp check_cdp check_sonmp check_edp check_ifaddrs
+TESTS = check_pack check_lldp check_cdp check_sonmp check_edp check_ifaddrs check_snmp
 
 if HAVE_CHECK
 
@@ -29,7 +29,12 @@ check_ifaddrs_SOURCES = check_ifaddrs.c \
 
 AM_CFLAGS = @CHECK_CFLAGS@
 LDADD = $(top_builddir)/src/liblldpd.la @CHECK_LIBS@
+
 if USE_SNMP
+check_snmp_SOURCES = check_snmp.c \
+       $(top_builddir)/src/lldpd.h \
+       $(top_builddir)/src/agent.h
+
 LDADD += @NETSNMP_LIBS@
 endif
 
diff --git a/tests/check_snmp.c b/tests/check_snmp.c
new file mode 100644 (file)
index 0000000..b420e36
--- /dev/null
@@ -0,0 +1,995 @@
+#include <check.h>
+
+#include "../src/lldpd.h"
+#include "../src/agent.h"
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/snmp_vars.h>
+
+extern struct lldpd *agent_scfg;
+extern struct timeval starttime;
+extern struct variable8 agent_lldp_vars[];
+extern int asprintf (char **, char *, ...);
+
+/* Our test config */
+struct lldpd test_cfg = {
+       .g_delay = 30,
+       .g_smart = 0,
+};
+struct timeval test_starttime = { .tv_sec = 100, .tv_usec = 0 };
+
+/* First chassis */
+struct lldpd_chassis chassis1 = {
+       .c_index         = 1,
+       .c_protocol      = LLDPD_MODE_LLDP,
+       .c_id_subtype    = LLDP_CHASSISID_SUBTYPE_LLADDR,
+       .c_id            = "AAA012",
+       .c_id_len        = 6,
+       .c_name          = "chassis1.example.com",
+       .c_descr         = "First chassis",
+       .c_cap_available = LLDP_CAP_BRIDGE | LLDP_CAP_WLAN | LLDP_CAP_ROUTER,
+       .c_cap_enabled   = LLDP_CAP_ROUTER,
+       .c_ttl           = 60,
+       .c_mgmt          = { .s_addr = 251789504 }, /* 192.0.2.15 */
+       .c_mgmt_if       = 3,
+#ifdef ENABLE_LLDPMED
+       .c_med_cap_available = LLDPMED_CAP_CAP | LLDPMED_CAP_IV | \
+               LLDPMED_CAP_LOCATION |  LLDPMED_CAP_POLICY | \
+               LLDPMED_CAP_MDI_PSE | LLDPMED_CAP_MDI_PD,
+       .c_med_type   = LLDPMED_CLASS_II,
+       .c_med_hw     = "Hardware 1",
+       /* We skip c_med_fw */
+       .c_med_sw     = "Software 1",
+       .c_med_sn     = "00-00-0000-AAAA",
+       .c_med_manuf  = "Manufacturer 1",
+       .c_med_model  = "Model 1",
+       .c_med_asset  = "Asset 1",
+#endif
+};
+/* Second chassis */
+struct lldpd_chassis chassis2 = {
+       .c_index         = 4,
+       .c_protocol      = LLDPD_MODE_LLDP,
+       .c_id_subtype    = LLDP_CHASSISID_SUBTYPE_LOCAL,
+       .c_id            = "chassis2",
+       .c_id_len        = 6,
+       .c_name          = "chassis2.example.com",
+       .c_descr         = "Second chassis",
+       .c_cap_available = LLDP_CAP_ROUTER,
+       .c_cap_enabled   = LLDP_CAP_ROUTER,
+       .c_ttl           = 60,
+       .c_mgmt          = { .s_addr = 285343936 }, /* 192.0.2.17 */
+       .c_mgmt_if       = 5,
+#ifdef ENABLE_LLDPMED
+       .c_med_hw     = "Hardware 2",
+       /* We skip c_med_fw */
+       .c_med_sw     = "Software 2",
+       .c_med_sn     = "00-00-0000-AAAC",
+       .c_med_manuf  = "Manufacturer 2",
+       .c_med_model  = "Model 2",
+       .c_med_asset  = "Asset 2",
+#endif
+};
+
+/* First port of first chassis */
+struct lldpd_hardware hardware1 = {
+       .h_ifindex = 3,
+       .h_tx_cnt = 1352,
+       .h_rx_cnt = 1458,
+       .h_rx_discarded_cnt = 5,
+       .h_rx_ageout_cnt = 1455,
+       .h_rx_unrecognized_cnt = 4,
+       .h_lport = {
+               .p_chassis    = &chassis1,
+               .p_lastchange = 200,
+               .p_protocol   = LLDPD_MODE_LLDP,
+               .p_id_subtype = LLDP_PORTID_SUBTYPE_LLADDR,
+               .p_id         = "AAA012",
+               .p_id_len     = 6,
+               .p_descr      = "eth2",
+               .p_mfs        = 1600,
+#ifdef ENABLE_DOT3
+               .p_aggregid   = 0,
+               .p_macphy     = {
+                       .autoneg_support = 1,
+                       .autoneg_enabled = 1,
+                       .autoneg_advertised = LLDP_DOT3_LINK_AUTONEG_100BASE_TX | LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD,
+                       .mau_type = LLDP_DOT3_MAU_100BASETXFD,
+               },
+               .p_power = {
+                       .devicetype  = LLDP_DOT3_POWER_PD,
+                       .supported   = 1,
+                       .enabled     = 1,
+                       .paircontrol = 1,
+                       .pairs       = 2,
+                       .class       = 3,
+                       .powertype   = LLDP_DOT3_POWER_8023AT_TYPE2,
+                       .source      = LLDP_DOT3_POWER_SOURCE_BOTH,
+                       .priority    = LLDP_DOT3_POWER_PRIO_LOW,
+                       .requested   = 2000,
+                       .allocated   = 2500,
+               },
+#endif
+#ifdef ENABLE_LLDPMED
+               .p_med_cap_enabled = LLDPMED_CAP_CAP | LLDPMED_CAP_IV | LLDPMED_CAP_MDI_PD |
+                       LLDPMED_CAP_POLICY | LLDPMED_CAP_LOCATION,
+               .p_med_policy = {
+                       { .type = 0 }, { .type = 0 }, {
+                               .type = LLDPMED_APPTYPE_GUESTVOICE,
+                               .unknown = 1,
+                               .tagged = 1,
+                               .vid = 475,
+                               .priority = 3,
+                               .dscp = 62
+                       }, { .type = 0 }, { .type = 0 }, { .type = 0 }, {
+                               .type = LLDPMED_APPTYPE_VIDEOSTREAM,
+                               .unknown = 0,
+                               .tagged = 1,
+                               .vid = 472,
+                               .priority = 1,
+                               .dscp = 60
+                       }, { .type = 0 }
+               },
+               .p_med_location = {
+                       { .format = 0 }, {
+                               .format = LLDPMED_LOCFORMAT_CIVIC,
+                               /* 2:FR:6:Commercial Rd:19:4 */
+                               .data = "\x15\x02FR\x06\x0dCommercial Rd\x13\x014",
+                               .data_len = 22,
+                       }, { .format = 0 }
+               },
+               .p_med_power = {
+                       .devicetype = LLDPMED_POW_TYPE_PD,
+                       .source = LLDPMED_POW_SOURCE_LOCAL,
+                       .priority = LLDPMED_POW_PRIO_HIGH,
+                       .val = 100
+               },
+#endif         
+#ifdef ENABLE_DOT1
+               .p_pvid = 47,
+               /* Remaining is done is snmp_config */
+#endif
+       }
+};
+/* Second port of first chassis */
+struct lldpd_hardware hardware2 = {
+       .h_ifindex = 4,
+       .h_tx_cnt = 11352,
+       .h_rx_cnt = 11458,
+       .h_rx_discarded_cnt = 55,
+       .h_rx_ageout_cnt = 21455,
+       .h_rx_unrecognized_cnt = 14,
+       .h_lport = {
+               .p_chassis    = &chassis1,
+               .p_lastchange = 50,
+               .p_protocol   = LLDPD_MODE_LLDP,
+               .p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME,
+               .p_id         = "eth4",
+               .p_id_len     = 4,
+               .p_descr      = "Intel 1000 GE",
+               .p_mfs        = 9000,
+#ifdef ENABLE_DOT3
+               .p_aggregid   = 3,
+               .p_macphy     = {
+                       .autoneg_support = 1,
+                       .autoneg_enabled = 1,
+                       .autoneg_advertised = LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD | LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD,
+                       .mau_type = LLDP_DOT3_MAU_1000BASETFD,
+               },
+#endif
+#ifdef ENABLE_LLDPMED
+               .p_med_cap_enabled = LLDPMED_CAP_CAP | LLDPMED_CAP_IV | LLDPMED_CAP_MDI_PD |
+                       LLDPMED_CAP_MDI_PSE | LLDPMED_CAP_POLICY | LLDPMED_CAP_LOCATION,
+               .p_med_policy = {
+                       { .type = 0 }, { .type = 0 }, {
+                               .type = LLDPMED_APPTYPE_GUESTVOICE,
+                               .unknown = 1,
+                               .tagged = 1,
+                               .vid = 475,
+                               .priority = 3,
+                               .dscp = 62
+                       }, { .type = 0 }, { .type = 0 }, {
+                               .type = LLDPMED_APPTYPE_VIDEOCONFERENCE,
+                               .unknown = 0,
+                               .tagged = 0,
+                               .vid = 1007,
+                               .priority = 1,
+                               .dscp = 49
+                       }, { .type = 0 }, { .type = 0 }
+               },
+               .p_med_location = {
+                       {
+                               .format = LLDPMED_LOCFORMAT_COORD,
+                               .data = "Not interpreted",
+                               .data_len = 15,
+                       }, { .format = 0 }, { .format = 0 },
+               },
+#endif         
+       }
+};
+
+#ifdef ENABLE_DOT1
+struct lldpd_vlan vlan47 = {
+       .v_name = "VLAN #47",
+       .v_vid = 47,
+};
+struct lldpd_vlan vlan49 = {
+       .v_name = "VLAN #49",
+       .v_vid = 49,
+};
+struct lldpd_vlan vlan1449 = {
+       .v_name = "VLAN #1449",
+       .v_vid = 1449,
+};
+struct lldpd_ppvid ppvid47 = {
+       .p_cap_status = LLDPD_PPVID_CAP_SUPPORTED | LLDPD_PPVID_CAP_ENABLED,
+       .p_ppvid = 47,
+};
+struct lldpd_ppvid ppvid118 = {
+       .p_cap_status = LLDPD_PPVID_CAP_SUPPORTED | LLDPD_PPVID_CAP_ENABLED,
+       .p_ppvid = 118,
+};
+struct lldpd_pi pi88cc = {
+       .p_pi = "\x88\xcc",
+       .p_pi_len = 2,
+};
+struct lldpd_pi pi888e01 = {
+       .p_pi = "\x88\x8e\e01",
+       .p_pi_len = 3,
+};
+#endif
+
+/* First port of second chassis */
+struct lldpd_port port2 = {
+       .p_chassis    = &chassis2,
+       .p_lastchange = 180,
+       .p_protocol   = LLDPD_MODE_LLDP,
+       .p_id_subtype = LLDP_PORTID_SUBTYPE_IFALIAS,
+       .p_id         = "Giga1/7",
+       .p_id_len     = 7,
+       .p_descr      = "Gigabit Ethernet 1/7",
+};
+
+void
+snmp_config()
+{
+       
+       starttime = test_starttime;
+       agent_scfg = &test_cfg;
+       TAILQ_INIT(&test_cfg.g_chassis);
+       TAILQ_INSERT_TAIL(&test_cfg.g_chassis, &chassis1, c_entries);
+       TAILQ_INSERT_TAIL(&test_cfg.g_chassis, &chassis2, c_entries);
+       TAILQ_INIT(&test_cfg.g_hardware);
+       TAILQ_INSERT_TAIL(&test_cfg.g_hardware, &hardware1, h_entries);
+       TAILQ_INSERT_TAIL(&test_cfg.g_hardware, &hardware2, h_entries);
+#ifdef ENABLE_DOT1
+       TAILQ_INIT(&hardware1.h_lport.p_vlans);
+       TAILQ_INSERT_TAIL(&hardware1.h_lport.p_vlans, &vlan47, v_entries);
+       TAILQ_INSERT_TAIL(&hardware1.h_lport.p_vlans, &vlan49, v_entries);
+       TAILQ_INSERT_TAIL(&hardware1.h_lport.p_vlans, &vlan1449, v_entries);
+       TAILQ_INIT(&hardware1.h_lport.p_ppvids);
+       TAILQ_INSERT_TAIL(&hardware1.h_lport.p_ppvids, &ppvid47, p_entries);
+       TAILQ_INSERT_TAIL(&hardware1.h_lport.p_ppvids, &ppvid118, p_entries);
+       TAILQ_INIT(&hardware1.h_lport.p_pids);
+       TAILQ_INSERT_TAIL(&hardware1.h_lport.p_pids, &pi88cc, p_entries);
+       TAILQ_INSERT_TAIL(&hardware1.h_lport.p_pids, &pi888e01, p_entries);
+       TAILQ_INIT(&hardware2.h_lport.p_vlans);
+       TAILQ_INIT(&hardware2.h_lport.p_ppvids);
+       TAILQ_INIT(&hardware2.h_lport.p_pids);
+       TAILQ_INIT(&port2.p_vlans);
+       TAILQ_INIT(&port2.p_ppvids);
+       TAILQ_INIT(&port2.p_pids);
+#endif
+       TAILQ_INIT(&hardware1.h_rports);
+       TAILQ_INSERT_TAIL(&hardware1.h_rports, &port2, p_entries);
+       TAILQ_INSERT_TAIL(&hardware1.h_rports, &hardware2.h_lport, p_entries);
+       TAILQ_INIT(&hardware2.h_rports);
+       TAILQ_INSERT_TAIL(&hardware2.h_rports, &hardware1.h_lport, p_entries);
+       
+}
+
+/* Convert OID to a string. Static buffer. */
+char*
+snmp_oidrepr(oid *name, size_t namelen)
+{
+       static char *buffer[4] = {NULL, NULL, NULL, NULL};
+       static int current = 0;
+       current = (current + 1)%4;
+       if (buffer[current]) free(buffer[current]); buffer[current] = NULL;
+
+       int i;
+       for (i = 0; i < namelen; i++) {
+               /* Not very efficient... */
+               char *newbuffer = NULL;
+               asprintf(&newbuffer, "%s.%u", buffer[current]?buffer[current]:"", name[i]);
+               if (buffer[current]) free(buffer[current]);
+               buffer[current] = newbuffer;
+       }
+       return buffer[current++];
+}
+
+struct tree_node {
+       oid    name[MAX_OID_LEN];
+       size_t namelen;
+       int    type;            /* ASN_* */
+       union {
+               unsigned long int integer;
+               struct {
+                       char *octet;
+                       size_t len;
+               } string;
+       } value;
+};
+
+static oid zeroDotZero[2] = {0, 0};
+struct tree_node snmp_tree[] = {
+       { {1, 1, 1, 0}, 4, ASN_INTEGER,   { .integer = 30 } }, /* lldpMessageTxInterval */
+       { {1, 1, 2, 0}, 4, ASN_INTEGER,   { .integer = 2 } },  /* lldpMessageTxHoldMultiplier */
+       { {1, 1, 3, 0}, 4, ASN_INTEGER,   { .integer = 1 } },  /* lldpReinitDelay */
+       { {1, 1, 4, 0}, 4, ASN_INTEGER,   { .integer = 1 } },  /* lldpTxDelay */
+       { {1, 1, 5, 0}, 4, ASN_INTEGER,   { .integer = 5 } },  /* lldpNotificationInterval */
+       { {1, 2, 1, 0}, 4, ASN_TIMETICKS, { .integer = 10000 } },/* lldpStatsRemTablesLastChangeTime */
+       { {1, 2, 2, 0}, 4, ASN_GAUGE,     { .integer = 12916 } }, /* lldpStatsRemTablesInserts */
+       { {1, 2, 3, 0}, 4, ASN_GAUGE,     { .integer = 12914 } }, /* lldpStatsRemTablesDeletes */
+       { {1, 2, 4, 0}, 4, ASN_GAUGE,     { .integer = 0 } }, /* lldpStatsRemTablesDrops */
+       { {1, 2, 5, 0}, 4, ASN_GAUGE,     { .integer = 22910 } }, /* lldpStatsRemTablesAgeouts */
+
+       { {1, 2, 6, 1, 2, 3}, 6, ASN_COUNTER, { .integer = 1352 } }, /* lldpStatsTxPortFramesTotal.3 */
+       { {1, 2, 6, 1, 2, 4}, 6, ASN_COUNTER, { .integer = 11352 } }, /* lldpStatsTxPortFramesTotal.4 */
+       { {1, 2, 7, 1, 2, 3}, 6, ASN_COUNTER, { .integer = 5 } }, /* lldpStatsRxPortFramesDiscardedTotal.3 */
+       { {1, 2, 7, 1, 2, 4}, 6, ASN_COUNTER, { .integer = 55 } }, /* lldpStatsRxPortFramesDiscardedTotal.4 */
+       { {1, 2, 7, 1, 3, 3}, 6, ASN_COUNTER, { .integer = 5 } }, /* lldpStatsRxPortFramesError.3 */
+       { {1, 2, 7, 1, 3, 4}, 6, ASN_COUNTER, { .integer = 55 } }, /* lldpStatsRxPortFramesError.4 */
+       { {1, 2, 7, 1, 4, 3}, 6, ASN_COUNTER, { .integer = 1458 } }, /* lldpStatsRxPortFramesTotal.3 */
+       { {1, 2, 7, 1, 4, 4}, 6, ASN_COUNTER, { .integer = 11458 } }, /* lldpStatsRxPortFramesTotal.4 */
+       { {1, 2, 7, 1, 5, 3}, 6, ASN_COUNTER, { .integer = 4 } }, /* lldpStatsRxPortTLVsDiscardedTotal.3 */
+       { {1, 2, 7, 1, 5, 4}, 6, ASN_COUNTER, { .integer = 14 } }, /* lldpStatsRxPortTLVsDiscardedTotal.4 */
+       { {1, 2, 7, 1, 6, 3}, 6, ASN_COUNTER, { .integer = 4 } }, /* lldpStatsRxPortTLVsUnrecognizedTotal.3 */
+       { {1, 2, 7, 1, 6, 4}, 6, ASN_COUNTER, { .integer = 14 } }, /* lldpStatsRxPortTLVsUnrecognizedTotal.4 */
+       { {1, 2, 7, 1, 7, 3}, 6, ASN_GAUGE,   { .integer = 1455 } }, /* lldpStatsRxPortAgeoutsTotal.3 */
+       { {1, 2, 7, 1, 7, 4}, 6, ASN_GAUGE,   { .integer = 21455 } }, /* lldpStatsRxPortAgeoutsTotal.4 */
+
+       { {1, 3, 1, 0}, 4, ASN_INTEGER,   { .integer = 4 } }, /* lldpLocChassisIdSubtype */
+       /* lldpLocChassisId */
+       { {1, 3, 2, 0}, 4, ASN_OCTET_STR, { .string = { .octet = "AAA012",
+                                                       .len = 6 } }},
+       /* lldpLocSysName */
+       { {1, 3, 3, 0}, 4, ASN_OCTET_STR, { .string = { .octet = "chassis1.example.com",
+                                                       .len = 20 } }},
+       /* lldpLocSysDesc */
+       { {1, 3, 4, 0}, 4, ASN_OCTET_STR, { .string = { .octet = "First chassis",
+                                                       .len = 13 } }},
+       /* lldpLocSysCapSupported */
+       { {1, 3, 5, 0}, 4, ASN_OCTET_STR, { .string = { .octet = "\x38",
+                                                       .len = 1 } }},
+       /* lldpLocSysCapEnabled */
+       { {1, 3, 6, 0}, 4, ASN_OCTET_STR, { .string = { .octet = "\x8",
+                                                       .len = 1 } }},
+
+       { {1, 3, 7, 1, 2, 3}, 6, ASN_INTEGER, { .integer = 3 } }, /* lldpLocPortIdSubtype.3 */
+       { {1, 3, 7, 1, 2, 4}, 6, ASN_INTEGER, { .integer = 5 } }, /* lldpLocPortIdSubtype.5 */
+       /* lldpLocPortId.3 */
+       { {1, 3, 7, 1, 3, 3}, 6, ASN_OCTET_STR, { .string = { .octet = "AAA012",
+                                                             .len = 6 } }},
+       /* lldpLocPortId.4 */
+       { {1, 3, 7, 1, 3, 4}, 6, ASN_OCTET_STR, { .string = { .octet = "eth4",
+                                                             .len = 4 } }},
+       /* lldpLocPortDesc.3 */
+       { {1, 3, 7, 1, 4, 3}, 6, ASN_OCTET_STR, { .string = { .octet = "eth2",
+                                                             .len = 4 } }},
+       /* lldpLocPortDesc.4 */
+       { {1, 3, 7, 1, 4, 4}, 6, ASN_OCTET_STR, { .string = { .octet = "Intel 1000 GE",
+                                                             .len = 13 } }},
+
+       { {1, 3, 8, 1, 3, 1, 4, 192, 0, 2, 15}, 11, ASN_INTEGER, { .integer = 5 } }, /* lldpLocManAddrLen */
+       { {1, 3, 8, 1, 4, 1, 4, 192, 0, 2, 15}, 11, ASN_INTEGER, { .integer = 2 } }, /* lldpLocManAddrIfSubtype */
+       { {1, 3, 8, 1, 5, 1, 4, 192, 0, 2, 15}, 11, ASN_INTEGER, { .integer = 3 } }, /* lldpLocManAddrIfId */
+       /* lldpLocManAddrOID */
+       { {1, 3, 8, 1, 6, 1, 4, 192, 0, 2, 15}, 11, ASN_OBJECT_ID,
+         { .string = { .octet = (char *)zeroDotZero,
+                       .len = sizeof(zeroDotZero) }} },
+
+       /* lldpRemChassisIdSubtype */
+       { {1, 4, 1, 1, 4, 0, 3, 1 }, 8, ASN_INTEGER, { .integer = 4 } }, 
+       { {1, 4, 1, 1, 4, 8000, 3, 4}, 8, ASN_INTEGER, { .integer = 7 } },
+       { {1, 4, 1, 1, 4, 10000, 4, 1}, 8, ASN_INTEGER, { .integer = 4 } },
+       /* lldpRemChassisId */
+       { {1, 4, 1, 1, 5, 0, 3, 1 }, 8, ASN_OCTET_STR, { .string = { .octet = "AAA012", .len = 6 }} },
+       { {1, 4, 1, 1, 5, 8000, 3, 4}, 8, ASN_OCTET_STR, { .string =
+                                                          { .octet = "chassis2",
+                                                            .len = 6 }} },
+       { {1, 4, 1, 1, 5, 10000, 4, 1}, 8, ASN_OCTET_STR, { .string = { .octet = "AAA012", .len = 6 }} },
+       /* lldpRemPortIdSubtype */
+       { {1, 4, 1, 1, 6, 0, 3, 1 }, 8, ASN_INTEGER, { .integer = 5 } }, 
+       { {1, 4, 1, 1, 6, 8000, 3, 4}, 8, ASN_INTEGER, { .integer = 1 } },
+       { {1, 4, 1, 1, 6, 10000, 4, 1}, 8, ASN_INTEGER, { .integer = 3 } },
+       /* lldpRemPortId */
+       { {1, 4, 1, 1, 7, 0, 3, 1 }, 8, ASN_OCTET_STR, { .string = { .octet = "eth4", .len = 4 }} },
+       { {1, 4, 1, 1, 7, 8000, 3, 4}, 8, ASN_OCTET_STR, { .string =
+                                                          { .octet = "Giga1/7", .len = 7 }} },
+       { {1, 4, 1, 1, 7, 10000, 4, 1}, 8, ASN_OCTET_STR, { .string = { .octet = "AAA012", .len = 6 }} },
+       /* lldpRemPortDesc */
+       { {1, 4, 1, 1, 8, 0, 3, 1 }, 8, ASN_OCTET_STR,
+         { .string = { .octet = "Intel 1000 GE", .len = 13 }} },
+       { {1, 4, 1, 1, 8, 8000, 3, 4}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "Gigabit Ethernet 1/7", .len = 20 }} },
+       { {1, 4, 1, 1, 8, 10000, 4, 1}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "eth2", .len = 4 }} },
+       /* lldpRemSysName */
+       { {1, 4, 1, 1, 9, 0, 3, 1 }, 8, ASN_OCTET_STR,
+         { .string = { .octet = "chassis1.example.com", .len = 20 }} },
+       { {1, 4, 1, 1, 9, 8000, 3, 4}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "chassis2.example.com", .len = 20 }} },
+       { {1, 4, 1, 1, 9, 10000, 4, 1}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "chassis1.example.com", .len = 20 }} },
+       /* lldpRemSysDesc */
+       { {1, 4, 1, 1, 10, 0, 3, 1 }, 8, ASN_OCTET_STR,
+         { .string = { .octet = "First chassis", .len = 13 }} },
+       { {1, 4, 1, 1, 10, 8000, 3, 4}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "Second chassis", .len = 14 }} },
+       { {1, 4, 1, 1, 10, 10000, 4, 1}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "First chassis", .len = 13 }} },
+       /* lldpRemSysCapSupported */
+       { {1, 4, 1, 1, 11, 0, 3, 1 }, 8, ASN_OCTET_STR,
+         { .string = { .octet = "\x38", .len = 1 }} },
+       { {1, 4, 1, 1, 11, 8000, 3, 4}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "\x8", .len = 1 }} },
+       { {1, 4, 1, 1, 11, 10000, 4, 1}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "\x38", .len = 1 }} },
+       /* lldpRemSysCapEnabled */
+       { {1, 4, 1, 1, 12, 0, 3, 1 }, 8, ASN_OCTET_STR,
+         { .string = { .octet = "\x8", .len = 1 }} },
+       { {1, 4, 1, 1, 12, 8000, 3, 4}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "\x8", .len = 1 }} },
+       { {1, 4, 1, 1, 12, 10000, 4, 1}, 8, ASN_OCTET_STR,
+         { .string = { .octet = "\x8", .len = 1 }} },
+
+       /* lldpRemManAddrIfSubtype */
+       { {1, 4, 2, 1, 3, 0, 3, 1, 1, 4, 192, 0, 2, 15 }, 14, ASN_INTEGER, { .integer = 2 } },
+       { {1, 4, 2, 1, 3, 8000, 3, 4, 1, 4, 192, 0, 2, 17 }, 14, ASN_INTEGER, { .integer = 2 } },
+       { {1, 4, 2, 1, 3, 10000, 4, 1, 1, 4, 192, 0, 2, 15 }, 14, ASN_INTEGER, { .integer = 2 } },
+       /* lldpRemManAddrIfId */
+       { {1, 4, 2, 1, 4, 0, 3, 1, 1, 4, 192, 0, 2, 15 }, 14, ASN_INTEGER, { .integer = 3 } },
+       { {1, 4, 2, 1, 4, 8000, 3, 4, 1, 4, 192, 0, 2, 17 }, 14, ASN_INTEGER, { .integer = 5 } },
+       { {1, 4, 2, 1, 4, 10000, 4, 1, 1, 4, 192, 0, 2, 15 }, 14, ASN_INTEGER, { .integer = 3 } },
+       /* lldpRemManAddrOID */
+       { {1, 4, 2, 1, 5, 0, 3, 1, 1, 4, 192, 0, 2, 15 }, 14, ASN_OBJECT_ID,
+         { .string = { .octet = (char *)zeroDotZero,
+                       .len = sizeof(zeroDotZero) }} },
+       { {1, 4, 2, 1, 5, 8000, 3, 4, 1, 4, 192, 0, 2, 17 }, 14, ASN_OBJECT_ID,
+         { .string = { .octet = (char *)zeroDotZero,
+                       .len = sizeof(zeroDotZero) }} },
+       { {1, 4, 2, 1, 5, 10000, 4, 1, 1, 4, 192, 0, 2, 15 }, 14, ASN_OBJECT_ID,
+         { .string = { .octet = (char *)zeroDotZero,
+                       .len = sizeof(zeroDotZero) }} },
+
+#ifdef ENABLE_DOT3
+       /* lldpXdot3LocPortAutoNegSupported */
+       { {1, 5, 4623, 1, 2, 1, 1, 1, 3 }, 9, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4623, 1, 2, 1, 1, 1, 4 }, 9, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3LocPortAutoNegEnabled */
+       { {1, 5, 4623, 1, 2, 1, 1, 2, 3 }, 9, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4623, 1, 2, 1, 1, 2, 4 }, 9, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3LocPortAutoNegAdvertisedCap */
+       { {1, 5, 4623, 1, 2, 1, 1, 3, 3 }, 9, ASN_OCTET_STR,
+         { .string = { .octet = "\x0c\x00", .len = 2 }} },
+       { {1, 5, 4623, 1, 2, 1, 1, 3, 4 }, 9, ASN_OCTET_STR,
+         { .string = { .octet = "\x04\x01", .len = 2 }} },
+       /* lldpXdot3LocPortOperMauType */
+       { {1, 5, 4623, 1, 2, 1, 1, 4, 3 }, 9, ASN_INTEGER, { .integer = 16 }},
+       { {1, 5, 4623, 1, 2, 1, 1, 4, 4 }, 9, ASN_INTEGER, { .integer = 30 }},
+
+       /* lldpXdot3LocPowerPortClass */
+       { {1, 5, 4623, 1, 2, 2, 1, 1, 3 }, 9, ASN_INTEGER, { .integer = 2 }},
+       /* lldpXdot3LocPowerMDISupported */
+       { {1, 5, 4623, 1, 2, 2, 1, 2, 3 }, 9, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3LocPowerMDIEnabled */
+       { {1, 5, 4623, 1, 2, 2, 1, 3, 3 }, 9, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3LocPowerPairControlable */
+       { {1, 5, 4623, 1, 2, 2, 1, 4, 3 }, 9, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3LocPowerPairs */
+       { {1, 5, 4623, 1, 2, 2, 1, 5, 3 }, 9, ASN_INTEGER, { .integer = 2 }},
+       /* lldpXdot3LocPowerClass */
+       { {1, 5, 4623, 1, 2, 2, 1, 6, 3 }, 9, ASN_INTEGER, { .integer = 3 }},
+       /* As per 802.3at-2009, not sure of the OID... */
+       /* lldpXdot3LocPowerType */
+       { {1, 5, 4623, 1, 2, 2, 1, 7, 3 }, 9, ASN_OCTET_STR,
+         { .string = { .octet = "\xC0", .len = 1 } }},
+       /* lldpXdot3LocPowerSource */
+       { {1, 5, 4623, 1, 2, 2, 1, 8, 3 }, 9, ASN_OCTET_STR,
+         { .string = { .octet = "\xC0", .len = 1 } }},
+       /* lldpXdot3LocPowerPriority */
+       { {1, 5, 4623, 1, 2, 2, 1, 9, 3 }, 9, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3LocPDRequestedPowerValue */
+       { {1, 5, 4623, 1, 2, 2, 1, 10, 3 }, 9, ASN_INTEGER, { .integer = 2000 }},
+       /* lldpXdot3LocPSEAllocatedPowerValue */
+       { {1, 5, 4623, 1, 2, 2, 1, 11, 3 }, 9, ASN_INTEGER, { .integer = 2500 }},
+
+       /* lldpXdot3LocLinkAggStatus */
+       { {1, 5, 4623, 1, 2, 3, 1, 1, 3 }, 9, ASN_OCTET_STR,
+         { .string = { .octet = "\x00", .len = 1 }} },
+       { {1, 5, 4623, 1, 2, 3, 1, 1, 4 }, 9, ASN_OCTET_STR,
+         { .string = { .octet = "\xC0", .len = 1 }} },
+       /* lldpXdot3LocLinkAggPortId */
+       { {1, 5, 4623, 1, 2, 3, 1, 2, 3 }, 9, ASN_INTEGER, { .integer = 0 }},
+       { {1, 5, 4623, 1, 2, 3, 1, 2, 4 }, 9, ASN_INTEGER, { .integer = 3 }},
+
+       /* lldpXdot3LocMaxFrameSize */
+       { {1, 5, 4623, 1, 2, 4, 1, 1, 3 }, 9, ASN_INTEGER, { .integer = 1600 }},
+       { {1, 5, 4623, 1, 2, 4, 1, 1, 4 }, 9, ASN_INTEGER, { .integer = 9000 }},
+
+       /* lldpXdot3RemPortAutoNegSupported */
+       { {1, 5, 4623, 1, 3, 1, 1, 1, 0, 3, 1 }, 11, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4623, 1, 3, 1, 1, 1, 8000, 3, 4 }, 11, ASN_INTEGER, { .integer = 2 }},
+       { {1, 5, 4623, 1, 3, 1, 1, 1, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3RemPortAutoNegEnabled */
+       { {1, 5, 4623, 1, 3, 1, 1, 2, 0, 3, 1 }, 11, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4623, 1, 3, 1, 1, 2, 8000, 3, 4 }, 11, ASN_INTEGER, { .integer = 2 }},
+       { {1, 5, 4623, 1, 3, 1, 1, 2, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3RemPortAutoNegAdvertisedCap */
+       { {1, 5, 4623, 1, 3, 1, 1, 3, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\x04\x01", .len = 2 }} },
+       { {1, 5, 4623, 1, 3, 1, 1, 3, 8000, 3, 4 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\x00\x00", .len = 2 }} },
+       { {1, 5, 4623, 1, 3, 1, 1, 3, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\x0c\x00", .len = 2 }} },
+       /* lldpXdot3RemPortOperMauType */
+       { {1, 5, 4623, 1, 3, 1, 1, 4, 0, 3, 1 }, 11, ASN_INTEGER, { .integer = 30 }},
+       { {1, 5, 4623, 1, 3, 1, 1, 4, 8000, 3, 4 }, 11, ASN_INTEGER, { .integer = 0 }},
+       { {1, 5, 4623, 1, 3, 1, 1, 4, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 16 }},
+
+       /* lldpXdot3RemPowerPortClass */
+       { {1, 5, 4623, 1, 3, 2, 1, 1, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 2 }},
+       /* lldpXdot3RemPowerMDISupported */
+       { {1, 5, 4623, 1, 3, 2, 1, 2, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3RemPowerMDIEnabled */
+       { {1, 5, 4623, 1, 3, 2, 1, 3, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3RemPowerPairControlable */
+       { {1, 5, 4623, 1, 3, 2, 1, 4, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3RemPowerPairs */
+       { {1, 5, 4623, 1, 3, 2, 1, 5, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 2 }},
+       /* lldpXdot3RemPowerClass */
+       { {1, 5, 4623, 1, 3, 2, 1, 6, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 3 }},
+       /* As per 802.3at-2009, not sure of the OID... */
+       /* lldpXdot3RemPowerType */
+       { {1, 5, 4623, 1, 3, 2, 1, 7, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\xC0", .len = 1 } }},
+       /* lldpXdot3RemPowerSource */
+       { {1, 5, 4623, 1, 3, 2, 1, 8, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\xC0", .len = 1 } }},
+       /* lldpXdot3RemPowerPriority */
+       { {1, 5, 4623, 1, 3, 2, 1, 9, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot3RemPDRequestedPowerValue */
+       { {1, 5, 4623, 1, 3, 2, 1, 10, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 2000 }},
+       /* lldpXdot3RemPSEAllocatedPowerValue */
+       { {1, 5, 4623, 1, 3, 2, 1, 11, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 2500 }},
+
+       /* lldpXdot3RemLinkAggStatus */
+       { {1, 5, 4623, 1, 3, 3, 1, 1, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\xC0", .len = 1 }} },
+       { {1, 5, 4623, 1, 3, 3, 1, 1, 8000, 3, 4 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\x00", .len = 1 }} },
+       { {1, 5, 4623, 1, 3, 3, 1, 1, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\x00", .len = 1 }} },
+       /* lldpXdot3RemLinkAggPortId */
+       { {1, 5, 4623, 1, 3, 3, 1, 2, 0, 3, 1 }, 11, ASN_INTEGER, { .integer = 3 }},
+       { {1, 5, 4623, 1, 3, 3, 1, 2, 8000, 3, 4 }, 11, ASN_INTEGER, { .integer = 0 }},
+       { {1, 5, 4623, 1, 3, 3, 1, 2, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 0 }},
+
+       /* lldpXdot3RemMaxFrameSize */
+       { {1, 5, 4623, 1, 3, 4, 1, 1, 0, 3, 1 }, 11, ASN_INTEGER, { .integer = 9000 }},
+       { {1, 5, 4623, 1, 3, 4, 1, 1, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 1600 }},
+#endif
+#ifdef ENABLE_LLDPMED
+       /* lldpXMedLocDeviceClass */
+       { {1, 5, 4795, 1, 1, 1, 0 }, 7, ASN_INTEGER, { .integer = 2 }},
+
+       /* lldpXMedLocMediaPolicyVlanID */
+       { {1, 5, 4795, 1, 2, 1, 1, 2, 3, 3 }, 10, ASN_INTEGER, { .integer = 475 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 2, 3, 7 }, 10, ASN_INTEGER, { .integer = 472 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 2, 4, 3 }, 10, ASN_INTEGER, { .integer = 475 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 2, 4, 6 }, 10, ASN_INTEGER, { .integer = 1007 }},
+       /* lldpXMedLocMediaPolicyPriority */
+       { {1, 5, 4795, 1, 2, 1, 1, 3, 3, 3 }, 10, ASN_INTEGER, { .integer = 3 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 3, 3, 7 }, 10, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 3, 4, 3 }, 10, ASN_INTEGER, { .integer = 3 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 3, 4, 6 }, 10, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXMedLocMediaPolicyDscp */
+       { {1, 5, 4795, 1, 2, 1, 1, 4, 3, 3 }, 10, ASN_INTEGER, { .integer = 62 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 4, 3, 7 }, 10, ASN_INTEGER, { .integer = 60 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 4, 4, 3 }, 10, ASN_INTEGER, { .integer = 62 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 4, 4, 6 }, 10, ASN_INTEGER, { .integer = 49 }},
+       /* lldpXMedLocMediaPolicyUnknown */
+       { {1, 5, 4795, 1, 2, 1, 1, 5, 3, 3 }, 10, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 5, 3, 7 }, 10, ASN_INTEGER, { .integer = 2 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 5, 4, 3 }, 10, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 5, 4, 6 }, 10, ASN_INTEGER, { .integer = 2 }},
+       /* lldpXMedLocMediaPolicyTagged */
+       { {1, 5, 4795, 1, 2, 1, 1, 6, 3, 3 }, 10, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 6, 3, 7 }, 10, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 6, 4, 3 }, 10, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 2, 1, 1, 6, 4, 6 }, 10, ASN_INTEGER, { .integer = 2 }},
+
+       /* lldpXMedLocHardwareRev */
+       { {1, 5, 4795, 1, 2, 2, 0 }, 7, ASN_OCTET_STR,
+         { .string = { .octet = "Hardware 1", .len = 10 }} },
+       /* lldpXMedLocSoftwareRev */
+       { {1, 5, 4795, 1, 2, 4, 0 }, 7, ASN_OCTET_STR,
+         { .string = { .octet = "Software 1", .len = 10 }} },
+       /* lldpXMedLocSerialNum */
+       { {1, 5, 4795, 1, 2, 5, 0 }, 7, ASN_OCTET_STR,
+         { .string = { .octet = "00-00-0000-AAAA", .len = 15 }} },
+       /* lldpXMedLocMfgName */
+       { {1, 5, 4795, 1, 2, 6, 0 }, 7, ASN_OCTET_STR,
+         { .string = { .octet = "Manufacturer 1", .len = 14 }} },
+       /* lldpXMedLocModelName */
+       { {1, 5, 4795, 1, 2, 7, 0 }, 7, ASN_OCTET_STR,
+         { .string = { .octet = "Model 1", .len = 7 }} },
+       /* lldpXMedLocAssetID */
+       { {1, 5, 4795, 1, 2, 8, 0 }, 7, ASN_OCTET_STR,
+         { .string = { .octet = "Asset 1", .len = 7 }} },
+
+       /* lldpXMedLocLocationInfo */
+       { {1, 5, 4795, 1, 2, 9, 1, 2, 3, 3}, 10, ASN_OCTET_STR,
+         { .string = { .octet = "\x15\x02FR\x06\x0dCommercial Rd\x13\x014", .len = 22 }} },
+       { {1, 5, 4795, 1, 2, 9, 1, 2, 4, 2}, 10, ASN_OCTET_STR,
+         { .string = { .octet = "Not interpreted", .len = 15 }} },
+
+       /* lldpXMedLocXPoEDeviceType */
+       { {1, 5, 4795, 1, 2, 10, 0 }, 7, ASN_INTEGER, { .integer = 3 }},
+       /* lldpXMedLocXPoEPDPowerReq */
+       { {1, 5, 4795, 1, 2, 13, 0 }, 7, ASN_GAUGE, { .integer = 100 }},
+       /* lldpXMedLocXPoEPDPowerSource */
+       { {1, 5, 4795, 1, 2, 14, 0 }, 7, ASN_INTEGER, { .integer = 3 }},
+       /* lldpXMedLocXPoEPDPowerPriority */
+       { {1, 5, 4795, 1, 2, 15, 0 }, 7, ASN_INTEGER, { .integer = 3 }},
+
+       /* lldpXMedRemCapSupported */
+       { {1, 5, 4795, 1, 3, 1, 1, 1, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\xFC", .len = 1 }} },
+       { {1, 5, 4795, 1, 3, 1, 1, 1, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\xFC", .len = 1 }}},
+       /* lldpXMedRemCapCurrent */
+       { {1, 5, 4795, 1, 3, 1, 1, 2, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\xFC", .len = 1 }} },
+       { {1, 5, 4795, 1, 3, 1, 1, 2, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "\xEC", .len = 1 }}},
+       /* lldpXMedRemDeviceClass */
+       { {1, 5, 4795, 1, 3, 1, 1, 3, 0, 3, 1 }, 11, ASN_INTEGER, { .integer = 2 }},
+       { {1, 5, 4795, 1, 3, 1, 1, 3, 10000, 4, 1 }, 11, ASN_INTEGER, { .integer = 2 }},
+
+       /* lldpXMedRemMediaPolicyVlanID */
+       { {1, 5, 4795, 1, 3, 2, 1, 2, 0, 3, 1, 3 }, 12, ASN_INTEGER, { .integer = 475 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 2, 0, 3, 1, 6 }, 12, ASN_INTEGER, { .integer = 1007 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 2, 10000, 4, 1, 3 }, 12, ASN_INTEGER, { .integer = 475 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 2, 10000, 4, 1, 7 }, 12, ASN_INTEGER, { .integer = 472 }},
+       /* lldpXMedRemMediaPolicyPriority */
+       { {1, 5, 4795, 1, 3, 2, 1, 3, 0, 3, 1, 3 }, 12, ASN_INTEGER, { .integer = 3 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 3, 0, 3, 1, 6 }, 12, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 3, 10000, 4, 1, 3 }, 12, ASN_INTEGER, { .integer = 3 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 3, 10000, 4, 1, 7 }, 12, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXMedLocMediaPolicyDscp */
+       { {1, 5, 4795, 1, 3, 2, 1, 4, 0, 3, 1, 3 }, 12, ASN_INTEGER, { .integer = 62 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 4, 0, 3, 1, 6 }, 12, ASN_INTEGER, { .integer = 49 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 4, 10000, 4, 1, 3 }, 12, ASN_INTEGER, { .integer = 62 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 4, 10000, 4, 1, 7 }, 12, ASN_INTEGER, { .integer = 60 }},
+       /* lldpXMedLocMediaPolicyUnknown */
+       { {1, 5, 4795, 1, 3, 2, 1, 5, 0, 3, 1, 3 }, 12, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 5, 0, 3, 1, 6 }, 12, ASN_INTEGER, { .integer = 2 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 5, 10000, 4, 1, 3 }, 12, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 5, 10000, 4, 1, 7 }, 12, ASN_INTEGER, { .integer = 2 }},
+       /* lldpXMedLocMediaPolicyTagged */
+       { {1, 5, 4795, 1, 3, 2, 1, 6, 0, 3, 1, 3 }, 12, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 6, 0, 3, 1, 6 }, 12, ASN_INTEGER, { .integer = 2 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 6, 10000, 4, 1, 3 }, 12, ASN_INTEGER, { .integer = 1 }},
+       { {1, 5, 4795, 1, 3, 2, 1, 6, 10000, 4, 1, 7 }, 12, ASN_INTEGER, { .integer = 1 }},
+
+       /* lldpXMedRemHardwareRev */
+       { {1, 5, 4795, 1, 3, 3, 1, 1, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Hardware 1", .len = 10 }} },
+       { {1, 5, 4795, 1, 3, 3, 1, 1, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Hardware 1", .len = 10 }} },
+       /* lldpXMedRemSoftwareRev */
+       { {1, 5, 4795, 1, 3, 3, 1, 3, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Software 1", .len = 10 }} },
+       { {1, 5, 4795, 1, 3, 3, 1, 3, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Software 1", .len = 10 }} },
+       /* lldpXMedRemSerialNum */
+       { {1, 5, 4795, 1, 3, 3, 1, 4, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "00-00-0000-AAAA", .len = 15 }} },
+       { {1, 5, 4795, 1, 3, 3, 1, 4, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "00-00-0000-AAAA", .len = 15 }} },
+       /* lldpXMedRemMfgName */
+       { {1, 5, 4795, 1, 3, 3, 1, 5, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Manufacturer 1", .len = 14 }} },
+       { {1, 5, 4795, 1, 3, 3, 1, 5, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Manufacturer 1", .len = 14 }} },
+       /* lldpXMedRemModelName */
+       { {1, 5, 4795, 1, 3, 3, 1, 6, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Model 1", .len = 7 }} },
+       { {1, 5, 4795, 1, 3, 3, 1, 6, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Model 1", .len = 7 }} },
+       /* lldpXMedRemAssetID */
+       { {1, 5, 4795, 1, 3, 3, 1, 7, 0, 3, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Asset 1", .len = 7 }} },
+       { {1, 5, 4795, 1, 3, 3, 1, 7, 10000, 4, 1 }, 11, ASN_OCTET_STR,
+         { .string = { .octet = "Asset 1", .len = 7 }} },
+
+       /* lldpXMedLocLocationInfo */
+       { {1, 5, 4795, 1, 3, 4, 1, 2, 0, 3, 1, 2}, 12, ASN_OCTET_STR,
+         { .string = { .octet = "Not interpreted", .len = 15 }} },
+       { {1, 5, 4795, 1, 3, 4, 1, 2, 10000, 4, 1, 3}, 12, ASN_OCTET_STR,
+         { .string = { .octet = "\x15\x02FR\x06\x0dCommercial Rd\x13\x014", .len = 22 }} },
+
+       /* lldpXMedRemXPoEDeviceType */
+       { {1, 5, 4795, 1, 3, 5, 1, 1, 0, 3, 1}, 11, ASN_INTEGER, { .integer = 4 }},
+       { {1, 5, 4795, 1, 3, 5, 1, 1, 10000, 4, 1}, 11, ASN_INTEGER, { .integer = 3 }},
+
+       /* lldpXMedRemXPoEPDPowerReq */
+       { {1, 5, 4795, 1, 3, 7, 1, 1, 10000, 4, 1}, 11, ASN_GAUGE, { .integer = 100 }},
+       /* lldpXMedRemXPoEPDPowerSource */
+       { {1, 5, 4795, 1, 3, 7, 1, 2, 10000, 4, 1}, 11, ASN_INTEGER, { .integer = 3 }},
+       /* lldpXMedRemXPoEPDPowerPriority */
+       { {1, 5, 4795, 1, 3, 7, 1, 3, 10000, 4, 1}, 11, ASN_INTEGER, { .integer = 3 }},
+
+#endif
+#ifdef ENABLE_DOT1
+       /* lldpXdot1LocPortVlanId */
+       { { 1, 5, 32962, 1, 2, 1, 1, 1, 3}, 9, ASN_INTEGER, { .integer = 47 }},
+       { { 1, 5, 32962, 1, 2, 1, 1, 1, 4}, 9, ASN_INTEGER, { .integer = 0 }},
+       /* lldpXdot1LocProtoVlanSupported */
+       { { 1, 5, 32962, 1, 2, 2, 1, 2, 3, 47}, 10, ASN_INTEGER, { .integer = 1 }},
+       { { 1, 5, 32962, 1, 2, 2, 1, 2, 3, 118}, 10, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot1LocProtoVlanEnabled */
+       { { 1, 5, 32962, 1, 2, 2, 1, 3, 3, 47}, 10, ASN_INTEGER, { .integer = 1 }},
+       { { 1, 5, 32962, 1, 2, 2, 1, 3, 3, 118}, 10, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot1LocVlanName */
+       { { 1, 5, 32962, 1, 2, 3, 1, 2, 3, 47}, 10, ASN_OCTET_STR,
+         { .string = { .octet = "VLAN #47", .len = 8 }} },
+       { { 1, 5, 32962, 1, 2, 3, 1, 2, 3, 49}, 10, ASN_OCTET_STR,
+         { .string = { .octet = "VLAN #49", .len = 8 }} },
+       { { 1, 5, 32962, 1, 2, 3, 1, 2, 3, 1449}, 10, ASN_OCTET_STR,
+         { .string = { .octet = "VLAN #1449", .len = 10 }} },
+       /* lldpXdot1LocProtocolId */
+       { { 1, 5, 32962, 1, 2, 4, 1, 2, 3, 13175}, 10, ASN_OCTET_STR,
+         { .string = { .octet = "\x88\xcc", .len = 2 } }},
+       { { 1, 5, 32962, 1, 2, 4, 1, 2, 3, 29020}, 10, ASN_OCTET_STR,
+         { .string = { .octet = "\x88\x8e\e01", .len = 3 } }},
+
+       /* lldpXdot1RemPortVlanId */
+       { { 1, 5, 32962, 1, 3, 1, 1, 1, 0, 3, 1}, 11, ASN_INTEGER, { .integer = 0 }},
+       { { 1, 5, 32962, 1, 3, 1, 1, 1, 8000, 3, 4}, 11, ASN_INTEGER, { .integer = 0 }},
+       { { 1, 5, 32962, 1, 3, 1, 1, 1, 10000, 4, 1}, 11, ASN_INTEGER, { .integer = 47 }},
+       /* lldpXdot1RemProtoVlanSupported */
+       { { 1, 5, 32962, 1, 3, 2, 1, 2, 10000, 4, 1, 47}, 12, ASN_INTEGER, { .integer = 1 }},
+       { { 1, 5, 32962, 1, 3, 2, 1, 2, 10000, 4, 1, 118}, 12, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot1RemProtoVlanEnabled */
+       { { 1, 5, 32962, 1, 3, 2, 1, 3, 10000, 4, 1, 47}, 12, ASN_INTEGER, { .integer = 1 }},
+       { { 1, 5, 32962, 1, 3, 2, 1, 3, 10000, 4, 1, 118}, 12, ASN_INTEGER, { .integer = 1 }},
+       /* lldpXdot1RemVlanName */
+       { { 1, 5, 32962, 1, 3, 3, 1, 2, 10000, 4, 1, 47}, 12, ASN_OCTET_STR,
+         { .string = { .octet = "VLAN #47", .len = 8 }} },
+       { { 1, 5, 32962, 1, 3, 3, 1, 2, 10000, 4, 1, 49}, 12, ASN_OCTET_STR,
+         { .string = { .octet = "VLAN #49", .len = 8 }} },
+       { { 1, 5, 32962, 1, 3, 3, 1, 2, 10000, 4, 1, 1449}, 12, ASN_OCTET_STR,
+         { .string = { .octet = "VLAN #1449", .len = 10 }} },
+       /* lldpXdot1RemProtocolId */
+       { { 1, 5, 32962, 1, 3, 4, 1, 2, 10000, 4, 1, 13175}, 12, ASN_OCTET_STR,
+         { .string = { .octet = "\x88\xcc", .len = 2 } }},
+       { { 1, 5, 32962, 1, 3, 4, 1, 2, 10000, 4, 1, 29020}, 12, ASN_OCTET_STR,
+         { .string = { .octet = "\x88\x8e\e01", .len = 3 } }},
+#endif
+};
+
+char*
+tohex(char *str, size_t len)
+{
+       static char *hex[] = { NULL, NULL };
+       static int which = 0;
+       if (hex[which]) free(hex[which]); hex[which] = NULL;
+       hex[which] = malloc(len * 3 + 1);
+       fail_unless(hex[which] != NULL, "Not enough memory?");
+       for (int i = 0; i < len; i++)
+               snprintf(hex[which] + 3*i, 4, "%02X ", (unsigned char)str[i]);
+       which = 1 - which;
+       return hex[1 - which];
+}
+
+int
+snmp_is_prefix_of(struct variable8 *vp, struct tree_node *n, char *repr)
+{
+       if (n->namelen < vp->namelen) return 0;
+       if (memcmp(n->name,
+                  vp->name,
+                  vp->namelen * sizeof(oid)))
+               return 0;
+       fail_unless(n->type == vp->type, "Inappropriate type for OID %s", repr);
+       return 1;
+}
+
+void
+snmp_merge(struct variable8 *v1, struct tree_node *n, struct variable *vp,
+          oid *target, size_t *targetlen)
+{
+       vp->magic = v1->magic;
+       vp->type = v1->type;
+       vp->acl = v1->acl;
+       vp->findVar = v1->findVar;
+       vp->namelen = v1->namelen + 
+               sizeof(lldp_oid)/sizeof(oid);
+       memcpy(vp->name, lldp_oid, sizeof(lldp_oid));
+       memcpy(vp->name + sizeof(lldp_oid)/sizeof(oid),
+              v1->name,
+              v1->namelen*sizeof(oid));
+       *targetlen = n->namelen +
+               sizeof(lldp_oid)/sizeof(oid);
+       memcpy(target, lldp_oid, sizeof(lldp_oid));
+       memcpy(target + sizeof(lldp_oid)/sizeof(oid),
+              n->name,
+              n->namelen * sizeof(oid));
+}
+
+void
+snmp_compare(struct tree_node *n,
+            u_char *result, size_t varlen,
+            oid *target, size_t targetlen, char *repr)
+{
+       fail_unless((targetlen == sizeof(lldp_oid)/sizeof(oid) + n->namelen) &&
+                   !memcmp(target, lldp_oid, sizeof(lldp_oid)) &&
+                   !memcmp(target + sizeof(lldp_oid)/sizeof(oid),
+                           n->name,
+                           n->namelen * sizeof(oid)),
+                   "Bad OID returned when querying %s: got %s", repr,
+                   snmp_oidrepr(target, targetlen));
+       switch (n->type) {
+       case ASN_INTEGER:
+       case ASN_TIMETICKS:
+       case ASN_GAUGE:
+       case ASN_COUNTER:
+               fail_unless(varlen == sizeof(unsigned long int),
+                           "Inappropriate length for integer type for OID %s",
+                           repr);
+               fail_unless(n->value.integer ==
+                           *(unsigned long int *)result,
+                           "For OID %s, expected value %u but got %u instead",
+                           repr,
+                           n->value.integer,
+                           *(unsigned long int *)result);
+               break;
+       default:
+               fail_unless(((n->value.string.len == varlen) &&
+                            !memcmp(n->value.string.octet,
+                                   result, varlen)),
+                           "OID %s: wanted %s, got %s",
+                           repr,
+                           tohex(n->value.string.octet, n->value.string.len),
+                           tohex((char *)result, varlen));
+       }
+}
+
+START_TEST (test_variable_order)
+{
+       int i;
+       for (i = 0; i < agent_lldp_vars_size() - 1; i++) {
+               fail_unless(snmp_oid_compare(agent_lldp_vars[i].name,
+                                            agent_lldp_vars[i].namelen,
+                                            agent_lldp_vars[i+1].name,
+                                            agent_lldp_vars[i+1].namelen) < 0,
+                           "Registered OID are out of orders (see %s and next one)",
+                           snmp_oidrepr(agent_lldp_vars[i].name,
+                                        agent_lldp_vars[i].namelen));
+       }
+}
+END_TEST
+
+START_TEST (test_get)
+{
+       int j;
+       for (j = 0;
+            j < sizeof(snmp_tree)/sizeof(struct tree_node);
+            j++) {
+               int             i;
+               int             found = 0;
+               struct variable vp;
+               oid             target[MAX_OID_LEN];
+               size_t          targetlen;
+               size_t          varlen;
+               u_char         *result;
+               WriteMethod    *wmethod;
+               char           *repr = snmp_oidrepr(snmp_tree[j].name,
+                                                   snmp_tree[j].namelen);
+
+               for (i = 0; i < agent_lldp_vars_size(); i++) {
+                       /* Search for the appropriate prefix. */
+                       if (!snmp_is_prefix_of(&agent_lldp_vars[i], &snmp_tree[j],
+                                              repr)) continue;
+
+                       /* We have our prefix. Fill out the vp struct
+                          correctly. We need to complete OID with
+                          LLDP prefix. */
+                       snmp_merge(&agent_lldp_vars[i], &snmp_tree[j], &vp, target, &targetlen);
+
+                       /* Invoke the function */
+                       result = vp.findVar(&vp, target, &targetlen, 1, &varlen, &wmethod);
+                       
+                       /* Check the result */
+                       fail_unless(result != NULL,
+                                   "No result when querying %s", repr);
+                       snmp_compare(&snmp_tree[j], result, varlen, target, targetlen, repr);
+
+                       found = 1;
+                       break;
+               }
+               if (!found)
+                       fail("OID %s not found", repr);
+       }
+}
+END_TEST
+
+START_TEST (test_getnext)
+{
+       int j;
+       int end = sizeof(snmp_tree)/sizeof(struct tree_node);
+       for (j = 0;
+            j < end;
+            j++) {
+               int             i;
+               struct variable vp;
+               oid             target[MAX_OID_LEN];
+               size_t          targetlen;
+               size_t          varlen;
+               u_char         *result = NULL;
+               WriteMethod    *wmethod;
+               char           *repr = snmp_oidrepr(snmp_tree[j].name,
+                                                   snmp_tree[j].namelen);
+               for (i = 0; i < agent_lldp_vars_size(); i++) {
+                       snmp_merge(&agent_lldp_vars[i], &snmp_tree[j], &vp, target, &targetlen);
+                       result = vp.findVar(&vp, target, &targetlen, 0, &varlen, &wmethod);
+                       if (result) /* Check next! */
+                               break;
+               }
+               if (!result) {
+                       fail_unless(j == end - 1,
+                                   "No next result found for %s", repr);
+                       return;
+               }
+               fail_unless(j < end - 1,
+                           "More results after %s", repr);
+
+               /* For unknown reasons, snmp_compare can be executed
+                  even when the above test fails... */
+               if (j < end - 1)
+                       snmp_compare(&snmp_tree[j+1], result, varlen, target, targetlen, repr);
+               
+       }       
+}
+END_TEST
+
+Suite *
+snmp_suite(void)
+{
+       Suite *s = suite_create("SNMP");
+
+       TCase *tc_snmp = tcase_create("SNMP");
+       tcase_add_checked_fixture(tc_snmp, snmp_config, NULL);
+       tcase_add_test(tc_snmp, test_variable_order);
+       tcase_add_test(tc_snmp, test_get);
+       tcase_add_test(tc_snmp, test_getnext);
+       suite_add_tcase(s, tc_snmp);
+
+       return s;
+}
+
+int
+main()
+{
+       int number_failed;
+       Suite *s = snmp_suite();
+       SRunner *sr = srunner_create(s);
+       srunner_run_all(sr, CK_ENV);
+       number_failed = srunner_ntests_failed(sr);
+       srunner_free(sr);
+       return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}