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