aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gb_proxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/gprs/gb_proxy.c')
-rw-r--r--openbsc/src/gprs/gb_proxy.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index 6e93e1493..2026d1a03 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -614,6 +614,8 @@ static int gbprox_rx_ptp_from_bss(struct gbproxy_config *cfg,
uint16_t nsvci, uint16_t ns_bvci)
{
struct gbproxy_peer *peer;
+ struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
+ uint8_t pdu_type = bgph->pdu_type;
int rc;
peer = gbproxy_peer_by_bvci(cfg, ns_bvci);
@@ -625,6 +627,19 @@ static int gbprox_rx_ptp_from_bss(struct gbproxy_config *cfg,
if (!rc)
return 0;
+ switch (pdu_type) {
+ case BSSGP_PDUT_FLOW_CONTROL_BVC:
+ if (!cfg->route_to_sgsn2)
+ break;
+
+ /* Send a copy to the secondary SGSN */
+ gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn2_nsei);
+ break;
+ default:
+ break;
+ }
+
+
return gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn_nsei);
}
@@ -634,6 +649,8 @@ static int gbprox_rx_ptp_from_sgsn(struct gbproxy_config *cfg,
uint16_t nsvci, uint16_t ns_bvci)
{
struct gbproxy_peer *peer;
+ struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
+ uint8_t pdu_type = bgph->pdu_type;
peer = gbproxy_peer_by_bvci(cfg, ns_bvci);
@@ -657,6 +674,19 @@ static int gbprox_rx_ptp_from_sgsn(struct gbproxy_config *cfg,
return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, NULL, msg);
}
+ switch (pdu_type) {
+ case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK:
+ case BSSGP_PDUT_BVC_BLOCK_ACK:
+ case BSSGP_PDUT_BVC_UNBLOCK_ACK:
+ if (cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei)
+ /* Hide ACKs from the secondary SGSN, the primary SGSN
+ * is responsible to send them. */
+ return 0;
+ break;
+ default:
+ break;
+ }
+
/* Optionally patch the message */
gbprox_process_bssgp_dl(cfg, msg, peer);
@@ -674,6 +704,7 @@ static int gbprox_rx_sig_from_bss(struct gbproxy_config *cfg,
int data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
struct gbproxy_peer *from_peer = NULL;
struct gprs_ra_id raid;
+ int copy_to_sgsn2 = 0;
int rc;
if (ns_bvci != 0 && ns_bvci != 1) {
@@ -758,6 +789,8 @@ static int gbprox_rx_sig_from_bss(struct gbproxy_config *cfg,
bvci, raid.mcc, raid.mnc, raid.lac,
raid.rac);
}
+ if (cfg->route_to_sgsn2)
+ copy_to_sgsn2 = 1;
}
break;
}
@@ -767,6 +800,10 @@ static int gbprox_rx_sig_from_bss(struct gbproxy_config *cfg,
rc = gbprox_process_bssgp_ul(cfg, msg, from_peer);
if (!rc)
return 0;
+
+ if (copy_to_sgsn2)
+ gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn2_nsei);
+
return gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn_nsei);
err_no_peer:
LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n",
@@ -900,8 +937,11 @@ static int gbprox_rx_sig_from_sgsn(struct gbproxy_config *cfg,
case BSSGP_PDUT_BVC_RESET:
rc = rx_reset_from_sgsn(cfg, msg, orig_msg, &tp, nsei, ns_bvci);
break;
- case BSSGP_PDUT_FLUSH_LL:
case BSSGP_PDUT_BVC_RESET_ACK:
+ if (cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei)
+ break;
+ /* fall through */
+ case BSSGP_PDUT_FLUSH_LL:
/* simple case: BVCI IE is mandatory */
if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI))
goto err_mand_ie;