/*---------------------------------------------------------------------------*/ static void send_broadcast(mac_callback_t sent, void *ptr) { struct queuebuf *qb; qb = queuebuf_new_from_packetbuf(); if(!qb || (NETSTACK_FRAMER.create() < 0)) { PRINTF("coresec-strategy: Did not send broadcast\n"); if(qb) { queuebuf_free(qb); } sent(ptr, MAC_TX_ERR, 0); return; } prepare_announce(); adaptivesec_send_command_frame(); watchdog_periodic(); queuebuf_to_packetbuf(qb); queuebuf_free(qb); #if WITH_BROADCAST_ENCRYPTION { uint8_t ignore[ADAPTIVESEC_BROADCAST_MIC_LEN]; if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2)) { adaptivesec_aead(adaptivesec_group_key, 1, ignore, 1); } } #endif /* WITH_BROADCAST_ENCRYPTION */ NETSTACK_MAC.send(sent, ptr); }
/*---------------------------------------------------------------------------*/ static void recv_from_ipolite(struct ipolite_conn *ipolite, const rimeaddr_t *from) { PRINTF("%d.%d: netflood recv_from_ipolite\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); struct netflood_conn *c = (struct netflood_conn *)ipolite; struct netflood_hdr hdr; uint8_t hops; struct queuebuf *queuebuf; memcpy(&hdr, packetbuf_dataptr(), sizeof(struct netflood_hdr)); hops = hdr.hops; /* Remember packet if we need to forward it. */ queuebuf = queuebuf_new_from_packetbuf(); packetbuf_hdrreduce(sizeof(struct netflood_hdr)); if(c->u->recv != NULL) { if(!(rimeaddr_cmp(&hdr.originator, &c->last_originator) && hdr.originator_seqno <= c->last_originator_seqno)) { if(c->u->recv(c, from, &hdr.originator, hdr.originator_seqno, hops)) { if(queuebuf != NULL) { queuebuf_to_packetbuf(queuebuf); queuebuf_free(queuebuf); queuebuf = NULL; memcpy(&hdr, packetbuf_dataptr(), sizeof(struct netflood_hdr)); /* Rebroadcast received packet. */ if(hops < HOPS_MAX) { PRINTF("%d.%d: netflood rebroadcasting %d.%d/%d (%d.%d/%d) hops %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.originator.u8[0], hdr.originator.u8[1], hdr.originator_seqno, c->last_originator.u8[0], c->last_originator.u8[1], c->last_originator_seqno, hops); hdr.hops++; memcpy(packetbuf_dataptr(), &hdr, sizeof(struct netflood_hdr)); send(c); rimeaddr_copy(&c->last_originator, &hdr.originator); c->last_originator_seqno = hdr.originator_seqno; } } } } } if(queuebuf != NULL) { queuebuf_free(queuebuf); } }
/*---------------------------------------------------------------------------*/ static rimeaddr_t * data_packet_forward(struct multihop_conn *multihop, const rimeaddr_t *originator, const rimeaddr_t *dest, const rimeaddr_t *prevhop, uint8_t hops) { struct route_entry *rt; struct mesh_conn *c = (struct mesh_conn *) ((char *)multihop - offsetof(struct mesh_conn, multihop)); rt = route_lookup(dest); if(rt == NULL) { if(c->queued_data != NULL) { queuebuf_free(c->queued_data); } PRINTF("data_packet_forward: queueing data, sending rreq\n"); c->queued_data = queuebuf_new_from_packetbuf(); rimeaddr_copy(&c->queued_data_dest, dest); route_discovery_discover(&c->route_discovery_conn, dest, PACKET_TIMEOUT); return NULL; } else { route_refresh(rt); } return &rt->R_next_addr; }
/*---------------------------------------------------------------------------*/ static void found_route(struct route_discovery_conn *rdc, const rimeaddr_t *dest) { struct route_entry *rt; struct mesh_conn *c = (struct mesh_conn *) ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn)); PRINTF("found_route\n"); if(c->queued_data != NULL && rimeaddr_cmp(dest, &c->queued_data_dest)) { queuebuf_to_packetbuf(c->queued_data); queuebuf_free(c->queued_data); c->queued_data = NULL; rt = route_lookup(dest); if(rt != NULL) { multihop_resend(&c->multihop, &rt->R_next_addr); if(c->cb->sent != NULL) { c->cb->sent(c); } } else { if(c->cb->timedout != NULL) { c->cb->timedout(c); } } } }
/*---------------------------------------------------------------------------*/ int mesh_send(struct mesh_conn *c, const rimeaddr_t *to) { int could_send; PRINTF("%d.%d: mesh_send to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], to->u8[0], to->u8[1]); could_send = multihop_send(&c->multihop, to); if(!could_send) { if(c->queued_data != NULL) { queuebuf_free(c->queued_data); } PRINTF("mesh_send: queueing data, sending rreq\n"); c->queued_data = queuebuf_new_from_packetbuf(); rimeaddr_copy(&c->queued_data_dest, to); route_discovery_discover(&c->route_discovery_conn, to, PACKET_TIMEOUT); return 0; } c->cb->sent(c); return 1; }
/*---------------------------------------------------------------------------*/ static void free_packet(struct neighbor_queue *n, struct rdc_buf_list *p, int status) { if(p != NULL) { /* Remove packet from list and deallocate */ list_remove(n->queued_packet_list, p); queuebuf_free(p->buf); memb_free(&metadata_memb, p->ptr); memb_free(&packet_memb, p); PRINTF("csma: free_queued_packet, queue length %d, free packets %d\n", list_length(n->queued_packet_list), memb_numfree(&packet_memb)); if(list_head(n->queued_packet_list) != NULL) { /* There is a next packet. We reset current tx information */ n->transmissions = 0; n->collisions = CSMA_MIN_BE; /* Schedule next transmissions */ schedule_transmission(n); } else { /* This was the last packet in the queue, we free the neighbor */ ctimer_stop(&n->transmit_timer); list_remove(neighbor_list, n); memb_free(&neighbor_memb, n); } } }
/*---------------------------------------------------------------------------*/ static void recv(struct broadcast_conn *broadcast, const linkaddr_t *from) { struct ipolite_conn *c = (struct ipolite_conn *)broadcast; if(c->q != NULL && packetbuf_datalen() == queuebuf_datalen(c->q) && memcmp(packetbuf_dataptr(), queuebuf_dataptr(c->q), MIN(c->hdrsize, packetbuf_datalen())) == 0) { /* We received a copy of our own packet, so we increase the duplicate counter. If it reaches its maximum, do not send out our packet. */ c->dups++; if(c->dups == c->maxdups) { queuebuf_free(c->q); c->q = NULL; ctimer_stop(&c->t); if(c->cb->dropped) { c->cb->dropped(c); } } } if(c->cb->recv) { c->cb->recv(c, from); } }
/*---------------------------------------------------------------------------*/ int stunicast_send_stubborn(struct stunicast_conn *c, const rimeaddr_t *receiver, clock_time_t rxmittime) { if(c->buf != NULL) { queuebuf_free(c->buf); } c->buf = queuebuf_new_from_packetbuf(); if(c->buf == NULL) { return 0; } rimeaddr_copy(&c->receiver, receiver); ctimer_set(&c->t, rxmittime, send, c); PRINTF("%d.%d: stunicast_send_stubborn to %d.%d\n", rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], c->receiver.u8[0],c->receiver.u8[1]); unicast_send(&c->c, &c->receiver); /* if(c->u->sent != NULL) { c->u->sent(c); }*/ return 1; }
/*---------------------------------------------------------------------------*/ 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", rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]); queuebuf_free(c->q); } c->dups = 0; c->hdrsize = hdrsize; if(interval == 0) { PRINTF("%d.%d: ipolite_send: interval 0\n", rimeaddr_node_addr.u8[0],rimeaddr_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", rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]); } return 0; }
/*---------------------------------------------------------------------------*/ static void free_packet(struct net_buf *buf, struct neighbor_queue *n, struct rdc_buf_list *p) { if(p != NULL) { /* Remove packet from list and deallocate */ list_remove(n->queued_packet_list, p); queuebuf_free(p->buf); memb_free(&metadata_memb, p->ptr); memb_free(&packet_memb, p); PRINTF("csma: free_queued_packet, queue length %d, free packets %d\n", list_length(n->queued_packet_list), memb_numfree(&packet_memb)); if(list_head(n->queued_packet_list) != NULL) { /* There is a next packet. We reset current tx information */ n->transmissions = 0; n->collisions = 0; n->deferrals = 0; transmit_packet_list(buf, n); } else { /* This was the last packet in the queue, we free the neighbor */ list_remove(uip_neighbor_list(buf), n); memb_free(&neighbor_memb, n); } } }
/*---------------------------------------------------------------------------*/ static void free_packet(struct neighbor_queue *n, struct rdc_buf_list *p) { if(p != NULL) { /* Remove packet from list and deallocate */ list_remove(n->queued_packet_list, p); queuebuf_free(p->buf); memb_free(&metadata_memb, p->ptr); memb_free(&packet_memb, p); PRINTF("csma: free_queued_packet, queue length %d\n", list_length(n->queued_packet_list)); if(list_head(n->queued_packet_list) != NULL) { /* There is a next packet. We reset current tx information */ n->transmissions = 0; n->collisions = 0; n->deferrals = 0; /* Set a timer for next transmissions */ ctimer_set(&n->transmit_timer, default_timebase(), transmit_packet_list, n); } else { /* This was the last packet in the queue, we free the neighbor */ ctimer_stop(&n->transmit_timer); list_remove(neighbor_list, n); memb_free(&neighbor_memb, n); } } }
/*---------------------------------------------------------------------------*/ static void send_broadcast(mac_callback_t sent, void *ptr) { struct queuebuf *qb; #if ANTI_REPLAY_WITH_SUPPRESSION uint16_t frame_counter_bytes_0_1; uint16_t frame_counter_bytes_2_3; uint8_t seqno; frame_counter_bytes_0_1 = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); frame_counter_bytes_2_3 = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); adaptivesec_add_security_header(NULL); #endif /* ANTI_REPLAY_WITH_SUPPRESSION */ qb = queuebuf_new_from_packetbuf(); if(!qb || (NETSTACK_FRAMER.create() < 0)) { PRINTF("coresec-strategy: Did not send broadcast\n"); if(qb) { queuebuf_free(qb); } sent(ptr, MAC_TX_ERR, 0); return; } prepare_announce(); #if ANTI_REPLAY_WITH_SUPPRESSION packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame_counter_bytes_0_1); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame_counter_bytes_2_3); packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno); #endif /* ANTI_REPLAY_WITH_SUPPRESSION */ adaptivesec_send_command_frame(); watchdog_periodic(); queuebuf_to_packetbuf(qb); queuebuf_free(qb); #if WITH_BROADCAST_ENCRYPTION { uint8_t ignore[ADAPTIVESEC_BROADCAST_MIC_LEN]; if(adaptivesec_get_sec_lvl() & (1 << 2)) { adaptivesec_aead(adaptivesec_group_key, 1, ignore, 1); } } #endif /* WITH_BROADCAST_ENCRYPTION */ NETSTACK_MAC.send(sent, ptr); }
/* Free a packet */ void tsch_queue_free_packet(struct tsch_packet *p) { if(p != NULL) { queuebuf_free(p->qb); memb_free(&packet_memb, p); } }
/*---------------------------------------------------------------------------*/ void polite_cancel(struct polite_conn *c) { ctimer_stop(&c->t); if(c->q != NULL) { queuebuf_free(c->q); c->q = NULL; } }
/*---------------------------------------------------------------------------*/ void stunicast_cancel(struct stunicast_conn *c) { ctimer_stop(&c->t); if(c->buf != NULL) { queuebuf_free(c->buf); c->buf = NULL; } }
/*---------------------------------------------------------------------------*/ void ipolite_close(struct ipolite_conn *c) { broadcast_close(&c->c); ctimer_stop(&c->t); if(c->q != NULL) { queuebuf_free(c->q); c->q = NULL; } }
/*---------------------------------------------------------------------------*/ void polite_close(struct polite_conn *c) { abc_close(&c->c); ctimer_stop(&c->t); if(c->q != NULL) { queuebuf_free(c->q); c->q = NULL; } }
/*---------------------------------------------------------------------------*/ static void timedout(struct route_discovery_conn *c) { PRINTF("uip-over-mesh: packet timed out\n"); if(queued_packet) { PRINTF("uip-over-mesh: freeing queued packet\n"); queuebuf_free(queued_packet); queued_packet = NULL; } }
/*---------------------------------------------------------------------------*/ static void remove_queued_packet(void *item) { struct packetqueue_item *i = item; struct packetqueue *q = i->queue; list_remove(*q->list, i); queuebuf_free(i->buf); ctimer_stop(&i->lifetimer); memb_free(q->memb, i); /* printf("removing queued packet due to timeout\n");*/ }
/*---------------------------------------------------------------------------*/ void packetqueue_dequeue(struct packetqueue *q) { struct packetqueue_item *i; i = list_head(*q->list); if(i != NULL) { list_remove(*q->list, i); queuebuf_free(i->buf); ctimer_stop(&i->lifetimer); memb_free(q->memb, i); } }
/*---------------------------------------------------------------------------*/ static void found_route(struct route_discovery_conn *rdc, rimeaddr_t *dest) { struct mesh_conn *c = (struct mesh_conn *) ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn)); if(c->queued_data != NULL && rimeaddr_cmp(dest, &c->queued_data_dest)) { queuebuf_to_packetbuf(c->queued_data); queuebuf_free(c->queued_data); c->queued_data = NULL; multihop_send(&c->multihop, dest); } }
/*---------------------------------------------------------------------------*/ void trickle_send(struct trickle_conn *c) { if(c->q != NULL) { queuebuf_free(c->q); } c->seqno++; packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, c->seqno); c->q = queuebuf_new_from_packetbuf(); PRINTF("%d.%d: trickle send seqno %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], c->seqno); reset_interval(c); send(c); }
/*---------------------------------------------------------------------------*/ static void send_packet(void *ptr) { struct phase_queueitem *p = ptr; if(p->buf_list == NULL) { queuebuf_to_packetbuf(p->q); queuebuf_free(p->q); NETSTACK_RDC.send(p->mac_callback, p->mac_callback_ptr); } else { NETSTACK_RDC.send_list(p->mac_callback, p->mac_callback_ptr, p->buf_list); } memb_free(&queued_packets_memb, p); }
/*---------------------------------------------------------------------------*/ int polite_send(struct polite_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. */ queuebuf_free(c->q); } c->hdrsize = hdrsize; c->q = queuebuf_new_from_packetbuf(); if(c->q != NULL) { ctimer_set(&c->t, interval / 2 + (random_rand() % (interval / 2)), send, c); return 1; } return 0; }
/*---------------------------------------------------------------------------*/ static void route_timed_out(struct route_discovery_conn *rdc) { struct mesh_conn *c = (struct mesh_conn *) ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn)); if(c->queued_data != NULL) { queuebuf_free(c->queued_data); c->queued_data = NULL; } if(c->cb->timedout) { c->cb->timedout(c); } }
/*---------------------------------------------------------------------------*/ static void send(void *ptr) { struct polite_conn *c = ptr; if(c->q != NULL) { queuebuf_to_packetbuf(c->q); queuebuf_free(c->q); c->q = NULL; abc_send(&c->c); if(c->cb->sent) { c->cb->sent(c); } } }
/*---------------------------------------------------------------------------*/ int stbroadcast_send_stubborn(struct stbroadcast_conn *c, clock_time_t t) { if(c->buf != NULL) { queuebuf_free(c->buf); } c->buf = queuebuf_new_from_packetbuf(); if(c->buf == NULL) { return 0; } send(c); stbroadcast_set_timer(c, t); return 1; }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(shell_packetize_process, ev, data) { static struct queuebuf *q = NULL; static char *ptr; static int size; int len; PROCESS_BEGIN(); while(1) { struct shell_input *input; PROCESS_WAIT_EVENT_UNTIL(ev == shell_event_input); if(q == NULL) { packetbuf_clear(); q = queuebuf_new_from_packetbuf(); if(q == NULL) { shell_output_str(&packetize_command, "packetize: could not allocate packet buffer", ""); PROCESS_EXIT(); } ptr = queuebuf_dataptr(q); size = 0; } input = data; len = input->len1 + input->len2; if(len + size >= PACKETBUF_SIZE || len == 0) { shell_output(&packetize_command, ptr, size, "", 0); queuebuf_free(q); q = NULL; PROCESS_EXIT(); } memcpy(ptr + size, input->data1, input->len1); size += input->len1; memcpy(ptr + size, input->data2, input->len2); size += input->len2; } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ static int send(void) { int r; id_counter++; /* Clean up already sent packets */ while(lastqueued != nextsend) { PRINTF("BUFFER Cleaning up packet #%i\n", id[lastqueued]); queuebuf_free(data[lastqueued]); data[lastqueued] = NULL; lastqueued = (lastqueued + 1) % NUM_PACKETS; } if((freeslot + 1) % NUM_PACKETS == lastqueued) { PRINTF("BUFFER Buffer full, dropping packet #%i\n", (id_counter+1)); return UIP_FW_DROPPED; } /* Allocate queue buf for packet */ data[freeslot] = queuebuf_new_from_packetbuf(); id[freeslot] = id_counter; if(data[freeslot] == NULL) { PRINTF("BUFFER Queuebuffer full, dropping packet #%i\n", id[freeslot]); return UIP_FW_DROPPED; } PRINTF("BUFFER Wrote packet #%i to buffer \n", id[freeslot]); freeslot = (freeslot + 1) % NUM_PACKETS; if(!timer_on) { PRINTF("TIMER Starting timer\n"); r = rtimer_set(&rtimer, RTIMER_NOW() + RTIMER_SECOND, 1, (void (*)(struct rtimer *, void *))transmitter, NULL); if(r) { PRINTF("TIMER Error #3: %d\n", r); } else { timer_on = 1; } } return UIP_FW_OK; /* TODO Return what? */ }
/*---------------------------------------------------------------------------*/ static void new_route(struct route_discovery_conn *c, const linkaddr_t *to) { struct route_entry *rt; if(queued_packet) { PRINTF("uip-over-mesh: new route, sending queued packet\n"); queuebuf_to_packetbuf(queued_packet); queuebuf_free(queued_packet); queued_packet = NULL; rt = route_lookup(&queued_receiver); if(rt) { route_decay(rt); send_data(&queued_receiver); } } }