further tiny steps of progress on the hnb-gw infrastructure

This commit is contained in:
Harald Welte 2015-08-29 21:47:39 +02:00
parent 6392710f84
commit a2e6a7a05e
3 changed files with 176 additions and 10 deletions

97
src/hnbgw.c Normal file
View File

@ -0,0 +1,97 @@
#include <osmocom/core/select.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/linuxlist.h>
#include "hnbgw.h"
struct hnb_gw g_hnb_gw = {
.config = {
.iuh_listen_port = IUH_DEFAULT_SCTP_PORT,
},
};
static int hnb_socket_cb(struct osmo_fd *fd, unsigned int what)
{
struct hnb_context *hnb = fd->data;
struct sctp_sndrcvinfo sinfo;
struct msgb *msg = msgb_alloc(IUH_MSGB_SIZE, "Iuh rx");
int flags;
int rc;
if (!msg)
return -ENOMEM;
rc = sctp_recvmsg(fd->fd, msgb_data(msg), msgb_tailroom(msg),
NULL, NULL, &sinfo, &flags);
if (rc < 0) {
LOGP(DMAIN, LOGL_ERROR, "Error during sctp_recvmsg()\n");
return rc;
} else
msgb_put(msg, rc);
switch (sinfo.sinfo_ppid) {
case IUH_PPI_HNBAP:
rc = hnbgw_hnbap_rx(hnb, msg);
break;
case IUH_PPI_RUA:
rc = hnbgw_rua_rx(hnb, msg);
break;
case IUH_PPI_SABP:
case IUH_PPI_RNA:
case IUH_PPI_PUA:
LOGP(DMAIN, LOGL_ERROR, "Unimplemented SCTP PPID=%u received\n",
sinfo.sinfo_ppid);
rc = 0;
break;
default:
LOGP(DMAIN, LOGL_ERROR, "Unknown SCTP PPID=%u received\n",
sinfo.sinfo_ppid);
rc = 0;
break;
}
return rc;
}
/*! call-back when the listen FD has something to read */
static int listen_fd_cb(struct osmo_fd *fd, unsigned int what)
{
struct hnb_gw *gw = fd->data;
struct hmb_context *ctx;
struct sokaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
int new_fd = accept(fd->fd, (struct sockaddr *)&sockaddr, &len);
if (new_fd < 0) {
LOGP(DMAIN, LOGL_ERROR, "Iuh accept() failed\n");
return new_fd;
}
LOGP(DMAIN, LOGL_INFO, "SCTP Connection accept()ed\n");
ctx = talloc_zero(tall_hnb_ctx, struct hnb_context);
if (!ctx)
return -ENOMEM;
ctx->gw = gw;
ctx->socket.data = ctx;
ctx->socket.fd = new_fd;
ctx->socket.when = BSC_FD_READ;
ctx->socket.cb = hnb_socket_cb;
osmo_fd_register(&cttx->socket);
return 0;
}
{
g_hnb_gw.listen_fd.cb = listen_fd_cb;
g_hnb_gw.listen_fd.when = BSC_FD_READ;
g_hnb_gw.listen_fd.data = &g_hnb_gw;
osmo_sock_init_ofd(&g_hnb_gw.listen_fd, AF_INET, SOCK_STREAM,
IPPROTO_SCTP, "127.0.0.1",
g_hnb_gw.config.iuh_listen_port, OSMO_SOCK_F_BIND);
}

View File

@ -3,27 +3,63 @@
#include <osmocom/core/select.h>
#include <osmocom/core/linuxlist.h>
/* 25.467 Section 7.1 */
#define IUH_DEFAULT_SCTP_PORT 29169
#define RNA_DEFAULT_SCTP_PORT 25471
#define IUH_PPI_RUA 19
#define IUH_PPI_HNBAP 20
#define IUH_PPI_SABP 31
#define IUH_PPI_RNA 42
#define IUH_PPI_PUA 55
#define IHU_MSGB_SIZE 2048
struct umts_cell_id {
uint16_t mcc; /*!< Mobile Country Code */
uint16_t mnc; /*!< Mobile Network Code */
uint16_t lac; /*!< Locaton Area Code */
uint16_t rac; /*!< Routing Area Code */
uint16_t sac; /*!< Service Area Code */
uint32_t cid; /*!< Cell ID */
};
struct hnb_gw;
struct hnb_context {
/*! Entry in HNB-global list of HNB */
struct llist_head list;
/*! HNB-GW we are part of */
struct hnb_gw *gw;
/*! SCTP socket for Iuh to this specific HNB */
struct osmo_fd socket;
/*! copied from HNB-Identity-Info */
char identity[256];
/*! copied from HNB-Identity-Info IE */
char identity_info[256];
/*! copied from Cell Identity IE */
struct umts_cell_id id;
};
struct ue_context {
/*! Entry in the HNB-global list of UE */
struct llist_head list;
/*! Unique Context ID for this UE */
uint32_t context_id;
/*! UE is serviced via this HNB */
struct hnb_context *hnb;
};
struct hnb_gw {
struct {
/*! SCTP port for Iuh listening */
uint16_t iuh_listen_port;
/*! The UDP port where we receive multiplexed CS user
* plane traffic from HNBs */
uint16_t iuh_cs_mux_port;
uint16_t rnc_id;
} config;
/*! SCTP listen socket for incoming connections */
struct osmo_fd listen_fd;
struct llist_head hnb_list;
};
extern struct hnb_gw g_hnb_gw;

