From 9e917647aef4679b6fd6eabbe77651bb50b60da8 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 12 Dec 2020 19:02:16 +0100 Subject: gbproxy: Implement scaling of BVC flow control in SGSN pool When there are multiple SGSNs inside a pool, we need to decide how much of the per-BVC capacity advertised by the BSS in its BVC-FLOW-CONTROL we should announce to each of the pool members. A conservative approach would be to advertise 1/num_sgsn, but there may also be use case where over-provisioning (announcing more than an equal share of the capacity) is useful. Hence, let's introduce "pool bvc-flow-control-ratio <1-100>" in order to allow the administrator to decide. Related: OS#4891 Change-Id: Ibe5addf657e7237499ca0205bacfe999ecd1e771 --- doc/manuals/chapters/gbproxy-configuration.adoc | 26 +++++++++++++++++++++++++ include/osmocom/sgsn/gb_proxy.h | 5 +++++ src/gbproxy/gb_proxy.c | 22 ++++++++++++++++++--- src/gbproxy/gb_proxy_vty.c | 15 ++++++++++++++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/doc/manuals/chapters/gbproxy-configuration.adoc b/doc/manuals/chapters/gbproxy-configuration.adoc index 599b3f7ba..e61af48b4 100644 --- a/doc/manuals/chapters/gbproxy-configuration.adoc +++ b/doc/manuals/chapters/gbproxy-configuration.adoc @@ -4,3 +4,29 @@ TBD. Unfortunately this chapter of the manual still needs to be written. Osmocom has very limited funding and support resources; Feel free to help us completing this documentation by contributing with code, documentation or by supporting the developers financially. + + +=== SGSN pool support + +In a SGSN pool, osmo-gbproxy is facing the problem of dividing the downlink +capacity of a cell towards the SGSN. The BSS advertises the per-BVC capacity +by means of the BSSGP FLOW-CONTROL-BVC messages, but as there are multiple +SGSN in a pool, they all have to share / divide that total capacity. + +By default, osmo-gbproxy advertises the full capacity to _each_ of the SGSN +pool members, which results in significant over-provisioning and can lead to +overload situations. + +The administrator can configure the _percentage_ of the overall BSS-advertised +capacity that shall be reported to each pool member SGSN using the +`pool bvc-flow-control-ratio <1-100>` configuration command. + +A setting of 100 means that each pool member is informed of 100% of the +BSS side capacity. + +A setting of 25 means that each pool member is informed of 25% of the +BSS side capacity. This would make most sense in a set-up with four +SGSN of equal share. + +More complex capacity division schemes are so far not supported by +osmo-gbproxy. diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h index 8892cf4df..200a539e6 100644 --- a/include/osmocom/sgsn/gb_proxy.h +++ b/include/osmocom/sgsn/gb_proxy.h @@ -52,6 +52,11 @@ struct gbproxy_config { /* NS instance of libosmogb */ struct gprs_ns2_inst *nsi; + struct { + /* percentage of BVC flow control advertised to each SGSN in the pool */ + uint8_t bvc_fc_ratio; + } pool; + /* Linked list of all BSS side Gb peers */ DECLARE_HASHTABLE(bss_nses, 8); diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c index a976d252f..53aecdf04 100644 --- a/src/gbproxy/gb_proxy.c +++ b/src/gbproxy/gb_proxy.c @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -566,15 +567,28 @@ static void bss_ptp_bvc_state_chg_notif(uint16_t nsei, uint16_t bvci, int old_st /* BVC FSM informs us about BVC-FC PDU receive */ static void bss_ptp_bvc_fc_bvc(uint16_t nsei, uint16_t bvci, const struct bssgp2_flow_ctrl *fc, void *priv) { + struct bssgp2_flow_ctrl fc_reduced; struct gbproxy_bvc *bss_bvc = priv; - struct gbproxy_cell *cell = bss_bvc->cell; + struct gbproxy_cell *cell; + struct gbproxy_config *cfg; + OSMO_ASSERT(bss_bvc); + OSMO_ASSERT(fc); + + cell = bss_bvc->cell; if (!cell) return; - /* FIXME: actually split the bandwidth among the SGSNs! */ + cfg = cell->cfg; + + /* reduce / scale according to configuration to make sure we only advertise a fraction + * of the capacity to each of the SGSNs in the pool */ + fc_reduced = *fc; + fc_reduced.bucket_size_max = (fc->bucket_size_max * cfg->pool.bvc_fc_ratio) / 100; + fc_reduced.bucket_leak_rate = (fc->bucket_leak_rate * cfg->pool.bvc_fc_ratio) / 100; + /* we don't modify the per-MS related values as any single MS is only served by one SGSN */ - dispatch_to_all_sgsn_bvc(cell, BSSGP_BVCFSM_E_REQ_FC_BVC, (void *) fc); + dispatch_to_all_sgsn_bvc(cell, BSSGP_BVCFSM_E_REQ_FC_BVC, (void *) &fc_reduced); } static const struct bssgp_bvc_fsm_ops bss_ptp_bvc_fsm_ops = { @@ -1270,6 +1284,8 @@ int gbproxy_init_config(struct gbproxy_config *cfg) { struct timespec tp; + /* by default we advertise 100% of the BSS-side capacity to _each_ SGSN */ + cfg->pool.bvc_fc_ratio = 100; hash_init(cfg->bss_nses); cfg->ctrg = rate_ctr_group_alloc(tall_sgsn_ctx, &global_ctrg_desc, 0); if (!cfg->ctrg) { diff --git a/src/gbproxy/gb_proxy_vty.c b/src/gbproxy/gb_proxy_vty.c index a9db596df..49ec91c95 100644 --- a/src/gbproxy/gb_proxy_vty.c +++ b/src/gbproxy/gb_proxy_vty.c @@ -76,6 +76,9 @@ static int config_write_gbproxy(struct vty *vty) vty_out(vty, "gbproxy%s", VTY_NEWLINE); + if (g_cfg->pool.bvc_fc_ratio != 100) + vty_out(vty, " pool bvc-flow-control-ratio %u%s", g_cfg->pool.bvc_fc_ratio, VTY_NEWLINE); + hash_for_each(g_cfg->sgsn_nses, i, nse, list) { vty_out(vty, " sgsn nsei %u%s", nse->nsei, VTY_NEWLINE); } @@ -134,6 +137,17 @@ free_nothing: return CMD_WARNING; } +DEFUN(cfg_pool_bvc_fc_ratio, + cfg_pool_bvc_fc_ratio_cmd, + "pool bvc-flow-control-ratio <1-100>", + "SGSN Pool related configuration\n" + "Ratio of BSS-advertised bucket size + leak rate advertised to each SGSN\n" + "Ratio of BSS-advertised bucket size + leak rate advertised to each SGSN (Percent)\n") +{ + g_cfg->pool.bvc_fc_ratio = atoi(argv[0]); + return CMD_SUCCESS; +} + static void log_set_bvc_filter(struct log_target *target, const uint16_t *bvci) { @@ -315,6 +329,7 @@ int gbproxy_vty_init(void) install_element(CONFIG_NODE, &cfg_gbproxy_cmd); install_node(&gbproxy_node, config_write_gbproxy); install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd); + install_element(GBPROXY_NODE, &cfg_pool_bvc_fc_ratio_cmd); return 0; } -- cgit v1.2.3