<p>lynxis lazus has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/22742">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">gprs_ns2_sns: rework tracking of NS-VC unblocked/alive state<br><br>The SNS must know when all NS-VC have failured. Further more<br>there might be a corner case when the SNS configuration succeeds but<br>no NS-VC comes up afterwards.<br><br>Change-Id: Ie72da9adeefe0c2850d49a9208b2d0a4556f9101<br>---<br>M src/gb/gprs_ns2.c<br>M src/gb/gprs_ns2_internal.h<br>M src/gb/gprs_ns2_sns.c<br>3 files changed, 90 insertions(+), 13 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/42/22742/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c</span><br><span>index de27fb4..ca47934 100644</span><br><span>--- a/src/gb/gprs_ns2.c</span><br><span>+++ b/src/gb/gprs_ns2.c</span><br><span>@@ -577,7 +577,7 @@</span><br><span>  ns2_nse_notify_unblocked(nsvc, false);</span><br><span> </span><br><span>   /* check if sns is using this VC */</span><br><span style="color: hsl(0, 100%, 40%);">-     ns2_sns_free_nsvc(nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+      ns2_sns_replace_nsvc(nsvc);</span><br><span>  osmo_fsm_inst_term(nsvc->fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span> </span><br><span>    /* let the driver/bind clean up it's internal state */</span><br><span>@@ -1175,6 +1175,7 @@</span><br><span> {</span><br><span>      struct gprs_ns2_nse *nse = nsvc->nse;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  ns2_sns_notify_alive(nse, nsvc, unblocked);</span><br><span>  ns2_nse_data_sum(nse);</span><br><span> </span><br><span>   if (unblocked == nse->alive)</span><br><span>diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h</span><br><span>index 6462907..ff95c81 100644</span><br><span>--- a/src/gb/gprs_ns2_internal.h</span><br><span>+++ b/src/gb/gprs_ns2_internal.h</span><br><span>@@ -350,7 +350,8 @@</span><br><span> int ns2_sns_rx(struct gprs_ns2_vc *nsvc, struct msgb *msg, struct tlv_parsed *tp);</span><br><span> struct osmo_fsm_inst *ns2_sns_bss_fsm_alloc(struct gprs_ns2_nse *nse,</span><br><span>                                         const char *id);</span><br><span style="color: hsl(0, 100%, 40%);">-void ns2_sns_free_nsvc(struct gprs_ns2_vc *nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+void ns2_sns_replace_nsvc(struct gprs_ns2_vc *nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+void ns2_sns_notify_alive(struct gprs_ns2_nse *nse, struct gprs_ns2_vc *nsvc, bool alive);</span><br><span> </span><br><span> /* vc */</span><br><span> struct osmo_fsm_inst *ns2_vc_fsm_alloc(struct gprs_ns2_vc *nsvc,</span><br><span>diff --git a/src/gb/gprs_ns2_sns.c b/src/gb/gprs_ns2_sns.c</span><br><span>index 427a153..a5b900f 100644</span><br><span>--- a/src/gb/gprs_ns2_sns.c</span><br><span>+++ b/src/gb/gprs_ns2_sns.c</span><br><span>@@ -80,6 +80,7 @@</span><br><span>    GPRS_SNS_EV_DELETE,</span><br><span>  GPRS_SNS_EV_CHANGE_WEIGHT,</span><br><span>   GPRS_SNS_EV_NO_NSVC,</span><br><span style="color: hsl(120, 100%, 40%);">+  GPRS_SNS_EV_NSVC_ALIVE,         /*!< a NS-VC became alive */</span><br><span> };</span><br><span> </span><br><span> static const struct value_string gprs_sns_event_names[] = {</span><br><span>@@ -122,6 +123,8 @@</span><br><span>       int bind_offset;</span><br><span>     /* timer N */</span><br><span>        int N;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* true if at least one nsvc is alive */</span><br><span style="color: hsl(120, 100%, 40%);">+      bool alive;</span><br><span> </span><br><span>      /* local configuration to send to the remote end */</span><br><span>  struct gprs_ns_ie_ip4_elem *ip4_local;</span><br><span>@@ -227,13 +230,18 @@</span><br><span>       return &gss->initial->saddr;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! called when a nsvc is beeing freed */</span><br><span style="color: hsl(0, 100%, 40%);">-void ns2_sns_free_nsvc(struct gprs_ns2_vc *nsvc)</span><br><span style="color: hsl(120, 100%, 40%);">+/*! called when all nsvcs has failed */</span><br><span style="color: hsl(120, 100%, 40%);">+void ns2_sns_nse_failure(struct gprs_ns2_nse *nse)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      struct gprs_ns2_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! called when a nsvc is beeing freed or the nsvc is become dead*/</span><br><span style="color: hsl(120, 100%, 40%);">+void ns2_sns_replace_nsvc(struct gprs_ns2_vc *nsvc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gprs_ns2_nse *nse = nsvc->nse;</span><br><span>     struct gprs_ns2_vc *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct osmo_fsm_inst *fi = nse->bss_sns_fi;</span><br><span>       struct ns2_sns_state *gss;</span><br><span style="color: hsl(0, 100%, 40%);">-      struct osmo_fsm_inst *fi = nsvc->nse->bss_sns_fi;</span><br><span> </span><br><span>  if (!fi)</span><br><span>             return;</span><br><span>@@ -242,17 +250,23 @@</span><br><span>      if (nsvc != gss->sns_nsvc)</span><br><span>                return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     nse = nsvc->nse;</span><br><span style="color: hsl(0, 100%, 40%);">-     if (nse->alive) {</span><br><span style="color: hsl(0, 100%, 40%);">-            /* choose a different sns nsvc */</span><br><span style="color: hsl(120, 100%, 40%);">+     gss->sns_nsvc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (gss->alive) {</span><br><span>                 llist_for_each_entry(tmp, &nse->nsvc, list) {</span><br><span>                         if (ns2_vc_is_unblocked(tmp))</span><br><span>                                gss->sns_nsvc = tmp;</span><br><span>              }</span><br><span>    } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                gss->sns_nsvc = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-                osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_NO_NSVC, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                /* the SNS is waiting for it's first NS-VC to come up</span><br><span style="color: hsl(120, 100%, 40%);">+              * choose any other nsvc */</span><br><span style="color: hsl(120, 100%, 40%);">+           llist_for_each_entry(tmp, &nse->nsvc, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (nsvc != tmp)</span><br><span style="color: hsl(120, 100%, 40%);">+                              gss->sns_nsvc = tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!gss->sns_nsvc)</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_NO_NSVC, NULL);</span><br><span> }</span><br><span> </span><br><span> static void ns2_clear_ipv46_entries(struct ns2_sns_state *gss)</span><br><span>@@ -715,6 +729,7 @@</span><br><span>      if (old_state != GPRS_SNS_ST_UNCONFIGURED)</span><br><span>           ns2_prim_status_ind(gss->nse, NULL, 0, GPRS_NS2_AFF_CAUSE_SNS_FAILURE);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        gss->alive = false;</span><br><span>       ns2_clear_ipv46_entries(gss);</span><br><span> </span><br><span>    /* no initial available */</span><br><span>@@ -873,6 +888,18 @@</span><br><span>    }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* calculate the timeout of the configured state. the configured</span><br><span style="color: hsl(120, 100%, 40%);">+ * state will fail if not at least one NS-VC is alive within X second.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int ns_sns_configured_timeout(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   int secs;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gprs_ns2_inst *nsi = nse_inst_from_fi(fi)->nsi;</span><br><span style="color: hsl(120, 100%, 40%);">+     secs = nsi->timeout[NS_TOUT_TNS_ALIVE] * nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES] ;</span><br><span style="color: hsl(120, 100%, 40%);">+      secs *= nsi->timeout[NS_TOUT_TNS_TEST];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return secs;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> static void ns_sns_st_config_sgsn_ip4(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>@@ -917,7 +944,7 @@</span><br><span>                ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);</span><br><span>               /* start the test procedure on ALL NSVCs! */</span><br><span>                 gprs_ns2_start_alive_all_nsvcs(nse);</span><br><span style="color: hsl(0, 100%, 40%);">-            osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, ns_sns_configured_timeout(fi), 3);</span><br><span>       } else {</span><br><span>             /* just send CONFIG-ACK */</span><br><span>           ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);</span><br><span>@@ -1259,6 +1286,9 @@</span><br><span>       case GPRS_SNS_EV_CHANGE_WEIGHT:</span><br><span>              ns2_sns_st_configured_change(fi, gss, tp);</span><br><span>           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case GPRS_SNS_EV_NSVC_ALIVE:</span><br><span style="color: hsl(120, 100%, 40%);">+          osmo_timer_del(&fi->timer);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span>       }</span><br><span> }</span><br><span> </span><br><span>@@ -1307,7 +1337,8 @@</span><br><span>   [GPRS_SNS_ST_CONFIGURED] = {</span><br><span>                 .in_event_mask = S(GPRS_SNS_EV_ADD) |</span><br><span>                                 S(GPRS_SNS_EV_DELETE) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                 S(GPRS_SNS_EV_CHANGE_WEIGHT),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 S(GPRS_SNS_EV_CHANGE_WEIGHT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                S(GPRS_SNS_EV_NSVC_ALIVE),</span><br><span>          .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |</span><br><span>                                S(GPRS_SNS_ST_SIZE),</span><br><span>               .name = "CONFIGURED",</span><br><span>@@ -1340,6 +1371,10 @@</span><br><span>                     osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIG_BSS, nsi->timeout[NS_TOUT_TSNS_PROV], 2);</span><br><span>          }</span><br><span>            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 3:</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGPFSML(fi, LOGL_ERROR, "NSE %d: Config succeeded but no NS-VC came online. Selecting next IP-SNS endpoint.\n", nse->nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_SELECT_ENDPOINT, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span>       }</span><br><span>    return 0;</span><br><span> }</span><br><span>@@ -1709,6 +1744,46 @@</span><br><span>      return count;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void ns2_sns_notify_alive(struct gprs_ns2_nse *nse, struct gprs_ns2_vc *nsvc, bool alive)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ns2_sns_state *gss;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gprs_ns2_vc *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!nse->bss_sns_fi)</span><br><span style="color: hsl(120, 100%, 40%);">+              return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     gss = nse->bss_sns_fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+    if(nse->bss_sns_fi->state != GPRS_SNS_ST_CONFIGURED)</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* check if this is the current SNS NS-VC */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (nsvc == gss->sns_nsvc) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* only replace the SNS NS-VC if there are other alive NS-VC.</span><br><span style="color: hsl(120, 100%, 40%);">+          * There aren't any other alive NS-VC when the SNS fsm just reached CONFIGURED</span><br><span style="color: hsl(120, 100%, 40%);">+             * and couldn't confirm yet if the NS-VC comes up */</span><br><span style="color: hsl(120, 100%, 40%);">+              if (gss->alive && !alive)</span><br><span style="color: hsl(120, 100%, 40%);">+                  ns2_sns_replace_nsvc(nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (alive == gss->alive)</span><br><span style="color: hsl(120, 100%, 40%);">+           return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (alive) {</span><br><span style="color: hsl(120, 100%, 40%);">+          gss->alive = true;</span><br><span style="color: hsl(120, 100%, 40%);">+         osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_NSVC_ALIVE, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* is there at least another alive nsvc? */</span><br><span style="color: hsl(120, 100%, 40%);">+           llist_for_each_entry(tmp, &nse->nsvc, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (ns2_vc_is_unblocked(nsvc))</span><br><span style="color: hsl(120, 100%, 40%);">+                                return;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* all NS-VC have failed */</span><br><span style="color: hsl(120, 100%, 40%);">+           gss->alive = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_NO_NSVC, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* initialize osmo_ctx on main tread */</span><br><span> static __attribute__((constructor)) void on_dso_load_ctx(void)</span><br><span> {</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/22742">change 22742</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/22742"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ie72da9adeefe0c2850d49a9208b2d0a4556f9101 </div>
<div style="display:none"> Gerrit-Change-Number: 22742 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: lynxis lazus <lynxis@fe80.eu> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>