From 6901715124d53574dc607d540105128573808b24 Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Mon, 14 Oct 2013 12:03:54 +0200 Subject: 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 --- src/gb/gprs_ns.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) (limited to 'src') 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; -- cgit v1.2.3