<p>lynxis lazus has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/22872">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">gprs_ns2: rework IP-SNS binds<br><br>Introduce a `ip-sns-bind BINDID` vty command within a `nse` vty object.<br>The ip-sns-bind defines the binds which will be used by the dynamic<br>configuration with IP-SNS.<br>This is only the first part which only use the binds when doing a<br>new SNS configuration.<br>The outgoing add procedure will be supported in a later patch<br>when the SNS fsm support outgoing procedures.<br><br>Change-Id: I9ab8092bf286e7d90e92f5702a5404425e959c84<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>M src/gb/gprs_ns2_vty.c<br>4 files changed, 420 insertions(+), 25 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/72/22872/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 39bbbef..f63c0ad 100644</span><br><span>--- a/src/gb/gprs_ns2.c</span><br><span>+++ b/src/gb/gprs_ns2.c</span><br><span>@@ -1267,6 +1267,7 @@</span><br><span> void gprs_ns2_free_bind(struct gprs_ns2_vc_bind *bind)</span><br><span> {</span><br><span>      struct gprs_ns2_vc *nsvc, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gprs_ns2_nse *nse;</span><br><span>    if (!bind)</span><br><span>           return;</span><br><span> </span><br><span>@@ -1274,6 +1275,12 @@</span><br><span>                 gprs_ns2_free_nsvc(nsvc);</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (gprs_ns2_is_ip_bind(bind)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              llist_for_each_entry(nse, &bind->nsi->nse, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  ns2_sns_remove_bind(nse, bind);</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>  if (bind->driver->free_bind)</span><br><span>           bind->driver->free_bind(bind);</span><br><span> </span><br><span>diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h</span><br><span>index 9dd9421..7da4a7c 100644</span><br><span>--- a/src/gb/gprs_ns2_internal.h</span><br><span>+++ b/src/gb/gprs_ns2_internal.h</span><br><span>@@ -365,6 +365,10 @@</span><br><span> void ns2_sns_replace_nsvc(struct gprs_ns2_vc *nsvc);</span><br><span> void ns2_sns_notify_alive(struct gprs_ns2_nse *nse, struct gprs_ns2_vc *nsvc, bool alive);</span><br><span> void ns2_update_weights(struct gprs_ns2_vc_bind *bind);</span><br><span style="color: hsl(120, 100%, 40%);">+int ns2_sns_add_bind(struct gprs_ns2_nse *nse,</span><br><span style="color: hsl(120, 100%, 40%);">+              struct gprs_ns2_vc_bind *bind);</span><br><span style="color: hsl(120, 100%, 40%);">+int ns2_sns_remove_bind(struct gprs_ns2_nse *nse,</span><br><span style="color: hsl(120, 100%, 40%);">+                       struct gprs_ns2_vc_bind *bind);</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 9e77f2a..7e0d5d9 100644</span><br><span>--- a/src/gb/gprs_ns2_sns.c</span><br><span>+++ b/src/gb/gprs_ns2_sns.c</span><br><span>@@ -103,6 +103,11 @@</span><br><span>  struct osmo_sockaddr saddr;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ns2_sns_bind {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gprs_ns2_vc_bind *bind;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct ns2_sns_state {</span><br><span>       struct gprs_ns2_nse *nse;</span><br><span> </span><br><span>@@ -110,6 +115,10 @@</span><br><span> </span><br><span>     /* holds the list of initial SNS endpoints */</span><br><span>        struct llist_head sns_endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* list of used struct ns2_sns_bind  */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct llist_head binds;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* pointer to the bind which was used to initiate the SNS connection */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ns2_sns_bind *current_bind;</span><br><span>   /* prevent recursive reselection */</span><br><span>  bool reselection_running;</span><br><span> </span><br><span>@@ -120,8 +129,6 @@</span><br><span>  struct sns_endpoint *initial;</span><br><span>        /* all SNS PDU will be sent over this nsvc */</span><br><span>        struct gprs_ns2_vc *sns_nsvc;</span><br><span style="color: hsl(0, 100%, 40%);">-   /* iterate over the binds after all remote has been tested */</span><br><span style="color: hsl(0, 100%, 40%);">-   int bind_offset;</span><br><span>     /* timer N */</span><br><span>        int N;</span><br><span>       /* true if at least one nsvc is alive */</span><br><span>@@ -741,23 +748,25 @@</span><br><span>     remote = &gss->initial->saddr;</span><br><span> </span><br><span>         /* count how many bindings are available (only UDP binds) */</span><br><span style="color: hsl(0, 100%, 40%);">-    count = ns2_ip_count_bind(nsi, remote);</span><br><span style="color: hsl(120, 100%, 40%);">+       count = llist_count(&gss->binds);</span><br><span>     if (count == 0) {</span><br><span>            /* TODO: logging */</span><br><span>          return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   bind = ns2_ip_get_bind_by_index(nsi, remote, gss->bind_offset);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!bind) {</span><br><span style="color: hsl(0, 100%, 40%);">-            if (gss->bind_offset) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      gss->bind_offset = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-                        bind = ns2_ip_get_bind_by_index(nsi, remote, gss->bind_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* take the first bind or take the next bind */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!gss->current_bind) {</span><br><span style="color: hsl(120, 100%, 40%);">+          gss->current_bind = llist_first_entry(&gss->binds, struct ns2_sns_bind, list);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (gss->current_bind->list.next != &gss->binds) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       gss->current_bind = llist_entry(gss->current_bind->list.next, struct ns2_sns_bind, list);</span><br><span style="color: hsl(120, 100%, 40%);">+            } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      gss->current_bind = llist_first_entry(&gss->binds, struct ns2_sns_bind, list);</span><br><span>             }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!bind)</span><br><span style="color: hsl(0, 100%, 40%);">-                      return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ bind = gss->current_bind->bind;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      /* setup the NSVC */</span><br><span>         if (!gss->sns_nsvc) {</span><br><span>             gss->sns_nsvc = ns2_ip_bind_connect(bind, gss->nse, remote);</span><br><span>@@ -1435,12 +1444,9 @@</span><br><span>                  return;</span><br><span>              } else if (!gss->initial) {</span><br><span>                       gss->initial = llist_first_entry(&gss->sns_endpoints, struct sns_endpoint, list);</span><br><span style="color: hsl(0, 100%, 40%);">-                     gss->bind_offset = 0;</span><br><span>             } else if (gss->initial->list.next == &gss->sns_endpoints) {</span><br><span>                    /* last entry, continue with first */</span><br><span>                        gss->initial = llist_first_entry(&gss->sns_endpoints, struct sns_endpoint, list);</span><br><span style="color: hsl(0, 100%, 40%);">-                     gss->bind_offset++;</span><br><span style="color: hsl(0, 100%, 40%);">-                  gss->bind_offset %= ns2_ip_count_bind(nse->nsi, &gss->initial->saddr);</span><br><span>               } else {</span><br><span>                     /* next element is an entry */</span><br><span>                       gss->initial = llist_entry(gss->initial->list.next, struct sns_endpoint, list);</span><br><span>@@ -1488,6 +1494,7 @@</span><br><span>     fi->priv = gss;</span><br><span>   gss->nse = nse;</span><br><span>   INIT_LLIST_HEAD(&gss->sns_endpoints);</span><br><span style="color: hsl(120, 100%, 40%);">+  INIT_LLIST_HEAD(&gss->binds);</span><br><span> </span><br><span>     return fi;</span><br><span> err:</span><br><span>@@ -1810,6 +1817,88 @@</span><br><span>  }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int ns2_sns_add_bind(struct gprs_ns2_nse *nse,</span><br><span style="color: hsl(120, 100%, 40%);">+                 struct gprs_ns2_vc_bind *bind)</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 ns2_sns_bind *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+     bool trigger_reselection = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(nse->bss_sns_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+      gss = nse->bss_sns_fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!gprs_ns2_is_ip_bind(bind)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EINVAL;</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 (!llist_empty(&gss->binds)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               llist_for_each_entry(tmp, &gss->binds, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (tmp->bind == bind)</span><br><span style="color: hsl(120, 100%, 40%);">+                             return -EALREADY;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              trigger_reselection = true;</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%);">+   tmp = talloc_zero(gss, struct ns2_sns_bind);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!tmp)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+       tmp->bind = bind;</span><br><span style="color: hsl(120, 100%, 40%);">+  llist_add_tail(&tmp->list, &gss->binds);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (trigger_reselection) {</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_SELECT_ENDPOINT, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* TODO: do a add SNS-IP procedure & add 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%);">+   return 0;</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%);">+/* Remove a bind from the SNS. All assosiated NSVC must be removed. */</span><br><span style="color: hsl(120, 100%, 40%);">+int ns2_sns_remove_bind(struct gprs_ns2_nse *nse,</span><br><span style="color: hsl(120, 100%, 40%);">+                     struct gprs_ns2_vc_bind *bind)</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 ns2_sns_bind *tmp, *tmp2;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gprs_ns2_vc *nsvc, *nsvc2;</span><br><span style="color: hsl(120, 100%, 40%);">+     bool found = false;</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 0;</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 (gss->current_bind && gss->current_bind->bind == bind) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (gss->current_bind->list.prev == &gss->binds)</span><br><span style="color: hsl(120, 100%, 40%);">+                 gss->current_bind = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          else</span><br><span style="color: hsl(120, 100%, 40%);">+                  gss->current_bind = llist_entry(gss->current_bind->list.prev, struct ns2_sns_bind, list);</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%);">+   llist_for_each_entry_safe(tmp, tmp2, &gss->binds, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (tmp->bind == bind) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   llist_del(&tmp->list);</span><br><span style="color: hsl(120, 100%, 40%);">+                 found = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                 talloc_free(tmp);</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 style="color: hsl(120, 100%, 40%);">+   if (!found)</span><br><span style="color: hsl(120, 100%, 40%);">+           return -ENOENT;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (nsvc->bind == bind) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  gprs_ns2_free_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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (llist_count(&gss->binds)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* TODO: do a remove SNS-IP procedure */</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%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Update SNS weights</span><br><span>  * \param[in] nsvc the NSVC which should be updated</span><br><span>  */</span><br><span>diff --git a/src/gb/gprs_ns2_vty.c b/src/gb/gprs_ns2_vty.c</span><br><span>index 53e5572..881761b 100644</span><br><span>--- a/src/gb/gprs_ns2_vty.c</span><br><span>+++ b/src/gb/gprs_ns2_vty.c</span><br><span>@@ -58,6 +58,7 @@</span><br><span> static struct gprs_ns2_inst *vty_nsi = NULL;</span><br><span> static struct osmo_fr_network *vty_fr_network = NULL;</span><br><span> static struct llist_head binds;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct llist_head nses;</span><br><span> </span><br><span> struct vty_bind {</span><br><span>      struct llist_head list;</span><br><span>@@ -70,6 +71,21 @@</span><br><span>         uint8_t ip_sns_data_weight;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct vty_nse {</span><br><span style="color: hsl(120, 100%, 40%);">+       struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint16_t nsei;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* list of binds which are valid for this nse. Only IP-SNS uses this</span><br><span style="color: hsl(120, 100%, 40%);">+   * to allow `no listen ..` in the bind context. So "half" created binds are valid for</span><br><span style="color: hsl(120, 100%, 40%);">+        * IP-SNS. This allows changing the bind ip without modifying all NSEs afterwards */</span><br><span style="color: hsl(120, 100%, 40%);">+  struct llist_head binds;</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%);">+/* used by IP-SNS to connect multiple vty_nse_bind to a vty_nse */</span><br><span style="color: hsl(120, 100%, 40%);">+struct vty_nse_bind {</span><br><span style="color: hsl(120, 100%, 40%);">+     struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct vty_bind *vbind;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* TODO: this should into osmo timer */</span><br><span> static const struct value_string gprs_ns_timer_strs[] = {</span><br><span>        { 0, "tns-block" },</span><br><span>@@ -135,6 +151,93 @@</span><br><span>         talloc_free(vbind);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static struct vty_nse *vty_nse_by_nsei(uint16_t nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct vty_nse *vnse;</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(vnse, &nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (vnse->nsei == nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+                    return vnse;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 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%);">+static struct vty_nse *vty_nse_alloc(uint16_t nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct vty_nse *vnse = talloc_zero(vty_nsi, struct vty_nse);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!vnse)</span><br><span style="color: hsl(120, 100%, 40%);">+            return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        vnse->nsei = nsei;</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&vnse->binds);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add(&vnse->list, &nses);</span><br><span style="color: hsl(120, 100%, 40%);">+     return vnse;</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%);">+static void vty_nse_free(struct vty_nse *vnse)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!vnse)</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%);">+     llist_del(&vnse->list);</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_free(vnse);</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%);">+static int vty_nse_add_vbind(struct vty_nse *vnse, struct vty_bind *vbind)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct vty_nse_bind *vnse_bind;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (vbind->ll != GPRS_NS2_LL_UDP)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     llist_for_each_entry(vnse_bind, &vnse->binds, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (vnse_bind->vbind == vbind)</span><br><span style="color: hsl(120, 100%, 40%);">+                     return -EALREADY;</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%);">+   vnse_bind = talloc(vnse, struct vty_nse_bind);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!vnse_bind)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+       vnse_bind->vbind = vbind;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        llist_add_tail(&vnse->list, &vnse->binds);</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</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%);">+static int vty_nse_remove_vbind(struct vty_nse *vnse, struct vty_bind *vbind)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct vty_nse_bind *vnse_bind, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (vbind->ll != GPRS_NS2_LL_UDP)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     llist_for_each_entry_safe(vnse_bind, tmp, &vnse->binds, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (vnse_bind->vbind == vbind) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   llist_del(&vnse_bind->list);</span><br><span style="color: hsl(120, 100%, 40%);">+                   talloc_free(vnse_bind);</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 style="color: hsl(120, 100%, 40%);">+   return -ENOENT;</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%);">+/* check if the NSE still has SNS configuration */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool vty_nse_check_sns(struct gprs_ns2_nse *nse) {</span><br><span style="color: hsl(120, 100%, 40%);">+   struct vty_nse *vnse = vty_nse_by_nsei(nse->nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       int count = gprs_ns2_sns_count(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (count > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* there are other sns endpoints */</span><br><span style="color: hsl(120, 100%, 40%);">+          return true;</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 (!vnse)</span><br><span style="color: hsl(120, 100%, 40%);">+            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (llist_empty(&vnse->binds))</span><br><span style="color: hsl(120, 100%, 40%);">+         return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct cmd_node ns_node = {</span><br><span>      L_NS_NODE,</span><br><span>   "%s(config-ns)# ",</span><br><span>@@ -172,14 +275,26 @@</span><br><span>       )</span><br><span> {</span><br><span>         struct gprs_ns2_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct vty_nse *vnse;</span><br><span>        uint16_t nsei = atoi(argv[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+        bool free_vnse = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     vnse = vty_nse_by_nsei(nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vnse) {</span><br><span style="color: hsl(120, 100%, 40%);">+          vnse = vty_nse_alloc(nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!vnse) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  vty_out(vty, "Failed to create vty NSE!%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+                   return CMD_ERR_INCOMPLETE;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             free_vnse = true;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> </span><br><span>        nse = gprs_ns2_nse_by_nsei(vty_nsi, nsei);</span><br><span>   if (!nse) {</span><br><span>          nse = gprs_ns2_create_nse(vty_nsi, nsei, GPRS_NS2_LL_UNDEF, GPRS_NS2_DIALECT_UNDEF);</span><br><span>                 if (!nse) {</span><br><span>                  vty_out(vty, "Failed to create NSE!%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-                 return CMD_ERR_INCOMPLETE;</span><br><span style="color: hsl(120, 100%, 40%);">+                    goto err;</span><br><span>            }</span><br><span>            nse->persistent = true;</span><br><span>   }</span><br><span>@@ -187,13 +302,19 @@</span><br><span>    if (!nse->persistent) {</span><br><span>           /* TODO: should the dynamic NSE removed? */</span><br><span>          vty_out(vty, "A dynamic NSE with the specified NSEI already exists%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-          return CMD_ERR_INCOMPLETE;</span><br><span style="color: hsl(120, 100%, 40%);">+            goto err;</span><br><span>    }</span><br><span> </span><br><span>        vty->node = L_NS_NSE_NODE;</span><br><span>        vty->index = nse;</span><br><span> </span><br><span>     return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+err:</span><br><span style="color: hsl(120, 100%, 40%);">+   if (free_vnse)</span><br><span style="color: hsl(120, 100%, 40%);">+                talloc_free(vnse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return CMD_ERR_INCOMPLETE;</span><br><span> }</span><br><span> </span><br><span> DEFUN(cfg_no_ns_nsei, cfg_no_ns_nsei_cmd,</span><br><span>@@ -204,6 +325,7 @@</span><br><span>       )</span><br><span> {</span><br><span>       struct gprs_ns2_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct vty_nse *vnse;</span><br><span>        uint16_t nsei = atoi(argv[0]);</span><br><span> </span><br><span>   nse = gprs_ns2_nse_by_nsei(vty_nsi, nsei);</span><br><span>@@ -219,6 +341,10 @@</span><br><span> </span><br><span>        vty_out(vty, "Deleting NS Entity %u%s", nse->nsei, VTY_NEWLINE);</span><br><span>        gprs_ns2_free_nse(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     vnse = vty_nse_by_nsei(nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_nse_free(vnse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        return CMD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span>@@ -472,7 +598,7 @@</span><br><span> {</span><br><span>      struct vty_bind *vbind = vty->index;</span><br><span>      struct gprs_ns2_vc_bind *bind;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc;</span><br><span>      const char *addr_str = argv[0];</span><br><span>      unsigned int port = atoi(argv[1]);</span><br><span>   struct osmo_sockaddr_str sockaddr_str;</span><br><span>@@ -494,8 +620,9 @@</span><br><span>                 return CMD_WARNING;</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (gprs_ns2_ip_bind(vty_nsi, vbind->name, &sockaddr, vbind->dscp, &bind) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-         vty_out(vty, "Failed to create the bind!%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = gprs_ns2_ip_bind(vty_nsi, vbind->name, &sockaddr, vbind->dscp, &bind);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                vty_out(vty, "Failed to create the bind (rc %d)!%s", rc, VTY_NEWLINE);</span><br><span>             return CMD_WARNING;</span><br><span>  }</span><br><span> </span><br><span>@@ -1320,7 +1447,6 @@</span><br><span>        struct osmo_sockaddr_str remote_str; /* argv[0] */</span><br><span>   struct osmo_sockaddr remote;</span><br><span>         uint16_t port = atoi(argv[1]);</span><br><span style="color: hsl(0, 100%, 40%);">-  int count;</span><br><span> </span><br><span>       if (nse->ll != GPRS_NS2_LL_UDP) {</span><br><span>                 vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);</span><br><span>@@ -1347,12 +1473,9 @@</span><br><span>                 return CMD_WARNING;</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   count = gprs_ns2_sns_count(nse);</span><br><span style="color: hsl(0, 100%, 40%);">-        if (count > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              /* there are other sns endpoints */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (vty_nse_check_sns(nse)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* there is still sns configuration valid */</span><br><span>                return CMD_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">-     } else if (count < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              OSMO_ASSERT(0);</span><br><span>      } else {</span><br><span>             /* clean up nse to allow other nsvc commands */</span><br><span>              osmo_fsm_inst_term(nse->bss_sns_fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span>@@ -1364,6 +1487,175 @@</span><br><span>       return CMD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(cfg_ns_nse_ip_sns_bind, cfg_ns_nse_ip_sns_bind_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "ip-sns-bind BINDID",</span><br><span style="color: hsl(120, 100%, 40%);">+      "IP SNS binds\n"</span><br><span style="color: hsl(120, 100%, 40%);">+      "A udp bind which this SNS will be used. The bind must be already exists. Can be given multiple times.\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gprs_ns2_nse *nse = vty->index;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gprs_ns2_vc_bind *bind;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct vty_bind *vbind;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct vty_nse *vnse;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name = argv[0];</span><br><span style="color: hsl(120, 100%, 40%);">+   bool ll_modified = false;</span><br><span style="color: hsl(120, 100%, 40%);">+     bool dialect_modified = false;</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (nse->ll == GPRS_NS2_LL_UNDEF) {</span><br><span style="color: hsl(120, 100%, 40%);">+                nse->ll = GPRS_NS2_LL_UDP;</span><br><span style="color: hsl(120, 100%, 40%);">+         ll_modified = true;</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 (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {</span><br><span style="color: hsl(120, 100%, 40%);">+              char sns[16];</span><br><span style="color: hsl(120, 100%, 40%);">+         snprintf(sns, sizeof(sns), "NSE%05u-SNS", nse->nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+            nse->bss_sns_fi = ns2_sns_bss_fsm_alloc(nse, sns);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!nse->bss_sns_fi)</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+             nse->dialect = GPRS_NS2_DIALECT_SNS;</span><br><span style="color: hsl(120, 100%, 40%);">+               dialect_modified = true;</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 (nse->ll != GPRS_NS2_LL_UDP) {</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+         goto err;</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 (nse->dialect != GPRS_NS2_DIALECT_SNS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+           goto err;</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%);">+   vbind = vty_bind_by_name(name);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!vbind) {</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, "Can not find the given bind '%s'%s", name, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+              goto err;</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 (vbind->ll != GPRS_NS2_LL_UDP) {</span><br><span style="color: hsl(120, 100%, 40%);">+                vty_out(vty, "ip-sns-bind can only be used with UDP bind%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                        VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+         goto err;</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%);">+   /* the vnse has been created together when creating the nse node. The parent node should check this already! */</span><br><span style="color: hsl(120, 100%, 40%);">+       vnse = vty_nse_by_nsei(nse->nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(vnse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = vty_nse_add_vbind(vnse, vbind);</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case -EALREADY:</span><br><span style="color: hsl(120, 100%, 40%);">+               vty_out(vty, "Failed to add ip-sns-bind %s already present%s", name, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+          goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+     case -ENOMEM:</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, "Failed to add ip-sns-bind %s out of memory%s", name, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+            goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+     default:</span><br><span style="color: hsl(120, 100%, 40%);">+              vty_out(vty, "Failed to add ip-sns-bind %s! %d%s", name, rc, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+          goto err;</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%);">+   /* the bind might not yet created because "listen" is missing. */</span><br><span style="color: hsl(120, 100%, 40%);">+   bind = gprs_ns2_bind_by_name(vty_nsi, name);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!bind)</span><br><span style="color: hsl(120, 100%, 40%);">+            return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = ns2_sns_add_bind(nse, bind);</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case -EALREADY:</span><br><span style="color: hsl(120, 100%, 40%);">+               vty_out(vty, "Failed to add ip-sns-bind %s already present%s", name, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+          goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+     case -ENOMEM:</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, "Failed to add ip-sns-bind %s out of memory%s", name, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+            goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+     default:</span><br><span style="color: hsl(120, 100%, 40%);">+              vty_out(vty, "Failed to add ip-sns-bind %s! %d%s", name, rc, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+          goto err;</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%);">+   return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+err:</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ll_modified)</span><br><span style="color: hsl(120, 100%, 40%);">+              nse->ll = GPRS_NS2_LL_UNDEF;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (dialect_modified)</span><br><span style="color: hsl(120, 100%, 40%);">+         nse->dialect = GPRS_NS2_DIALECT_UNDEF;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return CMD_WARNING;</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%);">+DEFUN(cfg_no_ns_nse_ip_sns_bind, cfg_no_ns_nse_ip_sns_bind_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "no ip-sns-bind BINDID",</span><br><span style="color: hsl(120, 100%, 40%);">+      NO_STR</span><br><span style="color: hsl(120, 100%, 40%);">+      "IP SNS binds\n"</span><br><span style="color: hsl(120, 100%, 40%);">+      "A udp bind which this SNS will be used.\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct gprs_ns2_nse *nse = vty->index;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gprs_ns2_vc_bind *bind;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct vty_bind *vbind;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct vty_nse *vnse;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name = argv[0];</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (nse->ll != GPRS_NS2_LL_UDP) {</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+           return CMD_WARNING;</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 (nse->dialect != GPRS_NS2_DIALECT_SNS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                vty_out(vty, "This NSE doesn't support UDP with dialect ip-sns.%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+               return CMD_WARNING;</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%);">+   vbind = vty_bind_by_name(name);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!vbind) {</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, "Can not find the given bind '%s'%s", name, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+              return CMD_WARNING;</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 (vbind->ll != GPRS_NS2_LL_UDP) {</span><br><span style="color: hsl(120, 100%, 40%);">+                vty_out(vty, "no ip-sns-bind can only be used with UDP bind%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                     VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+         return CMD_WARNING;</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%);">+   /* the vnse has been created together when creating the nse node. The parent node should check this already! */</span><br><span style="color: hsl(120, 100%, 40%);">+       vnse = vty_nse_by_nsei(nse->nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(vnse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = vty_nse_remove_vbind(vnse, vbind);</span><br><span style="color: hsl(120, 100%, 40%);">+       switch(rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case -ENOENT:</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, "Bind %s is not part of this NSE%s", name, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+               return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+   case -EINVAL:</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, "no ip-sns-bind can only be used with UDP bind%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                     VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+         return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+   default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return CMD_WARNING;</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%);">+   /* the bind might not exists yet */</span><br><span style="color: hsl(120, 100%, 40%);">+   bind = gprs_ns2_bind_by_name(vty_nsi, name);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (bind)</span><br><span style="color: hsl(120, 100%, 40%);">+             ns2_sns_remove_bind(nse, bind);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!vty_nse_check_sns(nse)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* clean up nse to allow other nsvc commands */</span><br><span style="color: hsl(120, 100%, 40%);">+               osmo_fsm_inst_term(nse->bss_sns_fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+          nse->bss_sns_fi = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+            nse->ll = GPRS_NS2_LL_UNDEF;</span><br><span style="color: hsl(120, 100%, 40%);">+               nse->dialect = GPRS_NS2_DIALECT_UNDEF;</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%);">+   return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /* non-config commands */</span><br><span> static void dump_nsvc(struct vty *vty, struct gprs_ns2_vc *nsvc, bool stats)</span><br><span>@@ -1676,6 +1968,7 @@</span><br><span> {</span><br><span>         vty_nsi = nsi;</span><br><span>       INIT_LLIST_HEAD(&binds);</span><br><span style="color: hsl(120, 100%, 40%);">+  INIT_LLIST_HEAD(&nses);</span><br><span> </span><br><span>      vty_fr_network = osmo_fr_network_alloc(nsi);</span><br><span>         if (!vty_fr_network)</span><br><span>@@ -1737,6 +2030,8 @@</span><br><span>         install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvc_ipa_cmd);</span><br><span>         install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_ip_sns_remote_cmd);</span><br><span>       install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_ip_sns_remote_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+     install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_ip_sns_bind_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+  install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_ip_sns_bind_cmd);</span><br><span> </span><br><span>  return 0;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/22872">change 22872</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/+/22872"/><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: I9ab8092bf286e7d90e92f5702a5404425e959c84 </div>
<div style="display:none"> Gerrit-Change-Number: 22872 </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>