Change in libosmocore[master]: gprs_ns2_sns: rework tracking of NS-VC unblocked/alive state

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
Tue Feb 9 15:42:02 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/22742 )

Change subject: gprs_ns2_sns: rework tracking of NS-VC unblocked/alive state
......................................................................

gprs_ns2_sns: rework tracking of NS-VC unblocked/alive state

The SNS must know when all NS-VC have failed. Further more
there might be a corner case when the SNS configuration succeeds but
no NS-VC comes up afterwards.

Related: OS#5355
Change-Id: Ie72da9adeefe0c2850d49a9208b2d0a4556f9101
---
M src/gb/gprs_ns2.c
M src/gb/gprs_ns2_internal.h
M src/gb/gprs_ns2_sns.c
3 files changed, 90 insertions(+), 14 deletions(-)

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



diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c
index de27fb4..ca47934 100644
--- a/src/gb/gprs_ns2.c
+++ b/src/gb/gprs_ns2.c
@@ -577,7 +577,7 @@
 	ns2_nse_notify_unblocked(nsvc, false);
 
 	/* check if sns is using this VC */
-	ns2_sns_free_nsvc(nsvc);
+	ns2_sns_replace_nsvc(nsvc);
 	osmo_fsm_inst_term(nsvc->fi, OSMO_FSM_TERM_REQUEST, NULL);
 
 	/* let the driver/bind clean up it's internal state */
@@ -1175,6 +1175,7 @@
 {
 	struct gprs_ns2_nse *nse = nsvc->nse;
 
+	ns2_sns_notify_alive(nse, nsvc, unblocked);
 	ns2_nse_data_sum(nse);
 
 	if (unblocked == nse->alive)
diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h
index 6462907..ff95c81 100644
--- a/src/gb/gprs_ns2_internal.h
+++ b/src/gb/gprs_ns2_internal.h
@@ -350,7 +350,8 @@
 int ns2_sns_rx(struct gprs_ns2_vc *nsvc, struct msgb *msg, struct tlv_parsed *tp);
 struct osmo_fsm_inst *ns2_sns_bss_fsm_alloc(struct gprs_ns2_nse *nse,
 					     const char *id);
-void ns2_sns_free_nsvc(struct gprs_ns2_vc *nsvc);
+void ns2_sns_replace_nsvc(struct gprs_ns2_vc *nsvc);
+void ns2_sns_notify_alive(struct gprs_ns2_nse *nse, struct gprs_ns2_vc *nsvc, bool alive);
 
 /* vc */
 struct osmo_fsm_inst *ns2_vc_fsm_alloc(struct gprs_ns2_vc *nsvc,
diff --git a/src/gb/gprs_ns2_sns.c b/src/gb/gprs_ns2_sns.c
index 427a153..b80a880 100644
--- a/src/gb/gprs_ns2_sns.c
+++ b/src/gb/gprs_ns2_sns.c
@@ -80,6 +80,7 @@
 	GPRS_SNS_EV_DELETE,
 	GPRS_SNS_EV_CHANGE_WEIGHT,
 	GPRS_SNS_EV_NO_NSVC,
+	GPRS_SNS_EV_NSVC_ALIVE,		/*!< a NS-VC became alive */
 };
 
 static const struct value_string gprs_sns_event_names[] = {
@@ -93,6 +94,7 @@
 	{ GPRS_SNS_EV_DELETE,		"DELETE" },
 	{ GPRS_SNS_EV_CHANGE_WEIGHT,	"CHANGE_WEIGHT" },
 	{ GPRS_SNS_EV_NO_NSVC,		"NO_NSVC" },
+	{ GPRS_SNS_EV_NSVC_ALIVE,	"NSVC_ALIVE"},
 	{ 0, NULL }
 };
 
@@ -122,6 +124,8 @@
 	int bind_offset;
 	/* timer N */
 	int N;
+	/* true if at least one nsvc is alive */
+	bool alive;
 
 	/* local configuration to send to the remote end */
 	struct gprs_ns_ie_ip4_elem *ip4_local;
@@ -227,13 +231,13 @@
 	return &gss->initial->saddr;
 }
 
-/*! called when a nsvc is beeing freed */
-void ns2_sns_free_nsvc(struct gprs_ns2_vc *nsvc)
+/*! called when a nsvc is beeing freed or the nsvc became dead */
+void ns2_sns_replace_nsvc(struct gprs_ns2_vc *nsvc)
 {
-	struct gprs_ns2_nse *nse;
+	struct gprs_ns2_nse *nse = nsvc->nse;
 	struct gprs_ns2_vc *tmp;
+	struct osmo_fsm_inst *fi = nse->bss_sns_fi;
 	struct ns2_sns_state *gss;
-	struct osmo_fsm_inst *fi = nsvc->nse->bss_sns_fi;
 
 	if (!fi)
 		return;
@@ -242,17 +246,26 @@
 	if (nsvc != gss->sns_nsvc)
 		return;
 
-	nse = nsvc->nse;
-	if (nse->alive) {
-		/* choose a different sns nsvc */
+	gss->sns_nsvc = NULL;
+	if (gss->alive) {
 		llist_for_each_entry(tmp, &nse->nsvc, list) {
-			if (ns2_vc_is_unblocked(tmp))
+			if (ns2_vc_is_unblocked(tmp)) {
 				gss->sns_nsvc = tmp;
+				return;
+			}
 		}
 	} else {
-		gss->sns_nsvc = NULL;
-		osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_NO_NSVC, NULL);
+		/* the SNS is waiting for its first NS-VC to come up
+		 * choose any other nsvc */
+		llist_for_each_entry(tmp, &nse->nsvc, list) {
+			if (nsvc != tmp) {
+				gss->sns_nsvc = tmp;
+				return;
+			}
+		}
 	}
+
+	osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_NO_NSVC, NULL);
 }
 
 static void ns2_clear_ipv46_entries(struct ns2_sns_state *gss)
