diff options
Diffstat (limited to 'openbsc/src/gprs/gb_proxy.c')
-rw-r--r-- | openbsc/src/gprs/gb_proxy.c | 42 |
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; |