1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2022 Huawei Device Co., Ltd.
4 *
5 * Description: Demo example of NewIP udp client.
6 *
7 * Author: Yang Yanjun <yangyanjun@huawei.com>
8 *
9 * Data: 2022-09-06
10 */
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <arpa/inet.h>
15 #include <sys/socket.h>
16 #include <sys/time.h>
17
18 #define __USE_GNU
19 #include <sched.h>
20 #include <pthread.h>
21
22 #include "nip_uapi.h"
23 #include "nip_lib.h"
24 #include "newip_route.h"
25
_sendto(int cfd,struct sockaddr_nin * si_server,int pkt_num)26 int _sendto(int cfd, struct sockaddr_nin *si_server, int pkt_num)
27 {
28 char buf[BUFLEN] = {0};
29 struct timeval sys_time;
30 socklen_t slen = sizeof(struct sockaddr_nin);
31 int ret;
32
33 gettimeofday(&sys_time, NULL);
34 ret = sprintf(buf, "%ld %6ld NIP_UDP # %6d", sys_time.tv_sec, sys_time.tv_usec, pkt_num);
35 if (ret < 0) {
36 printf("sprintf failed");
37 return -1;
38 }
39 if (sendto(cfd, buf, BUFLEN, 0, (struct sockaddr *)si_server, slen) < 0) {
40 printf("client sendto fail, pkt_num=%d", pkt_num);
41 return -1;
42 }
43
44 return 0;
45 }
46
_recvfrom(int cfd,struct sockaddr_nin * si_server,int pkt_num,int * success)47 int _recvfrom(int cfd, struct sockaddr_nin *si_server, int pkt_num, int *success)
48 {
49 char buf[BUFLEN] = {0};
50 fd_set readfds;
51 int tmp;
52 struct timeval tv;
53 socklen_t slen = sizeof(struct sockaddr_nin);
54
55 FD_ZERO(&readfds);
56 FD_SET(cfd, &readfds);
57 tv.tv_sec = TIMEOUT_SEC;
58 tv.tv_usec = 0;
59 if (select(cfd + 1, &readfds, NULL, NULL, &tv) < 0) {
60 printf("client select fail, pkt_num=%d", pkt_num);
61 return -1;
62 }
63
64 if (FD_ISSET(cfd, &readfds)) {
65 int ret;
66 int no = 0;
67
68 ret = recvfrom(cfd, buf, BUFLEN, 0, (struct sockaddr *)si_server, &slen);
69 if (ret > 0) {
70 *success += 1;
71 ret = sscanf(buf, "%d %d NIP_UDP # %d", &tmp, &tmp, &no);
72 if (ret)
73 printf("Received --%s sock %d success:%6d/%6d/no=%6d\n",
74 buf, cfd, *success, pkt_num + 1, no);
75 } else {
76 printf("client recvfrom fail, ret=%d\n", ret);
77 return -1;
78 }
79 }
80
81 return 0;
82 }
83
send_recv(void * args)84 void *send_recv(void *args)
85 {
86 int success = 0;
87 int cfd = ((struct thread_args *)args)->cfd;
88 struct sockaddr_nin si_server = ((struct thread_args *)args)->si_server;
89
90 for (int i = 0; i < PKTCNT; i++) {
91 if (_sendto(cfd, &si_server, i) != 0)
92 goto END;
93
94 if (_recvfrom(cfd, &si_server, i, &success) != 0)
95 goto END;
96
97 usleep(SLEEP_US);
98 }
99
100 END: return NULL;
101 }
102
main(int argc,char ** argv)103 int main(int argc, char **argv)
104 {
105 pthread_t th;
106 int cfd;
107 struct thread_args th_args;
108 struct sockaddr_nin si_server;
109
110 cfd = socket(AF_NINET, SOCK_DGRAM, IPPROTO_UDP);
111 if (cfd < 0) {
112 perror("socket");
113 return -1;
114 }
115
116 memset((char *)&si_server, 0, sizeof(si_server));
117 si_server.sin_family = AF_NINET;
118 si_server.sin_port = htons(UDP_SERVER_PORT);
119 // 2-byte address of the server: 0xDE00
120 si_server.sin_addr.NIP_ADDR_FIELD8[INDEX_0] = 0xDE;
121 si_server.sin_addr.NIP_ADDR_FIELD8[INDEX_1] = 0x00;
122 si_server.sin_addr.bitlen = NIP_ADDR_BIT_LEN_16; // 2-byte: 16bit
123
124 th_args.si_server = si_server;
125 th_args.si_server.sin_port = htons(UDP_SERVER_PORT);
126 th_args.cfd = cfd;
127 pthread_create(&th, NULL, send_recv, &th_args);
128 /* Wait for the thread to end and synchronize operations between threads */
129 pthread_join(th, NULL);
130 close(cfd);
131 return 0;
132 }
133
134