diff options
author | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2013-10-14 12:03:54 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2013-10-14 13:35:43 +0200 |
commit | 6901715124d53574dc607d540105128573808b24 (patch) | |
tree | ccd93926870b2b0c9ea6f430c9b6f1f6a671779d /src/gb/gprs_ns.c | |
parent | 34fc4701c7681a4855534c20a6f59d12c4c81521 (diff) |
gb: When sending on a NS-VC group use the first active NS-VC
Currently this first NS-VC with a matching NSEI is always used to
send a UNITDATA message via gprs_ns_sendmsg(). If the NS-VC found is
either dead or blocked, an error is returned.
This patch changes to code to skip blocked or dead NS-VCs while
searching and return the error if no usable NS-VC is found. This
makes it possible to have several NS-VCs per connection group.
Sponsored-by: On-Waves ehf
Diffstat (limited to 'src/gb/gprs_ns.c')
-rw-r--r-- | src/gb/gprs_ns.c | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index b5f91c49..7801b297 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -136,7 +136,7 @@ struct gprs_nsvc *gprs_nsvc_by_nsvci(struct gprs_ns_inst *nsi, uint16_t nsvci) /*! \brief Lookup struct gprs_nsvc based on NSEI * \param[in] nsi NS instance in which to search * \param[in] nsei NSEI to be searched - * \returns gprs_nsvc of respective NSEI + * \returns first gprs_nsvc of respective NSEI */ struct gprs_nsvc *gprs_nsvc_by_nsei(struct gprs_ns_inst *nsi, uint16_t nsei) { @@ -148,6 +148,20 @@ struct gprs_nsvc *gprs_nsvc_by_nsei(struct gprs_ns_inst *nsi, uint16_t nsei) return NULL; } +static struct gprs_nsvc *gprs_active_nsvc_by_nsei(struct gprs_ns_inst *nsi, + uint16_t nsei) +{ + struct gprs_nsvc *nsvc; + llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + if (nsvc->nsei == nsei) { + if (nsvc->state & NSE_S_BLOCKED || + !(nsvc->state & NSE_S_ALIVE)) + return nsvc; + } + } + return NULL; +} + /* Lookup struct gprs_nsvc based on remote peer socket addr */ static struct gprs_nsvc *nsvc_by_rem_addr(struct gprs_ns_inst *nsi, struct sockaddr_in *sin) @@ -559,27 +573,24 @@ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) struct gprs_ns_hdr *nsh; uint16_t bvci = msgb_bvci(msg); - nsvc = gprs_nsvc_by_nsei(nsi, msgb_nsei(msg)); + nsvc = gprs_active_nsvc_by_nsei(nsi, msgb_nsei(msg)); if (!nsvc) { - LOGP(DNS, LOGL_ERROR, "Unable to resolve NSEI %u " - "to NS-VC!\n", msgb_nsei(msg)); - msgb_free(msg); - return -EINVAL; - } - log_set_context(GPRS_CTX_NSVC, nsvc); + int rc; + if (gprs_nsvc_by_nsei(nsi, msgb_nsei(msg))) { + LOGP(DNS, LOGL_ERROR, + "All NS-VCs for NSEI %u are either dead or blocked!\n", + msgb_nsei(msg)); + rc = -EBUSY; + } else { + LOGP(DNS, LOGL_ERROR, "Unable to resolve NSEI %u " + "to NS-VC!\n", msgb_nsei(msg)); + rc = -EINVAL; + } - if (!(nsvc->state & NSE_S_ALIVE)) { - LOGP(DNS, LOGL_ERROR, "NSEI=%u is not alive, cannot send\n", - nsvc->nsei); msgb_free(msg); - return -EBUSY; - } - if (nsvc->state & NSE_S_BLOCKED) { - LOGP(DNS, LOGL_ERROR, "NSEI=%u is blocked, cannot send\n", - nsvc->nsei); - msgb_free(msg); - return -EBUSY; + return rc; } + log_set_context(GPRS_CTX_NSVC, nsvc); msg->l2h = msgb_push(msg, sizeof(*nsh) + 3); nsh = (struct gprs_ns_hdr *) msg->l2h; |