From 3771d09ec01581e50253dce4dc5ec0abba9a1e35 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 30 Apr 2010 20:26:32 +0200 Subject: [PATCH] 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 ++++++++++++++++++++++- openbsc/src/gprs_bssgp.c | 7 +---- openbsc/src/gprs_ns.c | 47 +++++++++++++--------------- 4 files changed, 71 insertions(+), 32 deletions(-) diff --git a/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h index f85ac48ec..3040e6a0e 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 34a3e581f..dd10d3339 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 diff --git a/openbsc/src/gprs_bssgp.c b/openbsc/src/gprs_bssgp.c index 650d7d45d..a2181b124 100644 --- a/openbsc/src/gprs_bssgp.c +++ b/openbsc/src/gprs_bssgp.c @@ -74,11 +74,6 @@ static const char *bssgp_cause_str(enum gprs_bssgp_cause cause) return "undefined"; } -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); -} - static inline struct msgb *bssgp_msgb_alloc(void) { return msgb_alloc_headroom(4096, 128, "BSSGP"); @@ -120,7 +115,7 @@ static int bssgp_tx_fc_bvc_ack(u_int16_t nsei, u_int8_t tag, u_int16_t ns_bvci) } /* Chapter 10.4.14: Status */ -static int bssgp_tx_status(u_int8_t cause, u_int16_t *bvci, struct msgb *orig_msg) +int bssgp_tx_status(u_int8_t cause, u_int16_t *bvci, struct msgb *orig_msg) { struct msgb *msg = bssgp_msgb_alloc(); struct bssgp_normal_hdr *bgph = diff --git a/openbsc/src/gprs_ns.c b/openbsc/src/gprs_ns.c index 6c495b01e..3bb0bf94d 100644 --- a/openbsc/src/gprs_ns.c +++ b/openbsc/src/gprs_ns.c @@ -72,30 +72,6 @@ static const struct tlv_definition ns_att_tlvdef = { }, }; -#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; - - union { - struct { - struct sockaddr_in bts_addr; - } ip; - }; -}; - enum gprs_ns_ll { GPRS_NS_LL_UDP, GPRS_NS_LL_E1, @@ -474,7 +450,7 @@ struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb) nsi->cb = cb; INIT_LLIST_HEAD(&nsi->gprs_nsvcs); - return NULL; + return nsi; } void gprs_ns_destroy(struct gprs_ns_inst *nsi) @@ -586,3 +562,24 @@ int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port) return ret; } + +/* 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 gprs_nsvc *nsvc; + + nsvc = nsvc_by_rem_addr(nsi, dest); + if (!nsvc) { + nsvc = nsvc_create(nsi, nsvci); + nsvc->ip.bts_addr = *dest; + } + nsvc->remote_end_is_sgsn = 1; + + /* Initiate a RESET procedure */ + if (gprs_ns_tx_simple(nsvc, NS_PDUT_RESET) < 0) + return NULL; + /* FIXME: should we run a timer and re-transmit the reset request? */ + + return nsvc; +}