@@ -715,6 +728,7 @@
 	if (old_state != GPRS_SNS_ST_UNCONFIGURED)
 		ns2_prim_status_ind(gss->nse, NULL, 0, GPRS_NS2_AFF_CAUSE_SNS_FAILURE);
 
+	gss->alive = false;
 	ns2_clear_ipv46_entries(gss);
 
 	/* no initial available */
@@ -873,6 +887,18 @@
 	}
 }
 
+/* calculate the timeout of the configured state. the configured
+ * state will fail if not at least one NS-VC is alive within X second.
+ */
+static inline int ns_sns_configured_timeout(struct osmo_fsm_inst *fi)
+{
+	int secs;
+	struct gprs_ns2_inst *nsi = nse_inst_from_fi(fi)->nsi;
+	secs = nsi->timeout[NS_TOUT_TNS_ALIVE] * nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES];
+	secs += nsi->timeout[NS_TOUT_TNS_TEST];
+
+	return secs;
+}
 
 static void ns_sns_st_config_sgsn_ip4(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 {
@@ -917,7 +943,7 @@
 		ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
 		/* start the test procedure on ALL NSVCs! */
 		gprs_ns2_start_alive_all_nsvcs(nse);
-		osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, 0, 0);
+		osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, ns_sns_configured_timeout(fi), 3);
 	} else {
 		/* just send CONFIG-ACK */
 		ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
@@ -1259,6 +1285,9 @@
 	case GPRS_SNS_EV_CHANGE_WEIGHT:
 		ns2_sns_st_configured_change(fi, gss, tp);
 		break;
+	case GPRS_SNS_EV_NSVC_ALIVE:
+		osmo_timer_del(&fi->timer);
+		break;
 	}
 }
 
@@ -1307,7 +1336,8 @@
 	[GPRS_SNS_ST_CONFIGURED] = {
 		.in_event_mask = S(GPRS_SNS_EV_ADD) |
 				 S(GPRS_SNS_EV_DELETE) |
-				 S(GPRS_SNS_EV_CHANGE_WEIGHT),
+				 S(GPRS_SNS_EV_CHANGE_WEIGHT) |
+				 S(GPRS_SNS_EV_NSVC_ALIVE),
 		.out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
 				  S(GPRS_SNS_ST_SIZE),
 		.name = "CONFIGURED",
@@ -1340,6 +1370,10 @@
 			osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIG_BSS, nsi->timeout[NS_TOUT_TSNS_PROV], 2);
 		}
 		break;
+	case 3:
+		LOGPFSML(fi, LOGL_ERROR, "NSE %d: Config succeeded but no NS-VC came online. Selecting next IP-SNS endpoint.\n", nse->nsei);
+		osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_SELECT_ENDPOINT, NULL);
+		break;
 	}
 	return 0;
 }
@@ -1709,6 +1743,46 @@
 	return count;
 }
 
+void ns2_sns_notify_alive(struct gprs_ns2_nse *nse, struct gprs_ns2_vc *nsvc, bool alive)
+{
+	struct ns2_sns_state *gss;
+	struct gprs_ns2_vc *tmp;
+
+	if (!nse->bss_sns_fi)
+		return;
+
+	gss = nse->bss_sns_fi->priv;
+	if(nse->bss_sns_fi->state != GPRS_SNS_ST_CONFIGURED)
+		return;
+
+	if (alive == gss->alive)
+		return;
+
+	/* check if this is the current SNS NS-VC */
+	if (nsvc == gss->sns_nsvc) {
+		/* only replace the SNS NS-VC if there are other alive NS-VC.
+		 * There aren't any other alive NS-VC when the SNS fsm just reached CONFIGURED
+		 * and couldn't confirm yet if the NS-VC comes up */
+		if (gss->alive && !alive)
+			ns2_sns_replace_nsvc(nsvc);
+	}
+
+	if (alive) {
+		gss->alive = true;
+		osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_NSVC_ALIVE, NULL);
+	} else {
+		/* is there at least another alive nsvc? */
+		llist_for_each_entry(tmp, &nse->nsvc, list) {
+			if (ns2_vc_is_unblocked(tmp))
+				return;
+		}
+
+		/* all NS-VC have failed */
+		gss->alive = false;
+		osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_NO_NSVC, NULL);
+	}
+}
+
 /* initialize osmo_ctx on main tread */
 static __attribute__((constructor)) void on_dso_load_ctx(void)
 {

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

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Ie72da9adeefe0c2850d49a9208b2d0a4556f9101
Gerrit-Change-Number: 22742
Gerrit-PatchSet: 8
Gerrit-Owner: lynxis lazus <lynxis at fe80.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-CC: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210209/cb4f0be7/attachment.htm>


More information about the gerrit-log mailing list