From 36f98d9c53e92a19b99a678ae7d713ef0055a8d5 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 6 Feb 2011 13:09:29 +0100 Subject: [gb_proxy] Track the state of blocked/unblocked BVC in the proxy This allows us to reject any additional messages sent by the SGSN after the BVC was blocked (+ acknowledged to be blocked) --- openbsc/src/gprs/gb_proxy.c | 72 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 13 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 934ceef68..19f6cbff2 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -47,6 +47,7 @@ struct gbprox_peer { /* BVCI used for Point-to-Point to this peer */ uint16_t bvci; + int blocked; /* Routeing Area that this peer is part of (raw 04.08 encoding) */ uint8_t ra[6]; @@ -202,6 +203,30 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, return gprs_ns_sendmsg(bssgp_nsi, msg); } +static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) +{ + struct gbprox_peer *peer; + + peer = peer_by_bvci(ptp_bvci); + if (!peer) { + LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", + ptp_bvci); + return -ENOENT; + } + + switch (pdu_type) { + case BSSGP_PDUT_BVC_BLOCK_ACK: + peer->blocked = 1; + break; + case BSSGP_PDUT_BVC_UNBLOCK_ACK: + peer->blocked = 0; + break; + default: + break; + } + return 0; +} + /* Send a message to a peer identified by ptp_bvci but using ns_bvci * in the NS hdr */ static int gbprox_relay2bvci(struct msgb *msg, uint16_t ptp_bvci, @@ -428,8 +453,6 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, rc = rx_reset_from_sgsn(msg, &tp, nsvc, ns_bvci); break; case BSSGP_PDUT_FLUSH_LL: - case BSSGP_PDUT_BVC_BLOCK_ACK: - case BSSGP_PDUT_BVC_UNBLOCK_ACK: case BSSGP_PDUT_BVC_RESET_ACK: /* simple case: BVCI IE is mandatory */ if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) @@ -474,6 +497,22 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, goto err_no_peer; rc = gbprox_relay2peer(msg, peer, ns_bvci); break; + case BSSGP_PDUT_BVC_BLOCK_ACK: + case BSSGP_PDUT_BVC_UNBLOCK_ACK: + if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) + goto err_mand_ie; + bvci = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI)); + if (bvci == 0) { + LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) BSSGP " + "%sBLOCK_ACK for signalling BVCI ?!?\n", nsvc->nsei, + pdu_type == BSSGP_PDUT_BVC_UNBLOCK_ACK ? "UN":""); + /* should we send STATUS ? */ + } else { + /* Mark BVC as (un)blocked */ + block_unblock_peer(bvci, pdu_type); + } + rc = gbprox_relay2bvci(msg, bvci, ns_bvci); + break; case BSSGP_PDUT_SGSN_INVOKE_TRACE: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsvc->nsei); @@ -501,6 +540,7 @@ err_no_peer: int gbprox_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci) { int rc; + struct gbprox_peer *peer; /* Only BVCI=0 messages need special treatment */ if (ns_bvci == 0 || ns_bvci == 1) { @@ -511,18 +551,24 @@ int gbprox_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci) } else { /* All other BVCI are PTP and thus can be simply forwarded */ if (!nsvc->remote_end_is_sgsn) { - rc = gbprox_relay2sgsn(msg, ns_bvci); - } else { - struct gbprox_peer *peer = peer_by_bvci(ns_bvci); - if (!peer) { - LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " - "BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, - nsvc->nsvci, nsvc->nsei); - peer = peer_alloc(ns_bvci); - peer->nsvc = nsvc; - } - rc = gbprox_relay2peer(msg, peer, ns_bvci); + return gbprox_relay2sgsn(msg, ns_bvci); + } + /* else: SGSN -> BSS direction */ + peer = peer_by_bvci(ns_bvci); + if (!peer) { + LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " + "BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, + nsvc->nsvci, nsvc->nsei); + peer = peer_alloc(ns_bvci); + peer->nsvc = nsvc; } + if (peer->blocked) { + LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for " + "blocked BVCI=%u via NSVC=%u/NSEI=%u\n", + ns_bvci, nsvc->nsvci, nsvc->nsei); + return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, NULL, msg); + } + rc = gbprox_relay2peer(msg, peer, ns_bvci); } return rc; -- cgit v1.2.3