Change in osmo-sgsn[master]: gbproxy: convert bss_nses from llist_head to hashtable

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Mon Dec 7 13:14:19 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-sgsn/+/21550 )

Change subject: gbproxy: convert bss_nses from llist_head to hashtable
......................................................................

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
---
M TODO-RELEASE
M include/osmocom/sgsn/gb_proxy.h
M src/gbproxy/gb_proxy.c
M src/gbproxy/gb_proxy_ctrl.c
M src/gbproxy/gb_proxy_peer.c
M src/gbproxy/gb_proxy_vty.c
M tests/gbproxy/gbproxy_test.c
7 files changed, 56 insertions(+), 35 deletions(-)

Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved



diff --git a/TODO-RELEASE b/TODO-RELEASE
index 6b29a87..1e409b5 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -1,2 +1,3 @@
 #component	what		description / commit summary line
 manual				needs common chapter cs7-config.adoc, vty_cpu_sched.adoc from osmo-gsm-manuals > 0.3.0
+configure.ac	libosmocore	depend on next released libosmocore after 1.4.x with hashtable support
diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h
index 27b47cf..b0ab83d 100644
--- a/include/osmocom/sgsn/gb_proxy.h
+++ b/include/osmocom/sgsn/gb_proxy.h
@@ -4,6 +4,7 @@
 
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/timer.h>
+#include <osmocom/core/hashtable.h>
 #include <osmocom/gsm/gsm23003.h>
 
 #include <osmocom/gprs/gprs_ns2.h>
@@ -102,7 +103,7 @@
 	struct gprs_ns2_inst *nsi;
 
 	/* Linked list of all BSS side Gb peers */
-	struct llist_head bss_nses;
+	DECLARE_HASHTABLE(bss_nses, 8);
 
 	/* Counter */
 	struct rate_ctr_group *ctrg;
@@ -176,7 +177,7 @@
 /* one NS Entity that we interact with (BSS/PCU) */
 struct gbproxy_nse {
 	/* linked to gbproxy_config.bss_nses */
-	struct llist_head list;
+	struct hlist_node list;
 
 	/* point back to the config */
 	struct gbproxy_config *cfg;
diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c
index 4c34941..c37b21a 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 @@
 	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 @@
 	} 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 @@
 	} 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 @@
 		}
 	} 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 @@
 	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 @@
 	 * 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 @@
 	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 @@
 		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 @@
 
 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 @@
 {
 	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 c3cfddf..8290412 100644
--- a/src/gbproxy/gb_proxy_ctrl.c
+++ b/src/gbproxy/gb_proxy_ctrl.c
@@ -56,6 +56,7 @@
 	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 @@
 		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 @@
 {
 	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 @@
 	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 c48a78f..00bff20 100644
--- a/src/gbproxy/gb_proxy_peer.c
+++ b/src/gbproxy/gb_proxy_peer.c
@@ -86,8 +86,9 @@
 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_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 @@
 					 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 @@
 					 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 @@
 					 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 @@
  *  \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 @@
 	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 @@
 	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 *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 e79297d..da8afdc 100644
--- a/src/gbproxy/gb_proxy_vty.c
+++ b/src/gbproxy/gb_proxy_vty.c
@@ -422,13 +422,14 @@
       "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 @@
 
 {
 	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 @@
 {
 	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 @@
 	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 @@
 		} 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) {
diff --git a/tests/gbproxy/gbproxy_test.c b/tests/gbproxy/gbproxy_test.c
index 5538089..bd5c8b5 100644
--- a/tests/gbproxy/gbproxy_test.c
+++ b/tests/gbproxy/gbproxy_test.c
@@ -120,7 +120,7 @@
 {
 	struct gbproxy_nse *nse;
 	struct gprs_ra_id raid;
-	unsigned int i;
+	unsigned int i, _nse;
 	const struct rate_ctr_group_desc *desc;
 	int rc;
 
@@ -129,7 +129,7 @@
 		return rc;
 
 
-	llist_for_each_entry(nse, &cfg->bss_nses, list) {
+	hash_for_each(cfg->bss_nses, _nse, nse, list) {
 		struct gbproxy_bvc *peer;
 		llist_for_each_entry(peer, &nse->bvcs, list) {
 			struct gbproxy_link_info *link_info;

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/21550
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: Idbb6a362332bb6e3ce22102e7409ae80d0980f44
Gerrit-Change-Number: 21550
Gerrit-PatchSet: 2
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201207/bb85a537/attachment.htm>


More information about the gerrit-log mailing list