From c1c57d3a26c84c3f7eaca1b847c01ed0dcc6e473 Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Thu, 28 Aug 2014 13:20:39 +0200 Subject: gbproxy: Copy uplink messages to SGSN 2 Some messages that are related to the BVC itself must be forwarded to the secondary SGSN, too. This patch implements this for BVC-RESET (BVCI != 0) and FLOW-CONTROL-BVC messages. The resulting acknowledgement messages from the secondary SGSN are silently dropped. The idea behind this is that the primary SGSN is responsible for setting up and maintaining the BVC whereas the secondary SGSN is rather passive and just has to accept it. Ticket: OW#1258 Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'openbsc/src/gprs/gb_proxy.c') 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; -- cgit v1.2.3