mirror of https://gerrit.osmocom.org/libosmocore
gprs: Don't discard SUSPEND/RESUME in bssgp_rcvmsg
Currently sending SUSPEND/RESUME messages to this function (like it is done in the osmo-sgsn) results in STATUS messages complaining about an unknown BVCI. The reason is, that these messages rely on a TLLI/RAI pair to identify the context and do not contain an explicit BVCI. This patch modifies bssgp_rcvmsg() to only complain about and unknown BVCI if one is given but a matching context is not found (except for RESET messages). The ctx argument is removed from the functions handling SUSPEND and RESUME since it will always be NULL then. Sponsored-by: On-Waves ehf
This commit is contained in:
parent
cdebf7484a
commit
b43baf20c5
|
@ -398,32 +398,32 @@ static int bssgp_rx_ul_ud(struct msgb *msg, struct tlv_parsed *tp,
|
||||||
return bssgp_prim_cb(&gbp.oph, NULL);
|
return bssgp_prim_cb(&gbp.oph, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp,
|
static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp)
|
||||||
struct bssgp_bvc_ctx *ctx)
|
|
||||||
{
|
{
|
||||||
struct osmo_bssgp_prim gbp;
|
struct osmo_bssgp_prim gbp;
|
||||||
struct gprs_ra_id raid;
|
struct gprs_ra_id raid;
|
||||||
uint32_t tlli;
|
uint32_t tlli;
|
||||||
|
uint16_t ns_bvci = msgb_bvci(msg);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) ||
|
if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) ||
|
||||||
!TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
|
!TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
|
||||||
LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u Rx SUSPEND "
|
LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u Rx SUSPEND "
|
||||||
"missing mandatory IE\n", ctx->bvci);
|
"missing mandatory IE\n", ns_bvci);
|
||||||
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
|
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
|
tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
|
||||||
|
|
||||||
DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x Rx SUSPEND\n",
|
DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x Rx SUSPEND\n",
|
||||||
ctx->bvci, tlli);
|
ns_bvci, tlli);
|
||||||
|
|
||||||
gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
|
gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
|
||||||
|
|
||||||
/* Inform GMM about the SUSPEND request */
|
/* Inform GMM about the SUSPEND request */
|
||||||
memset(&gbp, 0, sizeof(gbp));
|
memset(&gbp, 0, sizeof(gbp));
|
||||||
gbp.nsei = msgb_nsei(msg);
|
gbp.nsei = msgb_nsei(msg);
|
||||||
gbp.bvci = ctx->bvci;
|
gbp.bvci = ns_bvci;
|
||||||
gbp.tlli = tlli;
|
gbp.tlli = tlli;
|
||||||
gbp.ra_id = &raid;
|
gbp.ra_id = &raid;
|
||||||
osmo_prim_init(&gbp.oph, SAP_BSSGP_GMM, PRIM_BSSGP_GMM_SUSPEND,
|
osmo_prim_init(&gbp.oph, SAP_BSSGP_GMM, PRIM_BSSGP_GMM_SUSPEND,
|
||||||
|
@ -438,34 +438,34 @@ static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bssgp_rx_resume(struct msgb *msg, struct tlv_parsed *tp,
|
static int bssgp_rx_resume(struct msgb *msg, struct tlv_parsed *tp)
|
||||||
struct bssgp_bvc_ctx *ctx)
|
|
||||||
{
|
{
|
||||||
struct osmo_bssgp_prim gbp;
|
struct osmo_bssgp_prim gbp;
|
||||||
struct gprs_ra_id raid;
|
struct gprs_ra_id raid;
|
||||||
uint32_t tlli;
|
uint32_t tlli;
|
||||||
uint8_t suspend_ref;
|
uint8_t suspend_ref;
|
||||||
|
uint16_t ns_bvci = msgb_bvci(msg);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) ||
|
if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) ||
|
||||||
!TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA) ||
|
!TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA) ||
|
||||||
!TLVP_PRESENT(tp, BSSGP_IE_SUSPEND_REF_NR)) {
|
!TLVP_PRESENT(tp, BSSGP_IE_SUSPEND_REF_NR)) {
|
||||||
LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u Rx RESUME "
|
LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u Rx RESUME "
|
||||||
"missing mandatory IE\n", ctx->bvci);
|
"missing mandatory IE\n", ns_bvci);
|
||||||
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
|
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
|
tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
|
||||||
suspend_ref = *TLVP_VAL(tp, BSSGP_IE_SUSPEND_REF_NR);
|
suspend_ref = *TLVP_VAL(tp, BSSGP_IE_SUSPEND_REF_NR);
|
||||||
|
|
||||||
DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x Rx RESUME\n", ctx->bvci, tlli);
|
DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x Rx RESUME\n", ns_bvci, tlli);
|
||||||
|
|
||||||
gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
|
gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
|
||||||
|
|
||||||
/* Inform GMM about the RESUME request */
|
/* Inform GMM about the RESUME request */
|
||||||
memset(&gbp, 0, sizeof(gbp));
|
memset(&gbp, 0, sizeof(gbp));
|
||||||
gbp.nsei = msgb_nsei(msg);
|
gbp.nsei = msgb_nsei(msg);
|
||||||
gbp.bvci = ctx->bvci;
|
gbp.bvci = ns_bvci;
|
||||||
gbp.tlli = tlli;
|
gbp.tlli = tlli;
|
||||||
gbp.ra_id = &raid;
|
gbp.ra_id = &raid;
|
||||||
gbp.u.resume.suspend_ref = suspend_ref;
|
gbp.u.resume.suspend_ref = suspend_ref;
|
||||||
|
@ -886,23 +886,29 @@ static int bssgp_rx_sign(struct msgb *msg, struct tlv_parsed *tp,
|
||||||
uint8_t pdu_type = bgph->pdu_type;
|
uint8_t pdu_type = bgph->pdu_type;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
uint16_t ns_bvci = msgb_bvci(msg);
|
uint16_t ns_bvci = msgb_bvci(msg);
|
||||||
|
uint16_t bvci = bctx ? bctx->bvci : ns_bvci;
|
||||||
|
|
||||||
switch (bgph->pdu_type) {
|
switch (bgph->pdu_type) {
|
||||||
case BSSGP_PDUT_SUSPEND:
|
case BSSGP_PDUT_SUSPEND:
|
||||||
/* MS wants to suspend */
|
/* MS wants to suspend */
|
||||||
rc = bssgp_rx_suspend(msg, tp, bctx);
|
rc = bssgp_rx_suspend(msg, tp);
|
||||||
break;
|
break;
|
||||||
case BSSGP_PDUT_RESUME:
|
case BSSGP_PDUT_RESUME:
|
||||||
/* MS wants to resume */
|
/* MS wants to resume */
|
||||||
rc = bssgp_rx_resume(msg, tp, bctx);
|
rc = bssgp_rx_resume(msg, tp);
|
||||||
break;
|
break;
|
||||||
case BSSGP_PDUT_FLUSH_LL_ACK:
|
case BSSGP_PDUT_FLUSH_LL_ACK:
|
||||||
/* BSS informs us it has performed LL FLUSH */
|
/* BSS informs us it has performed LL FLUSH */
|
||||||
DEBUGP(DBSSGP, "BSSGP Rx BVCI=%u FLUSH LL ACK\n", bctx->bvci);
|
DEBUGP(DBSSGP, "BSSGP Rx BVCI=%u FLUSH LL ACK\n", bvci);
|
||||||
/* FIXME: send NM_FLUSH_LL.res to NM */
|
/* FIXME: send NM_FLUSH_LL.res to NM */
|
||||||
break;
|
break;
|
||||||
case BSSGP_PDUT_LLC_DISCARD:
|
case BSSGP_PDUT_LLC_DISCARD:
|
||||||
/* BSS informs that some LLC PDU's have been discarded */
|
/* BSS informs that some LLC PDU's have been discarded */
|
||||||
|
if (!bctx) {
|
||||||
|
LOGP(DBSSGP, LOGL_ERROR,
|
||||||
|
"BSSGP Rx LLC-DISCARD missing mandatory BVCI\n");
|
||||||
|
goto err_mand_ie;
|
||||||
|
}
|
||||||
rc = bssgp_rx_llc_disc(msg, tp, bctx);
|
rc = bssgp_rx_llc_disc(msg, tp, bctx);
|
||||||
break;
|
break;
|
||||||
case BSSGP_PDUT_BVC_BLOCK:
|
case BSSGP_PDUT_BVC_BLOCK:
|
||||||
|
@ -936,7 +942,7 @@ static int bssgp_rx_sign(struct msgb *msg, struct tlv_parsed *tp,
|
||||||
break;
|
break;
|
||||||
case BSSGP_PDUT_STATUS:
|
case BSSGP_PDUT_STATUS:
|
||||||
/* Some exception has occurred */
|
/* Some exception has occurred */
|
||||||
DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx BVC STATUS\n", bctx->bvci);
|
DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx BVC STATUS\n", bvci);
|
||||||
/* FIXME: send NM_STATUS.ind to NM */
|
/* FIXME: send NM_STATUS.ind to NM */
|
||||||
break;
|
break;
|
||||||
/* those only exist in the SGSN -> BSS direction */
|
/* those only exist in the SGSN -> BSS direction */
|
||||||
|
@ -951,13 +957,13 @@ static int bssgp_rx_sign(struct msgb *msg, struct tlv_parsed *tp,
|
||||||
case BSSGP_PDUT_BVC_UNBLOCK_ACK:
|
case BSSGP_PDUT_BVC_UNBLOCK_ACK:
|
||||||
case BSSGP_PDUT_SGSN_INVOKE_TRACE:
|
case BSSGP_PDUT_SGSN_INVOKE_TRACE:
|
||||||
DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx PDU type 0x%02x only exists "
|
DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx PDU type 0x%02x only exists "
|
||||||
"in DL\n", bctx->bvci, pdu_type);
|
"in DL\n", bvci, pdu_type);
|
||||||
bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg);
|
bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx PDU type 0x%02x unknown\n",
|
DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx PDU type 0x%02x unknown\n",
|
||||||
bctx->bvci, pdu_type);
|
bvci, pdu_type);
|
||||||
rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg);
|
rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -998,8 +1004,10 @@ int bssgp_rcvmsg(struct msgb *msg)
|
||||||
|
|
||||||
/* look-up or create the BTS context for this BVC */
|
/* look-up or create the BTS context for this BVC */
|
||||||
bctx = btsctx_by_bvci_nsei(bvci, msgb_nsei(msg));
|
bctx = btsctx_by_bvci_nsei(bvci, msgb_nsei(msg));
|
||||||
/* Only a RESET PDU can create a new BVC context */
|
/* Only a RESET PDU can create a new BVC context,
|
||||||
if (!bctx && pdu_type != BSSGP_PDUT_BVC_RESET) {
|
* otherwise it must be registered if a BVCI is given */
|
||||||
|
if (!bctx && bvci != BVCI_SIGNALLING &&
|
||||||
|
pdu_type != BSSGP_PDUT_BVC_RESET) {
|
||||||
LOGP(DBSSGP, LOGL_NOTICE, "NSEI=%u/BVCI=%u Rejecting PDU "
|
LOGP(DBSSGP, LOGL_NOTICE, "NSEI=%u/BVCI=%u Rejecting PDU "
|
||||||
"type %u for unknown BVCI\n", msgb_nsei(msg), bvci,
|
"type %u for unknown BVCI\n", msgb_nsei(msg), bvci,
|
||||||
pdu_type);
|
pdu_type);
|
||||||
|
|
|
@ -116,10 +116,10 @@ static void test_bssgp_suspend_resume(void)
|
||||||
memset(&last_oph, 0, sizeof(last_oph));
|
memset(&last_oph, 0, sizeof(last_oph));
|
||||||
|
|
||||||
send_bssgp_supend(BSSGP_PDUT_SUSPEND, tlli);
|
send_bssgp_supend(BSSGP_PDUT_SUSPEND, tlli);
|
||||||
/* OSMO_ASSERT(last_oph.primitive == PRIM_BSSGP_GMM_SUSPEND); */
|
OSMO_ASSERT(last_oph.primitive == PRIM_BSSGP_GMM_SUSPEND);
|
||||||
|
|
||||||
send_bssgp_resume(BSSGP_PDUT_RESUME, tlli);
|
send_bssgp_resume(BSSGP_PDUT_RESUME, tlli);
|
||||||
/* OSMO_ASSERT(last_oph.primitive == PRIM_BSSGP_GMM_RESUME); */
|
OSMO_ASSERT(last_oph.primitive == PRIM_BSSGP_GMM_RESUME);
|
||||||
|
|
||||||
printf("----- %s END\n", __func__);
|
printf("----- %s END\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
===== BSSGP test START
|
===== BSSGP test START
|
||||||
----- test_bssgp_suspend_resume START
|
----- test_bssgp_suspend_resume START
|
||||||
|
BSSGP primitive, SAP 16777219, prim = 3, op = 0, msg = 0b 1f 84 f0 12 34 56 1b 86 0f f1 80 20 37 00
|
||||||
|
BSSGP primitive, SAP 16777219, prim = 4, op = 0, msg = 0e 1f 84 f0 12 34 56 1b 86 0f f1 80 20 37 00 1d 81 01
|
||||||
----- test_bssgp_suspend_resume END
|
----- test_bssgp_suspend_resume END
|
||||||
===== BSSGP test END
|
===== BSSGP test END
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue