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 | |
| 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
| -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; | 
