/*---------------------------------------------------------------------------*/ void simple_rpl_global_repair(void) { if(rpl_repair_root(RPL_DEFAULT_INSTANCE)) { printf("\r\nsimple_rpl_global_repair: started global repair\n"); } else { printf("\r\nsimple_rpl_global_repair: failed to start global repair\n"); } }
/*---------------------------------------------------------------------------*/ 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, UIP_DS6_DEFAULT_PREFIX, 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; dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 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("Initiating global repair\n"); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(rplreset(struct httpd_state *s, char *ptr)) { PSOCK_BEGIN(&s->sout); if(rpl_repair_root(RPL_DEFAULT_INSTANCE)) { PSOCK_SEND_STR(&s->sout, "Initiating global repair of RPL network..."); } else { PSOCK_SEND_STR(&s->sout, "Could not start global network repair"); } PSOCK_END(&s->sout); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { static struct etimer et; PROCESS_BEGIN(); /* While waiting for the prefix to be sent through the SLIP connection, the future * border router can join an existing DAG as a parent or child, or acquire a default * router that will later take precedence over the SLIP fallback interface. * Prevent that by turning the radio off until we are initialized as a DAG root. */ prefix_set = 0; NETSTACK_MAC.off(0); PROCESS_PAUSE(); SENSORS_ACTIVATE(button_sensor); PRINTF("RPL-Border router started\n"); #if 0 /* The border router runs with a 100% duty cycle in order to ensure high packet reception rates. Note if the MAC RDC is not turned off now, aggressive power management of the cpu will interfere with establishing the SLIP connection */ NETSTACK_MAC.off(1); #endif /* Request prefix until it has been received */ while(!prefix_set) { etimer_set(&et, CLOCK_SECOND); request_prefix(); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); } /* Now turn the radio on, but disable radio duty cycling. * Since we are the DAG root, reception delays would constrain mesh throughbut. */ NETSTACK_MAC.off(1); #if DEBUG || 1 print_local_addresses(); #endif PRINTF("UIP_CONF_TCP_MSS %u \n",UIP_CONF_TCP_MSS); while(1) { PROCESS_YIELD(); if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiating global repair\n"); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } PROCESS_END(); }
PROCESS_THREAD(reset_process, ev, data) { PROCESS_BEGIN(); printf("Reset started\n"); SENSORS_ACTIVATE(button_sensor); while(1) { PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event && data == &button_sensor); printf("*** REPAIRING RPL ROOT\n"); rpl_repair_root(RPL_DEFAULT_INSTANCE); } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { PROCESS_BEGIN(); uip_ipaddr_t ipaddr; /* While waiting for the prefix to be sent through the SLIP connection, the future * border router can join an existing DAG as a parent or child, or acquire a default * router that will later take precedence over the SLIP fallback interface. * Prevent that by turning the radio off until we are initialized as a DAG root. */ prefix_set = 0; NETSTACK_MAC.off(0); PROCESS_PAUSE(); SENSORS_ACTIVATE(button_sensor); leds_init(); ip64_init(); PRINTF("RPL-Border router started\n"); #if 0 /* The border router runs with a 100% duty cycle in order to ensure high packet reception rates. Note if the MAC RDC is not turned off now, aggressive power management of the cpu will interfere with establishing the SLIP connection */ NETSTACK_MAC.off(1); #endif /* Now turn the radio on, but disable radio duty cycling. * Since we are the DAG root, reception delays would constrain mesh throughbut. */ NETSTACK_MAC.off(1); /* Derived from link local (MAC) address */ uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); set_prefix_64(&ipaddr); print_local_addresses(); while(1) { PROCESS_YIELD(); leds_on(LEDS_YELLOW); if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiating global repair\n"); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ int border_router_cmd_handler(const uint8_t *data, int len) { /* handle global repair, etc here */ if(data[0] == '!') { PRINTF("Got configuration message of type %c\n", data[1]); if(data[1] == 'G') { /* This is supposed to be from stdin */ printf("Performing Global Repair...\n"); rpl_repair_root(RPL_DEFAULT_INSTANCE); return 1; } else if(data[1] == 'M') { /* We need to know that this is from the slip-radio here. */ PRINTF("Setting MAC address\n"); border_router_set_mac(&data[2]); return 1; } else if(data[1] == 'C') { /* We need to know that this is from the slip-radio here. */ printf("Channel is:%d\n", data[2]); return 1; } else if(data[1] == 'R') { /* We need to know that this is from the slip-radio here. */ PRINTF("Packet data report for sid:%d st:%d tx:%d\n", data[2], data[3], data[4]); packet_sent(data[2], data[3], data[4]); return 1; } else if(data[1] == 'D') { /* We need to know that this is from the slip-radio here... */ PRINTF("Sensor data received\n"); border_router_set_sensors((const char *)&data[2], len - 2); return 1; } } else if(data[0] == '?') { PRINTF("Got request message of type %c\n", data[1]); if(data[1] == 'M') { uint8_t buf[20]; char* hexchar = "0123456789abcdef"; int j; /* this is just a test so far... just to see if it works */ buf[0] = '!'; buf[1] = 'M'; for(j = 0; j < 8; j++) { buf[2 + j * 2] = hexchar[uip_lladdr.addr[j] >> 4]; buf[3 + j * 2] = hexchar[uip_lladdr.addr[j] & 15]; } cmd_send(buf, 18); return 1; } else if(data[1] == 'C') {
/*---------------------------------------------------------------------------*/ static void net_init(uip_ipaddr_t *br_prefix) { uip_ipaddr_t global_ipaddr; if(br_prefix) { /* We are RPL root. Will be set automatically as TSCH pan coordinator via the tsch-rpl module */ memcpy(&global_ipaddr, br_prefix, 16); uip_ds6_set_addr_iid(&global_ipaddr, &uip_lladdr); uip_ds6_addr_add(&global_ipaddr, 0, ADDR_AUTOCONF); rpl_set_root(RPL_DEFAULT_INSTANCE, &global_ipaddr); rpl_set_prefix(rpl_get_any_dag(), br_prefix, 64); rpl_repair_root(RPL_DEFAULT_INSTANCE); } NETSTACK_MAC.on(); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { static struct etimer et; rpl_dag_t *dag; PROCESS_BEGIN(); prefix_set = 0; PROCESS_PAUSE(); 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(RPL_DEFAULT_INSTANCE,(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); while(1) { PROCESS_YIELD(); if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiating global repair\n"); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } PROCESS_END(); }
void cetic_6lbr_set_prefix(uip_ipaddr_t * prefix, unsigned len, uip_ipaddr_t * ipaddr) { #if CETIC_6LBR_SMARTBRIDGE int new_prefix = cetic_dag != NULL && !uip_ipaddr_prefixcmp(&cetic_dag->prefix_info.prefix, prefix, len); if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) { LOG6LBR_DEBUG("Ignoring RA\n"); return; } LOG6LBR_INFO("CETIC_BRIDGE : set_prefix\n"); if(cetic_dag != NULL) { rpl_set_prefix(cetic_dag, prefix, len); uip_ipaddr_copy(&wsn_net_prefix, prefix); wsn_net_prefix_len = len; if(new_prefix) { LOG6LBR_6ADDR(INFO, prefix, "Setting DAG prefix : "); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } #endif }
int rpl_verify_header(int uip_ext_opt_offset) { rpl_instance_t *instance; int down; uint8_t sender_closer; uip_ds6_route_t *route; if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { PRINTF("RPL: Bad header option! (wrong length)\n"); return 1; } instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); if(instance == NULL) { PRINTF("RPL: Unknown instance: %u\n", UIP_EXT_HDR_OPT_RPL_BUF->instance); return 1; } if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) { PRINTF("RPL: Forward error!\n"); /* We should try to repair it by removing the neighbor that caused the packet to be forwareded in the first place. We drop any routes that go through the neighbor that sent the packet to us. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(route != NULL) { uip_ds6_route_rm(route); /* If we are the root and just needed to remove a DAO route, chances are that the network needs to be repaired. The rpl_repair_root() function will cause a global repair if we happen to be the root node of the dag. */ PRINTF("RPL: initiate global repair\n"); rpl_repair_root(instance->instance_id); } /* Remove the forwarding error flag and return 0 to let the packet be forwarded again. */ UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_FWD_ERR; return 0; } if(!instance->current_dag->joined) { PRINTF("RPL: No DAG in the instance\n"); return 1; } down = 0; if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) { down = 1; } sender_closer = UIP_EXT_HDR_OPT_RPL_BUF->senderrank < instance->current_dag->rank; PRINTF("RPL: Packet going %s, sender closer %d (%d < %d)\n", down == 1 ? "down" : "up", sender_closer, UIP_EXT_HDR_OPT_RPL_BUF->senderrank, instance->current_dag->rank ); if((down && !sender_closer) || (!down && sender_closer)) { PRINTF("RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n", UIP_EXT_HDR_OPT_RPL_BUF->senderrank, instance->current_dag->rank, sender_closer); if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { PRINTF("RPL: Rank error signalled in RPL option!\n"); /* We should try to repair it, not implemented for the moment */ rpl_reset_dio_timer(instance); /* Forward the packet anyway. */ return 0; } PRINTF("RPL: Single error tolerated\n"); UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR; return 0; } PRINTF("RPL: Rank OK\n"); return 0; }
/*---------------------------------------------------------------------------*/ 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); leds_init(); PRINTF("UDP server started\n"); #if UIP_CONF_ROUTER /* The choice of server address determines its 6LoWPAN header compression. * Obviously the choice made here must also be selected in udp-client.c. * * For correct Wireshark decoding using a sniffer, add the /64 prefix to the * 6LowPAN protocol preferences, * e.g. set Context 0 to aaaa::. At present Wireshark copies Context/128 and * then overwrites it. * (Setting Context 0 to aaaa::1111:2222:3333:4444 will report a 16 bit * compressed address of aaaa::1111:22ff:fe33:xxxx) * Note Wireshark's IPCMV6 checksum verification depends on the correct * uncompressed addresses. */ #if 0 /* Mode 1 - 64 bits inline */ uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); #elif 1 /* Mode 2 - 16 bits inline */ uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); #else /* Mode 3 - derived from link local (MAC) address */ uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); #endif uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL); root_if = uip_ds6_addr_lookup(&ipaddr); if(root_if != NULL) { rpl_dag_t *dag; dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); 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_MAC.off(1); server_conn = udp_new(NULL, UIP_HTONS(UDP_CLIENT_PORT), NULL); if(server_conn == NULL) { PRINTF("No UDP connection available, exiting the process!\n"); PROCESS_EXIT(); } 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_root(RPL_DEFAULT_INSTANCE); } } PROCESS_END(); }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_clear_buf(); return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_clear_buf(); return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; /* We first check if the destination address is on our immediate link. If so, we simply use the destination address as our nexthop address. */ if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t *route; /* Check if we have a route to the destination address. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); /* No route was found - we send to the default route instead. */ if(route == NULL) { PRINTF("tcpip_ipv6_output: no route found, using default route\n"); nexthop = uip_ds6_defrt_choose(); if(nexthop == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } /* Inform the other end that the destination is not reachable. If it's * not informed routes might get lost unexpectedly until there's a need * to send a new packet to the peer */ if(UIP_FALLBACK_INTERFACE.output() < 0) { PRINTF("FALLBACK: output error. Reporting DST UNREACH\n"); uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0); uip_flags = 0; tcpip_ipv6_output(); return; } #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_clear_buf(); return; } } else { /* A route was found, so we look up the nexthop neighbor for the route. */ nexthop = uip_ds6_route_nexthop(route); /* If the nexthop is dead, for example because the neighbor never responded to link-layer acks, we drop its route. */ if(nexthop == NULL) { #if UIP_CONF_IPV6_RPL /* If we are running RPL, and if we are the root of the network, we'll trigger a global repair berfore we remove the route. */ rpl_dag_t *dag; rpl_instance_t *instance; dag = (rpl_dag_t *)route->state.dag; if(dag != NULL) { instance = dag->instance; rpl_repair_root(instance->instance_id); } #endif /* UIP_CONF_IPV6_RPL */ uip_ds6_route_rm(route); /* We don't have a nexthop to send the packet to, so we drop it. */ return; } } #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { static uint8_t annotate_last; static uint8_t annotate_has_last = 0; if(annotate_has_last) { printf("#L %u 0; red\n", annotate_last); } printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1]; annotate_has_last = 1; } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_clear_buf(); return; } #endif /* UIP_CONF_IPV6_RPL */ nbr = uip_ds6_nbr_lookup(nexthop); if(nbr == NULL) { #if UIP_ND6_SEND_NA if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_clear_buf(); return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){ uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; /* Send the first NS try from here (multicast destination IP address). */ } #else /* UIP_ND6_SEND_NA */ uip_len = 0; return; #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit and set the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } /* Send in parallel if we are running NUD (nbc state is either STALE, DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */ if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } #endif /* UIP_ND6_SEND_NA */ tcpip_output(uip_ds6_nbr_get_ll(nbr)); #if UIP_CONF_IPV6_QUEUE_PKT /* * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * to STALE, and you must both send a NA and the queued packet. */ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(uip_ds6_nbr_get_ll(nbr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } } /* Multicast IP destination address. */ tcpip_output(NULL); uip_clear_buf(); }
void menu_process(char c) { static enum menustate_enum /* Defines an enumeration type */ { normal, channel, txpower } menustate = normal; static char channel_string[3]; static uint8_t channel_string_i;// = 0; int tempchannel; if (menustate == channel) { switch(c) { case '\r': case '\n': if (channel_string_i) { channel_string[channel_string_i] = 0; tempchannel = atoi(channel_string); if ((tempchannel < 11) || (tempchannel > 26)) { PRINTF_P(PSTR("\n\rInvalid input\n\r")); } else { rf230_set_channel(tempchannel); #if CONTIKI_CONF_SETTINGS_MANAGER if(settings_set_uint8(SETTINGS_KEY_CHANNEL, tempchannel) == SETTINGS_STATUS_OK) { PRINTF_P(PSTR("\n\rChannel changed to %d and stored in EEPROM.\n\r"), tempchannel); } else { PRINTF_P(PSTR("\n\rChannel changed to %d, but unable to store in EEPROM!\n\r"), tempchannel); } #else PRINTF_P(PSTR("\n\rChannel changed to %d.\n\r"), tempchannel); #endif } } else { PRINTF_P(PSTR("\n\rChannel unchanged.\n\r")); } menustate = normal; break; case '\b': if (channel_string_i) { channel_string_i--; PRINTF_P(PSTR("\b \b")); } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (channel_string_i > 1) { // This time the user has gone too far. // Beep at them. putc('\a', stdout); break; } putc(c, stdout); channel_string[channel_string_i] = c; channel_string_i++; break; default: break; } } else if (menustate == txpower) { switch(c) { case '\r': case '\n': if (channel_string_i) { channel_string[channel_string_i] = 0; tempchannel = atoi(channel_string); if ((tempchannel < 0) || (tempchannel > 15)) { PRINTF_P(PSTR("\n\rInvalid input\n\r")); } else { PRINTF_P(PSTR(" ")); //for some reason needs a print here to clear the string input... rf230_set_txpower(tempchannel); #if CONTIKI_CONF_SETTINGS_MANAGER if(settings_set_uint8(SETTINGS_KEY_TXPOWER, tempchannel) == SETTINGS_STATUS_OK) { PRINTF_P(PSTR("\n\rTransmit power changed to %d, and stored in EEPROM.\n\r"), tempchannel); } else { PRINTF_P(PSTR("\n\rTransmit power changed to %d, but unable to store in EEPROM!\n\r"), tempchannel); } #else PRINTF_P(PSTR("\n\rTransmit power changed to %d.\n\r"), tempchannel); #endif } } else { PRINTF_P(PSTR("\n\rTransmit power unchanged.\n\r")); } menustate = normal; break; case '\b': if (channel_string_i) { channel_string_i--; PRINTF_P(PSTR("\b \b")); } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (channel_string_i > 1) { // This time the user has gone too far. // Beep at them. putc('\a', stdout); break; } putc(c, stdout); channel_string[channel_string_i] = c; channel_string_i++; break; default: break; } } else { uint8_t i; switch(c) { case '\r': case '\n': break; case 'h': case '?': menu_print(); break; case 'd': if (mx_console_mode.debugOn) { PRINTF_P(PSTR("Node does not output debug strings\n\r")); mx_console_mode.debugOn = 0; } else { PRINTF_P(PSTR("Node now outputs debug strings\n\r")); mx_console_mode.debugOn = 1; } break; case 'c': PRINTF_P(PSTR("\nSelect 802.15.4 Channel in range 11-26 [%d]: "), rf230_get_channel()); menustate = channel; channel_string_i = 0; break; case 'p': PRINTF_P(PSTR("\nSelect transmit power (0=+3dBm 15=-17.2dBm) [%d]: "), rf230_get_txpower()); menustate = txpower; channel_string_i = 0; break; #if UIP_CONF_IPV6_RPL #include "rpl.h" extern uip_ds6_nbr_t uip_ds6_nbr_cache[]; extern uip_ds6_netif_t uip_ds6_if; case 'N': { uint8_t i,j; PRINTF_P(PSTR("\n\rAddresses [%u max]\n\r"),UIP_DS6_ADDR_NB); for (i=0;i<UIP_DS6_ADDR_NB;i++) { if (uip_ds6_if.addr_list[i].isused) { ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr); PRINTF_P(PSTR("\n\r")); } } PRINTF_P(PSTR("\n\rNeighbors [%u max]\n\r"),UIP_DS6_NBR_NB); for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) { if(uip_ds6_nbr_cache[i].isused) { ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr); PRINTF_P(PSTR("\n\r")); j=0; } } if (j) PRINTF_P(PSTR(" <none>")); PRINTF_P(PSTR("\n\rRoutes [%u max]\n\r"),UIP_DS6_ROUTE_NB); { uip_ds6_route_t *r; j = 1; for(r = uip_ds6_route_list_head(); r != NULL; r = list_item_next(r)) { ipaddr_add(&r->ipaddr); PRINTF_P(PSTR("/%u (via "), r->length); ipaddr_add(&r->nexthop); if(r->state.lifetime < 600) { PRINTF_P(PSTR(") %lus\n\r"), r->state.lifetime); } else { PRINTF_P(PSTR(")\n\r")); } j = 0; } } if (j) PRINTF_P(PSTR(" <none>")); PRINTF_P(PSTR("\n\r---------\n\r")); break; } case 'G': PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_root(RPL_DEFAULT_INSTANCE)); break; case 'L': rpl_local_repair(rpl_get_any_dag()); PRINTF_P(PSTR("Local repair initiated\n\r")); break; #endif case 'm': PRINTF_P(PSTR("Currently running on\n\r")); PRINTF_P(PSTR(" * %s\n\r"), CONTIKI_VERSION_STRING); PRINTF_P(PSTR(" * NETSTACK_MAC: %s, NETSTACK_RDC: %s\n\r"), NETSTACK_MAC.name, NETSTACK_RDC.name); #if 1 { int i; PRINTF_P(PSTR(" * Address: ")); for (i = 0; i < 6; i += 2) { PRINTF_P(PSTR("%02x%02x:"), uip_lladdr.addr[i], uip_lladdr.addr[i + 1]); } PRINTF_P(PSTR("%02x%02x\n\r"), uip_lladdr.addr[6], uip_lladdr.addr[7]); } #endif #if UIP_CONF_IPV6_RPL PRINTF_P(PSTR(" * RPL Enabled\n\r")); #endif #if UIP_CONF_ROUTER PRINTF_P(PSTR(" * Routing Enabled\n\r")); #endif #if CONVERTTXPOWER PRINTF_P(PSTR(" * Operates on channel %d with TX power "),rf230_get_channel()); printtxpower(); PRINTF_P(PSTR("\n\r")); #else //just show the raw value PRINTF_P(PSTR(" * Operates on channel %d\n\r"), rf230_get_channel()); PRINTF_P(PSTR(" * TX Power(0=+3dBm, 15=-17.2dBm): %d\n\r"), rf230_get_txpower()); #endif if (rf230_smallest_rssi) { PRINTF_P(PSTR(" * Current/Last/Smallest RSSI: %d/%d/%ddBm\n\r"), -91+(rf230_rssi()-1), -91+(rf230_last_rssi-1),-91+(rf230_smallest_rssi-1)); rf230_smallest_rssi=0; } else { PRINTF_P(PSTR(" * Current/Last/Smallest RSSI: %d/%d/--dBm\n\r"), -91+(rf230_rssi()-1), -91+(rf230_last_rssi-1)); } #if CONFIG_STACK_MONITOR /* See contiki-raven-main.c for initialization of the magic numbers */ { extern uint16_t __bss_end; uint16_t p=(uint16_t)&__bss_end; do { if (*(uint16_t *)p != 0x4242) { printf_P(PSTR(" * Never-used stack > %d bytes\n\r"),p-(uint16_t)&__bss_end); break; } p+=100; } while (p<RAMEND-100); } #endif break; case 'e': PRINTF_P(PSTR("Energy Scan:\n")); { uint8_t i; uint16_t j; uint8_t previous_channel = rf230_get_channel(); int8_t RSSI, maxRSSI[17]; uint16_t accRSSI[17]; bzero((void*)accRSSI,sizeof(accRSSI)); bzero((void*)maxRSSI,sizeof(maxRSSI)); for(j=0;j<(1<<12);j++) { for(i=11;i<=26;i++) { rf230_listen_channel(i); _delay_us(3*10); RSSI = rf230_rssi(); //multiplies rssi register by 3 for consistency with energy-detect register maxRSSI[i-11]=Max(maxRSSI[i-11],RSSI); accRSSI[i-11]+=RSSI; } if(j&(1<<7)) { leds_on(LEDS_RED); if(!(j&((1<<7)-1))) { PRINTF_P(PSTR(".")); } } else { leds_off(LEDS_RED); } watchdog_periodic(); } rf230_set_channel(previous_channel); PRINTF_P(PSTR("\n")); for(i=11;i<=26;i++) { uint8_t activity=Min(maxRSSI[i-11],accRSSI[i-11]/(1<<7)); PRINTF_P(PSTR(" %d: %02ddB "),i, -91+(maxRSSI[i-11]-1)); for(;activity--;maxRSSI[i-11]--) { PRINTF_P(PSTR("#")); } for(;maxRSSI[i-11]>0;maxRSSI[i-11]--) { PRINTF_P(PSTR(":")); } PRINTF_P(PSTR("\n")); } } PRINTF_P(PSTR("Done.\n")); break; case 'R': PRINTF_P(PSTR("Resetting...\n\r")); leds_on(LEDS_ALL); for(i = 0; i < 20; i++) _delay_ms(100); watchdog_reboot(); break; default: PRINTF_P(PSTR("%c is not a valid option! h for menu\n\r"), c); break; } } }
/*---------------------------------------------------------------------------*/ httpd_simple_script_t httpd_simple_get_script(const char *name) { static uip_ds6_route_t *r; static char filename[HTTPD_PATHLEN]; static int i; strcpy(filename, slip_config_www_root); strcat(filename, "/"); strcat(filename, name); redirect = 0; if(strcmp(name, "index.html") == 0 || strcmp(name, "") == 0) { return generate_index; #if CONTIKI_TARGET_NATIVE } else if (access(filename, R_OK) == 0) { return send_file; #endif #if CETIC_NODE_INFO } else if(strcmp(name, "sensors.html") == 0) { return generate_sensors; #endif } else if(strcmp(name, "rpl.html") == 0) { return generate_rpl; } else if(strcmp(name, "network.html") == 0) { return generate_network; } else if(strcmp(name, "config.html") == 0) { return generate_config; } else if(strcmp(name, "statistics.html") == 0) { return generate_statistics; } else if ((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_CONFIG) == 0) { if(strcmp(name, "rpl-gr") == 0) { #if UIP_CONF_IPV6_RPL rpl_repair_root(RPL_DEFAULT_INSTANCE); #endif return generate_rpl; } else if(memcmp(name, "route_rm?", 9) == 0) { redirect = 1; i = atoi(name + 9); for(r = uip_ds6_route_list_head(); r != NULL; r = list_item_next(r), --i) { if(i == 0) { uip_ds6_route_rm(r); break; } } return generate_network; } else if(memcmp(name, "nbr_rm?", 7) == 0) { redirect = 1; uip_ds6_nbr_rm(&uip_ds6_nbr_cache[atoi(name + 7)]); return generate_network; } else if(memcmp(name, "config?", 7) == 0) { if(update_config(name + 7)) { return generate_config; } else { return generate_reboot; } } else { return generate_404; } } else { return generate_404; } }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { static struct etimer et; rpl_dag_t *dag; PROCESS_BEGIN(); /* While waiting for the prefix to be sent through the SLIP connection, the future * border router can join an existing DAG as a parent or child, or acquire a default * router that will later take precedence over the SLIP fallback interface. * Prevent that by turning the radio off until we are initialized as a DAG root. */ prefix_set = 0; NETSTACK_MAC.off(0); PROCESS_PAUSE(); SENSORS_ACTIVATE(button_sensor); PRINTF("RPL-Border router started\n"); #if 0 /* The border router runs with a 100% duty cycle in order to ensure high packet reception rates. Note if the MAC RDC is not turned off now, aggressive power management of the cpu will interfere with establishing the SLIP connection */ NETSTACK_MAC.off(1); #endif /* 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(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)dag_id); if(dag != NULL) { rpl_set_prefix(dag, &prefix, 64); PRINTF("created a new RPL dag\n"); } /* Now turn the radio on, but disable radio duty cycling. * Since we are the DAG root, reception delays would constrain mesh throughbut. */ NETSTACK_MAC.off(1); #if DEBUG || 1 print_local_addresses(); #endif #if ENABLE_CBC_LINK_SECURITY // /* // * new connection with remote host at port 0 // * to allow multiple remote ports on the same // * connection // */ // sec_conn = udp_new(NULL, 0, NULL); // if(sec_conn == NULL) { // PRINTFSECKEY("No UDP conn, exiting proc!\n"); // PROCESS_EXIT(); // } // udp_bind(sec_conn, UIP_HTONS(UDP_CLIENT_SEC_PORT)); #endif while(1) { PROCESS_YIELD(); if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiating global repair\n"); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { rpl_dag_t *dag; PROCESS_BEGIN(); /* While waiting for the prefix to be sent through the SLIP connection, the future * border router can join an existing DAG as a parent or child, or acquire a default * router that will later take precedence over the SLIP fallback interface. * Prevent that by turning the radio off until we are initialized as a DAG root. */ prefix_set = 0; NETSTACK_MAC.off(0); PROCESS_PAUSE(); //SENSORS_ACTIVATE(button_sensor); PRINTF("RPL-Border router started\n"); #if 0 /* The border router runs with a 100% duty cycle in order to ensure high packet reception rates. Note if the MAC RDC is not turned off now, aggressive power management of the cpu will interfere with establishing the SLIP connection */ NETSTACK_MAC.off(1); #endif /* Request prefix until it has been received */ #define REQUEST_PREFIX 1 #if REQUEST_PREFIX static struct etimer et; while(!prefix_set) { etimer_set(&et, 1000); request_prefix(); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); } dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)dag_id); if(dag != NULL) { rpl_set_prefix(dag, &prefix, 64); PRINTF("created a new RPL dag\n"); } #else { char buf[sizeof(dag_id)]; memcpy(buf,dag_id,sizeof(dag_id)); dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)buf); /* Assign separate addresses to the uip stack and the host network interface, but with the same prefix E.g. bbbb::ff:fe00:200 to the stack and bbbb::1 to the host *fallback* network interface Otherwise the host will trap packets intended for the stack, just as the stack will trap packets intended for the host $ifconfig usb0 -arp on Ubuntu to skip the neighbor solicitations. Add explicit neighbors on other OSs */ if(dag != NULL) { PRINTF("Created a new RPL dag\n"); #if UIP_CONF_ROUTER_RECEIVE_RA /* Contiki stack will shut down until assigned an address from the interface RA Currently this requires changes in the core rpl-icmp6.c to pass the link-local RA broadcast. */ #else { int i; uip_ip6addr_t ipaddr; #ifdef HARD_CODED_ADDRESS uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); #else uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0x1); #endif uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); rpl_set_prefix(dag, &ipaddr, 64); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { if(uip_ds6_if.addr_list[i].isused) { PRINTF("IPV6 Address: "); sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); PRINTF("\n"); } } } #endif } } #endif /* Now turn the radio on, but disable radio duty cycling. * Since we are the DAG root, reception delays would constrain mesh throughbut. */ NETSTACK_MAC.off(1); #if DEBUG || 1 print_local_addresses(); #endif while(1) { PROCESS_YIELD(); if (ev == sensors_event){ PRINTF("Initiating global repair\n"); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } PROCESS_END(); }