aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-virtual/virtual_um.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bts-virtual/virtual_um.c')
-rw-r--r--src/osmo-bts-virtual/virtual_um.c176
1 files changed, 34 insertions, 142 deletions
diff --git a/src/osmo-bts-virtual/virtual_um.c b/src/osmo-bts-virtual/virtual_um.c
index 2126b092..e2e86e44 100644
--- a/src/osmo-bts-virtual/virtual_um.c
+++ b/src/osmo-bts-virtual/virtual_um.c
@@ -19,118 +19,44 @@
*
*/
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <net/if.h>
-
#include <osmocom/core/select.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/gsmtap.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
#include "virtual_um.h"
+#include "osmo_mcast_sock.h"
-#define VIRT_UM_MSGB_SIZE 256
-
-static int mcast_join_group(int fd, const char *group, const char *netdev)
-{
- int ifindex = 0;
- int rc, af;
- socklen_t af_len = sizeof(af);
-
- if (netdev) {
- ifindex = if_nametoindex(netdev);
- if (!ifindex)
- return -1;
- }
-
- rc = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &af_len);
- if (rc < 0)
- return rc;
-
- switch (af) {
- case AF_INET:
- {
- struct ip_mreqn mr;
- memset(&mr, 0, sizeof(mr));
- inet_pton(AF_INET, group, &mr.imr_multiaddr);
- if (ifindex)
- mr.imr_ifindex = ifindex;
- rc = setsockopt(fd, SOL_SOCKET, IP_ADD_MEMBERSHIP,
- &mr, sizeof(mr));
- }
- break;
- case AF_INET6:
- {
- struct ipv6_mreq mr;
- memset(&mr, 0, sizeof(mr));
- inet_pton(AF_INET6, group, &mr.ipv6mr_multiaddr);
- if (ifindex)
- mr.ipv6mr_interface = ifindex;
- rc = setsockopt(fd, SOL_SOCKET, IPV6_ADD_MEMBERSHIP,
- &mr, sizeof(mr));
-
- }
- break;
- default:
- rc = -1;
- break;
- }
-
- return rc;
-}
-
-static int mcast_connect(int fd, const char *group, uint16_t port)
-{
- int rc, af;
- socklen_t af_len = sizeof(af);
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
-
- rc = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &af_len);
- if (rc < 0)
- return rc;
-
- switch (af) {
- case AF_INET:
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- inet_pton(AF_INET, group, &sin.sin_addr);
- rc = connect(fd, (struct sockaddr *) &sin, sizeof(sin));
- break;
- case AF_INET6:
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- sin6.sin6_port = htons(port);
- inet_pton(AF_INET6, group, &sin6.sin6_addr);
- rc = connect(fd, (struct sockaddr *) &sin6, sizeof(sin6));
- break;
- default:
- return -1;
- }
-
- return rc;
-}
-
+/**
+ * Virtual UM interface file descriptor callback.
+ * Should be called by select.c when the fd is ready for reading.
+ */
static int virt_um_fd_cb(struct osmo_fd *ofd, unsigned int what)
{
struct virt_um_inst *vui = ofd->data;
+ // check if the read flag is set
if (what & BSC_FD_READ) {
- struct msgb *msg = msgb_alloc(VIRT_UM_MSGB_SIZE, "Virtual UM Rx");
+ // allocate message buffer of specified size
+ struct msgb *msg = msgb_alloc(VIRT_UM_MSGB_SIZE,
+ "Virtual UM Rx");
int rc;
- rc = read(ofd->fd, msgb_data(msg), msgb_tailroom(msg));
+ // read message from fd in message buffer
+ rc = mcast_bidir_sock_rx(vui->mcast_sock, msgb_data(msg),
+ msgb_tailroom(msg));
+ // rc is number of bytes actually read
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 {
+ // TODO: this kind of error handling might be a bit harsh
vui->recv_cb(vui, NULL);
+ // Unregister fd from select loop
osmo_fd_unregister(ofd);
close(ofd->fd);
ofd->fd = -1;
@@ -141,70 +67,36 @@ static int virt_um_fd_cb(struct osmo_fd *ofd, unsigned int what)
return 0;
}
-struct virt_um_inst *virt_um_init(void *ctx, const char *group, uint16_t port,
- const char *netdev, void *priv,
- void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg))
+struct virt_um_inst *virt_um_init(
+ void *ctx, const char *tx_mcast_group, uint16_t tx_mcast_port,
+ const char *rx_mcast_group, uint16_t rx_mcast_port,
+ void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg))
{
- struct virt_um_inst *vui;
- int fd, rc;
-
- if (!port)
- port = GSMTAP_UDP_PORT;
- if (!group)
- group = "239.0.47.29";
-
- /* crate a socked and bind it to the multicast group. Do NOT
- * specify a fixed port locally, to make stack choose a random
- * free UDP port. */
- fd = osmo_sock_init(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, group,
- 0, OSMO_SOCK_F_BIND);
- if (fd < 0)
- return NULL;
-
- /* join the multicast group */
- rc = mcast_join_group(fd, group, netdev);
- if (rc < 0) {
- close(fd);
- return NULL;
- }
-
- /* and finally also connect */
- rc = mcast_connect(fd, group, port);
- if (rc < 0) {
- close(fd);
- return NULL;
- }
-
- vui = talloc_zero(ctx, struct virt_um_inst);
- vui->priv = priv;
+ struct virt_um_inst *vui = talloc_zero(ctx, struct virt_um_inst);
+ 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);
vui->recv_cb = recv_cb;
- vui->ofd.data = vui;
- vui->ofd.fd = fd;
- vui->ofd.when = BSC_FD_READ;
- vui->ofd.cb = virt_um_fd_cb;
-
- osmo_fd_register(&vui->ofd);
return vui;
+
}
void virt_um_destroy(struct virt_um_inst *vui)
{
- struct osmo_fd *ofd = &vui->ofd;
-
- osmo_fd_unregister(ofd);
- close(ofd->fd);
- ofd->fd = -1;
- ofd->when = 0;
-
+ mcast_bidir_sock_close(vui->mcast_sock);
talloc_free(vui);
}
+/**
+ * Write msg to to multicast socket and free msg afterwards
+ */
int virt_um_write_msg(struct virt_um_inst *vui, struct msgb *msg)
{
int rc;
- rc = write(vui->ofd.fd, msgb_data(msg), msgb_length(msg));
+ rc = mcast_bidir_sock_tx(vui->mcast_sock, msgb_data(msg),
+ msgb_length(msg));
msgb_free(msg);
return rc;