diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index f8587dbf8..7240ae7cb 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -62,11 +62,11 @@ extern rpl_of_t RPL_OF; static rpl_of_t * const objective_functions[] = {&RPL_OF}; /************************************************************************/ -#ifndef RPL_CONF_MAX_PARENTS_PER_DODAG -#define RPL_MAX_PARENTS_PER_DODAG 8 +#ifndef RPL_CONF_MAX_PARENTS_PER_DAG +#define RPL_MAX_PARENTS_PER_DAG 8 #else -#define RPL_MAX_PARENTS_PER_DODAG RPL_CONF_MAX_PARENTS_PER_DODAG -#endif /* !RPL_CONF_MAX_PARENTS */ +#define RPL_MAX_PARENTS_PER_DAG RPL_CONF_MAX_PARENTS_PER_DAG +#endif /* !RPL_CONF_MAX_PARENTS_PER_DAG */ /************************************************************************/ /* RPL definitions. */ @@ -77,30 +77,16 @@ static rpl_of_t * const objective_functions[] = {&RPL_OF}; #define RPL_GROUNDED RPL_CONF_GROUNDED #endif /* !RPL_CONF_GROUNDED */ -#ifndef RPL_CONF_DIO_INTERVAL_MIN -#define RPL_DIO_INTERVAL_MIN DEFAULT_DIO_INTERVAL_MIN -#else -#define RPL_DIO_INTERVAL_MIN RPL_CONF_DIO_INTERVAL_MIN -#endif /* !RPL_CONF_DIO_INTERVAL_MIN */ - -#ifndef RPL_CONF_DIO_INTERVAL_DOUBLINGS -#define RPL_DIO_INTERVAL_DOUBLINGS DEFAULT_DIO_INTERVAL_DOUBLINGS -#else -#define RPL_DIO_INTERVAL_DOUBLINGS RPL_CONF_DIO_INTERVAL_DOUBLINGS -#endif /* !RPL_CONF_DIO_INTERVAL_DOUBLINGS */ - /************************************************************************/ /* Allocate parents from the same static MEMB chunk to reduce memory waste. */ MEMB(parent_memb, struct rpl_parent, - RPL_MAX_PARENTS_PER_DODAG * RPL_MAX_INSTANCES * RPL_MAX_DODAG_PER_INSTANCE); - + RPL_MAX_PARENTS_PER_DAG * RPL_MAX_INSTANCES * RPL_MAX_DAG_PER_INSTANCE); /************************************************************************/ /* Allocate instance table. */ rpl_instance_t instance_table[RPL_MAX_INSTANCES]; rpl_instance_t *default_instance; - /************************************************************************/ -/* lollipop greater than function. */ +/* Greater-than function for the lollipop counter. */ /************************************************************************/ int rpl_lollipop_greater_than(int a, int b) { /* Check if we are comparing an initial value with an old value */ @@ -113,7 +99,6 @@ int rpl_lollipop_greater_than(int a, int b) { (a < b && (b - a) > (RPL_LOLLIPOP_CIRCULAR_REGION + 1- RPL_LOLLIPOP_SEQUENCE_WINDOWS)); } - /************************************************************************/ /* Remove DAG parents with a rank that is at least the same as minimum_rank. */ static void @@ -225,15 +210,15 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id)); - instance->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; - instance->dio_intmin = DEFAULT_DIO_INTERVAL_MIN; + instance->dio_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS; + instance->dio_intmin = RPL_DIO_INTERVAL_MIN; /* The current interval must differ from the minimum interval in order to trigger a DIO timer reset. */ - instance->dio_intcurrent = DEFAULT_DIO_INTERVAL_MIN + - DEFAULT_DIO_INTERVAL_DOUBLINGS; - instance->dio_redundancy = DEFAULT_DIO_REDUNDANCY; - instance->max_rankinc = DEFAULT_MAX_RANKINC; - instance->min_hoprankinc = DEFAULT_MIN_HOPRANKINC; + instance->dio_intcurrent = RPL_DIO_INTERVAL_MIN + + RPL_DIO_INTERVAL_DOUBLINGS; + instance->dio_redundancy = RPL_DIO_REDUNDANCY; + instance->max_rankinc = RPL_MAX_RANKINC; + instance->min_hoprankinc = RPL_MIN_HOPRANKINC; instance->default_lifetime = RPL_DEFAULT_LIFETIME; instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; @@ -409,7 +394,7 @@ rpl_alloc_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id) return dag; } - for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { if(!dag->used) { memset(dag, 0, sizeof(*dag)); dag->parents = &dag->parent_list; @@ -438,8 +423,8 @@ rpl_free_instance(rpl_instance_t *instance) PRINTF("RPL: Leaving the instance %u\n", instance->instance_id); - /* Remove any DODAG inside this instance */ - for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + /* Remove any DAG inside this instance */ + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { if(dag->used) { rpl_free_dodag(dag); } @@ -519,7 +504,7 @@ find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr) rpl_parent_t *p; rpl_dag_t *dag, *end; - for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { if(dag->used) { for(p = list_head(dag->parents); p != NULL; p = p->next) { if(uip_ipaddr_cmp(&p->addr, addr)) { @@ -537,7 +522,7 @@ rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr) rpl_parent_t *p; rpl_dag_t *dag, *end; - for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { if(dag->used) { for(p = list_head(dag->parents); p != NULL; p = p->next) { if(uip_ipaddr_cmp(&p->addr, addr)) { @@ -567,7 +552,7 @@ rpl_select_dodag(rpl_instance_t *instance, rpl_parent_t *p) } } else if(p->dag == best_dag) { best_dag = NULL; - for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != INFINITE_RANK) { if(best_dag == NULL) { best_dag = dag; @@ -588,7 +573,7 @@ rpl_select_dodag(rpl_instance_t *instance, rpl_parent_t *p) /* Remove routes installed by DAOs. */ rpl_remove_routes(instance->current_dag); - PRINTF("RPL: New preferred DODAG: "); + PRINTF("RPL: New preferred DAG: "); PRINT6ADDR(&best_dag->dag_id); PRINTF("\n"); @@ -613,7 +598,7 @@ rpl_select_dodag(rpl_instance_t *instance, rpl_parent_t *p) instance->current_dag->preferred_parent = NULL; if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) { /* Send a No-Path DAO to the removed preferred parent. */ - dao_output(last_parent, ZERO_LIFETIME); + dao_output(last_parent, RPL_ZERO_LIFETIME); } return NULL; } @@ -626,7 +611,7 @@ rpl_select_dodag(rpl_instance_t *instance, rpl_parent_t *p) if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { if(last_parent != NULL) { /* Send a No-Path DAO to the removed preferred parent. */ - dao_output(last_parent, ZERO_LIFETIME); + dao_output(last_parent, RPL_ZERO_LIFETIME); } /* The DAO parent set changed - schedule a DAO transmission. */ RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); @@ -692,7 +677,7 @@ rpl_nullify_parent(rpl_dag_t *dag, rpl_parent_t *parent) } dag->instance->def_route = NULL; } - dao_output(parent, ZERO_LIFETIME); + dao_output(parent, RPL_ZERO_LIFETIME); } } @@ -768,7 +753,7 @@ rpl_get_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id) return NULL; } - for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; ++i) { + for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) { dag = &instance->dag_table[i]; if(dag->used && uip_ipaddr_cmp(&dag->dag_id, dag_id)) { return dag; @@ -1003,7 +988,7 @@ rpl_local_repair(rpl_instance_t *instance) int i; PRINTF("RPL: Starting a local instance repair\n"); - for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; i++) { + for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) { if(instance->dag_table[i].used) { instance->dag_table[i].rank = INFINITE_RANK; nullify_parents(&instance->dag_table[i], 0); @@ -1029,7 +1014,7 @@ rpl_recalculate_ranks(void) */ for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { if(instance->used) { - for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; i++) { + for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) { if(instance->dag_table[i].used) { for(p = list_head(instance->dag_table[i].parents); p != NULL; p = p->next) { if(p->updated) { @@ -1190,7 +1175,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) if(p == NULL) { previous_dag = find_parent_dag(instance, from); if(previous_dag == NULL) { - if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS_PER_DODAG) { + if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS_PER_DAG) { /* Make room for a new parent. */ remove_worst_parent(dag, dio->rank); } @@ -1220,7 +1205,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) } } - PRINTF("RPL: preferred DODAG "); + PRINTF("RPL: preferred DAG "); PRINT6ADDR(&instance->current_dag->dag_id); PRINTF(", rank %u, min_rank %u, ", instance->current_dag->rank, instance->current_dag->min_rank); diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index efc9ee7fa..114b673e4 100755 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -92,6 +92,8 @@ void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *); void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); #endif +extern rpl_of_t RPL_OF; + /*---------------------------------------------------------------------------*/ static int get_global_addr(uip_ipaddr_t *addr) @@ -209,9 +211,15 @@ dio_input(void) memset(&dio, 0, sizeof(dio)); - dio.dag_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; - dio.dag_intmin = DEFAULT_DIO_INTERVAL_MIN; - dio.dag_redund = DEFAULT_DIO_REDUNDANCY; + /* Set default values in case the DIO configuration option is missing. */ + dio.dag_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS; + dio.dag_intmin = RPL_DIO_INTERVAL_MIN; + dio.dag_redund = RPL_DIO_REDUNDANCY; + dio.dag_min_hoprankinc = RPL_MIN_HOPRANKINC; + dio.dag_max_rankinc = RPL_MAX_RANKINC; + dio.ocp = RPL_OF.ocp; + dio.default_lifetime = RPL_DEFAULT_LIFETIME; + dio.lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; uip_ipaddr_copy(&from, &UIP_IP_BUF->srcipaddr); @@ -251,8 +259,10 @@ dio_input(void) dio.rank = get16(buffer, i); i += 2; - PRINTF("RPL: Incoming DIO InstanceID-Version %u-%u\n", (unsigned)dio.instance_id,(unsigned)dio.version); - PRINTF("RPL: Incoming DIO rank %u\n", (unsigned)dio.rank); + PRINTF("RPL: Incoming DIO (id, ver, rank) = (%u,%u,%u)\n", + (unsigned)dio.instance_id, + (unsigned)dio.version, + (unsigned)dio.rank); dio.grounded = buffer[i] & RPL_DIO_GROUNDED; dio.mop = (buffer[i]& RPL_DIO_MOP_MASK) >> RPL_DIO_MOP_SHIFT; @@ -265,9 +275,9 @@ dio_input(void) memcpy(&dio.dag_id, buffer + i, sizeof(dio.dag_id)); i += sizeof(dio.dag_id); - PRINTF("RPL: Incoming DIO DODAG "); + PRINTF("RPL: Incoming DIO (dag_id, pref) = ("); PRINT6ADDR(&dio.dag_id); - PRINTF(", preference: %u\n", dio.preference); + PRINTF(", %u)\n", dio.preference); /* Check if there are any DIO suboptions. */ for(; i < buffer_length; i += len) { @@ -326,7 +336,7 @@ dio_input(void) return; } - /* flags is both preference and flags for now */ + /* The flags field includes the preference value. */ dio.destination_prefix.length = buffer[i + 2]; dio.destination_prefix.flags = buffer[i + 3]; dio.destination_prefix.lifetime = get32(buffer, i + 4); @@ -337,7 +347,7 @@ dio_input(void) memcpy(&dio.destination_prefix.prefix, &buffer[i + 8], (dio.destination_prefix.length + 7) / 8); } else { - PRINTF("RPL: Invalid route infoprefix option, len = %d\n", len); + PRINTF("RPL: Invalid route info option, len = %d\n", len); RPL_STAT(rpl_stats.malformed_msgs++); return; } @@ -360,14 +370,14 @@ dio_input(void) /* buffer + 12 is reserved */ dio.default_lifetime = buffer[i + 13]; dio.lifetime_unit = get16(buffer, i + 14); - PRINTF("RPL: DIO Conf:dbl=%d, min=%d red=%d maxinc=%d mininc=%d ocp=%d d_l=%u l_u=%u\n", + PRINTF("RPL: DAG conf:dbl=%d, min=%d red=%d maxinc=%d mininc=%d ocp=%d d_l=%u l_u=%u\n", dio.dag_intdoubl, dio.dag_intmin, dio.dag_redund, dio.dag_max_rankinc, dio.dag_min_hoprankinc, dio.ocp, dio.default_lifetime, dio.lifetime_unit); break; case RPL_OPTION_PREFIX_INFO: if(len != 32) { - PRINTF("RPL: DAG Prefix info not ok, len != 32\n"); + PRINTF("RPL: DAG prefix info not ok, len != 32\n"); RPL_STAT(rpl_stats.malformed_msgs++); return; } @@ -398,6 +408,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) { unsigned char *buffer; int pos; + rpl_dag_t *dag = instance->current_dag; #if !RPL_LEAF_ONLY uip_ipaddr_t addr; #endif /* !RPL_LEAF_ONLY */ @@ -409,8 +420,6 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) } #endif /* RPL_LEAF_ONLY */ - rpl_dag_t *dag = instance->current_dag; - /* DAG Information Object */ pos = 0; @@ -436,9 +445,8 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) buffer[pos++] = instance->dtsn_out; - if(RPL_LOLLIPOP_IS_INIT(instance->dtsn_out)) { - RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); - } + /* always request new DAO to refresh route */ + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); /* reserved 2 bytes */ buffer[pos++] = 0; /* flags */ @@ -597,7 +605,7 @@ dao_input(void) /* Is the DAGID present? */ if(flags & RPL_DAO_D_FLAG) { if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) { - PRINTF("RPL: Ignoring a DAO for a DODAG different from ours\n"); + PRINTF("RPL: Ignoring a DAO for a DAG different from ours\n"); return; } pos += 16; @@ -640,7 +648,7 @@ dao_input(void) rep = uip_ds6_route_lookup(&prefix); - if(lifetime == ZERO_LIFETIME) { + if(lifetime == RPL_ZERO_LIFETIME) { /* No-Path DAO received; invoke the route purging routine. */ if(rep != NULL && rep->state.saved_lifetime == 0 && rep->length == prefixlen) { PRINTF("RPL: Setting expiration timer for prefix "); @@ -733,19 +741,19 @@ dao_output(rpl_parent_t *n, uint8_t lifetime) buffer[pos++] = instance->instance_id; buffer[pos] = 0; -#if RPL_DAO_SPECIFY_DODAG +#if RPL_DAO_SPECIFY_DAG buffer[pos] |= RPL_DAO_D_FLAG; -#endif /* RPL_DAO_SPECIFY_DODAG */ +#endif /* RPL_DAO_SPECIFY_DAG */ #if RPL_CONF_DAO_ACK buffer[pos] |= RPL_DAO_K_FLAG; #endif /* RPL_CONF_DAO_ACK */ ++pos; buffer[pos++] = 0; /* reserved */ buffer[pos++] = dao_sequence; -#if RPL_DAO_SPECIFY_DODAG +#if RPL_DAO_SPECIFY_DAG memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id)); pos+=sizeof(dag->dag_id); -#endif /* RPL_DAO_SPECIFY_DODAG */ +#endif /* RPL_DAO_SPECIFY_DAG */ /* create target subopt */ prefixlen = sizeof(prefix) * CHAR_BIT; diff --git a/core/net/rpl/rpl-of-etx.c b/core/net/rpl/rpl-of-etx.c index 05a521c83..a7c0e4429 100644 --- a/core/net/rpl/rpl-of-etx.c +++ b/core/net/rpl/rpl-of-etx.c @@ -112,7 +112,7 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) if(base_rank == 0) { return INFINITE_RANK; } - rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * DEFAULT_MIN_HOPRANKINC; + rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * RPL_MIN_HOPRANKINC; } else { /* multiply first, then scale down to avoid truncation effects */ rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric * p->dag->instance->min_hoprankinc); diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index ca239eb20..49f3c99d0 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -62,7 +62,7 @@ rpl_of_t rpl_of0 = { 0 }; -#define DEFAULT_RANK_INCREMENT DEFAULT_MIN_HOPRANKINC +#define DEFAULT_RANK_INCREMENT RPL_MIN_HOPRANKINC #define MIN_DIFFERENCE (NEIGHBOR_INFO_ETX_DIVISOR + NEIGHBOR_INFO_ETX_DIVISOR / 2) diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index 94eaec0d8..f48d31afd 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -110,10 +110,10 @@ /* Default values for RPL constants and variables. */ /* The default value for the DAO timer. */ -#define DEFAULT_DAO_LATENCY (CLOCK_SECOND * 8) +#define RPL_DAO_LATENCY (CLOCK_SECOND * 4) /* Special value indicating immediate removal. */ -#define ZERO_LIFETIME 0 +#define RPL_ZERO_LIFETIME 0 /* Default route lifetime unit. */ #define RPL_DEFAULT_LIFETIME_UNIT 0xffff @@ -125,13 +125,14 @@ ((unsigned long)(instance)->lifetime_unit * (lifetime)) #ifndef RPL_CONF_MIN_HOPRANKINC -#define DEFAULT_MIN_HOPRANKINC 256 +#define RPL_MIN_HOPRANKINC 256 #else -#define DEFAULT_MIN_HOPRANKINC RPL_CONF_MIN_HOPRANKINC +#define RPL_MIN_HOPRANKINC RPL_CONF_MIN_HOPRANKINC #endif -#define DEFAULT_MAX_RANKINC (7 * DEFAULT_MIN_HOPRANKINC) +#define RPL_MAX_RANKINC (7 * RPL_MIN_HOPRANKINC) -#define DAG_RANK(fixpt_rank, instance) ((fixpt_rank) / (instance)->min_hoprankinc) +#define DAG_RANK(fixpt_rank, instance) \ + ((fixpt_rank) / (instance)->min_hoprankinc) /* Rank of a virtual root node that coordinates DAG root nodes. */ #define BASE_RANK 0 @@ -148,23 +149,23 @@ means 8 milliseconds, but that is an unreasonable value if using power-saving / duty-cycling */ #ifdef RPL_CONF_DIO_INTERVAL_MIN -#define DEFAULT_DIO_INTERVAL_MIN RPL_CONF_DIO_INTERVAL_MIN +#define RPL_DIO_INTERVAL_MIN RPL_CONF_DIO_INTERVAL_MIN #else -#define DEFAULT_DIO_INTERVAL_MIN 12 +#define RPL_DIO_INTERVAL_MIN 12 #endif /* Maximum amount of timer doublings. */ #ifdef RPL_CONF_DIO_INTERVAL_DOUBLINGS -#define DEFAULT_DIO_INTERVAL_DOUBLINGS RPL_CONF_DIO_INTERVAL_DOUBLINGS +#define RPL_DIO_INTERVAL_DOUBLINGS RPL_CONF_DIO_INTERVAL_DOUBLINGS #else -#define DEFAULT_DIO_INTERVAL_DOUBLINGS 8 +#define RPL_DIO_INTERVAL_DOUBLINGS 8 #endif /* Default DIO redundancy. */ #ifdef RPL_CONF_DIO_REDUNDANCY -#define DEFAULT_DIO_REDUNDANCY RPL_CONF_DIO_REDUNDANCY +#define RPL_DIO_REDUNDANCY RPL_CONF_DIO_REDUNDANCY #else -#define DEFAULT_DIO_REDUNDANCY 10 +#define RPL_DIO_REDUNDANCY 10 #endif /* Expire DAOs from neighbors that do not respond in this time. (seconds) */ @@ -207,6 +208,20 @@ #endif #define RPL_DIS_START_DELAY 5 /*---------------------------------------------------------------------------*/ +/* Lollipop counters */ + +#define RPL_LOLLIPOP_MAX_VALUE 255 +#define RPL_LOLLIPOP_CIRCULAR_REGION 127 +#define RPL_LOLLIPOP_SEQUENCE_WINDOWS 16 +#define RPL_LOLLIPOP_INIT (RPL_LOLLIPOP_MAX_VALUE - RPL_LOLLIPOP_SEQUENCE_WINDOWS + 1) +#define RPL_LOLLIPOP_INCREMENT(counter) \ + ((counter) > RPL_LOLLIPOP_CIRCULAR_REGION ? \ + ++(counter) & RPL_LOLLIPOP_MAX_VALUE : \ + ++(counter) & RPL_LOLLIPOP_CIRCULAR_REGION) + +#define RPL_LOLLIPOP_IS_INIT(counter) \ + ((counter) > RPL_LOLLIPOP_CIRCULAR_REGION) +/*---------------------------------------------------------------------------*/ /* Logical representation of a DAG Information Object (DIO.) */ struct rpl_dio { uip_ipaddr_t dag_id; diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index 01cbe9138..0527d5363 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -225,8 +225,8 @@ rpl_schedule_dao(rpl_instance_t *instance) if(!etimer_expired(&instance->dao_timer.etimer)) { PRINTF("RPL: DAO timer already scheduled\n"); } else { - expiration_time = DEFAULT_DAO_LATENCY / 2 + - (random_rand() % (DEFAULT_DAO_LATENCY)); + expiration_time = RPL_DAO_LATENCY / 2 + + (random_rand() % (RPL_DAO_LATENCY)); PRINTF("RPL: Scheduling DAO timer %u ticks in the future\n", (unsigned)expiration_time); ctimer_set(&instance->dao_timer, expiration_time, diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index e039cf98d..90bf43626 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -97,24 +97,24 @@ /* * Maximum of concurent dodag inside an instance */ -#ifndef RPL_CONF_MAX_DODAG_PER_INSTANCE -#define RPL_MAX_DODAG_PER_INSTANCE 2 +#ifndef RPL_CONF_MAX_DAG_PER_INSTANCE +#define RPL_MAX_DAG_PER_INSTANCE 2 #else -#define RPL_MAX_DODAG_PER_INSTANCE RPL_CONF_MAX_DODAG_PER_INSTANCE -#endif /* !RPL_CONF_MAX_DODAG_PER_INSTANCE */ +#define RPL_MAX_DAG_PER_INSTANCE RPL_CONF_MAX_DAG_PER_INSTANCE +#endif /* !RPL_CONF_MAX_DAG_PER_INSTANCE */ /* * */ -#ifndef RPL_CONF_DAO_SPECIFY_DODAG -#if RPL_MAX_DODAG_PER_INSTANCE > 1 -#define RPL_DAO_SPECIFY_DODAG 1 -#else /* RPL_MAX_DODAG_PER_INSTANCE > 1*/ -#define RPL_DAO_SPECIFY_DODAG 0 -#endif /* RPL_MAX_DODAG_PER_INSTANCE > 1 */ -#else /* RPL_CONF_DAO_SPECIFY_DODAG */ -#define RPL_DAO_SPECIFY_DODAG RPL_CONF_DAO_SPECIFY_DODAG -#endif /* RPL_CONF_DAO_SPECIFY_DODAG */ +#ifndef RPL_CONF_DAO_SPECIFY_DAG +#if RPL_MAX_DAG_PER_INSTANCE > 1 +#define RPL_DAO_SPECIFY_DAG 1 +#else /* RPL_MAX_DAG_PER_INSTANCE > 1*/ +#define RPL_DAO_SPECIFY_DAG 0 +#endif /* RPL_MAX_DAG_PER_INSTANCE > 1 */ +#else /* RPL_CONF_DAO_SPECIFY_DAG */ +#define RPL_DAO_SPECIFY_DAG RPL_CONF_DAO_SPECIFY_DAG +#endif /* RPL_CONF_DAO_SPECIFY_DAG */ /*---------------------------------------------------------------------------*/ @@ -123,20 +123,6 @@ /*---------------------------------------------------------------------------*/ typedef uint16_t rpl_rank_t; typedef uint16_t rpl_ocp_t; - -/*---------------------------------------------------------------------------*/ -/* Lollipop counters */ - -#define RPL_LOLLIPOP_MAX_VALUE 255 -#define RPL_LOLLIPOP_CIRCULAR_REGION 127 -#define RPL_LOLLIPOP_SEQUENCE_WINDOWS 16 -#define RPL_LOLLIPOP_INIT RPL_LOLLIPOP_MAX_VALUE - RPL_LOLLIPOP_SEQUENCE_WINDOWS + 1 -#define RPL_LOLLIPOP_INCREMENT(ctr) (ctr > RPL_LOLLIPOP_CIRCULAR_REGION ? \ - ++ctr & RPL_LOLLIPOP_MAX_VALUE : \ - ++ctr & RPL_LOLLIPOP_CIRCULAR_REGION) - -#define RPL_LOLLIPOP_IS_INIT(counter) (counter > RPL_LOLLIPOP_CIRCULAR_REGION) - /*---------------------------------------------------------------------------*/ /* DAG Metric Container Object Types, to be confirmed by IANA. */ #define RPL_DAG_MC_NONE 0 /* Local identifier for empty MC */ @@ -217,7 +203,7 @@ typedef struct rpl_prefix rpl_prefix_t; /* Directed Acyclic Graph */ struct rpl_dag { uip_ipaddr_t dag_id; - rpl_rank_t min_rank; /* should be reset per DODAG iteration! */ + rpl_rank_t min_rank; /* should be reset per DAG iteration! */ uint8_t version; uint8_t grounded; uint8_t preference; @@ -286,7 +272,7 @@ struct rpl_instance { rpl_metric_container_t mc; rpl_of_t *of; rpl_dag_t *current_dag; - rpl_dag_t dag_table[RPL_MAX_DODAG_PER_INSTANCE]; + rpl_dag_t dag_table[RPL_MAX_DAG_PER_INSTANCE]; /* The current default router - used for routing "upwards" */ uip_ds6_defrt_t *def_route; uint8_t instance_id; diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java index f71d29fe2..217836800 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java @@ -59,6 +59,7 @@ import se.sics.cooja.mspmote.plugins.CodeVisualizerSkin; import se.sics.cooja.mspmote.plugins.MspBreakpointContainer; import se.sics.cooja.plugins.BufferListener.BufferAccess; import se.sics.cooja.plugins.Visualizer; +import se.sics.mspsim.cli.CommandContext; import se.sics.mspsim.cli.CommandHandler; import se.sics.mspsim.cli.LineListener; import se.sics.mspsim.cli.LineOutputStream; @@ -74,6 +75,7 @@ import se.sics.mspsim.util.DebugInfo; import se.sics.mspsim.util.ELF; import se.sics.mspsim.util.MapEntry; import se.sics.mspsim.util.MapTable; +import se.sics.mspsim.util.SimpleProfiler; /** * @author Fredrik Osterlind @@ -88,7 +90,6 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc } private CommandHandler commandHandler; - private ArrayList commandListeners = new ArrayList(); private MSP430 myCpu = null; private MspMoteType myMoteType = null; private MspMoteMemory myMemory = null; @@ -150,24 +151,6 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc return new MoteInterfaceHandler(this, getType().getMoteInterfaceClasses()); } - public void sendCLICommand(String line) { - if (commandHandler != null) { - commandHandler.lineRead(line); - } - } - - public boolean hasCLIListener() { - return !commandListeners.isEmpty(); - } - - public void addCLIListener(LineListener listener) { - commandListeners.add(listener); - } - - public void removeCLIListener(LineListener listener) { - commandListeners.remove(listener); - } - /** * @return MSP430 CPU */ @@ -234,17 +217,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc * @throws IOException Preparing mote failed */ protected void prepareMote(File fileELF, GenericNode node) throws IOException { - LineOutputStream lout = new LineOutputStream(new LineListener() { - public void lineRead(String line) { - for (LineListener l: commandListeners.toArray(new LineListener[0])) { - if (l == null) { - continue; - } - l.lineRead(line); - } - }}); - PrintStream out = new PrintStream(lout); - this.commandHandler = new CommandHandler(out, out); + this.commandHandler = new CommandHandler(System.out, System.err); node.setCommandHandler(commandHandler); ConfigManager config = new ConfigManager(); @@ -271,6 +244,10 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc myCpu.reset(); } + public CommandHandler getCLICommandHandler() { + return commandHandler; + } + /* called when moteID is updated */ public void idUpdated(int newID) { } @@ -344,13 +321,9 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc myCpu.stepMicros(t - lastExecute, duration); lastExecute = t; } catch (EmulationException e) { - String stackTraceOutput = sendCLICommandAndPrint("stacktrace"); - if (stackTraceOutput == null) { - stackTraceOutput = ""; - } - stackTraceOutput = e.getMessage() + "\n\n" + stackTraceOutput; + String trace = e.getMessage() + "\n\n" + getStackTrace(); throw (ContikiError) - new ContikiError(stackTraceOutput).initCause(e); + new ContikiError(trace).initCause(e); } /* Schedule wakeup */ @@ -377,22 +350,29 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc }*/ } - public String sendCLICommandAndPrint(String cmd) { - String response = executeCLICommand(cmd); - logger.fatal(response); - return response; + public String getStackTrace() { + return executeCLICommand("stacktrace"); + } + + public int executeCLICommand(String cmd, CommandContext context) { + return commandHandler.executeCommand(cmd, context); } public String executeCLICommand(String cmd) { final StringBuilder sb = new StringBuilder(); - LineListener tmp = new LineListener() { + LineListener ll = new LineListener() { public void lineRead(String line) { - sb.append(line + "\n"); + sb.append(line).append("\n"); } }; - commandListeners.add(tmp); - sendCLICommand(cmd); - commandListeners.remove(tmp); + PrintStream po = new PrintStream(new LineOutputStream(ll)); + CommandContext c = new CommandContext(commandHandler, null, "", new String[0], 1, null); + c.out = po; + c.err = po; + + if (0 != executeCLICommand(cmd, c)) { + sb.append("\nWarning: command failed"); + } return sb.toString(); } @@ -507,7 +487,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc } public String getPCString() { - int pc = myCpu.reg[MSP430Constants.PC]; + int pc = myCpu.getPC(); ELF elf = (ELF)myCpu.getRegistry().getComponent(ELF.class); DebugInfo di = elf.getDebugInfo(pc); @@ -517,6 +497,17 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc } if (di == null) { /* Return PC value */ + MapEntry mapEntry = ((SimpleProfiler)myCpu.getProfiler()).getCallMapEntry(0); + if (mapEntry != null) { + String file = mapEntry.getFile(); + if (file != null) { + if (file.indexOf('/') >= 0) { + file = file.substring(file.lastIndexOf('/')+1); + } + } + String name = mapEntry.getName(); + return file + ":?:" + name; + } return String.format("*%02x", myCpu.reg[MSP430Constants.PC]); } @@ -527,15 +518,19 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc /* strip path */ file = file.substring(file.lastIndexOf('/')+1, file.length()); } + String function = di.getFunction(); - function = function==null?"?":function; + function = function==null?"":function; if (function.contains(":")) { /* strip arguments */ function = function.substring(0, function.lastIndexOf(':')); } - return file + ":" + function + ":" + lineNo; + if (function.equals("* not available")) { + function = "?"; + } + return file + ":" + lineNo + ":" + function; - /*return executeCLICommand("line " + myCpu.reg[MSP430Constants.PC]);*/ + /*return executeCLICommand("line " + myCpu.getPC());*/ } public MemoryMonitor createMemoryMonitor(final MemoryEventHandler meh) { diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java index 5836b07be..6b375e0fa 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java @@ -36,6 +36,8 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; +import java.io.PrintStream; + import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; @@ -43,6 +45,7 @@ import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; + import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; import se.sics.cooja.Mote; @@ -51,7 +54,9 @@ import se.sics.cooja.PluginType; import se.sics.cooja.Simulation; import se.sics.cooja.VisPlugin; import se.sics.cooja.mspmote.MspMote; +import se.sics.mspsim.cli.CommandContext; import se.sics.mspsim.cli.LineListener; +import se.sics.mspsim.cli.LineOutputStream; @ClassDescription("Msp CLI") @PluginType(PluginType.MOTE_PLUGIN) @@ -66,8 +71,6 @@ public class MspCLI extends VisPlugin implements MotePlugin { private int historyPos = 0; private int historyCount = 0; - private LineListener myListener; - public MspCLI(Mote mote, Simulation simulationToVisualize, GUI gui) { super("Msp CLI (" + mote.getID() + ')', gui); this.mspMote = (MspMote) mote; @@ -79,20 +82,27 @@ public class MspCLI extends VisPlugin implements MotePlugin { logArea.setEditable(false); panel.add(new JScrollPane(logArea), BorderLayout.CENTER); + LineListener lineListener = new LineListener() { + public void lineRead(String line) { + addCLIData(line); + } + }; + PrintStream po = new PrintStream(new LineOutputStream(lineListener)); + final CommandContext commandContext = new CommandContext(mspMote.getCLICommandHandler(), null, "", new String[0], 1, null); + commandContext.out = po; + commandContext.err = po; + JPopupMenu popupMenu = new JPopupMenu(); JMenuItem clearItem = new JMenuItem("Clear"); clearItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { logArea.setText(""); } - }); popupMenu.add(clearItem); logArea.setComponentPopupMenu(popupMenu); ActionListener action = new ActionListener() { - public void actionPerformed(ActionEvent e) { String command = trim(commandField.getText()); if (command != null) { @@ -107,15 +117,16 @@ public class MspCLI extends VisPlugin implements MotePlugin { } historyPos = historyCount; addCLIData("> " + command); - mspMote.sendCLICommand(command); + + mspMote.executeCLICommand(command, commandContext); commandField.setText(""); } catch (Exception ex) { System.err.println("could not send '" + command + "':"); ex.printStackTrace(); JOptionPane.showMessageDialog(panel, - "could not send '" + command + "':\n" - + ex, "ERROR", - JOptionPane.ERROR_MESSAGE); + "could not send '" + command + "':\n" + + ex, "ERROR", + JOptionPane.ERROR_MESSAGE); } } else { commandField.getToolkit().beep(); @@ -166,19 +177,9 @@ public class MspCLI extends VisPlugin implements MotePlugin { }); panel.add(commandField, BorderLayout.SOUTH); - - myListener = new LineListener() { - public void lineRead(String line) { - addCLIData(line); - } - }; - mspMote.addCLIListener(myListener); } public void closePlugin() { - if (myListener != null) { - mspMote.addCLIListener(null); - } } public void addCLIData(final String text) { @@ -199,7 +200,7 @@ public class MspCLI extends VisPlugin implements MotePlugin { private String trim(String text) { return (text != null) && ((text = text.trim()).length() > 0) ? text : null; } - + public Mote getMote() { return mspMote; } diff --git a/tools/cooja/java/se/sics/cooja/dialogs/TableColumnAdjuster.java b/tools/cooja/java/se/sics/cooja/dialogs/TableColumnAdjuster.java index adf7c4825..af88396a2 100644 --- a/tools/cooja/java/se/sics/cooja/dialogs/TableColumnAdjuster.java +++ b/tools/cooja/java/se/sics/cooja/dialogs/TableColumnAdjuster.java @@ -40,6 +40,8 @@ package se.sics.cooja.dialogs; import java.awt.Component; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Arrays; + import javax.swing.JTable; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; @@ -68,16 +70,23 @@ public class TableColumnAdjuster implements PropertyChangeListener, TableModelLi this(table, 6); } + private boolean[] adjustColumns; + /* * Specify the table and spacing */ public TableColumnAdjuster(JTable table, int spacing) { this.table = table; this.spacing = spacing; + TableColumnModel tcm = table.getColumnModel(); + adjustColumns = new boolean[tcm.getColumnCount()]; + Arrays.fill(adjustColumns, true); + setColumnHeaderIncluded(true); setColumnDataIncluded(true); setOnlyAdjustLarger(true); setDynamicAdjustment(false); + } public void packColumns() { @@ -97,10 +106,16 @@ public class TableColumnAdjuster implements PropertyChangeListener, TableModelLi public void adjustColumns() { TableColumnModel tcm = table.getColumnModel(); for (int i = 0, n = tcm.getColumnCount(); i < n; i++) { - adjustColumn(i, isOnlyAdjustLarger); + if (adjustColumns[i]) { + adjustColumn(i, isOnlyAdjustLarger); + } } } + public void setAdjustColumn(int i, boolean adjust) { + adjustColumns[i] = adjust; + } + /* * Adjust the width of the specified column in the table */ @@ -109,6 +124,9 @@ public class TableColumnAdjuster implements PropertyChangeListener, TableModelLi } private void adjustColumn(int column, boolean onlyAdjustLarger) { + if (!adjustColumns[column]) { + return; + } int viewColumn = table.convertColumnIndexToView(column); if (viewColumn < 0) { return; @@ -194,6 +212,9 @@ public class TableColumnAdjuster implements PropertyChangeListener, TableModelLi private void adjustColumnsForNewRows(int firstRow, int lastRow) { TableColumnModel tcm = table.getColumnModel(); for (int column = 0, n = tcm.getColumnCount(); column < n; column++) { + if (!adjustColumns[column]) { + continue; + } int viewColumn = table.convertColumnIndexToView(column); if (viewColumn < 0) { continue; @@ -302,6 +323,9 @@ public class TableColumnAdjuster implements PropertyChangeListener, TableModelLi } else if (isOnlyAdjustLarger) { // Only need to worry about an increase in width for these cells + if (!adjustColumns[column]) { + return; + } int viewColumn = table.convertColumnIndexToView(column); if (viewColumn < 0) { // Column is not visible diff --git a/tools/cooja/java/se/sics/cooja/motes/AbstractEmulatedMote.java b/tools/cooja/java/se/sics/cooja/motes/AbstractEmulatedMote.java index fae2c4e50..1d9dae44e 100644 --- a/tools/cooja/java/se/sics/cooja/motes/AbstractEmulatedMote.java +++ b/tools/cooja/java/se/sics/cooja/motes/AbstractEmulatedMote.java @@ -60,7 +60,11 @@ public abstract class AbstractEmulatedMote extends AbstractWakeupMote implements public String getPCString() { return null; } - + + public String getStackTrace() { + return null; + } + public interface MemoryMonitor { public boolean start(int address, int size); public void stop(); diff --git a/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java b/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java index f7751aa22..6e4323650 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java +++ b/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java @@ -198,6 +198,9 @@ public class BufferListener extends VisPlugin { private boolean hideReads = true; private JCheckBoxMenuItem hideReadsCheckbox; + private boolean withStackTrace = false; + private JCheckBoxMenuItem withStackTraceCheckbox; + private JMenu parserMenu = new JMenu("Parser"); private JMenu bufferMenu = new JMenu("Buffer"); @@ -332,29 +335,44 @@ public class BufferListener extends VisPlugin { java.awt.Point p = e.getPoint(); int rowIndex = rowAtPoint(p); int colIndex = columnAtPoint(p); - int columnIndex = convertColumnIndexToModel(colIndex); - if (rowIndex < 0 || columnIndex < 0) { + if (rowIndex < 0 || colIndex < 0) { return super.getToolTipText(e); } - Object v = getValueAt(rowIndex, columnIndex); - if (v instanceof BufferAccess && parser instanceof GraphicalParser) { - return - "" + - StringUtils.hexDump(((BufferAccess)v).mem, 4, 4).replaceAll("\n", "
") + - ""; + int row = convertRowIndexToModel(rowIndex); + int column = convertColumnIndexToModel(colIndex); + if (row < 0 || column < 0) { + return super.getToolTipText(e); } - if (v != null) { - String t = v.toString(); - if (t.length() > 60) { - StringBuilder sb = new StringBuilder(); - sb.append(""); - do { - sb.append(t.substring(0, 60)).append("
"); - t = t.substring(60); - } while (t.length() > 60); - return sb.append(t).append("").toString(); + + if (column == COLUMN_SOURCE) { + BufferAccess ba = logs.get(row); + if (ba.stackTrace != null) { + return + "
" +
+            ba.stackTrace +
+            "
"; } + return "No stack trace (enable in popup menu)"; } + if (column == COLUMN_DATA) { + BufferAccess ba = logs.get(row); + if (parser instanceof GraphicalParser) { + return + "
" +
+            StringUtils.hexDump(ba.mem, 4, 4) +
+            "
"; + } + + String baString = ba.getParsedString(); + StringBuilder sb = new StringBuilder(); + sb.append(""); + while (baString.length() > 60) { + sb.append(baString.substring(0, 60)).append("
"); + baString = baString.substring(60); + }; + return sb.append(baString).append("").toString(); + } + return super.getToolTipText(e); } }; @@ -493,6 +511,7 @@ public class BufferListener extends VisPlugin { /* Automatically update column widths */ final TableColumnAdjuster adjuster = new TableColumnAdjuster(logTable, 0); adjuster.packColumns(); + logTable.getColumnModel().getColumn(COLUMN_DATA).setWidth(400); /* Popup menu */ JPopupMenu popupMenu = new JPopupMenu(); @@ -555,7 +574,7 @@ public class BufferListener extends VisPlugin { repaint(); } }); - hideReadsCheckbox = new JCheckBoxMenuItem("Hide READs", true); + hideReadsCheckbox = new JCheckBoxMenuItem("Hide READs", hideReads); popupMenu.add(hideReadsCheckbox); hideReadsCheckbox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -565,7 +584,16 @@ public class BufferListener extends VisPlugin { } }); - + withStackTraceCheckbox = new JCheckBoxMenuItem("Capture stack traces", withStackTrace); + popupMenu.add(withStackTraceCheckbox); + withStackTraceCheckbox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + withStackTrace = withStackTraceCheckbox.isSelected(); + setFilter(getFilter()); + repaint(); + } + }); + logTable.setComponentPopupMenu(popupMenu); /* Column width adjustment */ @@ -573,6 +601,7 @@ public class BufferListener extends VisPlugin { public void run() { /* Make sure this happens *after* adding history */ adjuster.setDynamicAdjustment(true); + adjuster.setAdjustColumn(COLUMN_DATA, false); } }); @@ -775,6 +804,10 @@ public class BufferListener extends VisPlugin { element = new Element("showreads"); config.add(element); } + if (withStackTrace) { + element = new Element("stacktrace"); + config.add(element); + } element = new Element("parser"); element.setText(parser.getClass().getName()); config.add(element); @@ -815,6 +848,9 @@ public class BufferListener extends VisPlugin { } else if ("showreads".equals(name)) { hideReads = false; hideReadsCheckbox.setSelected(false); + } else if ("stacktrace".equals(name)) { + withStackTrace = true; + withStackTraceCheckbox.setSelected(true); } else if ("formatted_time".equals(name)) { formatTimeString = true; repaintTimeColumn(); @@ -928,6 +964,7 @@ public class BufferListener extends VisPlugin { public final String typeStr; public final String sourceStr; + public final String stackTrace; public final byte[] mem; private boolean[] accessedBitpattern = null; @@ -970,6 +1007,11 @@ public class BufferListener extends VisPlugin { typeStr = type.toString(); String s = mote.getPCString(); sourceStr = s==null?"[unknown]":s; + if (withStackTrace) { + this.stackTrace = mote.getStackTrace(); + } else { + this.stackTrace = null; + } } public Object getParsedData() { @@ -1285,8 +1327,7 @@ public class BufferListener extends VisPlugin { } parser = bp; - logTable.getColumnModel().getColumn(COLUMN_DATA).setHeaderValue( - GUI.getDescriptionOf(bp)); + logTable.getColumnModel().getColumn(COLUMN_DATA).setHeaderValue(GUI.getDescriptionOf(bp)); repaint(); } diff --git a/tools/mspsim/mspsim.jar b/tools/mspsim/mspsim.jar index 43689baa7..fa3178fce 100644 Binary files a/tools/mspsim/mspsim.jar and b/tools/mspsim/mspsim.jar differ