/*---------------------------------------------------------------------------*/ static void recv(struct broadcast_conn *bc, const rimeaddr_t *from) { struct trickle_conn *c = (struct trickle_conn *)bc; uint16_t seqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID); PRINTF("%d.%d: trickle recv seqno %d from %d.%d our %d data len %d channel %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], seqno, from->u8[0], from->u8[1], c->seqno, packetbuf_datalen(), packetbuf_attr(PACKETBUF_ATTR_CHANNEL)); if(seqno == c->seqno) { /* c->cb->recv(c);*/ ++c->duplicates; } else if(SEQNO_LT(seqno, c->seqno)) { c->interval_scaling = 0; send(c); } else /* hdr->seqno > c->seqno */ { #if CONTIKI_TARGET_NETSIM /* ether_set_line(from->u8[0], from->u8[1]);*/ #endif /* CONTIKI_TARGET_NETSIM */ c->seqno = seqno; /* Store the incoming data in the queuebuf */ if(c->q != NULL) { queuebuf_free(c->q); } c->q = queuebuf_new_from_packetbuf(); c->interval_scaling = 0; reset_interval(c); ctimer_set(&c->first_transmission_timer, random_rand() % c->interval, send, c); c->cb->recv(c); } }
/*---------------------------------------------------------------------------*/ int handler_802154_frame_received(frame802154_t *frame) { if(answer_beacon_requests && frame->fcf.frame_type == FRAME802154_CMDFRAME && frame->payload[0] == FRAME802154_BEACONREQ) { others_beacon_reply = 0; ctimer_set(NULL, &beacon_send_timer, CLOCK_SECOND / 16 + (CLOCK_SECOND * (random_rand() & 0xff)) / 0x200, &handle_beacon_send_timer, NULL); return 1; } if(frame->fcf.frame_type == FRAME802154_BEACONFRAME) { HANDLER_802154_STAT(handler_802154_stats.beacons_received++); handle_beacon(frame); return 1; } return 0; }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(multicast_example_process, ev, data) { PROCESS_BEGIN(); /* Create a linkl-local multicast addresses. */ uip_ip6addr(&addr, 0xff02, 0, 0, 0, 0, 0, 0x1337, 0x0001); /* Join local group. */ if(uip_ds6_maddr_add(&addr) == NULL) { printf("Error: could not join local multicast group.\n"); } /* Register UDP socket callback */ udp_socket_register(&s, NULL, receiver); /* Bind UDP socket to local port */ udp_socket_bind(&s, PORT); /* Connect UDP socket to remote port */ udp_socket_connect(&s, NULL, PORT); while(1) { /* Set up two timers, one for keeping track of the send interval, which is periodic, and one for setting up a randomized send time within that interval. */ etimer_set(&periodic_timer, SEND_INTERVAL); etimer_set(&send_timer, (random_rand() % SEND_INTERVAL)); PROCESS_WAIT_UNTIL(etimer_expired(&send_timer)); printf("Sending multicast\n"); udp_socket_sendto(&s, "hello", 6, &addr, PORT); PROCESS_WAIT_UNTIL(etimer_expired(&periodic_timer)); } PROCESS_END(); }
static void new_dio_interval(rpl_dag_t *dag) { uint32_t time; /* TODO: too small timer intervals for many cases */ time = 1UL << dag->dio_intcurrent; /* Convert from milliseconds to CLOCK_TICKS. */ time = (time * CLOCK_SECOND) / 1000; dag->dio_next_delay = time; /* random number between I/2 and I */ time = time >> 1; time += (time * random_rand()) / RANDOM_RAND_MAX; /* * The intervals must be equally long among the nodes for Trickle to * operate efficiently. Therefore we need to calculate the delay between * the randomized time and the start time of the next interval. */ dag->dio_next_delay -= time; dag->dio_send = 1; #if RPL_CONF_STATS /* keep some stats */ dag->dio_totint++; dag->dio_totrecv += dag->dio_counter; ANNOTATE("#A rank=Xu.Xu(Xu),stats=Xd Xd Xd Xd,color=Xs");//, DAG_RANK(dag->rank, dag), (10 * (dag->rank % dag->min_hoprankinc)) / dag->min_hoprankinc, dag->version, dag->dio_totint, dag->dio_totsend, dag->dio_totrecv,dag->dio_intcurrent, dag->rank == ROOT_RANK(dag) ? "BLUE" : "ORANGE"); #endif /* RPL_CONF_STATS */ /* reset the redundancy counter */ dag->dio_counter = 0; /* schedule the timer */ PRINTF("RPL: Scheduling DIO timer Xlu ticks in future (Interval)"); PRINTF_DEC(time); ctimer_set(&dag->dio_timer, time, &handle_dio_timer, dag); }
/** * subscribe node will assemble the data according to the conditions */ void assemble_data(){ uint8_t value = random_rand()%10; assemble_total+=value; assemble_count++; if(value>max){ max = value; } if(assemble_count>= local_node.assemble_count){ Runicast_msg runicast_msg; runicast_msg.native_sen_type = local_node.sen_type; runicast_msg.seqno = clct_data_seqno; //runicast_msg.timestamp = CLOCK_SECOND; if(local_node.condition == MAX){ runicast_msg.value = max; }else if(local_node.condition == AVERAGE ){ runicast_msg.value = (assemble_total)/(assemble_count); } rimeaddr_copy(&runicast_msg.last_hop,&rimeaddr_node_addr); rimeaddr_copy(&runicast_msg.source,&rimeaddr_node_addr); //add_to_RU_list(runicast_msg); if(!runicast_is_transmitting(&runicast)){ printf("[PUBLISH] publish data value->%u seqno %u\n",runicast_msg.value,runicast_msg.seqno); //single_publish(&runicast,runicast_msg); printf("[RU] timestamp %d seqno %u last hop address %u.%u\n", runicast_msg.timestamp,runicast_msg.seqno,runicast_msg.last_hop.u8[0],runicast_msg.last_hop.u8[1]); packetbuf_copyfrom(&runicast_msg, sizeof(Runicast_msg)); runicast_send(&runicast,&find_best_route()->rt_entry.next_hop,MAX_RETRANSMISSIONS); packetbuf_clear(); } if(clct_data_seqno>254){ clct_data_seqno = 0; } clct_data_seqno++; assemble_count = 0; assemble_total = 0.0f; max = 0.0f; } }
/*---------------------------------------------------------------------------*/ void uip_ds6_init(void) { uip_ds6_neighbors_init(); uip_ds6_route_init(); PRINTF("Init of IPv6 data structures\n"); PRINTF("%u neighbors\n%u default routers\n%u prefixes\n%u routes\n%u unicast addresses\n%u multicast addresses\n%u anycast addresses\n", NBR_TABLE_MAX_NEIGHBORS, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB, UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB); memset(uip_ds6_prefix_list, 0, sizeof(uip_ds6_prefix_list)); memset(&uip_ds6_if, 0, sizeof(uip_ds6_if)); uip_ds6_addr_size = sizeof(struct uip_ds6_addr); uip_ds6_netif_addr_list_offset = offsetof(struct uip_ds6_netif, addr_list); /* Set interface parameters */ uip_ds6_if.link_mtu = UIP_LINK_MTU; uip_ds6_if.cur_hop_limit = UIP_TTL; uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME; uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time(); uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER; uip_ds6_if.maxdadns = UIP_ND6_DEF_MAXDADNS; uip_ds6_set_lladdr(&uip_lladdr); #if UIP_CONF_ROUTER #if UIP_ND6_SEND_RA stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */ #endif /* UIP_ND6_SEND_RA */ #else /* UIP_CONF_ROUTER */ etimer_set(&uip_ds6_timer_rs, random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND), &tcpip_process); #endif /* UIP_CONF_ROUTER */ etimer_set(&uip_ds6_timer_periodic, UIP_DS6_PERIOD, &tcpip_process); return; }
void generate_random_pan_id_and_aes_key(void) { /* PAN ID and AES key is only generated once at first startup */ if (eeprom_read_byte ((const void *)EE_FIRST_RUN_FLAG)) { uint8_t key[16]; //AES key rf212_generate_key(key); eeprom_write_block(key, (void *)EE_ENCRYPTION_KEY, EE_ENCRYPTION_KEY_SIZE); //PAN ID uint16_t rand_pan_id = 0xFFFF; //init random number generator with first 2 bytes of AES key random_init(eeprom_read_word ((const void *)EE_ENCRYPTION_KEY)); //generate random pan_id which is not the broadcast_pan_id and not the bootloader/provisioning pan_id while (rand_pan_id == 0xFFFF || rand_pan_id == 0x0001) { rand_pan_id = random_rand(); } eeprom_write_word ((void *)EE_PAN_ID, rand_pan_id); eeprom_write_byte ((void *)EE_FIRST_RUN_FLAG, 0x00); } }
/* Corresponds to Rule 6 of Trickle */ static void on_interval_expired(void *ptr) { clock_time_t half_interval_size; if(trickle_doublings < IMAX) { trickle_doublings++; PRINTF("akes-trickle: Doubling interval size\n"); } half_interval_size = interval_size() / 2; new_nbrs_count = 0; counter = 0; ctimer_set(&trickle_timer, half_interval_size + ((half_interval_size * random_rand()) / RANDOM_RAND_MAX), on_timeout, NULL); PRINTF("akes-trickle: I=%lus t=%lus\n", interval_size()/CLOCK_SECOND, trickle_timer.etimer.timer.interval/CLOCK_SECOND); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(collectd_process, ev, data) { static struct etimer period_timer, wait_timer; PROCESS_BEGIN(); collectd_conf_init(&collectd_conf); /* new connection with remote host */ client_conn = udp_new(NULL, UIP_HTONS(0), NULL); udp_bind(client_conn, UIP_HTONS(COLLECTD_CLIENT_PORT)); PRINTF("Created a connection with the server "); /* Send a packet every 60-62 seconds. */ etimer_set(&period_timer, CLOCK_SECOND * DEFAULT_UPDATE_PERIOD); while(1) { PROCESS_WAIT_EVENT(); //send update (collected data) if(ev == PROCESS_EVENT_TIMER) { if (data == &period_timer) { etimer_reset(&period_timer); //TODO: reset the period from collectd_conf.update freq if (collectd_conf.send_active == SEND_ACTIVE_YES) etimer_set(&wait_timer, random_rand() % (CLOCK_SECOND * RANDWAIT)); } else if(data == &wait_timer) { /* Time to send the data */ PRINTF("Time to send the data\n"); collectd_common_send(client_conn, &collectd_conf); } } //receive a request (here, expected a request to begin to send update) if(ev == tcpip_event) { collectd_udp_handler(); } } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ 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) { printf("Data (%d) received on port %d from port %d with length %d\n", *data, receiver_port, sender_port, datalen); #if RANDOM_TOKEN_ERROR if (0 == random_rand() % RANDOM_ERROR) { // this is written just to introduce random error to the algorithm printf("RANDOM Error Occurred\n"); token = 1; } #endif if ( (node_id - ((*data) % NUM_MOTES)) == 1) token = 1; }
/*---------------------------------------------------------------------------*/ void uip_ds6_send_ra_periodic(void) { if(racount > 0) { /* send previously scheduled RA */ uip_nd6_ra_output(NULL); PRINTF("Sending periodic RA\n"); } rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() % (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL); PRINTF("Random time 1 = %u\n", rand_time); if(racount < UIP_ND6_MAX_INITIAL_RAS) { if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) { rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL; PRINTF("Random time 2 = %u\n", rand_time); } racount++; } PRINTF("Random time 3 = %u\n", rand_time); stimer_set(&uip_ds6_timer_ra, rand_time); }
/*---------------------------------------------------------------------------*/ void servreg_hack_register(servreg_hack_id_t id, const uip_ipaddr_t *addr) { static servreg_hack_item_t *t; static struct servreg_hack_registration *r; /* Walk through list, see if we already have a service ID registered. If not, allocate a new registration and put it on our list. If we cannot allocate a service registration, we reuse one from the service registrations made by others. */ servreg_hack_init(); for(t = list_head(own_services); t != NULL; t = list_item_next(t)) { if(servreg_hack_item_id(t) == id) { return; } } r = memb_alloc(®istrations); if(r == NULL) { printf("servreg_hack_register: error, could not allocate memory, should reclaim another registration but this has not been implemented yet.\n"); return; } r->id = id; r->seqno = 1; uip_ipaddr_copy(&r->addr, addr); timer_set(&r->timer, LIFETIME / 2); list_push(own_services, r); PROCESS_CONTEXT_BEGIN(&servreg_hack_process); etimer_set(&sendtimer, random_rand() % (NEW_REG_TIME)); PROCESS_CONTEXT_END(&servreg_hack_process); }
/*---------------------------------------------------------------------------*/ static int run_trickle(struct trickle_conn *c) { clock_time_t interval; PT_BEGIN(&c->pt); while(1) { interval = c->interval << c->interval_scaling; set_timer(c, &c->interval_timer, interval); set_timer(c, &c->t, interval / 2 + (random_rand() % (interval / 2))); c->duplicates = 0; PT_YIELD(&c->pt); /* Wait until listen timeout */ if(c->duplicates < DUPLICATE_THRESHOLD) { send(c); } PT_YIELD(&c->pt); /* Wait until interval timer expired. */ if(c->interval_scaling < INTERVAL_MAX) { c->interval_scaling++; } } PT_END(&c->pt); }
/*---------------------------------------------------------------------------*/ int ipolite_send(struct ipolite_conn *c, clock_time_t interval, uint8_t hdrsize) { if(c->q != NULL) { /* If we are already about to send a packet, we cancel the old one. */ PRINTF("%d.%d: ipolite_send: cancel old send\n", linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1]); queuebuf_free(c->q); c->q = NULL; ctimer_stop(&c->t); } c->dups = 0; c->hdrsize = hdrsize; if(interval == 0) { PRINTF("%d.%d: ipolite_send: interval 0\n", linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1]); if(broadcast_send(&c->c)) { if(c->cb->sent) { c->cb->sent(c); } return 1; } } else { c->q = queuebuf_new_from_packetbuf(); if(c->q != NULL) { ctimer_set(&c->t, interval / 2 + (random_rand() % (interval / 2)), send, c); return 1; } PRINTF("%d.%d: ipolite_send: could not allocate queue buffer\n", linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1]); } return 0; }
char * storage_generate_file(char *prefix, unsigned long size) { static char filename[ATTRIBUTE_NAME_LENGTH + sizeof(".ffff")]; #if !DB_FEATURE_COFFEE int fd; #endif snprintf(filename, sizeof(filename), "%s.%x", prefix, (unsigned)(random_rand() & 0xffff)); #if DB_FEATURE_COFFEE PRINTF("DB: Reserving %lu bytes in %s\n", size, filename); if(cfs_coffee_reserve(filename, size) < 0) { PRINTF("DB: Failed to reserve\n"); return NULL; } return filename; #else fd = cfs_open(filename, CFS_WRITE); cfs_close(fd); return fd < 0 ? NULL : filename; #endif /* DB_FEATURE_COFFEE */ }
/*---------------------------------------------------------------------------*/ uip_ds6_addr_t * uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type) { if(uip_ds6_list_loop ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB, sizeof(uip_ds6_addr_t), ipaddr, 128, (uip_ds6_element_t **)&locaddr) == FREESPACE) { locaddr->isused = 1; uip_ipaddr_copy(&locaddr->ipaddr, ipaddr); locaddr->type = type; if(vlifetime == 0) { locaddr->isinfinite = 1; } else { locaddr->isinfinite = 0; stimer_set(&(locaddr->vlifetime), vlifetime); } #if UIP_ND6_DEF_MAXDADNS > 0 locaddr->state = ADDR_TENTATIVE; timer_set(&locaddr->dadtimer, random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND)); locaddr->dadnscount = 0; #else /* UIP_ND6_DEF_MAXDADNS > 0 */ #if UIP_CONF_6LN || UIP_CONF_6LR locaddr->state = uip_is_addr_link_local(ipaddr) ? ADDR_PREFERRED : ADDR_TENTATIVE; #else /* UIP_CONF_6LN || UIP_CONF_6LR */ locaddr->state = ADDR_PREFERRED; #endif /* UIP_CONF_6LN || UIP_CONF_6LR */ #endif /* UIP_ND6_DEF_MAXDADNS > 0 */ uip_create_solicited_node(ipaddr, &loc_fipaddr); uip_ds6_maddr_add(&loc_fipaddr); return locaddr; } return NULL; }
PROCESS_THREAD(collect_common_process, ev, data) { static struct etimer period_timer, wait_timer; PROCESS_BEGIN(); collect_common_net_init(); /* Send a packet every 60-62 seconds. */ etimer_set(&period_timer, CLOCK_SECOND * PERIOD); while(1) { PROCESS_WAIT_EVENT(); if(ev == serial_line_event_message) { char *line; char query[10]; char reg[2]; line = (char *)data; if(strncmp(line, "collect", 7) == 0 || strncmp(line, "gw", 2) == 0) { collect_common_set_sink(); } else if(strncmp(line, "net", 3) == 0) { collect_common_net_print(); } else if(strncmp(line, "time ", 5) == 0) { unsigned long tmp; line += 6; while(*line == ' ') { line++; } tmp = strtolong(line); time_offset = clock_seconds() - tmp; } else if(strncmp(line, "mac ", 4) == 0) { line +=4; while(*line == ' ') { line++; } if(*line == '0') { NETSTACK_RDC.off(1); } else { NETSTACK_RDC.on(); } } else if(strncmp(line, "~K", 2) == 0 || strncmp(line, "killall", 7) == 0) { /* Ignore stop commands */ } else if(strncmp(line, "Query-",6) == 0){ /* To extract the region information of the requested query */ strcpy(query, line+7); char *pch = NULL; pch = strtok (query,"."); if(strncmp(pch, "x", 1) != 0) { b = atoi(pch); multicast_flag = 0; } else{ b = 0; multicast_flag = 1; #if SCENARIO goto BUILD; #endif } pch = strtok (NULL, "."); if(strncmp(pch, "x", 1) != 0) { f = atoi(pch); multicast_flag = 0; } else{ f = 0; multicast_flag = 1; #if SCENARIO goto LEVL; #endif } pch = strtok (NULL, "."); if(strncmp(pch, "x", 1) != 0) { r = atoi(pch); multicast_flag = 0; } else{ r = 0; multicast_flag = 1; #if SCENARIO goto ROM; #endif } pch = strtok (NULL, "."); if(strncmp(pch, "x", 1) != 0) { sid = atoi(pch); multicast_flag = 0; } else{ sid = 0; multicast_flag = 1; #if SCENARIO goto SENSR; #endif } goto SEND_QR; #if SCENARIO BUILD: for(b=1;b<=3;b++) for(f=1;f<=3;f++) for(r=1;r<=3;r++) for(sid=1;sid<=3;sid++) query_send_sink(b,f,r,sid); goto JUMP; LEVL: for(f=1;f<=3;f++) for(r=1;r<=3;r++) for(sid=1;sid<=3;sid++) query_send_sink(b,f,r,sid); goto JUMP; ROM: for(r=1;r<=3;r++) for(sid=1;sid<=3;sid++) query_send_sink(b,f,r,sid); goto JUMP; SENSR: for(sid=1;sid<=3;sid++) query_send_sink(b,f,r,sid); goto JUMP; #endif SEND_QR: query_send_sink(b,f,r,sid); JUMP:{} } else if(strncmp(line, "Region-",7) == 0){ //Region of the node strcpy(reg, line+8); if(strncmp(reg, "B", 1) == 0){ region = BUILDING; } else if(strncmp(reg, "L", 1) == 0){ region = LEVEL; } else if(strncmp(reg, "R", 1) == 0){ region = ROOM; } else if(strncmp(reg, "S", 1) == 0){ region = SENSOR; } } else { //printf("unhandled command: %s\n", line); } } if(ev == PROCESS_EVENT_TIMER) { if(data == &period_timer) { etimer_reset(&period_timer); etimer_set(&wait_timer, random_rand() % (CLOCK_SECOND * RANDWAIT)); } else if(data == &wait_timer) { if(send_active) { /* Time to send the data */ /* Broadcast its own region rank */ if( region == ROOM ) broadcast_identity(ROOM); else if ( region == BUILDING ) broadcast_identity(BUILDING); else if ( region == LEVEL ) broadcast_identity(LEVEL); else if ( region == SENSOR ) broadcast_identity(SENSOR); } } } } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; static uint8_t initialized = 0; static uint16_t seqno; const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(!initialized) { initialized = 1; /* Initialize the sequence number to a random value as per 802.15.4. */ seqno = random_rand(); } if(seqno == 0) { /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity in framer-802154.c. */ seqno++; } packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++); /* Look for the neighbor entry */ n = neighbor_queue_from_addr(addr); if(n == NULL) { /* Allocate a new neighbor entry */ n = memb_alloc(&neighbor_memb); if(n != NULL) { /* Init neighbor entry */ rimeaddr_copy(&n->addr, addr); n->transmissions = 0; n->collisions = 0; n->deferrals = 0; /* Init packet list for this neighbor */ LIST_STRUCT_INIT(n, queued_packet_list); /* Add neighbor to the list */ list_add(neighbor_list, n); } } if(n != NULL) { /* Add packet to the neighbor's queue */ q = memb_alloc(&packet_memb); if(q != NULL) { q->ptr = memb_alloc(&metadata_memb); if(q->ptr != NULL) { q->buf = queuebuf_new_from_packetbuf(); if(q->buf != NULL) { struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; /* Neighbor and packet successfully allocated */ if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) { /* Use default configuration for max transmissions */ metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS; } else { metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); } metadata->sent = sent; metadata->cptr = ptr; if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); } else { list_add(n->queued_packet_list, q); } /* If q is the first packet in the neighbor's queue, send asap */ if(list_head(n->queued_packet_list) == q) { ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n); } return; } memb_free(&metadata_memb, q->ptr); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } memb_free(&packet_memb, q); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } /* The packet allocation failed. Remove and free neighbor entry if empty. */ if(list_length(n->queued_packet_list) == 0) { list_remove(neighbor_list, n); memb_free(&neighbor_memb, n); } PRINTF("csma: could not allocate packet, dropping packet\n"); } else { PRINTF("csma: could not allocate neighbor, dropping packet\n"); } mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); }
/*---------------------------------------------------------------------------*/ static int create_frame(int type, int do_create) { frame802154_t params; int hdr_len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); if(!initialized) { initialized = 1; mac_dsn = random_rand() & 0xff; } /* Build the FCF. */ params.fcf.frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE); params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(packetbuf_holds_broadcast()) { params.fcf.ack_required = 0; } else { params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK); } params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2006) version bits. */ params.fcf.frame_version = FRAME802154_IEEE802154_2006; #if LLSEC802154_SECURITY if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) { params.fcf.security_enabled = 1; } /* Setting security-related attributes */ params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); #if LLSEC802154_USES_EXPLICIT_KEYS params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE); params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX); params.aux_hdr.key_source.u16[0] = packetbuf_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_SECURITY */ /* Increment and set the data sequence number. */ if(!do_create) { /* Only length calculation - no sequence number is needed and should not be consumed. */ } else if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); } else { /* Ensure that the sequence number 0 is not used as it would bypass the above check. */ if(mac_dsn == 0) { mac_dsn++; } params.seq = mac_dsn++; packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, params.seq); } /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ if(LINKADDR_SIZE == 2) { /* Use short address mode if linkaddr size is short. */ params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; } params.dest_pid = mac_dst_pan_id; if(packetbuf_holds_broadcast()) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { linkaddr_copy((linkaddr_t *)¶ms.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* Use short address mode if linkaddr size is small */ if(LINKADDR_SIZE == 2) { params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } } /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; /* * Set up the source address using only the long address mode for * phase 1. */ linkaddr_copy((linkaddr_t *)¶ms.src_addr, packetbuf_addr(PACKETBUF_ADDR_SENDER)); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); hdr_len = frame802154_hdrlen(¶ms); if(!do_create) { /* Only calculate header length */ return hdr_len; } else if(packetbuf_hdralloc(hdr_len)) { frame802154_create(¶ms, packetbuf_hdrptr()); PRINTF("15.4-OUT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr); PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen()); return hdr_len; } else { PRINTF("15.4-OUT: too large header: %u\n", hdr_len); return FRAMER_FAILED; } }
/*---------------------------------------------------------------------------*/ void init_net(uint8_t node_id) { uint16_t shortaddr; uint64_t longaddr; linkaddr_t addr; #if WITH_UIP6 uip_ds6_addr_t *lladdr; uip_ipaddr_t ipaddr; #endif uint8_t i; memset(&shortaddr, 0, sizeof(shortaddr)); memset(&longaddr, 0, sizeof(longaddr)); *((uint8_t *)&shortaddr) = node_id >> 8; *((uint8_t *)&shortaddr + 1) = node_id; *((uint8_t *)&longaddr) = node_id >> 8; *((uint8_t *)&longaddr + 1) = node_id; for(i = 2; i < sizeof(longaddr); ++i) { ((uint8_t *)&longaddr)[i] = random_rand(); } PRINTF("SHORT MAC ADDRESS %02x:%02x\n", *((uint8_t *) & shortaddr), *((uint8_t *) & shortaddr + 1)); PRINTF("EXTENDED MAC ADDRESS %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", *((uint8_t *)&longaddr), *((uint8_t *)&longaddr + 1), *((uint8_t *)&longaddr + 2), *((uint8_t *)&longaddr + 3), *((uint8_t *)&longaddr + 4), *((uint8_t *)&longaddr + 5), *((uint8_t *)&longaddr + 6), *((uint8_t *)&longaddr + 7)); memset(&addr, 0, sizeof(linkaddr_t)); for(i = 0; i < sizeof(addr.u8); ++i) { addr.u8[i] = ((uint8_t *)&longaddr)[i]; } linkaddr_set_node_addr(&addr); PRINTF("Rime started with address: "); for(i = 0; i < sizeof(addr.u8) - 1; ++i) { PRINTF("%d.", addr.u8[i]); } PRINTF("%d\n", addr.u8[i]); queuebuf_init(); NETSTACK_RADIO.init(); mrf24j40_set_channel(RF_CHANNEL); mrf24j40_set_panid(IEEE802154_PANID); mrf24j40_set_short_mac_addr(shortaddr); mrf24j40_set_extended_mac_addr(longaddr); NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); PRINTF("%s %s, channel check rate %d Hz, radio channel %u\n", NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1 : NETSTACK_RDC.channel_check_interval()), RF_CHANNEL); #if WITH_UIP6 #if LINKADDR_CONF_SIZE == 2 memset(&uip_lladdr.addr, 0, sizeof(uip_lladdr.addr)); uip_lladdr.addr[3] = 0xff; uip_lladdr.addr[4]= 0xfe; memcpy(&uip_lladdr.addr[6], &shortaddr, sizeof(shortaddr)); #else memcpy(&uip_lladdr.addr, &longaddr, sizeof(uip_lladdr.addr)); #endif process_start(&tcpip_process, NULL); lladdr = uip_ds6_get_link_local(-1); PRINTF("Tentative link-local IPv6 address "); for(i = 0; i < 7; ++i) { PRINTF("%02x%02x:", lladdr->ipaddr.u8[i * 2], lladdr->ipaddr.u8[i * 2 + 1]); } PRINTF("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); if(!UIP_CONF_IPV6_RPL) { uip_ip6addr(&ipaddr, 0x2001, 0x1418, 0x100, 0x823c, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); PRINTF("Tentative global IPv6 address "); for(i = 0; i < 7; ++i) { PRINTF("%02x%02x:", ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); } PRINTF("%02x%02x\n", ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); } #endif }
/*---------------------------------------------------------------------------*/ static void packet_sent(void *ptr, int status, int num_transmissions) { struct neighbor_queue *n; struct rdc_buf_list *q; struct qbuf_metadata *metadata; clock_time_t time = 0; mac_callback_t sent; void *cptr; int num_tx; int backoff_exponent; int backoff_transmissions; n = ptr; if(n == NULL) { return; } switch(status) { case MAC_TX_OK: case MAC_TX_NOACK: n->transmissions++; break; case MAC_TX_COLLISION: n->collisions++; break; case MAC_TX_DEFERRED: n->deferrals++; break; } for(q = list_head(n->queued_packet_list); q != NULL; q = list_item_next(q)) { if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) == packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { break; } } if(q != NULL) { metadata = (struct qbuf_metadata *)q->ptr; if(metadata != NULL) { sent = metadata->sent; cptr = metadata->cptr; num_tx = n->transmissions; if(status == MAC_TX_COLLISION || status == MAC_TX_NOACK) { /* If the transmission was not performed because of a collision or noack, we must retransmit the packet. */ switch(status) { case MAC_TX_COLLISION: PRINTF("csma: rexmit collision %d\n", n->transmissions); break; case MAC_TX_NOACK: PRINTF("csma: rexmit noack %d\n", n->transmissions); break; default: PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions); } /* The retransmission time must be proportional to the channel check interval of the underlying radio duty cycling layer. */ time = default_timebase(); /* The retransmission time uses a truncated exponential backoff * so that the interval between the transmissions increase with * each retransmit. */ backoff_exponent = num_tx; /* Truncate the exponent if needed. */ if(backoff_exponent > CSMA_MAX_BACKOFF_EXPONENT) { backoff_exponent = CSMA_MAX_BACKOFF_EXPONENT; } /* Proceed to exponentiation. */ backoff_transmissions = 1 << backoff_exponent; /* Pick a time for next transmission, within the interval: * [time, time + 2^backoff_exponent * time[ */ time = time + (random_rand() % (backoff_transmissions * time)); if(n->transmissions < metadata->max_transmissions) { PRINTF("csma: retransmitting with time %lu %p\n", time, q); ctimer_set(&n->transmit_timer, time, transmit_packet_list, n); /* This is needed to correctly attribute energy that we spent transmitting this packet. */ queuebuf_update_attr_from_packetbuf(q->buf); } else { PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n", status, n->transmissions, n->collisions); free_packet(n, q); mac_call_sent_callback(sent, cptr, status, num_tx); } } else { if(status == MAC_TX_OK) { PRINTF("csma: rexmit ok %d\n", n->transmissions); } else { PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status); } free_packet(n, q); mac_call_sent_callback(sent, cptr, status, num_tx); } } } }
/** * %HENNEBURGGRAPH Randomly generates a rigid graph with Henneburg operations * @param adj Adjacency matrix */ void henneburgGraph(uchar *adj) { uchar i, op, v1, v2, v3; //Add first bar between first 2 nodes adj[mat2vec(0, 1)] = 1; adj[mat2vec(1, 0)] = 1; //Perform N-2 random Henneburg operations to generate graph for (i = 2; i < TOT_NUM_NODES; i++) { if (i > 2) op = (uchar) (random_rand() % 2) + 1; else op = 1; // Perform the 2-valent operation if (op == 1) { //Choose vertices v1 = (uchar) (random_rand() % i); v2 = (uchar) (random_rand() % i); while (v2 == v1) { v2 = (uchar) (random_rand() % i); } //% Add new edges adj[mat2vec(i, v1)] = 1; adj[mat2vec(v1, i)] = 1; adj[mat2vec(i, v2)] = 1; adj[mat2vec(v2, i)] = 1; } // Perform the 3-valent operation if (op == 2) { // Choose an edge v1 = (uchar) (random_rand() % i); v2 = choose_random_edge(v1, adj); // Choose a third vertex v3 = (uchar) (random_rand() % i); while (v3 == v1 || v3 == v2) { v3 = (uchar) (random_rand() % i); } //Remove edge (v1,v2) and add edges (v1,i), (v2,i), (v3,i) adj[mat2vec(v1, v2)] = 0; adj[mat2vec(v2, v1)] = 0; adj[mat2vec(v1, i)] = 1; adj[mat2vec(i, v1)] = 1; adj[mat2vec(v2, i)] = 1; adj[mat2vec(i, v2)] = 1; adj[mat2vec(v3, i)] = 1; adj[mat2vec(i, v3)] = 1; } } }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(shell_randwait_process, ev, data) { static int maxwait; static char command[MAX_COMMANDLENGTH]; static struct etimer etimer; static struct process *started_process; const char *args, *next; int ret; /* if(ev == shell_event_input) { struct shell_input *input; input = data; printf("shell randwait input %d %d\n", input->len1, input->len2); if(input->len1 + input->len2 != 0) { shell_output(&randwait_command, input->data1, input->len1, input->data2, input->len2); } }*/ PROCESS_BEGIN(); args = data; if(args == NULL) { shell_output_str(&randwait_command, "usage 0", ""); PROCESS_EXIT(); } maxwait = shell_strtolong(args, &next); if(next == args) { shell_output_str(&randwait_command, "usage 1", ""); PROCESS_EXIT(); } args = next; while(*args == ' ') { args++; } strncpy(command, args, MAX_COMMANDLENGTH); if(strlen(command) == 0) { shell_output_str(&repeat_command, "usage 3", ""); PROCESS_EXIT(); } /* printf("randwait %d command '%s'\n", maxwait, command);*/ etimer_set(&etimer, random_rand() % (CLOCK_SECOND * maxwait)); PROCESS_WAIT_UNTIL(etimer_expired(&etimer)); /* printf("Starting '%s' child %p (%s)\n", command, randwait_command.child, */ /* randwait_command.child == NULL? "null": randwait_command.child->command); */ ret = shell_start_command(command, (int)strlen(command), randwait_command.child, &started_process); if(started_process != NULL && process_is_running(started_process)) { PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXITED && data == started_process); } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ static int create(void) { frame802154_t params; int len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); if(!initialized) { initialized = 1; mac_dsn = random_rand() & 0xff; } /* Build the FCF. */ params.fcf.frame_type = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { params.fcf.ack_required = 0; } else { params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK); } params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ params.fcf.frame_version = FRAME802154_IEEE802154_2003; /* Increment and set the data sequence number. */ if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); } else { params.seq = mac_dsn++; packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, params.seq); } /* params.seq = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); */ /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ if(sizeof(linkaddr_t) == 2) { /* Use short address mode if linkaddr size is short. */ params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; } params.dest_pid = mac_dst_pan_id; /* * If the output address is NULL in the Rime buf, then it is broadcast * on the 802.15.4 network. */ if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { linkaddr_copy((linkaddr_t *)¶ms.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* Use short address mode if linkaddr size is small */ if(sizeof(linkaddr_t) == 2) { params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } } /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; /* * Set up the source address using only the long address mode for * phase 1. */ linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(len)) { frame802154_create(¶ms, packetbuf_hdrptr(), len); PRINTF("15.4-OUT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr); PRINTF("%d %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); return len; } else { PRINTF("15.4-OUT: too large header: %u\n", len); return FRAMER_FAILED; } }
/*---------------------------------------------------------------------------*/ int compute_state(int cstate) { //float r = rand()/((float)(RAND_MAX)+1); orig c code float r = (float)(random_rand()%32768)/(32768); float p1, p2, p3, p4; int i; //printf("state %d\n", state); if (oldstate == cstate) { //printf("old %d = new %d, same=%d maxmax %d\n", oldstate, cstate, same+1, maxmax+1); same++; maxsame++; if (maxsame > maxmax) { //printf("new maxmax %d\n", maxmax); maxmax = maxsame; } visits[cs]++; if (visits[cs] == 254) { // we have maximum for uint8_t */ //printf("new update!!!\n"); cs++; sstate[cs] = cstate; visits[cs] = 1; } } else { newstate++; cs++; sstate[cs] = cstate; visits[cs] = 1; //printf("new state %d old was %d or %d\n", cstate, sstate[cs-1],oldstate); maxsame = 0; same = 0; } oldstate = cstate; if (r<0 || r> 1.0) printf("================ ERROR ===========================================\n"); /* b states, except for b[MAX] */ if (cstate >= bSTATE_MIN && cstate < bSTATE_MIN+NRSTATES) { int s = cstate-bSTATE_MIN; //printf("%d\n",s); //printf("in b state %d s %d B[s] %d b[s] %d B[s+1] %d \n", cstate, s, //B[s], b[s], B[s+1]); /* when we come to this state, we turn on the interferer, if not already turned on, for timeb0. This time depends on next state */ bctr[s]++; p1 = (1-P)*ALFA[0]; p2 = (1-P)*(1-ALFA[0]); p3 = P*ALFA[s+1]; p4 = P*(1-ALFA[s+1]); if (r < p1) { return (b[0]); } else if (r>= p1 && r < p1+p2) { return (B[0]); } else if (r>= p1+p2 && r < p1+p2+p3) { return (b[s+1]); } else { return (B[s+1]); } } /* state b[max] */ if (cstate == bSTATE_MIN + NRSTATES) { int s = bSTATE_MIN + NRSTATES; //printf("%d\n",s); bctr[s]++; if (r<ALFA[0]) { return (b[0]); } else { return (B[0]); } } else if (cstate >= BSTATE_MIN && cstate <= BSTATE_MIN+NRSTATES) { int s = cstate-BSTATE_MIN; //printf("%d\n",s); //printf("in B ctate %d s %d B[s] %d b[s] %d\n", cstate, s, B[s], b[s]); Bctr[s]++; if (r<BETA[s]) { return (b[s]); } else { return (B[s]); } } else printf("compute-state: EORROR STATE EORROR STATE EORROR STATE %d\n", cstate); }
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); } } }
/* A periodic process to send TSCH Enhanced Beacons (EB) */ PROCESS_THREAD(tsch_send_eb_process, ev, data) { static struct etimer eb_timer; PROCESS_BEGIN(); /* Wait until association */ etimer_set(&eb_timer, CLOCK_SECOND / 10); while(!tsch_is_associated) { PROCESS_WAIT_UNTIL(etimer_expired(&eb_timer)); etimer_reset(&eb_timer); } /* Set an initial delay except for coordinator, which should send an EB asap */ if(!tsch_is_coordinator) { etimer_set(&eb_timer, random_rand() % TSCH_EB_PERIOD); PROCESS_WAIT_UNTIL(etimer_expired(&eb_timer)); } while(1) { unsigned long delay; if(tsch_is_associated && tsch_current_eb_period > 0) { /* Enqueue EB only if there isn't already one in queue */ if(tsch_queue_packet_count(&tsch_eb_address) == 0) { int eb_len; uint8_t hdr_len = 0; uint8_t tsch_sync_ie_offset; /* Prepare the EB packet and schedule it to be sent */ packetbuf_clear(); /* We don't use seqno 0 */ if(++tsch_packet_seqno == 0) { tsch_packet_seqno++; } packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_BEACONFRAME); packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno); #if TSCH_SECURITY_ENABLED if(tsch_is_pan_secured) { /* Set security level, key id and index */ packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, TSCH_SECURITY_KEY_SEC_LEVEL_EB); packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, FRAME802154_1_BYTE_KEY_ID_MODE); /* Use 1-byte key index */ packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, TSCH_SECURITY_KEY_INDEX_EB); } #endif /* TSCH_SECURITY_ENABLED */ eb_len = tsch_packet_create_eb(packetbuf_dataptr(), PACKETBUF_SIZE, tsch_packet_seqno, &hdr_len, &tsch_sync_ie_offset); if(eb_len != 0) { struct tsch_packet *p; packetbuf_set_datalen(eb_len); /* Enqueue EB packet */ if(!(p = tsch_queue_add_packet(&tsch_eb_address, NULL, NULL))) { PRINTF("TSCH:! could not enqueue EB packet\n"); } else { PRINTF("TSCH: enqueue EB packet %u %u\n", eb_len, hdr_len); p->tsch_sync_ie_offset = tsch_sync_ie_offset; p->header_len = hdr_len; } } } } if(tsch_current_eb_period > 0) { /* Next EB transmission with a random delay * within [tsch_current_eb_period*0.75, tsch_current_eb_period[ */ delay = (tsch_current_eb_period - tsch_current_eb_period / 4) + random_rand() % (tsch_current_eb_period / 4); } else { delay = TSCH_EB_PERIOD; } etimer_set(&eb_timer, delay); PROCESS_WAIT_UNTIL(etimer_expired(&eb_timer)); } PROCESS_END(); }
struct net_context *net_context_get(enum ip_protocol ip_proto, const struct net_addr *remote_addr, uint16_t remote_port, struct net_addr *local_addr, uint16_t local_port) { #ifdef CONFIG_NETWORKING_WITH_IPV6 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; const uip_ds6_addr_t *uip_addr; uip_ipaddr_t ipaddr; #endif int i; struct net_context *context = NULL; /* User must provide storage for the local address. */ if (!local_addr) { return NULL; } #ifdef CONFIG_NETWORKING_WITH_IPV6 if (memcmp(&local_addr->in6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) { uip_addr = uip_ds6_get_global(-1); if (!uip_addr) { uip_addr = uip_ds6_get_link_local(-1); } if (!uip_addr) { return NULL; } memcpy(&local_addr->in6_addr, &uip_addr->ipaddr, sizeof(struct in6_addr)); } #else if (local_addr->in_addr.s_addr == INADDR_ANY) { uip_gethostaddr((uip_ipaddr_t *)&local_addr->in_addr); } #endif nano_sem_take(&contexts_lock, TICKS_UNLIMITED); if (local_port) { if (context_port_used(ip_proto, local_port, local_addr) < 0) { return NULL; } } else { do { local_port = random_rand() | 0x8000; } while (context_port_used(ip_proto, local_port, local_addr) == -EEXIST); } for (i = 0; i < NET_MAX_CONTEXT; i++) { if (!contexts[i].tuple.ip_proto) { contexts[i].tuple.ip_proto = ip_proto; contexts[i].tuple.remote_addr = (struct net_addr *)remote_addr; contexts[i].tuple.remote_port = remote_port; contexts[i].tuple.local_addr = (struct net_addr *)local_addr; contexts[i].tuple.local_port = local_port; context = &contexts[i]; break; } } context_sem_give(&contexts_lock); /* Set our local address */ #ifdef CONFIG_NETWORKING_WITH_IPV6 memcpy(&ipaddr.u8, local_addr->in6_addr.s6_addr, sizeof(ipaddr.u8)); if (uip_is_addr_mcast(&ipaddr)) { uip_ds6_maddr_add(&ipaddr); } else { uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL); } #endif return context; }
/* Returns a 4-byte wide, unsigned random number */ static uint32_t wide_rand(void) { return ((uint32_t)random_rand() << 16 | random_rand()); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(collect_common_process, ev, data) { static struct etimer period_timer, wait_timer; PROCESS_BEGIN(); collect_common_net_init(); /* Send a packet every 60-62 seconds. */ etimer_set(&period_timer, CLOCK_SECOND * PERIOD); while(1) { PROCESS_WAIT_EVENT(); if(ev == serial_line_event_message) { /* char *line; line = (char *)data; if(strncmp(line, "collect", 7) == 0 || strncmp(line, "gw", 2) == 0) { collect_common_set_sink(); } else if(strncmp(line, "net", 3) == 0) { collect_common_net_print(); } else if(strncmp(line, "time ", 5) == 0) { unsigned long tmp; line += 6; while(*line == ' ') { line++; } tmp = strtolong(line); time_offset = clock_seconds() - tmp; printf("Time offset set to %lu\n", time_offset); } else if(strncmp(line, "mac ", 4) == 0) { line +=4; while(*line == ' ') { line++; } if(*line == '0') { NETSTACK_RDC.off(1); printf("mac: turned MAC off (keeping radio on): %s\n", NETSTACK_RDC.name); } else { NETSTACK_RDC.on(); printf("mac: turned MAC on: %s\n", NETSTACK_RDC.name); } } else if(strncmp(line, "~K", 2) == 0 || strncmp(line, "killall", 7) == 0) { /* Ignore stop commands */ /* } else { printf("unhandled command: %s\n", line); }*/ } if(ev == PROCESS_EVENT_TIMER) { if(data == &period_timer) { etimer_reset(&period_timer); etimer_set(&wait_timer, random_rand() % (CLOCK_SECOND * RANDWAIT)); } else if(data == &wait_timer) { if(send_active) { /* Time to send the data */ collect_common_send(); } } } } PROCESS_END(); }