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.
This commit is contained in:
Harald Welte 2010-04-30 19:54:29 +02:00
parent 645609ddc8
commit 24a655f140
3 changed files with 64 additions and 34 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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;