From 6845d2a1aa64cd256a80a6b085919b655bb6c3fe Mon Sep 17 00:00:00 2001 From: adamdunkels Date: Tue, 13 Nov 2007 20:39:29 +0000 Subject: [PATCH] Updated tree to use expected transmissions (etx) as routing metric --- core/net/rime/neighbor.c | 114 +++++++++++++++-------- core/net/rime/neighbor.h | 22 +++-- core/net/rime/tree.c | 196 ++++++++++++++++++++++++--------------- core/net/rime/tree.h | 9 +- 4 files changed, 216 insertions(+), 125 deletions(-) diff --git a/core/net/rime/neighbor.c b/core/net/rime/neighbor.c index e57b25d47..4281843a7 100644 --- a/core/net/rime/neighbor.c +++ b/core/net/rime/neighbor.c @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: neighbor.c,v 1.9 2007/05/22 21:15:17 adamdunkels Exp $ + * $Id: neighbor.c,v 1.10 2007/11/13 20:39:29 adamdunkels Exp $ */ /** @@ -52,7 +52,7 @@ #define MAX_NEIGHBORS 5 -#define HOPCOUNT_MAX 32 +#define RTMETRIC_MAX 64 static struct neighbor neighbors[MAX_NEIGHBORS]; @@ -64,13 +64,15 @@ static void periodic(void *ptr) { int i; + + /* Go through all neighbors and remove old ones. */ for(i = 0; i < MAX_NEIGHBORS; ++i) { if(!rimeaddr_cmp(&neighbors[i].addr, &rimeaddr_null) && neighbors[i].time < max_time) { neighbors[i].time++; if(neighbors[i].time == max_time) { - neighbors[i].hopcount = HOPCOUNT_MAX; + neighbors[i].rtmetric = RTMETRIC_MAX; /* printf("%d: removing old neighbor %d\n", node_id, neighbors[i].nodeid);*/ rimeaddr_copy(&neighbors[i].addr, &rimeaddr_null); } @@ -106,26 +108,57 @@ neighbor_find(rimeaddr_t *addr) } /*---------------------------------------------------------------------------*/ void -neighbor_update(struct neighbor *n, u8_t hopcount, u16_t signal) +neighbor_update(struct neighbor *n, u8_t rtmetric, u8_t etx) { if(n != NULL) { - n->hopcount = hopcount; - n->signal = signal; + n->rtmetric = rtmetric; n->time = 0; + neighbor_update_etx(n, etx); } } /*---------------------------------------------------------------------------*/ void -neighbor_add(rimeaddr_t *addr, u8_t nhopcount, u16_t nsignal) +neighbor_timedout_etx(struct neighbor *n, u8_t etx) +{ + if(n != NULL) { + n->etxs[n->etxptr] = etx; + n->etxptr = (n->etxptr + 1) % NEIGHBOR_NUM_ETXS; + } +} +/*---------------------------------------------------------------------------*/ +void +neighbor_update_etx(struct neighbor *n, u8_t etx) +{ + if(n != NULL) { + n->etxs[n->etxptr] = etx; + n->etxptr = (n->etxptr + 1) % NEIGHBOR_NUM_ETXS; + n->time = 0; + } +} +/*---------------------------------------------------------------------------*/ +uint8_t +neighbor_etx(struct neighbor *n) +{ + int i, etx; + + etx = 0; + for(i = 0; i < NEIGHBOR_NUM_ETXS; ++i) { + etx += n->etxs[i]; + } + return NEIGHBOR_ETX_SCALE * etx / NEIGHBOR_NUM_ETXS; +} +/*---------------------------------------------------------------------------*/ +void +neighbor_add(rimeaddr_t *addr, u8_t nrtmetric, u8_t netx) { int i, n; - u8_t hopcount; - u16_t signal; + u8_t rtmetric; + u8_t etx; /* Find the first unused entry or the used entry with the highest - hopcount and lowest signal strength. */ - hopcount = 0; - signal = USHRT_MAX; + rtmetric and highest etx. */ + rtmetric = 0; + etx = 0; n = 0; for(i = 0; i < MAX_NEIGHBORS; ++i) { @@ -135,30 +168,33 @@ neighbor_add(rimeaddr_t *addr, u8_t nhopcount, u16_t nsignal) break; } if(!rimeaddr_cmp(&neighbors[i].addr, &rimeaddr_null)) { - if(neighbors[i].hopcount > hopcount) { - hopcount = neighbors[i].hopcount; - signal = neighbors[i].signal; + if(neighbors[i].rtmetric > rtmetric) { + rtmetric = neighbors[i].rtmetric; + etx = neighbor_etx(&neighbors[i]); n = i; - } else if(neighbors[i].hopcount == hopcount) { - if(neighbors[i].signal < signal) { - hopcount = neighbors[i].hopcount; - signal = neighbors[i].signal; + } else if(neighbors[i].rtmetric == rtmetric) { + if(neighbor_etx(&neighbors[i]) > etx) { + rtmetric = neighbors[i].rtmetric; + etx = neighbor_etx(&neighbors[i]); n = i; - /* printf("%d: found worst neighbor %d with hopcount %d, signal %d\n", - node_id, neighbors[n].nodeid, hopcount, signal);*/ + /* printf("%d: found worst neighbor %d with rtmetric %d, signal %d\n", + node_id, neighbors[n].nodeid, rtmetric, signal);*/ } } } } - /* printf("%d: adding neighbor %d with hopcount %d, signal %d at %d\n", - node_id, neighbors[n].nodeid, hopcount, signal, n);*/ + /* printf("%d: adding neighbor %d with rtmetric %d, signal %d at %d\n", + node_id, neighbors[n].nodeid, rtmetric, signal, n);*/ neighbors[n].time = 0; rimeaddr_copy(&neighbors[i].addr, addr); - neighbors[n].hopcount = nhopcount; - neighbors[n].signal = nsignal; + neighbors[n].rtmetric = nrtmetric; + for(i = 0; i < NEIGHBOR_NUM_ETXS; ++i) { + neighbors[n].etxs[i] = netx; + } + neighbors[n].etxptr = 0; } /*---------------------------------------------------------------------------*/ void @@ -170,7 +206,7 @@ neighbor_remove(rimeaddr_t *addr) if(rimeaddr_cmp(&neighbors[i].addr, addr)) { printf("%d: removing %d @ %d\n", rimeaddr_node_addr.u16[0], addr->u16[0], i); rimeaddr_copy(&neighbors[i].addr, &rimeaddr_null); - neighbors[i].hopcount = HOPCOUNT_MAX; + neighbors[i].rtmetric = RTMETRIC_MAX; return; } } @@ -181,37 +217,37 @@ neighbor_best(void) { int i, found; int lowest, best; - u8_t hopcount; - u16_t signal; + u8_t rtmetric; + u8_t etx; - hopcount = HOPCOUNT_MAX; + rtmetric = RTMETRIC_MAX; lowest = 0; found = 0; /* printf("%d: ", node_id);*/ - /* Find the lowest hopcount. */ + /* Find the lowest rtmetric. */ for(i = 0; i < MAX_NEIGHBORS; ++i) { - /* printf("%d:%d ", neighbors[i].nodeid, neighbors[i].hopcount);*/ + /* printf("%d:%d ", neighbors[i].nodeid, neighbors[i].rtmetric);*/ if(!rimeaddr_cmp(&neighbors[i].addr, &rimeaddr_null) && - hopcount > neighbors[i].hopcount) { - hopcount = neighbors[i].hopcount; + rtmetric > neighbors[i].rtmetric) { + rtmetric = neighbors[i].rtmetric; lowest = i; found = 1; } } /* printf("\n");*/ - /* Find the neighbor with highest signal strength of the ones that - have the lowest hopcount. */ + /* Find the neighbor with lowest etx of the ones that + have the lowest rtmetric. */ if(found) { - signal = 0; + etx = 0; best = lowest; for(i = 0; i < MAX_NEIGHBORS; ++i) { if(!rimeaddr_cmp(&neighbors[i].addr, &rimeaddr_null) && - hopcount == neighbors[i].hopcount && - neighbors[i].signal > signal) { - signal = neighbors[i].signal; + rtmetric == neighbors[i].rtmetric && + neighbor_etx(&neighbors[i]) < etx) { + etx = neighbor_etx(&neighbors[i]); best = i; } } diff --git a/core/net/rime/neighbor.h b/core/net/rime/neighbor.h index 8dc90584e..bbf6c2ea5 100644 --- a/core/net/rime/neighbor.h +++ b/core/net/rime/neighbor.h @@ -38,7 +38,7 @@ * * This file is part of the Contiki operating system. * - * $Id: neighbor.h,v 1.5 2007/03/31 18:31:28 adamdunkels Exp $ + * $Id: neighbor.h,v 1.6 2007/11/13 20:39:29 adamdunkels Exp $ */ /** @@ -53,25 +53,31 @@ #include "net/rime/rimeaddr.h" +#define NEIGHBOR_ETX_SCALE 16 +#define NEIGHBOR_NUM_ETXS 8 + struct neighbor { - u16_t signal; - u16_t time; + uint16_t time; rimeaddr_t addr; - u8_t hopcount; + uint8_t rtmetric; + uint8_t etxptr; + uint8_t etxs[NEIGHBOR_NUM_ETXS]; }; void neighbor_init(void); /*void neighbor_periodic(int max_time);*/ -void neighbor_add(rimeaddr_t *addr, u8_t hopcount, u16_t signal); -void neighbor_update(struct neighbor *n, u8_t hopcount, u16_t signal); - +void neighbor_add(rimeaddr_t *addr, u8_t rtmetric, u8_t etx); +void neighbor_update(struct neighbor *n, u8_t rtmetric, u8_t etx); +void neighbor_update_etx(struct neighbor *n, u8_t etx); +void neighbor_timedout_etx(struct neighbor *n, u8_t etx); void neighbor_remove(rimeaddr_t *addr); - struct neighbor *neighbor_find(rimeaddr_t *addr); struct neighbor *neighbor_best(void); void neighbor_set_lifetime(int seconds); +uint8_t neighbor_etx(struct neighbor *n); + #endif /* __NEIGHBOR_H__ */ /** @} */ diff --git a/core/net/rime/tree.c b/core/net/rime/tree.c index eccb92531..b053b150a 100644 --- a/core/net/rime/tree.c +++ b/core/net/rime/tree.c @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: tree.c,v 1.12 2007/05/22 20:57:44 adamdunkels Exp $ + * $Id: tree.c,v 1.13 2007/11/13 20:39:29 adamdunkels Exp $ */ /** @@ -60,21 +60,23 @@ #include #include +/* struct adv_msg { - u8_t hopcount; + u8_t rtmetric; u8_t pad; }; +*/ struct hdr { rimeaddr_t originator; u8_t originator_seqno; - u8_t hopcount; + u8_t rtmetric; u8_t hoplim; u8_t rexmits; }; #define SINK 0 -#define HOPCOUNT_MAX TREE_MAX_DEPTH +#define RTMETRIC_MAX TREE_MAX_DEPTH #define MAX_HOPLIM 10 @@ -89,6 +91,58 @@ struct hdr { #define PRINTF(...) #endif +/*---------------------------------------------------------------------------*/ +static void +update_rtmetric(struct tree_conn *tc) +{ + struct neighbor *n; + + /* We should only update the rtmetric if we are not the sink. */ + if(tc->local_rtmetric != SINK) { + + /* Find the neighbor with the lowest rtmetric. */ + n = neighbor_best(); + + /* If n is NULL, we have no best neighbor. */ + if(n == NULL) { + + /* If we have don't have any neighbors, we set our rtmetric to + the maximum value to indicate that we do not have a route. */ + + if(tc->local_rtmetric != RTMETRIC_MAX) { + PRINTF("%d.%d: didn't find a best neighbor, setting rtmetric to max\n", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); + } + tc->local_rtmetric = RTMETRIC_MAX; + } else { + + /* We set our rtmetric to the rtmetric of our best neighbor plus + the expected transmissions to reach that neighbor. */ + if(n->rtmetric + neighbor_etx(n) != tc->local_rtmetric) { + tc->local_rtmetric = n->rtmetric + neighbor_etx(n); + nbh_start(&tc->nbh_conn, tc->local_rtmetric); + /* send_adv(tc, MIN_INTERVAL);*/ + PRINTF("%d.%d: new rtmetric %d\n", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], + tc->local_rtmetric); + } + } + } + + /* DEBUG_PRINTF("%d: new rtmetric %d\n", node_id, rtmetric);*/ +#if NETSIM + { + char buf[8]; + if(tc->local_rtmetric == RTMETRIC_MAX) { + strcpy(buf, " "); + } else { + snprintf(buf, sizeof(buf), "%d", tc->local_rtmetric); + } + ether_set_text(buf); + } +#endif +} +#if 0 /*---------------------------------------------------------------------------*/ static void send_adv(struct tree_conn *tc, clock_time_t interval) @@ -98,49 +152,11 @@ send_adv(struct tree_conn *tc, clock_time_t interval) rimebuf_clear(); rimebuf_set_datalen(sizeof(struct adv_msg)); hdr = rimebuf_dataptr(); - hdr->hopcount = tc->hops_from_sink; + hdr->rtmetric = tc->local_rtmetric; ipolite_send(&tc->ipolite_conn, interval, rimebuf_totlen()); } /*---------------------------------------------------------------------------*/ static void -update_hopcount(struct tree_conn *tc) -{ - struct neighbor *n; - - if(tc->hops_from_sink != SINK) { - n = neighbor_best(); - if(n == NULL) { - if(tc->hops_from_sink != HOPCOUNT_MAX) { - PRINTF("%d.%d: didn't find a best neighbor, setting hopcount to max\n", - rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); - } - tc->hops_from_sink = HOPCOUNT_MAX; - } else { - if(n->hopcount + 1 != tc->hops_from_sink) { - tc->hops_from_sink = n->hopcount + 1; - send_adv(tc, MIN_INTERVAL); - PRINTF("%d.%d: new hopcount %d\n", - rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], - tc->hops_from_sink); - } - } - } - - /* DEBUG_PRINTF("%d: new hopcount %d\n", node_id, hopcount);*/ -#if NETSIM - { - char buf[8]; - if(tc->hops_from_sink == HOPCOUNT_MAX) { - strcpy(buf, " "); - } else { - snprintf(buf, sizeof(buf), "%d", tc->hops_from_sink); - } - ether_set_text(buf); - } -#endif -} -/*---------------------------------------------------------------------------*/ -static void adv_packet_received(struct ipolite_conn *c, rimeaddr_t *from) { struct tree_conn *tc = (struct tree_conn *) @@ -148,23 +164,23 @@ adv_packet_received(struct ipolite_conn *c, rimeaddr_t *from) struct adv_msg *msg = rimebuf_dataptr(); struct neighbor *n; - /* PRINTF("%d.%d: adv_packet_received from %d.%d with hopcount %d\n", + /* PRINTF("%d.%d: adv_packet_received from %d.%d with rtmetric %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], - from->u8[0], from->u8[1], msg->hopcount);*/ + from->u8[0], from->u8[1], msg->rtmetric);*/ n = neighbor_find(from); if(n == NULL) { - neighbor_add(from, msg->hopcount, radio_sensor.value(1)); + neighbor_add(from, msg->rtmetric, radio_sensor.value(1)); } else { - neighbor_update(n, msg->hopcount, radio_sensor.value(1)); + neighbor_update(n, msg->rtmetric, radio_sensor.value(1)); PRINTF("%d.%d: updating neighbor %d.%d, radio sensor %d, hops %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], n->addr.u8[0], n->addr.u8[1], - radio_sensor.value(1), msg->hopcount); + radio_sensor.value(1), msg->rtmetric); } - update_hopcount(tc); + update_rtmetric(tc); } /*---------------------------------------------------------------------------*/ @@ -192,6 +208,7 @@ send_timer(void *ptr) send_adv(tc, MAX_INTERVAL / 2); ctimer_set(&tc->t, MAX_INTERVAL, send_timer, tc); } +#endif /* 0 */ /*---------------------------------------------------------------------------*/ static int node_packet_received(struct ruc_conn *c, rimeaddr_t *from, u8_t seqno) @@ -201,28 +218,28 @@ node_packet_received(struct ruc_conn *c, rimeaddr_t *from, u8_t seqno) struct hdr *hdr = rimebuf_dataptr(); struct neighbor *n; - if(tc->hops_from_sink == SINK) { + if(tc->local_rtmetric == SINK) { rimebuf_hdrreduce(sizeof(struct hdr)); - PRINTF("%d.%d: sink received packet from %d.%d via %d.%d with hopcount %d\n", + PRINTF("%d.%d: sink received packet from %d.%d via %d.%d with rtmetric %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->originator.u8[0], hdr->originator.u8[1], - from->u8[0], from->u8[1], hdr->hopcount); + from->u8[0], from->u8[1], hdr->rtmetric); if(tc->cb->recv != NULL) { tc->cb->recv(&hdr->originator, hdr->originator_seqno, - hdr->hopcount); + hdr->rtmetric); } return 1; - } else if(hdr->hoplim > 1 && tc->hops_from_sink != HOPCOUNT_MAX) { + } else if(hdr->hoplim > 1 && tc->local_rtmetric != RTMETRIC_MAX) { hdr->hoplim--; - PRINTF("%d.%d: packet received from %d.%d via %d.%d with hopcount %d, best neighbor %p, forwarding %d\n", + PRINTF("%d.%d: packet received from %d.%d via %d.%d with rtmetric %d, best neighbor %p, forwarding %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->originator.u8[0], hdr->originator.u8[1], - from->u8[0], from->u8[1], hdr->hopcount, + from->u8[0], from->u8[1], hdr->rtmetric, neighbor_best(), tc->forwarding); if(!tc->forwarding) { @@ -243,45 +260,75 @@ node_packet_received(struct ruc_conn *c, rimeaddr_t *from, u8_t seqno) } /*---------------------------------------------------------------------------*/ static void -node_packet_sent(struct ruc_conn *c) +node_packet_sent(struct ruc_conn *c, rimeaddr_t *to, u8_t retransmissions) { struct tree_conn *tc = (struct tree_conn *) ((char *)c - offsetof(struct tree_conn, ruc_conn)); tc->forwarding = 0; + neighbor_update_etx(neighbor_find(to), retransmissions); } /*---------------------------------------------------------------------------*/ static void -node_packet_timedout(struct ruc_conn *c) +node_packet_timedout(struct ruc_conn *c, rimeaddr_t *to, u8_t retransmissions) { struct tree_conn *tc = (struct tree_conn *) ((char *)c - offsetof(struct tree_conn, ruc_conn)); tc->forwarding = 0; + neighbor_timedout_etx(neighbor_find(to), retransmissions); } /*---------------------------------------------------------------------------*/ -static const struct ipolite_callbacks ipolite_callbacks = - {adv_packet_received, adv_packet_sent, adv_packet_dropped}; +static void +adv_received(struct nbh_conn *c, rimeaddr_t *from, uint16_t rtmetric) +{ + struct tree_conn *tc = (struct tree_conn *) + ((char *)c - offsetof(struct tree_conn, nbh_conn)); + struct neighbor *n; + + n = neighbor_find(from); + + if(n == NULL) { + if(rtmetric < tc->local_rtmetric) { + neighbor_add(from, rtmetric, 1); + } + } else { + neighbor_update(n, rtmetric, 1); + PRINTF("%d.%d: updating neighbor %d.%d, etx %d, hops %d\n", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], + n->addr.u8[0], n->addr.u8[1], + 1, rtmetric); + } + + update_rtmetric(tc); +} +/*---------------------------------------------------------------------------*/ +/*static const struct ipolite_callbacks ipolite_callbacks = + {adv_packet_received, adv_packet_sent, adv_packet_dropped};*/ static const struct ruc_callbacks ruc_callbacks = {node_packet_received, node_packet_sent, node_packet_timedout}; +static const struct nbh_callbacks nbh_callbacks = { adv_received, + NULL}; /*---------------------------------------------------------------------------*/ void tree_open(struct tree_conn *tc, u16_t channels, const struct tree_callbacks *cb) { - ipolite_open(&tc->ipolite_conn, channels, &ipolite_callbacks); + /* ipolite_open(&tc->ipolite_conn, channels, &ipolite_callbacks);*/ + nbh_open(&tc->nbh_conn, channels, &nbh_callbacks); ruc_open(&tc->ruc_conn, channels + 1, &ruc_callbacks); - tc->hops_from_sink = HOPCOUNT_MAX; + tc->local_rtmetric = RTMETRIC_MAX; tc->cb = cb; - send_adv(tc, MAX_INTERVAL); - ctimer_set(&tc->t, MAX_INTERVAL, send_timer, tc); + /* send_adv(tc, MAX_INTERVAL); + ctimer_set(&tc->t, MAX_INTERVAL, send_timer, tc);*/ } /*---------------------------------------------------------------------------*/ void tree_close(struct tree_conn *tc) { - ipolite_close(&tc->ipolite_conn); + /* ipolite_close(&tc->ipolite_conn);*/ + nbh_close(&tc->nbh_conn); ruc_close(&tc->ruc_conn); } /*---------------------------------------------------------------------------*/ @@ -289,12 +336,13 @@ void tree_set_sink(struct tree_conn *tc, int should_be_sink) { if(should_be_sink) { - tc->hops_from_sink = SINK; - send_adv(tc, MIN_INTERVAL); + tc->local_rtmetric = SINK; + /* send_adv(tc, MIN_INTERVAL);*/ + nbh_start(&tc->nbh_conn, tc->local_rtmetric); } else { - tc->hops_from_sink = HOPCOUNT_MAX; + tc->local_rtmetric = RTMETRIC_MAX; } - update_hopcount(tc); + update_rtmetric(tc); } /*---------------------------------------------------------------------------*/ void @@ -308,14 +356,14 @@ tree_send(struct tree_conn *tc, int rexmits) hdr = rimebuf_hdrptr(); hdr->originator_seqno = tc->seqno++; rimeaddr_copy(&hdr->originator, &rimeaddr_node_addr); - hdr->hopcount = tc->hops_from_sink; + hdr->rtmetric = tc->local_rtmetric; hdr->hoplim = MAX_HOPLIM; hdr->rexmits = rexmits; - if(tc->hops_from_sink == 0) { + if(tc->local_rtmetric == 0) { if(tc->cb->recv != NULL) { tc->cb->recv(&hdr->originator, hdr->originator_seqno, - hdr->hopcount); - } + hdr->rtmetric); + } } else { n = neighbor_best(); if(n != NULL) { @@ -333,7 +381,7 @@ tree_send(struct tree_conn *tc, int rexmits) int tree_depth(struct tree_conn *tc) { - return tc->hops_from_sink; + return tc->local_rtmetric; } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/core/net/rime/tree.h b/core/net/rime/tree.h index 719fe5b25..6293fd856 100644 --- a/core/net/rime/tree.h +++ b/core/net/rime/tree.h @@ -47,7 +47,7 @@ * * This file is part of the Contiki operating system. * - * $Id: tree.h,v 1.8 2007/05/22 20:57:44 adamdunkels Exp $ + * $Id: tree.h,v 1.9 2007/11/13 20:39:29 adamdunkels Exp $ */ /** @@ -62,6 +62,7 @@ #include "net/rime/ipolite.h" #include "net/rime/ruc.h" +#include "net/rime/nbh.h" struct tree_callbacks { void (* recv)(rimeaddr_t *originator, u8_t seqno, @@ -69,12 +70,12 @@ struct tree_callbacks { }; struct tree_conn { - struct ipolite_conn ipolite_conn; + struct nbh_conn nbh_conn; struct ruc_conn ruc_conn; const struct tree_callbacks *cb; struct ctimer t; u8_t forwarding; - u8_t hops_from_sink; + u8_t local_rtmetric; u8_t seqno; }; @@ -88,7 +89,7 @@ void tree_set_sink(struct tree_conn *c, int should_be_sink); int tree_depth(struct tree_conn *c); -#define TREE_MAX_DEPTH 63 +#define TREE_MAX_DEPTH 255 #endif /* __TREE_H__ */ /** @} */