aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2024-03-16 18:15:47 +0100
committerHarald Welte <laforge@osmocom.org>2024-03-16 21:08:22 +0100
commit3c133dc3863415ca86c3e453e664667aea44cf13 (patch)
tree9cba5e597096a9f118e79647ac00e533e5460e4c
parent3af73977ddd88a43da3457057152a34246d2a967 (diff)
osmo-bts-virtual: Port over to osmo_io
osmo_io permits us to use the io_uring backend, which should significantly speed up the many small read/writes we're doing on virt-um. Change-Id: Icfe42da00fd446c38090055e2baa5d5e0ae5b70c
-rw-r--r--src/osmo-bts-virtual/osmo_mcast_sock.c112
-rw-r--r--src/osmo-bts-virtual/osmo_mcast_sock.h28
-rw-r--r--src/osmo-bts-virtual/scheduler_virtbts.c2
-rw-r--r--src/osmo-bts-virtual/virtual_um.c49
4 files changed, 100 insertions, 91 deletions
diff --git a/src/osmo-bts-virtual/osmo_mcast_sock.c b/src/osmo-bts-virtual/osmo_mcast_sock.c
index 3e565142..c802e02d 100644
--- a/src/osmo-bts-virtual/osmo_mcast_sock.c
+++ b/src/osmo-bts-virtual/osmo_mcast_sock.c
@@ -3,6 +3,7 @@
#include <netdb.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/select.h>
+#include <osmocom/core/osmo_io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -10,102 +11,133 @@
#include <unistd.h>
#include "osmo_mcast_sock.h"
+static void noop_write_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg)
+{
+ /* nothing */
+}
+
+static const struct osmo_io_ops srv_ioops = {
+ /* no read call-back as we don't read from the socket */
+ /* libosmcoore before change-id I0c071a29e508884bac331ada5e510bbfcf440bbf requires write call-back
+ * even if we don't care about it */
+ .write_cb = noop_write_cb,
+};
+
/* server socket is what we use for transmission. It is not subscribed
* to a multicast group or locally bound, but it is just a normal UDP
* socket that's connected to the remote mcast group + port */
-int mcast_server_sock_setup(struct osmo_fd *ofd, const char* tx_mcast_group,
- uint16_t tx_mcast_port, bool loopback)
+static struct osmo_io_fd *
+mcast_server_sock_setup(void *ctx, const char *tx_mcast_group, uint16_t tx_mcast_port, bool loopback)
{
- int rc;
+ int rc, fd;
unsigned int flags = OSMO_SOCK_F_CONNECT | OSMO_SOCK_F_UDP_REUSEADDR;
+ struct osmo_io_fd *iofd;
if (!loopback)
flags |= OSMO_SOCK_F_NO_MCAST_LOOP;
/* setup mcast server socket */
- rc = osmo_sock_init_ofd(ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
- tx_mcast_group, tx_mcast_port, flags);
+ rc = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP, tx_mcast_group, tx_mcast_port, flags);
if (rc < 0) {
perror("Failed to create Multicast Server Socket");
- return rc;
+ return NULL;
}
+ fd = rc;
- return 0;
+ iofd = osmo_iofd_setup(ctx, rc, "mcast_server_sock", OSMO_IO_FD_MODE_READ_WRITE, &srv_ioops, NULL);
+ if (!iofd) {
+ close(fd);
+ return NULL;
+ }
+
+ osmo_iofd_register(iofd, -1);
+ return iofd;
+}
+
+static void mcast_sock_read_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg)
+{
+ struct mcast_bidir_sock *bidir_sock = osmo_iofd_get_data(iofd);
+ bidir_sock->read_cb(res, msg, bidir_sock->data);
}
+const struct osmo_io_ops clnt_ioops = {
+ .read_cb = mcast_sock_read_cb,
+ /* no write call-back as we don't write to the socket */
+};
+
/* the client socket is what we use for reception. It is a UDP socket
* that's bound to the GSMTAP UDP port and subscribed to the respective
* multicast group */
-int mcast_client_sock_setup(struct osmo_fd *ofd, const char *mcast_group, uint16_t mcast_port,
- int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what),
- void *osmo_fd_data)
+static struct osmo_io_fd *
+mcast_client_sock_setup(void *ctx, const char *mcast_group, uint16_t mcast_port,
+ void (*read_cb)(int rc, struct msgb *msg, void *data))
{
- int rc;
+ int rc, fd;
unsigned int flags = OSMO_SOCK_F_BIND | OSMO_SOCK_F_NO_MCAST_ALL | OSMO_SOCK_F_UDP_REUSEADDR;
-
- osmo_fd_setup(ofd, -1, OSMO_FD_READ, fd_rx_cb, osmo_fd_data, 0);
+ struct osmo_io_fd *iofd;
/* Create mcast client socket */
- rc = osmo_sock_init_ofd(ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
- NULL, mcast_port, flags);
+ rc = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, mcast_port, flags);
if (rc < 0) {
perror("Could not create mcast client socket");
- return rc;
+ return NULL;
}
+ fd = rc;
/* Configure and join the multicast group */
- rc = osmo_sock_mcast_subscribe(ofd->fd, mcast_group);
+ rc = osmo_sock_mcast_subscribe(fd, mcast_group);
if (rc < 0) {
perror("Failed to join to mcast goup");
- osmo_fd_close(ofd);
- return rc;
+ close(fd);
+ return NULL;
+ }
+
+ iofd = osmo_iofd_setup(ctx, fd, "mcast_client_sock", OSMO_IO_FD_MODE_READ_WRITE, &clnt_ioops, ctx);
+ if (!iofd) {
+ close(fd);
+ return NULL;
}
- return 0;
+ osmo_iofd_register(iofd, -1);
+ return iofd;
}
struct mcast_bidir_sock *
mcast_bidir_sock_setup(void *ctx, const char *tx_mcast_group, uint16_t tx_mcast_port,
const char *rx_mcast_group, uint16_t rx_mcast_port, bool loopback,
- int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what),
- void *osmo_fd_data)
+ void (*read_cb)(int rc, struct msgb *msg, void *data),
+ void *data)
{
struct mcast_bidir_sock *bidir_sock = talloc(ctx, struct mcast_bidir_sock);
- int rc;
if (!bidir_sock)
return NULL;
- rc = mcast_client_sock_setup(&bidir_sock->rx_ofd, rx_mcast_group, rx_mcast_port,
- fd_rx_cb, osmo_fd_data);
- if (rc < 0) {
+ bidir_sock->read_cb = read_cb;
+ bidir_sock->data = data;
+
+ bidir_sock->rx_iofd = mcast_client_sock_setup(bidir_sock, rx_mcast_group, rx_mcast_port, read_cb);
+ if (!bidir_sock->rx_iofd) {
talloc_free(bidir_sock);
return NULL;
}
- rc = mcast_server_sock_setup(&bidir_sock->tx_ofd, tx_mcast_group, tx_mcast_port, loopback);
- if (rc < 0) {
- osmo_fd_close(&bidir_sock->rx_ofd);
+ bidir_sock->tx_iofd = mcast_server_sock_setup(bidir_sock, tx_mcast_group, tx_mcast_port, loopback);
+ if (!bidir_sock->tx_iofd) {
+ osmo_iofd_free(bidir_sock->rx_iofd);
talloc_free(bidir_sock);
return NULL;
}
return bidir_sock;
-
-}
-
-int mcast_bidir_sock_tx(struct mcast_bidir_sock *bidir_sock, const uint8_t *data,
- unsigned int data_len)
-{
- return send(bidir_sock->tx_ofd.fd, data, data_len, 0);
}
-int mcast_bidir_sock_rx(struct mcast_bidir_sock *bidir_sock, uint8_t *buf, unsigned int buf_len)
+int mcast_bidir_sock_tx_msg(struct mcast_bidir_sock *bidir_sock, struct msgb *msg)
{
- return recv(bidir_sock->rx_ofd.fd, buf, buf_len, 0);
+ return osmo_iofd_write_msgb(bidir_sock->tx_iofd, msg);
}
void mcast_bidir_sock_close(struct mcast_bidir_sock *bidir_sock)
{
- osmo_fd_close(&bidir_sock->tx_ofd);
- osmo_fd_close(&bidir_sock->rx_ofd);
+ osmo_iofd_free(bidir_sock->tx_iofd);
+ osmo_iofd_free(bidir_sock->rx_iofd);
talloc_free(bidir_sock);
}
diff --git a/src/osmo-bts-virtual/osmo_mcast_sock.h b/src/osmo-bts-virtual/osmo_mcast_sock.h
index aa2013c6..5f68415b 100644
--- a/src/osmo-bts-virtual/osmo_mcast_sock.h
+++ b/src/osmo-bts-virtual/osmo_mcast_sock.h
@@ -4,26 +4,20 @@
#include <stdint.h>
#include <netinet/in.h>
#include <osmocom/core/select.h>
+#include <osmocom/core/osmo_io.h>
struct mcast_bidir_sock {
- struct osmo_fd tx_ofd;
- struct osmo_fd rx_ofd;
+ struct osmo_io_fd *tx_iofd;
+ struct osmo_io_fd *rx_iofd;
+ void (*read_cb)(int rc, struct msgb *msg, void *data);
+ void *data;
};
-struct mcast_bidir_sock *mcast_bidir_sock_setup(void *ctx,
- const char *tx_mcast_group, uint16_t tx_mcast_port,
- const char *rx_mcast_group, uint16_t rx_mcast_port, bool loopback,
- int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what),
- void *osmo_fd_data);
+struct mcast_bidir_sock *
+mcast_bidir_sock_setup(void *ctx, const char *tx_mcast_group, uint16_t tx_mcast_port,
+ const char *rx_mcast_group, uint16_t rx_mcast_port, bool loopback,
+ void (*read_cb)(int rc, struct msgb *msg, void *data),
+ void *data);
-int mcast_server_sock_setup(struct osmo_fd *ofd, const char *tx_mcast_group,
- uint16_t tx_mcast_port, bool loopback);
-
-int mcast_client_sock_setup(struct osmo_fd *ofd, const char *mcast_group, uint16_t mcast_port,
- int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what),
- void *osmo_fd_data);
-
-int mcast_bidir_sock_tx(struct mcast_bidir_sock *bidir_sock, const uint8_t *data, unsigned int data_len);
-int mcast_bidir_sock_rx(struct mcast_bidir_sock *bidir_sock, uint8_t *buf, unsigned int buf_len);
+int mcast_bidir_sock_tx_msg(struct mcast_bidir_sock *bidir_sock, struct msgb *msg);
void mcast_bidir_sock_close(struct mcast_bidir_sock* bidir_sock);
-
diff --git a/src/osmo-bts-virtual/scheduler_virtbts.c b/src/osmo-bts-virtual/scheduler_virtbts.c
index 1bcec063..87596a79 100644
--- a/src/osmo-bts-virtual/scheduler_virtbts.c
+++ b/src/osmo-bts-virtual/scheduler_virtbts.c
@@ -102,8 +102,6 @@ static void _tx_to_virt_um(struct l1sched_ts *l1ts,
if (rc < 0)
LOGL1SB(DL1P, LOGL_ERROR, l1ts, br,
"GSMTAP msg could not send to virtual Um: %s\n", strerror(-rc));
- else if (rc == 0)
- bts_shutdown(trx->bts, "VirtPHY write socket died\n");
else
LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br,
"Sending GSMTAP message to virtual Um\n");
diff --git a/src/osmo-bts-virtual/virtual_um.c b/src/osmo-bts-virtual/virtual_um.c
index 44747fa6..711e75d3 100644
--- a/src/osmo-bts-virtual/virtual_um.c
+++ b/src/osmo-bts-virtual/virtual_um.c
@@ -32,33 +32,15 @@
#include <errno.h>
/**
- * Virtual UM interface file descriptor callback.
- * Should be called by select.c when the fd is ready for reading.
+ * Virtual UM interface file descriptor read callback.
*/
-static int virt_um_fd_cb(struct osmo_fd *ofd, unsigned int what)
+static void virt_um_read_cb(int rc, struct msgb *msg, void *data)
{
- struct virt_um_inst *vui = ofd->data;
+ struct virt_um_inst *vui = data;
+ msg->l1h = msg->data;
- if (what & OSMO_FD_READ) {
- struct msgb *msg = msgb_alloc(VIRT_UM_MSGB_SIZE, "Virtual UM Rx");
- int rc;
-
- /* read message from fd into message buffer */
- rc = mcast_bidir_sock_rx(vui->mcast_sock, msgb_data(msg), msgb_tailroom(msg));
- if (rc > 0) {
- msgb_put(msg, rc);
- msg->l1h = msgb_data(msg);
- /* call the l1 callback function for a received msg */
- vui->recv_cb(vui, msg);
- } else if (rc == 0) {
- vui->recv_cb(vui, NULL);
- osmo_fd_close(ofd);
- } else
- perror("Read from multicast socket");
-
- }
-
- return 0;
+ /* call the l1 callback function for a received msg */
+ vui->recv_cb(vui, msg);
}
struct virt_um_inst *virt_um_init(void *ctx, char *tx_mcast_group, uint16_t tx_mcast_port,
@@ -69,7 +51,7 @@ struct virt_um_inst *virt_um_init(void *ctx, char *tx_mcast_group, uint16_t tx_m
int rc;
vui->mcast_sock = mcast_bidir_sock_setup(ctx, tx_mcast_group, tx_mcast_port,
- rx_mcast_group, rx_mcast_port, 1, virt_um_fd_cb, vui);
+ rx_mcast_group, rx_mcast_port, 1, virt_um_read_cb, vui);
if (!vui->mcast_sock) {
perror("Unable to create VirtualUm multicast socket");
talloc_free(vui);
@@ -79,7 +61,8 @@ struct virt_um_inst *virt_um_init(void *ctx, char *tx_mcast_group, uint16_t tx_m
/* -1 means default, i.e. no TTL explicitly configured in VTY */
if (ttl >= 0) {
- rc = osmo_sock_mcast_ttl_set(vui->mcast_sock->tx_ofd.fd, ttl);
+ int txfd = osmo_iofd_get_fd(vui->mcast_sock->tx_iofd);
+ rc = osmo_sock_mcast_ttl_set(txfd, ttl);
if (rc < 0) {
perror("Cannot set TTL of Virtual Um transmit socket");
goto out_close;
@@ -87,12 +70,14 @@ struct virt_um_inst *virt_um_init(void *ctx, char *tx_mcast_group, uint16_t tx_m
}
if (dev_name) {
- rc = osmo_sock_mcast_iface_set(vui->mcast_sock->tx_ofd.fd, dev_name);
+ int txfd = osmo_iofd_get_fd(vui->mcast_sock->tx_iofd);
+ rc = osmo_sock_mcast_iface_set(txfd, dev_name);
if (rc < 0) {
perror("Cannot bind multicast tx to given device");
goto out_close;
}
- rc = osmo_sock_mcast_iface_set(vui->mcast_sock->rx_ofd.fd, dev_name);
+ int rxfd = osmo_iofd_get_fd(vui->mcast_sock->rx_iofd);
+ rc = osmo_sock_mcast_iface_set(rxfd, dev_name);
if (rc < 0) {
perror("Cannot bind multicast rx to given device");
goto out_close;
@@ -120,11 +105,11 @@ int virt_um_write_msg(struct virt_um_inst *vui, struct msgb *msg)
{
int rc;
- rc = mcast_bidir_sock_tx(vui->mcast_sock, msgb_data(msg),
- msgb_length(msg));
- if (rc < 0)
+ rc = mcast_bidir_sock_tx_msg(vui->mcast_sock, msg);
+ if (rc < 0) {
+ msgb_free(msg);
rc = -errno;
- msgb_free(msg);
+ }
return rc;
}