aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-04-27 21:44:34 +0200
committerHarald Welte <laforge@osmocom.org>2021-04-27 21:53:32 +0200
commitce53e03dc9ee231103c2ac1d3f2cb52515bbce0e (patch)
treefd58a201bef89dd7c3882ee97cd56f10f0010d7d
parent069967be86bc8f341d23e45fa8c8a967f6d22eea (diff)
socket: Introduce osmo_sock_set_dscp() to set socket DSCP value
At least on Linux, sockets have a IP_TOS socket option that can be configured to set the TOS. However, TOS (of RFC791) was replaced by the DSCP (of RFC2474) in 1998. As the DCSP bits are only the upper 6 bits of the TOS bits, let's introduce a helper to get, mask and set the DSCP values in the TOS bits. Related: OS#5136, SYS#5427 Change-Id: Ia4ba389a5b7e3e9d5f17a742a900d6fd68c08e40
-rw-r--r--include/osmocom/core/socket.h2
-rw-r--r--src/socket.c26
2 files changed, 28 insertions, 0 deletions
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index 0443c06e..92cd202b 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -122,5 +122,7 @@ const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *sockaddr);
char *osmo_sockaddr_to_str_buf(char *buf, size_t buf_len,
const struct osmo_sockaddr *sockaddr);
+int osmo_sock_set_dscp(int fd, uint8_t dscp);
+
#endif /* (!EMBEDDED) */
/*! @} */
diff --git a/src/socket.c b/src/socket.c
index 229f72e3..095dee6b 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1776,6 +1776,32 @@ char *osmo_sockaddr_to_str_buf(char *buf, size_t buf_len,
return buf;
}
+/*! Set the DSCP (differentiated services code point) of a socket.
+ * \param[in] dscp DSCP value in range 0..63
+ * \returns 0 on success; negative on error. */
+int osmo_sock_set_dscp(int fd, uint8_t dscp)
+{
+ uint8_t tos;
+ socklen_t tos_len = sizeof(tos);
+ int rc;
+
+ /* DSCP is a 6-bit value stored in the upper 6 bits of the 8-bit TOS */
+ if (dscp > 63)
+ return -EINVAL;
+
+ /* read the original value */
+ rc = getsockopt(fd, IPPROTO_IP, IP_TOS, &tos, &tos_len);
+ if (rc < 0)
+ return rc;
+
+ /* mask-in the DSCP into the upper 6 bits */
+ tos &= 0x03;
+ tos |= dscp << 2;
+
+ /* and write it back to the kernel */
+ return setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
+}
+
#endif /* HAVE_SYS_SOCKET_H */