diff options
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/gprs_ns.h | 3 | ||||
-rw-r--r-- | openbsc/src/gprs_bssgp.c | 34 | ||||
-rw-r--r-- | openbsc/src/gprs_ns.c | 61 |
3 files changed, 64 insertions, 34 deletions
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 diff --git a/openbsc/src/gprs_bssgp.c b/openbsc/src/gprs_bssgp.c index b4436294..650d7d45 100644 --- a/openbsc/src/gprs_bssgp.c +++ b/openbsc/src/gprs_bssgp.c @@ -37,6 +37,7 @@ /* global pointer to the gsm network data structure */ /* FIXME: this must go! */ extern struct gsm_network *bsc_gsmnet; +struct gprs_ns_inst *bssgp_nsi; /* Chapter 11.3.9 / Table 11.10: Cause coding */ static const char *bssgp_cause_strings[] = { @@ -84,31 +85,38 @@ static inline struct msgb *bssgp_msgb_alloc(void) } /* Transmit a simple response such as BLOCK/UNBLOCK/RESET ACK/NACK */ -static int bssgp_tx_simple_bvci(u_int8_t pdu_type, u_int16_t bvci, u_int16_t ns_bvci) +static int bssgp_tx_simple_bvci(u_int8_t pdu_type, u_int16_t nsei, + u_int16_t bvci, u_int16_t ns_bvci) { struct msgb *msg = bssgp_msgb_alloc(); struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph)); u_int16_t _bvci; + msgb_nsei(msg) = nsei; + msgb_bvci(msg) = ns_bvci; + bgph->pdu_type = pdu_type; _bvci = htons(bvci); msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (u_int8_t *) &_bvci); - return gprs_ns_sendmsg(NULL, ns_bvci, msg); + return gprs_ns_sendmsg(bssgp_nsi, msg); } /* Chapter 10.4.5: Flow Control BVC ACK */ -static int bssgp_tx_fc_bvc_ack(u_int8_t tag, u_int16_t ns_bvci) +static int bssgp_tx_fc_bvc_ack(u_int16_t nsei, u_int8_t tag, u_int16_t ns_bvci) { struct msgb *msg = bssgp_msgb_alloc(); struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph)); + msgb_nsei(msg) = nsei; + msgb_bvci(msg) = ns_bvci; + bgph->pdu_type = BSSGP_PDUT_FLOW_CONTROL_BVC_ACK; msgb_tvlv_put(msg, BSSGP_IE_TAG, 1, &tag); - return gprs_ns_sendmsg(NULL, ns_bvci, msg); + return gprs_ns_sendmsg(bssgp_nsi, msg); } /* Chapter 10.4.14: Status */ @@ -119,6 +127,8 @@ static int bssgp_tx_status(u_int8_t cause, u_int16_t *bvci, struct msgb *orig_ms (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph)); DEBUGPC(DGPRS, "BSSGP: TX STATUS, cause=%s\n", bssgp_cause_str(cause)); + msgb_nsei(msg) = msgb_nsei(orig_msg); + msgb_bvci(msg) = 0; bgph->pdu_type = BSSGP_PDUT_STATUS; msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause); @@ -130,7 +140,7 @@ static int bssgp_tx_status(u_int8_t cause, u_int16_t *bvci, struct msgb *orig_ms msgb_tvlv_put(msg, BSSGP_IE_PDU_IN_ERROR, msgb_l3len(orig_msg), orig_msg->l3h); - return gprs_ns_sendmsg(NULL, 0, msg); + return gprs_ns_sendmsg(bssgp_nsi, msg); } /* Uplink unit-data */ @@ -221,7 +231,8 @@ static int bssgp_rx_fc_bvc(struct msgb *msg, struct tlv_parsed *tp, return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); /* Send FLOW_CONTROL_BVC_ACK */ - return bssgp_tx_fc_bvc_ack(*TLVP_VAL(tp, BSSGP_IE_TAG), ns_bvci); + return bssgp_tx_fc_bvc_ack(msgb_nsei(msg), *TLVP_VAL(tp, BSSGP_IE_TAG), + ns_bvci); } /* We expect msg->l3h to point to the BSSGP header */ int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci) @@ -287,7 +298,7 @@ int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci) DEBUGPC(DGPRS, "BVCI=%u, cause=%s\n", bvci, bssgp_cause_str(*TLVP_VAL(&tp, BSSGP_IE_CAUSE))); rc = bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK_ACK, - bvci, ns_bvci); + msgb_nsei(msg), bvci, ns_bvci); break; case BSSGP_PDUT_BVC_UNBLOCK: /* BSS tells us that BVC shall be unblocked */ @@ -297,7 +308,7 @@ int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci) bvci = ntohs(*(u_int16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI)); DEBUGPC(DGPRS, "BVCI=%u\n", bvci); rc = bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_UNBLOCK_ACK, - bvci, ns_bvci); + msgb_nsei(msg), bvci, ns_bvci); break; case BSSGP_PDUT_BVC_RESET: /* BSS tells us that BVC init is required */ @@ -309,7 +320,7 @@ int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci) DEBUGPC(DGPRS, "BVCI=%u, cause=%s\n", bvci, bssgp_cause_str(*TLVP_VAL(&tp, BSSGP_IE_CAUSE))); rc = bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_RESET_ACK, - bvci, ns_bvci); + msgb_nsei(msg), bvci, ns_bvci); break; case BSSGP_PDUT_STATUS: /* Some exception has occurred */ @@ -393,5 +404,8 @@ int gprs_bssgp_tx_dl_ud(struct msgb *msg) budh->tlli = htonl(msgb_tlli(msg)); budh->pdu_type = BSSGP_PDUT_DL_UNITDATA; - return gprs_ns_sendmsg(NULL, bts->gprs.cell.bvci, msg); + msgb_nsei(msg) = bts->gprs.nse.nsei; + msgb_bvci(msg) = bts->gprs.cell.bvci; + + return gprs_ns_sendmsg(bssgp_nsi, msg); } diff --git a/openbsc/src/gprs_ns.c b/openbsc/src/gprs_ns.c index b57de1d7..6c495b01 100644 --- a/openbsc/src/gprs_ns.c +++ b/openbsc/src/gprs_ns.c @@ -1,4 +1,4 @@ -/* GPRS Networks Service (NS) messages on the Gb interface +/* GPRS Networks Service (NS) messages on the Gb interfacebvci = msgb_bvci(msg); * 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05) */ /* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> @@ -132,6 +132,19 @@ static struct gprs_nsvc *nsvc_by_nsvci(struct gprs_ns_inst *nsi, return NULL; } +/* Lookup struct gprs_nsvc based on NSVCI */ +static struct gprs_nsvc *nsvc_by_nsei(struct gprs_ns_inst *nsi, + u_int16_t nsei) +{ + struct gprs_nsvc *nsvc; + llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + if (nsvc->nsei == nsei) + return nsvc; + } + return NULL; +} + + /* Lookup struct gprs_nsvc based on remote peer socket addr */ static struct gprs_nsvc *nsvc_by_rem_addr(struct gprs_ns_inst *nsi, struct sockaddr_in *sin) @@ -184,15 +197,15 @@ static const char *gprs_ns_cause_str(enum ns_cause cause) return "undefined"; } -static int nsip_sendmsg(struct msgb *msg, struct gprs_nsvc *nsvc); +static int nsip_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg); -static int gprs_ns_tx(struct msgb *msg, struct gprs_nsvc *nsvc) +static int gprs_ns_tx(struct gprs_nsvc *nsvc, struct msgb *msg) { int ret; switch (nsvc->nsi->ll) { case GPRS_NS_LL_UDP: - ret = nsip_sendmsg(msg, nsvc); + ret = nsip_sendmsg(nsvc, msg); break; default: LOGP(DGPRS, LOGL_ERROR, "unsupported NS linklayer %u\n", nsvc->nsi->ll); @@ -215,7 +228,7 @@ static int gprs_ns_tx_simple(struct gprs_nsvc *nsvc, u_int8_t pdu_type) nsh->pdu_type = pdu_type; - return gprs_ns_tx(msg, nsvc); + return gprs_ns_tx(nsvc, msg); } #define NS_TIMER_ALIVE 3, 0 /* after 3 seconds without response, we retry */ @@ -268,14 +281,21 @@ static int gprs_ns_tx_reset_ack(struct gprs_nsvc *nsvc) msgb_tvlv_put(msg, NS_IE_VCI, 2, (u_int8_t *)&nsvci); msgb_tvlv_put(msg, NS_IE_NSEI, 2, (u_int8_t *)&nsei); - return gprs_ns_tx(msg, nsvc); + return gprs_ns_tx(nsvc, msg); } -/* Section 9.2.10: transmit side */ -int gprs_ns_sendmsg(struct gprs_nsvc *nsvc, u_int16_t bvci, - struct msgb *msg) +/* Section 9.2.10: transmit side / NS-UNITDATA-REQUEST primitive */ +int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) { + struct gprs_nsvc *nsvc; struct gprs_ns_hdr *nsh; + u_int16_t bvci = msgb_bvci(msg); + + nsvc = nsvc_by_nsei(nsi, msgb_nsei(msg)); + if (!nsvc) { + DEBUGP(DGPRS, "Unable to resolve NSEI %u to NS-VC!\n", msgb_nsei(msg)); + return -EINVAL; + } nsh = (struct gprs_ns_hdr *) msgb_push(msg, sizeof(*nsh) + 3); if (!nsh) { @@ -288,14 +308,13 @@ int gprs_ns_sendmsg(struct gprs_nsvc *nsvc, u_int16_t bvci, nsh->data[1] = bvci >> 8; nsh->data[2] = bvci & 0xff; - return gprs_ns_tx(msg, nsvc); + return gprs_ns_tx(nsvc, msg); } /* Section 9.2.10: receive side */ -static int gprs_ns_rx_unitdata(struct msgb *msg) +static int gprs_ns_rx_unitdata(struct gprs_nsvc *nsvc, struct msgb *msg) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *)msg->l2h; - struct gprs_nsvc *nsvc = msgb_nsvc(msg); u_int16_t bvci; /* spare octet in data[0] */ @@ -307,10 +326,9 @@ static int gprs_ns_rx_unitdata(struct msgb *msg) } /* Section 9.2.7 */ -static int gprs_ns_rx_status(struct msgb *msg) +static int gprs_ns_rx_status(struct gprs_nsvc *nsvc, struct msgb *msg) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; - struct gprs_nsvc *nsvc = msgb_nsvc(msg); struct tlv_parsed tp; u_int8_t cause; int rc; @@ -331,10 +349,9 @@ static int gprs_ns_rx_status(struct msgb *msg) } /* Section 7.3 */ -static int gprs_ns_rx_reset(struct msgb *msg) +static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; - struct gprs_nsvc *nsvc = msgb_nsvc(msg); struct tlv_parsed tp; u_int8_t *cause; u_int16_t *nsvci, *nsei; @@ -388,10 +405,10 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, return -EIO; nsvc = nsvc_create(nsi, 0xffff); nsvc->ip.bts_addr = *saddr; - rc = gprs_ns_rx_reset(msg); + rc = gprs_ns_rx_reset(nsvc, msg); return rc; } - msgb_nsvc(msg) = nsvc; + msgb_nsei(msg) = nsvc->nsei; switch (nsh->pdu_type) { case NS_PDUT_ALIVE: @@ -408,13 +425,13 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, break; case NS_PDUT_UNITDATA: /* actual user data */ - rc = gprs_ns_rx_unitdata(msg); + rc = gprs_ns_rx_unitdata(nsvc, msg); break; case NS_PDUT_STATUS: - rc = gprs_ns_rx_status(msg); + rc = gprs_ns_rx_status(nsvc, msg); break; case NS_PDUT_RESET: - rc = gprs_ns_rx_reset(msg); + rc = gprs_ns_rx_reset(nsvc, msg); break; case NS_PDUT_RESET_ACK: DEBUGP(DGPRS, "NS RESET ACK\n"); @@ -523,7 +540,7 @@ static int handle_nsip_write(struct bsc_fd *bfd) return -EIO; } -int nsip_sendmsg(struct msgb *msg, struct gprs_nsvc *nsvc) +int nsip_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg) { int rc; struct gprs_ns_inst *nsi = nsvc->nsi; |