int gnrc_gomach_send_preamble_ack(gnrc_netif_t *netif, gnrc_gomach_packet_info_t *info) { assert(netif != NULL); assert(info != NULL); gnrc_pktsnip_t *gomach_pkt = NULL; gnrc_pktsnip_t *pkt = NULL; gnrc_netif_hdr_t *nethdr_preamble_ack = NULL; /* Start assemble the preamble-ACK packet according to preamble packet info. */ gnrc_gomach_frame_preamble_ack_t gomach_preamble_ack_hdr; gomach_preamble_ack_hdr.header.type = GNRC_GOMACH_FRAME_PREAMBLE_ACK; gomach_preamble_ack_hdr.dst_addr = info->src_addr; /* Tell the preamble sender the device's (preamble-ACK sender) current phase. * This is to allow the preamble sender to deduce the exact phase of the receiver. */ gomach_preamble_ack_hdr.phase_in_us = gnrc_gomach_phase_now(netif); pkt = gnrc_pktbuf_add(NULL, &gomach_preamble_ack_hdr, sizeof(gomach_preamble_ack_hdr), GNRC_NETTYPE_GOMACH); if (pkt == NULL) { LOG_ERROR("ERROR: [GOMACH]: pktbuf add failed in gnrc_gomach_send_preamble_ack().\n"); return -ENOBUFS; } gomach_pkt = pkt; pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t), GNRC_NETTYPE_NETIF); if (pkt == NULL) { LOG_ERROR("ERROR: [GOMACH]: netif_hdr add failed in gnrc_gomach_send_preamble_ack().\n"); gnrc_pktbuf_release(gomach_pkt); return -ENOBUFS; } gomach_pkt = pkt; gnrc_pktsnip_t *netif_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (netif_snip == NULL) { LOG_ERROR("[GOMACH]: NO netif_hdr found in gnrc_gomach_send_preamble_ack().\n"); gnrc_pktbuf_release(gomach_pkt); return -ENOBUFS; } else { nethdr_preamble_ack = netif_snip->data; } /* Construct NETIF header and insert address for preamble-ACK packet. */ gnrc_netif_hdr_init(nethdr_preamble_ack, 0, 0); /* Send preamble-ACK as broadcast. */ nethdr_preamble_ack->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; int res = gnrc_gomach_send(netif, pkt, NETOPT_DISABLE); if (res < 0) { LOG_ERROR("ERROR: [GOMACH]: send preamble-ack failed in" " gnrc_gomach_send_preamble_ack().\n"); gnrc_pktbuf_release(gomach_pkt); } return res; }
/* shell commands */ int _netif_send(int argc, char **argv) { kernel_pid_t dev; uint8_t addr[MAX_ADDR_LEN]; size_t addr_len; gnrc_pktsnip_t *pkt; gnrc_netif_hdr_t *nethdr; uint8_t flags = 0x00; if (argc < 4) { printf("usage: %s <if> [<addr>|bcast] <data>\n", argv[0]); return 1; } /* parse interface */ dev = (kernel_pid_t)atoi(argv[1]); if (!_is_iface(dev)) { puts("error: invalid interface given"); return 1; } /* parse address */ addr_len = gnrc_netif_addr_from_str(addr, sizeof(addr), argv[2]); if (addr_len == 0) { if (strcmp(argv[2], "bcast") == 0) { flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; } else { puts("error: invalid address given"); return 1; } } /* put packet together */ pkt = gnrc_pktbuf_add(NULL, argv[3], strlen(argv[3]), GNRC_NETTYPE_UNDEF); pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t) + addr_len, GNRC_NETTYPE_NETIF); nethdr = (gnrc_netif_hdr_t *)pkt->data; gnrc_netif_hdr_init(nethdr, 0, addr_len); gnrc_netif_hdr_set_dst_addr(nethdr, addr, addr_len); nethdr->flags = flags; /* and send it */ if (gnrc_netapi_send(dev, pkt) < 1) { puts("error: unable to send\n"); gnrc_pktbuf_release(pkt); return 1; } return 0; }
int gnrc_gomach_send_preamble(gnrc_netif_t *netif, netopt_enable_t csma_enable) { assert(netif != NULL); gnrc_pktsnip_t *pkt; gnrc_netif_hdr_t *nethdr_preamble; gnrc_pktsnip_t *gomach_pkt; /* Assemble the preamble packet. */ gnrc_gomach_frame_preamble_t gomach_preamble_hdr; gomach_preamble_hdr.header.type = GNRC_GOMACH_FRAME_PREAMBLE; memcpy(gomach_preamble_hdr.dst_addr.addr, netif->mac.tx.current_neighbor->l2_addr, netif->mac.tx.current_neighbor->l2_addr_len); gomach_preamble_hdr.dst_addr.len = netif->mac.tx.current_neighbor->l2_addr_len; pkt = gnrc_pktbuf_add(NULL, &gomach_preamble_hdr, sizeof(gomach_preamble_hdr), GNRC_NETTYPE_GOMACH); if (pkt == NULL) { LOG_ERROR("ERROR: [GOMACH]: pktbuf add failed in gnrc_gomach_send_preamble().\n"); return -ENOBUFS; } gomach_pkt = pkt; pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t), GNRC_NETTYPE_NETIF); if (pkt == NULL) { LOG_ERROR("ERROR: [GOMACH]: netif add failed in gnrc_gomach_send_preamble().\n"); gnrc_pktbuf_release(gomach_pkt); return -ENOBUFS; } gomach_pkt = pkt; gnrc_pktsnip_t *netif_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (netif_snip == NULL) { LOG_ERROR("[GOMACH]: No netif_hdr found in gnrc_gomach_send_preamble().\n"); gnrc_pktbuf_release(gomach_pkt); return -ENOBUFS; } else { nethdr_preamble = netif_snip->data; } /* Construct NETIF header and initiate address fields. */ gnrc_netif_hdr_init(nethdr_preamble, 0, 0); /* Send preamble packet as broadcast. */ nethdr_preamble->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; return gnrc_gomach_send(netif, pkt, csma_enable); }
int gnrc_gomach_bcast_subchann_seq(gnrc_netif_t *netif, netopt_enable_t use_csma) { assert(netif != NULL); gnrc_pktsnip_t *pkt; gnrc_pktsnip_t *gomach_pkt; gnrc_netif_hdr_t *nethdr_announce; /* Assemble the sub-channel sequence announce packet. */ gnrc_gomach_frame_announce_t gomach_announce_hdr; gomach_announce_hdr.header.type = GNRC_GOMACH_FRAME_ANNOUNCE; gomach_announce_hdr.subchannel_seq = netif->mac.prot.gomach.sub_channel_seq; pkt = gnrc_pktbuf_add(NULL, &gomach_announce_hdr, sizeof(gomach_announce_hdr), GNRC_NETTYPE_GOMACH); if (pkt == NULL) { LOG_ERROR("ERROR: [GOMACH]: pktbuf add failed in gnrc_gomach_bcast_subchann_seq().\n"); return -ENOBUFS; } gomach_pkt = pkt; pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t), GNRC_NETTYPE_NETIF); if (pkt == NULL) { gnrc_pktbuf_release(gomach_pkt); LOG_ERROR("ERROR: [GOMACH]: netif add failed in gnrc_gomach_bcast_subchann_seq().\n"); return -ENOBUFS; } gnrc_pktsnip_t *netif_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (netif_snip == NULL) { LOG_ERROR("[GOMACH]: No netif_hdr found in gnrc_gomach_bcast_subchann_seq().\n"); gnrc_pktbuf_release(pkt); return -ENOBUFS; } else { nethdr_announce = netif_snip->data; } /* Construct NETIF header and initiate address fields. */ gnrc_netif_hdr_init(nethdr_announce, 0, 0); /* Send the packet as broadcast. */ nethdr_announce->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; return gnrc_gomach_send(netif, pkt, use_csma); }
gnrc_pktsnip_t *gnrc_netif_hdr_build(const uint8_t *src, uint8_t src_len, const uint8_t *dst, uint8_t dst_len) { gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, NULL, sizeof(gnrc_netif_hdr_t) + src_len + dst_len, GNRC_NETTYPE_NETIF); if (pkt == NULL) { return NULL; } gnrc_netif_hdr_init(pkt->data, src_len, dst_len); if (src != NULL && src_len > 0) { gnrc_netif_hdr_set_src_addr(pkt->data, src, src_len); } if (dst != NULL && dst_len > 0) { gnrc_netif_hdr_set_dst_addr(pkt->data, dst, dst_len); } return pkt; }
static gnrc_pktsnip_t *_recv(gnrc_netdev2_t *gnrc_netdev2) { netdev2_t *dev = gnrc_netdev2->dev; cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x; cc110x_pkt_t *cc110x_pkt = &cc110x->pkt_buf.packet; int payload_length = cc110x_pkt->length - CC110X_HEADER_LENGTH; int nettype; int addr_len; switch (cc110x_pkt->flags) { #ifdef MODULE_GNRC_SIXLOWPAN case 1: addr_len = 8; nettype = GNRC_NETTYPE_SIXLOWPAN; break; #endif default: addr_len = 1; nettype = GNRC_NETTYPE_UNDEF; } /* copy packet payload into pktbuf */ gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, cc110x_pkt->data, payload_length, nettype); if(!pkt) { DEBUG("cc110x: _recv: cannot allocate pktsnip.\n"); return NULL; } gnrc_pktsnip_t *netif_hdr; netif_hdr = gnrc_pktbuf_add(NULL, NULL, sizeof(gnrc_netif_hdr_t) + 2*addr_len, GNRC_NETTYPE_NETIF); if (netif_hdr == NULL) { DEBUG("gnrc_netdev2_cc110x: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return NULL; } gnrc_netif_hdr_init(netif_hdr->data, addr_len, addr_len); if (addr_len == 8) { uint64_t src_addr = cc110x_pkt->phy_src; uint64_t dst_addr = cc110x_pkt->address; gnrc_netif_hdr_set_src_addr(netif_hdr->data, (uint8_t*)&src_addr, addr_len); gnrc_netif_hdr_set_dst_addr(netif_hdr->data, (uint8_t*)&dst_addr, addr_len); } else { gnrc_netif_hdr_set_src_addr(netif_hdr->data, (uint8_t*)&cc110x_pkt->phy_src, addr_len); gnrc_netif_hdr_set_dst_addr(netif_hdr->data, (uint8_t*)&cc110x_pkt->address, addr_len); } ((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = thread_getpid(); ((gnrc_netif_hdr_t *)netif_hdr->data)->lqi = cc110x->pkt_buf.lqi; ((gnrc_netif_hdr_t *)netif_hdr->data)->rssi = cc110x->pkt_buf.rssi; DEBUG("gnrc_netdev2_cc110x: received packet from %02x" " of length %u\n", (unsigned)cc110x_pkt->phy_src, (unsigned)cc110x_pkt->length-CC110X_HEADER_LENGTH); #if defined(MODULE_OD) && ENABLE_DEBUG od_hex_dump(cc110x_pkt->data, payload_length, OD_WIDTH_DEFAULT); #endif pkt->next = netif_hdr; return pkt; }
static gnrc_pktsnip_t *_recv(gnrc_netdev2_t *gnrc_netdev2) { netdev2_t *dev = gnrc_netdev2->dev; int bytes_expected = dev->driver->recv(dev, NULL, 0); gnrc_pktsnip_t *pkt = NULL; if (bytes_expected) { pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF); if(!pkt) { DEBUG("_recv_ethernet_packet: cannot allocate pktsnip.\n"); goto out; } int nread = dev->driver->recv(dev, pkt->data, bytes_expected); if(nread <= 0) { DEBUG("_recv_ethernet_packet: read error.\n"); goto safe_out; } if (nread < bytes_expected) { /* we've got less then the expected packet size, * so free the unused space.*/ DEBUG("_recv_ethernet_packet: reallocating.\n"); gnrc_pktbuf_realloc_data(pkt, nread); } /* mark ethernet header */ gnrc_pktsnip_t *eth_hdr = gnrc_pktbuf_mark(pkt, sizeof(ethernet_hdr_t), GNRC_NETTYPE_UNDEF); if (!eth_hdr) { DEBUG("gnrc_netdev2_eth: no space left in packet buffer\n"); goto safe_out; } ethernet_hdr_t *hdr = (ethernet_hdr_t *)eth_hdr->data; /* set payload type from ethertype */ pkt->type = gnrc_nettype_from_ethertype(byteorder_ntohs(hdr->type)); /* create netif header */ gnrc_pktsnip_t *netif_hdr; netif_hdr = gnrc_pktbuf_add(NULL, NULL, sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN), GNRC_NETTYPE_NETIF); if (netif_hdr == NULL) { DEBUG("gnrc_netdev2_eth: no space left in packet buffer\n"); pkt = eth_hdr; goto safe_out; } gnrc_netif_hdr_init(netif_hdr->data, ETHERNET_ADDR_LEN, ETHERNET_ADDR_LEN); gnrc_netif_hdr_set_src_addr(netif_hdr->data, hdr->src, ETHERNET_ADDR_LEN); gnrc_netif_hdr_set_dst_addr(netif_hdr->data, hdr->dst, ETHERNET_ADDR_LEN); ((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = thread_getpid(); DEBUG("gnrc_netdev2_eth: received packet from %02x:%02x:%02x:%02x:%02x:%02x " "of length %zu\n", hdr->src[0], hdr->src[1], hdr->src[2], hdr->src[3], hdr->src[4], hdr->src[5], nread); #if defined(MODULE_OD) && ENABLE_DEBUG od_hex_dump(hdr, nread, OD_WIDTH_DEFAULT); #endif gnrc_pktbuf_remove_snip(pkt, eth_hdr); LL_APPEND(pkt, netif_hdr); } out: return pkt; safe_out: gnrc_pktbuf_release(pkt); return NULL; }
static void _send_packet(void) { gnrc_netif_t *netif = gnrc_netif_iter(NULL); struct { gnrc_netif_hdr_t netif_hdr; uint8_t src[8]; uint8_t dst[8]; } netif_hdr = { .src = IEEE802154_REMOTE_EUI64, .dst = IEEE802154_LOCAL_EUI64, }; gnrc_netif_hdr_init(&(netif_hdr.netif_hdr), 8, 8); netif_hdr.netif_hdr.if_pid = netif->pid; uint8_t data1[] = { /* 6LoWPAN Header */ /* Fragmentation Header (first) */ 0xc0, 0x94, /* 0b11000: frag1, 0b00010010100: datagram_size (148) */ 0x00, 0x01, /* datagram_tag */ /* 0b011: LOWPAN_IPHC */ /* 0b11: Traffic Class and Flow Label are elided */ /* 0b1: Next Header is compressed */ /* 0b11: The Hop Limit field is compressed and the hop limit is 255 */ 0x7f, /* 0b0: No additional 8-bit Context Identifier Extension is used */ /* 0b0: Source address compression uses stateless compression */ /* 0b11: source address mode is 0 bits */ /* 0b0: Destination address is not a multicast address */ /* 0x0: Destination address compression uses stateless compression */ /* 0x00: destination address mode is 128 bits */ 0x30, /* destination address: fd01::1 */ 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0b11110: UDP LOWPAN_NHC */ /* 0b0: Checksum is carried in-line */ /* 0b11: First 12 bits of both Source Port and Destination Port are 0xf0b and elided */ 0xf3, 0x00, /* Source Port and Destination Port (4 bits each) */ 0x23, 0x2f, /* Checksum */ /* payload */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; uint8_t data2[] = { /* 6LoWPAN Header */ /* Fragmentation Header (rest) */ 0xe0, 0x94, /* 0b11100: frag1, 0b00010010100: datagram_size (148) */ 0x00, 0x01, /* datagram_tag */ 0x0c, /* datagram_offset (12 * 8 = 96) */ /* payload */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; gnrc_netreg_entry_t dump_6lowpan = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_entry_t dump_ipv6 = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_entry_t dump_udp = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_entry_t dump_udp_61616 = GNRC_NETREG_ENTRY_INIT_PID(61616, gnrc_pktdump_pid); gnrc_netreg_register(GNRC_NETTYPE_SIXLOWPAN, &dump_6lowpan); gnrc_netreg_register(GNRC_NETTYPE_IPV6, &dump_ipv6); gnrc_netreg_register(GNRC_NETTYPE_UDP, &dump_udp); gnrc_netreg_register(GNRC_NETTYPE_UDP, &dump_udp_61616); gnrc_pktsnip_t *netif1 = gnrc_pktbuf_add(NULL, &netif_hdr, sizeof(netif_hdr), GNRC_NETTYPE_NETIF); gnrc_pktsnip_t *pkt1 = gnrc_pktbuf_add(netif1, data1, sizeof(data1), GNRC_NETTYPE_SIXLOWPAN); gnrc_netapi_dispatch_receive(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt1); gnrc_pktsnip_t *netif2 = gnrc_pktbuf_add(NULL, &netif_hdr, sizeof(netif_hdr), GNRC_NETTYPE_NETIF); gnrc_pktsnip_t *pkt2 = gnrc_pktbuf_add(netif2, data2, sizeof(data2), GNRC_NETTYPE_SIXLOWPAN); gnrc_netapi_dispatch_receive(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt2); }
static uint8_t _send_wr(gnrc_netif_t *netif) { assert(netif != NULL); uint8_t tx_info = 0; gnrc_pktsnip_t *pkt; gnrc_pktsnip_t *pkt_lwmac; gnrc_netif_hdr_t *nethdr; /* if found ongoing transmission, quit this cycle for collision avoidance. * Data packet will be re-queued and try to send in the next cycle. */ if (_gnrc_lwmac_get_netdev_state(netif) == NETOPT_STATE_RX) { if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) { gnrc_pktbuf_release(netif->mac.tx.packet); LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n"); } /* drop pointer so it wont be free'd */ netif->mac.tx.packet = NULL; tx_info |= GNRC_LWMAC_TX_FAIL; return tx_info; } /* Assemble WR */ gnrc_lwmac_frame_wr_t wr_hdr; wr_hdr.header.type = GNRC_LWMAC_FRAMETYPE_WR; memcpy(&(wr_hdr.dst_addr.addr), netif->mac.tx.current_neighbor->l2_addr, netif->mac.tx.current_neighbor->l2_addr_len); wr_hdr.dst_addr.len = netif->mac.tx.current_neighbor->l2_addr_len; pkt = gnrc_pktbuf_add(NULL, &wr_hdr, sizeof(wr_hdr), GNRC_NETTYPE_LWMAC); if (pkt == NULL) { LOG_ERROR("ERROR: [LWMAC-tx] Cannot allocate pktbuf of type GNRC_NETTYPE_LWMAC\n"); gnrc_pktbuf_release(netif->mac.tx.packet); LOG_ERROR("ERROR: [LWMAC-tx] Memory maybe full, drop the data packet\n"); /* clear packet point to avoid TX retry */ netif->mac.tx.packet = NULL; tx_info |= GNRC_LWMAC_TX_FAIL; return tx_info; } /* track the location of this lwmac_frame_wr_t header */ pkt_lwmac = pkt; pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t), GNRC_NETTYPE_NETIF); if (pkt == NULL) { LOG_ERROR("ERROR: [LWMAC-tx] Cannot allocate pktbuf of type GNRC_NETTYPE_NETIF\n"); gnrc_pktbuf_release(pkt_lwmac); LOG_ERROR("ERROR: [LWMAC-tx] Memory maybe full, drop the data packet\n"); gnrc_pktbuf_release(netif->mac.tx.packet); /* clear packet point to avoid TX retry */ netif->mac.tx.packet = NULL; tx_info |= GNRC_LWMAC_TX_FAIL; return tx_info; } /* We wouldn't get here if adding the NETIF header had failed, so no * sanity checks needed */ nethdr = (gnrc_netif_hdr_t *) (gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF))->data; /* Construct NETIF header and insert address for WR packet */ gnrc_netif_hdr_init(nethdr, 0, 0); /* Send WR as broadcast*/ nethdr->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; /* Disable Auto ACK */ netopt_enable_t autoack = NETOPT_DISABLE; netif->dev->driver->set(netif->dev, NETOPT_AUTOACK, &autoack, sizeof(autoack)); /* Prepare WR, this will discard any frame in the transceiver that has * possibly arrived in the meantime but we don't care at this point. */ int res = _gnrc_lwmac_transmit(netif, pkt); if (res < 0) { LOG_ERROR("ERROR: [LWMAC-tx] Send WR failed."); if (pkt != NULL) { gnrc_pktbuf_release(pkt); } tx_info |= GNRC_LWMAC_TX_FAIL; return tx_info; } gnrc_priority_pktqueue_flush(&netif->mac.rx.queue); return tx_info; }
int gnrc_gomach_send_beacon(gnrc_netif_t *netif) { assert(netif != NULL); uint8_t i; uint8_t j = 0; uint8_t total_tdma_node_num = 0; uint8_t total_tdma_slot_num = 0; gnrc_pktsnip_t *pkt = NULL; gnrc_pktsnip_t *gomach_pkt = NULL; gnrc_netif_hdr_t *nethdr_beacon = NULL; /* Start assemble the beacon packet */ gnrc_gomach_frame_beacon_t gomach_beaocn_hdr; gomach_beaocn_hdr.header.type = GNRC_GOMACH_FRAME_BEACON; gomach_beaocn_hdr.sub_channel_seq = netif->mac.prot.gomach.sub_channel_seq; /* Start generating the slots list and the related ID list for guiding * the following vTMDA procedure (slotted transmission). */ netif->mac.rx.vtdma_manag.total_slots_num = 0; gnrc_gomach_l2_id_t id_list[GNRC_GOMACH_SLOSCH_UNIT_COUNT]; uint8_t slots_list[GNRC_GOMACH_SLOSCH_UNIT_COUNT]; /* Check the maximum number of slots that can be allocated to senders. */ uint16_t max_slot_num = (GNRC_GOMACH_SUPERFRAME_DURATION_US - gnrc_gomach_phase_now(netif)) / GNRC_GOMACH_VTDMA_SLOT_SIZE_US; for (i = 0; i < GNRC_GOMACH_SLOSCH_UNIT_COUNT; i++) { if (netif->mac.rx.slosch_list[i].queue_indicator > 0) { /* Record the device's (that will be allocated slots) address to the ID list. */ memcpy(id_list[j].addr, netif->mac.rx.slosch_list[i].node_addr.addr, netif->mac.rx.slosch_list[i].node_addr.len); /* Record the number of allocated slots to the slots list. */ slots_list[j] = netif->mac.rx.slosch_list[i].queue_indicator; total_tdma_node_num++; total_tdma_slot_num += slots_list[j]; /* If there is no room for allocating more slots, stop. */ if (total_tdma_slot_num >= max_slot_num) { uint8_t redueced_slots_num; redueced_slots_num = total_tdma_slot_num - max_slot_num; slots_list[j] -= redueced_slots_num; total_tdma_slot_num -= redueced_slots_num; break; } j++; /* If reach the maximum sender ID number limit, stop. */ if (total_tdma_node_num >= GNRC_GOMACH_MAX_ALLOC_SENDER_NUM) { break; } } } gomach_beaocn_hdr.schedulelist_size = total_tdma_node_num; if (total_tdma_node_num > 0) { if (!_assemble_beacon(netif, total_tdma_slot_num, total_tdma_node_num, slots_list, id_list, &pkt, &gomach_pkt, &gomach_beaocn_hdr)) { return -ENOBUFS; } gomach_pkt = pkt; } else { /* If there is no slots to allocate, quit sending beacon! */ return -ENOBUFS; } /* Add the Netif header. */ pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t), GNRC_NETTYPE_NETIF); if (pkt == NULL) { LOG_ERROR("ERROR: [GOMACH]: pktbuf add failed in gnrc_gomach_send_beacon().\n"); gnrc_pktbuf_release(gomach_pkt); return -ENOBUFS; } gomach_pkt = pkt; gnrc_pktsnip_t *beacon_netif_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (beacon_netif_snip == NULL) { LOG_ERROR("[GOMACH]: NO netif_hdr found in send_beacon().\n"); gnrc_pktbuf_release(pkt); return -ENOBUFS; } else { nethdr_beacon = beacon_netif_snip->data; } /* Construct NETIF header. */ gnrc_netif_hdr_init(nethdr_beacon, 0, 0); /* Send beacon as broadcast*/ nethdr_beacon->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; int res; if (gnrc_gomach_get_unintd_preamble(netif)) { /* Use csma for collision avoidance if we found ongoing preamble transmission. */ res = gnrc_gomach_send(netif, pkt, NETOPT_ENABLE); } else { /* Send the beacon without CSMA if there is no ongoing preamble transmission. */ res = gnrc_gomach_send(netif, pkt, NETOPT_DISABLE); } if (res < 0) { LOG_ERROR("ERROR: [GOMACH]: send beacon failed, release it.\n"); gnrc_pktbuf_release(pkt); } else { gnrc_gomach_set_timeout(netif, GNRC_GOMACH_TIMEOUT_NO_TX_ISR, GNRC_GOMACH_NO_TX_ISR_US); } return res; }
/* return false if send wa failed, otherwise return true */ static bool _send_wa(gnrc_netdev_t *gnrc_netdev) { gnrc_pktsnip_t *pkt; gnrc_pktsnip_t *pkt_lwmac; gnrc_netif_hdr_t *nethdr_wa; assert(gnrc_netdev != NULL); assert(gnrc_netdev->rx.l2_addr.len != 0); /* if found ongoing transmission, * quit sending WA for collision avoidance. */ if (_gnrc_lwmac_get_netdev_state(gnrc_netdev) == NETOPT_STATE_RX) { gnrc_netdev->rx.rx_bad_exten_count++; return false; } /* Assemble WA packet */ gnrc_lwmac_frame_wa_t lwmac_hdr; lwmac_hdr.header.type = GNRC_LWMAC_FRAMETYPE_WA; lwmac_hdr.dst_addr = gnrc_netdev->rx.l2_addr; uint32_t phase_now = _gnrc_lwmac_phase_now(); /* Embed the current 'relative phase timing' (counted from the start of this cycle) * of the receiver into its WA packet, thus to allow the sender to infer the * receiver's exact wake-up timing */ if (phase_now > _gnrc_lwmac_ticks_to_phase(gnrc_netdev->lwmac.last_wakeup)) { lwmac_hdr.current_phase = (phase_now - _gnrc_lwmac_ticks_to_phase(gnrc_netdev->lwmac.last_wakeup)); } else { lwmac_hdr.current_phase = (phase_now + RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)) - _gnrc_lwmac_ticks_to_phase(gnrc_netdev->lwmac.last_wakeup); } pkt = gnrc_pktbuf_add(NULL, &lwmac_hdr, sizeof(lwmac_hdr), GNRC_NETTYPE_LWMAC); if (pkt == NULL) { LOG_ERROR("ERROR: [LWMAC-rx] Cannot allocate pktbuf of type GNRC_NETTYPE_LWMAC\n"); gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true); return false; } pkt_lwmac = pkt; pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t) + gnrc_netdev->rx.l2_addr.len, GNRC_NETTYPE_NETIF); if (pkt == NULL) { LOG_ERROR("ERROR: [LWMAC-rx] Cannot allocate pktbuf of type GNRC_NETTYPE_NETIF\n"); gnrc_pktbuf_release(pkt_lwmac); gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true); return false; } /* We wouldn't get here if add the NETIF header had failed, so no sanity checks needed */ nethdr_wa = (gnrc_netif_hdr_t *)(gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF)->data); /* Construct NETIF header and insert address for WA packet */ gnrc_netif_hdr_init(nethdr_wa, 0, gnrc_netdev->rx.l2_addr.len); /* Send WA as broadcast*/ nethdr_wa->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; /* Disable Auto ACK */ netopt_enable_t autoack = NETOPT_DISABLE; gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_AUTOACK, &autoack, sizeof(autoack)); /* Send WA */ if (gnrc_netdev->send(gnrc_netdev, pkt) < 0) { LOG_ERROR("ERROR: [LWMAC-rx] Send WA failed."); if (pkt != NULL) { gnrc_pktbuf_release(pkt); } gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true); return false; } /* Enable Auto ACK again for data reception */ autoack = NETOPT_ENABLE; gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_AUTOACK, &autoack, sizeof(autoack)); return true; }