aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2020-12-05 00:31:07 +0100
committerHarald Welte <laforge@osmocom.org>2020-12-05 13:49:37 +0100
commit78db244b42be1e2bf9726cb2d80150876c70dedc (patch)
treebd726b8a33fdf6d2249492774c1e0c24d4815888 /src
parent0e1b791c818181f5b95aa55d71d6b2469fb95475 (diff)
gbproxy: convert bss_nses from llist_head to hashtable
For the common lookup-by-nsei, this should reduce the computational complexity significantly. Depends: libosmocore.git I8ef73a62fe9846ce45058eb21cf999dd3eed5741 Change-Id: Idbb6a362332bb6e3ce22102e7409ae80d0980f44
Diffstat (limited to 'src')
-rw-r--r--src/gbproxy/gb_proxy.c22
-rw-r--r--src/gbproxy/gb_proxy_ctrl.c9
-rw-r--r--src/gbproxy/gb_proxy_peer.c35
-rw-r--r--src/gbproxy/gb_proxy_vty.c15
4 files changed, 50 insertions, 31 deletions
diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c
index 4c34941f..c37b21ad 100644
--- a/src/gbproxy/gb_proxy.c
+++ b/src/gbproxy/gb_proxy.c
@@ -31,6 +31,7 @@
#include <arpa/inet.h>
#include <time.h>
+#include <osmocom/core/hashtable.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
@@ -1183,6 +1184,7 @@ static int gbprox_rx_paging(struct gbproxy_config *cfg, struct msgb *msg, struct
struct gbproxy_bvc *bvc;
unsigned int n_nses = 0;
int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN;
+ int i;
/* FIXME: Handle paging logic to only page each matching NSE */
@@ -1203,7 +1205,7 @@ static int gbprox_rx_paging(struct gbproxy_config *cfg, struct msgb *msg, struct
} else if (TLVP_PRES_LEN(tp, BSSGP_IE_ROUTEING_AREA, 6)) {
errctr = GBPROX_GLOB_CTR_INV_RAI;
/* iterate over all bvcs and dispatch the paging to each matching one */
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
llist_for_each_entry(bvc, &nse->bvcs, list) {
if (!memcmp(bvc->ra, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA), 6)) {
LOGPNSE(nse, LOGL_INFO, "routing to NSE (RAI match)\n");
@@ -1217,7 +1219,7 @@ static int gbprox_rx_paging(struct gbproxy_config *cfg, struct msgb *msg, struct
} else if (TLVP_PRES_LEN(tp, BSSGP_IE_LOCATION_AREA, 5)) {
errctr = GBPROX_GLOB_CTR_INV_LAI;
/* iterate over all bvcs and dispatch the paging to each matching one */
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
llist_for_each_entry(bvc, &nse->bvcs, list) {
if (!memcmp(bvc->ra, TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA), 5)) {
LOGPNSE(nse, LOGL_INFO, "routing to NSE (LAI match)\n");
@@ -1230,7 +1232,7 @@ static int gbprox_rx_paging(struct gbproxy_config *cfg, struct msgb *msg, struct
}
} else if (TLVP_PRES_LEN(tp, BSSGP_IE_BSS_AREA_ID, 1)) {
/* iterate over all bvcs and dispatch the paging to each matching one */
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
llist_for_each_entry(bvc, &nse->bvcs, list) {
LOGPNSE(nse, LOGL_INFO, "routing to NSE (broadcast)\n");
gbprox_relay2nse(msg, nse, ns_bvci);
@@ -1263,6 +1265,7 @@ static int rx_reset_from_sgsn(struct gbproxy_config *cfg,
struct gbproxy_nse *nse;
struct gbproxy_bvc *bvc;
uint16_t ptp_bvci;
+ int i;
if (!TLVP_PRES_LEN(tp, BSSGP_IE_BVCI, 2)) {
rate_ctr_inc(&cfg->ctrg->
@@ -1291,7 +1294,7 @@ static int rx_reset_from_sgsn(struct gbproxy_config *cfg,
* from the SGSN. As the signalling BVCI is shared
* among all the BSS's that we multiplex, it needs to
* be relayed */
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
llist_for_each_entry(bvc, &nse->bvcs, list)
gbprox_relay2peer(msg, bvc, ns_bvci);
}
@@ -1315,6 +1318,7 @@ static int gbprox_rx_sig_from_sgsn(struct gbproxy_config *cfg,
struct msgb *msg;
int rc = 0;
int cause;
+ int i;
if (ns_bvci != 0 && ns_bvci != 1) {
LOGP(DGPRS, LOGL_NOTICE, "NSE(%05u/SGSN) BVCI=%05u is not "
@@ -1425,7 +1429,7 @@ static int gbprox_rx_sig_from_sgsn(struct gbproxy_config *cfg,
LOGP(DGPRS, LOGL_DEBUG,
"NSE(%05u/SGSN) BSSGP %s: broadcasting\n", nsei, bssgp_pdu_str(pdu_type));
/* broadcast to all BSS-side bvcs */
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
gbprox_relay2nse(msg, nse, 0);
}
break;
@@ -1618,9 +1622,11 @@ int gprs_ns2_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
void gbprox_reset(struct gbproxy_config *cfg)
{
- struct gbproxy_nse *nse, *ntmp;
+ struct gbproxy_nse *nse;
+ struct hlist_node *ntmp;
+ int i;
- llist_for_each_entry_safe(nse, ntmp, &cfg->bss_nses, list) {
+ hash_for_each_safe(cfg->bss_nses, i, ntmp, nse, list) {
struct gbproxy_bvc *bvc, *tmp;
llist_for_each_entry_safe(bvc, tmp, &nse->bvcs, list)
gbproxy_bvc_free(bvc);
@@ -1636,7 +1642,7 @@ int gbproxy_init_config(struct gbproxy_config *cfg)
{
struct timespec tp;
- INIT_LLIST_HEAD(&cfg->bss_nses);
+ hash_init(cfg->bss_nses);
cfg->ctrg = rate_ctr_group_alloc(tall_sgsn_ctx, &global_ctrg_desc, 0);
if (!cfg->ctrg) {
LOGP(DGPRS, LOGL_ERROR, "Cannot allocate global counter group!\n");
diff --git a/src/gbproxy/gb_proxy_ctrl.c b/src/gbproxy/gb_proxy_ctrl.c
index c3cfddf7..82904129 100644
--- a/src/gbproxy/gb_proxy_ctrl.c
+++ b/src/gbproxy/gb_proxy_ctrl.c
@@ -56,6 +56,7 @@ static int get_nsvc_state(struct ctrl_cmd *cmd, void *data)
struct gprs_ns2_inst *nsi = cfg->nsi;
struct gprs_ns2_nse *nse;
struct gbproxy_nse *nse_peer;
+ int i;
cmd->reply = talloc_strdup(cmd, "");
@@ -69,7 +70,7 @@ static int get_nsvc_state(struct ctrl_cmd *cmd, void *data)
gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd);
/* NS-VCs for BSS peers */
- llist_for_each_entry(nse_peer, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse_peer, list) {
nse = gprs_ns2_nse_by_nsei(nsi, nse_peer->nsei);
if (nse)
gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd);
@@ -84,10 +85,11 @@ static int get_gbproxy_state(struct ctrl_cmd *cmd, void *data)
{
struct gbproxy_config *cfg = data;
struct gbproxy_nse *nse_peer;
+ int i;
cmd->reply = talloc_strdup(cmd, "");
- llist_for_each_entry(nse_peer, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse_peer, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse_peer->bvcs, list) {
struct gprs_ra_id raid;
@@ -111,8 +113,9 @@ static int get_num_peers(struct ctrl_cmd *cmd, void *data)
struct gbproxy_config *cfg = data;
struct gbproxy_nse *nse_peer;
uint32_t count = 0;
+ int i;
- llist_for_each_entry(nse_peer, &cfg->bss_nses, list)
+ hash_for_each(cfg->bss_nses, i, nse_peer, list)
count += llist_count(&nse_peer->bvcs);
cmd->reply = talloc_strdup(cmd, "");
diff --git a/src/gbproxy/gb_proxy_peer.c b/src/gbproxy/gb_proxy_peer.c
index c48a78f2..00bff208 100644
--- a/src/gbproxy/gb_proxy_peer.c
+++ b/src/gbproxy/gb_proxy_peer.c
@@ -86,8 +86,9 @@ static const struct rate_ctr_group_desc bvc_ctrg_desc = {
struct gbproxy_bvc *gbproxy_bvc_by_bvci(struct gbproxy_config *cfg, uint16_t bvci)
{
struct gbproxy_nse *nse;
+ int i;
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse->bvcs, list) {
if (bvc->bvci == bvci)
@@ -102,11 +103,11 @@ struct gbproxy_bvc *gbproxy_bvc_by_bvci(struct gbproxy_config *cfg, uint16_t bvc
struct gbproxy_bvc *gbproxy_bvc_by_nsei(struct gbproxy_config *cfg,
uint16_t nsei)
{
- struct gbproxy_nse *nse;
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
- if (nse->nsei == nsei && !llist_empty(&nse->bvcs))
- return llist_first_entry(&nse->bvcs, struct gbproxy_bvc, list);
- }
+ struct gbproxy_nse *nse = gbproxy_nse_by_nsei(cfg, nsei);
+
+ if (nse && !llist_empty(&nse->bvcs))
+ return llist_first_entry(&nse->bvcs, struct gbproxy_bvc, list);
+
return NULL;
}
@@ -116,8 +117,9 @@ struct gbproxy_bvc *gbproxy_bvc_by_rai(struct gbproxy_config *cfg,
const uint8_t *ra)
{
struct gbproxy_nse *nse;
+ int i;
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse->bvcs, list) {
if (!memcmp(bvc->ra, ra, 6))
@@ -134,8 +136,9 @@ struct gbproxy_bvc *gbproxy_bvc_by_lai(struct gbproxy_config *cfg,
const uint8_t *la)
{
struct gbproxy_nse *nse;
+ int i;
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse->bvcs, list) {
if (!memcmp(bvc->ra, la, 5))
@@ -151,8 +154,9 @@ struct gbproxy_bvc *gbproxy_bvc_by_lac(struct gbproxy_config *cfg,
const uint8_t *la)
{
struct gbproxy_nse *nse;
+ int i;
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each(cfg->bss_nses, i, nse, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse->bvcs, list) {
if (!memcmp(bvc->ra + 3, la + 3, 2))
@@ -268,11 +272,12 @@ void gbproxy_bvc_move(struct gbproxy_bvc *bvc, struct gbproxy_nse *nse)
* \param[in] bvci if 0: remove all BVCs; if != 0: BVCI of the single BVC to clean up */
int gbproxy_cleanup_bvcs(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci)
{
- int counter = 0;
- struct gbproxy_nse *nse, *ntmp;
+ int i, counter = 0;
+ struct gbproxy_nse *nse;
+ struct hlist_node *ntmp;
OSMO_ASSERT(cfg);
- llist_for_each_entry_safe(nse, ntmp, &cfg->bss_nses, list) {
+ hash_for_each_safe(cfg->bss_nses, i, ntmp, nse, list) {
struct gbproxy_bvc *bvc, *tmp;
if (nse->nsei != nsei)
continue;
@@ -300,7 +305,7 @@ struct gbproxy_nse *gbproxy_nse_alloc(struct gbproxy_config *cfg, uint16_t nsei)
nse->nsei = nsei;
nse->cfg = cfg;
- llist_add(&nse->list, &cfg->bss_nses);
+ hash_add(cfg->bss_nses, &nse->list, nsei);
INIT_LLIST_HEAD(&nse->bvcs);
@@ -313,7 +318,7 @@ void gbproxy_nse_free(struct gbproxy_nse *nse)
if (!nse)
return;
- llist_del(&nse->list);
+ hash_del(&nse->list);
llist_for_each_entry_safe(bvc, tmp, &nse->bvcs, list)
gbproxy_bvc_free(bvc);
@@ -326,7 +331,7 @@ struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nse
struct gbproxy_nse *nse;
OSMO_ASSERT(cfg);
- llist_for_each_entry(nse, &cfg->bss_nses, list) {
+ hash_for_each_possible(cfg->bss_nses, nse, list, nsei) {
if (nse->nsei == nsei)
return nse;
}
diff --git a/src/gbproxy/gb_proxy_vty.c b/src/gbproxy/gb_proxy_vty.c
index e79297d5..da8afdc1 100644
--- a/src/gbproxy/gb_proxy_vty.c
+++ b/src/gbproxy/gb_proxy_vty.c
@@ -422,13 +422,14 @@ DEFUN(cfg_gbproxy_link_list_clean_stale_timer,
"Frequency at which the periodic timer is fired (in seconds)\n")
{
struct gbproxy_nse *nse;
+ int i;
g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);
/* Re-schedule running timers soon in case prev frequency was really big
and new frequency is desired to be lower. After initial run, periodic
time is used. Use random() to avoid firing timers for all bvcs at
the same time */
- llist_for_each_entry(nse, &g_cfg->bss_nses, list) {
+ hash_for_each(g_cfg->bss_nses, i, nse, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse->bvcs, list)
osmo_timer_schedule(&bvc->clean_stale_timer,
@@ -445,9 +446,10 @@ DEFUN(cfg_gbproxy_link_list_no_clean_stale_timer,
{
struct gbproxy_nse *nse;
+ int i;
g_cfg->clean_stale_timer_freq = 0;
- llist_for_each_entry(nse, &g_cfg->bss_nses, list) {
+ hash_for_each(g_cfg->bss_nses, i, nse, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse->bvcs, list)
osmo_timer_del(&bvc->clean_stale_timer);
@@ -580,11 +582,12 @@ DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
{
struct gbproxy_nse *nse;
int show_stats = argc >= 1;
+ int i;
if (show_stats)
vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
- llist_for_each_entry(nse, &g_cfg->bss_nses, list) {
+ hash_for_each(g_cfg->bss_nses, i, nse, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse->bvcs, list) {
gbprox_vty_print_bvc(vty, bvc);
@@ -602,11 +605,12 @@ DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
struct gbproxy_nse *nse;
time_t now;
struct timespec ts = {0,};
+ int i;
osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
now = ts.tv_sec;
- llist_for_each_entry(nse, &g_cfg->bss_nses, list) {
+ hash_for_each(g_cfg->bss_nses, i, nse, list) {
struct gbproxy_bvc *bvc;
llist_for_each_entry(bvc, &nse->bvcs, list) {
struct gbproxy_link_info *link_info;
@@ -703,8 +707,9 @@ DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
} else {
struct gbproxy_nse *nse;
struct gbproxy_bvc *bvc;
+ int i;
counter = 0;
- llist_for_each_entry(nse, &g_cfg->bss_nses, list) {
+ hash_for_each(g_cfg->bss_nses, i, nse, list) {
if (nse->nsei != nsei)
continue;
llist_for_each_entry(bvc, &nse->bvcs, list) {