/*---------------------------------------------------------------------------*/ PROCESS_THREAD(udp_server_process, ev, data) { uip_ipaddr_t ipaddr; struct uip_ds6_addr *root_if; PROCESS_BEGIN(); PROCESS_PAUSE(); SENSORS_ACTIVATE(button_sensor); PRINTF("UDP server started\n"); #if UIP_CONF_ROUTER uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); /* uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); */ uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL); root_if = uip_ds6_addr_lookup(&ipaddr); if(root_if != NULL) { rpl_dag_t *dag; rpl_set_root((uip_ip6addr_t *)&ipaddr); dag = rpl_get_dag(RPL_ANY_INSTANCE); uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("created a new RPL dag\n"); } else { PRINTF("failed to create a new RPL DAG\n"); } #endif /* UIP_CONF_ROUTER */ print_local_addresses(); /* The data sink runs with a 100% duty cycle in order to ensure high packet reception rates. */ NETSTACK_RDC.off(1); server_conn = udp_new(NULL, UIP_HTONS(UDP_CLIENT_PORT), NULL); udp_bind(server_conn, UIP_HTONS(UDP_SERVER_PORT)); PRINTF("Created a server connection with remote address "); PRINT6ADDR(&server_conn->ripaddr); PRINTF(" local/remote port %u/%u\n", UIP_HTONS(server_conn->lport), UIP_HTONS(server_conn->rport)); while(1) { PROCESS_YIELD(); if(ev == tcpip_event) { tcpip_handler(); } else if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiaing global repair\n"); rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); } } PROCESS_END(); }
void rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr) { rpl_dag_t *dag; rpl_parent_t *p; /* This only handles one DODAG - if multiple we need to check all */ dag = rpl_get_dag(RPL_ANY_INSTANCE); if(dag == NULL) { return; } /* if this is our default route then clean the dag->def_route state */ if(dag->def_route != NULL && uip_ipaddr_cmp(&dag->def_route->ipaddr, &nbr->ipaddr)) { dag->def_route = NULL; } if(!nbr->isused) { PRINTF("RPL: Removing neighbor "); PRINT6ADDR(&nbr->ipaddr); PRINTF("\n"); p = rpl_find_parent(dag, &nbr->ipaddr); if(p != NULL) { p->rank = INFINITE_RANK; /* Trigger DAG rank recalculation. */ p->updated = 1; } } }
void rpl_recalculate_ranks(void) { rpl_dag_t *dag; rpl_parent_t *p; /* * We recalculate ranks when we receive feedback from the system rather * than RPL protocol messages. This periodical recalculation is called * from a timer in order to keep the stack depth reasonably low. */ dag = rpl_get_dag(RPL_ANY_INSTANCE); if(dag != NULL) { for(p = list_head(dag->parents); p != NULL; p = p->next) { if(p->updated) { p->updated = 0; rpl_process_parent_event(dag, p); /* * Stop calculating here because the parent list may have changed. * If more ranks need to be recalculated, it will be taken care of * in subsequent calls to this functions. */ break; } } } }
rpl_dag_t * rpl_set_root(uip_ipaddr_t *dag_id) { rpl_dag_t *dag; int version; version = -1; dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); if(dag != NULL) { PRINTF("RPL: Dropping a joined DAG when setting this node as root"); version = dag->version; rpl_free_dag(dag); } dag = rpl_alloc_dag(RPL_DEFAULT_INSTANCE); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG\n"); return NULL; } dag->joined = 1; dag->version = version + 1; dag->grounded = RPL_GROUNDED; dag->mop = RPL_MOP_DEFAULT; dag->of = &RPL_OF; dag->preferred_parent = NULL; dag->dtsn_out = 1; /* Trigger DAOs from the beginning. */ memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id)); dag->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; dag->dio_intmin = DEFAULT_DIO_INTERVAL_MIN; dag->dio_redundancy = DEFAULT_DIO_REDUNDANCY; dag->max_rankinc = DEFAULT_MAX_RANKINC; dag->min_hoprankinc = DEFAULT_MIN_HOPRANKINC; dag->default_lifetime = RPL_DEFAULT_LIFETIME; dag->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; dag->rank = ROOT_RANK(dag); dag->of->update_metric_container(dag); PRINTF("RPL: Node set to be a DAG root with DAG ID "); PRINT6ADDR(&dag->dag_id); PRINTF("\n"); ANNOTATE("#A root=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]); rpl_reset_dio_timer(dag, 1); return dag; }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { static struct etimer et; rpl_dag_t *dag; PROCESS_BEGIN(); prefix_set = 0; PROCESS_PAUSE(); #if WEBSERVER process_start(&webserver_nogui_process, NULL); #endif //SENSORS_ACTIVATE(button_sensor); PRINTF("RPL-Border router started\n"); /* Request prefix until it has been received */ while(!prefix_set) { etimer_set(&et, CLOCK_SECOND); request_prefix(); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); } dag = rpl_set_root((uip_ip6addr_t *)dag_id); if(dag != NULL) { rpl_set_prefix(dag, &prefix, 64); PRINTF("created a new RPL dag\n"); } #if DEBUG || 1 print_local_addresses(); #endif /* The border router runs with a 100% duty cycle in order to ensure high packet reception rates. */ NETSTACK_MAC.off(1); static struct etimer t; etimer_set(&t, 10*CLOCK_SECOND); while(1) { PROCESS_YIELD(); //if (ev == sensors_event && data == &button_sensor) { if (etimer_expired(&t)) { PRINTF("Initiating global repair\n"); rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); etimer_reset(&t); } } PROCESS_END(); }
static void handle_periodic_timer(void *ptr) { rpl_purge_routes(); rpl_recalculate_ranks(); /* handle DIS */ #ifdef RPL_DIS_SEND next_dis++; if(rpl_get_dag(RPL_ANY_INSTANCE) == NULL && next_dis >= RPL_DIS_INTERVAL) { next_dis = 0; dis_output(NULL); } #endif ctimer_reset(&periodic_timer); }
static void rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) { uip_ipaddr_t ipaddr; rpl_dag_t *dag; rpl_parent_t *parent; uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr); PRINTF("RPL: Neighbor "); PRINT6ADDR(&ipaddr); PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx)); dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); if(dag == NULL) { return; } parent = rpl_find_parent(dag, &ipaddr); if(parent == NULL) { if(!known) { PRINTF("RPL: Deleting routes installed by DAOs received from "); PRINT6ADDR(&ipaddr); PRINTF("\n"); uip_ds6_route_rm_by_nexthop(&ipaddr); } return; } /* Trigger DAG rank recalculation. */ parent->updated = 1; parent->link_metric = etx; if(dag->of->parent_state_callback != NULL) { dag->of->parent_state_callback(parent, known, etx); } if(!known) { PRINTF("RPL: Removing parent "); PRINT6ADDR(&parent->addr); PRINTF(" because of bad connectivity (ETX %d)\n", etx); parent->rank = INFINITE_RANK; } }
/*---------------------------------------------------------------------------*/ static void create_rpl_dag(uip_ipaddr_t *ipaddr) { struct uip_ds6_addr *root_if; root_if = uip_ds6_addr_lookup(ipaddr); if(root_if != NULL) { rpl_dag_t *dag; uip_ipaddr_t prefix; rpl_set_root(ipaddr); dag = rpl_get_dag(RPL_ANY_INSTANCE); uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &prefix, 64); PRINTF("created a new RPL dag\n"); } else { PRINTF("failed to create a new RPL DAG\n"); } }
void collect_common_net_print(void) { rpl_dag_t *dag; int i; dag = rpl_get_dag(RPL_ANY_INSTANCE); if(dag->preferred_parent != NULL) { PRINTF("Preferred parent: "); PRINT6ADDR(&dag->preferred_parent->addr); PRINTF("\n"); } PRINTF("Route entries:\n"); for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { if(uip_ds6_routing_table[i].isused) { PRINT6ADDR(&uip_ds6_routing_table[i].ipaddr); PRINTF("\n"); } } PRINTF("---\n"); }
void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { rpl_dag_t *dag; rpl_parent_t *p; if(dio->mop != RPL_MOP_DEFAULT) { PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop); return; } // LVD 24/03/2011 instanceID = dio->instance_id; dag = rpl_get_dag(dio->instance_id); if(dag == NULL) { /* Join the first possible DAG of this RPL instance. */ if(dio->rank != INFINITE_RANK) { join_dag(from, dio); } else { PRINTF("RPL: Ignoring DIO from node with infinite rank: "); PRINT6ADDR(from); PRINTF("\n"); } return; } if(memcmp(&dag->dag_id, &dio->dag_id, sizeof(dag->dag_id))) { PRINTF("RPL: Ignoring DIO for another DAG within our instance\n"); return; } if(dio->version > dag->version) { if(dag->rank == ROOT_RANK(dag)) { PRINTF("RPL: Root received inconsistent DIO version number\n"); dag->version = dio->version + 1; rpl_reset_dio_timer(dag, 1); } else { global_repair(from, dag, dio); } return; } else if(dio->version < dag->version) { /* Inconsistency detected - someone is still on old version */ PRINTF("RPL: old version received => inconsistency detected\n"); rpl_reset_dio_timer(dag, 1); return; } if(dio->rank == INFINITE_RANK) { rpl_reset_dio_timer(dag, 1); } else if(dio->rank < ROOT_RANK(dag)) { PRINTF("RPL: Ignoring DIO with too low rank: %u\n", (unsigned)dio->rank); return; } if(dag->rank == ROOT_RANK(dag)) { if(dio->rank != INFINITE_RANK) { dag->dio_counter++; } return; } /* * At this point, we know that this DIO pertains to a DAG that * we are already part of. We consider the sender of the DIO to be * a candidate parent, and let rpl_process_parent_event decide * whether to keep it in the set. */ p = rpl_find_parent(dag, from); if(p == NULL) { if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS) { /* Make room for a new parent. */ remove_worst_parent(dag, dio->rank); } /* Add the DIO sender as a candidate parent. */ p = rpl_add_parent(dag, dio, from); if(p == NULL) { PRINTF("RPL: Failed to add a new parent ("); PRINT6ADDR(from); PRINTF(")\n"); return; } PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank); PRINT6ADDR(from); PRINTF("\n"); } else if(DAG_RANK(p->rank, dag) == DAG_RANK(dio->rank, dag)) { PRINTF("RPL: Received consistent DIO\n"); dag->dio_counter++; } /* We have allocated a candidate parent; process the DIO further. */ memcpy(&p->mc, &dio->mc, sizeof(p->mc)); p->rank = dio->rank; if(rpl_process_parent_event(dag, p) == 0) { /* The candidate parent no longer exists. */ return; } if(should_send_dao(dag, dio, p)) { rpl_schedule_dao(dag); } p->dtsn = dio->dtsn; }
/*---------------------------------------------------------------------------*/ 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; dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); if(dag != NULL) { preferred_parent = dag->preferred_parent; if(preferred_parent != NULL) { uip_ds6_nbr_t *nbr; nbr = uip_ds6_nbr_lookup(&preferred_parent->addr); 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 = neighbor_info_get_metric((rimeaddr_t *) &nbr->lladdr) / 2; } } rtmetric = dag->rank; beacon_interval = (uint16_t) ((2L << dag->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)); }