further tiny steps of progress on the hnb-gw infrastructure
parent
6392710f84
commit
a2e6a7a05e
|
@ -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);
|
||||
}
|
42
src/hnbgw.h
42
src/hnbgw.h
|
@ -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;
|
||||
|
|
|
@ -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() */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue