Example #1
0
static bool send_ipv4_udp_msg(struct net_if *iface,
			      struct in_addr *src,
			      struct in_addr *dst,
			      u16_t src_port,
			      u16_t dst_port,
			      struct ud *ud,
			      bool expect_failure)
{
	struct net_pkt *pkt;
	struct net_buf *frag;
	int ret;

	pkt = net_pkt_get_reserve_tx(0, K_FOREVER);
	frag = net_pkt_get_frag(pkt, K_FOREVER);
	net_pkt_frag_add(pkt, frag);

	net_pkt_set_iface(pkt, iface);
	net_pkt_set_ll_reserve(pkt, net_buf_headroom(frag));

	setup_ipv4_udp(pkt, src, dst, src_port, dst_port);

	ret = net_recv_data(iface, pkt);
	if (ret < 0) {
		printk("Cannot recv pkt %p, ret %d\n", pkt, ret);
		zassert_true(0, "exiting");
	}

	if (k_sem_take(&recv_lock, TIMEOUT)) {

		/**TESTPOINT: Check for failure*/
		zassert_true(expect_failure, "Timeout, packet not received");
		return true;
	}

	/* Check that the returned user data is the same as what was given
	 * as a parameter.
	 */
	if (ud != returned_ud && !expect_failure) {
		printk("IPv4 wrong user data %p returned, expected %p\n",
		       returned_ud, ud);
		zassert_true(0, "exiting");
	}

	return !fail;
}
Example #2
0
static enum net_verdict ieee802154_recv(struct net_if *iface,
					struct net_pkt *pkt)
{
	struct ieee802154_mpdu mpdu;

	if (!ieee802154_validate_frame(net_pkt_ll(pkt),
				       net_pkt_get_len(pkt), &mpdu)) {
		return NET_DROP;
	}

