blob: 4498356cfe3c6ab51c8d080ad55ef52813558821 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Rashmica Gupta04273e92023-06-16 16:03:37 +10002#include "socket.h"
3
4#include <errno.h>
5#include <limits.h>
6#include <stddef.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <sys/socket.h>
10
11int pldm_socket_sndbuf_init(struct pldm_socket_sndbuf *ctx, int socket)
12{
13 FILE *fp;
14 long max_buf_size;
15 char line[128];
16 char *endptr;
17
18 if (socket == -1) {
19 return -1;
20 }
21 ctx->socket = socket;
22
23 fp = fopen("/proc/sys/net/core/wmem_max", "r");
Rashmica Gupta178531a2023-07-06 12:21:20 +100024 if (fp == NULL) {
25 return -1;
26 }
27
28 if (fgets(line, sizeof(line), fp) == NULL) {
Rashmica Gupta04273e92023-06-16 16:03:37 +100029 fclose(fp);
30 return -1;
31 }
32
33 errno = 0;
34 max_buf_size = strtol(line, &endptr, 10);
35 if (errno != 0 || endptr == line) {
36 fclose(fp);
37 return -1;
38 }
39
40 fclose(fp);
41
42 if (max_buf_size > INT_MAX) {
43 max_buf_size = INT_MAX;
44 }
45 ctx->max_size = (int)max_buf_size;
46
47 if (pldm_socket_sndbuf_get(ctx)) {
48 return -1;
49 }
50
51 return 0;
52}
53
54int pldm_socket_sndbuf_accomodate(struct pldm_socket_sndbuf *ctx, int msg_len)
55{
56 if (msg_len < ctx->size) {
57 return 0;
58 }
59 /* If message is bigger than the max size, don't return a failure. Set
60 * the buffer to the max size and see what happens. We don't know how
61 * much of the extra space the kernel actually uses so let it tell us if
62 * there wasn't enough space */
63 if (msg_len > ctx->max_size) {
64 msg_len = ctx->max_size;
65 }
66 if (ctx->size == ctx->max_size) {
67 return 0;
68 }
69 int rc = setsockopt(ctx->socket, SOL_SOCKET, SO_SNDBUF, &(msg_len),
70 sizeof(msg_len));
71 if (rc == -1) {
72 return -1;
73 }
74 ctx->size = msg_len;
75 return 0;
76}
77
78int pldm_socket_sndbuf_get(struct pldm_socket_sndbuf *ctx)
79{
80 /* size returned by getsockopt is the actual size of the buffer - twice
81 * the size of the value used by setsockopt. So for consistency, return
82 * half of the buffer size */
83 int buf_size;
84 socklen_t optlen = sizeof(buf_size);
85 int rc = getsockopt(ctx->socket, SOL_SOCKET, SO_SNDBUF, &(buf_size),
86 &optlen);
87 if (rc == -1) {
88 return -1;
89 }
90 ctx->size = buf_size / 2;
91 return 0;
92}