View File

@ -29,7 +29,31 @@ struct ProtocolIE_Field_1 *find_ie(const struct ProtocolIE_Container_1 *cont, Pr
return NULL;
}
static int hnbgw_rx_hnb_register_req(struct HNBRegisterRequest *req)
static inline uint16_t asn1str_to_u16(ASN1String *as)
{
if (as->len < 2)
return 0;
else
return *(uint16_t *)as->buf;
}
static inline uint8_t asn1str_to_u8(ASN1String *as)
{
if (as->len < 1)
return 0;
else
return *(uint8_t *)as->buf;
}
static inline uint8_t asn1bitstr_to_u32(ASN1BitString *as)
{
if (as->len < 25)
return 0;
else
return *(uint32_t *)as->buf;
}
static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, struct HNBRegisterRequest *req)
{
HNB_Identity *identity =
FIND_IE(req->protocolIEs, HNBAP_IEI_HNB_Identity);
@ -47,10 +71,19 @@ static int hnbgw_rx_hnb_register_req(struct HNBRegisterRequest *req)
if(!identity || !loc || !plmn_id || !cell_id || !lac || !rac || !sac)
return -1;
/* copy all identity parameters from the message to ctx */
strncpy(ctx->identity_info, sizeof(ctx->identity_info, identity_info->buf);
ctx->id.lac = asn1str_to_u16(lac);
ctx->id.sac = asn1str_to_u16(sac);
ctx->id.rac = asn1str_to_u8(rac);
ctx->id.cid = asn1bitstr_to_u32(cell_id);
ctx->id.mcc FIXME
ctx->id.mnc FIXME
/* FIXME: Send HNBRegisterAccept */
}
static int hnbgw_rx_ue_register_req(struct UERegisterRequest *req)
static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, struct UERegisterRequest *req)
{
UE_Identity *id =
FIND_IE(req->protocolIEs, HNBAP_IEI_UE_Identity);
@ -65,7 +98,7 @@ static int hnbgw_rx_ue_register_req(struct UERegisterRequest *req)
/* FIXME: Send UERegisterAccept */
}
static int hnbgw_rx_initiating_msg(struct InitiatingMessage *msg)
static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, struct InitiatingMessage *msg)
{
int rc;
@ -73,14 +106,14 @@ static int hnbgw_rx_initiating_msg(struct InitiatingMessage *msg)
case HNBAP_PC_HNBRegister: /* 8.2 */
if (msg->value.type != asn1_type_HNBRegisterRequest)
return -1;
rc = hnbgw_rx_hnb_register_req();
rc = hnbgw_rx_hnb_register_req(hnb, FIXME);
break;
case HNBAP_PC_HNBDe_Register: /* 8.3 */
break;
case HNBAP_PC_UERegister: /* 8.4 */
if (msg->value.type != asn1_type_UERegisterRequest)
return -1;
rc = hnbgw_rx_ue_register_req();
rc = hnbgw_rx_ue_register_req(hnb, FIXME);
break;
case HNBAP_PC_UEDe_Register: /* 8.5 */
break;
@ -107,7 +140,7 @@ static int hnbgw_rx_unsuccessful_outcome_msg(struct UnsuccessfulOutcome *msg)
}
static int _hnbgw_hnbap_rx(struct HNBAP_PDU *pdu)
static int _hnbgw_hnbap_rx(struct hnb_context *hnb, struct HNBAP_PDU *pdu)
{
/* it's a bit odd that we can't dispatch on procedure code, but
* that's not possible */
@ -126,7 +159,7 @@ static int _hnbgw_hnbap_rx(struct HNBAP_PDU *pdu)
}
}
int hnbgw_hnbap_rx(struct msgb *msg)
int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg)
{
/* FIXME: decode and handle to _hnbgw_hnbap_rx() */
}