| /* |
| * Copyright (c) 2021 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/logging/log.h> |
| LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/linker/sections.h> |
| #include <zephyr/ztest.h> |
| #include <zephyr/random/rand32.h> |
| |
| #include <fcntl.h> |
| |
| #include <zephyr/net/ethernet.h> |
| #include <zephyr/net/dummy.h> |
| #include <zephyr/net/net_if.h> |
| #include <zephyr/net/socket.h> |
| |
| struct fake_dev_context { |
| uint8_t mac_addr[sizeof(struct net_eth_addr)]; |
| struct net_if *iface; |
| }; |
| |
| static const char testing_data[] = "Tappara"; |
| |
| static int fake_dev_send(const struct device *dev, struct net_pkt *pkt) |
| { |
| struct net_pkt *recv_pkt; |
| int ret; |
| |
| ARG_UNUSED(dev); |
| ARG_UNUSED(pkt); |
| |
| /* Loopback the data back to stack: */ |
| NET_DBG("Dummy device: Loopbacking data (%d bytes) to iface %d\n", net_pkt_get_len(pkt), |
| net_if_get_by_iface(net_pkt_iface(pkt))); |
| |
| recv_pkt = net_pkt_clone(pkt, K_NO_WAIT); |
| |
| k_sleep(K_MSEC(10)); /* Let the receiver run */ |
| |
| ret = net_recv_data(net_pkt_iface(recv_pkt), recv_pkt); |
| zassert_equal(ret, 0, "Cannot receive data (%d)", ret); |
| return 0; |
| } |
| |
| static uint8_t *fake_dev_get_mac(struct fake_dev_context *ctx) |
| { |
| if (ctx->mac_addr[2] == 0x00) { |
| /* 00-00-5E-00-53-xx Documentation RFC 7042 */ |
| ctx->mac_addr[0] = 0x00; |
| ctx->mac_addr[1] = 0x00; |
| ctx->mac_addr[2] = 0x5E; |
| ctx->mac_addr[3] = 0x00; |
| ctx->mac_addr[4] = 0x53; |
| ctx->mac_addr[5] = sys_rand32_get(); |
| } |
| |
| return ctx->mac_addr; |
| } |
| |
| static void fake_dev_iface_init(struct net_if *iface) |
| { |
| const struct device *dev = net_if_get_device(iface); |
| struct fake_dev_context *ctx = dev->data; |
| uint8_t *mac = fake_dev_get_mac(ctx); |
| |
| net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET); |
| |
| ctx->iface = iface; |
| } |
| |
| int fake_dev_init(const struct device *dev) |
| { |
| ARG_UNUSED(dev); |
| |
| return 0; |
| } |
| |
| struct fake_dev_context fake_dev_context_data; |
| |
| static struct dummy_api fake_dev_if_api = { |
| .iface_api.init = fake_dev_iface_init, |
| .send = fake_dev_send, |
| }; |
| |
| #define _ETH_L2_LAYER DUMMY_L2 |
| #define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2) |
| |
| NET_DEVICE_INIT(fake_dev, "fake_dev", fake_dev_init, NULL, &fake_dev_context_data, NULL, |
| CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &fake_dev_if_api, _ETH_L2_LAYER, |
| _ETH_L2_CTX_TYPE, 127); |
| |
| static void *test_setup(void) |
| { |
| struct net_if *iface; |
| struct in_addr in4addr_my = { { { 192, 168, 0, 2 } } }; |
| struct net_if_addr *ifaddr; |
| |
| iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)); |
| zassert_not_null(iface, "Could not get dummy iface"); |
| |
| net_if_up(iface); |
| |
| ifaddr = net_if_ipv4_addr_add(iface, &in4addr_my, NET_ADDR_MANUAL, 0); |
| zassert_not_null(ifaddr, "Could not add iface address"); |
| |
| return NULL; |
| } |
| |
| ZTEST(net_sckt_packet_raw_ip, test_sckt_raw_packet_raw_ip) |
| { |
| /* A test case for testing socket combo: AF_PACKET & SOCK_RAW & IPPROTO_RAW: */ |
| struct net_if *iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)); |
| int recv_data_len, ret; |
| struct sockaddr_ll dst = { 0 }; |
| char receive_buffer[128]; |
| int sock; |
| |
| sock = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW); |
| zassert_true(sock >= 0, "Could not create a socket"); |
| |
| dst.sll_ifindex = net_if_get_by_iface(iface); |
| dst.sll_family = AF_PACKET; |
| |
| ret = bind(sock, (const struct sockaddr *)&dst, sizeof(struct sockaddr_ll)); |
| zassert_true(ret >= 0, "Could not bind the socket"); |
| |
| /* Let's send some data: */ |
| ret = sendto(sock, testing_data, ARRAY_SIZE(testing_data), 0, (const struct sockaddr *)&dst, |
| sizeof(struct sockaddr_ll)); |
| zassert_true(ret > 0, "Could not send data"); |
| |
| /* Receive the same data back: */ |
| recv_data_len = recv(sock, receive_buffer, sizeof(receive_buffer), 0); |
| zassert_true(recv_data_len == ARRAY_SIZE(testing_data), "Expected data not received"); |
| |
| NET_DBG("Received successfully data %s", receive_buffer); |
| |
| close(sock); |
| } |
| |
| ZTEST_SUITE(net_sckt_packet_raw_ip, NULL, test_setup, NULL, NULL, NULL); |