| /* |
| * Copyright (c) 2019 Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <logging/log.h> |
| LOG_MODULE_REGISTER(net_pkt_sock_sample, LOG_LEVEL_DBG); |
| |
| #include <zephyr.h> |
| #include <errno.h> |
| #include <stdio.h> |
| |
| #include <net/socket.h> |
| #include <net/ethernet.h> |
| |
| #define STACK_SIZE 1024 |
| #define THREAD_PRIORITY K_PRIO_COOP(8) |
| #define RECV_BUFFER_SIZE 1280 |
| #define RAW_WAIT K_SECONDS(5) |
| |
| static struct packet_data packet; |
| |
| static struct k_sem quit_lock; |
| |
| struct packet_data { |
| int sock; |
| char recv_buffer[RECV_BUFFER_SIZE]; |
| struct k_delayed_work send; |
| }; |
| |
| static void process_packet(void); |
| static void send_packet(void); |
| |
| K_THREAD_DEFINE(packet_thread_id, STACK_SIZE, |
| process_packet, NULL, NULL, NULL, |
| THREAD_PRIORITY, 0, K_FOREVER); |
| |
| /* Generated by http://www.lipsum.com/ |
| * 2 paragraphs, 179 words, 1160 bytes of Lorem Ipsum |
| */ |
| const char lorem_ipsum[] = |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque " |
| "sodales lorem lorem, sed congue enim vehicula a. Sed finibus diam sed " |
| "odio ultrices pharetra. Nullam dictum arcu ultricies turpis congue, " |
| "vel venenatis turpis venenatis. Nam tempus arcu eros, ac congue libero " |
| "tristique congue. Proin velit lectus, euismod sit amet quam in, " |
| "maximus condimentum urna. Cras vel erat luctus, mattis orci ut, varius " |
| "urna. Nam eu lobortis velit." |
| "\n" |
| "Nullam sit amet diam vel odio sodales cursus vehicula eu arcu. Proin " |
| "fringilla, enim nec consectetur mollis, lorem orci interdum nisi, " |
| "vitae suscipit nisi mauris eu mi. Proin diam enim, mollis ac rhoncus " |
| "vitae, placerat et eros. Suspendisse convallis, ipsum nec rhoncus " |
| "aliquam, ex augue ultrices nisl, id aliquet mi diam quis ante. " |
| "Pellentesque venenatis ornare ultrices. Quisque et porttitor lectus. " |
| "Ut venenatis nunc et urna imperdiet porttitor non laoreet massa. Donec " |
| "eleifend eros in mi sagittis egestas. Sed et mi nunc. Nunc vulputate, " |
| "mauris non ullamcorper viverra, lorem nulla vulputate diam, et congue " |
| "dui velit non erat. Duis interdum leo et ipsum tempor consequat. In " |
| "faucibus enim quis purus vulputate nullam." |
| "\n"; |
| |
| static void quit(void) |
| { |
| k_sem_give(&quit_lock); |
| } |
| |
| static int start_packet_socket(void) |
| { |
| struct sockaddr_ll dst; |
| int ret; |
| |
| packet.sock = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL); |
| if (packet.sock < 0) { |
| LOG_ERR("Failed to create RAW socket : %d", errno); |
| return -errno; |
| } |
| |
| dst.sll_ifindex = net_if_get_by_iface(net_if_get_default()); |
| dst.sll_family = AF_PACKET; |
| |
| ret = bind(packet.sock, (const struct sockaddr *)&dst, |
| sizeof(struct sockaddr_ll)); |
| if (ret < 0) { |
| LOG_ERR("Failed to bind packet socket : %d", errno); |
| return -errno; |
| } |
| |
| return 0; |
| } |
| |
| static void wait_send(struct k_work *work) |
| { |
| /* Send a new packet at this point */ |
| send_packet(); |
| } |
| |
| static void send_packet(void) |
| { |
| struct sockaddr_ll dst; |
| u8_t send = 100U; |
| int ret; |
| |
| dst.sll_ifindex = net_if_get_by_iface(net_if_get_default()); |
| |
| /* Sending dummy data */ |
| ret = sendto(packet.sock, lorem_ipsum, send, 0, |
| (const struct sockaddr *)&dst, |
| sizeof(struct sockaddr_ll)); |
| if (ret < 0) { |
| LOG_ERR("Failed to send, errno %d", errno); |
| } else { |
| LOG_DBG("Sent %d bytes", send); |
| } |
| |
| k_delayed_work_submit(&packet.send, RAW_WAIT); |
| } |
| |
| static int process_packet_socket(void) |
| { |
| int ret = 0; |
| int received; |
| |
| LOG_INF("Waiting for packets ..."); |
| |
| send_packet(); |
| |
| do { |
| received = recv(packet.sock, packet.recv_buffer, |
| sizeof(packet.recv_buffer), 0); |
| |
| if (received < 0) { |
| LOG_ERR("RAW : recv error %d", errno); |
| ret = -errno; |
| break; |
| } |
| |
| LOG_DBG("Received %d bytes", received); |
| |
| } while (true); |
| |
| return ret; |
| } |
| |
| static void process_packet(void) |
| { |
| int ret; |
| |
| ret = start_packet_socket(); |
| if (ret < 0) { |
| quit(); |
| return; |
| } |
| |
| while (ret == 0) { |
| ret = process_packet_socket(); |
| if (ret < 0) { |
| quit(); |
| return; |
| } |
| } |
| } |
| |
| void main(void) |
| { |
| k_sem_init(&quit_lock, 0, UINT_MAX); |
| k_delayed_work_init(&packet.send, wait_send); |
| |
| LOG_INF("Packet socket sample is running"); |
| |
| k_thread_start(packet_thread_id); |
| |
| k_sem_take(&quit_lock, K_FOREVER); |
| |
| LOG_INF("Stopping..."); |
| |
| k_thread_abort(packet_thread_id); |
| |
| k_delayed_work_cancel(&packet.send); |
| |
| if (packet.sock > 0) { |
| (void)close(packet.sock); |
| } |
| } |