/* This function goes through all encounters to see if it finds a matching neighbor. If so, we set a ctimer that will turn on the radio just before we expect the neighbor to send a probe packet. If we cannot find a matching encounter, we just turn on the radio. The outbound packet is put on either the pending_packets_list or the queued_packets_list, depending on if the packet should be sent immediately. */ static void turn_radio_on_for_neighbor(rimeaddr_t *neighbor, struct queue_list_item *i) { struct encounter *e; #if WITH_STREAMING if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_STREAM) { is_streaming = 1; turn_radio_on(); list_add(queued_packets_list, i); ctimer_set(&stream_off_timer, STREAM_OFF_TIME, stream_off, NULL); return; } #endif /* WITH_STREAMING */ if(rimeaddr_cmp(neighbor, &rimeaddr_null)) { #if ! WITH_PENDING_BROADCAST /* We have been asked to turn on the radio for a broadcast, so we just turn on the radio. */ turn_radio_on(); #endif /* ! WITH_PENDING_BROADCAST */ list_add(queued_packets_list, i); return; } #if WITH_ENCOUNTER_OPTIMIZATION /* We go through the list of encounters to find if we have recorded an encounter with this particular neighbor. If so, we can compute the time for the next expected encounter and setup a ctimer to switch on the radio just before the encounter. */ for(e = list_head(encounter_list); e != NULL; e = e->next) { if(rimeaddr_cmp(neighbor, &e->neighbor)) { clock_time_t wait, now; /* We expect encounters to happen roughly every OFF_TIME time units. The next expected encounter is at time e->time + OFF_TIME. To compute a relative offset, we subtract with clock_time(). Because we are only interested in turning on the radio within the OFF_TIME period, we compute the waiting time with modulo OFF_TIME. */ now = clock_time(); wait = ((clock_time_t)(e->time - now)) % (OFF_TIME); /* printf("now %d e %d e-n %d w %d %d\n", now, e->time, e->time - now, (e->time - now) % (OFF_TIME), wait); printf("Time now %lu last encounter %lu next expected encouter %lu wait %lu/%d (%lu)\n", (1000ul * (unsigned long)now) / CLOCK_SECOND, (1000ul * (unsigned long)e->time) / CLOCK_SECOND, (1000ul * (unsigned long)(e->time + OFF_TIME)) / CLOCK_SECOND, (1000ul * (unsigned long)wait) / CLOCK_SECOND, wait, (1000ul * (unsigned long)(wait + now)) / CLOCK_SECOND);*/ /* printf("Neighbor %d.%d found encounter, waiting %d ticks\n", neighbor->u8[0], neighbor->u8[1], wait);*/ ctimer_set(&e->turn_on_radio_timer, wait, turn_radio_on_callback, i); list_add(pending_packets_list, i); return; } } #endif /* WITH_ENCOUNTER_OPTIMIZATION */ /* We did not find the neighbor in the list of recent encounters, so we just turn on the radio. */ /* printf("Neighbor %d.%d not found in recent encounters\n", neighbor->u8[0], neighbor->u8[1]);*/ turn_radio_on(); list_add(queued_packets_list, i); return; }
/*---------------------------------------------------------------------------*/ static PT_THREAD(generate_index(struct httpd_state *s)) { static int i; #if BUF_USES_STACK char buf[BUF_SIZE]; #endif #if WEBSERVER_CONF_LOADTIME static clock_time_t numticks; numticks = clock_time(); #endif PSOCK_BEGIN(&s->sout); SEND_STRING(&s->sout, TOP); SEND_STRING(&s->sout, BODY); reset_buf(); add_div_home("Info"); add("<div id=\"left_home\">"); add("<h2>Info</h2>"); add("Version : " CETIC_6LBR_VERSION " (" CONTIKI_VERSION_STRING ")<br />"); add("Mode : "); #if CETIC_6LBR_SMARTBRIDGE add("SMART BRIGDE"); #endif #if CETIC_6LBR_TRANSPARENTBRIDGE #if CETIC_6LBR_LEARN_RPL_MAC add("RPL Relay"); #else add("FULL TRANSPARENT BRIGDE"); #endif #endif #if CETIC_6LBR_ROUTER #if UIP_CONF_IPV6_RPL add("RPL ROUTER"); #else add("NDP ROUTER"); #endif #endif #if CETIC_6LBR_6LR add("6LR"); #endif add("<br />\n"); i = clock_seconds() - cetic_6lbr_startup; add("Uptime : %dh %dm %ds<br />", i / 3600, (i / 60) % 60, i % 60); SEND_STRING(&s->sout, buf); reset_buf(); add("<br /><h2>WSN</h2>"); add("MAC: %s<br />RDC: %s (%d Hz)<br />", NETSTACK_MAC.name, NETSTACK_RDC.name, (NETSTACK_RDC.channel_check_interval() == 0) ? 0 : CLOCK_SECOND / NETSTACK_RDC.channel_check_interval()); #if UIP_CONF_IPV6_RPL add("Prefix : "); ipaddr_add(&cetic_dag->prefix_info.prefix); add("/%d", cetic_dag->prefix_info.length); add("<br />"); #endif add("HW address : "); lladdr_add(&uip_lladdr); add("<br />"); SEND_STRING(&s->sout, buf); reset_buf(); add("<br /><h2>Ethernet</h2>"); #if CETIC_6LBR_ROUTER add("Address : "); ipaddr_add(ð_ip_addr); add("<br />"); add("Local address : "); ipaddr_add(ð_ip_local_addr); add("<br />"); #endif add("HW address : "); ethaddr_add(ð_mac_addr); add("<br />"); SEND_STRING(&s->sout, buf); reset_buf(); #if CONTIKI_TARGET_ECONOTAG add("<br /><h2>Memory</h2>"); add("Global : %d (%d %%)<br /><br />", &_end - &_start, (100 * (&_end - &_start)) / (96 * 1024)); add("Code : %d<br />", &_etext - &_start); add("Initialised data : %d<br /><br />", &_edata - &_etext); add("Data : %d<br />", &_bss_end__ - &__bss_start); add("Stack : %d<br />", &__bss_start - &_edata); add("Heap : %d<br />", &_end - &_bss_end__); SEND_STRING(&s->sout, buf); reset_buf(); #endif add_div_footer(); #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; add("<br><i>This page sent %u times</i>", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME numticks = clock_time() - numticks + 1; add(" <i>(%u.%02u sec)</i>", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND) / CLOCK_SECOND)); #endif add("</div></div>"); SEND_STRING(&s->sout, buf); SEND_STRING(&s->sout, BOTTOM); PSOCK_END(&s->sout); }
static PT_THREAD(generate_rpl(struct httpd_state *s)) { #if UIP_CONF_IPV6_RPL static int i; static int j; #endif #if BUF_USES_STACK char buf[BUF_SIZE]; #endif #if WEBSERVER_CONF_LOADTIME static clock_time_t numticks; numticks = clock_time(); #endif PSOCK_BEGIN(&s->sout); SEND_STRING(&s->sout, TOP); SEND_STRING(&s->sout, BODY); reset_buf(); add_div_home("RPL"); add("<div id=\"left_home\">"); SEND_STRING(&s->sout, buf); reset_buf(); #if UIP_CONF_IPV6_RPL add("<h2>Configuration</h2>"); add("Lifetime : %d (%d x %d s)<br />", RPL_CONF_DEFAULT_LIFETIME * RPL_CONF_DEFAULT_LIFETIME_UNIT, RPL_CONF_DEFAULT_LIFETIME, RPL_CONF_DEFAULT_LIFETIME_UNIT); add("<br />"); SEND_STRING(&s->sout, buf); reset_buf(); for(i = 0; i < RPL_MAX_INSTANCES; ++i) { if(instance_table[i].used) { add("<h2>Instance %d</h2>", instance_table[i].instance_id); for(j = 0; j < RPL_MAX_DAG_PER_INSTANCE; ++j) { if(instance_table[i].dag_table[j].used) { add("<h3>DODAG %d</h3>", j); add("DODAG ID : "); ipaddr_add(&instance_table[i].dag_table[j].dag_id); SEND_STRING(&s->sout, buf); reset_buf(); add("<br />Version : %d", instance_table[i].dag_table[j].version); add("<br />Grounded : %s", instance_table[i].dag_table[j].grounded ? "Yes" : "No"); add("<br />Preference : %d", instance_table[i].dag_table[j].preference); add("<br />Mode of Operation : %u", instance_table[i].mop); add("<br />Current DIO Interval [%u-%u] : %u", instance_table[i].dio_intmin, instance_table[i].dio_intmin + instance_table[i].dio_intdoubl, instance_table[i].dio_intcurrent); add("<br />Objective Function Code Point : %u", instance_table[i].of->ocp); add("<br />Joined : %s", instance_table[i].dag_table[j].joined ? "Yes" : "No"); add("<br />Rank : %d", instance_table[i].dag_table[j].rank); add("<br />"); SEND_STRING(&s->sout, buf); reset_buf(); } } } } if ((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_CONFIG) == 0) { add("<br /><h3>Actions</h3>"); add("<a href=\"rpl-gr\">Trigger global repair</a><br />"); } else { add("<br /><h3>Actions (disabled)</h3>"); add("Trigger global repair<br />"); } SEND_STRING(&s->sout, buf); reset_buf(); #else add("<h3>RPL is deactivated</h3>"); #endif add_div_footer(); #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; add("<br><i>This page sent %u times</i>", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME numticks = clock_time() - numticks + 1; add(" <i>(%u.%02u sec)</i>", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND) / CLOCK_SECOND)); #endif add("</div></div>"); SEND_STRING(&s->sout, buf); SEND_STRING(&s->sout, BOTTOM); PSOCK_END(&s->sout); }
/* Wait for a multiple of clock ticks (7.8 ms at 128 Hz). */ void clock_wait(clock_time_t t) { clock_time_t start; start = clock_time(); while(clock_time() - start < (clock_time_t)t); }
/** * Restart the timer from the current point in time * * This function restarts a timer with the same interval that was * given to the timer_set() function. The timer will start at the * current time. * * \note A periodic timer will drift if this function is used to reset * it. For preioric timers, use the timer_reset() function instead. * * \param t A pointer to the timer. * * \sa timer_reset() */ void timer_restart(struct timer *t) { t->start = clock_time(); }
/*---------------------------------------------------------------------------*/ void lpm_drop() { lpm_registered_module_t *module; uint8_t max_pm = LPM_MODE_MAX_SUPPORTED; uint8_t module_pm; clock_time_t next_event; uint32_t domains = LOCKABLE_DOMAINS; if(RTIMER_CLOCK_LT(soc_rtc_get_next_trigger(), RTIMER_NOW() + STANDBY_MIN_DURATION)) { lpm_sleep(); return; } /* Collect max allowed PM permission from interested modules */ for(module = list_head(modules_list); module != NULL; module = module->next) { if(module->request_max_pm) { module_pm = module->request_max_pm(); if(module_pm < max_pm) { max_pm = module_pm; } } } /* Check if any events fired during this process. Last chance to abort */ if(process_nevents()) { return; } /* Drop */ if(max_pm == LPM_MODE_SLEEP) { lpm_sleep(); } else { /* Critical. Don't get interrupted! */ ti_lib_int_master_disable(); /* * Reschedule AON RTC CH1 to fire an event N ticks before the next etimer * event */ next_event = etimer_next_expiration_time(); if(next_event) { next_event = next_event - clock_time(); soc_rtc_schedule_one_shot(AON_RTC_CH1, RTIMER_NOW() + (next_event * (RTIMER_SECOND / CLOCK_SECOND))); } /* * Notify all registered modules that we are dropping to mode X. We do not * need to do this for simple sleep. * * This is a chance for modules to delay us a little bit until an ongoing * operation has finished (e.g. uart TX) or to configure themselves for * deep sleep. * * At this stage, we also collect power domain locks, if any. * The argument to PRCMPowerDomainOff() is a bitwise OR, so every time * we encounter a lock we just clear the respective bits in the 'domains' * variable as required by the lock. In the end the domains variable will * just hold whatever has not been cleared */ for(module = list_head(modules_list); module != NULL; module = module->next) { if(module->shutdown) { module->shutdown(max_pm); } /* Clear the bits specified in the lock */ domains &= ~module->domain_lock; } /* Pat the dog: We don't want it to shout right after we wake up */ watchdog_periodic(); /* Clear unacceptable bits, just in case a lock provided a bad value */ domains &= LOCKABLE_DOMAINS; /* * Freeze the IOs on the boundary between MCU and AON. We only do this if * PERIPH is not needed */ if(domains & PRCM_DOMAIN_PERIPH) { ti_lib_aon_ioc_freeze_enable(); } /* * Among LOCKABLE_DOMAINS, turn off those that are not locked * * If domains is != 0, pass it as-is */ if(domains) { ti_lib_prcm_power_domain_off(domains); } /* * Before entering Deep Sleep, we must switch off the HF XOSC. The HF XOSC * is predominantly controlled by the RF driver. In a build with radio * cycling (e.g. ContikiMAC), the RF driver will request the XOSC before * using the Freq. Synth, and switch back to the RC when it is about to * turn back off. * * If the radio is on, we won't even reach here, and if it's off the HF * clock source should already be the HF RC. * * Nevertheless, request the switch to the HF RC explicitly here. */ oscillators_switch_to_hf_rc(); /* Configure clock sources for MCU and AUX: No clock */ ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); /* Full RAM retention. */ ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION | MCU_RAM2_RETENTION | MCU_RAM3_RETENTION); /* Disable retention of AUX RAM */ ti_lib_aon_wuc_aux_sram_config(false); /* * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off * already */ ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS); /* Request JTAG domain power off */ ti_lib_aon_wuc_jtag_power_off(); /* Turn off AUX */ ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); ti_lib_aon_wuc_domain_power_down_enable(); while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON); /* Configure the recharge controller */ ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE); /* * If both PERIPH and SERIAL PDs are off, request the uLDO as the power * source while in deep sleep. */ if(domains == LOCKABLE_DOMAINS) { ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO); } /* We are only interested in IRQ energest while idle or in LPM */ ENERGEST_IRQ_RESTORE(irq_energest); ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM); /* Sync the AON interface to ensure all writes have gone through. */ ti_lib_sys_ctrl_aon_sync(); /* * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of * retention mismatch between VIMS logic and cache. We wait to do this * until right before deep sleep to be able to use the cache for as long * as possible. */ ti_lib_prcm_cache_retention_disable(); ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF); /* Deep Sleep */ ti_lib_prcm_deep_sleep(); /* * When we reach here, some interrupt woke us up. The global interrupt * flag is off, hence we have a chance to run things here. We will wake up * the chip properly, and then we will enable the global interrupt without * unpending events so the handlers can fire */ wake_up(); ti_lib_int_master_enable(); } }
static PT_THREAD(generate_sensor(struct httpd_state *s)) { static uip_ipaddr_t ipaddr; static node_info_t * node_info = NULL; PSOCK_BEGIN(&s->sout); if(s->query && strncmp(s->query, "ip=", 3) == 0 && uiplib_ipaddrconv(s->query + 3, &ipaddr) != 0) { node_info = node_info_lookup(&ipaddr); if(node_info) { add("<h2>Info</h2>"); #if CETIC_NODE_CONFIG_HAS_NAME if ( node_config_loaded ) { add("Name: %s<br />", node_config_get_name(node_config_find_by_ip(&ipaddr))); } #endif add("IP: "); ipaddr_add(&ipaddr); add("<br />"); add("Model: -<br />"); add("Parent: "); #if CETIC_NODE_CONFIG_HAS_NAME if (node_config_loaded) { add("%s (", node_config_get_name(node_config_find_by_ip(&node_info->ip_parent))); ipaddr_add(&node_info->ip_parent); add(")</a>"); } else #endif { ipaddr_add(&node_info->ip_parent); add("</a>"); } add("<br />"); add("Downward route: %s<br />", node_info->has_route ? "Yes" : "No"); SEND_STRING(&s->sout, buf); reset_buf(); add("<br /><h2>Statistics</h2>"); add("Since : %d s<br />", (clock_time() - node_info->stats_start) / CLOCK_SECOND); add("Last seen : %d s<br />", (clock_time() - node_info->last_seen) / CLOCK_SECOND); add("Hop count: %d<br />", node_info->hop_count); add("Parent switch: %d<br />", node_info->parent_switch); add("<br /><h3>Upstream</h3>"); add("Last sequence number: %d<br />", node_info->last_up_sequence); add("Messages sent: %d<br />", node_info->messages_sent); add("Messages lost: %d<br />", node_info->up_messages_lost); if(node_info->messages_sent > 0) { add("PRR: %.1f%%<br />", 100.0 * (node_info->messages_sent - node_info->up_messages_lost)/node_info->messages_sent); } else { add("PRR: n/a<br />"); } add("<br /><h3>Downstream</h3>"); add("Last sequence number: %d<br />", node_info->last_down_sequence); add("Messages sent: %d<br />", node_info->replies_sent); add("Messages lost: %d<br />", node_info->down_messages_lost); if(node_info->replies_sent > 0) { add("PRR: %.1f%%<br />", 100.0 * (node_info->replies_sent - node_info->down_messages_lost)/node_info->replies_sent); } else { add("PRR: n/a<br />"); } SEND_STRING(&s->sout, buf); reset_buf(); add("<br /><h2>Actions</h2>"); add("<form action=\"reset-stats\" method=\"get\">"); add("<input type=\"hidden\" name=\"ip\" value=\""); ipaddr_add(&node_info->ipaddr); add("\"/>"); add("<input type=\"submit\" value=\"Reset statistics\"/></form><br />"); add("<form action=\"rm-node\" method=\"get\">"); add("<input type=\"hidden\" name=\"ip\" value=\""); ipaddr_add(&node_info->ipaddr); add("\"/>"); add("<input type=\"submit\" value=\"Delete node\"/></form><br />"); } else { add("Sensor address unknown"); } } else { add("Sensor address missing"); } SEND_STRING(&s->sout, buf); reset_buf(); PSOCK_END(&s->sout); }
void * calc(void *thread) { long t = (long) thread; int start_index = t * (X_SIZE / THREADS); int end_index = (t != THREADS - 1)?(t + 1) * (X_SIZE / THREADS) - 1: X_SIZE - 1; matrix local(phi.size()), next(phi.size(),row(phi[0].size())); row zeros; for (int i = 0; i < Y_SIZE; i++) { zeros.push_back(0); } double cur_time = 0, a = 0; int x, y; int counter = 0; unsigned long long iters = 0; std::cout << "I am thread " << t << ". My start index: " << start_index << ". My end index: " << end_index << std::endl; row left_t, mid_t, right_t; unsigned long long start = clock_time(); double mid, right, left, top, bot; while (cur_time < T) { //for(int i = 0; i < 3; i ++) { pthread_barrier_wait(&syn); #ifndef NOGNUPLOT if (t == 0) { if (cur_time > (double) T / 4) I[25][25] = 0; if (cur_time - a > 1e-2) { a = cur_time; std::stringstream convert; convert << counter; std::string num = convert.str(); std::ofstream file((data_file_name + num).c_str(), std::ofstream::out|std::ofstream::trunc); for (int i = 0; i < phi.size(); i++) { for(int j = 0; j < phi[i].size(); j++) { file << i << " " << j << " " << phi[i][j] << std::endl; } } file.close(); counter ++; gnuplot << "splot \"" << data_file_name + num << "\"" << "with lines title \"phi\"\n"; gnuplot << "pause 0.1" << std::endl; } } /*out << cur_time << " "; for (int i = 0; i < gnuplot_points.size(); i++) { x = gnuplot_points[i].first; y = gnuplot_points[i].second; if (x >= 0 && x < X_SIZE && y >=0 && y < Y_SIZE) out << phi[x][y] << " "; } } } out << std::endl;*/ #endif cur_time += dt; /*for (int i = start_index; i <= end_index; i ++) { iters ++; mid_t = phi[i]; if (i == start_index && start_index == 0) { left_t = zeros; right_t = phi[i+1]; } else if (i == end_index && end_index == X_SIZE - 1) { left_t = phi[i - 1]; right_t = zeros; } else { left_t = phi[i - 1]; right_t = phi[i + 1]; }*/ for(int i = start_index; i <= end_index; i++){ for(int j = 0; j < phi[i].size(); j++){ mid = phi[i][j]; top = j == 0 ? 0:phi[i][j-1]; bot = j == Y_SIZE - 1 ? 0 : phi[i][j+1]; left = i == start_index && start_index ==0 ? 0 : phi[i-1][j]; right = i == end_index && end_index == X_SIZE - 1 ? 0 :phi[i+1][j]; next[i][j] = mid + (top+ bot + left + right - 4 * mid) * dt / (R * C) + I[i][j] * dt /C; } } //next[i] = solve(left_t, mid_t, right_t, i); //} pthread_barrier_wait(&bar); for (int i = start_index; i <=end_index; i++) { phi[i] = next[i]; } } pthread_exit(NULL); }
int main(int argc, char **argv) { int time_to_modulate; int num_threads; int x_grid, y_grid; const char* short_options = "tpxy"; int c; T = atoi(argv[4]); dt = 1e-6; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); x_grid = atoi(argv[1]); y_grid = atoi(argv[2]); num_threads = atoi(argv[3]); #ifndef NOGNUPLOT /*int print_points = atoi(argv[5]); std::cout << "Enter " << print_points << " nodes to print in format <m> <n>" << std::endl; int x, y; for(int i = 0; i < print_points; i++) { std::cin >> x >> y; gnuplot_points.push_back(std::make_pair(x, y)); }*/ #endif THREADS = num_threads; time_to_modulate = 2; X_SIZE = x_grid; Y_SIZE = y_grid; phi.resize(x_grid); for(int i = 0; i < phi.size(); i++) { phi[i].resize(y_grid); } I.resize(x_grid); for(int i = 0; i < I.size(); i++) { I[i].resize(y_grid); for(int j = 0; j < y_grid; j++) I[i][j] = 0;//rand() % 6 - 3; } I[25][25] = 2; #ifndef NOGNUPLOT gnuplot << "set size ratio 1\n"; gnuplot << "set hidden3d\n"; gnuplot << "set dgrid 50,50\n"; gnuplot << "set zrange [-3: 3]\n"; //int res = system("gnuplot -persist cmd"); #endif // I[1][1] = 1; // I[0][1] = -1; pthread_barrier_init(&bar, NULL, THREADS); pthread_barrier_init(&val, NULL, THREADS); pthread_barrier_init(&syn, NULL, THREADS); pthread_mutex_init(&lock, NULL); pthread_t *threads = new pthread_t[THREADS]; unsigned long long start = clock_time(); for (long i = 0; i < THREADS; i++) { if (pthread_create(&threads[i], NULL, calc, (void *)i) != 0) { std::cout << "Can't create thread " << i << std::endl; } } for (int i = 0; i < THREADS; i++) { pthread_join(threads[i], NULL); } std::cout << "It takes " << (clock_time() - start) << std::endl; return 0; }
void dtls_clock_init(void) { clock_init(); dtls_clock_offset = clock_time(); }
void dtls_ticks(dtls_tick_t *t) { *t = clock_time(); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(shell_repeat_process, ev, data) { static int reps, period, period_left; static char command[MAX_COMMANDLENGTH]; static struct etimer etimer; static int i; static clock_time_t start_time; const char *args, *next; if(ev == shell_event_input) { struct shell_input *input; input = data; /* printf("shell repeat input %d %d\n", input->len1, input->len2);*/ if(input->len1 + input->len2 != 0) { shell_output(&repeat_command, input->data1, input->len1, input->data2, input->len2); } } PROCESS_BEGIN(); /* printf("data '%s'\n", data);*/ args = data; if(args == NULL) { repeat_print_usage(); PROCESS_EXIT(); } reps = shell_strtolong(args, &next); if(next == args) { repeat_print_usage(); PROCESS_EXIT(); } args = next; period = shell_strtolong(args, &next); if(next == args) { repeat_print_usage(); PROCESS_EXIT(); } args = next; while(*args == ' ') { args++; } strncpy(command, args, MAX_COMMANDLENGTH); if(strlen(command) == 0) { repeat_print_usage(); PROCESS_EXIT(); } /* printf("repeats %d period %d command '%s'\n", reps, period, command);*/ start_time = clock_time(); etimer_set(&etimer, CLOCK_SECOND * period); for(i = 0; reps == 0 || i < reps; ++i) { process_start(&shell_repeat_server_process, command); process_post(&shell_repeat_server_process, PROCESS_EVENT_CONTINUE, &shell_repeat_process); PROCESS_WAIT_UNTIL(ev == PROCESS_EVENT_EXITED && data == &shell_repeat_server_process); PROCESS_WAIT_UNTIL(etimer_expired(&etimer)); etimer_reset(&etimer); /* PROCESS_PAUSE(); for(period_left = period; period_left > 0; period_left -= MIN(PERIOD_INTERVAL, period_left)) { etimer_set(&etimer, CLOCK_SECOND * MIN(PERIOD_INTERVAL, period_left)); PROCESS_WAIT_UNTIL(etimer_expired(&etimer)); }*/ } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr, u8_t isrouter, u8_t state) { int r; r = uip_ds6_list_loop ((uip_ds6_element_t *) uip_ds6_nbr_cache, UIP_DS6_NBR_NB, sizeof(uip_ds6_nbr_t), ipaddr, 128, (uip_ds6_element_t **) &locnbr); // printf("r %d\n", r); if(r == FREESPACE) { locnbr->isused = 1; uip_ipaddr_copy(&(locnbr->ipaddr), ipaddr); if(lladdr != NULL) { memcpy(&(locnbr->lladdr), lladdr, UIP_LLADDR_LEN); } else { memset(&(locnbr->lladdr), 0, UIP_LLADDR_LEN); } locnbr->isrouter = isrouter; locnbr->state = state; /* timers are set separately, for now we put them in expired state */ stimer_set(&(locnbr->reachable), 0); stimer_set(&(locnbr->sendns), 0); locnbr->nscount = 0; PRINTF("Adding neighbor with ip addr"); PRINT6ADDR(ipaddr); PRINTF("link addr"); PRINTLLADDR((&(locnbr->lladdr))); PRINTF("state %u\n", state); NEIGHBOR_STATE_CHANGED(locnbr); locnbr->last_lookup = clock_time(); // printf("add %p\n", locnbr); return locnbr; } else if(r == NOSPACE) { /* We did not find any empty slot on the neighbor list, so we need to remove one old entry to make room. */ uip_ds6_nbr_t *n, *oldest; clock_time_t oldest_time; oldest = NULL; oldest_time = clock_time(); for(n = uip_ds6_nbr_cache; n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; n++) { if(n->isused) { if((n->last_lookup < oldest_time) && (uip_ds6_is_nbr_garbage_collectible(n))) { /* We do not want to remove any non-garbage-collectible entry */ oldest = n; oldest_time = n->last_lookup; } } } if(oldest != NULL) { // printf("rm3\n"); uip_ds6_nbr_rm(oldest); locdefrt = uip_ds6_defrt_lookup(&oldest->ipaddr); uip_ds6_defrt_rm(locdefrt); uip_ds6_reg_cleanup_defrt(locdefrt); return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state); } } PRINTF("uip_ds6_nbr_add drop\n"); return NULL; }
/** * Read a packet from the underlying radio driver. If the incoming * packet is a probe packet and the sender of the probe matches the * destination address of the queued packet (if any), the queued packet * is sent. */ static int read_packet(void) { int len; struct lpp_hdr *hdr; clock_time_t reception_time; reception_time = clock_time(); packetbuf_clear(); len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); if(len > sizeof(struct lpp_hdr)) { packetbuf_set_datalen(len); hdr = packetbuf_dataptr(); packetbuf_hdrreduce(sizeof(struct lpp_hdr)); /* PRINTF("got packet type %d\n", hdr->type);*/ if(hdr->type == TYPE_PROBE) { /* Parse incoming announcements */ struct announcement_msg *adata = packetbuf_dataptr(); int i; /* PRINTF("%d.%d: probe from %d.%d with %d announcements\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->sender.u8[0], hdr->sender.u8[1], adata->num);*/ for(i = 0; i < adata->num; ++i) { /* PRINTF("%d.%d: announcement %d: %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->data[i].id, adata->data[i].value);*/ announcement_heard(&hdr->sender, adata->data[i].id, adata->data[i].value); } /* Register the encounter with the sending node. We now know the neighbor's phase. */ register_encounter(&hdr->sender, reception_time); /* Go through the list of packets to be sent to see if any of them match the sender of the probe, or if they are a broadcast packet that should be sent. */ if(list_length(queued_packets_list) > 0) { struct queue_list_item *i; for(i = list_head(queued_packets_list); i != NULL; i = i->next) { struct lpp_hdr *qhdr; qhdr = queuebuf_dataptr(i->packet); if(rimeaddr_cmp(&qhdr->receiver, &hdr->sender) || rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) { queuebuf_to_packetbuf(i->packet); #if WITH_PENDING_BROADCAST if(i->broadcast_flag == BROADCAST_FLAG_NONE || i->broadcast_flag == BROADCAST_FLAG_SEND) { radio->send(queuebuf_dataptr(i->packet), queuebuf_datalen(i->packet)); PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->sender.u8[0], hdr->sender.u8[1], qhdr->receiver.u8[0], qhdr->receiver.u8[1]); } else { PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->sender.u8[0], hdr->sender.u8[1]); } #else /* WITH_PENDING_BROADCAST */ radio->send(queuebuf_dataptr(i->packet), queuebuf_datalen(i->packet)); PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->sender.u8[0], hdr->sender.u8[1], qhdr->receiver.u8[0], qhdr->receiver.u8[1]); #endif /* WITH_PENDING_BROADCAST */ /* Attribute the energy spent on listening for the probe to this packet transmission. */ compower_accumulate(&i->compower); /* If the packet was not a broadcast packet, we dequeue it now. Broadcast packets should be transmitted to all neighbors, and are dequeued by the dutycycling function instead, after the appropriate time. */ if(!rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) { remove_queued_packet(i); #if WITH_PROBE_AFTER_TRANSMISSION /* Send a probe packet to catch any reply from the other node. */ restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME); #endif /* WITH_PROBE_AFTER_TRANSMISSION */ #if WITH_STREAMING if(is_streaming) { ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME, send_stream_probe, NULL); } #endif /* WITH_STREAMING */ } #if WITH_ACK_OPTIMIZATION if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) { /* We're sending a packet that needs an ACK, so we keep the radio on in anticipation of the ACK. */ turn_radio_on(); } #endif /* WITH_ACK_OPTIMIZATION */ } } } } else if(hdr->type == TYPE_DATA) { if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { /* Not broadcast or for us */ PRINTF("%d.%d: data not for us from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->sender.u8[0], hdr->sender.u8[1]); return 0; } packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr->receiver); } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr->sender); PRINTF("%d.%d: got data from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr->sender.u8[0], hdr->sender.u8[1]); /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #if WITH_PENDING_BROADCAST if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { /* This is a broadcast packet. Check the list of pending packets to see if we are currently sending a broadcast. If so, we refrain from sending our broadcast until one sleep cycle period, so that the other broadcaster will have finished sending. */ struct queue_list_item *i; for(i = list_head(queued_packets_list); i != NULL; i = i->next) { /* If the packet is a broadcast packet that is not yet ready to be sent, we do not send it. */ if(i->broadcast_flag == BROADCAST_FLAG_PENDING) { PRINTF("Someone else is sending, pending -> waiting\n"); set_broadcast_flag(i, BROADCAST_FLAG_WAITING); } } } #endif /* WITH_PENDING_BROADCAST */ #if WITH_PROBE_AFTER_RECEPTION /* XXX send probe after receiving a packet to facilitate data streaming. We must first copy the contents of the packetbuf into a queuebuf to avoid overwriting the data with the probe packet. */ if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { struct queuebuf *q; q = queuebuf_new_from_packetbuf(); if(q != NULL) { send_probe(); queuebuf_to_packetbuf(q); queuebuf_free(q); } } #endif /* WITH_PROBE_AFTER_RECEPTION */ #if WITH_ADAPTIVE_OFF_TIME off_time = LOWEST_OFF_TIME; restart_dutycycle(off_time); #endif /* WITH_ADAPTIVE_OFF_TIME */ } len = packetbuf_datalen(); } return len; }
/*---------------------------------------------------------------------------*/ 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) { static int cl_temp; static int cl_sec; unsigned int clock; unsigned int second; double temp; //printf("recieved msg at clock time: %d \n",clock_time()- offset - prop_delay); //printf( "%d \n",clock_time()- offset - prop_delay); TWAMPtimestamp ts_rcv; clock = clock_time(); second = clock/CLOCK_SECOND; printf("RECEIVE AT: clock: %d || second: %d \n",clock,second); //temp = (double) (clock - start_time)/CLOCK_SECOND - second; temp = (double) (clock)/CLOCK_SECOND - second; ts_rcv.Second = second; ts_rcv.Fraction = temp * 1000; printf("Data received from "); uip_debug_ipaddr_print(sender_addr); printf(" on port %d from port %d \n", receiver_port, sender_port); printf("Datalen = %d\n",datalen); SenderUAuthPacket sender_pkt; memset(&sender_pkt, 0, sizeof(sender_pkt)); memcpy(&sender_pkt, data, datalen); ReflectorUAuthPacket reflect_pkt; //printf("Paket size = %d\n", sizeof(reflect_pkt)); reflect_pkt.SeqNo = seqno; reflect_pkt.ErrorEstimate = 999; reflect_pkt.ReceiverTimestamp = ts_rcv; reflect_pkt.SenderSeqNo = sender_pkt.SeqNo; reflect_pkt.SenderTimestamp = sender_pkt.Timestamp; reflect_pkt.SenderErrorEstimate = sender_pkt.ErrorEstimate; reflect_pkt.SenderTTL = 255; clock = clock_time(); second = clock/CLOCK_SECOND; temp = (double) (clock)/CLOCK_SECOND - second; reflect_pkt.Timestamp.Second = second; reflect_pkt.Timestamp.Fraction = temp * 1000; simple_udp_sendto(&unicast_connection, &reflect_pkt, sizeof(reflect_pkt), sender_addr); printf("Packet reflected to:\n"); uip_debug_ipaddr_print(sender_addr); printf("\n#################\n"); //Prints for debugging printf("SeqNo: %"PRIu32"\n", sender_pkt.SeqNo); printf("Seconds: %"PRIu32"\n", sender_pkt.Timestamp.Second); printf("Micro: %"PRIu32"\n", sender_pkt.Timestamp.Fraction); printf("Error: %"PRIu16"\n", sender_pkt.ErrorEstimate); current++; }
/*===========================================================================* * fs_readsuper * *===========================================================================*/ int fs_readsuper() { /* This function reads the superblock of the partition, gets the root inode * and sends back the details of them. Note, that the FS process does not * know the index of the vmnt object which refers to it, whenever the pathname * lookup leaves a partition an -ELEAVEMOUNT error is transferred back * so that the VFS knows that it has to find the vnode on which this FS * process' partition is mounted on. */ struct ext2_inode *root_ip; cp_grant_id_t label_gid; size_t label_len; int r = 0; endpoint_t driver_e; int readonly, isroot; u32_t mask; fs_dev = fs_m_in.REQ_DEV; label_gid = fs_m_in.REQ_GRANT; label_len = fs_m_in.REQ_PATH_LEN; readonly = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0; isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0; if (label_len > sizeof(fs_dev_label)) return(-EINVAL); r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label, label_len, D); if (r != 0) { printk("%s:%d fs_readsuper: safecopyfrom failed: %d\n", __FILE__, __LINE__, r); return(-EINVAL); } r= ds_retrieve_u32(fs_dev_label, &driver_e); if (r != 0) { printk("ext2:fs_readsuper: ds_retrieve_label_endpt failed for '%s': %d\n", fs_dev_label, r); return -EINVAL; } /* Map the driver endpoint for this major */ driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e; /* Open the device the file system lives on. */ if (dev_open(driver_e, fs_dev, driver_e, readonly ? R_BIT : (R_BIT|W_BIT)) != 0) { return(-EINVAL); } /* Fill in the super block. */ STATICINIT(superblock, sizeof(struct ext2_super_block)); if (!superblock) panic("EXT2","Can't allocate memory for superblock.",NO_NUM); superblock->s_dev = fs_dev; /* read_super() needs to know which dev */ r = read_super(superblock); /* Is it recognized as a Minix filesystem? */ if (r != 0) { superblock->s_dev = NO_DEV; dev_close(driver_e, fs_dev); return(r); } if (superblock->s_rev_level != EXT2_GOOD_OLD_REV) { struct ext2_super_block *sp = superblock; /* just shorter name */ mask = ~SUPPORTED_INCOMPAT_FEATURES; if (HAS_INCOMPAT_FEATURE(sp, mask)) { if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_COMPRESSION & mask)) printk("ext2: fs compression is not supported by server\n"); if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_FILETYPE & mask)) printk("ext2: fs in dir filetype is not supported by server\n"); if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_RECOVER & mask)) printk("ext2: fs recovery is not supported by server\n"); if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_JOURNAL_DEV & mask)) printk("ext2: fs journal dev is not supported by server\n"); if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_META_BG & mask)) printk("ext2: fs meta bg is not supported by server\n"); return(-EINVAL); } mask = ~SUPPORTED_RO_COMPAT_FEATURES; if (HAS_RO_COMPAT_FEATURE(sp, mask)) { if (HAS_RO_COMPAT_FEATURE(sp, RO_COMPAT_SPARSE_SUPER & mask)) { printk("ext2: sparse super is not supported by server, \ remount read-only\n"); } if (HAS_RO_COMPAT_FEATURE(sp, RO_COMPAT_LARGE_FILE & mask)) { printk("ext2: large files are not supported by server, \ remount read-only\n"); } if (HAS_RO_COMPAT_FEATURE(sp, RO_COMPAT_BTREE_DIR & mask)) { printk("ext2: dir's btree is not supported by server, \ remount read-only\n"); } return(-EINVAL); } } if (superblock->s_state == EXT2_ERROR_FS) { printk("ext2: filesystem wasn't cleanly unmounted previous time\n"); superblock->s_dev = NO_DEV; dev_close(driver_e, fs_dev); return(-EINVAL); } set_blocksize(superblock->s_block_size); /* Get the root inode of the mounted file system. */ if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL) { printk("ext2: couldn't get root inode\n"); superblock->s_dev = NO_DEV; dev_close(driver_e, fs_dev); return(-EINVAL); } if (root_ip != NULL && root_ip->i_mode == 0) { printk("%s:%d zero mode for root inode?\n", __FILE__, __LINE__); put_inode(root_ip); superblock->s_dev = NO_DEV; dev_close(driver_e, fs_dev); return(-EINVAL); } if (root_ip != NULL && (root_ip->i_mode & I_TYPE) != I_DIRECTORY) { printk("%s:%d root inode has wrong type, it's not a DIR\n", __FILE__, __LINE__); put_inode(root_ip); superblock->s_dev = NO_DEV; dev_close(driver_e, fs_dev); return(-EINVAL); } superblock->s_rd_only = readonly; superblock->s_is_root = isroot; if (!readonly) { superblock->s_state = EXT2_ERROR_FS; superblock->s_mnt_count++; superblock->s_mtime = clock_time(); write_super(superblock); /* Commit info, we just set above */ } /* Root inode properties */ fs_m_out.RES_INODE_NR = root_ip->i_num; fs_m_out.RES_MODE = root_ip->i_mode; fs_m_out.RES_FILE_SIZE_LO = root_ip->i_size; fs_m_out.RES_UID = root_ip->i_uid; fs_m_out.RES_GID = root_ip->i_gid; return(r); }
void rt_callback(struct rtimer *t, void *ptr) { rt_now = RTIMER_NOW(); ct = clock_time(); printf("Task called at %u (clock = %u)\n", rt_now, ct); }
void c_lqe_ewma_recv(struct pipe *p, struct stackmodule_i *module){ PRINTF("c_lqe_ewma_recv seqno %u \n", packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)); uint16_t crtseqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); int16_t l = 0; struct c_neighbor *n; struct c_neighbor *new_n = memb_alloc(&p->neighbor_mem);; rimeaddr_copy(&new_n->addr, get_node_addr(0, 1, 0)); double alpha = p->lqe_ewma_param.alpha; uint8_t list_len = list_length(p->neighbor_list); double highest_cost = 100.0; /* Find the neighbor. */ for(n = list_head(p->neighbor_list); n != NULL; n = list_item_next(n)) { if(rimeaddr_cmp(&new_n->addr, &n->addr)) { if (highest_cost > n->cost) { highest_cost = n->cost; } PRINTF("node found \n"); PRINTF("n-lastseqno %d n-m %d n-k %d\n", n->last_seq_no, n->m, n->k); new_n->m = crtseqno - n->last_seq_no - 1; //the current seq number - last seq number - crt packet no if (new_n->m > n->k) { l = new_n->m - n->k; new_n->k = n->k; } else { l = 0; new_n->k = 0; } PRINTF("newn-lastseqno %d newn-m %d newn-k %d\n", new_n->last_seq_no, new_n->m, new_n->k); uint8_t lost_p; for(lost_p = 0; lost_p < l; lost_p++) { n->cost *= alpha; } new_n->cost = n->cost * alpha + (1 - alpha); PRINTF("l %d cost %f\n", l, new_n->cost); if (n->count_lock == 1) { new_n->count = n->count; } else { new_n->count = n->count + 1; } new_n->first_time_stamp = n->first_time_stamp; new_n->last_seq_no = crtseqno; new_n->last_time_stamp = clock_time(); new_n->rate = (new_n->count + new_n->m) / (new_n->last_time_stamp - new_n->first_time_stamp); new_n->cost_lock = 1; list_remove(p->neighbor_list, n); memb_free(&p->neighbor_mem, n); list_push(p->neighbor_list, new_n); print_list(p->neighbor_list); return; } } new_n->count = 1; new_n->cost = 1; new_n->m = 0; new_n->k = 0; new_n->last_seq_no = crtseqno; new_n->rate = 1 / clock_time(); new_n->last_time_stamp = clock_time(); new_n->cost_lock = 1; new_n->first_time_stamp = new_n->last_time_stamp; /*If neighbor is not in the list and list is full, remove from list before adding*/ if (list_len >= NUM_NEIGHBOR_ENTRIES) { for(n = list_head(p->neighbor_list); n != NULL; n = list_item_next(n)) { if (highest_cost == n->cost) { list_remove(p->neighbor_list, n); memb_free(&p->neighbor_mem, n); } } } list_push(p->neighbor_list, new_n); print_list(p->neighbor_list); }
static void set_timer(clock_time_t timeout) { future = clock_time() + timeout; }
/** * The time until the timer expires * * This function returns the time until the timer expires. * * \param t A pointer to the timer * * \return The time until the timer expires * */ clock_time_t timer_remaining(struct timer *t) { return t->start + t->interval - clock_time(); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(clock_test_process, ev, data) { PROCESS_BEGIN(); etimer_set(&et, 2 * CLOCK_SECOND); PROCESS_YIELD(); #if TEST_CLOCK_DELAY_USEC printf("clock_delay_usec test, (10,000 x i) usec:\n"); i = 1; while(i < 7) { start_count = RTIMER_NOW(); clock_delay_usec(10000 * i); end_count = RTIMER_NOW(); diff = end_count - start_count; printf("Requested: %u usec, Real: %u rtimer ticks = ~%u us\n", 10000 * i, diff, diff * 64); i++; } #endif #if TEST_RTIMER printf("Rtimer Test, 1 sec (%u rtimer ticks):\n", RTIMER_SECOND); i = 0; while(i < 5) { etimer_set(&et, 2 * CLOCK_SECOND); printf("=======================\n"); ct = clock_time(); rt_now = RTIMER_NOW(); rt_for = rt_now + RTIMER_SECOND; printf("Now=%u (clock = %u) - For=%u\n", rt_now, ct, rt_for); if(rtimer_set(&rt, rt_for, 1, (rtimer_callback_t) rt_callback, NULL) != RTIMER_OK) { printf("Error setting\n"); } PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); i++; } #endif #if TEST_ETIMER printf("Clock tick and etimer test, 1 sec (%u clock ticks):\n", CLOCK_SECOND); i = 0; while(i < 10) { etimer_set(&et, CLOCK_SECOND); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); count = clock_time(); printf("%u ticks\n", count); leds_toggle(LEDS_RED); i++; } #endif #if TEST_CLOCK_SECONDS printf("Clock seconds test (5s):\n"); i = 0; while(i < 10) { etimer_set(&et, 5 * CLOCK_SECOND); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); sec = clock_seconds(); printf("%lu seconds\n", sec); leds_toggle(LEDS_GREEN); i++; } #endif printf("Done!\n"); PROCESS_END(); }
static void handle_packet(struct deluge_msg_packet *msg) { struct deluge_page *page; uint16_t crc; struct deluge_msg_packet packet; memcpy(&packet, msg, sizeof(packet)); PRINTF("Incoming packet for object id %u, version %u, page %u, packet num %u!\n", (unsigned)packet.object_id, (unsigned)packet.version, (unsigned)packet.pagenum, (unsigned)packet.packetnum); if(packet.pagenum != current_object.current_rx_page) { return; } if(packet.version != current_object.version) { neighbor_inconsistency = 1; } page = ¤t_object.pages[packet.pagenum]; if(packet.version == page->version && !(page->flags & PAGE_COMPLETE)) { memcpy(¤t_object.current_page[S_PKT * packet.packetnum], packet.payload, S_PKT); crc = crc16_data(packet.payload, S_PKT, 0); if(packet.crc != crc) { PRINTF("packet crc: %hu, calculated crc: %hu\n", packet.crc, crc); return; } page->last_data = clock_time(); page->packet_set |= (1 << packet.packetnum); if(page->packet_set == ALL_PACKETS) { /* This is the last packet of the requested page; stop streaming. */ packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM_END); write_page(¤t_object, packet.pagenum, current_object.current_page); page->version = packet.version; page->flags = PAGE_COMPLETE; PRINTF("Page %u completed\n", packet.pagenum); current_object.current_rx_page++; if(packet.pagenum == OBJECT_PAGE_COUNT(current_object) - 1) { current_object.version = current_object.update_version; leds_on(LEDS_RED); PRINTF("Update completed for object %u, version %u\n", (unsigned)current_object.object_id, packet.version); } else if(current_object.current_rx_page < OBJECT_PAGE_COUNT(current_object)) { if(ctimer_expired(&rx_timer)) { ctimer_set(&rx_timer, CONST_OMEGA * ESTIMATED_TX_TIME + (random_rand() % T_R), send_request, ¤t_object); } } /* Deluge R.3 */ transition(DELUGE_STATE_MAINTAIN); } else { /* More packets to come. Put lower layers in streaming mode. */ packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM); } } }
/* Attempt to associate to a network form an incoming EB */ static int tsch_associate(rtimer_clock_t timestamp) { struct ieee802154_ies ies; uint8_t hdrlen; int i; if(NETSTACK_FRAMER.parse() == FRAMER_FAILED) { PRINTF("TSCH:! framer failed to parse EB (len %u)\n", packetbuf_totlen()); return 0; } if(tsch_packet_parse_eb(&ies, &hdrlen, 0) == 0) { PRINTF("TSCH:! tsch_packet_parse_eb failed to parse EB (len %u)\n", packetbuf_totlen()); return 0; } tsch_current_asn = ies.ie_asn; tsch_join_priority = ies.ie_join_priority + 1; #if TSCH_JOIN_SECURED_ONLY if(!packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) { PRINTF("TSCH:! parse_eb: EB is not secured\n"); return 0; } #endif /* TSCH_JOIN_SECURED_ONLY */ #if LLSEC802154_ENABLED if(!tsch_security_parse_frame(packetbuf_hdrptr(), hdrlen, packetbuf_totlen() - hdrlen - tsch_security_mic_len(), packetbuf_addr(PACKETBUF_ADDR_SENDER), &tsch_current_asn)) { PRINTF("TSCH:! parse_eb: failed to authenticate\n"); return 0; } #endif /* LLSEC802154_ENABLED */ #if TSCH_JOIN_MY_PANID_ONLY /* Check if the EB comes from the PAN ID we expect */ if(packetbuf_attr(PACKETBUF_ATTR_SOURCE_PANID) != IEEE802154_PANID) { PRINTF("TSCH:! parse_eb: PAN ID %x != %x\n", packetbuf_attr(PACKETBUF_ATTR_SOURCE_PANID), IEEE802154_PANID); return 0; } #endif /* TSCH_JOIN_MY_PANID_ONLY */ /* There was no join priority (or 0xff) in the EB, do not join */ if(ies.ie_join_priority == 0xff) { PRINTF("TSCH:! parse_eb: no join priority\n"); return 0; } /* TSCH timeslot timing */ for(i = 0; i < tsch_ts_elements_count; i++) { if(ies.ie_tsch_timeslot_id == 0) { tsch_timing[i] = US_TO_RTIMERTICKS(tsch_default_timing_us[i]); } else { tsch_timing[i] = US_TO_RTIMERTICKS(ies.ie_tsch_timeslot[i]); } } /* TSCH hopping sequence */ if(ies.ie_channel_hopping_sequence_id == 0) { memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)); TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)); } else { if(ies.ie_hopping_sequence_len <= sizeof(tsch_hopping_sequence)) { memcpy(tsch_hopping_sequence, ies.ie_hopping_sequence_list, ies.ie_hopping_sequence_len); TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len); } else { PRINTF("TSCH:! parse_eb: hopping sequence too long (%u)\n", ies.ie_hopping_sequence_len); return 0; } } #if TSCH_CHECK_TIME_AT_ASSOCIATION > 0 /* Divide by 4k and multiply again to avoid integer overflow */ uint32_t expected_asn = 4096 * TSCH_CLOCK_TO_SLOTS(clock_time() / 4096, tsch_timing_timeslot_length); /* Expected ASN based on our current time*/ int32_t asn_threshold = TSCH_CHECK_TIME_AT_ASSOCIATION * 60ul * TSCH_CLOCK_TO_SLOTS(CLOCK_SECOND, tsch_timing_timeslot_length); int32_t asn_diff = (int32_t)tsch_current_asn.ls4b - expected_asn; if(asn_diff > asn_threshold) { PRINTF("TSCH:! EB ASN rejected %lx %lx %ld\n", tsch_current_asn.ls4b, expected_asn, asn_diff); return 0; } #endif #if TSCH_INIT_SCHEDULE_FROM_EB /* Create schedule */ if(ies.ie_tsch_slotframe_and_link.num_slotframes == 0) { #if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL PRINTF("TSCH: parse_eb: no schedule, setting up minimal schedule\n"); tsch_schedule_create_minimal(); #else PRINTF("TSCH: parse_eb: no schedule\n"); #endif } else { /* First, empty current schedule */ tsch_schedule_remove_all_slotframes(); /* We support only 0 or 1 slotframe in this IE */ int num_links = ies.ie_tsch_slotframe_and_link.num_links; if(num_links <= FRAME802154E_IE_MAX_LINKS) { int i; struct tsch_slotframe *sf = tsch_schedule_add_slotframe( ies.ie_tsch_slotframe_and_link.slotframe_handle, ies.ie_tsch_slotframe_and_link.slotframe_size); for(i = 0; i < num_links; i++) { tsch_schedule_add_link(sf, ies.ie_tsch_slotframe_and_link.links[i].link_options, LINK_TYPE_ADVERTISING, &tsch_broadcast_address, ies.ie_tsch_slotframe_and_link.links[i].timeslot, ies.ie_tsch_slotframe_and_link.links[i].channel_offset); } } else { PRINTF("TSCH:! parse_eb: too many links in schedule (%u)\n", num_links); return 0; } } #endif /* TSCH_INIT_SCHEDULE_FROM_EB */ if(tsch_join_priority < TSCH_MAX_JOIN_PRIORITY) { struct tsch_neighbor *n; /* Add coordinator to list of neighbors, lock the entry */ n = tsch_queue_add_nbr(packetbuf_addr(PACKETBUF_ADDR_SENDER)); if(n != NULL) { tsch_queue_update_time_source(packetbuf_addr(PACKETBUF_ADDR_SENDER)); /* Set PANID */ frame802154_set_pan_id(packetbuf_attr(PACKETBUF_ATTR_SOURCE_PANID)); /* Synchronize on EB */ tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], &tsch_current_asn); /* Update global flags */ tsch_is_associated = 1; #if LLSEC802154_ENABLED tsch_is_pan_secured = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); #else /* LLSEC802154_ENABLED */ tsch_is_pan_secured = 0; #endif /* LLSEC802154_ENABLED */ /* Start sending keep-alives now that tsch_is_associated is set */ tsch_schedule_keepalive(); #ifdef TSCH_CALLBACK_JOINING_NETWORK TSCH_CALLBACK_JOINING_NETWORK(); #endif PRINTF("TSCH: association done, sec %u, PAN ID %x, asn-%x.%lx, jp %u, timeslot id %u, hopping id %u, slotframe len %u with %u links, from ", tsch_is_pan_secured, packetbuf_attr(PACKETBUF_ATTR_SOURCE_PANID), tsch_current_asn.ms1b, tsch_current_asn.ls4b, tsch_join_priority, ies.ie_tsch_timeslot_id, ies.ie_channel_hopping_sequence_id, ies.ie_tsch_slotframe_and_link.slotframe_size, ies.ie_tsch_slotframe_and_link.num_links); PRINTLLADDR((const uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTF("\n"); return 1; } } PRINTF("TSCH:! did not associate.\n"); return 0; }
node_info_t * node_info_update(uip_ipaddr_t * ipaddr, char * info) { node_info_t *node = NULL; char * sep; uip_ipaddr_t ip_parent; node = node_info_lookup(ipaddr); if (node == NULL) { node = node_info_add(ipaddr); } if ( node != NULL ) { node->last_seen = clock_time(); node->last_message = clock_time(); uint16_t up_sequence = 0; uint16_t down_sequence = 0; sep = index(info, '|'); if (sep != NULL) { node->messages_received++; up_sequence = atoi(info); *sep = 0; info = sep + 1; if (*info == ' ') { info++; } sep = index(info, '|'); if (sep != NULL) { *sep = 0; } if (uiplib_ipaddrconv(info, &ip_parent) == 0) { uip_create_unspecified(&ip_parent); } if(!uip_ipaddr_cmp(&node->ip_parent, &ip_parent)) { uip_ipaddr_copy(&(node->ip_parent), &ip_parent); if (node->messages_received > 1) { node->parent_switch++; } } if (sep != NULL) { info = sep + 1; down_sequence = atoi(info); } if (node->messages_received > 1) { uint16_t up_delta = up_sequence - node->last_up_sequence; if (up_delta < 100) { node->messages_sent += up_delta; node->up_messages_lost += up_delta - 1; if(down_sequence != node->last_down_sequence + 1) { node->down_messages_lost += 1; } } else { //Reset statistics node->messages_sent = 1; node->replies_sent = 0; node->up_messages_lost = 0; node->down_messages_lost = 0; } } else { node->messages_sent = 1; node->replies_sent = 0; node->up_messages_lost = 0; node->down_messages_lost = 0; } node->last_up_sequence = up_sequence; node->last_down_sequence = down_sequence; } else { node->last_up_sequence = 0; node->last_down_sequence = 0; uip_create_unspecified(&node->ip_parent); } } return node; }
/** * Set a timer. * * This function is used to set a timer for a time sometime in the * future. The function timer_expired() will evaluate to true after * the timer has expired. * * \param t A pointer to the timer * \param interval The interval before the timer expires. * */ void timer_set(struct timer *t, clock_time_t interval) { t->interval = interval; t->start = clock_time(); }
/** * Check if a timer has expired. * * This function tests if a timer has expired and returns true or * false depending on its status. * * \param t A pointer to the timer * * \return Non-zero if the timer has expired, zero otherwise. * */ int timer_expired(struct timer *t) { return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval; }
static PT_THREAD(generate_sensors(struct httpd_state *s)) { static int i; #if BUF_USES_STACK char buf[BUF_SIZE]; #endif #if WEBSERVER_CONF_LOADTIME static clock_time_t numticks; numticks = clock_time(); #endif PSOCK_BEGIN(&s->sout); SEND_STRING(&s->sout, TOP); SEND_STRING(&s->sout, BODY); reset_buf(); add_div_home("Sensors"); add("<div id=\"left_home\">"); add ("<table>" "<theader><tr class=\"row_first\"><td>Node</td><td>Type</td><td>Status</td><td>Last seen</td></tr></theader>" "<tbody>"); SEND_STRING(&s->sout, buf); reset_buf(); for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { if(node_info_table[i].isused) { add("<tr><td><a href=http://["); ipaddr_add(&node_info_table[i].ipaddr); add("]/>"); SEND_STRING(&s->sout, buf); //TODO: why tunslip6 needs an output here, wpcapslip does not reset_buf(); ipaddr_add(&node_info_table[i].ipaddr); add("</a></td>"); if(node_info_table[i].ipaddr.u8[8] == 0x02 && node_info_table[i].ipaddr.u8[9] == 0x12 && node_info_table[i].ipaddr.u8[10] == 0x74) { add("<td><a href=http://["); ipaddr_add(&node_info_table[i].ipaddr); add("]/status.shtml>Crossbow Telos</a></td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0x02 && node_info_table[i].ipaddr.u8[9] == 0x50 && node_info_table[i].ipaddr.u8[10] == 0xC2 && node_info_table[i].ipaddr.u8[11] == 0xA8 && (node_info_table[i].ipaddr.u8[12] & 0XF0) == 0xC0) { add("<td>Redwire Econotag I</td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0xEE && node_info_table[i].ipaddr.u8[9] == 0x47 && node_info_table[i].ipaddr.u8[10] == 0x3C) { if(node_info_table[i].ipaddr.u8[11] == 0x4D && node_info_table[i].ipaddr.u8[12] == 0x12) { add("<td>Redwire M12</td>"); } else { add("<td>Redwire Unknown</td>"); } } else if((node_info_table[i].ipaddr.u8[8] & 0x02) == 0) { add("<td>User defined</td>"); } else { add("<td>Unknown</td>"); } add("<td>%s</td>", node_info_table[i].my_info); add("<td>%d</td>", (clock_time() - node_info_table[i].last_lookup) / CLOCK_SECOND); add("</tr>"); SEND_STRING(&s->sout, buf); reset_buf(); } } add("</tbody></table><br />"); SEND_STRING(&s->sout, buf); reset_buf(); add ("<center>" "<img src=\"http://chart.googleapis.com/chart?cht=gv&chls=1&chl=digraph{_%04x;", (uip_lladdr.addr[6] << 8) + uip_lladdr.addr[7]); for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { if(node_info_table[i].isused) { int l = strlen(node_info_table[i].my_info); if(l > 4) { add("_%04hx->_%s;", (node_info_table[i].ipaddr.u8[14] << 8) + node_info_table[i].ipaddr.u8[15], &node_info_table[i].my_info[l - 4]); } } } add("}\"alt=\"\" /></center>"); SEND_STRING(&s->sout, buf); reset_buf(); add_div_footer(); #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; add("<br><i>This page sent %u times</i>", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME numticks = clock_time() - numticks + 1; add(" <i>(%u.%02u sec)</i>", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND) / CLOCK_SECOND)); #endif add("</div></div>"); SEND_STRING(&s->sout, buf); SEND_STRING(&s->sout, BOTTOM); PSOCK_END(&s->sout); }
/* * A protosocket always requires a protothread. The protothread * contains the code that uses the protosocket. We define the * protothread here. */ static PT_THREAD(connection_setup(struct psock *p)) { /* * A protosocket's protothread must start with a PSOCK_BEGIN(), with * the protosocket as argument. */ PSOCK_BEGIN(p); printf("TIME: %d\n",clock_time()); /* * Here we define all the thread local variables that we need to * utilize. */ static ServerGreeting greet; static SetupResponseUAuth setup; static ServerStartMsg start; static int i; static int acceptedMode = 1; /* * We configure the Server-Greeting that we want to send. Setting * the accepted modes to those we accept. The following modes are * meaningful: * 1 - Unauthenticated * 2 - Authenticated * 3 - Encrypted * 0 - Do not wish to communicate. */ memset(&greet, 0, sizeof(greet)); greet.Modes = 1; /* * We generate random sequence of octects for the challenge and * salt. */ for (i = 0; i < 16; i++){ greet.Challenge[i] = rand() % 16; } for (i = 0; i < 16; i++){ greet.Salt[i] = rand() % 16; } /* * Count must be a power of 2 and be at least 1024. */ //greet.Count = (1 << 12); /* * We set the MBZ octets to zero. */ for (i = 0; i < 12; i++){ greet.MBZ[i] = 0; } /* * Using PSOCK_SEND() we send the Server-Greeting to the connected * client. */ PSOCK_SEND(p, &greet, sizeof(greet)); /* * We wait until we receive a server greeting from the server. * PSOCK_NEWDATA(p) returns 1 when new data has arrived in * the protosocket. */ PSOCK_WAIT_UNTIL(p,PSOCK_NEWDATA(p)); if(PSOCK_NEWDATA(p)){ /* * We read data from the buffer now that it has arrived. * Using memcpy we store it in our local variable. */ PSOCK_READBUF(p); memcpy(&setup,buffer,sizeof(setup)); if(setup.Modes != acceptedMode){ printf("Client did not match our modes!\n"); PSOCK_CLOSE_EXIT(p); } else{ /* * We have agreed upon the mode. Now we send the Server-Start * message. */ memset(&start,0,sizeof(start)); /* * We set the MBZ octets to zero. */ for (i = 0; i < 15; i++){ start.MBZ1[i] = 0; } for (i = 0; i < 8; i++){ start.MBZ2[i] = 0; } /* * The accept field is set to zero if the server wishes to continue * communicating. A non-zero value is defined as in RFC 4656. */ start.Accept = 0; /* * Timestamp is set to the time the Server started. */ double temp; start.timestamp.Second = clock_seconds(); temp = (double) clock_time()/CLOCK_SECOND - start.timestamp.Second; start.timestamp.Fraction = temp*1000; /* * Using PSOCK_SEND() we send the Server-Start to the connected * client. */ PSOCK_SEND(p, &start, sizeof(start)); printf("Client agreed to mode: %d\n",setup.Modes); } } else { printf("Timed out!\n"); } state = 2; PSOCK_END(p); }
static PT_THREAD(generate_network(struct httpd_state *s)) { static int i; static uip_ds6_route_t *r; static uip_ds6_defrt_t *dr; #if BUF_USES_STACK char buf[BUF_SIZE]; #endif #if WEBSERVER_CONF_LOADTIME static clock_time_t numticks; numticks = clock_time(); #endif PSOCK_BEGIN(&s->sout); SEND_STRING(&s->sout, TOP); if(redirect) { //Quick hack to rewrite url after route or neighbour removal SEND_STRING(&s->sout, "<meta http-equiv=\"refresh\" content=\"0; url=/network.html\" />"); } SEND_STRING(&s->sout, BODY); reset_buf(); add_div_home("Network"); add("<div id=\"left_home\">"); add("<br /><h2>Addresses</h2><pre>"); SEND_STRING(&s->sout, buf); reset_buf(); 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); char flag; if(uip_ds6_if.addr_list[i].state == ADDR_TENTATIVE) { flag = 'T'; } else if(uip_ds6_if.addr_list[i].state == ADDR_PREFERRED) { flag = 'P'; } else { flag = '?'; } add(" %c", flag); if(uip_ds6_if.addr_list[i].type == ADDR_MANUAL) { flag = 'M'; } else if(uip_ds6_if.addr_list[i].type == ADDR_DHCP) { flag = 'D'; } else if(uip_ds6_if.addr_list[i].type == ADDR_AUTOCONF) { flag = 'A'; } else { flag = '?'; } add(" %c", flag); if(!uip_ds6_if.addr_list[i].isinfinite) { add(" %u s", stimer_remaining(&uip_ds6_if.addr_list[i].vlifetime)); } add("\n"); SEND_STRING(&s->sout, buf); reset_buf(); } } add("</pre><h2>Prefixes</h2><pre>"); for(i = 0; i < UIP_DS6_PREFIX_NB; i++) { if(uip_ds6_prefix_list[i].isused) { ipaddr_add(&uip_ds6_prefix_list[i].ipaddr); add(" "); #if UIP_CONF_ROUTER if(uip_ds6_prefix_list[i].advertise) { add("A"); } #else if(uip_ds6_prefix_list[i].isinfinite) { add("I"); } #endif add("\n"); } } SEND_STRING(&s->sout, buf); reset_buf(); add("</pre><h2>Neighbors</h2><pre>"); for(i = 0; i < UIP_DS6_NBR_NB; i++) { if(uip_ds6_nbr_cache[i].isused) { if ((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_CONFIG) == 0) { add("[<a href=\"nbr_rm?%d\">del</a>] ", i); } ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr); add(" "); lladdr_add(&uip_ds6_nbr_cache[i].lladdr); add(" "); add_network_cases(uip_ds6_nbr_cache[i].state); add("\n"); SEND_STRING(&s->sout, buf); reset_buf(); } } add("</pre><h2>Routes</h2><pre>"); SEND_STRING(&s->sout, buf); reset_buf(); for(r = uip_ds6_route_list_head(), i = 0; r != NULL; r = list_item_next(r), ++i) { if ((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_CONFIG) == 0) { add("[<a href=\"route_rm?%d\">del</a>] ", i); } ipaddr_add(&r->ipaddr); add("/%u (via ", r->length); ipaddr_add(&r->nexthop); if(1 || (r->state.lifetime < 600)) { add(") %lu s\n", r->state.lifetime); } else { add(")\n"); } SEND_STRING(&s->sout, buf); reset_buf(); } add("</pre><h2>Default Routers</h2><pre>"); for(dr = uip_ds6_defrt_list_head(); dr != NULL; dr = list_item_next(r)) { ipaddr_add(&dr->ipaddr); if(!dr->isinfinite) { add(" %u s", stimer_remaining(&dr->lifetime)); } add("\n"); SEND_STRING(&s->sout, buf); reset_buf(); } #if UIP_CONF_DS6_ROUTE_INFORMATION add("</pre><h2>Route info</h2><pre>"); for(i = 0; i < UIP_DS6_ROUTE_INFO_NB; i++) { if(uip_ds6_route_info_list[i].isused) { ipaddr_add(&uip_ds6_route_info_list[i].ipaddr); add("/%u (%x) %us\n", uip_ds6_route_info_list[i].length, uip_ds6_route_info_list[i].flags, uip_ds6_route_info_list[i].lifetime); } } SEND_STRING(&s->sout, buf); reset_buf(); #endif #if CETIC_6LBR_TRANSPARENTBRIDGE add("</pre><h2>HW Prefixes cache</h2><pre>"); for(i = 0; i < prefixCounter; i++) { add("%02x:%02x:%02x\n", prefixBuffer[i][0], prefixBuffer[i][1], prefixBuffer[i][2]); } SEND_STRING(&s->sout, buf); reset_buf(); add("</pre><br />"); #endif add_div_footer(); #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; add("<br><i>This page sent %u times</i>", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME numticks = clock_time() - numticks + 1; add(" <i>(%u.%02u sec)</i>", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND) / CLOCK_SECOND)); #endif add("</div></div>"); SEND_STRING(&s->sout, buf); SEND_STRING(&s->sout, BOTTOM); PSOCK_END(&s->sout); }
/** * Read a packet from the underlying radio driver. If the incoming * packet is a probe packet and the sender of the probe matches the * destination address of the queued packet (if any), the queued packet * is sent. */ static void input_packet(void) { struct lpp_hdr hdr; clock_time_t reception_time; reception_time = clock_time(); if(!NETSTACK_FRAMER.parse()) { printf("lpp input_packet framer error\n"); } memcpy(&hdr, packetbuf_dataptr(), sizeof(struct lpp_hdr));; packetbuf_hdrreduce(sizeof(struct lpp_hdr)); /* PRINTF("got packet type %d\n", hdr->type);*/ if(hdr.type == TYPE_PROBE) { struct announcement_msg adata; /* Register the encounter with the sending node. We now know the neighbor's phase. */ register_encounter(&hdr.sender, reception_time); /* Parse incoming announcements */ memcpy(&adata, packetbuf_dataptr(), MIN(packetbuf_datalen(), sizeof(adata))); #if 0 PRINTF("%d.%d: probe from %d.%d with %d announcements\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], adata->num); if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) { /* Sanity check. The number of announcements is too large - corrupt packet has been received. */ return 0; } for(i = 0; i < adata.num; ++i) { /* PRINTF("%d.%d: announcement %d: %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->data[i].id, adata->data[i].value);*/ announcement_heard(&hdr.sender, adata.data[i].id, adata.data[i].value); } #endif /* 0 */ /* Go through the list of packets to be sent to see if any of them match the sender of the probe, or if they are a broadcast packet that should be sent. */ if(list_length(queued_packets_list) > 0) { struct queue_list_item *i; for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) { const rimeaddr_t *receiver; uint8_t sent; sent = 0; receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER); if(rimeaddr_cmp(receiver, &hdr.sender) || rimeaddr_cmp(receiver, &rimeaddr_null)) { queuebuf_to_packetbuf(i->packet); #if WITH_PENDING_BROADCAST if(i->broadcast_flag == BROADCAST_FLAG_NONE || i->broadcast_flag == BROADCAST_FLAG_SEND) { i->num_transmissions = 1; NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), queuebuf_datalen(i->packet)); sent = 1; PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], receiver->u8[0], receiver->u8[1]); } else { PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); } #else /* WITH_PENDING_BROADCAST */ i->num_transmissions = 1; NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), queuebuf_datalen(i->packet)); PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], receiver->u8[0], receiver->u8[1]); #endif /* WITH_PENDING_BROADCAST */ /* off();*/ /* Attribute the energy spent on listening for the probe to this packet transmission. */ compower_accumulate(&i->compower); /* If the packet was not a broadcast packet, we dequeue it now. Broadcast packets should be transmitted to all neighbors, and are dequeued by the dutycycling function instead, after the appropriate time. */ if(!rimeaddr_cmp(receiver, &rimeaddr_null)) { #define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 5000 #define ACK_LEN 3 #define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1000 rtimer_clock_t wt; uint8_t ack_received = 0; wt = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { } /* Check for incoming ACK. */ if((NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet() || NETSTACK_RADIO.channel_clear() == 0)) { int len; uint8_t ackbuf[ACK_LEN]; wt = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { } len = NETSTACK_RADIO.read(ackbuf, ACK_LEN); } if(ack_received) { remove_queued_packet(i, 1); } else { remove_queued_packet(i, 0); } #if WITH_PROBE_AFTER_TRANSMISSION /* Send a probe packet to catch any reply from the other node. */ restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME); #endif /* WITH_PROBE_AFTER_TRANSMISSION */ #if WITH_STREAMING if(is_streaming) { ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME, send_stream_probe, NULL); } #endif /* WITH_STREAMING */ } if(sent) { turn_radio_off(); } #if WITH_ACK_OPTIMIZATION if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) { /* We're sending a packet that needs an ACK, so we keep the radio on in anticipation of the ACK. */ turn_radio_on(); } #endif /* WITH_ACK_OPTIMIZATION */ } } } } else if(hdr.type == TYPE_DATA) { turn_radio_off(); if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) { if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) { /* Not broadcast or for us */ PRINTF("%d.%d: data not for us from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); return; } packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver); } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender); PRINTF("%d.%d: got data from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #if WITH_PENDING_BROADCAST if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) { /* This is a broadcast packet. Check the list of pending packets to see if we are currently sending a broadcast. If so, we refrain from sending our broadcast until one sleep cycle period, so that the other broadcaster will have finished sending. */ struct queue_list_item *i; for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) { /* If the packet is a broadcast packet that is not yet ready to be sent, we do not send it. */ if(i->broadcast_flag == BROADCAST_FLAG_PENDING) { PRINTF("Someone else is sending, pending -> waiting\n"); set_broadcast_flag(i, BROADCAST_FLAG_WAITING); } } } #endif /* WITH_PENDING_BROADCAST */ #if WITH_PROBE_AFTER_RECEPTION /* XXX send probe after receiving a packet to facilitate data streaming. We must first copy the contents of the packetbuf into a queuebuf to avoid overwriting the data with the probe packet. */ if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) { struct queuebuf *q; q = queuebuf_new_from_packetbuf(); if(q != NULL) { send_probe(); queuebuf_to_packetbuf(q); queuebuf_free(q); } } #endif /* WITH_PROBE_AFTER_RECEPTION */ #if WITH_ADAPTIVE_OFF_TIME off_time = LOWEST_OFF_TIME; restart_dutycycle(off_time); #endif /* WITH_ADAPTIVE_OFF_TIME */ NETSTACK_MAC.input(); } }