/*----------------------------------------------------------------------------*/ static void entry_init(entry_t *e) { memset(e, 0, sizeof(*e)); e->stats.ttl = 0; e->stats.count = 0; LIST_STRUCT_INIT(e, windows); LIST_STRUCT_INIT(e, actions); }
/*---------------------------------------------------------------------------*/ rpl_dag_t * rpl_alloc_dag(uint8_t instance_id, uip_ipaddr_t *dag_id) { rpl_dag_t *dag, *end; rpl_instance_t *instance; instance = rpl_get_instance(instance_id); if(instance == NULL) { instance = rpl_alloc_instance(instance_id); if(instance == NULL) { RPL_STAT(rpl_stats.mem_overflows++); return NULL; } } for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { if(!dag->used) { memset(dag, 0, sizeof(*dag)); LIST_STRUCT_INIT(dag, parents); dag->used = 1; dag->rank = INFINITE_RANK; dag->min_rank = INFINITE_RANK; dag->instance = instance; return dag; } } RPL_STAT(rpl_stats.mem_overflows++); rpl_free_instance(instance); return NULL; }
/* Adds and returns a slotframe (NULL if failure) */ struct tsch_slotframe * tsch_schedule_add_slotframe(uint16_t handle, uint16_t size) { if(size == 0) { return NULL; } if(tsch_schedule_get_slotframe_by_handle(handle)) { /* A slotframe with this handle already exists */ return NULL; } if(tsch_get_lock()) { struct tsch_slotframe *sf = memb_alloc(&slotframe_memb); if(sf != NULL) { /* Initialize the slotframe */ sf->handle = handle; ASN_DIVISOR_INIT(sf->size, size); LIST_STRUCT_INIT(sf, links_list); /* Add the slotframe to the global list */ list_add(slotframe_list, sf); } PRINTF("TSCH-schedule: add_slotframe %u %u\n", handle, size); tsch_release_lock(); return sf; } return NULL; }
/*---------------------------------------------------------------------------*/ void collect_neighbor_list_new(struct collect_neighbor_list *neighbors_list) { LIST_STRUCT_INIT(neighbors_list, list); list_init(neighbors_list->list); ctimer_set(&neighbors_list->periodic, CLOCK_SECOND, periodic, neighbors_list); }
/*! * \breif Init a task struct * * Initializes the is_list field of the task * * @param task - the task to be initialized */ static void task_init(tres_res_t *task) { LIST_STRUCT_INIT(task, is_list); task_reset_state(task); task_od_reset(task); }
static void relation_clear(relation_t *rel) { memset(rel, 0, sizeof(*rel)); rel->tuple_storage = -1; rel->cardinality = INVALID_TUPLE; rel->dir = DB_STORAGE; LIST_STRUCT_INIT(rel, attributes); }
int mqtt_sn_create_socket(struct mqtt_sn_connection *mqc, uint16_t local_port, uip_ipaddr_t *remote_addr, uint16_t remote_port) { simple_udp_register(&(mqc->sock), local_port, remote_addr, remote_port, mqtt_sn_receiver); mqc->stat = MQTTSN_DISCONNECTED; mqc->keep_alive=0; mqc->next_message_id = 1; mqc->connection_retries = 0; LIST_STRUCT_INIT(mqc,requests); mqtt_sn_request_event = process_alloc_event(); process_start(&mqtt_sn_process, NULL); return 0; }
/*----------------------------------------------------------------------------*/ static action_t * action_allocate(void) { action_t *a; a = memb_alloc(&actions_memb); if(a == NULL) { PRINTF("[FLT]: Failed to allocate an action\n"); return NULL; } memset(a, 0, sizeof(*a)); LIST_STRUCT_INIT(a, bytes); return a; }
/*---------------------------------------------------------------------------*/ void init_runqueues() { //run_queue_init stored the data, and run_queues points to it. uint8_t i; /* struct sch_add_process add = {11, 11, 0, 0, 0, 0}; struct process old = {NULL, "HI", NULL}; struct sch_process pvalue = {NULL, NULL, NULL}; struct sch_process processvalue = {(struct process *)&old, (struct sch_add_process *)&add}; struct sch_process *p = &pvalue; struct sch_process *process = &processvalue; */ run_queue_init.active = &run_queue_init.arrays[0]; run_queue_init.expired= &run_queue_init.arrays[1]; run_queue_init.arrays[0].nr_active = 0; run_queue_init.arrays[0].map = 0; run_queue_init.arrays[1].nr_active = 0; run_queue_init.arrays[1].map = 0; for (i = 0; i <= 15; ++i) { LIST_STRUCT_INIT(&(run_queue_init.arrays[0].queue[i]), list); LIST_STRUCT_INIT(&(run_queue_init.arrays[1].queue[i]), list); } run_queues = &run_queue_init; /* printf("pushing...\n"); list_add(run_queues->arrays[0].queue[0].list, process); p = list_head(run_queues->arrays[0].queue[0].list); printf("head -- prio:%d correct:%d\n", p->add->prio, process->add->prio); p = list_pop(run_queues->arrays[0].queue[0].list); printf("pop -- prio:%d correct:%d\n", p->add->prio, process->add->prio); */ }
/*---------------------------------------------------------------------------*/ 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); }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop) { uip_ds6_route_t *r; struct uip_ds6_route_neighbor_route *nbrr; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ /* Get link-layer address of next hop, make sure it is in neighbor table */ const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop); if(nexthop_lladdr == NULL) { PRINTF("uip_ds6_route_add: neighbor link-local address unknown for "); PRINT6ADDR(nexthop); PRINTF("\n"); return NULL; } /* First make sure that we don't add a route twice. If we find an existing route for our destination, we'll delete the old one first. */ r = uip_ds6_route_lookup(ipaddr); if(r != NULL) { PRINTF("uip_ds6_route_add: old route for "); PRINT6ADDR(ipaddr); PRINTF(" found, deleting it\n"); uip_ds6_route_rm(r); } { struct uip_ds6_route_neighbor_routes *routes; /* If there is no routing entry, create one. We first need to check if we have room for this route. If not, we remove the least recently used one we have. */ if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) { /* Removing the oldest route entry from the route table. The least recently used route is the first route on the list. */ uip_ds6_route_t *oldest; oldest = list_tail(routelist); /* uip_ds6_route_head(); */ PRINTF("uip_ds6_route_add: dropping route to "); PRINT6ADDR(&oldest->ipaddr); PRINTF("\n"); uip_ds6_route_rm(oldest); } /* Every neighbor on our neighbor table holds a struct uip_ds6_route_neighbor_routes which holds a list of routes that go through the neighbor. We add our route entry to this list. We first check to see if we already have this neighbor in our nbr_route table. If so, the neighbor already has a route entry list. */ routes = nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)nexthop_lladdr); if(routes == NULL) { /* If the neighbor did not have an entry in our neighbor table, we create one. The nbr_table_add_lladdr() function returns a pointer to a pointer that we may use for our own purposes. We initialize this pointer with the list of routing entries that are attached to this neighbor. */ routes = nbr_table_add_lladdr(nbr_routes, (linkaddr_t *)nexthop_lladdr); if(routes == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate neighbor table entry\n"); return NULL; } LIST_STRUCT_INIT(routes, route_list); } /* Allocate a routing entry and populate it. */ r = memb_alloc(&routememb); if(r == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate route\n"); return NULL; } /* add new routes first - assuming that there is a reason to add this and that there is a packet coming soon. */ list_push(routelist, r); nbrr = memb_alloc(&neighborroutememb); if(nbrr == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate neighbor route list entry\n"); memb_free(&routememb, r); return NULL; } nbrr->route = r; /* Add the route to this neighbor */ list_add(routes->route_list, nbrr); r->neighbor_routes = routes; num_routes++; PRINTF("uip_ds6_route_add num %d\n", num_routes); } uip_ipaddr_copy(&(r->ipaddr), ipaddr); r->length = length; #ifdef UIP_DS6_ROUTE_STATE_TYPE memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE)); #endif PRINTF("uip_ds6_route_add: adding route: "); PRINT6ADDR(ipaddr); PRINTF(" via "); PRINT6ADDR(nexthop); PRINTF("\n"); ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop); #endif #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return r; }
/*---------------------------------------------------------------------------*/ static void packet_sent(void *ptr, int status, int num_transmissions) { struct neighbor_queue *n; struct rdc_buf_list *q; n = ptr; if(n == NULL) { return; } /* Find out what packet this callback refers to */ for(q = list_head(n->queued_packet_list); q != NULL; q = list_item_next(q)) { #if CETIC_6LBR_MULTI_RADIO if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) == packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO) && (q->ptr == NULL || ((struct qbuf_metadata *)q->ptr)->ifindex == multi_radio_input_ifindex)) { #else if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) == packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { #endif break; } } if(q == NULL) { PRINTF("csma: seqno %d not found\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); return; } else if(q->ptr == NULL) { PRINTF("csma: no metadata\n"); return; } switch(status) { case MAC_TX_OK: tx_ok(q, n, num_transmissions); break; case MAC_TX_NOACK: noack(q, n, num_transmissions); break; case MAC_TX_COLLISION: collision(q, n, num_transmissions); break; case MAC_TX_DEFERRED: break; default: tx_done(status, q, n); break; } } /*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); /* 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 */ linkaddr_copy(&n->addr, addr); n->transmissions = 0; n->collisions = CSMA_MIN_BE; /* 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 */ if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) { 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_MAX_FRAME_RETRIES + 1; } else { metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); } metadata->sent = sent; metadata->cptr = ptr; #if CETIC_6LBR_MULTI_RADIO metadata->ifindex = multi_radio_output_ifindex; #endif #if PACKETBUF_WITH_PACKET_TYPE if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); } else #endif { list_add(n->queued_packet_list, q); } PRINTF("csma: send_packet, queue length %d, free packets %d\n", list_length(n->queued_packet_list), memb_numfree(&packet_memb)); /* If q is the first packet in the neighbor's queue, send asap */ if(list_head(n->queued_packet_list) == q) { schedule_transmission(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); } } else { PRINTF("csma: Neighbor queue full\n"); } PRINTF("csma: could not allocate packet, dropping packet\n"); csma_packet_overflow++; } else { PRINTF("csma: could not allocate neighbor, dropping packet\n"); csma_neighbor_overflow++; } mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); } /*---------------------------------------------------------------------------*/ static void input_packet(void) { csma_received_packets++; NETSTACK_LLSEC.input(); }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop) { uip_ds6_route_t *r; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ /* Get link-layer address of next hop, make sure it is in neighbor table */ const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop); if(nexthop_lladdr == NULL) { PRINTF("uip_ds6_route_add: neighbor link-local address unknown "); PRINT6ADDR(ipaddr); PRINTF("\n"); return NULL; } /* First make sure that we don't add a route twice. If we find an existing route for our destination, we'll just update the old one. */ r = uip_ds6_route_lookup(ipaddr); if(r != NULL) { PRINTF("uip_ds6_route_add: old route already found, updating this one instead: "); PRINT6ADDR(ipaddr); PRINTF("\n"); } else { struct uip_ds6_route_neighbor_routes *routes; /* If there is no routing entry, create one */ /* Every neighbor on our neighbor table holds a struct uip_ds6_route_neighbor_routes which holds a list of routes that go through the neighbor. We add our route entry to this list. We first check to see if we already have this neighbor in our nbr_route table. If so, the neighbor already has a route entry list. */ routes = nbr_table_get_from_lladdr(nbr_routes, (rimeaddr_t *)nexthop_lladdr); if(routes == NULL) { /* If the neighbor did not have an entry in our neighbor table, we create one. The nbr_table_add_lladdr() function returns a pointer to a pointer that we may use for our own purposes. We initialize this pointer with the list of routing entries that are attached to this neighbor. */ routes = nbr_table_add_lladdr(nbr_routes, (rimeaddr_t *)nexthop_lladdr); if(routes == NULL) { PRINTF("uip_ds6_route_add: could not allocate a neighbor table entri for new route to "); PRINT6ADDR(ipaddr); PRINTF(", dropping it\n"); return NULL; } LIST_STRUCT_INIT(routes, route_list); } /* Allocate a routing entry and populate it. */ r = memb_alloc(&routememb); if(r == NULL) { PRINTF("uip_ds6_route_add: could not allocate memory for new route to "); PRINT6ADDR(ipaddr); PRINTF(", dropping it\n"); return NULL; } /* Add the route to this neighbor */ list_add(routes->route_list, r); num_routes++; PRINTF("uip_ds6_route_add num %d\n", num_routes); r->routes = routes; } uip_ipaddr_copy(&(r->ipaddr), ipaddr); r->length = length; #ifdef UIP_DS6_ROUTE_STATE_TYPE memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE)); #endif PRINTF("uip_ds6_route_add: adding route: "); PRINT6ADDR(ipaddr); PRINTF(" via "); PRINT6ADDR(nexthop); PRINTF("\n"); ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop); #endif #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return r; }
/*---------------------------------------------------------------------------*/ 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_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; #if CSMA_ADVANCED num_tx = n->transmissions + n->collisions/8; #else num_tx = n->transmissions; #endif 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; case MAC_TX_DEFERRED: PRINTF("phase deferred\n"); break; default: PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions); } #if CSMA_ADVANCED int i; /* The retransmission time must be proportional to the channel check interval of the underlying radio duty cycling layer. */ time = default_timebase() / 3; /* The retransmission time uses a linear backoff so that the interval between the transmissions increase with each retransmit. */ backoff_transmissions = 1; for(i=0; i<num_tx-1; i++) { backoff_transmissions *= 3; } /* Clamp the number of backoffs so that we don't get a too long timeout here, since that will delay all packets in the queue. */ if(backoff_transmissions > 3 * 3) { backoff_transmissions = 3 * 3; } time = default_timebase() + (random_rand() % (backoff_transmissions * time)); if(num_tx < metadata->max_transmissions) { #else /* 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 linear backoff so that the interval between the transmissions increase with each retransmit. */ backoff_transmissions = n->transmissions + 1; /* Clamp the number of backoffs so that we don't get a too long timeout here, since that will delay all packets in the queue. */ if(backoff_transmissions > 3) { backoff_transmissions = 3; } time = time + (random_rand() % (backoff_transmissions * time)); if(n->transmissions < metadata->max_transmissions) { #endif 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 { if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { LOG_FROM_PACKETBUF("csma: drop with status %d after %d transmissions, %d collisions", status, n->transmissions, n->collisions); } free_packet(n, q); mac_call_sent_callback(sent, cptr, status, num_tx); } } else { if(status == MAC_TX_OK) { if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { LOG_FROM_PACKETBUF("csma: rexmit ok after %d transmissions, %d collisions", n->transmissions, n->collisions); } } else { //LOG_FROM_PACKETBUF("csma: rexmit failed %d: %d\n", n->transmissions, status); } free_packet(n, q); mac_call_sent_callback(sent, cptr, status, num_tx); } } } } /*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; static uint16_t seqno; const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); 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 void input_packet(void) { NETSTACK_NETWORK.input(); } /*---------------------------------------------------------------------------*/ static int on(void) { return NETSTACK_RDC.on(); } /*---------------------------------------------------------------------------*/ static int off(int keep_radio_on) { return NETSTACK_RDC.off(keep_radio_on); } /*---------------------------------------------------------------------------*/ static unsigned short channel_check_interval(void) { if(NETSTACK_RDC.channel_check_interval) { return NETSTACK_RDC.channel_check_interval(); } return 0; } /*---------------------------------------------------------------------------*/ static void init(void) { memb_init(&packet_memb); memb_init(&metadata_memb); memb_init(&neighbor_memb); }
/*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); /* 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 */ linkaddr_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 */ if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) { 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_WITH_PACKET_TYPE if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); } else #endif { list_add(n->queued_packet_list, q); } PRINTF("csma: send_packet, queue length %d, free packets %d\n", list_length(n->queued_packet_list), memb_numfree(&packet_memb)); /* 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); } } else { PRINTF("csma: Neighbor queue full\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 uint8_t send_packet(struct net_buf *buf, mac_callback_t sent, bool last_fragment, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; static uint8_t initialized = 0; static uint16_t seqno; const linkaddr_t *addr = packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER); if (!buf) { UIP_LOG("csma: send_packet(): net_buf is NULL, cannot send packet"); return 0; } 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(buf, PACKETBUF_ATTR_MAC_SEQNO, seqno++); /* Look for the neighbor entry */ n = neighbor_queue_from_addr(buf, addr); if(n == NULL) { /* Allocate a new neighbor entry */ n = memb_alloc(&neighbor_memb); if(n != NULL) { /* Init neighbor entry */ linkaddr_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(uip_neighbor_list(buf), n); } } if(n != NULL) { /* Add packet to the neighbor's queue */ if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) { q = memb_alloc(&packet_memb); if(q != NULL) { q->ptr = memb_alloc(&metadata_memb); if(q->ptr != NULL) { q->buf = queuebuf_new_from_packetbuf(buf); if(q->buf != NULL) { struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; /* Neighbor and packet successfully allocated */ if(packetbuf_attr(buf, 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(buf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); } metadata->sent = sent; metadata->cptr = ptr; if(packetbuf_attr(buf, PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); } else { list_add(n->queued_packet_list, q); } PRINTF("csma: send_packet, queue length %d, free packets %d\n", list_length(n->queued_packet_list), memb_numfree(&packet_memb)); /* if received packet is last fragment/only one packet start sending * packets in list, do not start any timer.*/ if (last_fragment) { transmit_packet_list(buf, n); } return 1; } 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(uip_neighbor_list(buf), n); memb_free(&neighbor_memb, n); } } else { PRINTF("csma: Neighbor queue full\n"); } PRINTF("csma: could not allocate packet, dropping packet\n"); } else { PRINTF("csma: could not allocate neighbor, dropping packet\n"); } mac_call_sent_callback(buf, sent, ptr, MAC_TX_ERR, 1); return 0; }