/* TODO: generalize and move to (gnrc_)ieee802154 */ static size_t _make_data_frame_hdr(at86rf2xx_t *dev, uint8_t *buf, gnrc_netif_hdr_t *hdr) { int pos = 0; /* we are building a data frame here */ buf[0] = IEEE802154_FCF_TYPE_DATA; buf[1] = IEEE802154_FCF_VERS_V1; /* if AUTOACK is enabled, then we also expect ACKs for this packet */ if (!(hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) && !(hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) && (dev->options & AT86RF2XX_OPT_AUTOACK)) { buf[0] |= IEEE802154_FCF_ACK_REQ; } /* fill in destination PAN ID */ pos = 3; buf[pos++] = (uint8_t)((dev->pan) & 0xff); buf[pos++] = (uint8_t)((dev->pan) >> 8); /* fill in destination address */ if (hdr->flags & (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { buf[1] |= IEEE802154_FCF_DST_ADDR_SHORT; buf[pos++] = 0xff; buf[pos++] = 0xff; } else if (hdr->dst_l2addr_len == 2) { uint8_t *dst_addr = gnrc_netif_hdr_get_dst_addr(hdr); buf[1] |= IEEE802154_FCF_DST_ADDR_SHORT; buf[pos++] = dst_addr[1]; buf[pos++] = dst_addr[0]; } else if (hdr->dst_l2addr_len == 8) { buf[1] |= IEEE802154_FCF_DST_ADDR_LONG; uint8_t *dst_addr = gnrc_netif_hdr_get_dst_addr(hdr); for (int i = 7; i >= 0; i--) { buf[pos++] = dst_addr[i]; } } else { /* unsupported address length */ return 0; } /* fill in source PAN ID (if applicable */ if (dev->options & AT86RF2XX_OPT_USE_SRC_PAN) { buf[pos++] = (uint8_t)((dev->pan) & 0xff); buf[pos++] = (uint8_t)((dev->pan) >> 8); } else {
static gnrc_pktsnip_t *_build_frag_pkt(gnrc_pktsnip_t *pkt, size_t payload_len, size_t size) { gnrc_netif_hdr_t *hdr = pkt->data, *new_hdr; gnrc_pktsnip_t *netif, *frag; netif = gnrc_netif_hdr_build(gnrc_netif_hdr_get_src_addr(hdr), hdr->src_l2addr_len, gnrc_netif_hdr_get_dst_addr(hdr), hdr->dst_l2addr_len); if (netif == NULL) { DEBUG("6lo frag: error allocating new link-layer header\n"); return NULL; } new_hdr = netif->data; new_hdr->if_pid = hdr->if_pid; new_hdr->flags = hdr->flags; new_hdr->rssi = hdr->rssi; new_hdr->lqi = hdr->lqi; frag = gnrc_pktbuf_add(NULL, NULL, _min(size, payload_len), GNRC_NETTYPE_SIXLOWPAN); if (frag == NULL) { DEBUG("6lo frag: error allocating first fragment\n"); gnrc_pktbuf_release(netif); return NULL; } LL_PREPEND(frag, netif); return frag; }
static int _send(gnrc_netdev_t *netdev, gnrc_pktsnip_t *pkt) { xbee_t *dev = (xbee_t *)netdev; size_t size; size_t pos; gnrc_netif_hdr_t *hdr; gnrc_pktsnip_t *payload; /* check device descriptor and packet */ if (pkt == NULL) { return -ENOMSG; } if (dev == NULL) { gnrc_pktbuf_release(pkt); return -ENODEV; } /* figure out the size of the payload to send */ size = gnrc_pkt_len(pkt->next); if (size > XBEE_MAX_PAYLOAD_LENGTH) { DEBUG("xbee: Error sending data, payload length exceeds limit\n"); gnrc_pktbuf_release(pkt); return -EOVERFLOW; } /* get netif header check address length and flags */ hdr = (gnrc_netif_hdr_t *)pkt->data; if (!((hdr->dst_l2addr_len == 2) || (hdr->dst_l2addr_len == 8) || _is_broadcast(hdr))) { gnrc_pktbuf_release(pkt); return -ENOMSG; } /* acquire TX lock */ mutex_lock(&(dev->tx_lock)); /* put together the API frame */ dev->tx_buf[0] = API_START_DELIMITER; dev->tx_buf[4] = 0; /* set to zero to disable response frame */ /* set size, API id and address field depending on dst address length */ if (_is_broadcast(hdr)) { dev->tx_buf[1] = (uint8_t)((size + 5) >> 8); dev->tx_buf[2] = (uint8_t)(size + 5); dev->tx_buf[3] = API_ID_TX_SHORT_ADDR; dev->tx_buf[4] = 0xff; dev->tx_buf[5] = 0xff; } if (hdr->dst_l2addr_len == 2) { dev->tx_buf[1] = (uint8_t)((size + 5) >> 8); dev->tx_buf[2] = (uint8_t)(size + 5); dev->tx_buf[3] = API_ID_TX_SHORT_ADDR; memcpy(dev->tx_buf + 5, gnrc_netif_hdr_get_dst_addr(hdr), 2); pos = 7; }
int gnrc_netif_hdr_get_dstaddr(gnrc_pktsnip_t* pkt, uint8_t** pointer_to_addr) { assert(pkt != NULL); pkt = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (pkt && pkt->data) { gnrc_netif_hdr_t *netif_hdr = pkt->data; if (netif_hdr->dst_l2addr_len > 0) { *pointer_to_addr = gnrc_netif_hdr_get_dst_addr(netif_hdr); return netif_hdr->dst_l2addr_len; } } return -ENOENT; }
static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) { netdev_t *dev = netif->dev; netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev; gnrc_netif_hdr_t *netif_hdr; const uint8_t *src, *dst = NULL; int res = 0; size_t src_len, dst_len; uint8_t mhr[IEEE802154_MAX_HDR_LEN]; uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK); le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan)); flags |= IEEE802154_FCF_TYPE_DATA; if (pkt == NULL) { DEBUG("_send_ieee802154: pkt was NULL\n"); return -EINVAL; } if (pkt->type != GNRC_NETTYPE_NETIF) { DEBUG("_send_ieee802154: first header is not generic netif header\n"); return -EBADMSG; } netif_hdr = pkt->data; if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MORE_DATA) { /* Set frame pending field */ flags |= IEEE802154_FCF_FRAME_PEND; } /* prepare destination address */ if (netif_hdr->flags & /* If any of these flags is set assume broadcast */ (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { dst = ieee802154_addr_bcast; dst_len = IEEE802154_ADDR_BCAST_LEN; } else { dst = gnrc_netif_hdr_get_dst_addr(netif_hdr); dst_len = netif_hdr->dst_l2addr_len; } src_len = netif_hdr->src_l2addr_len; if (src_len > 0) { src = gnrc_netif_hdr_get_src_addr(netif_hdr); } else { src_len = netif->l2addr_len; src = netif->l2addr; } /* fill MAC header, seq should be set by device */ if ((res = ieee802154_set_frame_hdr(mhr, src, src_len, dst, dst_len, dev_pan, dev_pan, flags, state->seq++)) == 0) { DEBUG("_send_ieee802154: Error preperaring frame\n"); return -EINVAL; } /* prepare iolist for netdev / mac layer */ iolist_t iolist = { .iol_next = (iolist_t *)pkt->next, .iol_base = mhr, .iol_len = (size_t)res }; #ifdef MODULE_NETSTATS_L2 if (netif_hdr->flags & (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { netif->stats.tx_mcast_count++; } else { netif->stats.tx_unicast_count++; } #endif #ifdef MODULE_GNRC_MAC if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) { res = csma_sender_csma_ca_send(dev, &iolist, &netif->mac.csma_conf); } else { res = dev->driver->send(dev, &iolist); } #else res = dev->driver->send(dev, &iolist); #endif /* release old data */ gnrc_pktbuf_release(pkt); return res; }
static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt) { netdev2_t *netdev = gnrc_netdev2->dev; netdev2_ieee802154_t *state = (netdev2_ieee802154_t *)gnrc_netdev2->dev; gnrc_netif_hdr_t *netif_hdr; gnrc_pktsnip_t *vec_snip; uint8_t *src, *dst = NULL; int res = 0; size_t n, src_len; uint8_t mhr[IEEE802154_MAX_HDR_LEN]; uint8_t flags = (uint8_t)(state->flags & NETDEV2_IEEE802154_SEND_MASK); le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan)); flags |= IEEE802154_FCF_TYPE_DATA; if (pkt == NULL) { DEBUG("_send_ieee802154: pkt was NULL\n"); return -EINVAL; } if (pkt->type != GNRC_NETTYPE_NETIF) { DEBUG("_send_ieee802154: first header is not generic netif header\n"); return -EBADMSG; } netif_hdr = pkt->data; /* prepare destination address */ if (netif_hdr->flags & /* If any of these flags is set so this is correct */ (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { flags |= IEEE802154_BCAST; } else { dst = gnrc_netif_hdr_get_dst_addr(netif_hdr); } src_len = netif_hdr->src_l2addr_len; if (src_len > 0) { src = gnrc_netif_hdr_get_src_addr(netif_hdr); } else if (state->flags & NETDEV2_IEEE802154_SRC_MODE_LONG) { src_len = IEEE802154_LONG_ADDRESS_LEN; src = state->long_addr; } else { src_len = IEEE802154_SHORT_ADDRESS_LEN; src = state->short_addr; } /* fill MAC header, seq should be set by device */ if ((res = ieee802154_set_frame_hdr(mhr, src, src_len, dst, netif_hdr->dst_l2addr_len, dev_pan, dev_pan, flags, state->seq++)) == 0) { DEBUG("_send_ieee802154: Error preperaring frame\n"); return -EINVAL; } /* prepare packet for sending */ vec_snip = gnrc_pktbuf_get_iovec(pkt, &n); if (vec_snip != NULL) { struct iovec *vector; pkt = vec_snip; /* reassign for later release; vec_snip is prepended to pkt */ vector = (struct iovec *)pkt->data; vector[0].iov_base = mhr; vector[0].iov_len = (size_t)res; res = netdev->driver->send(netdev, vector, n); } else { return -ENOBUFS; } /* release old data */ gnrc_pktbuf_release(pkt); return res; }
/* tests receiving */ static int test_receive(void) { ethernet_hdr_t *rcv_mac = (ethernet_hdr_t *)_tmp; uint8_t *rcv_payload = _tmp + sizeof(ethernet_hdr_t); gnrc_pktsnip_t *pkt, *hdr; gnrc_netreg_entry_t me = { NULL, GNRC_NETREG_DEMUX_CTX_ALL, thread_getpid() }; msg_t msg; if (_dev.netdev.event_callback == NULL) { puts("Device's event_callback not set"); return 0; } /* prepare receive buffer */ memcpy(rcv_mac->dst, _dev_addr, sizeof(_dev_addr)); memcpy(rcv_mac->src, _test_src, sizeof(_test_src)); /* no gnrc_ipv6 in compile unit => ETHERTYPE_IPV6 translates to * GNRC_NETTYPE_UNDEF */ rcv_mac->type = byteorder_htons(ETHERTYPE_IPV6); memcpy(rcv_payload, _TEST_PAYLOAD2, sizeof(_TEST_PAYLOAD2) - 1); _tmp_len = sizeof(_TEST_PAYLOAD2) + sizeof(ethernet_hdr_t) - 1; /* register for GNRC_NETTYPE_UNDEF */ gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &me); /* fire ISR event */ _dev.netdev.event_callback((netdev2_t *)&_dev.netdev, NETDEV2_EVENT_ISR); /* wait for packet from MAC layer*/ msg_receive(&msg); /* check message */ if (msg.sender_pid != _mac_pid) { puts("Unexpected sender of netapi receive message"); return 0; } if (msg.type != GNRC_NETAPI_MSG_TYPE_RCV) { puts("Expected netapi receive message"); return 0; } pkt = msg.content.ptr; /* check payload */ if (pkt->size != _tmp_len - sizeof(ethernet_hdr_t)) { puts("Payload of unexpected size"); } if ((pkt->type != GNRC_NETTYPE_UNDEF) || (memcmp(pkt->data, _TEST_PAYLOAD2, pkt->size) != 0)) { puts("Unexpected payload"); puts("==========================================================="); puts("expected"); puts("==========================================================="); od_hex_dump(_TEST_PAYLOAD2, pkt->size, OD_WIDTH_DEFAULT); puts("==========================================================="); puts("send data"); puts("==========================================================="); od_hex_dump(pkt->data, pkt->size, OD_WIDTH_DEFAULT); return 0; } hdr = pkt->next; /* check netif header */ if ((hdr->type != GNRC_NETTYPE_NETIF) || (hdr->next != NULL) || (hdr->size) != (sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN))) { puts("Malformed header received"); return 0; } if (memcmp(gnrc_netif_hdr_get_src_addr(hdr->data), _test_src, ETHERNET_ADDR_LEN) != 0) { char addr_str[ETHERNET_ADDR_LEN * 3]; puts("Unexpected source received"); puts("================="); puts("expected"); puts("================="); puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), _test_src, ETHERNET_ADDR_LEN)); puts("================="); puts("received source"); puts("================="); puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), gnrc_netif_hdr_get_src_addr(hdr->data), ETHERNET_ADDR_LEN)); return 0; } if (memcmp(gnrc_netif_hdr_get_dst_addr(hdr->data), _dev_addr, ETHERNET_ADDR_LEN) != 0) { char addr_str[ETHERNET_ADDR_LEN * 3]; puts("Unexpected destination received"); puts("================="); puts("expected"); puts("================="); puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), _dev_addr, ETHERNET_ADDR_LEN)); puts("===================="); puts("received destination"); puts("===================="); puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), gnrc_netif_hdr_get_dst_addr(hdr->data), ETHERNET_ADDR_LEN)); return 0; } gnrc_pktbuf_release(pkt); gnrc_netreg_unregister(GNRC_NETTYPE_UNDEF, &me); return 1; }
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, size_t frag_size, size_t offset) { rbuf_t *entry; /* cppcheck-suppress variableScope * (reason: cppcheck is clearly wrong here) */ unsigned int data_offset = 0; size_t original_size = frag_size; sixlowpan_frag_t *frag = pkt->data; rbuf_int_t *ptr; uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t); _rbuf_gc(); entry = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len, gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len, byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK, byteorder_ntohs(frag->tag)); if (entry == NULL) { DEBUG("6lo rbuf: reassembly buffer full.\n"); return; } ptr = entry->ints; /* dispatches in the first fragment are ignored */ if (offset == 0) { if (data[0] == SIXLOWPAN_UNCOMP) { data++; /* skip 6LoWPAN dispatch */ frag_size--; } #ifdef MODULE_GNRC_SIXLOWPAN_IPHC else if (sixlowpan_iphc_is(data)) { size_t iphc_len, nh_len = 0; iphc_len = gnrc_sixlowpan_iphc_decode(&entry->pkt, pkt, entry->pkt->size, sizeof(sixlowpan_frag_t), &nh_len); if (iphc_len == 0) { DEBUG("6lo rfrag: could not decode IPHC dispatch\n"); gnrc_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } data += iphc_len; /* take remaining data as data */ frag_size -= iphc_len; /* and reduce frag size by IPHC dispatch length */ /* but add IPv6 header + next header lengths */ frag_size += sizeof(ipv6_hdr_t) + nh_len; /* start copying after IPv6 header and next headers */ data_offset += sizeof(ipv6_hdr_t) + nh_len; } #endif } else { data++; /* FRAGN header is one byte longer (offset) */ } if ((offset + frag_size) > entry->pkt->size) { DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); gnrc_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } /* If the fragment overlaps another fragment and differs in either the size * or the offset of the overlapped fragment, discards the datagram * https://tools.ietf.org/html/rfc4944#section-5.3 */ while (ptr != NULL) { if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) { DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n"); gnrc_pktbuf_release(entry->pkt); _rbuf_rem(entry); /* "A fresh reassembly may be commenced with the most recently * received link fragment" * https://tools.ietf.org/html/rfc4944#section-5.3 */ rbuf_add(netif_hdr, pkt, original_size, offset); return; } ptr = ptr->next; } if (_rbuf_update_ints(entry, offset, frag_size)) { DEBUG("6lo rbuf: add fragment data\n"); entry->cur_size += (uint16_t)frag_size; memcpy(((uint8_t *)entry->pkt->data) + offset + data_offset, data, frag_size - data_offset); } if (entry->cur_size == entry->pkt->size) { gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(entry->src, entry->src_len, entry->dst, entry->dst_len); if (netif == NULL) { DEBUG("6lo rbuf: error allocating netif header\n"); gnrc_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } /* copy the transmit information of the latest fragment into the newly * created header to have some link_layer information. The link_layer * info of the previous fragments is discarded. */ gnrc_netif_hdr_t *new_netif_hdr = netif->data; new_netif_hdr->if_pid = netif_hdr->if_pid; new_netif_hdr->flags = netif_hdr->flags; new_netif_hdr->lqi = netif_hdr->lqi; new_netif_hdr->rssi = netif_hdr->rssi; LL_APPEND(entry->pkt, netif); if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, entry->pkt)) { DEBUG("6lo rbuf: No receivers for this packet found\n"); gnrc_pktbuf_release(entry->pkt); } _rbuf_rem(entry); } }
static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt) { cc110x_pkt_t cc110x_pkt; netdev2_t *dev = gnrc_netdev2->dev; netdev2_cc110x_t *netdev_cc110x = (netdev2_cc110x_t *) dev; cc110x_t *cc110x = &netdev_cc110x->cc110x; assert(pkt != NULL); assert(dev->driver == &netdev2_cc110x_driver); gnrc_netif_hdr_t *netif_hdr; gnrc_pktsnip_t *payload; payload = pkt->next; if (pkt->type != GNRC_NETTYPE_NETIF) { DEBUG("gnrc_netdev2_cc110x: First header was not generic netif header\n"); gnrc_pktbuf_release(pkt); return -EBADMSG; } netif_hdr = (gnrc_netif_hdr_t *) pkt->data; /* set up header */ if (netif_hdr->src_l2addr_len == 1) { uint8_t *_src_addr = gnrc_netif_hdr_get_src_addr(netif_hdr); cc110x_pkt.phy_src = *_src_addr; } else { cc110x_pkt.phy_src = cc110x->radio_address; } if (netif_hdr->flags & (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { cc110x_pkt.address = 0; } else { uint8_t *_dst_addr = gnrc_netif_hdr_get_dst_addr(netif_hdr); cc110x_pkt.address = _dst_addr[netif_hdr->dst_l2addr_len-1]; } switch (payload->type) { #ifdef MODULE_GNRC_SIXLOWPAN case GNRC_NETTYPE_SIXLOWPAN: cc110x_pkt.flags = 1; break; #endif default: cc110x_pkt.flags = 0; } struct iovec vector; vector.iov_base = (char*)&cc110x_pkt; vector.iov_len = sizeof(cc110x_pkt_t); unsigned payload_len = 0; uint8_t *pos = cc110x_pkt.data; while (payload) { payload_len += payload->size; if (payload_len > CC110X_MAX_DATA_LENGTH) { DEBUG("gnrc_netdev2_cc110x: payload length exceeds maximum" "(%u>%u)\n", payload_len, CC110X_MAX_DATA_LENGTH); gnrc_pktbuf_release(pkt); return -EBADMSG; } memcpy(pos, payload->data, payload->size); pos += payload->size; payload = payload->next; } /* pkt has been copied into iovec, we're done with it. */ gnrc_pktbuf_release(pkt); cc110x_pkt.length = (uint8_t) payload_len + CC110X_HEADER_LENGTH; DEBUG("gnrc_netdev2_cc110x: sending packet from %u to %u with payload " "length %u\n", (unsigned)cc110x_pkt.phy_src, (unsigned)cc110x_pkt.address, (unsigned)cc110x_pkt.length); return dev->driver->send(dev, &vector, 1); }
static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt) { ethernet_hdr_t hdr; gnrc_netif_hdr_t *netif_hdr; gnrc_pktsnip_t *payload; netdev2_t *dev = gnrc_netdev2->dev; if (pkt == NULL) { DEBUG("gnrc_netdev2_eth: pkt was NULL"); return -EINVAL; } payload = pkt->next; if (pkt->type != GNRC_NETTYPE_NETIF) { DEBUG("gnrc_netdev2_eth: First header was not generic netif header\n"); return -EBADMSG; } if (payload) { hdr.type = byteorder_htons(gnrc_nettype_to_ethertype(payload->type)); } else { hdr.type = byteorder_htons(ETHERTYPE_UNKNOWN); } netif_hdr = pkt->data; /* set ethernet header */ if (netif_hdr->src_l2addr_len == ETHERNET_ADDR_LEN) { memcpy(hdr.dst, gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len); } else { dev->driver->get(dev, NETOPT_ADDRESS, hdr.src, ETHERNET_ADDR_LEN); } if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) { _addr_set_broadcast(hdr.dst); } else if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) { _addr_set_multicast(hdr.dst, payload); } else if (netif_hdr->dst_l2addr_len == ETHERNET_ADDR_LEN) { memcpy(hdr.dst, gnrc_netif_hdr_get_dst_addr(netif_hdr), ETHERNET_ADDR_LEN); } else { DEBUG("gnrc_netdev2_eth: destination address had unexpected format\n"); return -EBADMSG; } DEBUG("gnrc_netdev2_eth: send to %02x:%02x:%02x:%02x:%02x:%02x\n", hdr.dst[0], hdr.dst[1], hdr.dst[2], hdr.dst[3], hdr.dst[4], hdr.dst[5]); size_t n; pkt = gnrc_pktbuf_get_iovec(pkt, &n); struct iovec *vector = (struct iovec *)pkt->data; vector[0].iov_base = (char*)&hdr; vector[0].iov_len = sizeof(ethernet_hdr_t); dev->driver->send(dev, vector, n); gnrc_pktbuf_release(pkt); return 0; }
int _gnrc_gomach_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) { netdev_t *dev = netif->dev; netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev; gnrc_netif_hdr_t *netif_hdr; gnrc_pktsnip_t *vec_snip; const uint8_t *src, *dst = NULL; int res = 0; size_t n, src_len, dst_len; uint8_t mhr[IEEE802154_MAX_HDR_LEN]; uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK); le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan)); flags |= IEEE802154_FCF_TYPE_DATA; if (pkt == NULL) { DEBUG("_send_ieee802154: pkt was NULL\n"); return -EINVAL; } if (pkt->type != GNRC_NETTYPE_NETIF) { DEBUG("_send_ieee802154: first header is not generic netif header\n"); return -EBADMSG; } netif_hdr = pkt->data; /* prepare destination address */ if (netif_hdr->flags & /* If any of these flags is set assume broadcast */ (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { dst = ieee802154_addr_bcast; dst_len = IEEE802154_ADDR_BCAST_LEN; } else { dst = gnrc_netif_hdr_get_dst_addr(netif_hdr); dst_len = netif_hdr->dst_l2addr_len; } src_len = netif_hdr->src_l2addr_len; if (src_len > 0) { src = gnrc_netif_hdr_get_src_addr(netif_hdr); } else { src_len = netif->l2addr_len; src = netif->l2addr; } /* fill MAC header, seq should be set by device */ if ((res = ieee802154_set_frame_hdr(mhr, src, src_len, dst, dst_len, dev_pan, dev_pan, flags, state->seq++)) == 0) { DEBUG("_send_ieee802154: Error preperaring frame\n"); return -EINVAL; } /* prepare packet for sending */ vec_snip = gnrc_pktbuf_get_iovec(pkt, &n); if (vec_snip != NULL) { struct iovec *vector; pkt = vec_snip; /* reassign for later release; vec_snip is prepended to pkt */ vector = (struct iovec *)pkt->data; vector[0].iov_base = mhr; vector[0].iov_len = (size_t)res; #ifdef MODULE_NETSTATS_L2 if (netif_hdr->flags & (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { netif->dev->stats.tx_mcast_count++; } else { netif->dev->stats.tx_unicast_count++; } #endif #ifdef MODULE_GNRC_MAC if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) { res = csma_sender_csma_ca_send(dev, vector, n, &netif->mac.csma_conf); } else { res = dev->driver->send(dev, vector, n); } #else res = dev->driver->send(dev, vector, n); #endif } else { return -ENOBUFS; } /* release old data */ gnrc_pktbuf_release(pkt); return res; }
static int _parse_packet(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt, gnrc_gomach_packet_info_t *info) { assert(info != NULL); assert(pkt != NULL); netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev; /* Get the packet sequence number */ info->seq = ieee802154_get_seq(pkt->next->data); gnrc_pktsnip_t *netif_snip = _make_netif_hdr(pkt->next->data); if (netif_snip == NULL) { DEBUG("gomach: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return -ENODATA; } gnrc_netif_hdr_t *netif_hdr = netif_snip->data; netif_hdr->lqi = netif->mac.prot.gomach.rx_pkt_lqi; netif_hdr->rssi = netif->mac.prot.gomach.rx_pkt_rssi; netif_hdr->if_pid = netif->pid; pkt->type = state->proto; gnrc_pktbuf_remove_snip(pkt, pkt->next); LL_APPEND(pkt, netif_snip); gnrc_pktsnip_t *gomach_snip = NULL; gnrc_gomach_hdr_t *gomach_hdr = NULL; netif_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (netif_snip == NULL) { return -ENODATA; } else { netif_hdr = netif_snip->data; } if (netif_hdr->dst_l2addr_len > sizeof(info->dst_addr)) { return -ENODATA; } if (netif_hdr->src_l2addr_len > sizeof(info->src_addr)) { return -ENODATA; } /* Dissect GoMacH header, Every frame has header as first member */ gomach_hdr = (gnrc_gomach_hdr_t *) pkt->data; switch (gomach_hdr->type) { case GNRC_GOMACH_FRAME_BEACON: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_beacon_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_PREAMBLE: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_preamble_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_PREAMBLE_ACK: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_preamble_ack_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_DATA: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_data_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_ANNOUNCE: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_announce_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_BROADCAST: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_broadcast_t), GNRC_NETTYPE_GOMACH); break; } default: { return -ENODATA; } } /* Memory location may have changed while marking. */ gomach_hdr = gomach_snip->data; /* Get the destination address. */ switch (gomach_hdr->type) { case GNRC_GOMACH_FRAME_PREAMBLE: { info->dst_addr = ((gnrc_gomach_frame_preamble_t *)gomach_hdr)->dst_addr; break; } case GNRC_GOMACH_FRAME_PREAMBLE_ACK: { info->dst_addr = ((gnrc_gomach_frame_preamble_ack_t *)gomach_hdr)->dst_addr; break; } case GNRC_GOMACH_FRAME_DATA: { if (netif_hdr->dst_l2addr_len) { info->dst_addr.len = netif_hdr->dst_l2addr_len; memcpy(info->dst_addr.addr, gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len); } break; } default: { break; } } /* Get the source address. */ if (netif_hdr->src_l2addr_len) { info->src_addr.len = netif_hdr->src_l2addr_len; memcpy(info->src_addr.addr, gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len); } info->header = gomach_hdr; return 0; }
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, size_t offset, unsigned page) { rbuf_t *entry; sixlowpan_frag_t *frag = pkt->data; rbuf_int_t *ptr; uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t); size_t frag_size; rbuf_gc(); entry = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len, gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len, byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK, byteorder_ntohs(frag->tag), page); if (entry == NULL) { DEBUG("6lo rbuf: reassembly buffer full.\n"); return; } ptr = entry->ints; /* dispatches in the first fragment are ignored */ if (offset == 0) { frag_size = pkt->size - sizeof(sixlowpan_frag_t); if (data[0] == SIXLOWPAN_UNCOMP) { frag_size--; } } else { frag_size = pkt->size - sizeof(sixlowpan_frag_n_t); data++; /* FRAGN header is one byte longer (offset) */ } if ((offset + frag_size) > entry->super.pkt->size) { DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); return; } /* If the fragment overlaps another fragment and differs in either the size * or the offset of the overlapped fragment, discards the datagram * https://tools.ietf.org/html/rfc4944#section-5.3 */ while (ptr != NULL) { if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) { DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n"); gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); /* "A fresh reassembly may be commenced with the most recently * received link fragment" * https://tools.ietf.org/html/rfc4944#section-5.3 */ rbuf_add(netif_hdr, pkt, offset, page); return; } ptr = ptr->next; } if (_rbuf_update_ints(entry, offset, frag_size)) { DEBUG("6lo rbuf: add fragment data\n"); entry->super.current_size += (uint16_t)frag_size; if (offset == 0) { #ifdef MODULE_GNRC_SIXLOWPAN_IPHC if (sixlowpan_iphc_is(data)) { gnrc_pktsnip_t *frag_hdr = gnrc_pktbuf_mark(pkt, sizeof(sixlowpan_frag_t), GNRC_NETTYPE_SIXLOWPAN); if (frag_hdr == NULL) { gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); return; } gnrc_sixlowpan_iphc_recv(pkt, &entry->super, 0); return; } else #endif if (data[0] == SIXLOWPAN_UNCOMP) { data++; } } memcpy(((uint8_t *)entry->super.pkt->data) + offset, data, frag_size); } gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(&entry->super, netif_hdr); gnrc_pktbuf_release(pkt); }