	if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON) {
		return ieee802154_handle_beacon(iface, &mpdu);
	}

	if (ieee802154_is_scanning(iface)) {
		return NET_DROP;
	}

	if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_MAC_COMMAND) {
		return ieee802154_handle_mac_command(iface, &mpdu);
	}

	/* At this point the frame has to be a DATA one */

	ieee802154_acknowledge(iface, &mpdu);

	net_pkt_set_ll_reserve(pkt, mpdu.payload - (void *)net_pkt_ll(pkt));
	net_buf_pull(pkt->frags, net_pkt_ll_reserve(pkt));

	set_pkt_ll_addr(net_pkt_ll_src(pkt), mpdu.mhr.fs->fc.pan_id_comp,
			mpdu.mhr.fs->fc.src_addr_mode, mpdu.mhr.src_addr);

	set_pkt_ll_addr(net_pkt_ll_dst(pkt), false,
			mpdu.mhr.fs->fc.dst_addr_mode, mpdu.mhr.dst_addr);

	if (!ieee802154_decipher_data_frame(iface, pkt, &mpdu)) {
		return NET_DROP;
	}

	pkt_hexdump(pkt, true);

	return ieee802154_manage_recv_packet(iface, pkt);
}
Example #3
0
static void nrf5_rx_thread(void *arg1, void *arg2, void *arg3)
{
	struct device *dev = (struct device *)arg1;
	struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
	struct net_buf *frag = NULL;
	enum net_verdict ack_result;
	struct net_pkt *pkt;
	u8_t pkt_len;

	ARG_UNUSED(arg2);
	ARG_UNUSED(arg3);

	while (1) {
		pkt = NULL;

		SYS_LOG_DBG("Waiting for frame");
		k_sem_take(&nrf5_radio->rx_wait, K_FOREVER);

		SYS_LOG_DBG("Frame received");

		pkt = net_pkt_get_reserve_rx(0, K_NO_WAIT);
		if (!pkt) {
			SYS_LOG_ERR("No pkt available");
			goto out;
		}

#if defined(CONFIG_IEEE802154_NRF5_RAW)
		/**
		 * Reserve 1 byte for length
		 */
		net_pkt_set_ll_reserve(pkt, 1);
#endif

		frag = net_pkt_get_frag(pkt, K_NO_WAIT);
		if (!frag) {
			SYS_LOG_ERR("No frag available");
			goto out;
		}

		net_pkt_frag_insert(pkt, frag);

		/* rx_mpdu contains length, psdu, fcs|lqi
		 * The last 2 bytes contain LQI or FCS, depending if
		 * automatic CRC handling is enabled or not, respectively.
		 */
#if defined(CONFIG_IEEE802154_NRF5_RAW)
		pkt_len = nrf5_radio->rx_psdu[0];
#else
		pkt_len = nrf5_radio->rx_psdu[0] -  NRF5_FCS_LENGTH;
#endif

		/* Skip length (first byte) and copy the payload */
		memcpy(frag->data, nrf5_radio->rx_psdu + 1, pkt_len);
		net_buf_add(frag, pkt_len);

		nrf_drv_radio802154_buffer_free(nrf5_radio->rx_psdu);

		ack_result = ieee802154_radio_handle_ack(nrf5_radio->iface,
							 pkt);
		if (ack_result == NET_OK) {
			SYS_LOG_DBG("ACK packet handled");
			goto out;
		}

		SYS_LOG_DBG("Caught a packet (%u) (LQI: %u)",
			    pkt_len, nrf5_radio->lqi);

		if (net_recv_data(nrf5_radio->iface, pkt) < 0) {
			SYS_LOG_DBG("Packet dropped by NET stack");
			goto out;
		}

		net_analyze_stack("nRF5 rx stack",
				  (unsigned char *)nrf5_radio->rx_stack,
				  CONFIG_IEEE802154_NRF5_RX_STACK_SIZE);
		continue;

out:
		if (pkt) {
			net_pkt_unref(pkt);
		}
	}
}
Example #4
0
static void test_pkt_read_write_insert(void)
{
	struct net_buf *read_frag;
	struct net_buf *temp_frag;
	struct net_pkt *pkt;
	struct net_buf *frag;
	u8_t read_data[100];
	u16_t read_pos;
	u16_t len;
	u16_t pos;

	/* Example of multi fragment read, append and skip APS's */
	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	net_pkt_set_ll_reserve(pkt, LL_RESERVE);

	frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt),
					   K_FOREVER);
	net_pkt_frag_add(pkt, frag);

	/* 1) Offset is with in input fragment.
	 * Write app data after IPv6 and UDP header. (If the offset is after
	 * IPv6 + UDP header size, api will create empty space till offset
	 * and write data).
	 */
	frag = net_pkt_write(pkt, frag, NET_IPV6UDPH_LEN, &pos, 10,
			     (u8_t *)sample_data, K_FOREVER);
	zassert_false(!frag || pos != 58, "Usecase 1: Write failed");

	read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 10,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		      "Usecase 1: Read failed");

	zassert_false(memcmp(read_data, sample_data, 10),
		      "Usecase 1: Read data mismatch");

	/* 2) Write IPv6 and UDP header at offset 0. (Empty space is created
	 * already in Usecase 1, just need to fill the header, at this point
	 * there shouldn't be any length change).
	 */
	frag = net_pkt_write(pkt, frag, 0, &pos, NET_IPV6UDPH_LEN,
			     (u8_t *)sample_data, K_FOREVER);
	zassert_false(!frag || pos != 48, "Usecase 2: Write failed");

	read_frag = net_frag_read(frag, 0, &read_pos, NET_IPV6UDPH_LEN,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		     "Usecase 2: Read failed");

	zassert_false(memcmp(read_data, sample_data, NET_IPV6UDPH_LEN),
		      "Usecase 2: Read data mismatch");

	net_pkt_unref(pkt);

	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	net_pkt_set_ll_reserve(pkt, LL_RESERVE);

	/* 3) Offset is in next to next fragment.
	 * Write app data after 2 fragments. (If the offset far away, api will
	 * create empty fragments(space) till offset and write data).
	 */
	frag = net_pkt_write(pkt, pkt->frags, 200, &pos, 10,
			     (u8_t *)sample_data + 10, K_FOREVER);
	zassert_not_null(frag, "Usecase 3: Write failed");

	read_frag = net_frag_read(frag, pos - 10, &read_pos, 10,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		     "Usecase 3: Read failed");

	zassert_false(memcmp(read_data, sample_data + 10, 10),
		      "Usecase 3: Read data mismatch");

	/* 4) Offset is in next to next fragment (overwrite).
	 * Write app data after 2 fragments. (Space is already available from
	 * Usecase 3, this scenatio doesn't create any space, it just overwrites
	 * the existing data.
	 */
	frag = net_pkt_write(pkt, pkt->frags, 190, &pos, 10,
			     (u8_t *)sample_data, K_FOREVER);
	zassert_not_null(frag, "Usecase 4: Write failed");

	read_frag = net_frag_read(frag, pos - 10, &read_pos, 20,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		      "Usecase 4: Read failed");

	zassert_false(memcmp(read_data, sample_data, 20),
		      "Usecase 4: Read data mismatch");

	net_pkt_unref(pkt);

	/* 5) Write 20 bytes in fragment which has only 10 bytes space.
	 *    API should overwrite on first 10 bytes and create extra 10 bytes
	 *    and write there.
	 */
	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	net_pkt_set_ll_reserve(pkt, LL_RESERVE);

	frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt),
					   K_FOREVER);
	net_pkt_frag_add(pkt, frag);

	/* Create 10 bytes space. */
	net_buf_add(frag, 10);

	frag = net_pkt_write(pkt, frag, 0, &pos, 20, (u8_t *)sample_data,
			     K_FOREVER);
	zassert_false(!frag && pos != 20, "Usecase 5: Write failed");

	read_frag = net_frag_read(frag, 0, &read_pos, 20, read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		     "Usecase 5: Read failed");

	zassert_false(memcmp(read_data, sample_data, 20),
		      "USecase 5: Read data mismatch");

	net_pkt_unref(pkt);

	/* 6) First fragment is full, second fragment has 10 bytes tail room,
	 *    third fragment has 5 bytes.
	 *    Write data (30 bytes) in second fragment where offset is 10 bytes
	 *    before the tailroom.
	 *    So it should overwrite 10 bytes and create space for another 10
	 *    bytes and write data. Third fragment 5 bytes overwritten and space
	 *    for 5 bytes created.
	 */
	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	net_pkt_set_ll_reserve(pkt, LL_RESERVE);

	/* First fragment make it fully occupied. */
	frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt),
					   K_FOREVER);
	net_pkt_frag_add(pkt, frag);

	len = net_buf_tailroom(frag);
	net_buf_add(frag, len);

	/* 2nd fragment last 10 bytes tailroom, rest occupied */
	frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt),
					   K_FOREVER);
	net_pkt_frag_add(pkt, frag);

	len = net_buf_tailroom(frag);
	net_buf_add(frag, len - 10);

	read_frag = temp_frag = frag;
	read_pos = frag->len - 10;

	/* 3rd fragment, only 5 bytes occupied */
	frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt),
					   K_FOREVER);
	net_pkt_frag_add(pkt, frag);
	net_buf_add(frag, 5);

	temp_frag = net_pkt_write(pkt, temp_frag, temp_frag->len - 10, &pos,
				  30, (u8_t *) sample_data, K_FOREVER);
	zassert_not_null(temp_frag, "Use case 6: Write failed");

	read_frag = net_frag_read(read_frag, read_pos, &read_pos, 30,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		      "Usecase 6: Read failed");

	zassert_false(memcmp(read_data, sample_data, 30),
		      "Usecase 6: Read data mismatch");

	net_pkt_unref(pkt);

	/* 7) Offset is with in input fragment.
	 * Write app data after IPv6 and UDP header. (If the offset is after
	 * IPv6 + UDP header size, api will create empty space till offset
	 * and write data). Insert some app data after IPv6 + UDP header
	 * before first set of app data.
	 */

	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	net_pkt_set_ll_reserve(pkt, LL_RESERVE);

	/* First fragment make it fully occupied. */
	frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt),
					   K_FOREVER);
	net_pkt_frag_add(pkt, frag);

	frag = net_pkt_write(pkt, frag, NET_IPV6UDPH_LEN, &pos, 10,
			     (u8_t *)sample_data + 10, K_FOREVER);
	zassert_false(!frag || pos != 58, "Usecase 7: Write failed");

	read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 10,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		      "Usecase 7: Read failed");

	zassert_false(memcmp(read_data, sample_data + 10, 10),
		     "Usecase 7: Read data mismatch");

	zassert_true(net_pkt_insert(pkt, frag, NET_IPV6UDPH_LEN, 10,
				    (u8_t *)sample_data, K_FOREVER),
		     "Usecase 7: Insert failed");

	read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 20,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		      "Usecase 7: Read after failed");

	zassert_false(memcmp(read_data, sample_data, 20),
		      "Usecase 7: Read data mismatch after insertion");

	/* Insert data outside input fragment length, error case. */
	zassert_false(net_pkt_insert(pkt, frag, 70, 10, (u8_t *)sample_data,
				     K_FOREVER),
		      "Usecase 7: False insert failed");

	net_pkt_unref(pkt);

	/* 8) Offset is with in input fragment.
	 * Write app data after IPv6 and UDP header. (If the offset is after
	 * IPv6 + UDP header size, api will create empty space till offset
	 * and write data). Insert some app data after IPv6 + UDP header
	 * before first set of app data. Insertion data is long which will
	 * take two fragments.
	 */
	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	net_pkt_set_ll_reserve(pkt, LL_RESERVE);

	/* First fragment make it fully occupied. */
	frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt),
					   K_FOREVER);
	net_pkt_frag_add(pkt, frag);

	frag = net_pkt_write(pkt, frag, NET_IPV6UDPH_LEN, &pos, 10,
			     (u8_t *)sample_data + 60, K_FOREVER);
	zassert_false(!frag || pos != 58, "Usecase 8: Write failed");

	read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 10,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		      "Usecase 8: Read failed");

	zassert_false(memcmp(read_data, sample_data + 60, 10),
		      "Usecase 8: Read data mismatch");

	zassert_true(net_pkt_insert(pkt, frag, NET_IPV6UDPH_LEN, 60,
				    (u8_t *)sample_data, K_FOREVER),
		     "Usecase 8: Insert failed");

	read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 70,
				 read_data);
	zassert_false(!read_frag && read_pos == 0xffff,
		      "Usecase 8: Read after failed");

	zassert_false(memcmp(read_data, sample_data, 70),
		      "Usecase 8: Read data mismatch after insertion");

	net_pkt_unref(pkt);

	DBG("test_pkt_read_write_insert passed\n");
}
Example #5
0
static struct net_pkt *build_reply_pkt(const char *name,
				       struct net_context *context,
				       struct net_pkt *pkt)
{
	struct net_pkt *reply_pkt;
	struct net_buf *frag, *tmp;
	int header_len, recv_len, reply_len;

