Files
openairinterface5g/openair2/NAS/DRIVER/CELLULAR/NASRG/nasrg_ascontrol.c
T
2015-04-10 13:18:11 +00:00

1504 lines
54 KiB
C
Executable File

/***************************************************************************
nasrg_ascontrol.c - description
***************************************************************************
Access Stratum Control features for eNodeB
***************************************************************************
Eurecom OpenAirInterface 2
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 450 route des Chappes, 06410 Biot Sophia Antipolis, France
*******************************************************************************/
/*! \file nasrg_ascontrol.c
* \brief Access Stratum Control functions for OpenAirInterface CELLULAR version - RG
* \author michelle.wetterwald, navid.nikaein, raymond.knopp, Lionel Gauthier
* \company Eurecom
* \email: michelle.wetterwald@eurecom.fr, raymond.knopp@eurecom.fr, navid.nikaein@eurecom.fr, lionel.gauthier@eurecom.fr
*/
/*******************************************************************************/
#ifdef NODE_RG
#include "nasrg_variables.h"
#include "nasrg_proto.h"
//---------------------------------------------------------------------------
void nasrg_ASCTL_init(void)
{
//---------------------------------------------------------------------------
int cxi, i;
gpriv->next_sclassref = NASRG_DEFAULTRAB_CLASSREF;
// Initialize MBMS services list in MT
for (cxi=0; cxi<NAS_CX_MAX ; ++cxi) {
for (i = 0; i<NASRG_MBMS_SVCES_MAX; i++) {
gpriv->cx[cxi].requested_joined_services[i]= -1;
gpriv->cx[cxi].requested_left_services[i]= -1;
gpriv->cx[cxi].joined_services[i]= -1;
}
}
printk("nasrg_ASCTL_init Complete\n");
}
//---------------------------------------------------------------------------
int nasrg_ASCTL_write(int sap, unsigned char *data_buffer, unsigned int data_length)
{
//---------------------------------------------------------------------------
int bytes_wrote = 0;
#ifdef PDCP_USE_NETLINK
unsigned char xmit_buffer [NAS_MESSAGE_MAXLEN];
//write SAP_Id
switch (sap) {
case RRC_DEVICE_GC:
xmit_buffer[0] = RRC_NAS_GC_IN;
break;
case RRC_DEVICE_NT:
xmit_buffer[0] = RRC_NAS_NT_IN;
break;
case RRC_DEVICE_DC_INPUT0:
xmit_buffer[0] = RRC_NAS_DC0_IN;
break;
case RRC_DEVICE_DC_INPUT1:
xmit_buffer[0] = RRC_NAS_DC1_IN;
//case RRC_DEVICE_DC_INPUT2:
//xmit_buffer[0] = RRC_NAS_DC2_IN;
break;
default:
printk("nasrg_ASCTL_write - ERROR - Invalid SAP %d\n", sap);
return 0;
break;
}
memcpy (&((char*)xmit_buffer)[1], data_buffer, data_length);
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_write - Sending data to RRC, sap %d, length %d (including NETLINK SAP value)\n", sap, data_length+1);
nasrg_TOOL_print_buffer(xmit_buffer,data_length+1);
#endif
bytes_wrote = nasrg_netlink_send(xmit_buffer,data_length+1, NASNL_DEST_RRC);
#else
//bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); //original version
bytes_wrote = rtf_put(sap, data_buffer, data_length+1);
#endif //PDCP_USE_NETLINK
return bytes_wrote-1;
}
//---------------------------------------------------------------------------
//For demo, add automatically a radio bearer
//Equivalent to rb add send 0 5 2
void nasrg_ASCTL_start_default_rb(struct cx_entity *cx)
{
//---------------------------------------------------------------------------
#ifdef DEMO_3GSM
struct rb_entity *rb;
int status;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_start_default_rb - begin \n");
#endif
if (!cx) {
printk("nasrg_ASCTL_start_default_rb - input parameter cx is NULL \n");
return;
}
// End debug information
rb = nasrg_COMMON_add_rb(cx, NASRG_DEFAULTRAB_RBID, NASRG_DEFAULTRAB_QoS);
if (rb!=NULL) {
rb->cnxid = (NAS_RB_MAX_NUM * cx->lcr)+1;
//rb->default_rab =1;
rb->dscp = NASRG_DEFAULTRAB_DSCP;
rb->dscp_ul = NASRG_DEFAULTRAB_DSCP;
status=nasrg_ASCTL_DC_send_rb_establish_request(cx, rb);
} else
status=-NAS_ERROR_NOMEMORY;
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_start_default_rb - end %d \n",status);
#endif
}
#endif
//---------------------------------------------------------------------------
//For demo, add automatically a classifier
//Equivalent to class add send 0 -f qos <x> -cr 0
void nasrg_ASCTL_start_default_sclassifier(struct cx_entity *cx,struct rb_entity *rb)
{
//---------------------------------------------------------------------------
struct classifier_entity *gc;
// Start debug information
#ifdef NAS_DEBUG_CLASS
printk("nasrg_ASCTL_start_default_sclassifier - begin \n");
#endif
if (!cx || !rb) {
printk("nasrg_ASCTL_start_default_sclassifier - input parameter is NULL \n");
return;
}
// End debug information
gc=nasrg_CLASS_add_sclassifier(cx, NAS_DSCP_DEFAULT, gpriv->next_sclassref);
if (gc==NULL) {
printk("nasrg_ASCTL_start_default_sclassifier - Classifier pointer is null : not added \n");
return;
}
gc->fct = nasrg_COMMON_QOS_send;
gc->rab_id =rb->rab_id;
gc->rb= rb;
gc->version = NASRG_DEFAULTRAB_IPVERSION;
gc->protocol= NAS_PROTOCOL_DEFAULT;
gc->dplen= NAS_DEFAULT_IPv6_PREFIX_LENGTH;
// copy locator part of address into the gc structure
//gc->daddr.ipv6.s6_addr32[0] = 0;
//gc->daddr.ipv6.s6_addr32[1] = 0;
//gc->daddr.ipv6.s6_addr32[2] = 0;
//gc->daddr.ipv6.s6_addr32[3] = 0;
#ifdef NAS_DEBUG_CLASS
printk("nasrg_ASCTL_start_default_sclassifier - end \n");
nasrg_TOOL_print_classifier(gc);
#endif
}
//---------------------------------------------------------------------------
//Add automatically a classifier on DSCP
//Equivalent to class add send 0 -f qos <x> -cr 0
void nasrg_ASCTL_start_sclassifier(struct cx_entity *cx,struct rb_entity *rb)
{
//---------------------------------------------------------------------------
struct classifier_entity *gc;
// Start debug information
#ifdef NAS_DEBUG_CLASS
printk("nasrg_ASCTL_start_sclassifier - begin \n");
#endif
if (!cx || !rb) {
printk("nasrg_ASCTL_start_sclassifier - input parameter is NULL \n");
return;
}
// End debug information
gc=nasrg_CLASS_add_sclassifier(cx, rb->dscp, gpriv->next_sclassref);
if (gc==NULL) {
printk("nasrg_ASCTL_start_sclassifier - Classifier pointer is null : not added \n");
return;
}
gc->fct = nasrg_COMMON_QOS_send;
gc->rab_id =rb->rab_id;
gc->rb= rb;
gc->version = NASRG_DEFAULTRAB_IPVERSION;
gc->protocol= NAS_PROTOCOL_DEFAULT;
gc->dplen= NAS_DEFAULT_IPv6_PREFIX_LENGTH;
// copy locator part of address into the gc structure
gc->daddr.ipv6.s6_addr32[2] = cx->iid6[0];
gc->daddr.ipv6.s6_addr32[3] = cx->iid6[1];
#ifdef NAS_DEBUG_CLASS
printk("nasrg_ASCTL_start_sclassifier - end \n");
nasrg_TOOL_print_classifier(gc);
#endif
}
//---------------------------------------------------------------------------
//Add automatically a classifier for mbms
void nasrg_ASCTL_start_mbmsclassifier(int mbms_ix,struct rb_entity *mbms_rb)
{
//---------------------------------------------------------------------------
struct classifier_entity *gc;
// Start debug information
#ifdef NAS_DEBUG_CLASS
printk("nasrg_ASCTL_start_mbmsclassifier - begin \n");
#endif
if (!mbms_rb) {
printk("nasrg_ASCTL_start_mbmsclassifier - input parameter is NULL \n");
return;
}
// End debug information
//
// gc=nasrg_CLASS_add_mbmsclassifier(mbms_ix, gpriv->next_mbmsclassref);
gc=nasrg_CLASS_add_mbmsclassifier(mbms_ix, gpriv->next_sclassref++);
if (gc==NULL) {
printk("nasrg_ASCTL_start_mbmsclassifier - Classifier pointer is null : not added \n");
return;
}
gc->fct = nasrg_COMMON_QOS_send;
gc->rab_id =mbms_rb->mbms_rbId;
gc->rb= mbms_rb;
gc->version = NASRG_DEFAULTRAB_IPVERSION;
gc->protocol= NAS_PROTOCOL_DEFAULT;
#ifdef NAS_DEBUG_CLASS
printk("nasrg_ASCTL_start_mbmsclassifier - end \n");
nasrg_TOOL_print_classifier(gc);
#endif
}
//---------------------------------------------------------------------------
//Notifies automatically UE on default MBMS service
void nasrg_ASCTL_start_default_ue_notification(struct cx_entity *cx)
{
//---------------------------------------------------------------------------
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_start_default_ue_notification - begin \n");
#endif
if (!cx) {
printk("\nERROR nasrg_ASCTL_start_default_ue_notification - input parameter is NULL \n");
return;
}
// End debug information
// set value for default MBMS service
cx->requested_joined_services[0] = (NAS_CX_MAX*NAS_RB_MAX_NUM) +1;
nasrg_ASCTL_DC_send_mbms_ue_notify_req(cx);
}
//---------------------------------------------------------------------------
//Notifies automatically UE on default MBMS service
void nasrg_ASCTL_start_default_mbms_service(void)
{
//---------------------------------------------------------------------------
int mbms_ix=0; // should allocate index based on Service_id /cnxid / MC IP address
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_start_default_mbms_service - begin \n");
#endif
// Establish MBMS bearer if not already done
if ((gpriv->mbms_rb[mbms_ix].state != NAS_CX_DCH)&&(gpriv->mbms_rb[mbms_ix].state != NAS_RB_ESTABLISHING)) {
gpriv->mbms_rb[mbms_ix].cnxid = (NAS_CX_MAX*NAS_RB_MAX_NUM) +1;
gpriv->mbms_rb[mbms_ix].serviceId = (NAS_CX_MAX*NAS_RB_MAX_NUM) +1;
gpriv->mbms_rb[mbms_ix].sessionId = NASRG_TEMP_MBMS_SESSION_ID; //Temp hard coded
gpriv->mbms_rb[mbms_ix].mbms_rbId = NASRG_DEFAULTRAB_RBID;
gpriv->mbms_rb[mbms_ix].sapi = NAS_DC_INPUT_SAPI;
#ifdef NAS_DEBUG_MBMS_PROT
gpriv->mbms_rb[mbms_ix].sapi = NAS_DRB_INPUT_SAPI; //Only one RT-FIFO is used
#endif
gpriv->mbms_rb[mbms_ix].qos = 20; //from first version of MBMS traces
gpriv->mbms_rb[mbms_ix].dscp = 0; //maybe 7
gpriv->mbms_rb[mbms_ix].duration = NASRG_TEMP_MBMS_DURATION; //Temp hard coded
//memcpy ((char *)&(gpriv->mbms_rb[mbms_ix].mcast_address),(char *)&(msgreq->mcast_group), 16);
gpriv->mbms_rb[mbms_ix].mcast_address[0] = 0xFF;
gpriv->mbms_rb[mbms_ix].mcast_address[1] = 0x0E;
nasrg_ASCTL_GC_send_mbms_bearer_establish_req(mbms_ix);
} else {
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_start_default_mbms_service - skipped, mbms_rb.state = %d \n", gpriv->mbms_rb[mbms_ix].state);
#endif
}
}
//---------------------------------------------------------------------------
void nasrg_ASCTL_timer(unsigned long data)
{
//---------------------------------------------------------------------------
uint8_t cxi;
struct cx_entity *cx;
struct rb_entity *rb;
spin_lock(&gpriv->lock);
#ifdef NAS_DEBUG_TIMER
printk("nasrg_ASCTL_timer - begin \n");
#endif
(gpriv->timer).function = nasrg_ASCTL_timer;
(gpriv->timer).expires=jiffies+NAS_TIMER_TICK;
(gpriv->timer).data=0L;
for (cxi=0; cxi<NAS_CX_MAX ; ++cxi) {
cx=gpriv->cx+cxi;
if (!cx) {
printk("nasrg_ASCTL_timer - No pointer for connection %d \n", cxi);
continue;
}
for (rb=cx->rb; rb!=NULL; rb=rb->next) {
if (rb->countimer!=NAS_TIMER_IDLE) {
#ifdef NAS_DEBUG_TIMER
printk("nasrg_ASCTL_timer : rb countimer %d, rb state %d\n", rb->countimer, rb->state);
#endif
if (rb->countimer==0) {
switch (rb->state) {
case NAS_CX_CONNECTING:
case NAS_CX_CONNECTING_FAILURE: // MW - 15/01/07 Useless, currently no retry if failure
if (rb->retry<gpriv->retry_limit) {
printk("nasrg_ASCTL_timer: Retry RB establishment %d\n", rb->retry);
nasrg_ASCTL_DC_send_rb_establish_request(cx, rb);
} else {
printk("nasrg_ASCTL_timer: RB Establishment failure\n");
rb->state=NAS_IDLE;
rb->countimer=NAS_TIMER_IDLE;
}
break;
case NAS_CX_DCH:
#ifdef DEMO_3GSM
if (cx->num_rb == 1) {
nasrg_ASCTL_start_default_sclassifier(cx, rb);
}
#endif
nasrg_ASCTL_start_sclassifier(cx, rb);
rb->countimer=NAS_TIMER_IDLE;
break;
case NAS_CX_RELEASING_FAILURE:
nasrg_ASCTL_DC_send_rb_release_request(cx, rb);
break;
default:
rb->countimer=NAS_TIMER_IDLE;
}
} else {
--rb->countimer;
printk("nasrg_ASCTL_timer : rb countimer-- %d, rb state %d\n", rb->countimer, rb->state);
}
}
}
}
add_timer(&gpriv->timer);
#ifdef NAS_DEBUG_TIMER
printk("nasrg_ASCTL_timer - end \n");
#endif
spin_unlock(&gpriv->lock);
}
/***************************************************************************
Transmission side
***************************************************************************/
//---------------------------------------------------------------------------
// Encode INFO_BROADCAST_REQ message
int nasrg_ASCTL_GC_send_broadcast_request(uint8_t category)
{
//---------------------------------------------------------------------------
char *xmit_data = "TESTING BROADCASTING ROUTER ADVERTISEMENT. TESTING BROADCASTING ROUTER ADVERTISEMENT. BROADCASTING ROUTER.\0";
int bytes_wrote = 0;
#ifdef PDCP_USE_NETLINK
unsigned char xbuffer[NAS_MESSAGE_MAXLEN];
int count=0;
#endif
struct nas_rg_gc_element *p;
p= (struct nas_rg_gc_element *)(gpriv->xbuffer);
p->type = INFO_BROADCAST_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASInfoBroadcastReq);
//
p->nasRGGCPrimitive.broadcast_req.period = 0;
p->nasRGGCPrimitive.broadcast_req.category = category;
p->nasRGGCPrimitive.broadcast_req.nasDataLength = strlen(xmit_data)+1; // TBD
//bytes_wrote = rtf_put(gpriv->sap[NAS_GC_SAPI], p, p->length); //original version
#ifdef PDCP_USE_NETLINK
memcpy(xbuffer,(unsigned char *)p, p->length);
count = p->length;
bytes_wrote = count;
#else
bytes_wrote = nasrg_ASCTL_write(gpriv->sap[NAS_GC_SAPI], (unsigned char *)p, p->length);
#endif
//printk("nasrg_ASCTL_GC_send_broadcast_request - Wrote %d bytes to RRC NAS_GC_SAPII\n", bytes_wrote);
//bytes_wrote += rtf_put(gpriv->sap[NAS_GC_SAPI], xmit_data, p->nasRGGCPrimitive.broadcast_req.nasDataLength);
#ifdef PDCP_USE_NETLINK
memcpy(&(xbuffer[count]),(unsigned char *)xmit_data, p->nasRGGCPrimitive.broadcast_req.nasDataLength);
count += p->nasRGGCPrimitive.broadcast_req.nasDataLength;
bytes_wrote += nasrg_ASCTL_write(gpriv->sap[NAS_GC_SAPI], xbuffer, count);
#else
bytes_wrote += nasrg_ASCTL_write((gpriv->sap[NAS_GC_SAPI], xmit_data, p->nasRGGCPrimitive.broadcast_req.nasDataLength);
#endif
if (bytes_wrote==p->length+p->nasRGGCPrimitive.broadcast_req.nasDataLength) {
#ifdef NAS_DEBUG_GC
printk("nasrg_ASCTL_GC_send_broadcast: INFO_BROADCAST_REQ primitive sent successfully in GC-FIFO\n");
#endif
} else {
printk("nasrg_ASCTL_GC_send_broadcast: Message sent failure in GC-FIFO\n");
}
return bytes_wrote;
}
//---------------------------------------------------------------------------
// Encode INFO_BROADCAST_REQ message for RRC SIB1
int nasrg_ASCTL_GC_send_SIB1_broadcast_request(struct sk_buff *skb)
{
//---------------------------------------------------------------------------
struct nas_rg_gc_element *p;
char sib1_flag; // will be used for reception in nas_ue
int bytes_wrote = 0;
#ifdef PDCP_USE_NETLINK
unsigned char xbuffer[NAS_MESSAGE_MAXLEN];
int count=0;
#endif
// Start debug information
#ifdef NAS_DEBUG_GC
printk("nasrg_ASCTL_GC_send_SIB1_broadcast_request - begin \n");
#endif
if (!skb) {
printk("nasrg_ASCTL_GC_send_SIB1_broadcast_request - input parameter is NULL \n");
return 0;
}
// End debug information
p= (struct nas_rg_gc_element *)(gpriv->xbuffer);
p->type = INFO_BROADCAST_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASInfoBroadcastReq);
//
p->nasRGGCPrimitive.broadcast_req.period = 10; // to be checked
p->nasRGGCPrimitive.broadcast_req.category = 1;
p->nasRGGCPrimitive.broadcast_req.nasDataLength = skb->len+1; // TBD
sib1_flag = 1;
// send header
//bytes_wrote = rtf_put(gpriv->sap[NAS_GC_SAPI], p, p->length); //original version
#ifdef PDCP_USE_NETLINK
memcpy(xbuffer,(unsigned char *)p, p->length);
count = p->length;
bytes_wrote = count;
#else
bytes_wrote = nasrg_ASCTL_write(gpriv->sap[NAS_GC_SAPI], (unsigned char *)p, p->length);
#endif
//printk("nasrg_ASCTL_GC_send_broadcast_request - Wrote %d bytes to RRC NAS_GC_SAPII\n", bytes_wrote);
if (bytes_wrote!=p->length) {
printk("nasrg_ASCTL_GC_send_SIB1_broadcast_request: Header send failure in GC-FIFO\n");
return bytes_wrote;
}
// send sib1_flag
//bytes_wrote += rtf_put(gpriv->sap[NAS_GC_SAPI], &sib1_flag, 1);
#ifdef PDCP_USE_NETLINK
memcpy(&(xbuffer[count]),(unsigned char *)&sib1_flag, 1);
count += 1;
bytes_wrote = count;
#else
bytes_wrote += nasrg_ASCTL_write(gpriv->sap[NAS_GC_SAPI], (unsigned char *)&sib1_flag, 1);
#endif
if (bytes_wrote!=p->length+1) {
printk("nasrg_ASCTL_GC_send_SIB1_broadcast_request: sib1_flag send failure in GC-FIFO\n");
return bytes_wrote;
}
// send data
//bytes_wrote += rtf_put(gpriv->sap[NAS_GC_SAPI], skb->data, skb->len);
#ifdef PDCP_USE_NETLINK
memcpy(&(xbuffer[count]),skb->data, skb->len);
count += skb->len;
bytes_wrote = nasrg_ASCTL_write(gpriv->sap[NAS_GC_SAPI], xbuffer, count);
#else
bytes_wrote += nasrg_ASCTL_write(gpriv->sap[NAS_GC_SAPI], skb->data, skb->len);
#endif
if (bytes_wrote!=p->length+skb->len+1) {
printk("nasrg_ASCTL_GC_send_SIB1_broadcast_request: Data send failure in GC-FIFO\n");
return bytes_wrote;
}
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_GC_send_SIB1_broadcast_request - end \n");
#endif
return bytes_wrote;
}
//-----------------------------------------------------------------------------
// Encode MBMS_BEARER_ESTABLISH_REQ message
int nasrg_ASCTL_GC_send_mbms_bearer_establish_req(int mbms_ix )
{
//-----------------------------------------------------------------------------
struct nas_rg_gc_element *p;
int bytes_wrote = 0;
p= (struct nas_rg_gc_element *)(gpriv->xbuffer);
p->type = MBMS_BEARER_ESTABLISH_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASMBMSBearerEstablishReq);
//
p->nasRGGCPrimitive.mbms_establish_req.mbms_serviceId = gpriv->mbms_rb[mbms_ix].serviceId;
p->nasRGGCPrimitive.mbms_establish_req.mbms_sessionId = gpriv->mbms_rb[mbms_ix].sessionId;
p->nasRGGCPrimitive.mbms_establish_req.mbms_rbId = gpriv->mbms_rb[mbms_ix].mbms_rbId;
p->nasRGGCPrimitive.mbms_establish_req.mbms_sapId = gpriv->mbms_rb[mbms_ix].sapi;
p->nasRGGCPrimitive.mbms_establish_req.mbms_QoSclass = gpriv->mbms_rb[mbms_ix].qos;
p->nasRGGCPrimitive.mbms_establish_req.mbms_duration = gpriv->mbms_rb[mbms_ix].duration;
gpriv->mbms_rb[mbms_ix].state = NAS_RB_ESTABLISHING;
//
//bytes_wrote = rtf_put(gpriv->sap[NAS_GC_SAPI], p, p->length);
bytes_wrote = nasrg_ASCTL_write(gpriv->sap[NAS_GC_SAPI], (unsigned char *)p, p->length);
if (bytes_wrote==p->length) {
#ifdef NAS_DEBUG_GC
printk(" nasrg_ASCTL_GC_send_mbms_bearer_establish: MBMS_BEARER_ESTABLISH_REQ primitive sent successfully in GC-FIFO\n");
printk(" ServiceId %d, RB_Id %d , qos class %d \n",
p->nasRGGCPrimitive.mbms_establish_req.mbms_serviceId,
p->nasRGGCPrimitive.mbms_establish_req.mbms_rbId,
p->nasRGGCPrimitive.mbms_establish_req.mbms_QoSclass);
#endif
} else {
printk("nasrg_ASCTL_GC_send_mbms_bearer_establish: Message sent failure in GC-FIFO\n");
}
return bytes_wrote;
}
//-----------------------------------------------------------------------------
// HNN - Encode MBMS_BEARER_RELEASE_REQ message
int nasrg_ASCTL_GC_send_mbms_bearer_release_req(int mbms_ix)
{
//-----------------------------------------------------------------------------
struct nas_rg_gc_element *p;
uint16_t classref=0;
int bytes_wrote = 0;
p= (struct nas_rg_gc_element *)(gpriv->xbuffer);
p->type = MBMS_BEARER_RELEASE_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASMBMSBearerReleaseReq);
//
p->nasRGGCPrimitive.mbms_release_req.mbms_serviceId = gpriv->mbms_rb[mbms_ix].serviceId;
p->nasRGGCPrimitive.mbms_release_req.mbms_sessionId = gpriv->mbms_rb[mbms_ix].sessionId;
p->nasRGGCPrimitive.mbms_release_req.mbms_rbId = gpriv->mbms_rb[mbms_ix].mbms_rbId;
//gpriv->mbms_rb[mbms_ix].state = NAS_RB_RELEASING;
//
//bytes_wrote = rtf_put(gpriv->sap[NAS_GC_SAPI], p, p->length);
bytes_wrote = nasrg_ASCTL_write(gpriv->sap[NAS_GC_SAPI], (unsigned char *)p, p->length);
if (bytes_wrote==p->length) {
#ifdef NAS_DEBUG_GC
printk(" nasrg_ASCTL_GC_send_mbms_bearer_release: MBMS_BEARER_RELEASE_REQ primitive sent successfully in GC-FIFO\n");
printk(" ServiceId %d, RB_Id %d \n", p->nasRGGCPrimitive.mbms_establish_req.mbms_serviceId, p->nasRGGCPrimitive.mbms_establish_req.mbms_rbId);
#endif
// clean NASRG private structures
classref = (gpriv->mbmsclassifier[mbms_ix])->classref;
nasrg_CLASS_del_mbmsclassifier(mbms_ix, classref);
//nasrg_CLASS_flush_mbmsclassifier();
//gpriv->mbms_rb[mbms_ix].state = NAS_IDLE;
memset (&(gpriv->mbms_rb[mbms_ix]),0,sizeof (struct rb_entity));
} else {
printk("nasrg_ASCTL_GC_send_mbms_bearer_release: Message sent failure in GC-FIFO\n");
}
return bytes_wrote;
}
//---------------------------------------------------------------------------
// Confirm the establishment of a connection (DC channel)
int nasrg_ASCTL_DC_send_cx_establish_confirm(struct cx_entity *cx, uint8_t response)
{
//---------------------------------------------------------------------------
struct nas_rg_dc_element *p;
int bytes_wrote = 0;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_cx_establish - begin \n");
#endif
if (!cx) {
printk("nasrg_ASCTL_DC_send_cx_establish - input parameter cx is NULL \n");
return NAS_ERROR_NOTCORRECTVALUE;
}
// End debug information
p= (struct nas_rg_dc_element *)(gpriv->xbuffer);
p->type = CONN_ESTABLISH_CNF;
p->length = NAS_TL_SIZE + sizeof(struct NASConnEstablishConf);
p->nasRGDCPrimitive.conn_establish_conf.localConnectionRef = cx->lcr;
p->nasRGDCPrimitive.conn_establish_conf.status = response; // can be ACCEPTED or FAILURE
p->nasRGDCPrimitive.conn_establish_conf.num_RBs = 0; // Hard coded in first step
//
//bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length);
bytes_wrote = nasrg_ASCTL_write(cx->sap[NAS_DC_INPUT_SAPI], (unsigned char *)p, p->length);
if (bytes_wrote==p->length) {
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_cx_establish: CONN_ESTABLISH_CNF primitive sent successfully in DC-FIFO\n");
printk(" lcr (Mobile_id) %u\n",p->nasRGDCPrimitive.conn_establish_conf.localConnectionRef);
printk(" Status %u\n",p->nasRGDCPrimitive.conn_establish_conf.status);
#endif
} else
printk("nasrg_ASCTL_DC_send_cx_establish: Message transmission failure to DC-FIFO\n");
return bytes_wrote;
}
//---------------------------------------------------------------------------
// Request the establishment of a radio bearer
int nasrg_ASCTL_DC_send_rb_establish_request(struct cx_entity *cx, struct rb_entity *rb)
{
//---------------------------------------------------------------------------
struct nas_rg_dc_element *p;
int bytes_wrote = 0;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_rb_establish - begin \n");
#endif
if (!cx || !rb) {
printk("nasrg_ASCTL_DC_send_rb_establish - input parameter is NULL \n");
return NAS_ERROR_NOTCORRECTVALUE;
}
// End debug information
switch(rb->state) {
case NAS_CX_CONNECTING:
case NAS_CX_CONNECTING_FAILURE:
case NAS_IDLE:
++rb->retry;
rb->countimer=gpriv->timer_establishment;
if (cx->state==NAS_CX_DCH) {
p= (struct nas_rg_dc_element *)(gpriv->xbuffer);
p->type = RB_ESTABLISH_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASrbEstablishReq);
p->nasRGDCPrimitive.rb_establish_req.localConnectionRef = cx->lcr;
p->nasRGDCPrimitive.rb_establish_req.rbId = rb->rab_id + (NAS_RB_MAX_NUM * cx->lcr);
p->nasRGDCPrimitive.rb_establish_req.QoSclass = rb->qos;
p->nasRGDCPrimitive.rb_establish_req.dscp = rb->dscp_ul;
//
//bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length);
bytes_wrote = nasrg_ASCTL_write(cx->sap[NAS_DC_INPUT_SAPI], (unsigned char *)p, p->length);
if (bytes_wrote==p->length) {
rb->state=NAS_CX_CONNECTING;
#ifdef NAS_DEBUG_DC
printk(" nasrg_ASCTL_DC_send_rb_establish: RB_ESTABLISH_REQ primitive sent successfully in DC-FIFO\n");
printk(" lcr (Mobile_id) %u\n",p->nasRGDCPrimitive.rb_establish_req.localConnectionRef);
printk(" Radio Bearer identification %u\n",p->nasRGDCPrimitive.rb_establish_req.rbId);
printk(" QoS %u\n",p->nasRGDCPrimitive.rb_establish_req.QoSclass);
#endif
} else {
rb->state=NAS_CX_CONNECTING_FAILURE;
printk("nasrg_ASCTL_DC_send_rb_establish: Message sent failure in DC-FIFO\n");
}
return bytes_wrote;
} else {
rb->state=NAS_CX_CONNECTING_FAILURE;
printk("nasrg_ASCTL_DC_send_rb_establish: Failure \n");
return 0;
}
default:
return -NAS_ERROR_NOTIDLE;
}
}
//---------------------------------------------------------------------------
// Request the release of a radio bearer
int nasrg_ASCTL_DC_send_rb_release_request(struct cx_entity *cx, struct rb_entity *rb)
{
//---------------------------------------------------------------------------
struct nas_rg_dc_element *p;
int bytes_wrote = 0;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_rb_release - begin \n");
#endif
if (!cx || !rb) {
printk("nasrg_ASCTL_DC_send_rb_release - input parameter is NULL \n");
return NAS_ERROR_NOTCORRECTVALUE;
}
// End debug information
switch (rb->state) {
case NAS_CX_RELEASING_FAILURE:
case NAS_CX_DCH:
p= (struct nas_rg_dc_element *)(gpriv->xbuffer);
p->type = RB_RELEASE_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASrbReleaseReq);
p->nasRGDCPrimitive.rb_release_req.localConnectionRef = cx->lcr;
p->nasRGDCPrimitive.rb_release_req.rbId = rb->rab_id + (NAS_RB_MAX_NUM * cx->lcr);
//
//bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length);
bytes_wrote = nasrg_ASCTL_write(cx->sap[NAS_DC_INPUT_SAPI], (unsigned char *)p, p->length);
if (bytes_wrote) {
rb->state=NAS_IDLE;
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_rb_release: RB_RELEASE_REQ primitive sent successfully in DC-FIFO\n");
#endif
} else {
++rb->retry;
rb->countimer=gpriv->timer_release;
rb->state=NAS_CX_RELEASING_FAILURE;
printk("nasrg_ASCTL_DC_send_rb_release: Message sent failure in DC-FIFO\n");
}
return bytes_wrote;
default:
return -NAS_ERROR_NOTCONNECTED;
}
}
//-----------------------------------------------------------------------------
// Request the notification of a UE to joined or left services
int nasrg_ASCTL_DC_send_mbms_ue_notify_req(struct cx_entity *cx)
{
//-----------------------------------------------------------------------------
struct nas_rg_dc_element *p;
int i;
int bytes_wrote = 0;
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_mbms_ue_notify_req - begin \n");
#endif
if (!cx) {
printk("nasrg_ASCTL_DC_send_mbms_ue_notify_req - input parameter is NULL \n");
return NAS_ERROR_NOTCORRECTVALUE;
}
// End debug information
p= (struct nas_rg_dc_element *)(gpriv->xbuffer);
p->type = MBMS_UE_NOTIFY_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASMBMSUENotifyReq);
//
p->nasRGDCPrimitive.mbms_ue_notify_req.localConnectionRef = cx->lcr;
// joined/left services are lists of MAX_MBMS_SERVICES
// -1 means the end of the list
for (i = 0; i < MAX_MBMS_SERVICES; i++) {
p->nasRGDCPrimitive.mbms_ue_notify_req.joined_services[i].mbms_serviceId = (nasMBMSServiceId_t)cx->requested_joined_services[i];
p->nasRGDCPrimitive.mbms_ue_notify_req.left_services[i].mbms_serviceId = (nasMBMSServiceId_t)cx->requested_left_services[i];
}
//
//bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length);
bytes_wrote = nasrg_ASCTL_write(cx->sap[NAS_DC_INPUT_SAPI], (unsigned char *)p, p->length);
if (bytes_wrote==p->length) {
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_mbms_ue_notify_req: MBMS_UE_NOTIFY_REQ primitive sent successfully in DC-FIFO\n");
printk(" lcr (Mobile_id) %u\n",p->nasRGDCPrimitive.mbms_ue_notify_req.localConnectionRef);
printk(" joined service %d, left service %d\n",cx->requested_joined_services[0], cx->requested_left_services[0] );
#endif
} else
printk("nasrg_ASCTL_DC_send_mbms_ue_notify_req: Message transmission failure to DC-FIFO\n");
return bytes_wrote;
}
//---------------------------------------------------------------------------
// Request the transfer of data (DC SAP)
void nasrg_ASCTL_DC_send_sig_data_request(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc)
{
//---------------------------------------------------------------------------
struct nas_rg_dc_element *p;
int bytes_wrote = 0;
#ifdef PDCP_USE_NETLINK
unsigned char xbuffer[NAS_MESSAGE_MAXLEN];
int count=0;
#endif
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_sig_data - begin \n");
#endif
if (!skb || !gc || !cx) {
printk("nasrg_ASCTL_DC_send_sig_data - input parameter is NULL \n");
return;
}
// End debug information
if (cx->state!=NAS_CX_DCH) {
printk("nasrg_ASCTL_DC_send_sig_data: Not connected, so the message is dropped\n");
++gpriv->stats.tx_dropped;
return;
}
p = (struct nas_rg_dc_element *)(gpriv->xbuffer);
p->type = DATA_TRANSFER_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASDataReq);
p->nasRGDCPrimitive.data_transfer_req.localConnectionRef = cx->lcr;
p->nasRGDCPrimitive.data_transfer_req.priority = NAS_SIG_SRB3;
p->nasRGDCPrimitive.data_transfer_req.nasDataLength = skb->len;
//
//bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length);
#ifdef PDCP_USE_NETLINK
memcpy(xbuffer,(unsigned char *)p, p->length);
count = p->length;
bytes_wrote = count;
#else
bytes_wrote = nasrg_ASCTL_write(cx->sap[NAS_DC_INPUT_SAPI], (unsigned char *)p, p->length);
#endif
if (bytes_wrote!=p->length) {
printk("nasrg_ASCTL_DC_send_sig_data: Header sent failure in DC-FIFO\n");
return;
}
//bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], skb->data, skb->len);
#ifdef PDCP_USE_NETLINK
memcpy(&(xbuffer[count]),(unsigned char *)skb->data, skb->len);
count += skb->len;
bytes_wrote = nasrg_ASCTL_write(cx->sap[NAS_DC_INPUT_SAPI], xbuffer, count);
#else
bytes_wrote += nasrg_ASCTL_write(cx->sap[NAS_DC_INPUT_SAPI], (unsigned char *)skb->data, skb->len);
#endif
if (bytes_wrote!=p->length+skb->len) {
printk("nasrg_ASCTL_DC_send_sig_data: Data sent failure in DC-FIFO\n");
return;
}
gpriv->stats.tx_bytes += skb->len;
gpriv->stats.tx_packets ++;
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_sig_data - end \n");
#endif
}
//---------------------------------------------------------------------------
// Confirm the establishment of a connection (DC channel)
int nasrg_ASCTL_DC_send_eNBmeasurement_req(struct cx_entity *cx)
{
//---------------------------------------------------------------------------
struct nas_rg_dc_element *p;
int bytes_wrote = 0;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_eNBmeasurement_req - begin \n");
#endif
if (!cx) {
printk("nasrg_ASCTL_DC_send_eNBmeasurement_req - input parameter cx is NULL \n");
return NAS_ERROR_NOTCORRECTVALUE;
}
// End debug information
p= (struct nas_rg_dc_element *)(gpriv->xbuffer);
p->type = ENB_MEASUREMENT_REQ;
p->length = NAS_TL_SIZE + sizeof(struct NASENbMeasureReq);
p->nasRGDCPrimitive.eNBmeasurement_req.cell_id = cx->cellid;
//
//bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length);
bytes_wrote = nasrg_ASCTL_write(cx->sap[NAS_DC_INPUT_SAPI], (unsigned char *)p, p->length);
if (bytes_wrote==p->length) {
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_send_eNBmeasurement_req: ENB_MEASUREMENT_REQ primitive sent successfully in DC-FIFO\n");
printk(" cell_id %u\n",p->nasRGDCPrimitive.eNBmeasurement_req.cell_id);
#endif
} else
printk("nasrg_ASCTL_DC_send_eNBmeasurement_req: Message transmission failure to DC-FIFO\n");
return bytes_wrote;
}
/***************************************************************************
Reception side
***************************************************************************/
//---------------------------------------------------------------------------
// Decode CONN_ESTABLISH_IND message from RRC
void nasrg_ASCTL_DC_decode_cx_establish_ind(struct cx_entity *cx, struct nas_rg_dc_element *p)
{
//---------------------------------------------------------------------------
int i;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_cx_establish - begin \n");
#endif
if (!cx || !p) {
printk("nasrg_ASCTL_DC_decode_cx_establish - input parameter is NULL \n");
return;
}
// End debug information
if (nasrg_ASCTL_DC_send_cx_establish_confirm(cx, ACCEPTED)>0) {
nasrg_TOOL_imei2iid(p->nasRGDCPrimitive.conn_establish_ind.InterfaceIMEI, (uint8_t *)cx->iid6);
cx->iid4=97; // A AUTOMATISER
cx->lcr = p->nasRGDCPrimitive.conn_establish_ind.localConnectionRef;
cx->state=NAS_CX_DCH;
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_cx_establish: CONN_ESTABLISH_IND reception\n");
printk(" primitive length %d\n",p->length);
printk(" Local Connection reference %d\n",p->nasRGDCPrimitive.conn_establish_ind.localConnectionRef);
printk(" IMEI ");
for (i=0; i<14; ++i)
printk("%u",p->nasRGDCPrimitive.conn_establish_ind.InterfaceIMEI[i]);
printk(" state ");
nasrg_TOOL_print_state(cx->state);
#endif
}
}
//---------------------------------------------------------------------------
// Decode CONN_RELEASE_IND message from RRC
void nasrg_ASCTL_DC_decode_cx_release_ind(struct cx_entity *cx, struct nas_rg_dc_element *p)
{
//---------------------------------------------------------------------------
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_cx_release - begin \n");
#endif
if (!cx || !p) {
printk("nasrg_ASCTL_DC_decode_cx_release - input parameter is NULL \n");
return;
}
// End debug information
cx->state=NAS_IDLE;
cx->iid4=0;
nasrg_TOOL_imei2iid(NAS_NULL_IMEI, (uint8_t *)cx->iid6);
nasrg_COMMON_flush_rb(cx);
nasrg_CLASS_flush_sclassifier(cx);
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_cx_release: CONN_RELEASE_IND reception\n");
printk(" Primitive length %u\n",p->length);
printk(" Local Connection reference %u\n",p->nasRGDCPrimitive.conn_release_ind.localConnectionRef);
printk(" Release cause %u\n",p->nasRGDCPrimitive.conn_release_ind.releaseCause);
nasrg_TOOL_print_state(cx->state);
#endif
}
//---------------------------------------------------------------------------
// Decode CONN_LOSS_IND message from RRC
void nasrg_ASCTL_DC_decode_cx_loss_ind(struct cx_entity *cx, struct nas_rg_dc_element *p)
{
//---------------------------------------------------------------------------
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_cx_loss - begin \n");
#endif
if (!cx || !p) {
printk("nasrg_ASCTL_DC_decode_cx_loss - input parameter is NULL \n");
return;
}
// End debug information
cx->state = NAS_IDLE;
cx->iid4=0;
nasrg_TOOL_imei2iid(NAS_NULL_IMEI, (uint8_t *)cx->iid6);
nasrg_COMMON_flush_rb(cx);
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_cx_loss: CONN_LOSS_IND reception\n");
printk(" Primitive length %u\n",(int)(p->length));
printk(" Local Connection reference %u\n",p->nasRGDCPrimitive.conn_loss_ind.localConnectionRef);
nasrg_TOOL_print_state(cx->state);
#endif
}
//---------------------------------------------------------------------------
// Decode RB_ESTABLISH_CNF message from RRC
void nasrg_ASCTL_DC_decode_rb_establish_cnf(struct cx_entity *cx, struct nas_rg_dc_element *p)
{
//---------------------------------------------------------------------------
struct rb_entity *rb;
int rb_id;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_rb_establish - begin \n");
#endif
if (!cx || !p) {
printk("nasrg_ASCTL_DC_decode_rb_establish - input parameter is NULL \n");
return;
}
// End debug information
rb_id = p->nasRGDCPrimitive.rb_establish_conf.rbId;
rb=nasrg_COMMON_search_rb(cx, rb_id - (NAS_RB_MAX_NUM * cx->lcr));
//
if (rb!=NULL) {
if (rb->state==NAS_CX_CONNECTING) {
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_rb_establish: RB_ESTABLISH_CNF received\n");
printk(" Primitive length %u\n", p->length);
printk(" Local Connection reference %u\n",p->nasRGDCPrimitive.rb_establish_conf.localConnectionRef);
printk(" RB Id %u\n",p->nasRGDCPrimitive.rb_establish_conf.rbId);
printk(" SAP Id %u\n",p->nasRGDCPrimitive.rb_establish_conf.sapId);
printk(" Status %u, Failure code %d, Cx state, RB state\n",p->nasRGDCPrimitive.rb_establish_conf.status, p->nasRGDCPrimitive.rb_establish_conf.fail_code);
nasrg_TOOL_print_state(cx->state);
nasrg_TOOL_print_state(rb->state);
#endif
switch (p->nasRGDCPrimitive.rb_establish_conf.status) {
case ACCEPTED:
rb->state = NAS_CX_DCH;
rb->countimer=1;
break;
case FAILURE:
printk("nasrg_ASCTL_DC_decode_rb_establish: RB_ESTABLISH_CNF rejected\n");
rb->state = NAS_CX_CONNECTING_FAILURE;
//delete rb
break;
default:
printk("nasrg_ASCTL_DC_decode_rb_establish: RB_ESTABLISH_CNF reception, invalid status\n");
}
} else
printk("nasrg_ASCTL_DC_decode_rb_establish: invalid state %u\n", cx->state);
} else
printk("nasrg_ASCTL_DC_decode_rb_establish: RB_ESTABLISH_CNF, No corresponding radio bearer\n");
}
//---------------------------------------------------------------------------
// Decode DATA_TRANSFER_IND message from RRC
void nasrg_ASCTL_DC_decode_data_transfer_ind(struct cx_entity *cx, struct nas_rg_dc_element *p, char *buffer)
{
//---------------------------------------------------------------------------
uint8_t nasrg_data[10];
unsigned int nas_length;
char data_type;
int bytes_read=0;
unsigned int peer_command;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_data_transfer - begin \n");
#endif
if (!cx || !p) {
printk("nasrg_ASCTL_DC_decode_data_transfer - input parameter is NULL \n");
return;
}
// End debug information
bytes_read=p->length;
// Get first character
nas_length = (p->nasRGDCPrimitive.data_transfer_ind.nasDataLength) -1;
#ifndef PDCP_USE_NETLINK
bytes_read += rtf_get(cx->sap[NAS_DC_OUTPUT_SAPI], &data_type, 1);
#else
memcpy (&data_type, (char *)(&buffer[bytes_read]), 1);
bytes_read ++;
#endif
//check if peer message
if (data_type =='A') {
// receive in a skbuff
//nasrg_COMMON_receive((p->length) + 1, nas_length, cx->sap[NAS_DC_OUTPUT_SAPI]); // original
#ifndef PDCP_USE_NETLINK
//void nasrg_COMMON_receive(uint16_t bytes_read, uint16_t payload_length, void *data_buffer, int rb_id, int sap);
// data_buffer is NULL because FIFO should be read directly in the skbuff (LITE has an intermediary buffer)
nasrg_COMMON_receive((p->length) + 1, nas_length, NULL, 2, cx->sap[NAS_DC_OUTPUT_SAPI]);
#else
//nasrg_COMMON_receive((p->length) + 1, nas_length, (unsigned char *)p+p->length+1, 2, 0);
nasrg_COMMON_receive((p->length) + 1, nas_length, (unsigned char *)(&buffer[bytes_read]), 2, 0);
#endif
} else {
// if FIFO, empty remaining data
#ifndef PDCP_USE_NETLINK
bytes_read += rtf_get(cx->sap[NAS_DC_OUTPUT_SAPI], (gpriv->rbuffer)+ (p->length), nas_length);
#endif
if (data_type=='Z') {
#ifndef PDCP_USE_NETLINK
memcpy (&nasrg_data, (char *)(gpriv->rbuffer)+ (p->length), 10);
#else
memcpy (&nasrg_data, (char *)(&buffer[bytes_read]), 10);
#endif
peer_command = (int)nasrg_data[0];
printk("nasrg_ASCTL_DC_decode_data_transfer: Received peer message %d %d \n", nasrg_data[0], peer_command);
nasrg_TOOL_print_buffer(nasrg_data, 10);
if (nasrg_data[0]== NAS_CMD_OPEN_RB) {
// open radio bearer
printk("nasrg_ASCTL_DC_decode_data_transfer: Opening Default Radio Bearer\n");
nasrg_ASCTL_start_default_rb(cx);
} else if (nasrg_data[0]== NAS_CMD_ENTER_SLEEP) {
printk("nasrg_ASCTL_DC_decode_data_transfer: Entering Sleep Mode\n");
cx->state = NAS_CX_RELEASING;
} else if (nasrg_data[0]== NAS_CMD_LEAVE_SLEEP) {
printk("nasrg_ASCTL_DC_decode_data_transfer: Leaving Sleep Mode\n");
cx->state = NAS_CX_DCH;
} else {
printk("\n\nnasrg_ASCTL_DC_decode_data_transfer: Unknown peer command\n");
}
} else
printk("nasrg_ASCTL_DC_decode_data_transfer: Error during reception of the message - Dropped\n");
}
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_data_transfer: DATA_TRANSFER_IND reception\n");
printk(" Primitive length %u\n", p->length);
printk(" Local Connection reference %u\n",p->nasRGDCPrimitive.data_transfer_ind.localConnectionRef);
printk(" Data Length %u\n", p->nasRGDCPrimitive.data_transfer_ind.nasDataLength);
nasrg_TOOL_print_state(cx->state);
#endif
}
//---------------------------------------------------------------------------
// Decode MBMS_BEARER_ESTABLISH_CNF message from RRC
void nasrg_ASCTL_DC_decode_mbms_bearer_establish_cnf(struct nas_rg_dc_element *p)
{
//---------------------------------------------------------------------------
int mbms_ix;
int rb_id;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_mbms_bearer_establish - begin \n");
#endif
if (!p) {
printk("nasrg_ASCTL_DC_decode_mbms_bearer_establish - input parameter is NULL \n");
return;
}
// End debug information
rb_id = p->nasRGDCPrimitive.mbms_establish_cnf.rbId;
mbms_ix = 0; // A revoir - find using cnxid...
if (rb_id == gpriv->mbms_rb[mbms_ix].mbms_rbId) {
switch (p->nasRGDCPrimitive.mbms_establish_cnf.status) {
case ACCEPTED:
gpriv->mbms_rb[mbms_ix].state = NAS_CX_DCH;
gpriv->mbms_rb[mbms_ix].rab_id = gpriv->mbms_rb[mbms_ix].mbms_rbId;
nasrg_ASCTL_start_mbmsclassifier(mbms_ix,&(gpriv->mbms_rb[mbms_ix]));
break;
case FAILURE:
printk("nasrg_ASCTL_DC_decode_mbms_bearer_establish: MBMS_BEARER_ESTABLISH_CNF rejected\n");
gpriv->mbms_rb[mbms_ix].state = NAS_CX_CONNECTING_FAILURE; //supprimer l'entree
break;
default:
printk("nasrg_ASCTL_DC_decode_mbms_bearer_establish: MBMS_BEARER_ESTABLISH_CNF reception, invalid status\n");
}
} else
printk(" nasrg_ASCTL_DC_decode_mbms_bearer_establish: invalid RB_Id %d\n", rb_id);
#ifdef NAS_DEBUG_DC
printk(" nasrg_ASCTL_DC_decode_mbms_bearer_establish: MBMS_BEARER_ESTABLISH_CNF reception\n");
printk(" Primitive length %u\n",p->length);
printk(" rb_id %d, status %d\n",p->nasRGDCPrimitive.mbms_establish_cnf.rbId, p->nasRGDCPrimitive.mbms_establish_cnf.status);
nasrg_TOOL_print_state(gpriv->mbms_rb[mbms_ix].state);
#endif
}
//---------------------------------------------------------------------------
// Decode MBMS_UE_NOTIFY_CNF message from RRC
void nasrg_ASCTL_DC_decode_mbms_ue_notify_cnf(struct cx_entity *cx, struct nas_rg_dc_element *p)
{
//---------------------------------------------------------------------------
int i, j, k;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_mbms_ue_notify - begin \n");
#endif
if (!cx || !p) {
printk("nasrg_ASCTL_DC_decode_mbms_ue_notify - input parameter is NULL \n");
return;
}
// End debug information
if (p->nasRGDCPrimitive.mbms_ue_notify_cnf.mbmsStatus == ACCEPTED) {
for (i = 0; i<NASRG_MBMS_SVCES_MAX; i++) {
if (cx->requested_joined_services[i] >=0) {
for (j = 0; j<NASRG_MBMS_SVCES_MAX; j++) {
if (cx->joined_services[j] ==-1) {
cx->joined_services[j]= cx->requested_joined_services[i];
cx->requested_joined_services[i]=-1;
break;
}
}
}
if (cx->requested_left_services[i] >=0) {
for (k = 0; k<NASRG_MBMS_SVCES_MAX; k++) {
if (cx->joined_services[k] == cx->requested_left_services[i]) {
cx->joined_services[k]=-1;
cx->requested_left_services[i]=-1;
break;
}
}
}
}
}
#ifdef NAS_DEBUG_DC
printk(" nasrg_ASCTL_DC_decode_mbms_ue_notify: MBMS_UE_NOTIFY_CNF reception\n");
printk(" Primitive length %u\n",p->length);
printk(" Local Connection reference %u\n",p->nasRGDCPrimitive.mbms_ue_notify_cnf.localConnectionRef);
printk(" MBMS Status: %d\n", p->nasRGDCPrimitive.mbms_ue_notify_cnf.mbmsStatus);
printk(" UE services currently joined \n");
for (i = 0; i<NASRG_MBMS_SVCES_MAX; i++)
printk ("%d * ", cx->joined_services[i]);
nasrg_TOOL_print_state(cx->state);
#endif
}
/*
msgToBuild->nasRgPrimitive.dc_sap_prim.nasRGDCPrimitive.eNBmeasurement_ind.cell_id = protocol_bs->rrc.rg_cell_id;
// next values are temp hard coded, to be replaced by real values
msgToBuild->nasRgPrimitive.dc_sap_prim.nasRGDCPrimitive.eNBmeasurement_ind.num_UEs = num_connected_UEs;
for (ix=0; ix<ralpriv->num_connected_UEs; ix++){
msgToBuild->nasRgPrimitive.dc_sap_prim.nasRGDCPrimitive.eNBmeasurement_ind.measures[ix].rlcBufferOccupancy = 100 - (30*ix);
msgToBuild->nasRgPrimitive.dc_sap_prim.nasRGDCPrimitive.eNBmeasurement_ind.measures[ix].scheduledPRB = 500 - (200*ix);
msgToBuild->nasRgPrimitive.dc_sap_prim.nasRGDCPrimitive.eNBmeasurement_ind.measures[ix].totalDataVolume = 640000 + (160000*ix);
}
msgToBuild->nasRgPrimitive.dc_sap_prim.nasRGDCPrimitive.eNBmeasurement_ind.totalNumPRBs = 1000;
*/
//---------------------------------------------------------------------------
// Decode ENB_MEASUREMENT_IND message from RRC
void nasrg_ASCTL_DC_decode_eNBmeasurement_ind(struct nas_rg_dc_element *p)
{
//---------------------------------------------------------------------------
uint8_t i;
// Start debug information
#ifdef NAS_DEBUG_DC
printk("nasrg_ASCTL_DC_decode_eNBmeasurement_ind - begin \n");
#endif
if (!p) {
printk("nasrg_ASCTL_DC_decode_eNBmeasurement_ind - input parameter p is NULL \n");
return;
}
// End debug information
#ifdef NAS_DEBUG_DC_DETAIL
printk(" nasrg_ASCTL_DC_decode_eNBmeasurement_ind : ENB_MEASUREMENT_IND reception\n");
printk(" Measured Cell: %u\n", p->nasRGDCPrimitive.eNBmeasurement_ind.cell_id);
printk(" Number of Connected Mobiles: %u\n", p->nasRGDCPrimitive.eNBmeasurement_ind.num_UEs);
for (i=0; i<p->nasRGDCPrimitive.eNBmeasurement_ind.num_UEs; ++i) {
printk(" UE[%u]: rlcBufferOccupancy %u, scheduledPRB: %u, totalDataVolume: %u\n", i,
p->nasRGDCPrimitive.eNBmeasurement_ind.measures[i].rlcBufferOccupancy,
p->nasRGDCPrimitive.eNBmeasurement_ind.measures[i].scheduledPRB,
p->nasRGDCPrimitive.eNBmeasurement_ind.measures[i].totalDataVolume);
}
printk(" Total number of PRBs: %u\n", p->nasRGDCPrimitive.eNBmeasurement_ind.totalNumPRBs);
#endif
// store Measures
gpriv->measured_cell_id = p->nasRGDCPrimitive.eNBmeasurement_ind.cell_id;
gpriv->num_UEs = p->nasRGDCPrimitive.eNBmeasurement_ind.num_UEs;
for (i=0; i<gpriv-> num_UEs; ++i) {
gpriv->rlcBufferOccupancy[i] = p->nasRGDCPrimitive.eNBmeasurement_ind.measures[i].rlcBufferOccupancy;
gpriv->scheduledPRB[i] += p->nasRGDCPrimitive.eNBmeasurement_ind.measures[i].scheduledPRB;
gpriv->totalDataVolume[i] += p->nasRGDCPrimitive.eNBmeasurement_ind.measures[i].totalDataVolume;
}
gpriv->totalNumPRBs += p->nasRGDCPrimitive.eNBmeasurement_ind.totalNumPRBs;
}
//---------------------------------------------------------------------------
// Check if anything in DC FIFO and process it (RG Finite State Machine)
int nasrg_ASCTL_DC_receive(struct cx_entity *cx, char *buffer)
{
//---------------------------------------------------------------------------
int bytes_read=0;
// Start debug information
#ifdef NAS_DEBUG_DC_DETAIL
printk("nasrg_ASCTL_DC_receive - begin \n");
#endif
if (!cx) {
printk("nasrg_ASCTL_DC_receive - input parameter cx is NULL \n");
return 0;
}
// End debug information
#ifndef PDCP_USE_NETLINK
bytes_read = rtf_get(cx->sap[NAS_DC_OUTPUT_SAPI] , gpriv->rbuffer, NAS_TL_SIZE);
#else
bytes_read = NAS_TL_SIZE;
#endif
if (bytes_read>0) {
struct nas_rg_dc_element *p;
#ifndef PDCP_USE_NETLINK
p= (struct nas_rg_dc_element *)(gpriv->rbuffer);
//get the rest of the primitive
bytes_read += rtf_get(cx->sap[NAS_DC_OUTPUT_SAPI], (uint8_t *)p+NAS_TL_SIZE, p->length-NAS_TL_SIZE);
if (bytes_read!=p->length) {
printk("nasrg_ASCTL_DC_receive: Problem while reading primitive's header\n");
return bytes_read;
}
#else
p= (struct nas_rg_dc_element *)(buffer);
bytes_read=p->length;
#endif
switch (p->type) {
case CONN_ESTABLISH_IND :
if (p->nasRGDCPrimitive.conn_establish_ind.localConnectionRef!=cx->lcr)
printk("nasrg_ASCTL_DC_receive: CONN_ESTABLISH_IND reception, Local connection reference not correct %u\n", p->nasRGDCPrimitive.conn_establish_ind.localConnectionRef);
else {
switch(cx->state) {
case NAS_IDLE:
nasrg_ASCTL_DC_decode_cx_establish_ind(cx,p);
break;
default:
printk("nasrg_ASCTL_DC_receive: CONN_ESTABLISH_IND reception, invalid state %u\n", cx->state);
}
}
break;
case CONN_RELEASE_IND :
if (p->nasRGDCPrimitive.conn_release_ind.localConnectionRef!=cx->lcr)
printk("nasrg_ASCTL_DC_receive: CONN_RELEASE_IND reception, Local connection reference not correct %u\n", p->nasRGDCPrimitive.conn_release_ind.localConnectionRef);
else {
switch(cx->state) {
case NAS_CX_DCH:
nasrg_ASCTL_DC_decode_cx_release_ind(cx,p);
break;
default:
printk("nasrg_ASCTL_DC_receive: CONN_RELEASE_IND reception, invalid state %u\n", cx->state);
}
}
break;
case CONN_LOSS_IND:
if (p->nasRGDCPrimitive.conn_loss_ind.localConnectionRef!=cx->lcr)
printk("nasrg_ASCTL_DC_receive: CONN_LOSS_IND reception, Local connection reference not correct %u\n", p->nasRGDCPrimitive.conn_loss_ind.localConnectionRef);
else {
switch(cx->state) {
case NAS_CX_DCH:
nasrg_ASCTL_DC_decode_cx_loss_ind(cx,p);
break;
default:
printk("nasrg_ASCTL_DC_receive: CONN_LOSS_IND reception, invalid state %u\n", cx->state);
}
}
break;
case RB_ESTABLISH_CNF:
if (p->nasRGDCPrimitive.rb_establish_conf.localConnectionRef!=cx->lcr)
printk("nasrg_ASCTL_DC_receive: RB_ESTABLISH_CNF reception, Local connection reference not correct %u\n", p->nasRGDCPrimitive.rb_establish_conf.localConnectionRef);
else {
switch(cx->state) {
case NAS_CX_DCH:
nasrg_ASCTL_DC_decode_rb_establish_cnf(cx,p);
#ifdef NAS_AUTO_MBMS
nasrg_ASCTL_start_default_ue_notification(cx);
#endif
break;
default:
printk("nasrg_ASCTL_DC_receive: RB_ESTABLISH_CNF reception, invalid state %u\n", cx->state);
}
}
break;
case DATA_TRANSFER_IND:
if (p->nasRGDCPrimitive.data_transfer_ind.localConnectionRef!=cx->lcr)
printk("nasrg_ASCTL_DC_receive: DATA_TRANSFER_IND reception, Local connection reference not correct %u\n", p->nasRGDCPrimitive.rb_establish_conf.localConnectionRef);
else {
switch(cx->state) {
case NAS_CX_DCH:
case NAS_CX_RELEASING:
nasrg_ASCTL_DC_decode_data_transfer_ind(cx,p,buffer);
break;
default:
printk("nasrg_ASCTL_DC_receive: DATA_TRANSFER_IND reception, invalid state %u\n", cx->state);
}
}
break;
// Temp - Should be in uplink GC-SAP
case MBMS_BEARER_ESTABLISH_CNF:
// if (p->nasRGDCPrimitive.mbms_ue_notify_cnf.localConnectionRef!=cx->lcr)
// printk("nasrg_ASCTL_DC_receive: MBMS_BEARER_ESTABLISH_CNF reception, Local connection reference not correct %u\n", p->nasRGDCPrimitive.rb_establish_conf.localConnectionRef);
// else
nasrg_ASCTL_DC_decode_mbms_bearer_establish_cnf(p);
break;
case MBMS_UE_NOTIFY_CNF:
if (p->nasRGDCPrimitive.mbms_ue_notify_cnf.localConnectionRef!=cx->lcr)
printk("nasrg_ASCTL_DC_receive: MBMS_UE_NOTIFY_CNF reception, Local connection reference not correct %u\n", p->nasRGDCPrimitive.rb_establish_conf.localConnectionRef);
else {
switch(cx->state) {
case NAS_CX_DCH:
nasrg_ASCTL_DC_decode_mbms_ue_notify_cnf(cx,p);
/* //Temp
nasrg_ASCTL_start_default_mbms_service();*/
break;
default:
printk("nasrg_ASCTL_DC_receive: MBMS_UE_NOTIFY_CNF reception, invalid state %u\n", cx->state);
}
}
break;
// Temp - Should be in uplink GC-SAP
case ENB_MEASUREMENT_IND :
// if (p->nasRGDCPrimitive.eNBmeasurement_ind.localConnectionRef!=cx->lcr)
// printk("nasrg_ASCTL_DC_receive: ENB_MEASUREMENT_IND reception, Local connection reference not correct %u\n", p->nasRGDCPrimitive.eNBmeasurement_ind.localConnectionRef);
// else
nasrg_ASCTL_DC_decode_eNBmeasurement_ind(p);
break;
default :
printk("nasrg_ASCTL_DC_receive: Invalid message received\n");
}
}
return bytes_read;
}
#endif