RTE OSAdapter POSIX 0.1.0 build 41b3eb3
POSIX/Linux OAL OSAdapter for Platform_RTE
Loading...
Searching...
No Matches
rte_posix_osadapter_socket.c
Go to the documentation of this file.
1#define _POSIX_C_SOURCE 200809L
2
9
12
13#include <arpa/inet.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <netinet/in.h>
17#include <poll.h>
18#include <string.h>
19#include <sys/socket.h>
20#include <unistd.h>
21
22static rte_status_t posix_socket_set_nonblocking(rte_os_socket_handle_t handle, bool nonblocking);
23
24/* REQ-OAL-SOCKET-001 (Platform_RTE SRS 2.13): OK only with a non-blocking socket; *out_handle unwritten on error. */
25static rte_status_t posix_socket_open(rte_os_socket_type_t type, rte_os_socket_handle_t *out_handle)
26{
27 int domain = AF_INET;
28 int sock_type;
29 int fd;
30 int reuse = 1;
31
32 if (out_handle == NULL)
33 {
34 return RTE_STATUS_INVALID_PARAM;
35 }
36
37 if (type == RTE_OS_SOCKET_TYPE_UDP)
38 {
39 sock_type = SOCK_DGRAM;
40 }
41 else if (type == RTE_OS_SOCKET_TYPE_TCP)
42 {
43 sock_type = SOCK_STREAM;
44 }
45 else
46 {
47 return RTE_STATUS_NOT_SUPPORTED;
48 }
49
50 fd = socket(domain, sock_type, 0);
51 if (fd < 0)
52 {
53 return RTE_STATUS_INTERNAL_ERROR;
54 }
55
56 (void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, (socklen_t)sizeof(reuse));
57#ifdef SO_REUSEPORT
58 (void)setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reuse, (socklen_t)sizeof(reuse));
59#endif
60
61 /* OSA rule R5: every socket is non-blocking from creation (checked F_GETFL + F_SETFL; set_nonblocking(false)
62 * can still switch it back). On failure the fd is closed and *out_handle stays unwritten. */
63 if (posix_socket_set_nonblocking((rte_os_socket_handle_t)fd, true) != RTE_STATUS_OK)
64 {
65 (void)close(fd);
66 return RTE_STATUS_INTERNAL_ERROR;
67 }
68
69 *out_handle = (rte_os_socket_handle_t)fd;
70 return RTE_STATUS_OK;
71}
72
73static rte_status_t posix_socket_bind(rte_os_socket_handle_t handle, const char *host, uint16_t port)
74{
75 int fd = (int)handle;
76 struct sockaddr_in addr;
77
78 if (fd < 0)
79 {
80 return RTE_STATUS_INVALID_PARAM;
81 }
82
83 memset(&addr, 0, sizeof(addr));
84 addr.sin_family = AF_INET;
85 addr.sin_port = htons(port);
86
87 if ((host == NULL) || (host[0] == '\0'))
88 {
89 addr.sin_addr.s_addr = INADDR_ANY;
90 }
91 else
92 {
93 if (inet_pton(AF_INET, host, &addr.sin_addr) != 1)
94 {
95 return RTE_STATUS_INVALID_PARAM;
96 }
97 }
98
99 if (bind(fd, (const struct sockaddr *)(const void *)&addr, (socklen_t)sizeof(addr)) != 0)
100 {
101 return RTE_STATUS_INTERNAL_ERROR;
102 }
103
104 return RTE_STATUS_OK;
105}
106
107static rte_status_t posix_socket_connect(rte_os_socket_handle_t handle, const char *host, uint16_t port)
108{
109 int fd = (int)handle;
110 struct sockaddr_in addr;
111
112 if ((fd < 0) || (host == NULL))
113 {
114 return RTE_STATUS_INVALID_PARAM;
115 }
116
117 memset(&addr, 0, sizeof(addr));
118 addr.sin_family = AF_INET;
119 addr.sin_port = htons(port);
120
121 if (inet_pton(AF_INET, host, &addr.sin_addr) != 1)
122 {
123 return RTE_STATUS_INVALID_PARAM;
124 }
125
126 if (connect(fd, (const struct sockaddr *)(const void *)&addr, (socklen_t)sizeof(addr)) != 0)
127 {
128 if (errno == EINPROGRESS)
129 {
130 return RTE_STATUS_OK;
131 }
132 return RTE_STATUS_INTERNAL_ERROR;
133 }
134
135 return RTE_STATUS_OK;
136}
137
138static rte_status_t posix_socket_send(rte_os_socket_handle_t handle, const void *buf,
139 size_t len, size_t *out_sent)
140{
141 int fd = (int)handle;
142 ssize_t rc;
143
144 if ((fd < 0) || (buf == NULL))
145 {
146 return RTE_STATUS_INVALID_PARAM;
147 }
148
149 rc = send(fd, buf, len, 0);
150 if (rc < 0)
151 {
152 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
153 {
154 return RTE_STATUS_TIMEOUT;
155 }
156 return RTE_STATUS_INTERNAL_ERROR;
157 }
158
159 if (out_sent != NULL)
160 {
161 *out_sent = (size_t)rc;
162 }
163 return RTE_STATUS_OK;
164}
165
166static rte_status_t posix_socket_sendto(rte_os_socket_handle_t handle, const void *buf,
167 size_t len, const char *host, uint16_t port,
168 size_t *out_sent)
169{
170 int fd = (int)handle;
171 struct sockaddr_in addr;
172 ssize_t rc;
173
174 if ((fd < 0) || (buf == NULL) || (host == NULL))
175 {
176 return RTE_STATUS_INVALID_PARAM;
177 }
178
179 memset(&addr, 0, sizeof(addr));
180 addr.sin_family = AF_INET;
181 addr.sin_port = htons(port);
182
183 if (inet_pton(AF_INET, host, &addr.sin_addr) != 1)
184 {
185 return RTE_STATUS_INVALID_PARAM;
186 }
187
188 rc = sendto(fd, buf, len, 0, (const struct sockaddr *)(const void *)&addr, (socklen_t)sizeof(addr));
189 if (rc < 0)
190 {
191 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
192 {
193 return RTE_STATUS_TIMEOUT;
194 }
195 return RTE_STATUS_INTERNAL_ERROR;
196 }
197
198 if (out_sent != NULL)
199 {
200 *out_sent = (size_t)rc;
201 }
202 return RTE_STATUS_OK;
203}
204
205static rte_status_t posix_socket_recv(rte_os_socket_handle_t handle, void *buf,
206 size_t len, size_t *out_recv)
207{
208 int fd = (int)handle;
209 ssize_t rc;
210
211 if ((fd < 0) || (buf == NULL) || (out_recv == NULL))
212 {
213 return RTE_STATUS_INVALID_PARAM;
214 }
215
216 rc = recv(fd, buf, len, 0);
217 if (rc < 0)
218 {
219 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
220 {
221 return RTE_STATUS_TIMEOUT;
222 }
223 return RTE_STATUS_INTERNAL_ERROR;
224 }
225
226 *out_recv = (size_t)rc;
227 return RTE_STATUS_OK;
228}
229
230static rte_status_t posix_socket_recvfrom(rte_os_socket_handle_t handle, void *buf,
231 size_t len, char *out_host, size_t host_len,
232 uint16_t *out_port, size_t *out_recv)
233{
234 int fd = (int)handle;
235 struct sockaddr_in addr;
236 socklen_t addr_len = (socklen_t)sizeof(addr);
237 ssize_t rc;
238
239 if ((fd < 0) || (buf == NULL) || (out_recv == NULL))
240 {
241 return RTE_STATUS_INVALID_PARAM;
242 }
243
244 memset(&addr, 0, sizeof(addr));
245 rc = recvfrom(fd, buf, len, 0, (struct sockaddr *)(void *)&addr, &addr_len);
246 if (rc < 0)
247 {
248 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
249 {
250 return RTE_STATUS_TIMEOUT;
251 }
252 return RTE_STATUS_INTERNAL_ERROR;
253 }
254
255 if (out_host != NULL && host_len > 0U)
256 {
257 (void)inet_ntop(AF_INET, &addr.sin_addr, out_host, (socklen_t)host_len);
258 }
259 if (out_port != NULL)
260 {
261 *out_port = ntohs(addr.sin_port);
262 }
263
264 *out_recv = (size_t)rc;
265 return RTE_STATUS_OK;
266}
267
268static rte_status_t posix_socket_poll(rte_os_socket_handle_t handle, uint32_t events,
269 rte_duration_ms_t timeout_ms, uint32_t *out_revents)
270{
271 int fd = (int)handle;
272 struct pollfd pfd;
273 int rc;
274
275 if ((fd < 0) || (out_revents == NULL))
276 {
277 return RTE_STATUS_INVALID_PARAM;
278 }
279
280 memset(&pfd, 0, sizeof(pfd));
281 pfd.fd = fd;
282 if ((events & RTE_OS_SOCKET_EVENT_READ) != 0U)
283 {
284 pfd.events |= POLLIN;
285 }
286 if ((events & RTE_OS_SOCKET_EVENT_WRITE) != 0U)
287 {
288 pfd.events |= POLLOUT;
289 }
290
291 rc = poll(&pfd, 1, posix_poll_timeout_ms(timeout_ms));
292 if (rc < 0)
293 {
294 if (errno == EINTR)
295 {
296 return RTE_STATUS_TIMEOUT;
297 }
298 return RTE_STATUS_INTERNAL_ERROR;
299 }
300 if (rc == 0)
301 {
302 *out_revents = 0U;
303 return RTE_STATUS_TIMEOUT;
304 }
305
306 *out_revents = 0U;
307 if ((pfd.revents & POLLIN) != 0)
308 {
309 *out_revents |= RTE_OS_SOCKET_EVENT_READ;
310 }
311 if ((pfd.revents & POLLOUT) != 0)
312 {
313 *out_revents |= RTE_OS_SOCKET_EVENT_WRITE;
314 }
315 if ((pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) != 0)
316 {
317 *out_revents |= RTE_OS_SOCKET_EVENT_ERROR;
318 }
319
320 return RTE_STATUS_OK;
321}
322
323static rte_status_t posix_socket_set_nonblocking(rte_os_socket_handle_t handle, bool nonblocking)
324{
325 int fd = (int)handle;
326 int flags;
327
328 if (fd < 0)
329 {
330 return RTE_STATUS_INVALID_PARAM;
331 }
332
333 flags = fcntl(fd, F_GETFL, 0);
334 if (flags < 0)
335 {
336 return RTE_STATUS_INTERNAL_ERROR;
337 }
338
339 flags = nonblocking ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK);
340 if (fcntl(fd, F_SETFL, flags) < 0)
341 {
342 return RTE_STATUS_INTERNAL_ERROR;
343 }
344
345 return RTE_STATUS_OK;
346}
347
348static rte_status_t posix_socket_close(rte_os_socket_handle_t handle)
349{
350 int fd = (int)handle;
351 if (fd >= 0)
352 {
353 (void)close(fd);
354 }
355 return RTE_STATUS_OK;
356}
357
358static const rte_os_socket_ops_t s_posix_socket_ops = {
359 posix_socket_open,
360 posix_socket_bind,
361 posix_socket_connect,
362 posix_socket_send,
363 posix_socket_sendto,
364 posix_socket_recv,
365 posix_socket_recvfrom,
366 posix_socket_poll,
367 posix_socket_set_nonblocking,
368 posix_socket_close
369};
370
371const rte_os_socket_ops_t *rte_posix_osadapter_socket_ops(void)
372{
373 return &s_posix_socket_ops;
374}
Real POSIX/Linux OSAdapter for every OAL service (ADR-018).
const rte_os_socket_ops_t * rte_posix_osadapter_socket_ops(void)
The POSIX raw OS socket operations vtable (UDP and TCP).
Private helpers: millisecond waits for poll()'s int timeout argument.