	NET_INFO("%s received %d bytes", name,
		 net_pkt_appdatalen(pkt));

	if (net_pkt_appdatalen(pkt) == 0) {
		return NULL;
	}

	reply_pkt = net_pkt_get_tx(context, K_FOREVER);

	NET_ASSERT(reply_pkt);

	recv_len = net_pkt_get_len(pkt);

	tmp = pkt->frags;

	/* First fragment will contain IP header so move the data
	 * down in order to get rid of it.
	 */
	header_len = net_pkt_appdata(pkt) - tmp->data;

	NET_ASSERT(header_len < CONFIG_NET_BUF_DATA_SIZE);

	/* After this pull, the tmp->data points directly to application
	 * data.
	 */
	net_buf_pull(tmp, header_len);

	while (tmp) {
		frag = net_pkt_get_data(context, K_FOREVER);

		if (!net_buf_headroom(tmp)) {
			/* If there is no link layer headers in the
			 * received fragment, then get rid of that also
			 * in the sending fragment. We end up here
			 * if MTU is larger than fragment size, this
			 * is typical for ethernet.
			 */
			net_buf_push(frag, net_buf_headroom(frag));

			frag->len = 0; /* to make fragment empty */

			/* Make sure to set the reserve so that
			 * in sending side we add the link layer
			 * header if needed.
			 */
			net_pkt_set_ll_reserve(reply_pkt, 0);
		}

		NET_ASSERT(net_buf_tailroom(frag) >= tmp->len);

		memcpy(net_buf_add(frag, tmp->len), tmp->data, tmp->len);

		net_pkt_frag_add(reply_pkt, frag);

		tmp = net_pkt_frag_del(pkt, NULL, tmp);
	}

