summaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/gprs_ns.h3
-rw-r--r--openbsc/src/gprs_bssgp.c34
-rw-r--r--openbsc/src/gprs_ns.c61
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;