Change in libosmocore[master]: ns2: implement link sharing selector

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/.

lynxis lazus gerrit-no-reply at lists.osmocom.org
Thu Nov 19 02:05:20 UTC 2020


lynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/21244 )


Change subject: ns2: implement link sharing selector
......................................................................

ns2: implement link sharing selector

Change-Id: I212fa1a65e8c16cf1e525d1962d5689446c7e49e
---
M include/osmocom/gprs/gprs_ns2.h
M src/gb/gprs_ns2.c
M src/gb/gprs_ns2_internal.h
3 files changed, 138 insertions(+), 15 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/44/21244/1

diff --git a/include/osmocom/gprs/gprs_ns2.h b/include/osmocom/gprs/gprs_ns2.h
index 2a805c2..c13d315 100644
--- a/include/osmocom/gprs/gprs_ns2.h
+++ b/include/osmocom/gprs/gprs_ns2.h
@@ -92,6 +92,7 @@
 	union {
 		struct {
 			enum gprs_ns2_change_ip_endpoint change;
+			uint32_t link_selector;
 			/* TODO: implement resource distribution
 			 * add place holder for the link selector */
 			long long _resource_distribution_placeholder1;
diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c
index 4b32ddf..602bca7 100644
--- a/src/gb/gprs_ns2.c
+++ b/src/gb/gprs_ns2.c
@@ -57,9 +57,7 @@
  * Those mappings are administratively configured.
  *
  * This implementation has the following limitations:
- * - Only one NS-VC for each NSE: No load-sharing function
  * - NSVCI 65535 and 65534 are reserved for internal use
- * - Only UDP is supported as of now, no frame relay support
  * - There are no BLOCK and UNBLOCK timers (yet?)
  *
  * \file gprs_ns2.c */
@@ -303,19 +301,130 @@
 	return osmo_fsm_inst_state_name(nsvc->fi);
 }
 
+/* select a signalling NSVC and respect sig_counter
+ * param[out] reset_counter - all counter has to be resetted to their signal weight
+ * return the chosen nsvc or NULL
+ */
+static struct gprs_ns2_vc *ns2_load_sharing_signal(
+		struct gprs_ns2_nse *nse)
+{
+	struct gprs_ns2_vc *nsvc = NULL, *last = NULL, *tmp;
+
+	llist_for_each_entry(tmp, &nse->nsvc, list) {
+		if (tmp->sig_weight == 0)
+			continue;
+		if (!gprs_ns2_vc_is_unblocked(tmp))
+			continue;
+		if (tmp->sig_counter == 0) {
+			last = tmp;
+			continue;
+		}
+
+		tmp->sig_counter--;
+		nsvc = tmp;
+		break;
+	}
+
+	/* all counter were zero, but there are valid nsvc */
+	if (!nsvc && last) {
+		llist_for_each_entry(tmp, &nse->nsvc, list) {
+			tmp->sig_counter = tmp->sig_weight;
+		}
+
+		last->sig_counter--;
+		return last;
+	} else {
+		return nsvc;
+	}
+}
+
+/* 4.4.1 Load Sharing function for the Frame Relay Sub-Network */
+static struct gprs_ns2_vc *ns2_load_sharing_modulor(
+		struct gprs_ns2_nse *nse,
+		uint16_t bvci,
+		uint32_t load_selector)
+{
+	struct gprs_ns2_vc *tmp;
+	uint32_t mod = (bvci + load_selector) % nse->nsvc_data_count;
+	uint32_t i = 0;
+
+	llist_for_each_entry(tmp, &nse->nsvc, list) {
+		if (!gprs_ns2_vc_is_unblocked(tmp))
+			continue;
+		if (tmp->data_weight == 0)
+			continue;
+
+		if (i == mod)
+			return tmp;
+		i++;
+	}
+
+	return NULL;
+}
+
+/* pick the first available data NSVC - no load sharing */
+struct gprs_ns2_vc *ns2_load_sharing_first(struct gprs_ns2_nse *nse)
+{
+	struct gprs_ns2_vc *nsvc = NULL, *tmp;
+
+	llist_for_each_entry(tmp, &nse->nsvc, list) {
+		if (!gprs_ns2_vc_is_unblocked(tmp))
+			continue;
+		if (tmp->data_weight == 0)
+			continue;
+
+		nsvc = tmp;
+		break;
+	}
+
+	return nsvc;
+}
+
+
+static struct gprs_ns2_vc *ns2_load_sharing(
+		struct gprs_ns2_nse *nse,
+		uint16_t bvci,
+		uint32_t link_selector)
+{
+	struct gprs_ns2_vc *nsvc = NULL;
+
+	if (bvci == 0) {
+		/* signalling */
+		nsvc = ns2_load_sharing_signal(nse);
+	} else {
+		enum gprs_ns_ll ll;
+
+		/* data with load sharing parameter */
+		if (llist_empty(&nse->nsvc))
+			return NULL;
+		nsvc = llist_first_entry(&nse->nsvc, struct gprs_ns2_vc, list);
+		ll = nsvc->ll;
+
+		switch (ll) {
+		case GPRS_NS_LL_FR:
+			nsvc = ns2_load_sharing_modulor(nse, bvci, link_selector);
+			break;
+		default:
+			nsvc = ns2_load_sharing_first(nse);
+			break;
+		}
+	}
+
+	return nsvc;
+}
+
 /*! Receive a primitive from the NS User (Gb).
  *  \param[in] nsi NS instance to which the primitive is issued
  *  \param[in] oph The primitive
  *  \return 0 on success; negative on error */
 int gprs_ns2_recv_prim(struct gprs_ns2_inst *nsi, struct osmo_prim_hdr *oph)
 {
-	/* TODO: implement load distribution function */
 	/* TODO: implement resource distribution */
 	/* TODO: check for empty PDUs which can be sent to Request/Confirm
 	 *       the IP endpoint */
 	struct osmo_gprs_ns2_prim *nsp;
 	struct gprs_ns2_nse *nse = NULL;
-	struct gprs_ns2_vc *nsvc = NULL, *tmp;
+	struct gprs_ns2_vc *nsvc = NULL;
 	uint16_t bvci, nsei;
 	uint8_t sducontrol = 0;
 
@@ -337,16 +446,7 @@
 	if (!nse)
 		return -EINVAL;
 
-	llist_for_each_entry(tmp, &nse->nsvc, list) {
-		if (!gprs_ns2_vc_is_unblocked(tmp))
-			continue;
-		if (bvci == 0 && tmp->sig_weight == 0)
-			continue;
-		if (bvci != 0 && tmp->data_weight == 0)
-			continue;
-
-		nsvc = tmp;
-	}
+	nsvc = ns2_load_sharing(nse, bvci, nsp->u.unitdata.link_selector);
 
 	/* TODO: send a status primitive back */
 	if (!nsvc)
@@ -980,6 +1080,20 @@
 	return rc;
 }
 
+/* summarize all active data nsvcs */
+void ns2_nse_data_sum(struct gprs_ns2_nse *nse)
+{
+	struct gprs_ns2_vc *nsvc;
+	nse->nsvc_data_count = 0;
+
+	llist_for_each_entry(nsvc, &nse->nsvc, list) {
+		if (!gprs_ns2_vc_is_unblocked(nsvc))
+			continue;
+		if (nsvc->data_weight > 0)
+			nse->nsvc_data_count++;
+	}
+}
+
 /*! Notify a nse about the change of a NS-VC.
  *  \param[in] nsvc NS-VC which has detected the change (and shall not be notified).
  *  \param[in] unblocked whether the NSE should be marked as unblocked (true) or blocked (false) */
@@ -988,6 +1102,8 @@
 	struct gprs_ns2_nse *nse = nsvc->nse;
 	struct gprs_ns2_vc *tmp;
 
+	ns2_nse_data_sum(nse);
+
 	if (unblocked == nse->alive)
 		return;
 
diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h
index e4d2d8a..78b6d82 100644
--- a/src/gb/gprs_ns2_internal.h
+++ b/src/gb/gprs_ns2_internal.h
@@ -118,6 +118,9 @@
 	/*! llist head to hold all nsvc */
 	struct llist_head nsvc;
 
+	/*! count all active NSVCs with data capabilities */
+	int nsvc_data_count;
+
 	/*! true if this NSE was created by VTY or pcu socket) */
 	bool persistent;
 
@@ -154,7 +157,10 @@
 	/*! signalling weight. 0 = don't use for signalling (BVCI == 0)*/
 	uint8_t sig_weight;
 
-	/*! signaling weight. 0 = don't use for user data (BVCI != 0) */
+	/*! signalling packet counter for the load sharing function */
+	uint8_t sig_counter;
+
+	/*! data weight. 0 = don't use for user data (BVCI != 0) */
 	uint8_t data_weight;
 
 	/*! can be used by the bind/driver of the virtual circuit. e.g. ipv4/ipv6/frgre/e1 */

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

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: I212fa1a65e8c16cf1e525d1962d5689446c7e49e
Gerrit-Change-Number: 21244
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <lynxis at fe80.eu>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201119/4a127426/attachment.htm>


More information about the gerrit-log mailing list