From af48bed556079313074d8a2ea132fd689af8a100 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 26 Sep 2011 11:23:06 +0200 Subject: 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) --- include/osmocom/gsm/Makefile.am | 2 +- include/osmocom/gsm/lapd_core.h | 171 ++++++++++++++++++++++++++++++++++++++++ include/osmocom/gsm/lapdm.h | 51 +----------- 3 files changed, 175 insertions(+), 49 deletions(-) create mode 100644 include/osmocom/gsm/lapd_core.h (limited to 'include/osmocom') diff --git a/include/osmocom/gsm/Makefile.am b/include/osmocom/gsm/Makefile.am index 90f19bc5..5971d0c5 100644 --- a/include/osmocom/gsm/Makefile.am +++ b/include/osmocom/gsm/Makefile.am @@ -1,6 +1,6 @@ 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 \ - sysinfo.h prim.h gsm0502.h lapdm.h + sysinfo.h prim.h gsm0502.h lapd_core.h lapdm.h SUBDIRS = protocol diff --git a/include/osmocom/gsm/lapd_core.h b/include/osmocom/gsm/lapd_core.h new file mode 100644 index 00000000..0f4e8899 --- /dev/null +++ b/include/osmocom/gsm/lapd_core.h @@ -0,0 +1,171 @@ +#ifndef _OSMOCOM_LAPD_H +#define _OSMOCOM_LAPD_H + +#include + +#include +#include +#include + +/*! \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 */ diff --git a/include/osmocom/gsm/lapdm.h b/include/osmocom/gsm/lapdm.h index b71feef1..cc9c63fe 100644 --- a/include/osmocom/gsm/lapdm.h +++ b/include/osmocom/gsm/lapdm.h @@ -1,11 +1,7 @@ #ifndef _OSMOCOM_LAPDM_H #define _OSMOCOM_LAPDM_H -#include - -#include -#include -#include +#include /*! \defgroup lapdm LAPDm implementation according to GSM TS 04.06 * @{ @@ -15,7 +11,7 @@ /* primitive related sutff */ -/*! \brief LAPDm related primitives */ +/*! \brief LAPDm related primitives (L1<->L2 SAP) */ enum osmo_ph_prim { PRIM_PH_DATA, /*!< \brief PH-DATA */ PRIM_PH_RACH, /*!< \brief PH-RANDOM_ACCESS */ @@ -68,52 +64,22 @@ enum lapdm_mode { 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; /*! \brief LAPDm message context */ struct lapdm_msg_ctx { struct lapdm_datalink *dl; int lapdm_fmt; - uint8_t n201; uint8_t chan_nr; uint8_t link_id; - uint8_t addr; - uint8_t ctrl; uint8_t ta_ind; uint8_t tx_power_ind; }; /*! \brief LAPDm datalink like TS 04.06 / Section 3.5.2 */ struct lapdm_datalink { - 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 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 lapd_datalink dl; /* \brief common LAPD */ 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 */ }; @@ -127,11 +93,6 @@ enum lapdm_dl_sapi { 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_POLLING_ONLY 0x0002 @@ -144,12 +105,6 @@ struct lapdm_entity { enum lapdm_mode mode; /*!< \brief are we in BTS mode or MS mode */ 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 *l3_ctx; /*!< \brief context for layer3 instance */ -- cgit v1.2.3