aboutsummaryrefslogtreecommitdiffstats
path: root/src/gb
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2013-10-14 12:03:54 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-10-14 13:35:43 +0200
commit6901715124d53574dc607d540105128573808b24 (patch)
treeccd93926870b2b0c9ea6f430c9b6f1f6a671779d /src/gb
parent34fc4701c7681a4855534c20a6f59d12c4c81521 (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')
-rw-r--r--src/gb/gprs_ns.c47
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;