	reply_len = net_pkt_get_len(reply_pkt);

	NET_ASSERT_INFO((recv_len - header_len) == reply_len,
			"Received %d bytes, sending %d bytes",
			recv_len - header_len, reply_len);

	return reply_pkt;
}
Example #6
0
struct net_pkt *
ieee802154_create_mac_cmd_frame(struct ieee802154_context *ctx,
				enum ieee802154_cfi type,
				struct ieee802154_frame_params *params)
{
	struct ieee802154_fcf_seq *fs;
	struct net_pkt *pkt;
	struct net_buf *frag;
	u8_t *p_buf;

	pkt = net_pkt_get_reserve_tx(0, K_FOREVER);
	if (!pkt) {
		return NULL;
	}

	frag = net_pkt_get_frag(pkt, K_FOREVER);
	if (!frag) {
		goto error;
	}

	net_pkt_frag_add(pkt, frag);
	p_buf = net_pkt_ll(pkt);

	fs = generate_fcf_grounds(&p_buf,
				  type == IEEE802154_CFI_BEACON_REQUEST ?
				  false : ctx->ack_requested);

	fs->fc.frame_type = IEEE802154_FRAME_TYPE_MAC_COMMAND;
	fs->sequence = ctx->sequence;

	if (!cfi_to_fs_settings(type, fs, params)) {
		goto error;
	}

	p_buf = generate_addressing_fields(ctx, fs, params, p_buf);

	/* Let's insert the cfi */
	((struct ieee802154_command *)p_buf)->cfi = type;

	/* In MAC command, we consider ll header being the mhr.
	 * Rest will be the MAC command itself. This will proove
	 * to be easy to handle afterwards to point directly to MAC
	 * command space, in order to fill-in its content.
	 */
	net_pkt_set_ll_reserve(pkt, p_buf - net_pkt_ll(pkt));
	net_buf_pull(frag, net_pkt_ll_reserve(pkt));

	/* Thus setting the right MAC command length
	 * Now up to the caller to fill-in this space relevantly.
	 * See ieee802154_mac_command() helper.
	 */
	frag->len = mac_command_length(type);

	dbg_print_fs(fs);

	return pkt;
error:
	net_pkt_unref(pkt);

	return NULL;
}