mirror of
https://gerrit.osmocom.org/osmocom-bb
synced 2024-08-15 01:46:38 +00:00
Split of LAPDm into a core part and a GSM specific part
Instead of mixing together the GSM layer 1 interface and RSL interface with the implementation of LAPD, the core function of LAPD is now extracted from LAPDm. The core implementation is now in lapd_core.c and lapd_core.h respectively. The lapd_core.c implements exactly one datalink instance for one SAP. The surrounding implementation "lapdm.c" codes/decodes the layer 2 headers and handles multiplexing and datalink instances, as well as translates primitives from/to RSL layer. lapd_core.c can now be used for other LAPD implementations. (ISDN/ABIS)
This commit is contained in:
parent
8a996b4844
commit
af48bed556
6 changed files with 2647 additions and 1686 deletions
|
@ -1,6 +1,6 @@
|
||||||
osmogsm_HEADERS = a5.h comp128.h gsm0808.h gsm48_ie.h mncc.h rxlev_stat.h \
|
osmogsm_HEADERS = a5.h comp128.h gsm0808.h gsm48_ie.h mncc.h rxlev_stat.h \
|
||||||
gsm0480.h gsm48.h gsm_utils.h rsl.h tlv.h abis_nm.h \
|
gsm0480.h gsm48.h gsm_utils.h rsl.h tlv.h abis_nm.h \
|
||||||
sysinfo.h prim.h gsm0502.h lapdm.h
|
sysinfo.h prim.h gsm0502.h lapd_core.h lapdm.h
|
||||||
|
|
||||||
SUBDIRS = protocol
|
SUBDIRS = protocol
|
||||||
|
|
||||||
|
|
171
include/osmocom/gsm/lapd_core.h
Normal file
171
include/osmocom/gsm/lapd_core.h
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
#ifndef _OSMOCOM_LAPD_H
|
||||||
|
#define _OSMOCOM_LAPD_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/timer.h>
|
||||||
|
#include <osmocom/core/msgb.h>
|
||||||
|
#include <osmocom/gsm/prim.h>
|
||||||
|
|
||||||
|
/*! \defgroup lapd LAPD implementation common part
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file lapd.h */
|
||||||
|
|
||||||
|
/* primitive related sutff */
|
||||||
|
|
||||||
|
/*! \brief LAPD related primitives (L2<->L3 SAP)*/
|
||||||
|
enum osmo_dl_prim {
|
||||||
|
PRIM_DL_UNIT_DATA, /*!< \brief DL-UNIT-DATA */
|
||||||
|
PRIM_DL_DATA, /*!< \brief DL-DATA */
|
||||||
|
PRIM_DL_EST, /*!< \brief DL-ESTABLISH */
|
||||||
|
PRIM_DL_REL, /*!< \brief DL-RLEEASE */
|
||||||
|
PRIM_DL_SUSP, /*!< \brief DL-SUSPEND */
|
||||||
|
PRIM_DL_RES, /*!< \brief DL-RESUME */
|
||||||
|
PRIM_DL_RECON, /*!< \brief DL-RECONNECT */
|
||||||
|
PRIM_MDL_ERROR, /*!< \brief MDL-ERROR */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Uses the same values as RLL, so no conversion for GSM is required. */
|
||||||
|
#define MDL_CAUSE_T200_EXPIRED 0x01
|
||||||
|
#define MDL_CAUSE_REEST_REQ 0x02
|
||||||
|
#define MDL_CAUSE_UNSOL_UA_RESP 0x03
|
||||||
|
#define MDL_CAUSE_UNSOL_DM_RESP 0x04
|
||||||
|
#define MDL_CAUSE_UNSOL_DM_RESP_MF 0x05
|
||||||
|
#define MDL_CAUSE_UNSOL_SPRV_RESP 0x06
|
||||||
|
#define MDL_CAUSE_SEQ_ERR 0x07
|
||||||
|
#define MDL_CAUSE_UFRM_INC_PARAM 0x08
|
||||||
|
#define MDL_CAUSE_SFRM_INC_PARAM 0x09
|
||||||
|
#define MDL_CAUSE_IFRM_INC_MBITS 0x0a
|
||||||
|
#define MDL_CAUSE_IFRM_INC_LEN 0x0b
|
||||||
|
#define MDL_CAUSE_FRM_UNIMPL 0x0c
|
||||||
|
#define MDL_CAUSE_SABM_MF 0x0d
|
||||||
|
#define MDL_CAUSE_SABM_INFO_NOTALL 0x0e
|
||||||
|
#define MDL_CAUSE_FRMR 0x0f
|
||||||
|
|
||||||
|
/*! \brief for MDL-ERROR.ind */
|
||||||
|
struct mdl_error_ind_param {
|
||||||
|
uint8_t cause; /*!< \brief generic cause value */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief for DL-REL.req */
|
||||||
|
struct dl_rel_req_param {
|
||||||
|
uint8_t mode; /*!< \brief release mode */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief primitive header for LAPD DL-SAP primitives */
|
||||||
|
struct osmo_dlsap_prim {
|
||||||
|
struct osmo_prim_hdr oph; /*!< \brief generic primitive header */
|
||||||
|
union {
|
||||||
|
struct mdl_error_ind_param error_ind;
|
||||||
|
struct dl_rel_req_param rel_req;
|
||||||
|
} u; /*!< \brief request-specific data */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief LAPD mode/role */
|
||||||
|
enum lapd_mode {
|
||||||
|
LAPD_MODE_USER, /*!< \brief behave like user */
|
||||||
|
LAPD_MODE_NETWORK, /*!< \brief behave like network */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief LAPD state (Figure B.2/Q.921)*/
|
||||||
|
enum lapd_state {
|
||||||
|
LAPD_STATE_NULL = 0,
|
||||||
|
LAPD_STATE_TEI_UNASS,
|
||||||
|
LAPD_STATE_ASS_TEI_WAIT,
|
||||||
|
LAPD_STATE_EST_TEI_WAIT,
|
||||||
|
LAPD_STATE_IDLE,
|
||||||
|
LAPD_STATE_SABM_SENT,
|
||||||
|
LAPD_STATE_DISC_SENT,
|
||||||
|
LAPD_STATE_MF_EST,
|
||||||
|
LAPD_STATE_TIMER_RECOV,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief LAPD message format (I / S / U) */
|
||||||
|
enum lapd_format {
|
||||||
|
LAPD_FORM_UKN = 0,
|
||||||
|
LAPD_FORM_I,
|
||||||
|
LAPD_FORM_S,
|
||||||
|
LAPD_FORM_U,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief LAPD message context */
|
||||||
|
struct lapd_msg_ctx {
|
||||||
|
struct lapd_datalink *dl;
|
||||||
|
int n201;
|
||||||
|
/* address */
|
||||||
|
uint8_t cr;
|
||||||
|
uint8_t sapi;
|
||||||
|
uint8_t tei;
|
||||||
|
uint8_t lpd;
|
||||||
|
/* control */
|
||||||
|
uint8_t format;
|
||||||
|
uint8_t p_f; /* poll / final bit */
|
||||||
|
uint8_t n_send;
|
||||||
|
uint8_t n_recv;
|
||||||
|
uint8_t s_u; /* S or repectivly U function bits */
|
||||||
|
/* length */
|
||||||
|
int length;
|
||||||
|
uint8_t more;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lapd_cr_ent {
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t resp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lapd_history {
|
||||||
|
struct msgb *msg; /* message to be sent / NULL, if histoy is empty */
|
||||||
|
int more; /* if message is fragmented */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief LAPD datalink */
|
||||||
|
struct lapd_datalink {
|
||||||
|
int (*send_dlsap)(struct osmo_dlsap_prim *dp,
|
||||||
|
struct lapd_msg_ctx *lctx);
|
||||||
|
int (*send_ph_data_req)(struct lapd_msg_ctx *lctx, struct msgb *msg);
|
||||||
|
struct {
|
||||||
|
/*! \brief filled-in once we set the lapd_mode above */
|
||||||
|
struct lapd_cr_ent loc2rem;
|
||||||
|
struct lapd_cr_ent rem2loc;
|
||||||
|
} cr;
|
||||||
|
enum lapd_mode mode; /*!< \brief current mode of link */
|
||||||
|
int use_sabme; /*!< \brief use SABME instead of SABM */
|
||||||
|
int reestablish; /*!< \brief enable reestablish support */
|
||||||
|
int n200, n200_est_rel; /*!< \brief number of retranmissions */
|
||||||
|
struct lapd_msg_ctx lctx; /*!< \brief LAPD context */
|
||||||
|
int maxf; /*!< \brief maximum frame size (after defragmentation) */
|
||||||
|
uint8_t k; /*!< \brief maximum number of unacknowledged frames */
|
||||||
|
uint8_t v_range; /*!< \brief range of sequence numbers */
|
||||||
|
uint8_t v_send; /*!< \brief seq nr of next I frame to be transmitted */
|
||||||
|
uint8_t v_ack; /*!< \brief last frame ACKed by peer */
|
||||||
|
uint8_t v_recv; /*!< \brief seq nr of next I frame expected to be received */
|
||||||
|
uint32_t state; /*!< \brief LAPD state (\ref lapd_state) */
|
||||||
|
int seq_err_cond; /*!< \brief condition of sequence error */
|
||||||
|
uint8_t own_busy; /*!< \brief receiver busy on our side */
|
||||||
|
uint8_t peer_busy; /*!< \brief receiver busy on remote side */
|
||||||
|
int t200_sec, t200_usec; /*!< \brief retry timer (default 1 sec) */
|
||||||
|
int t203_sec, t203_usec; /*!< \brief retry timer (default 10 secs) */
|
||||||
|
struct osmo_timer_list t200; /*!< \brief T200 timer */
|
||||||
|
struct osmo_timer_list t203; /*!< \brief T203 timer */
|
||||||
|
uint8_t retrans_ctr; /*!< \brief re-transmission counter */
|
||||||
|
struct llist_head tx_queue; /*!< \brief frames to L1 */
|
||||||
|
struct llist_head send_queue; /*!< \brief frames from L3 */
|
||||||
|
struct msgb *send_buffer; /*!< \brief current frame transmitting */
|
||||||
|
int send_out; /*!< \brief how much was sent from send_buffer */
|
||||||
|
struct lapd_history *tx_hist; /*!< \brief tx history structure array */
|
||||||
|
uint8_t range_hist; /*!< \brief range of history buffer 2..2^n */
|
||||||
|
struct msgb *rcv_buffer; /*!< \brief buffer to assemble the received message */
|
||||||
|
struct msgb *cont_res; /*!< \brief buffer to store content resolution data on network side, to detect multiple phones on same channel */
|
||||||
|
};
|
||||||
|
|
||||||
|
void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range,
|
||||||
|
int maxf);
|
||||||
|
void lapd_dl_exit(struct lapd_datalink *dl);
|
||||||
|
void lapd_dl_reset(struct lapd_datalink *dl);
|
||||||
|
int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode);
|
||||||
|
int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx);
|
||||||
|
int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
|
||||||
|
|
||||||
|
#endif /* _OSMOCOM_LAPD_H */
|
|
@ -1,11 +1,7 @@
|
||||||
#ifndef _OSMOCOM_LAPDM_H
|
#ifndef _OSMOCOM_LAPDM_H
|
||||||
#define _OSMOCOM_LAPDM_H
|
#define _OSMOCOM_LAPDM_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <osmocom/gsm/lapd_core.h>
|
||||||
|
|
||||||
#include <osmocom/core/timer.h>
|
|
||||||
#include <osmocom/core/msgb.h>
|
|
||||||
#include <osmocom/gsm/prim.h>
|
|
||||||
|
|
||||||
/*! \defgroup lapdm LAPDm implementation according to GSM TS 04.06
|
/*! \defgroup lapdm LAPDm implementation according to GSM TS 04.06
|
||||||
* @{
|
* @{
|
||||||
|
@ -15,7 +11,7 @@
|
||||||
|
|
||||||
/* primitive related sutff */
|
/* primitive related sutff */
|
||||||
|
|
||||||
/*! \brief LAPDm related primitives */
|
/*! \brief LAPDm related primitives (L1<->L2 SAP) */
|
||||||
enum osmo_ph_prim {
|
enum osmo_ph_prim {
|
||||||
PRIM_PH_DATA, /*!< \brief PH-DATA */
|
PRIM_PH_DATA, /*!< \brief PH-DATA */
|
||||||
PRIM_PH_RACH, /*!< \brief PH-RANDOM_ACCESS */
|
PRIM_PH_RACH, /*!< \brief PH-RANDOM_ACCESS */
|
||||||
|
@ -68,52 +64,22 @@ enum lapdm_mode {
|
||||||
LAPDM_MODE_BTS, /*!< \brief behave like a BTS (network) */
|
LAPDM_MODE_BTS, /*!< \brief behave like a BTS (network) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief LAPDm state */
|
|
||||||
enum lapdm_state {
|
|
||||||
LAPDm_STATE_NULL = 0,
|
|
||||||
LAPDm_STATE_IDLE,
|
|
||||||
LAPDm_STATE_SABM_SENT,
|
|
||||||
LAPDm_STATE_MF_EST,
|
|
||||||
LAPDm_STATE_TIMER_RECOV,
|
|
||||||
LAPDm_STATE_DISC_SENT,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lapdm_entity;
|
struct lapdm_entity;
|
||||||
|
|
||||||
/*! \brief LAPDm message context */
|
/*! \brief LAPDm message context */
|
||||||
struct lapdm_msg_ctx {
|
struct lapdm_msg_ctx {
|
||||||
struct lapdm_datalink *dl;
|
struct lapdm_datalink *dl;
|
||||||
int lapdm_fmt;
|
int lapdm_fmt;
|
||||||
uint8_t n201;
|
|
||||||
uint8_t chan_nr;
|
uint8_t chan_nr;
|
||||||
uint8_t link_id;
|
uint8_t link_id;
|
||||||
uint8_t addr;
|
|
||||||
uint8_t ctrl;
|
|
||||||
uint8_t ta_ind;
|
uint8_t ta_ind;
|
||||||
uint8_t tx_power_ind;
|
uint8_t tx_power_ind;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief LAPDm datalink like TS 04.06 / Section 3.5.2 */
|
/*! \brief LAPDm datalink like TS 04.06 / Section 3.5.2 */
|
||||||
struct lapdm_datalink {
|
struct lapdm_datalink {
|
||||||
uint8_t V_send; /*!< \brief seq nr of next I frame to be transmitted */
|
struct lapd_datalink dl; /* \brief common LAPD */
|
||||||
uint8_t V_ack; /*!< \brief last frame ACKed by peer */
|
|
||||||
uint8_t N_send; /*!< \brief ? set to V_send at Tx time*/
|
|
||||||
uint8_t V_recv; /*!< \brief seq nr of next I frame expected to be received */
|
|
||||||
uint8_t N_recv; /*!< \brief expected send seq nr of the next received I frame */
|
|
||||||
uint32_t state; /*!< \brief LAPDm state (\ref lapdm_state) */
|
|
||||||
int seq_err_cond; /*!< \brief condition of sequence error */
|
|
||||||
uint8_t own_busy; /*!< \brief receiver busy on our side */
|
|
||||||
uint8_t peer_busy; /*!< \brief receiver busy on remote side */
|
|
||||||
struct osmo_timer_list t200; /*!< \brief T200 timer */
|
|
||||||
uint8_t retrans_ctr; /*!< \brief re-transmission counter */
|
|
||||||
struct llist_head send_queue; /*!< \brief frames from L3 */
|
|
||||||
struct msgb *send_buffer; /*!< \brief current frame transmitting */
|
|
||||||
int send_out; /*!< \brief how much was sent from send_buffer */
|
|
||||||
uint8_t tx_hist[8][200]; /*!< \brief tx history buffer */
|
|
||||||
int tx_length[8]; /*!< \brief length in history buffer */
|
|
||||||
struct llist_head tx_queue; /*!< \brief frames to L1 */
|
|
||||||
struct lapdm_msg_ctx mctx; /*!< \brief context of established connection */
|
struct lapdm_msg_ctx mctx; /*!< \brief context of established connection */
|
||||||
struct msgb *rcv_buffer; /*!< \brief buffer to assemble the received message */
|
|
||||||
|
|
||||||
struct lapdm_entity *entity; /*!< \brief LAPDm entity we are part of */
|
struct lapdm_entity *entity; /*!< \brief LAPDm entity we are part of */
|
||||||
};
|
};
|
||||||
|
@ -127,11 +93,6 @@ enum lapdm_dl_sapi {
|
||||||
|
|
||||||
typedef int (*lapdm_cb_t)(struct msgb *msg, struct lapdm_entity *le, void *ctx);
|
typedef int (*lapdm_cb_t)(struct msgb *msg, struct lapdm_entity *le, void *ctx);
|
||||||
|
|
||||||
struct lapdm_cr_ent {
|
|
||||||
uint8_t cmd;
|
|
||||||
uint8_t resp;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LAPDM_ENT_F_EMPTY_FRAME 0x0001
|
#define LAPDM_ENT_F_EMPTY_FRAME 0x0001
|
||||||
#define LAPDM_ENT_F_POLLING_ONLY 0x0002
|
#define LAPDM_ENT_F_POLLING_ONLY 0x0002
|
||||||
|
|
||||||
|
@ -144,12 +105,6 @@ struct lapdm_entity {
|
||||||
enum lapdm_mode mode; /*!< \brief are we in BTS mode or MS mode */
|
enum lapdm_mode mode; /*!< \brief are we in BTS mode or MS mode */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
struct {
|
|
||||||
/*! \brief filled-in once we set the lapdm_mode above */
|
|
||||||
struct lapdm_cr_ent loc2rem;
|
|
||||||
struct lapdm_cr_ent rem2loc;
|
|
||||||
} cr;
|
|
||||||
|
|
||||||
void *l1_ctx; /*!< \brief context for layer1 instance */
|
void *l1_ctx; /*!< \brief context for layer1 instance */
|
||||||
void *l3_ctx; /*!< \brief context for layer3 instance */
|
void *l3_ctx; /*!< \brief context for layer3 instance */
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,6 @@ lib_LTLIBRARIES = libosmogsm.la
|
||||||
libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c gsm_utils.c \
|
libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c gsm_utils.c \
|
||||||
rsl.c gsm48.c gsm48_ie.c gsm0808.c sysinfo.c \
|
rsl.c gsm48.c gsm48_ie.c gsm0808.c sysinfo.c \
|
||||||
gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \
|
gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \
|
||||||
lapdm.c
|
lapd_core.c lapdm.c
|
||||||
libosmogsm_la_LDFLAGS = -version-info $(LIBVERSION)
|
libosmogsm_la_LDFLAGS = -version-info $(LIBVERSION)
|
||||||
libosmogsm_la_LIBADD = $(top_builddir)/src/libosmocore.la
|
libosmogsm_la_LIBADD = $(top_builddir)/src/libosmocore.la
|
||||||
|
|
2128
src/gsm/lapd_core.c
Normal file
2128
src/gsm/lapd_core.c
Normal file
File diff suppressed because it is too large
Load diff
1997
src/gsm/lapdm.c
1997
src/gsm/lapdm.c
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue