/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.0 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*************************************************************************** nas_mesh.c - description ------------------- copyright : (C) 2003-2008 by Eurecom email : navid.nikaein@eurecom.fr lionel.gauthier@eurecom.fr raymond.knopp@eurecom.fr ***************************************************************************/ #include "local.h" #include "proto_extern.h" //--------------------------------------------------------------------------- void nas_mesh_init(int inst) { //--------------------------------------------------------------------------- // struct cx_entity *cx; printk("NAS_MESH_INIT Complete\n"); // Request the establishment of a connexion // cx=nas_COMMON_search_cx(0); // if (cx==NULL) // { // printk("NAS_MESH_INIT: connexion failure\n"); // return; // } // cx->countimer=5; // cx->state=NAS_CX_CONNECTING; // cx->retry=0; // cx->cellid=25; } //--------------------------------------------------------------------------- //For demo, add automatically a classifier //Equivalent to class add send 0 -f qos <x> -cr 0 void nas_mesh_start_broadcast_sclassifier(struct cx_entity *cx,struct rb_entity *rb) { struct classifier_entity *gc; // Start debug information #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_BROADCAST_SCLASS - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - input parameter cx is NULL \n"); #endif return; } if (rb==NULL) { #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - input parameter rb is NULL \n"); #endif return; } // End debug information gc=nas_CLASS_add_sclassifier(cx, NAS_DSCP_DEFAULT, 6); // gc=nas_CLASS_add_sclassifier(cx, 5, 0); if (gc==NULL) { #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - Classifier not added \n"); #endif return; } gc->fct = nas_COMMON_QOS_send; gc->rab_id =rb->rab_id; //5 gc->rb= rb; gc->version = NAS_VERSION_DEFAULT; gc->protocol= NAS_PROTOCOL_ICMP6; // gc->sport = NAS_PORT_DEFAULT; // gc->dport = NAS_PORT_DEFAULT; #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - end \n"); nas_print_classifier(gc); #endif } void nas_mesh_start_default_sclassifier(struct cx_entity *cx,struct rb_entity *rb) { //--------------------------------------------------------------------------- #ifdef DEMO_3GSM struct classifier_entity *gc; // Start debug information #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - input parameter cx is NULL \n"); #endif return; } if (rb==NULL) { #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - input parameter rb is NULL \n"); #endif return; } // End debug information gc=nas_CLASS_add_sclassifier(cx, NAS_DSCP_DEFAULT, 5); // gc=nas_CLASS_add_sclassifier(cx, 5, 0); if (gc==NULL) { #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - Classifier not added \n"); #endif return; } gc->fct = nas_COMMON_QOS_send; gc->rab_id =rb->rab_id; //5 gc->rb= rb; gc->version = NAS_VERSION_DEFAULT; gc->protocol= NAS_PROTOCOL_DEFAULT; // gc->sport = NAS_PORT_DEFAULT; // gc->dport = NAS_PORT_DEFAULT; #ifdef NAS_DEBUG_CLASS printk("NAS_MESH_START_DEFAULT_SCLASS - end \n"); nas_print_classifier(gc); #endif #endif } //--------------------------------------------------------------------------- void nas_mesh_timer(unsigned long data) { //--------------------------------------------------------------------------- struct nas_priv *gpriv=(struct nas_priv *) data; uint8_t cxi; struct cx_entity *cx; struct rb_entity *rb; // spin_lock(&gpriv->lock); #ifdef NAS_DEBUG_TIMER printk("NAS_MESH_TIMER - begin \n"); #endif (gpriv->timer).function=nas_mesh_timer; (gpriv->timer).expires=jiffies+NAS_TIMER_TICK; (gpriv->timer).data=data; return; for (cxi=0; cxi<NAS_CX_MAX; ++cxi) { cx=gpriv->cx+cxi; if (cx==NULL) { #ifdef NAS_DEBUG_TIMER printk("NAS_MESH_TIMER - No pointer for connection %d \n", cxi); #endif continue; } if (cx->countimer!=NAS_TIMER_IDLE) { #ifdef NAS_DEBUG_TIMER printk("NAS_MESH_TIMER: lcr %u, countimer %u\n", cx->lcr, cx->countimer); #endif if (cx->countimer==0) { switch (cx->state) { case NAS_CX_CONNECTING: case NAS_CX_CONNECTING_FAILURE: if (cx->retry<gpriv->retry_limit) nas_mesh_DC_send_cx_establish_request(cx,gpriv); else { printk("NAS_MESH_TIMER: Establishment failure\n"); cx->state=NAS_IDLE; cx->retry=0; cx->countimer=NAS_TIMER_IDLE; } break; case NAS_CX_RELEASING_FAILURE: nas_mesh_DC_send_cx_release_request(cx,gpriv); break; default: printk("NAS_MESH_TIMER: default value\n"); cx->countimer=NAS_TIMER_IDLE; } } else --cx->countimer; } for (rb=cx->rb; rb!=NULL; rb=rb->next) { if (rb->countimer!=NAS_TIMER_IDLE) { #ifdef NAS_DEBUG_TIMER printk("NAS_MESH_TIMER : rb countimer %d, rb state %d\n", rb->countimer, rb->state); #endif if (rb->countimer==0) { switch (rb->state) { case NAS_RB_DCH: nas_mesh_start_default_sclassifier(cx, rb); rb->countimer=NAS_TIMER_IDLE; break; default: rb->countimer=NAS_TIMER_IDLE; } } else { --rb->countimer; printk("NAS_MESH_TIMER : rb countimer-- %d, rb state %d\n", rb->countimer, rb->state); } } } } // add_timer(&gpriv->timer); // spin_unlock(&gpriv->lock); } //--------------------------------------------------------------------------- // Request the establishment of a connexion (DC channel) int nas_mesh_DC_send_cx_establish_request(struct cx_entity *cx,struct nas_priv *gpriv) { //--------------------------------------------------------------------------- struct nas_ue_dc_element *p; int bytes_wrote=0; // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_CX_ESTABLISH - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_CX_ESTABLISH - input parameter cx is NULL \n"); #endif return NAS_ERROR_NOTCORRECTVALUE; } // End debug information switch (cx->state) { case NAS_CX_CONNECTING: case NAS_CX_CONNECTING_FAILURE: case NAS_IDLE: p= (struct nas_ue_dc_element *)(gpriv->xbuffer); p->type = CONN_ESTABLISH_REQ; p->length = NAS_TL_SIZE + sizeof(struct NASConnEstablishReq); p->nasUEDCPrimitive.conn_establish_req.localConnectionRef = cx->lcr; p->nasUEDCPrimitive.conn_establish_req.cellId = cx->cellid; #ifdef NAS_DEBUG_DC printk ("\nCONN_ESTABLISH_REQ Buffer to Xmit: "); nas_tool_print_buffer((char *)p,p->length); #endif ++cx->retry; #ifdef PDCP_USE_NETLINK #else // bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); #endif cx->countimer=gpriv->timer_establishment; if (bytes_wrote==p->length) { cx->state=NAS_CX_CONNECTING; #ifdef NAS_DEBUG_DC printk("nas_mesh_DC_send_cx_establish_req: Message sent successfully in DC-FIFO\n"); printk(" Local Connection reference %u\n", p->nasUEDCPrimitive.conn_establish_req.localConnectionRef); printk(" Cell Identification %u\n", p->nasUEDCPrimitive.conn_establish_req.cellId); print_TOOL_state(cx->state); #endif } else { cx->state=NAS_CX_CONNECTING_FAILURE; printk("NAS_MESH_DC_SEND_CX_ESTABLISHMENT_REQUEST: Message sent failure in DC-FIFO\n"); print_TOOL_state(cx->state); } return bytes_wrote; default: return -NAS_ERROR_NOTIDLE; #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_CX_ESTABLISH - NAS_ERROR_NOTIDLE \n"); #endif } } //--------------------------------------------------------------------------- // Request the release of a connexion (DC channel) int nas_mesh_DC_send_cx_release_request(struct cx_entity *cx, struct nas_priv *gpriv) { //--------------------------------------------------------------------------- struct nas_ue_dc_element *p; int bytes_wrote=0; // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_CX_RELEASE - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_CX_RELEASE - input parameter cx is NULL \n"); #endif return NAS_ERROR_NOTCORRECTVALUE; } // End debug information switch (cx->state) { case NAS_CX_RELEASING_FAILURE: case NAS_CX_DCH: p= (struct nas_ue_dc_element *)(gpriv->xbuffer); p->type = CONN_RELEASE_REQ; p->length = NAS_TL_SIZE + sizeof(struct NASConnReleaseReq); p->nasUEDCPrimitive.conn_release_req.localConnectionRef = cx->lcr; p->nasUEDCPrimitive.conn_release_req.releaseCause = NAS_CX_RELEASE_UNDEF_CAUSE; #ifdef PDCP_USE_NETLINK #else // bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); #endif if (bytes_wrote==p->length) { cx->state=NAS_IDLE; cx->iid4=0; // nas_TOOL_imei2iid(NAS_NULL_IMEI, (uint8_t *)cx->iid6); nas_COMMON_flush_rb(cx); #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_CX_RELEASE_REQUEST: Message sent successfully in DC-FIFO\n"); printk(" Local Connection Reference %u\n", p->nasUEDCPrimitive.conn_release_req.localConnectionRef); printk(" Release Cause %u\n", p->nasUEDCPrimitive.conn_release_req.releaseCause); print_TOOL_state(cx->state); #endif } else { ++cx->retry; cx->countimer=gpriv->timer_release; cx->state=NAS_CX_RELEASING_FAILURE; printk("NAS_MESH_DC_SEND_CX_RELEASE_REQUEST: Message sent failure in DC-FIFO\n"); print_TOOL_state(cx->state); } return bytes_wrote; default: return -NAS_ERROR_NOTCONNECTED; #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_CX_RELEASE_REQUEST - NAS_ERROR_NOTCONNECTED \n"); #endif } } //--------------------------------------------------------------------------- // Request the transfer of data (DC SAP) void nas_mesh_DC_send_sig_data_request(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc, int inst, struct nas_priv *gpriv) { //--------------------------------------------------------------------------- struct nas_ue_dc_element *p; //char data_type = 'A'; int bytes_wrote=0; // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_SIG - begin \n"); #endif if (skb==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_SIG - input parameter skb is NULL \n"); #endif return; } if (gc==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_SIG - input parameter gc is NULL \n"); #endif return; } if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_SIG - input parameter cx is NULL \n"); #endif return; } // End debug information if (cx->state!=NAS_CX_DCH) { printk("NAS_MESH_DC_SEND_SIG: Not connected, so the message is dropped\n"); ++gpriv->stats.tx_dropped; return; } p = (struct nas_ue_dc_element *)(gpriv->xbuffer); p->type = DATA_TRANSFER_REQ; p->length = NAS_TL_SIZE + sizeof(struct NASDataReq); p->nasUEDCPrimitive.data_transfer_req.localConnectionRef = cx->lcr; p->nasUEDCPrimitive.data_transfer_req.priority = 3; // TBD p->nasUEDCPrimitive.data_transfer_req.nasDataLength = (skb->len)+1; //adds category character #ifdef PDCP_USE_NETLINK #else // bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); #endif if (bytes_wrote!=p->length) { printk("NAS_MESH_DC_SEND_SIG: Header sent failure in DC-FIFO\n"); return; } #ifdef PDCP_USE_NETLINK #else // bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], &data_type, 1); // bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], skb->data, skb->len); #endif if (bytes_wrote != p->length + skb->len + 1) { printk("NAS_MESH_DC_SEND_SIG: Data sent failure in DC-FIFO\n"); return; } gpriv->stats.tx_bytes += skb->len; gpriv->stats.tx_packets ++; #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_SEND_SIG - end \n"); #endif } //--------------------------------------------------------------------------- // Request the transfer of data (DC SAP) void nas_mesh_DC_send_peer_sig_data_request(struct cx_entity *cx, uint8_t sig_category, struct nas_priv *gpriv) { //--------------------------------------------------------------------------- struct nas_ue_dc_element *p; uint8_t nas_data[10]; unsigned int nas_length; //char data_type = 'Z'; int bytes_wrote=0; // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_PEER_SEND_SIG - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_PEER_SEND_SIG - input parameter cx is NULL \n"); #endif return; } // End debug information if (cx->state!=NAS_CX_DCH) { printk("NAS_MESH_DC_PEER_SEND_SIG: Not connected, so the message is dropped\n"); return; } // Initialize peer message nas_length = 10; memset (nas_data, 0, nas_length); nas_data[0]= sig_category; // p = (struct nas_ue_dc_element *)(gpriv->xbuffer); p->type = DATA_TRANSFER_REQ; p->length = NAS_TL_SIZE + sizeof(struct NASDataReq); p->nasUEDCPrimitive.data_transfer_req.localConnectionRef = cx->lcr; p->nasUEDCPrimitive.data_transfer_req.priority = 3; // TBD p->nasUEDCPrimitive.data_transfer_req.nasDataLength = (nas_length)+1; //adds category character #ifdef PDCP_USE_NETLINK #else // bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); #endif if (bytes_wrote!=p->length) { printk("NAS_MESH_DC_PEER_SEND_SIG: Header sent failure in DC-FIFO\n"); return; } #ifdef PDCP_USE_NETLINK #else // bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], &data_type, 1); // bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], (char *)nas_data, nas_length); #endif if (bytes_wrote != p->length + nas_length + 1) { printk("NAS_MESH_DC_PEER_SEND_SIG: Data sent failure in DC-FIFO\n"); return; } #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_PEER_SEND_SIG - end \n"); #endif } //--------------------------------------------------------------------------- // Decode CONN_ESTABLISH_RESP message from RRC void nas_mesh_DC_decode_cx_establish_resp(struct cx_entity *cx, struct nas_ue_dc_element *p,struct nas_priv *gpriv) { //--------------------------------------------------------------------------- uint8_t sig_category; // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_CX_ESTABLISH - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_CX_ESTABLISH - input parameter cx is NULL \n"); #endif return; } if (p==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_CX_ESTABLISH - input parameter p is NULL \n"); #endif return; } // End debug information cx->retry=0; if (p->nasUEDCPrimitive.conn_establish_resp.status == TERMINATED) { cx->state=NAS_CX_DCH; //to be changed to NAS_CX_FACH cx->iid4=1; //nas_TOOL_imei2iid(NAS_RG_IMEI, (uint8_t *)cx->iid6); sig_category = NAS_CMD_OPEN_RB; //For demo, add automatically a radio bearer #ifdef DEMO_3GSM printk("NAS_MESH_DC_DECODE_CX_ESTABLISH - sig_category %u \n", sig_category); nas_mesh_DC_send_peer_sig_data_request(cx, sig_category,gpriv); #endif } else { cx->state=NAS_IDLE; } #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_RECEIVE: CONN_ESTABLISH_RESP\n"); printk("Local Connection reference %u\n",p->nasUEDCPrimitive.conn_establish_resp.localConnectionRef); printk("Connection Establishment status %u\n",p->nasUEDCPrimitive.conn_establish_resp.status); print_TOOL_state(cx->state); #endif } //--------------------------------------------------------------------------- // Decode CONN_LOSS_IND message from RRC void nas_mesh_DC_decode_cx_loss_ind(struct cx_entity *cx, struct nas_ue_dc_element *p) { //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_CX_LOSS - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_CX_LOSS - input parameter cx is NULL \n"); #endif return; } if (p==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_CX_LOSS - input parameter p is NULL \n"); #endif return; } // End debug information cx->state=NAS_IDLE; cx->iid4=0; //nas_TOOL_imei2iid(NAS_NULL_IMEI, (uint8_t *)cx->iid6); nas_COMMON_flush_rb(cx); #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_RECEIVE: CONN_LOSS_IND reception\n"); printk(" Local Connection reference %u\n", p->nasUEDCPrimitive.conn_loss_ind.localConnectionRef); print_TOOL_state(cx->state); #endif } //--------------------------------------------------------------------------- // Decode CONN_RELEASE_IND message from RRC //void nas_mesh_DC_decode_cx_release_ind(struct cx_entity *cx, struct nas_ue_dc_element *p){ //--------------------------------------------------------------------------- // printk("\t\tCONN_RELEASE_IND\n"); // printk("\t\tLocal Connection reference %u\n", p->nasUEDCPrimitive.conn_release_ind.localConnectionRef); // printk("\t\tRelease cause %u\n", p->nasRGDCPrimitive.conn_release_ind.releaseCause); // if (gpriv->cx[cxi].state==NAS_CX_DCH) // { // gpriv->cx[cxi].state=NAS_IDLE; // printk("\t\tMobile no more connected\n"); // return bytes_read; // } // printk("\t\tIncoherent state %u\n", gpriv->cx[cxi].state); // return bytes_read; //} //--------------------------------------------------------------------------- // Decode DATA_TRANSFER_IND message from RRC void nas_mesh_DC_decode_sig_data_ind(struct cx_entity *cx, struct nas_ue_dc_element *p) { //--------------------------------------------------------------------------- // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_SIG_DATA_IND - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_SIG_DATA_IND - input parameter cx is NULL \n"); #endif return; } if (p==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_SIG_DATA_IND - input parameter p is NULL \n"); #endif return; } // End debug information #ifndef PDCP_USE_NETLINK // nas_COMMON_receive(p->length, p->nasUEDCPrimitive.data_transfer_ind.nasDataLength, cx->sap[NAS_DC_OUTPUT_SAPI]); #endif #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_RECEIVE: DATA_TRANSFER_IND reception\n"); printk(" Local Connection reference %u\n",p->nasUEDCPrimitive.data_transfer_ind.localConnectionRef); printk(" Signaling Priority %u\n",p->nasUEDCPrimitive.data_transfer_ind.priority); printk(" NAS Data length %u\n",p->nasUEDCPrimitive.data_transfer_ind.nasDataLength); printk(" NAS Data string %s\n", (uint8_t *)p+p->length); #endif } //--------------------------------------------------------------------------- // Decode RB_ESTABLISH_IND message from RRC void nas_mesh_DC_decode_rb_establish_ind(struct cx_entity *cx, struct nas_ue_dc_element *p,struct nas_priv *gpriv) { //--------------------------------------------------------------------------- struct rb_entity *rb; // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_RB_ESTABLISH_IND - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_RB_ESTABLISH_IND - input parameter cx is NULL \n"); #endif return; } if (p==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_RB_ESTABLISH_IND - input parameter p is NULL \n"); #endif return; } // End debug information rb=nas_COMMON_search_rb(cx, p->nasUEDCPrimitive.rb_release_ind.rbId); if (rb==NULL) { rb=nas_COMMON_add_rb(cx, p->nasUEDCPrimitive.rb_establish_ind.rbId, p->nasUEDCPrimitive.rb_establish_ind.QoSclass); rb->state=NAS_RB_DCH; cx->state=NAS_CX_DCH; //For demo, add automatically a classifier #ifdef DEMO_3GSM rb->countimer=gpriv->timer_establishment+10; #endif #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_RB_ESTABLISH_IND: RB_ESTABLISH_IND reception\n"); printk(" Local Connection reference %u\n",p->nasUEDCPrimitive.rb_establish_ind.localConnectionRef); printk(" Radio Bearer Identity %u \n",p->nasUEDCPrimitive.rb_establish_ind.rbId); printk(" QoS Traffic Class %u\n",p->nasUEDCPrimitive.rb_establish_ind.QoSclass); printk(" DSCP Code %u\n",p->nasUEDCPrimitive.rb_establish_ind.dscp); printk(" SAP Id %u\n",p->nasUEDCPrimitive.rb_establish_ind.sapId); print_TOOL_state(cx->state); nas_print_rb_entity(rb); #endif } else printk("NAS_MESH_DC_DECODE_RB_ESTABLISH_IND: RB_ESTABLISH_IND reception, Radio bearer already opened\n"); } //--------------------------------------------------------------------------- // Decode RB_RELEASE_IND message from RRC void nas_mesh_DC_decode_rb_release_ind(struct cx_entity *cx, struct nas_ue_dc_element *p) { //--------------------------------------------------------------------------- struct rb_entity *rb; // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_RB_RELEASE_IND - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_RB_RELEASE_IND - input parameter cx is NULL \n"); #endif return; } if (p==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_RB_RELEASE_IND - input parameter p is NULL \n"); #endif return; } // End debug information rb=nas_COMMON_search_rb(cx, p->nasUEDCPrimitive.rb_release_ind.rbId); if (rb!=NULL) { rb->state=NAS_IDLE; //needs also to flush corresponding control block to be coherent with add_rb #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_RB_RELEASE_IND: RB_RELEASE_IND reception\n"); printk("Local Connection reference %u\n",p->nasUEDCPrimitive.rb_release_ind.localConnectionRef); printk("Radio Bearer Identity %u\n",p->nasUEDCPrimitive.rb_release_ind.rbId); print_TOOL_state(cx->state); #endif } else printk("NAS_DC_RG_RECEIVE: RB_RELEASE_IND reception, No corresponding radio bearer\n"); } //--------------------------------------------------------------------------- // Decode MEASUREMENT_IND message from RRC void nas_mesh_DC_decode_measurement_ind(struct cx_entity *cx, struct nas_ue_dc_element *p) { //--------------------------------------------------------------------------- uint8_t i; // Start debug information #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_MEASUREMENT_IND - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_MEASUREMENT_IND - input parameter cx is NULL \n"); #endif return; } if (p==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_DECODE_MEASUREMENT_IND - input parameter p is NULL \n"); #endif return; } // End debug information #ifdef NAS_DEBUG_DC_MEASURE printk("NAS_MESH_DC_RECEIVE: MEASUREMENT_IND reception\n"); printk(" Local Connection reference: %u\n", p->nasUEDCPrimitive.measurement_ind.localConnectionRef); printk(" Number of RGs: %u\n", p->nasUEDCPrimitive.measurement_ind.nb_rg); print_TOOL_state(cx->state); for (i=0; i<p->nasUEDCPrimitive.measurement_ind.nb_rg; ++i) { printk(" RG[%u]: Cell_Id %u, Level: %u\n", i, p->nasUEDCPrimitive.measurement_ind.measures[i].cell_id, p->nasUEDCPrimitive.measurement_ind.measures[i].level); } #endif //NAS_DEBUG_DC_MEASURE cx->num_measures = p->nasUEDCPrimitive.measurement_ind.nb_rg; for (i=0; i<cx->num_measures; i++) { cx->meas_cell_id[i]= (int)(p->nasUEDCPrimitive.measurement_ind.measures[i].cell_id); cx->meas_level[i] = (int)(p->nasUEDCPrimitive.measurement_ind.measures[i].level); //npriv->provider_id[i]=; } cx->provider_id[0]=25; cx->provider_id[1]=1; cx->provider_id[2]=25; } //--------------------------------------------------------------------------- // Check if anything in DC FIFO and decode it (MESH) int nas_mesh_DC_receive(struct cx_entity *cx,struct nas_priv *gpriv) { //--------------------------------------------------------------------------- // Start debug information int bytes_read=0; #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_RECEIVE - begin \n"); #endif if (cx==NULL) { #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_RECEIVE - input parameter cx is NULL \n"); #endif return NAS_ERROR_NOTCORRECTVALUE; } // End debug information #ifdef PDCP_USE_NETLINK #else // bytes_read = rtf_get(cx->sap[NAS_DC_OUTPUT_SAPI] , gpriv->rbuffer, NAS_TL_SIZE); #endif if (bytes_read>0) { struct nas_ue_dc_element *p; p= (struct nas_ue_dc_element *)(gpriv->rbuffer); //get the rest of the primitive #ifdef PDCP_USE_NETLINK #else // bytes_read += rtf_get(cx->sap[NAS_DC_OUTPUT_SAPI], (uint8_t *)p+NAS_TL_SIZE, p->length-NAS_TL_SIZE); #endif if (bytes_read!=p->length) { printk("NAS_MESH_DC_RECEIVE: Problem while reading primitive header\n"); return bytes_read; } switch (p->type) { case CONN_ESTABLISH_RESP : if (p->nasUEDCPrimitive.conn_establish_resp.localConnectionRef!=cx->lcr) printk("NAS_MESH_DC_RECEIVE: CONN_ESTABLISH_RESP, Local connection reference not correct %u\n",p->nasUEDCPrimitive.conn_establish_resp.localConnectionRef); else { switch (cx->state) { case NAS_CX_CONNECTING: nas_mesh_DC_decode_cx_establish_resp(cx,p,gpriv); // process message break; default: printk("NAS_MESH_DC_RECEIVE: CONN_ESTABLISH_RESP reception, Invalid state %u\n", cx->state); } } break; case CONN_LOSS_IND : if (p->nasUEDCPrimitive.conn_loss_ind.localConnectionRef!=cx->lcr) printk("NAS_MESH_DC_RECEIVE: CONN_LOSS_IND reception, Local connection reference not correct %u\n", p->nasUEDCPrimitive.conn_loss_ind.localConnectionRef); else { switch (cx->state) { case NAS_CX_RELEASING_FAILURE: cx->retry=0; case NAS_CX_DCH: nas_mesh_DC_decode_cx_loss_ind(cx,p); // process message break; default: printk("NAS_MESH_DC_RECEIVE: CONN_LOSS_IND reception, Invalid state %u", cx->state); } } break; // case CONN_RELEASE_IND : // break; case DATA_TRANSFER_IND : if (p->nasUEDCPrimitive.data_transfer_ind.localConnectionRef!=cx->lcr) printk("NAS_MESH_DC_RECEIVE: DATA_TRANSFER_IND reception, Local connection reference not correct %u\n", p->nasUEDCPrimitive.conn_loss_ind.localConnectionRef); else { switch (cx->state) { case NAS_CX_FACH: case NAS_CX_DCH: nas_mesh_DC_decode_sig_data_ind(cx,p); // process message break; default: printk("NAS_MESH_DC_RECEIVE: DATA_TRANSFER_IND reception, Invalid state %u", cx->state); } } break; case RB_ESTABLISH_IND : if (p->nasUEDCPrimitive.rb_establish_ind.localConnectionRef!=cx->lcr) printk("NAS_MESH_DC_RECEIVE: RB_ESTABLISH_IND reception, Local connexion reference not correct %u\n", p->nasUEDCPrimitive.rb_establish_ind.localConnectionRef); else { switch (cx->state) { case NAS_CX_FACH: case NAS_CX_DCH: nas_mesh_DC_decode_rb_establish_ind(cx,p,gpriv); // process message break; default: printk("NAS_MESH_DC_RECEIVE: RB_ESTABLISH_IND reception, Invalid state %u", cx->state); } } break; case RB_RELEASE_IND : if (p->nasUEDCPrimitive.rb_release_ind.localConnectionRef!=cx->lcr) printk("NAS_DC_MESH_RECEIVE: RB_RELEASE_IND reception, Local connection reference not correct %u\n", p->nasUEDCPrimitive.rb_release_ind.localConnectionRef); else { switch (cx->state) { case NAS_CX_DCH: nas_mesh_DC_decode_rb_release_ind(cx,p); // process message break; default: printk("NAS_MESH_DC_RECEIVE: RB_RELEASE_IND reception, Invalid state %u", cx->state); } } break; case MEASUREMENT_IND : if (p->nasUEDCPrimitive.measurement_ind.localConnectionRef!=cx->lcr) printk("NAS_MESH_DC_RECEIVE: MEASUREMENT_IND reception, Local connection reference not correct %u\n", p->nasUEDCPrimitive.measurement_ind.localConnectionRef); else { nas_mesh_DC_decode_measurement_ind(cx,p); } break; default : printk("NAS_MESH_DC_RECEIVE: Invalid message received\n"); } } #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_RECEIVE - end \n"); #endif return bytes_read; } //--------------------------------------------------------------------------- // Check if anything in GC FIFO and decode it (MESH) int nas_mesh_GC_receive(struct nas_priv *gpriv) { //--------------------------------------------------------------------------- int bytes_read=0; #ifdef NAS_DEBUG_GC printk("NAS_MESH_GC_RECEIVE - begin \n"); #endif #ifdef PDCP_USE_NETLINK #else // bytes_read = rtf_get(gpriv->sap[NAS_GC_SAPI], gpriv->rbuffer, NAS_TL_SIZE); #endif if (bytes_read>0) { struct nas_ue_gc_element *p; p= (struct nas_ue_gc_element *)(gpriv->rbuffer); //get the rest of the primitive #ifdef PDCP_USE_NETLINK #else // bytes_read += rtf_get(gpriv->sap[NAS_GC_SAPI], (uint8_t *)p+NAS_TL_SIZE, p->length-NAS_TL_SIZE); #endif if (bytes_read!=p->length) { printk("NAS_MESH_GC_RECEIVE: Problem while reading primitive's header\n"); return bytes_read; } // start decoding message switch (p->type) { case INFO_BROADCAST_IND : #ifdef PDCP_USE_NETLINK #else // bytes_read += rtf_get(gpriv->sap[NAS_GC_SAPI], (uint8_t *)p+p->length, p->nasUEGCPrimitive.broadcast_ind.nasDataLength); #endif if (bytes_read!=p->length+p->nasUEGCPrimitive.broadcast_ind.nasDataLength) { printk("NAS_MESH_GC_RECEIVE: INFO_BROADCAST_IND reception, Problem while reading primitive's data\n"); return bytes_read; } #ifdef NAS_DEBUG_GC printk("NAS_MESH_GC_RECEIVE: INFO_BROADCAST_IND reception\n"); printk(" Primitive length %d \n", (int)(p->type)); printk(" Data length %u\n", p->nasUEGCPrimitive.broadcast_ind.nasDataLength); printk(" Data string %s\n", (uint8_t *)p+p->length); #endif //NAS_DEBUG_GC return bytes_read; default : printk("NAS_MESH_GC_RECEIVE: Invalid message received\n"); return -1; } } else return -1; }