From 9ba500559a1609fa4bd0a7a7ea7f4d73c65d9440 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 14 Mar 2010 15:45:01 +0800 Subject: Create new 'gprs-sgsn' branch on top of 'gprs-conf' This branch contains the partial SGSN/GGSN implementation that was originally developed as part of the gprs branch. --- openbsc/include/openbsc/gprs_bssgp.h | 138 +++++++++++++++++++++++++++++++++++ openbsc/include/openbsc/gprs_ns.h | 61 ++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 openbsc/include/openbsc/gprs_bssgp.h create mode 100644 openbsc/include/openbsc/gprs_ns.h (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h new file mode 100644 index 00000000..f85ac48e --- /dev/null +++ b/openbsc/include/openbsc/gprs_bssgp.h @@ -0,0 +1,138 @@ +#ifndef _GPRS_BSSGP_H +#define _GPRS_BSSGP_H + +/* Section 11.3.26 / Table 11.27 */ +enum bssgp_pdu_type { + /* PDUs between RL and BSSGP SAPs */ + BSSGP_PDUT_DL_UNITDATA = 0x00, + BSSGP_PDUT_UL_UNITDATA = 0x01, + BSSGP_PDUT_RA_CAPABILITY = 0x02, + BSSGP_PDUT_PTM_UNITDATA = 0x03, + /* PDUs between GMM SAPs */ + BSSGP_PDUT_PAGING_PS = 0x06, + BSSGP_PDUT_PAGING_CS = 0x07, + BSSGP_PDUT_RA_CAPA_UDPATE = 0x08, + BSSGP_PDUT_RA_CAPA_UPDATE_ACK = 0x09, + BSSGP_PDUT_RADIO_STATUS = 0x0a, + BSSGP_PDUT_SUSPEND = 0x0b, + BSSGP_PDUT_SUSPEND_ACK = 0x0c, + BSSGP_PDUT_SUSPEND_NACK = 0x0d, + BSSGP_PDUT_RESUME = 0x0e, + BSSGP_PDUT_RESUME_ACK = 0x0f, + BSSGP_PDUT_RESUME_NACK = 0x10, + /* PDus between NM SAPs */ + BSSGP_PDUT_BVC_BLOCK = 0x20, + BSSGP_PDUT_BVC_BLOCK_ACK = 0x21, + BSSGP_PDUT_BVC_RESET = 0x22, + BSSGP_PDUT_BVC_RESET_ACK = 0x23, + BSSGP_PDUT_BVC_UNBLOCK = 0x24, + BSSGP_PDUT_BVC_UNBLOCK_ACK = 0x25, + BSSGP_PDUT_FLOW_CONTROL_BVC = 0x26, + BSSGP_PDUT_FLOW_CONTROL_BVC_ACK = 0x27, + BSSGP_PDUT_FLOW_CONTROL_MS = 0x28, + BSSGP_PDUT_FLOW_CONTROL_MS_ACK = 0x29, + BSSGP_PDUT_FLUSH_LL = 0x2a, + BSSGP_PDUT_FLUSH_LL_ACK = 0x2b, + BSSGP_PDUT_LLC_DISCARD = 0x2c, + BSSGP_PDUT_SGSN_INVOKE_TRACE = 0x40, + BSSGP_PDUT_STATUS = 0x41, + /* PDUs between PFM SAP's */ + BSSGP_PDUT_DOWNLOAD_BSS_PFC = 0x50, + BSSGP_PDUT_CREATE_BSS_PFC = 0x51, + BSSGP_PDUT_CREATE_BSS_PFC_ACK = 0x52, + BSSGP_PDUT_CREATE_BSS_PFC_NACK = 0x53, + BSSGP_PDUT_MODIFY_BSS_PFC = 0x54, + BSSGP_PDUT_MODIFY_BSS_PFC_ACK = 0x55, + BSSGP_PDUT_DELETE_BSS_PFC = 0x56, + BSSGP_PDUT_DELETE_BSS_PFC_ACK = 0x57, +}; + +/* Section 10.2.1 and 10.2.2 */ +struct bssgp_ud_hdr { + u_int8_t pdu_type; + u_int32_t tlli; + u_int8_t qos_profile[3]; + u_int8_t data[0]; /* TLV's */ +} __attribute__((packed)); + +struct bssgp_normal_hdr { + u_int8_t pdu_type; + u_int8_t data[0]; /* TLV's */ +}; + +enum bssgp_iei_type { + BSSGP_IE_ALIGNMENT = 0x00, + BSSGP_IE_BMAX_DEFAULT_MS = 0x01, + BSSGP_IE_BSS_AREA_ID = 0x02, + BSSGP_IE_BUCKET_LEAK_RATE = 0x03, + BSSGP_IE_BVCI = 0x04, + BSSGP_IE_BVC_BUCKET_SIZE = 0x05, + BSSGP_IE_BVC_MEASUREMENT = 0x06, + BSSGP_IE_CAUSE = 0x07, + BSSGP_IE_CELL_ID = 0x08, + BSSGP_IE_CHAN_NEEDED = 0x09, + BSSGP_IE_DRX_PARAMS = 0x0a, + BSSGP_IE_EMLPP_PRIO = 0x0b, + BSSGP_IE_FLUSH_ACTION = 0x0c, + BSSGP_IE_IMSI = 0x0d, + BSSGP_IE_LLC_PDU = 0x0e, + BSSGP_IE_LLC_FRAMES_DISCARDED = 0x0f, + BSSGP_IE_LOCATION_AREA = 0x10, + BSSGP_IE_MOBILE_ID = 0x11, + BSSGP_IE_MS_BUCKET_SIZE = 0x12, + BSSGP_IE_MS_RADIO_ACCESS_CAP = 0x13, + BSSGP_IE_OMC_ID = 0x14, + BSSGP_IE_PDU_IN_ERROR = 0x15, + BSSGP_IE_PDU_LIFETIME = 0x16, + BSSGP_IE_PRIORITY = 0x17, + BSSGP_IE_QOS_PROFILE = 0x18, + BSSGP_IE_RADIO_CAUSE = 0x19, + BSSGP_IE_RA_CAP_UPD_CAUSE = 0x1a, + BSSGP_IE_ROUTEING_AREA = 0x1b, + BSSGP_IE_R_DEFAULT_MS = 0x1c, + BSSGP_IE_SUSPEND_REF_NR = 0x1d, + BSSGP_IE_TAG = 0x1e, + BSSGP_IE_TLLI = 0x1f, + BSSGP_IE_TMSI = 0x20, + BSSGP_IE_TRACE_REFERENC = 0x21, + BSSGP_IE_TRACE_TYPE = 0x22, + BSSGP_IE_TRANSACTION_ID = 0x23, + BSSGP_IE_TRIGGER_ID = 0x24, + BSSGP_IE_NUM_OCT_AFF = 0x25, + BSSGP_IE_LSA_ID_LIST = 0x26, + BSSGP_IE_LSA_INFORMATION = 0x27, + BSSGP_IE_PACKET_FLOW_ID = 0x28, + BSSGP_IE_PACKET_FLOW_TIMER = 0x29, + BSSGP_IE_AGG_BSS_QOS_PROFILE = 0x3a, + BSSGP_IE_FEATURE_BITMAP = 0x3b, + BSSGP_IE_BUCKET_FULL_RATIO = 0x3c, + BSSGP_IE_SERVICE_UTRAN_CCO = 0x3d, +}; + +/* Section 11.3.8 / Table 11.10: Cause coding */ +enum gprs_bssgp_cause { + BSSGP_CAUSE_PROC_OVERLOAD = 0x00, + BSSGP_CAUSE_EQUIP_FAIL = 0x01, + BSSGP_CAUSE_TRASIT_NET_FAIL = 0x02, + BSSGP_CAUSE_CAPA_GREATER_0KPBS = 0x03, + BSSGP_CAUSE_UNKNOWN_MS = 0x04, + BSSGP_CAUSE_UNKNOWN_BVCI = 0x05, + BSSGP_CAUSE_CELL_TRAF_CONG = 0x06, + BSSGP_CAUSE_SGSN_CONG = 0x07, + BSSGP_CAUSE_OML_INTERV = 0x08, + BSSGP_CAUSE_BVCI_BLOCKED = 0x09, + BSSGP_CAUSE_PFC_CREATE_FAIL = 0x0a, + BSSGP_CAUSE_SEM_INCORR_PDU = 0x20, + BSSGP_CAUSE_INV_MAND_INF = 0x21, + BSSGP_CAUSE_MISSING_MAND_IE = 0x22, + BSSGP_CAUSE_MISSING_COND_IE = 0x23, + BSSGP_CAUSE_UNEXP_COND_IE = 0x24, + BSSGP_CAUSE_COND_IE_ERR = 0x25, + BSSGP_CAUSE_PDU_INCOMP_STATE = 0x26, + BSSGP_CAUSE_PROTO_ERR_UNSPEC = 0x27, + BSSGP_CAUSE_PDU_INCOMP_FEAT = 0x28, +}; + +extern int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t bvci); + +#endif /* _GPRS_BSSGP_H */ diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h new file mode 100644 index 00000000..90f1adf3 --- /dev/null +++ b/openbsc/include/openbsc/gprs_ns.h @@ -0,0 +1,61 @@ +#ifndef _GPRS_NS_H +#define _GPRS_NS_H + +struct gprs_ns_hdr { + u_int8_t pdu_type; + u_int8_t data[0]; +} __attribute__((packed)); + +/* TS 08.16, Section 10.3.7, Table 14 */ +enum ns_pdu_type { + NS_PDUT_UNITDATA = 0x00, + NS_PDUT_RESET = 0x02, + NS_PDUT_RESET_ACK = 0x03, + NS_PDUT_BLOCK = 0x04, + NS_PDUT_BLOCK_ACK = 0x05, + NS_PDUT_UNBLOCK = 0x06, + NS_PDUT_UNBLOCK_ACK = 0x07, + NS_PDUT_STATUS = 0x08, + NS_PDUT_ALIVE = 0x0a, + NS_PDUT_ALIVE_ACK = 0x0b, +}; + +/* TS 08.16, Section 10.3, Table 12 */ +enum ns_ctrl_ie { + NS_IE_CAUSE = 0x00, + NS_IE_VCI = 0x01, + NS_IE_PDU = 0x02, + NS_IE_BVCI = 0x03, + NS_IE_NSEI = 0x04, +}; + +/* TS 08.16, Section 10.3.2, Table 13 */ +enum ns_cause { + NS_CAUSE_TRANSIT_FAIL = 0x00, + NS_CAUSE_OM_INTERVENTION = 0x01, + NS_CAUSE_EQUIP_FAIL = 0x02, + NS_CAUSE_NSVC_BLOCKED = 0x03, + NS_CAUSE_NSVC_UNKNOWN = 0x04, + NS_CAUSE_BVCI_UNKNOWN = 0x05, + NS_CAUSE_SEM_INCORR_PDU = 0x08, + NS_CAUSE_PDU_INCOMP_PSTATE = 0x0a, + NS_CAUSE_PROTO_ERR_UNSPEC = 0x0b, + NS_CAUSE_INVAL_ESSENT_IE = 0x0c, + NS_CAUSE_MISSING_ESSENT_IE = 0x0d, +}; + +/* a layer 1 entity transporting NS frames */ +struct gprs_ns_link { + union { + struct { + int fd; + } ip; + }; +}; + + +int gprs_ns_rcvmsg(struct msgb *msg); + +int gprs_ns_sendmsg(struct gprs_ns_link *link, u_int16_t bvci, + struct msgb *msg); +#endif -- cgit v1.2.3 From c547848eadb3f285078a68d17240ba9280c2c117 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 18 Mar 2010 00:01:43 +0800 Subject: GPRS: remove hard-coded IP address for NSIP responses from SGSN->BTS --- openbsc/include/openbsc/gprs_ns.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 90f1adf3..9ea4d675 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -54,7 +54,7 @@ struct gprs_ns_link { }; -int gprs_ns_rcvmsg(struct msgb *msg); +int gprs_ns_rcvmsg(struct msgb *msg, struct sockaddr_in *saddr); int gprs_ns_sendmsg(struct gprs_ns_link *link, u_int16_t bvci, struct msgb *msg); -- cgit v1.2.3 From f030b210e8c13314d361a6b721a0cbcc72935219 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 26 Apr 2010 19:18:54 +0200 Subject: GPRS: Modularize the NS implementation * move UDP listener code for NSIP from input/ipaccess.c and into gprs_ns.c * add PDU type, IE and CAUSE values for later IP based 3GPP TS 48.016 * support multiple NS-VCs and their lookup based on NSVC and sockaddr_in * maintain the remote_state (blocked/alive) for each NSVC * introduce the concept of GPRS_NS instances, move all global vars to instance * remove hardcoded calls to gprs_bssgp_rcvmsg() and replace it by callback WARNING: This is not finished code. While it will compile, it will not work yet, as BSSGP needs to be converted to properly indicate the NSVC to which it needs to send data. --- openbsc/include/openbsc/gprs_ns.h | 62 +++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 9 deletions(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 9ea4d675..98b31f8d 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -1,6 +1,10 @@ #ifndef _GPRS_NS_H #define _GPRS_NS_H +/* GPRS Networks Service (NS) messages on the Gb interface + * 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05) + * 3GPP TS 48.016 version 6.5.0 Release 6 / ETSI TS 148 016 V6.5.0 (2005-11) */ + struct gprs_ns_hdr { u_int8_t pdu_type; u_int8_t data[0]; @@ -18,6 +22,15 @@ enum ns_pdu_type { NS_PDUT_STATUS = 0x08, NS_PDUT_ALIVE = 0x0a, NS_PDUT_ALIVE_ACK = 0x0b, + /* TS 48.016 Section 10.3.7, Table 10.3.7.1 */ + SNS_PDUT_ACK = 0x0c, + SNS_PDUT_ADD = 0x0d, + SNS_PDUT_CHANGE_WEIGHT = 0x0e, + SNS_PDUT_CONFIG = 0x0f, + SNS_PDUT_CONFIG_ACK = 0x10, + SNS_PDUT_DELETE = 0x11, + SNS_PDUT_SIZE = 0x12, + SNS_PDUT_SIZE_ACK = 0x13, }; /* TS 08.16, Section 10.3, Table 12 */ @@ -27,6 +40,14 @@ enum ns_ctrl_ie { NS_IE_PDU = 0x02, NS_IE_BVCI = 0x03, NS_IE_NSEI = 0x04, + /* TS 48.016 Section 10.3, Table 10.3.1 */ + NS_IE_IPv4_LIST = 0x05, + NS_IE_IPv6_LIST = 0x06, + NS_IE_MAX_NR_NSVC = 0x07, + NS_IE_IPv4_EP_NR = 0x08, + NS_IE_IPv6_EP_NR = 0x09, + NS_IE_RESET_FLAG = 0x0a, + NS_IE_IP_ADDR = 0x0b, }; /* TS 08.16, Section 10.3.2, Table 13 */ @@ -42,20 +63,43 @@ enum ns_cause { NS_CAUSE_PROTO_ERR_UNSPEC = 0x0b, NS_CAUSE_INVAL_ESSENT_IE = 0x0c, NS_CAUSE_MISSING_ESSENT_IE = 0x0d, + /* TS 48.016 Section 10.3.2, Table 10.3.2.1 */ + NS_CAUSE_INVAL_NR_IPv4_EP = 0x0e, + NS_CAUSE_INVAL_NR_IPv6_EP = 0x0f, + NS_CAUSE_INVAL_NR_NS_VC = 0x10, + NS_CAUSE_INVAL_WEIGH = 0x11, + NS_CAUSE_UNKN_IP_EP = 0x12, + NS_CAUSE_UNKN_IP_ADDR = 0x13, + NS_CAUSE_UNKN_IP_TEST_FAILED = 0x14, }; -/* a layer 1 entity transporting NS frames */ -struct gprs_ns_link { - union { - struct { - int fd; - } ip; - }; +struct gprs_nsvc; +struct gprs_ns_inst; + +enum gprs_ns_evt { + GPRS_NS_EVT_UNIT_DATA, }; +typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, + struct msgb *msg, u_int16_t bvci); + +/* Create a new NS protocol instance */ +struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb); + +/* Destroy a NS protocol instance */ +void gprs_ns_destroy(struct gprs_ns_inst *nsi); -int gprs_ns_rcvmsg(struct msgb *msg, struct sockaddr_in *saddr); +/* Listen for incoming GPRS packets */ +int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port); -int gprs_ns_sendmsg(struct gprs_ns_link *link, u_int16_t bvci, +struct sockaddr_in; + +/* main entry point, here incoming NS frames enter */ +int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, + struct sockaddr_in *saddr); + +/* main function for higher layers (BSSGP) to send NS messages */ +int gprs_ns_sendmsg(struct gprs_nsvc *nsvc, u_int16_t bvci, struct msgb *msg); + #endif -- cgit v1.2.3 From 24a655f1406f53ce54802e72f72b6bf19394672e Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 30 Apr 2010 19:54:29 +0200 Subject: gprs: remove msgb->nsvc pointer and replace it with NSEI and BVCI According to TS 08.16, the BSSGP layer needs to specify NSEI and BVCI when executing the NS UNITDATA REQUEST primitive of the underlying NS layer. Rather than passing around a pointer to the 'struct gprs_nsvc', we now have NSEI and BVCI as members of 'struct obsc_msgb_cb' and set them when BSSGP hands a message down to NS. NS then does a lookup of the 'gprs_nsvc' based on the NSEI parameter. --- openbsc/include/openbsc/gprs_ns.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 98b31f8d..34a3e581 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -99,7 +99,6 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, struct sockaddr_in *saddr); /* main function for higher layers (BSSGP) to send NS messages */ -int gprs_ns_sendmsg(struct gprs_nsvc *nsvc, u_int16_t bvci, - struct msgb *msg); +int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg); #endif -- cgit v1.2.3 From 3771d09ec01581e50253dce4dc5ec0abba9a1e35 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 30 Apr 2010 20:26:32 +0200 Subject: GPRS: Introduce a GPRS Gb Proxy The ida of the Gb proxy is to aggregate Gb links with a number of BSS and then present all the BSSGP-VC's together inside one NS-VC to the actual SGSN. The code is not yet expected to be complete. --- openbsc/include/openbsc/gprs_bssgp.h | 10 +++++++++ openbsc/include/openbsc/gprs_ns.h | 39 +++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h index f85ac48e..3040e6a0 100644 --- a/openbsc/include/openbsc/gprs_bssgp.h +++ b/openbsc/include/openbsc/gprs_bssgp.h @@ -133,6 +133,16 @@ enum gprs_bssgp_cause { BSSGP_CAUSE_PDU_INCOMP_FEAT = 0x28, }; +/* Our implementation */ + +#include + extern int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t bvci); +/* Wrapper around TLV parser to parse BSSGP IEs */ +static inline int bssgp_tlv_parse(struct tlv_parsed *tp, u_int8_t *buf, int len) +{ + return tlv_parse(tp, &tvlv_att_def, buf, len, 0, 0); +} + #endif /* _GPRS_BSSGP_H */ diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 34a3e581..dd10d333 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -73,7 +73,37 @@ enum ns_cause { NS_CAUSE_UNKN_IP_TEST_FAILED = 0x14, }; -struct gprs_nsvc; + +/* Our Implementation */ +#include + +#define NSE_S_BLOCKED 0x0001 +#define NSE_S_ALIVE 0x0002 + +struct gprs_nsvc { + struct llist_head list; + struct gprs_ns_inst *nsi; + + u_int16_t nsei; /* end-to-end significance */ + u_int16_t nsvci; /* uniquely identifies NS-VC at SGSN */ + + u_int32_t state; + u_int32_t remote_state; + + struct timer_list alive_timer; + int timer_is_tns_alive; + int alive_retries; + + int remote_end_is_sgsn; + + union { + struct { + struct sockaddr_in bts_addr; + } ip; + }; +}; + + struct gprs_ns_inst; enum gprs_ns_evt { @@ -101,4 +131,11 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, /* main function for higher layers (BSSGP) to send NS messages */ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg); + +/* Listen for incoming GPRS packets */ +int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port); + +/* Establish a connection (from the BSS) to the SGSN */ +struct gprs_nsvc *nsip_connect(struct gprs_ns_inst *nsi, + struct sockaddr_in *dest, uint16_t nsvci); #endif -- cgit v1.2.3 From 1203de3993a7df15a01469492d8ea9179c763668 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 1 May 2010 11:28:43 +0200 Subject: [gprs] fully integrate VTY configuration into Gb proxy The Gb-proxy is now fully configured by config file / VTY --- openbsc/include/openbsc/gprs_ns.h | 49 ++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index dd10d333..ca02c4b5 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -76,10 +76,46 @@ enum ns_cause { /* Our Implementation */ #include +#include +#include +#include +#include #define NSE_S_BLOCKED 0x0001 #define NSE_S_ALIVE 0x0002 +enum gprs_ns_ll { + GPRS_NS_LL_UDP, + GPRS_NS_LL_E1, +}; + +enum gprs_ns_evt { + GPRS_NS_EVT_UNIT_DATA, +}; + +struct gprs_nsvc; +typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, + struct msgb *msg, u_int16_t bvci); + +/* An instance of the NS protocol stack */ +struct gprs_ns_inst { + /* callback to the user for incoming UNIT DATA IND */ + gprs_ns_cb_t *cb; + + /* linked lists of all NSVC in this instance */ + struct llist_head gprs_nsvcs; + + /* which link-layer are we based on? */ + enum gprs_ns_ll ll; + + union { + /* NS-over-IP specific bits */ + struct { + struct bsc_fd fd; + } nsip; + }; +}; + struct gprs_nsvc { struct llist_head list; struct gprs_ns_inst *nsi; @@ -103,16 +139,6 @@ struct gprs_nsvc { }; }; - -struct gprs_ns_inst; - -enum gprs_ns_evt { - GPRS_NS_EVT_UNIT_DATA, -}; - -typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, - struct msgb *msg, u_int16_t bvci); - /* Create a new NS protocol instance */ struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb); @@ -137,5 +163,6 @@ int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port); /* Establish a connection (from the BSS) to the SGSN */ struct gprs_nsvc *nsip_connect(struct gprs_ns_inst *nsi, - struct sockaddr_in *dest, uint16_t nsvci); + struct sockaddr_in *dest, uint16_t nsei, + uint16_t nsvci); #endif -- cgit v1.2.3 From 30bc19a5c6b171142569a00739a52db008eb8ba6 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 2 May 2010 11:19:37 +0200 Subject: [gprs] SGSN: Expect all Identifiers to be stored at highest level We now expect the highest level (actual SGSN GMM code) to know all identifiers for every element in the protocol stack, i.e. TLLI, SAPI, BVCI and NSEI. The layer-inetrnal state is looked up based on those identifiers. The reason for this is to ensure only the highest level state needs to be persistent, while everything else can be regenerated dynamically (e.g. in a SGSN restart) --- openbsc/include/openbsc/gprs_bssgp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h index 3040e6a0..a00481e4 100644 --- a/openbsc/include/openbsc/gprs_bssgp.h +++ b/openbsc/include/openbsc/gprs_bssgp.h @@ -137,7 +137,7 @@ enum gprs_bssgp_cause { #include -extern int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t bvci); +extern int gprs_bssgp_rcvmsg(struct msgb *msg); /* Wrapper around TLV parser to parse BSSGP IEs */ static inline int bssgp_tlv_parse(struct tlv_parsed *tp, u_int8_t *buf, int len) -- cgit v1.2.3 From 8f9a3ee67bf25b62936ffbcd88936936916ad0e9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 2 May 2010 11:26:34 +0200 Subject: [gprs] Use stdint.h types (uintXX_t instead of u_intXX_t) libosmocore already uses them, it's time (at least for new code) in openbsc to do the same. --- openbsc/include/openbsc/gprs_bssgp.h | 16 +++++++++------- openbsc/include/openbsc/gprs_ns.h | 16 +++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h index a00481e4..c70868af 100644 --- a/openbsc/include/openbsc/gprs_bssgp.h +++ b/openbsc/include/openbsc/gprs_bssgp.h @@ -1,6 +1,8 @@ #ifndef _GPRS_BSSGP_H #define _GPRS_BSSGP_H +#include + /* Section 11.3.26 / Table 11.27 */ enum bssgp_pdu_type { /* PDUs between RL and BSSGP SAPs */ @@ -49,15 +51,15 @@ enum bssgp_pdu_type { /* Section 10.2.1 and 10.2.2 */ struct bssgp_ud_hdr { - u_int8_t pdu_type; - u_int32_t tlli; - u_int8_t qos_profile[3]; - u_int8_t data[0]; /* TLV's */ + uint8_t pdu_type; + uint32_t tlli; + uint8_t qos_profile[3]; + uint8_t data[0]; /* TLV's */ } __attribute__((packed)); struct bssgp_normal_hdr { - u_int8_t pdu_type; - u_int8_t data[0]; /* TLV's */ + uint8_t pdu_type; + uint8_t data[0]; /* TLV's */ }; enum bssgp_iei_type { @@ -140,7 +142,7 @@ enum gprs_bssgp_cause { extern int gprs_bssgp_rcvmsg(struct msgb *msg); /* Wrapper around TLV parser to parse BSSGP IEs */ -static inline int bssgp_tlv_parse(struct tlv_parsed *tp, u_int8_t *buf, int len) +static inline int bssgp_tlv_parse(struct tlv_parsed *tp, uint8_t *buf, int len) { return tlv_parse(tp, &tvlv_att_def, buf, len, 0, 0); } diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index ca02c4b5..573536d1 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -1,13 +1,15 @@ #ifndef _GPRS_NS_H #define _GPRS_NS_H +#include + /* GPRS Networks Service (NS) messages on the Gb interface * 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05) * 3GPP TS 48.016 version 6.5.0 Release 6 / ETSI TS 148 016 V6.5.0 (2005-11) */ struct gprs_ns_hdr { - u_int8_t pdu_type; - u_int8_t data[0]; + uint8_t pdu_type; + uint8_t data[0]; } __attribute__((packed)); /* TS 08.16, Section 10.3.7, Table 14 */ @@ -95,7 +97,7 @@ enum gprs_ns_evt { struct gprs_nsvc; typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, - struct msgb *msg, u_int16_t bvci); + struct msgb *msg, uint16_t bvci); /* An instance of the NS protocol stack */ struct gprs_ns_inst { @@ -120,11 +122,11 @@ struct gprs_nsvc { struct llist_head list; struct gprs_ns_inst *nsi; - u_int16_t nsei; /* end-to-end significance */ - u_int16_t nsvci; /* uniquely identifies NS-VC at SGSN */ + uint16_t nsei; /* end-to-end significance */ + uint16_t nsvci; /* uniquely identifies NS-VC at SGSN */ - u_int32_t state; - u_int32_t remote_state; + uint32_t state; + uint32_t remote_state; struct timer_list alive_timer; int timer_is_tns_alive; -- cgit v1.2.3 From a2ca4ed96073328c33cc6fd8fdf626b2685463f8 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 2 May 2010 11:54:55 +0200 Subject: [gprs] pass BSSGP UL-UNITDATA Cell ID up into GMM layer BSSGP stores a pointer to the Cell Identifier IE in msgb->cb, which is later used by the GMM layer to identify the cell that has sent a given message. This now also means that the gsm_04_08_gprs.c code is free of any legacy references to msg->trx or struct gsm_bts. --- openbsc/include/openbsc/gprs_bssgp.h | 1 + 1 file changed, 1 insertion(+) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h index c70868af..c1094b35 100644 --- a/openbsc/include/openbsc/gprs_bssgp.h +++ b/openbsc/include/openbsc/gprs_bssgp.h @@ -140,6 +140,7 @@ enum gprs_bssgp_cause { #include extern int gprs_bssgp_rcvmsg(struct msgb *msg); +uint16_t bssgp_parse_cell_id(struct gprs_ra_id *raid, const uint8_t *buf); /* Wrapper around TLV parser to parse BSSGP IEs */ static inline int bssgp_tlv_parse(struct tlv_parsed *tp, uint8_t *buf, int len) -- cgit v1.2.3 From 80405458a0c325e11e55133065df9b767bb0edc4 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 3 May 2010 20:16:13 +0200 Subject: [gprs] NS: replace nsvc->timer_is_tns_alive with nsvc->timer_mode This will allow to use the timer in more than 2 modes --- openbsc/include/openbsc/gprs_ns.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 573536d1..40784049 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -118,6 +118,14 @@ struct gprs_ns_inst { }; }; +enum nsvc_timer_mode { + /* standard timers */ + NSVC_TIMER_TNS_TEST, + NSVC_TIMER_TNS_ALIVE, + /* custom timer */ + NSVC_TIMER_RESET, +}; + struct gprs_nsvc { struct llist_head list; struct gprs_ns_inst *nsi; @@ -128,8 +136,8 @@ struct gprs_nsvc { uint32_t state; uint32_t remote_state; - struct timer_list alive_timer; - int timer_is_tns_alive; + struct timer_list timer; + enum nsvc_timer_mode timer_mode; int alive_retries; int remote_end_is_sgsn; -- cgit v1.2.3 From 69a4cf27318f471a70759a80923a0dfbbe0a8e0a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 3 May 2010 20:55:10 +0200 Subject: [gprs] NS: improved timer handling for RESET --- openbsc/include/openbsc/gprs_ns.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 40784049..27c54cb1 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -122,8 +122,8 @@ enum nsvc_timer_mode { /* standard timers */ NSVC_TIMER_TNS_TEST, NSVC_TIMER_TNS_ALIVE, - /* custom timer */ - NSVC_TIMER_RESET, + NSVC_TIMER_TNS_RESET, + _NSVC_TIMER_NR, }; struct gprs_nsvc { -- cgit v1.2.3 From 834f26d62c55a7ba837ca370e7c60d0672aaead1 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 11 May 2010 06:20:54 +0200 Subject: [gprs] NS: Add signals in the event of BLOCK/UNBLOCK/RESET The signals will be sent upon reception of NS-BLOCK/UNBLOCK/RESET PDUs We also export functions to generate/send BLOCK/UNBLOCK and RESET. --- openbsc/include/openbsc/gprs_ns.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 27c54cb1..c74546a8 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -167,6 +167,9 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, /* main function for higher layers (BSSGP) to send NS messages */ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg); +int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause); +int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause); +int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc); /* Listen for incoming GPRS packets */ int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port); -- cgit v1.2.3 From af0867882d5302f5f356aedf55524315624c5071 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 11 May 2010 10:01:17 +0200 Subject: [gprs] gb_proxy: Send proper BSSGP STATUS msg in error case In order to reuse the existing bssgp_tx_* functions without pulling in the dependencies of gprs_bssgp.c, we have to move those functions to gprs_bssgp_util.c Furthermore, we can remove gbprox_nsi and replace it with bssgp_nsi, and we can do proper processing of BVC-RESET messages coming from the SGSN on the signalling BVC. In that case we need to send RESET messages to all the BSS. --- openbsc/include/openbsc/gprs_bssgp.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h index c1094b35..d3ccb12e 100644 --- a/openbsc/include/openbsc/gprs_bssgp.h +++ b/openbsc/include/openbsc/gprs_bssgp.h @@ -137,6 +137,18 @@ enum gprs_bssgp_cause { /* Our implementation */ +/* gprs_bssgp_util.c */ +extern struct gprs_ns_inst *bssgp_nsi; +struct msgb *bssgp_msgb_alloc(void); +const char *bssgp_cause_str(enum gprs_bssgp_cause cause); +/* Transmit a simple response such as BLOCK/UNBLOCK/RESET ACK/NACK */ +int bssgp_tx_simple_bvci(uint8_t pdu_type, uint16_t nsei, + uint16_t bvci, uint16_t ns_bvci); +/* Chapter 10.4.14: Status */ +int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg); + +/* gprs_bssgp.c */ + #include extern int gprs_bssgp_rcvmsg(struct msgb *msg); -- cgit v1.2.3 From 2bffac599f4a93a3113a7260955ac3ec1cd4b39c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 12 May 2010 15:55:23 +0000 Subject: NS: Add support for persistent NS-VC configuration With persistent NS-VC configuration (configured through VTY), we can respond properly to BSS with a somewhat strange NS implementation Such as the BSplus. It enables us to respond with a proper NS-RESET (including NSVCI/NSEI) when receiving a NS-ALIVE or other PDU for a BLOCKED/DEAD NS-VC after our end of the connection is rebooted. --- openbsc/include/openbsc/gprs_ns.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index c74546a8..60051d13 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -140,7 +140,8 @@ struct gprs_nsvc { enum nsvc_timer_mode timer_mode; int alive_retries; - int remote_end_is_sgsn; + unsigned int remote_end_is_sgsn:1; + unsigned int persistent:1; union { struct { @@ -178,4 +179,8 @@ int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port); struct gprs_nsvc *nsip_connect(struct gprs_ns_inst *nsi, struct sockaddr_in *dest, uint16_t nsei, uint16_t nsvci); + +/* Add NS-specific VTY stuff */ +int gprs_ns_vty_init(struct gprs_ns_inst *nsi); + #endif -- cgit v1.2.3 From fe4ab901cc00f88e644e5640c2988f52c79f4183 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 12 May 2010 17:19:53 +0000 Subject: NS: Make all timers configurable from VTY --- openbsc/include/openbsc/gprs_ns.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 60051d13..847e8f9c 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -75,7 +75,6 @@ enum ns_cause { NS_CAUSE_UNKN_IP_TEST_FAILED = 0x14, }; - /* Our Implementation */ #include #include @@ -83,6 +82,25 @@ enum ns_cause { #include #include +#define NS_TIMERS_COUNT 7 +#define NS_TIMERS "(tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries)" +#define NS_TIMERS_HELP \ + "(un)blocking Timer (Tns-block) timeout\n" \ + "(un)blocking Timer (Tns-block) number of retries\n" \ + "Reset Timer (Tns-reset) timeout\n" \ + "Reset Timer (Tns-reset) number of retries\n" \ + "Test Timer (Tns-test) timeout\n" \ + +enum ns_timeout { + NS_TOUT_TNS_BLOCK, + NS_TOUT_TNS_BLOCK_RETRIES, + NS_TOUT_TNS_RESET, + NS_TOUT_TNS_RESET_RETRIES, + NS_TOUT_TNS_TEST, + NS_TOUT_TNS_ALIVE, + NS_TOUT_TNS_ALIVE_RETRIES, +}; + #define NSE_S_BLOCKED 0x0001 #define NSE_S_ALIVE 0x0002 @@ -107,6 +125,8 @@ struct gprs_ns_inst { /* linked lists of all NSVC in this instance */ struct llist_head gprs_nsvcs; + uint16_t timeout[NS_TIMERS_COUNT]; + /* which link-layer are we based on? */ enum gprs_ns_ll ll; -- cgit v1.2.3 From 144e0295c2c92470756cb2d386c136810fcd4a91 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 13 May 2010 11:45:07 +0200 Subject: [GPRS] NS: Start to use rate_ctr_group code from libosmocore Every NS-VC now has a set of counters for incoming and outgoing number of packets and bytes. We also split the VTY part of the gprs_ns.c implementation into gprs_ns_vty.c to make sure the protocol can actually be used without the VTY code being present. --- openbsc/include/openbsc/gprs_ns.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 847e8f9c..34b1b62d 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -163,6 +163,8 @@ struct gprs_nsvc { unsigned int remote_end_is_sgsn:1; unsigned int persistent:1; + struct rate_ctr_group *ctrg; + union { struct { struct sockaddr_in bts_addr; @@ -200,6 +202,10 @@ struct gprs_nsvc *nsip_connect(struct gprs_ns_inst *nsi, struct sockaddr_in *dest, uint16_t nsei, uint16_t nsvci); +struct gprs_nsvc *nsvc_create(struct gprs_ns_inst *nsi, uint16_t nsvci); +void nsvc_delete(struct gprs_nsvc *nsvc); +struct gprs_nsvc *nsvc_by_nsei(struct gprs_ns_inst *nsi, uint16_t nsei); + /* Add NS-specific VTY stuff */ int gprs_ns_vty_init(struct gprs_ns_inst *nsi); -- cgit v1.2.3 From dd1c83c52d66c28583e06ba3b930883b488689ea Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 13 May 2010 13:58:08 +0200 Subject: [GPRS] NS: Fix segfault when receiving message from unknown NS-VC In the previous code we used a static fake_nsvc structure in case we needed to send a message to an unknown NSVC for which we don't have a real 'struct nsvc'. However, since we now have a rate_ctr_group hanging off the nsvc, the fake structure didn't have that. So now we keep a nsi->unknown_nsvc around to be used whenever we need a nsvc but don't have a real one. The gprs_ns_vty.c code explicitly does not list that NSVC in 'show ns' --- openbsc/include/openbsc/gprs_ns.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'openbsc/include') diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 34b1b62d..4ccf4c7b 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -125,6 +125,9 @@ struct gprs_ns_inst { /* linked lists of all NSVC in this instance */ struct llist_head gprs_nsvcs; + /* a NSVC object that's needed to deal with packets for unknown NSVC */ + struct gprs_nsvc *unknown_nsvc; + uint16_t timeout[NS_TIMERS_COUNT]; /* which link-layer are we based on? */ -- cgit v1.2.3