/*---------------------------------------------------------------------------*/ static void rpl_set_preferred_parent(rpl_dag_t *dag, rpl_parent_t *p) { if(dag != NULL && dag->preferred_parent != p) { PRINTF("RPL: rpl_set_preferred_parent "); if(p != NULL) { PRINT6ADDR(rpl_get_parent_ipaddr(p)); } else { PRINTF("NULL"); } PRINTF(" used to be "); if(dag->preferred_parent != NULL) { PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent)); } else { PRINTF("NULL"); } PRINTF("\n"); /* Always keep the preferred parent locked, so it remains in the * neighbor table. */ nbr_table_unlock(rpl_parents, dag->preferred_parent); nbr_table_lock(rpl_parents, p); dag->preferred_parent = p; } }
static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { rpl_rank_t r1, r2; rpl_dag_t *dag; PRINTF("RPL: Comparing parent "); PRINT6ADDR(rpl_get_parent_ipaddr(p1)); PRINTF(" (confidence %d, rank %d) with parent ", p1->link_metric, p1->rank); PRINT6ADDR(rpl_get_parent_ipaddr(p2)); PRINTF(" (confidence %d, rank %d)\n", p2->link_metric, p2->rank); r1 = DAG_RANK(p1->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + p1->link_metric; r2 = DAG_RANK(p2->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + p2->link_metric; /* Compare two parents by looking both and their rank and at the ETX for that parent. We choose the parent that has the most favourable combination. */ dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */ if(r1 < r2 + MIN_DIFFERENCE && r1 > r2 - MIN_DIFFERENCE) { return dag->preferred_parent; } else if(r1 < r2) { return p1; } else { return p2; } }
/*---------------------------------------------------------------------------*/ void rpl_nullify_parent(rpl_parent_t *parent) { rpl_dag_t *dag = parent->dag; /* This function can be called when the preferred parent is NULL, so we need to handle this condition in order to trigger uip_ds6_defrt_rm. */ if(parent == dag->preferred_parent || dag->preferred_parent == NULL) { dag->rank = INFINITE_RANK; if(dag->joined) { if(dag->instance->def_route != NULL) { PRINTF("RPL: Removing default route "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); PRINTF("\n"); uip_ds6_defrt_rm(dag->instance->def_route); dag->instance->def_route = NULL; } /* Send No-Path DAO only to preferred parent, if any */ if(parent == dag->preferred_parent) { dao_output(parent, RPL_ZERO_LIFETIME); rpl_set_preferred_parent(dag, NULL); } } } PRINTF("RPL: Nullifying parent "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); PRINTF("\n"); }
/*---------------------------------------------------------------------------*/ void rpl_nullify_parent(rpl_parent_t *parent) { rpl_dag_t *dag = parent->dag; #if WITH_ORPL /* We don't have a preferred parent in ORPL. * We simply recalculate our EDC. */ dag->instance->of->calculate_rank(parent, 0); return; #endif /* WITH_ORPL */ /* This function can be called when the preferred parent is NULL, so we need to handle this condition in order to trigger uip_ds6_defrt_rm. */ if(parent == dag->preferred_parent || dag->preferred_parent == NULL) { rpl_set_preferred_parent(dag, NULL); dag->rank = INFINITE_RANK; if(dag->joined) { if(dag->instance->def_route != NULL) { PRINTF("RPL: Removing default route "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); PRINTF("\n"); uip_ds6_defrt_rm(dag->instance->def_route); dag->instance->def_route = NULL; } dao_output(parent, RPL_ZERO_LIFETIME); } } PRINTF("RPL: Nullifying parent "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); PRINTF("\n"); }
/*---------------------------------------------------------------------------*/ void rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) { if(parent == dag_src->preferred_parent) { rpl_set_preferred_parent(dag_src, NULL); dag_src->rank = INFINITE_RANK; if(dag_src->joined && dag_src->instance->def_route != NULL) { PRINTF("RPL: Removing default route "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); PRINTF("\n"); PRINTF("rpl_move_parent\n"); uip_ds6_defrt_rm(dag_src->instance->def_route); dag_src->instance->def_route = NULL; } } else if(dag_src->joined) { /* Remove uIPv6 routes that have this parent as the next hop. */ rpl_remove_routes_by_nexthop(rpl_get_parent_ipaddr(parent), dag_src); } PRINTF("RPL: Moving parent "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); PRINTF("\n"); parent->dag = dag_dst; }
uint16_t create_parent_msg(char *buf,rpl_parent_t *parent, uint8_t preferred) { uint8_t n = 0; uip_ds6_nbr_t *nbr; uip_ipaddr_t * addr = rpl_get_parent_ipaddr(parent); n += sprintf(&(buf[n]), "{\"eui\":\"%04x%04x%04x%04x\",", UIP_HTONS(addr->u16[4]), UIP_HTONS(addr->u16[5]), UIP_HTONS(addr->u16[6]), UIP_HTONS(addr->u16[7])); n += sprintf(&(buf[n]), "\"pref\":"); if(preferred == 1) { n += sprintf(&(buf[n]), "true,"); }else { n += sprintf(&(buf[n]), "false,"); } nbr = rpl_get_nbr(parent); // Estimated Retransmission part (ETX) value n += sprintf(&(buf[n]), "\"etx\":%d}",nbr->link_metric); buf[n] = 0; // clear next buffer value PRINTF("buf: %s\n", buf); // print the buffer value return n; }
/*---------------------------------------------------------------------------*/ static void res_rpl_parent_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint16_t length; rpl_instance_t *instance; char message[REST_MAX_CHUNK_SIZE]; memset(message, 0, REST_MAX_CHUNK_SIZE); instance = rpl_get_instance(RPL_DEFAULT_INSTANCE); /* Print the parent */ if(instance != NULL && instance->current_dag != NULL && instance->current_dag->preferred_parent != NULL) { sprintf(&message[0], "RPL Parent: "); sprint_addr6(&message[0], rpl_get_parent_ipaddr(instance->current_dag->preferred_parent)); } else { sprintf(&message[0], "No parent yet\n"); } length = strlen(&message[0]); memcpy(buffer, message, length); REST.set_header_content_type(response, REST.type.TEXT_PLAIN); REST.set_header_etag(response, (uint8_t *)&length, 1); REST.set_response_payload(response, buffer, length); }
/*---------------------------------------------------------------------------*/ void monitor_parents(void) { rpl_parent_t *p; uip_ipaddr_t *dest; uint16_t temp1,temp2; //counter++; rpl_parent_t *pref_parent =(&instance_table[0])->current_dag->preferred_parent; // rpl_instance_t *instance=&instance_table[0]; temp1 = ((((&instance_table[0])->current_dag->rank)%256)*100)/256; printf("rank= %u.%u:{", (((&instance_table[0])->current_dag->rank)/256), temp1); for(p = nbr_table_head(rpl_parents); p != NULL ; p = nbr_table_next(rpl_parents, p)) { dest=rpl_get_parent_ipaddr(p); printf("("); if(p==pref_parent) printf("pref-prnt "); printf("%02x ", ((uint8_t *)dest)[15]); temp1 = ((p->link_metric%128)*100)/128; temp2 = ((p->rank%256)*100)/256; printf(" etx=%d.%2d,rank=%u.%2u)", p->link_metric/128, temp1 ,p->rank/256 , temp2); //printf("%d- etx=%d.%2d,rank=%u.%2u)", counter, p->link_metric/128, temp1 ,p->rank/256 , temp2); //printf("%d %d.%2d \n", counter, p->link_metric/128, temp1); /*PRINTF("RPL: My path ETX to the root is %u.%u\n", instance->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR, (instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR);*/ } printf("}\n"); }
/*---------------------------------------------------------------------------*/ const uip_ipaddr_t * simple_rpl_parent(void) { rpl_dag_t *dag; dag = rpl_get_any_dag(); if(dag != NULL && dag->preferred_parent != NULL) { return rpl_get_parent_ipaddr(dag->preferred_parent); } return NULL; }
/*---------------------------------------------------------------------------*/ void rpl_remove_parent(rpl_parent_t *parent) { PRINTF("RPL: Removing parent "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); PRINTF("\n"); rpl_nullify_parent(parent); nbr_table_remove(rpl_parents, parent); }
/*---------------------------------------------------------------------------*/ static void handle_probing_timer(void *ptr) { rpl_instance_t *instance = (rpl_instance_t *)ptr; rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(instance->current_dag); /* Perform probing */ if(probing_target != NULL && rpl_get_parent_ipaddr(probing_target) != NULL) { PRINTF("RPL: probing %3u\n", nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7]); /* Send probe, e.g. unicast DIO or DIS */ RPL_PROBING_SEND_FUNC(instance, rpl_get_parent_ipaddr(probing_target)); } /* Schedule next probing */ rpl_schedule_probing(instance); #if DEBUG rpl_print_neighbor_list(); #endif }
/*---------------------------------------------------------------------------*/ int rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) { int return_value; #if DEBUG rpl_rank_t old_rank; old_rank = instance->current_dag->rank; #endif /* DEBUG */ return_value = 1; if(!acceptable_rank(p->dag, p->rank)) { /* The candidate parent is no longer valid: the rank increase resulting from the choice of it as a parent would be too high. */ PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank); rpl_nullify_parent(p); if(p != instance->current_dag->preferred_parent) { return 0; } else { return_value = 0; } } if(rpl_select_dag(instance, p) == NULL) { /* No suitable parent; trigger a local repair. */ PRINTF("RPL: No parents found in any DAG\n"); rpl_local_repair(instance); return 0; } #if DEBUG if(DAG_RANK(old_rank, instance) != DAG_RANK(instance->current_dag->rank, instance)) { PRINTF("RPL: Moving in the instance from rank %hu to %hu\n", DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance)); if(instance->current_dag->rank != INFINITE_RANK) { PRINTF("RPL: The preferred parent is "); PRINT6ADDR(rpl_get_parent_ipaddr (instance->current_dag->preferred_parent)); PRINTF(" (rank %u)\n", (unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance)); } else { PRINTF("RPL: We don't have any parent"); } } #endif /* DEBUG */ return return_value; }
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { rpl_dag_t *dag; rpl_parent_t *parent; int32_t strpos = 0; const uip_ipaddr_t *addr; addr = &uip_ds6_if.addr_list[1].ipaddr; dag = rpl_get_any_dag(); parent_index = 0; if (dag != NULL) { /* seek to the parents entry and return it */ strpos += sprintf(&(buffer[strpos]),"{\"node\":\"n%x\"",addr->u8[15]); // last addr byte of mote strpos += sprintf(&(buffer[strpos]),",\"nbr\":{"); parent = nbr_table_head(rpl_parents); // addr of first neighbor while (parent != NULL) { etx_table[parent_index].nbr_addr = rpl_get_parent_ipaddr(parent)->u8[15]; etx_table[parent_index].nbr_etx = rpl_get_parent_link_metric(parent); etx_table[parent_index].p = parent; strpos += sprintf(&(buffer[strpos]),"\"n%x\":%u,",etx_table[parent_index].nbr_addr, etx_table[parent_index].nbr_etx); parent = nbr_table_next(rpl_parents, parent); parent_index++; } PRINTF("parent_index:%d\n",parent_index); } else { /* no DAG */ strpos += sprintf(&(buffer[strpos]),"{}\n"); } //PRINTF("strpos: %ld\n", strpos); //rpl_print_neighbor_list(); // get parents for debug purposes //PRINTF("buf_parents: %s\n", buffer); strpos += sprintf(&(buffer[strpos-1]),"}}\n"); //replace the last comma //PRINTF("strpos-after: %ld\n", strpos); REST.set_header_content_type(response, APPLICATION_JSON); REST.set_header_max_age(response, res_etx.periodic->period / CLOCK_SECOND); //*offset = -1; // try to fix Copper response REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%s", buffer)); /* The REST.subscription_handler() will be called for observable resources by the REST framework. */ }
void collect_common_net_print(void) { rpl_dag_t *dag; uip_ds6_route_t *r; /* Let's suppose we have only one instance */ dag = rpl_get_any_dag(); if(dag->preferred_parent != NULL) { PRINTF("Preferred parent: "); PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent)); PRINTF("\n"); } for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { PRINT6ADDR(&r->ipaddr); } PRINTF("---\n"); }
/* length of an neighbor entry, must be fixed width */ uint16_t create_parent_msg(char *buf, rpl_parent_t *parent, uint8_t preferred) { uint8_t n = 0; uip_ipaddr_t * addr = rpl_get_parent_ipaddr(parent); n += sprintf(&(buf[n]), "{\"eui\":\"%04x%04x%04x%04x\",", UIP_HTONS(addr->u16[4]), UIP_HTONS(addr->u16[5]), UIP_HTONS(addr->u16[6]), UIP_HTONS(addr->u16[7])); n += sprintf(&(buf[n]), "\"pref\":"); if(preferred == 1) { n += sprintf(&(buf[n]), "true,"); } else { n += sprintf(&(buf[n]), "false,"); } n += sprintf(&(buf[n]), "\"etx\":%d}", rpl_get_parent_link_metric(parent)); buf[n] = 0; PRINTF("buf: %s\n", buf); return n; }
void collect_common_send() { /* Send the query reply back to the sink */ rpl_parent_t *preferred_parent; rpl_dag_t *dag; query_reply_t qrpkt; dag = rpl_get_any_dag(); if(dag != NULL) { preferred_parent = dag->preferred_parent; if(preferred_parent != NULL) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_lookup(rpl_get_parent_ipaddr(preferred_parent)); if(nbr != NULL) { // Use parts of the IPv6 address as the parent address, in reversed byte order. qrpkt.parent_etx = (uint16_t)preferred_parent->link_metric + preferred_parent->rank; } } } uip_udp_packet_sendto(client_conn, &qrpkt, sizeof(qrpkt), &server_ipaddr, UIP_HTONS(UDP_SERVER_PORT)); }
/*---------------------------------------------------------------------------*/ void collect_common_send(void) { static uint8_t seqno; struct { uint8_t seqno; uint8_t for_alignment; struct collect_view_data_msg msg; } msg; /* struct collect_neighbor *n; */ uint16_t parent_etx; uint16_t rtmetric; uint16_t num_neighbors; uint16_t beacon_interval; rpl_parent_t *preferred_parent; rimeaddr_t parent; rpl_dag_t *dag; if(client_conn == NULL) { /* Not setup yet */ return; } memset(&msg, 0, sizeof(msg)); seqno++; if(seqno == 0) { /* Wrap to 128 to identify restarts */ seqno = 128; } msg.seqno = seqno; rimeaddr_copy(&parent, &rimeaddr_null); parent_etx = 0; /* Let's suppose we have only one instance */ dag = rpl_get_any_dag(); if(dag != NULL) { preferred_parent = dag->preferred_parent; if(preferred_parent != NULL) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_lookup(rpl_get_parent_ipaddr(preferred_parent)); if(nbr != NULL) { /* Use parts of the IPv6 address as the parent address, in reversed byte order. */ parent.u8[RIMEADDR_SIZE - 1] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 2]; parent.u8[RIMEADDR_SIZE - 2] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]; parent_etx = rpl_get_parent_rank((rimeaddr_t *) uip_ds6_nbr_get_ll(nbr)) / 2; } } rtmetric = dag->rank; beacon_interval = (uint16_t) ((2L << dag->instance->dio_intcurrent) / 1000); num_neighbors = RPL_PARENT_COUNT(dag); } else { rtmetric = 0; beacon_interval = 0; num_neighbors = 0; } /* num_neighbors = collect_neighbor_list_num(&tc.neighbor_list); */ collect_view_construct_message(&msg.msg, &parent, parent_etx, rtmetric, num_neighbors, beacon_interval); uip_udp_packet_sendto(client_conn, &msg, sizeof(msg), &server_ipaddr, UIP_HTONS(UDP_SERVER_PORT)); }
/*---------------------------------------------------------------------------*/ rpl_dag_t * rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) { rpl_parent_t *last_parent; rpl_dag_t *dag, *end, *best_dag; rpl_rank_t old_rank; old_rank = instance->current_dag->rank; last_parent = instance->current_dag->preferred_parent; if(instance->current_dag->rank != ROOT_RANK(instance)) { rpl_select_parent(p->dag); } best_dag = NULL; 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; } else { best_dag = instance->of->best_dag(best_dag, dag); } } } if(best_dag == NULL) { /* No parent found: the calling function handle this problem. */ return NULL; } if(instance->current_dag != best_dag) { /* Remove routes installed by DAOs. */ rpl_remove_routes(instance->current_dag); PRINTF("RPL: New preferred DAG: "); PRINT6ADDR(&best_dag->dag_id); PRINTF("\n"); if(best_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { check_prefix(&instance->current_dag->prefix_info, &best_dag->prefix_info); } else if(instance->current_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { check_prefix(&instance->current_dag->prefix_info, NULL); } best_dag->joined = 1; instance->current_dag->joined = 0; instance->current_dag = best_dag; } instance->of->update_metric_container(instance); /* Update the DAG rank. */ best_dag->rank = instance->of->calculate_rank(best_dag->preferred_parent, 0); if(last_parent == NULL || best_dag->rank < best_dag->min_rank) { best_dag->min_rank = best_dag->rank; } else if(!acceptable_rank(best_dag, best_dag->rank)) { PRINTF("RPL: New rank unacceptable!\n"); rpl_set_preferred_parent(instance->current_dag, 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, RPL_ZERO_LIFETIME); } return NULL; } if(best_dag->preferred_parent != last_parent) { rpl_set_default_route(instance, rpl_get_parent_ipaddr(best_dag->preferred_parent)); PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n", (unsigned)old_rank, best_dag->rank); RPL_STAT(rpl_stats.parent_switch++); 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, RPL_ZERO_LIFETIME); } /* The DAO parent set changed - schedule a DAO transmission. */ RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); rpl_schedule_dao(instance); } rpl_reset_dio_timer(instance); #if DEBUG rpl_print_neighbor_list(); #endif } else if(best_dag->rank != old_rank) { PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n", (unsigned)old_rank, best_dag->rank); } return best_dag; }
/*simple-udp-rpl---------------------------------------------------------------------------*/ static void receiver(struct simple_udp_connection *c, const uip_ipaddr_t *sender_addr, uint16_t sender_port, const uip_ipaddr_t *receiver_addr, uint16_t receiver_port, const uint8_t *data, uint16_t datalen) { // #ifdef WITH_LEAPFROG //for packet elimination // int leapfrog_elimination_flag = 0; // if(data[0] == LEAPFROG_DATA_HEADER){ // char tmp_lf_pc = data[1] - LEAPFROG_BEACON_OFFSET; // int tmp_sid = sender_addr->u8[15]; // char tmp_lf_an = leapfrog_elimination_id_array[tmp_sid]; // if(tmp_lf_an <= LEAPFROG_DATA_COUNTER_WIDTH){ // if(tmp_lf_pc <= tmp_lf_an || LEAPFROG_DATA_COUNTER_MAX - (LEAPFROG_DATA_COUNTER_WIDTH - tmp_lf_an ) <= tmp_lf_pc) leapfrog_elimination_flag = 1; // }else{ // if(tmp_lf_an - LEAPFROG_DATA_COUNTER_WIDTH <= tmp_lf_pc && tmp_lf_pc <= tmp_lf_an) leapfrog_elimination_flag = 1; // } // if(leapfrog_elimination_flag == 1){ // PRINTF("LEAPFROG: Elimination discard data\n"); // }else{ // PRINTF("LEAPFROG: "); // leapfrog_elimination_id_array[tmp_sid] = tmp_lf_pc; // } // } // if(leapfrog_elimination_flag != 1){ // #endif /*WITH_LEAPFROG*/ printf("DATA: received from "); uip_debug_ipaddr_print(sender_addr); printf(" on port %d from port %d with length %d: '%s'\n", receiver_port, sender_port, datalen, data); #ifdef WITH_LEAPFROG //for beaconing if(data[0] == LEAPFROG_BEACON_HEADER){ char temp_sid = 0; //sender id of packet char temp_pid = 0; //sender's parent id char temp_gid = 0; //sender's grand parent id char temp_aid = 0; //sender's alt parent id temp_sid = sender_addr->u8[15]; //get most least byte. must be modified to store whole address temp_pid = data[2] - LEAPFROG_BEACON_OFFSET; temp_gid = data[4] - LEAPFROG_BEACON_OFFSET; temp_aid = data[6] - LEAPFROG_BEACON_OFFSET; char temp_pps_num; char temp_pps_str[LEAPFROG_NUM_NEIGHBOR_NODE]; int temp_pps_itr; temp_pps_num = data[8] - LEAPFROG_BEACON_OFFSET; for(temp_pps_itr = 0; temp_pps_itr < (int)temp_pps_num; temp_pps_itr++){ //do nothing if temp_pps_num = 0 temp_pps_str[temp_pps_itr] = data[8 + 1 + temp_pps_itr]; } temp_pps_str[temp_pps_itr] = '\0'; printf("LEAPFROG: receive beacon S %d P %d GP %d AP %d PPs #%d %s\n", temp_sid, temp_pid, temp_gid, temp_aid, temp_pps_num, temp_pps_str); //judge and registor parent, grandparent, alt parent uip_ipaddr_t * addr; #ifdef WITH_LEAPFROG_TSCH char my_id = 0; addr = &uip_ds6_if.addr_list[2].ipaddr; //get own ID. [2] seems to be default if(addr != NULL){ my_id = addr->u8[15]; } #endif //WITH_LEAPFROG_TSCH addr = rpl_get_parent_ipaddr(default_instance->current_dag->preferred_parent); if(addr != NULL){ char my_pid = addr->u8[15]; // if(leapfrog_parent_id == 0){ //registor parent // leapfrog_parent_id = my_pid; // }else //new parent and reset P, GP, AP if(leapfrog_parent_id != my_pid){ //new parent and reset P, GP, AP leapfrog_parent_id = my_pid; leapfrog_grand_parent_id = 0; leapfrog_alt_parent_id = 0; printf("LEAPFROG: reset P GP AP\n"); } //judge Grand Parent if(leapfrog_parent_id > 0 && leapfrog_parent_id == my_pid){ //judge Grand Parent if(temp_sid == my_pid){ if(temp_pid > 0 && temp_pid != my_pid){ leapfrog_grand_parent_id = temp_pid; //get grand parent } } } //judge Alternate Parent if(leapfrog_grand_parent_id > 0 && temp_pid > 0 && leapfrog_grand_parent_id == temp_pid && leapfrog_parent_id != temp_sid){ //judge Alt Parent if(leapfrog_alt_parent_id != temp_sid){ leapfrog_alt_parent_id = temp_sid; //get alt parent #ifdef WITH_LEAPFROG_TSCH //add unicast tx link to AP based on own(child) ID linkaddr_copy(&alt_parent_linkaddr, packetbuf_addr(PACKETBUF_ADDR_SENDER)); //alt_parent_linkaddr.u8[7] = leapfrog_alt_parent_id; //for tsch //printf("LEAPFROG-TSCH: update AP %d %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", // leapfrog_alt_parent_id, // alt_parent_linkaddr.u8[0], // alt_parent_linkaddr.u8[1], // alt_parent_linkaddr.u8[2], // alt_parent_linkaddr.u8[3], // alt_parent_linkaddr.u8[4], // alt_parent_linkaddr.u8[5], // alt_parent_linkaddr.u8[6], // alt_parent_linkaddr.u8[7]); printf("LEAPFROG-TSCH: update alt tx normally -> AP %d\n", leapfrog_alt_parent_id); orchestra_leapfrog_add_uc_tx_link(leapfrog_alt_parent_id); #endif /*WITH_LEAPFROG_TSCH*/ } }else{ //judge Alternate Parent by Possible Parent if(my_pid != temp_sid){ for(temp_pps_itr = 0; temp_pps_itr < (int)temp_pps_num; temp_pps_itr++){ //do nothing if temp_pps_num = 0 if(leapfrog_grand_parent_id == data[8 + 1 + temp_pps_itr] - LEAPFROG_BEACON_OFFSET){ leapfrog_alt_parent_id = temp_sid; #ifdef WITH_LEAPFROG_TSCH linkaddr_copy(&alt_parent_linkaddr, packetbuf_addr(PACKETBUF_ADDR_SENDER)); printf("LEAPFROG-TSCH: update alt tx by PP -> AP %d\n", leapfrog_alt_parent_id); orchestra_leapfrog_add_uc_tx_link(leapfrog_alt_parent_id); #endif //WITH_LEAPFROG_TSCH break; } } } } for(temp_pps_itr = 0; temp_pps_itr < leapfrog_possible_parent_num; temp_pps_itr++){ temp_pps_str[temp_pps_itr] = leapfrog_possible_parent_id_array[temp_pps_itr] + LEAPFROG_BEACON_OFFSET; } temp_pps_str[temp_pps_itr] = '\0'; printf("LEAPFROG: own P %d GP %d AP %d PPs #%d %s\n", leapfrog_parent_id, leapfrog_grand_parent_id, leapfrog_alt_parent_id, leapfrog_possible_parent_num, temp_pps_str); //judge I am sender's Alt Parent and prepare Rx link for alt child #ifdef WITH_LEAPFROG_TSCH //judge I am sender's Alt Parent if(temp_aid != 0 && my_id == temp_aid){ printf("LEAPFROG-TSCH: update rx s <- (alt)C %d\n", temp_sid); orchestra_leapfrog_add_uc_rx_link(temp_sid); } #endif /*WITH_LEAPFROG_TSCH*/ } } // }else{ // //receiving processes is skipped because of elimination // } #endif /*WITH_LEAPFROG*/ }
/*---------------------------------------------------------------------------*/ static void sendpacket(int mode) { static uip_ipaddr_t *parent_ipaddr=NULL,tempadd; static rpl_dag_t *current_dag=NULL; static int i=0; static rpl_instance_t * instance_id=NULL; for(i = 0; i < RPL_MAX_INSTANCES; ++i) { if(instance_table[i].used && instance_table[i].current_dag->joined) { current_dag = instance_table[i].current_dag; instance_id = &instance_table[i]; break; } } if(current_dag != NULL) { parent_ipaddr=rpl_get_parent_ipaddr(current_dag->preferred_parent); }else return; //if current dag is null return if(!parent_ipaddr->u8[15])// if parent is null return return; uip_ds6_nbr_t *nbr=NULL; int num = uip_ds6_nbr_num(); int sizeof_buf = sizeof(int) + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(int) + sizeof(uint16_t) +sizeof(uint8_t) + sizeof(uint16_t)+ sizeof(int) + num * ( sizeof(uint8_t) + sizeof(uint16_t) ); // code + node + id_of_intermediate + msg_instance + own rank + parent + rank + numof_nbr*(nbr+rank) unsigned char buf[sizeof_buf]; unsigned char * buf_p = buf; i=2;myrank=current_dag->rank; MAPPER_ADD_PACKETDATA(buf_p, i); MAPPER_ADD_PACKETDATA(buf_p, myip.u8[15]); if(mode) //for first time setting msg_instance = 100*myip.u8[15]; MAPPER_ADD_PACKETDATA(buf_p, myip.u8[15]); //added to track limited boradcasting intermediate node id MAPPER_ADD_PACKETDATA(buf_p, msg_instance); //added to track limited boradcasting msg_instance++; MAPPER_ADD_PACKETDATA(buf_p, current_dag->rank); MAPPER_ADD_PACKETDATA(buf_p, parent_ipaddr->u8[15]); MAPPER_ADD_PACKETDATA(buf_p, current_dag->preferred_parent->rank); MAPPER_ADD_PACKETDATA(buf_p, num); printf(" %02x R %u P %u PR %u Bufsize %d msg_instance %d ",myip.u8[15],current_dag->rank,parent_ipaddr->u8[15],current_dag->preferred_parent->rank, sizeof_buf, msg_instance-1); num_nbrs=0; rpl_parent_t *p=NULL; for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { //p=find_parent_any_dag_any_instance(&nbr->ipaddr); p=rpl_find_parent_any_dag(instance_id, &nbr->ipaddr); MAPPER_ADD_PACKETDATA(buf_p,nbr->ipaddr.u8[15]); //rank = rpl_get_parent_rank(uip_ds6_nbr_get_ll(nbr)); MAPPER_ADD_PACKETDATA(buf_p,p->rank); printf("No of nbrs %d : %02x rank %u ",num,nbr->ipaddr.u8[15],p->rank); nbrs[num_nbrs]=nbr->ipaddr.u8[15]; num_nbrs++; } printf("\n"); if(mode) { uip_udp_packet_sendto(client_conn, buf, sizeof(buf), &server_ipaddr, UIP_HTONS(2345)); uip_create_unspecified(&client_conn->ripaddr); parent_change=0; printf("parent change info send via unicast 6BR\n"); } else { //uip_udp_packet_sendto(client_conn, buf, sizeof(buf), &server_ipaddr, UIP_HTONS(2345));//temporaryly aadded //uip_create_unspecified(&client_conn->ripaddr); //send_broadcast(buf,sizeof(buf)); ///* //uip_create_unspecified(&udp_bconn->ripaddr); int j=0; for(i=0,j=0;i<=num_nbrs*3;i++,j=0) for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { uip_ipaddr_copy(&tempadd, &nbr->ipaddr); j++; if(nbr->ipaddr.u8[15]!=myip.u8[15] && i==j){ uip_udp_packet_sendto(client_conn, buf, sizeof(buf), &tempadd, UIP_HTONS(10000+(int)tempadd.u8[15])); printf("send to %u \n",tempadd.u8[15]); uip_create_unspecified(&client_conn->ripaddr); } } printf("parent change info send via broadcast 6BR\n"); } }
/*void start_no_data_timer() { etimer_set(&bad_etx_timer, NO_DATA_PERIOD); } void stop_no_data_timer(){ etimer_stop(&bad_etx_timer); }*/ void eventhandler(process_event_t ev, process_data_t data) { switch (ev) { case PARENT_UNREACHABLE: { instance = &instance_table[0]; dag = instance->current_dag; if (dag->preferred_parent != NULL) { p = dag->preferred_parent; PRINT6ADDR(rpl_get_parent_ipaddr(p)); } else { PRINTF("NULL"); } PRINTF("\n"); if (test_unreachable == 1 && hand_off_backoff_flag == 0) { PRINTF("Connection unstable\n"); reliable = 0; if (wait_dio_flag == 0) { PRINTF("Sending DIS to current parent\n"); dis_output(rpl_get_parent_ipaddr(p), 1, 0, 0, 0); /* Send DIS to assess parent */ wait_dio_flag = 1; /* * Wait DIO reply. If parent doesn't reply until timer finishes, * he's considered unreachable. */ etimer_set(&dio_check, WAIT_DIO); } else { etimer_set(&dio_check, WAIT_DIO); } } } break; case PARENT_REACHABLE: { uint8_t *dis_rssi; /* We received the DIO reply from parent but we need to check the RSSI value */ dis_rssi = data; rssi = dis_rssi - 45; if (dis_rssi > 200) { rssi = dis_rssi - 255 - 46; } PRINTF("RSSI response from parent = %d ->", rssi); if (rssi <= -85) { PRINTF(" Unreliable\n"); mobility_flag = 1; leds_on(LEDS_ALL); current_t = clock_time() * 1000 / CLOCK_SECOND; PRINTF("%u\n", current_t); dis_output(NULL, 1, counter, 0, 0); rpl_dis_burst(); } else { PRINTF(" Reliable\n"); reliable = 1; process_post(&tcpip_process, RESET_MOBILITY_FLAG, NULL); } } break; case DIS_BURST: { etimer_reset(&dis_timer); } break; /* DIO received when checking current parent, stop the timer */ case STOP_DIO_CHECK: { printf("stopping DIO CHECK\n"); etimer_stop(&dio_check); etimer_stop(&dis_timer); } break; case PROCESS_EVENT_TIMER: { /* Current parent Unreachable/Unreliable, print current time and start DIS_BURST */ if (data == &dio_check && etimer_expired(&dio_check) && !reliable && test_unreachable == 1) { mobility_flag = 1; if (dis_burst_flag == 0) { dis_burst_flag++; current_t = clock_time() * 1000 / CLOCK_SECOND; printf("Start %u\n", current_t); dis_output(NULL, 1, counter, 0, 0); etimer_set(&dis_timer, SEND_TIME); } else { rpl_dis_burst(); } } /* 1st DIS was sent above. Check for the backoff delay and keep sending (Total = 3DIS) */ if (data == &dis_timer && etimer_expired(&dis_timer)) { counter++; dis_output(NULL, 1, counter, 0, 0); if (counter < 3) { etimer_reset(&dis_timer); } else { counter = 1; dis_burst_flag = 0; } } }break; } }
/*-----------------------------------------------------------*/ static void neighbor_link_callback(rpl_parent_t *p, int status, int numtx) { uint16_t recorded_etx = p->link_metric; uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR; uint16_t new_etx; uip_ipaddr_t *dest; dest=rpl_get_parent_ipaddr(p); unsigned int test; //elnaz unsigned long delta; rpl_parent_t * pref; //elnaz /* Do not penalize the ETX when collisions or transmission errors occur. */ p->msg_num++; p->retransmission_num = p->retransmission_num + numtx; if(set_tx_flag_char==1) { retransmission_num = retransmission_num + numtx; return; } if(status == MAC_TX_OK || status == MAC_TX_NOACK) { if(status == MAC_TX_NOACK) { packet_etx = MAX_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; //printf("no ack %02x%02x \n",((uint8_t *)dest)[14], ((uint8_t *)dest)[15]); } dest=rpl_get_parent_ipaddr(p); //printf("numtx=%d ADDR=%02x%02x \n", numtx, ((uint8_t *)dest)[14], ((uint8_t *)dest)[15]); new_etx = ((uint32_t)recorded_etx * ETX_ALPHA + (uint32_t)packet_etx * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE; PRINTF("RPL: ETX changed from %u to %u (packet ETX = %u)\n", (unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR), (unsigned)(new_etx / RPL_DAG_MC_ETX_DIVISOR), (unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR)); p->link_metric = new_etx; //elnaz //----------------------- PROBE if(start_flag==1) {last_probe_time=clock_seconds(); start_flag=0; set_ETX_th();} //test = PROBE_NUM_THRESHOLD * PROBE_INTERVAL * 2; //printf("%lu , test= %d, delta=%d ", (clock_seconds()-last_probe_time), test, (PROBE_NUM_THRESHOLD * PROBE_INTERVAL * 2) ); pref = p->dag->preferred_parent; if((p->link_metric)>ETX_THERESHOLD && p==pref) { printf("pass threshhold ADDR=%02x etx=%u th=%u\n", ((uint8_t *)dest)[15],p->link_metric,ETX_THERESHOLD); delta = (clock_seconds()-last_probe_time); //printf("t=%lu , %lu,%lu, %lu \n",delta, delta*CLOCK_SECOND, 120, 120*CLOCK_SECOND); if(delta>(wait*60)) { //printf("pass time constraint"); wait=5; if(etx_flag==1) { ETX_THERESHOLD = pref->link_metric; etx_flag=0; printf("adjust etx-th \n"); } else if(rpl_pt_parents(0)==1) { last_probe_time=clock_seconds(); printf("update time\n"); //steps=0; } } // if(delta>=) else { /*steps++; if(steps==11) { adjust_ETX_th(p->link_metric); steps=0; }*/ //steps=0; //printf("not if"); } } } else { printf("error ADDR= %02x%02x \n",((uint8_t *)dest)[14], ((uint8_t *)dest)[15]); } monitor_parents(); }
char rpl_pt_parents(char set_tx) { rpl_parent_t *p; struct ip_addr_list_struct test; uip_ipaddr_t *dest; unsigned long age; int timer;// jitter; rpl_rank_t srank; rpl_parent_t * pref_parent; /*if(flag==0) { flag=1; memb_init(&pt_prnt_mem); list_init(ip_addr_list); }*/ pt_parents[0].rank=INFINITE_RANK; pt_parents[0].ipaddr=NULL; pt_parents[1]=pt_parents[0]; pt_parents[2]=pt_parents[1]; //printf("\nP_T={"); //printf("rank= %u:{", (((&instance_table[0])->current_dag->rank)/256)); pref_parent =(&instance_table[0])->current_dag->preferred_parent; p = nbr_table_head(rpl_parents); srank = p->dag->rank; for( ;p != NULL;p = nbr_table_next(rpl_parents, p)) { if(set_tx==1) { p->retransmission_num = 0; p->msg_num = 0; } if(p==pref_parent) {continue;} dest=rpl_get_parent_ipaddr(p); age = (clock_seconds()-(p->update_time))/2000; printf("prnt rssi=%d,rank=%u\n",p->rssi, p->rank); if(p->rssi > RSSI_THRESHOLD && (p->rank)<srank)// age<AGE_THRESHOLD && { if(p->rank < pt_parents[0].rank) { test=pt_parents[1]; pt_parents[1]=pt_parents[0]; pt_parents[2]=test; pt_parents[0].rank=p->rank; pt_parents[0].ipaddr=dest; continue; } if(p->rank < pt_parents[1].rank) { pt_parents[2]=pt_parents[1]; pt_parents[1].rank=p->rank; pt_parents[1].ipaddr=dest; continue; } if(p->rank < pt_parents[2].rank) { pt_parents[2].rank= p->rank; pt_parents[2].ipaddr= dest; } } } printf("P_T={%02x, %02x, %02x}\n",((uint8_t *)pt_parents[0].ipaddr)[15],((uint8_t *)pt_parents[1].ipaddr)[15],((uint8_t *)pt_parents[2].ipaddr)[15]); if(pt_parents[0].rank!=INFINITE_RANK) { timer = (PROBE_INTERVAL * CLOCK_SECOND); //timer += (random_rand()*CLOCK_SECOND)/RANDOM_RAND_MAX; ctimer_set(&probe_timer, timer, &handle_probe_timer, pt_parents); } else { //printf("there is no pt_pref_prnt\n"); return 0; } return 1; }
/*---------------------------------------------------------------------------*/ static void res_rpl_info_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /*Return RPL information in JSON format */ uint16_t length = 0; rpl_instance_t *instance; uip_ds6_nbr_t *nbr; char message[REST_MAX_CHUNK_SIZE]; memset(message, 0, sizeof(message)); instance = rpl_get_instance(RPL_DEFAULT_INSTANCE); if(instance != NULL && instance->current_dag != NULL && instance->current_dag->preferred_parent != NULL) { nbr = rpl_get_nbr(instance->current_dag->preferred_parent); } else { nbr = NULL; } /* Write all RPL info in JSON format */ snprintf(message, sizeof(message) - 1, "{\"parent\":\""); length = strlen(message); if(instance != NULL && instance->current_dag != NULL && instance->current_dag->preferred_parent != NULL) { sprint_addr6(&message[length], rpl_get_parent_ipaddr(instance->current_dag->preferred_parent)); length = strlen(message); snprintf(&message[length], sizeof(message) - length - 1, "\""); } else { snprintf(&message[length], sizeof(message) - length - 1, "None\""); } length = strlen(message); snprintf(&message[length], sizeof(message) - length - 1, " ,\"rank\":\""); length = strlen(message); if(instance != NULL && instance->current_dag != NULL) { snprintf(&message[length], sizeof(message) - length - 1, "%u.%02u\"", (instance->current_dag->rank / RPL_DAG_MC_ETX_DIVISOR), (100 * (instance->current_dag->rank % RPL_DAG_MC_ETX_DIVISOR)) / RPL_DAG_MC_ETX_DIVISOR); } else { snprintf(&message[length], sizeof(message) - length - 1, "inf\""); } length = strlen(message); snprintf(&message[length], sizeof(message) - length - 1, " ,\"link-metric\":\""); length = strlen(message); if(nbr != NULL) { snprintf(&message[length], sizeof(message) - length - 1, "%u.%02u\"", nbr->link_metric / RPL_DAG_MC_ETX_DIVISOR, (100 * (nbr->link_metric % RPL_DAG_MC_ETX_DIVISOR)) / RPL_DAG_MC_ETX_DIVISOR); } else { snprintf(&message[length], sizeof(message) - length - 1, "inf\""); } length = strlen(message); snprintf(&message[length], sizeof(message) - length - 1, "}"); length = strlen(message); memcpy(buffer, message, length); REST.set_header_content_type(response, REST.type.APPLICATION_JSON); REST.set_header_etag(response, (uint8_t *)&length, 1); REST.set_response_payload(response, buffer, length); }