//--------------------------------------------------------------------------- // 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 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"); }
//--------------------------------------------------------------------------- struct rb_entity *nas_COMMON_add_rb(struct cx_entity *cx, nasRadioBearerId_t rab_id, nasQoSTrafficClass_t qos) { //-------------------------------------------------------------------------- struct rb_entity *rb; #ifdef NAS_DEBUG_CLASS printk("NAS_COMMON_ADD_RB - begin for rab_id %d , qos %d\n", rab_id, qos ); #endif if (cx==NULL) { #ifdef NAS_DEBUG_CLASS printk("NAS_COMMON_ADD_RB - input parameter cx is NULL \n"); #endif return NULL; } rb=nas_COMMON_search_rb(cx, rab_id); if (rb==NULL) { rb=(struct rb_entity *)kmalloc(sizeof(struct rb_entity), GFP_KERNEL); if (rb!=NULL) { rb->retry=0; rb->countimer=NAS_TIMER_IDLE; rb->rab_id=rab_id; // rb->rab_id=rab_id+(32*cx->lcr); #ifdef NAS_DEBUG_DC printk("NAS_COMMON_ADD_RB: rab_id=%u, mt_id=%u\n",rb->rab_id, cx->lcr); #endif rb->qos=qos; rb->sapi=NAS_RAB_INPUT_SAPI; rb->state=NAS_IDLE; rb->next=cx->rb; cx->rb=rb; ++cx->num_rb; } else printk("NAS_ADD_CTL_RB: no memory\n"); } #ifdef NAS_DEBUG_CLASS printk("NAS_COMMON_ADD_RB - end \n" ); #endif return rb; }
/////////////////////////////////////////////////////////////////////////////// // Radio Bearer Release //--------------------------------------------------------------------------- void nas_set_msg_rb_release_reply(struct nas_msg_rb_release_reply *msgrep, struct nas_msg_rb_release_request *msgreq, struct nas_priv *priv) { //--------------------------------------------------------------------------- if (msgreq->lcr<NAS_CX_MAX) { struct rb_entity *rb; struct cx_entity *cx; cx=nas_COMMON_search_cx(msgreq->lcr,priv); rb=nas_COMMON_search_rb(cx, msgreq->rab_id); if (rb!=NULL) { //msgrep->status=nas_rg_DC_send_rb_release_request(cx, rb); } else msgrep->status=-NAS_ERROR_NOTCONNECTED; // msgrep->cnxid = msgreq->cnxid; } else msgrep->status=-NAS_ERROR_NOTCORRECTLCR; }
/////////////////////////////////////////////////////////////////////////////// // Request the addition of a classifier rule //--------------------------------------------------------------------------- void nas_set_msg_class_add_reply( struct nas_msg_class_add_reply *msgrep, struct nas_msg_class_add_request *msgreq, struct nas_priv *priv) { //--------------------------------------------------------------------------- struct classifier_entity *gc,*gc2; unsigned char *saddr,*daddr; unsigned int *saddr32,*daddr32; printk("[NAS][CLASS] nas_set_msg_class_add_reply\n"); if (msgreq->dscp>NAS_DSCP_MAX) { printk("NAS_SET_MSG_CLASS_ADD_REPLY: Incoherent parameter value\n"); msgrep->status=-NAS_ERROR_NOTCORRECTDSCP; return; } if (msgreq->dir==NAS_DIRECTION_SEND) { struct cx_entity *cx; cx=nas_COMMON_search_cx(msgreq->lcr,priv); if (cx!=NULL) { printk("NAS_SET_MSG_CLASS_ADD_REPLY: DSCP/EXP %d, Classref %d, RB %u\n", msgreq->dscp, msgreq->classref,msgreq->rab_id ); gc=nas_CLASS_add_sclassifier(cx, msgreq->dscp, msgreq->classref); printk("NAS_SET_MSG_CLASS_ADD_REPLY: %p %p\n" , msgreq, gc); if (gc==NULL) { msgrep->status=-NAS_ERROR_NOMEMORY; return; } } else { msgrep->status=-NAS_ERROR_NOTCORRECTLCR; return; } gc->rab_id=msgreq->rab_id; gc->rb=nas_COMMON_search_rb(cx, gc->rab_id); printk("NAS_SET_MSG_CLASS_ADD_REPLY: gc_rb %p %u \n", gc->rb, gc->rab_id); } else { if (msgreq->dir==NAS_DIRECTION_RECEIVE) { gc=nas_CLASS_add_rclassifier(msgreq->dscp, msgreq->classref, priv); if (gc==NULL) { msgrep->status=-NAS_ERROR_NOMEMORY; return; } gc->rab_id=msgreq->rab_id; } else { msgrep->status=-NAS_ERROR_NOTCORRECTDIR; return; } for (gc2 = priv->rclassifier[msgreq->dscp]; gc2!=NULL ; gc2 = gc2->next) printk("[NAS][CLASS] Add Receive Classifier dscp %d: rab_id %d (%p,next %p)\n",msgreq->dscp,gc2->rab_id,gc2,gc2->next); } printk("[NAS][CLASS] Getting addresses ...\n"); nas_TOOL_fct(gc, msgreq->fct); gc->version=msgreq->version; switch(gc->version) { case 4: gc->saddr.ipv4=msgreq->saddr.ipv4; gc->daddr.ipv4=msgreq->daddr.ipv4; // #ifdef NAS_CLASS_DEBUG saddr = (unsigned char *)&gc->saddr.ipv4; daddr = (unsigned char *)&gc->daddr.ipv4; printk("[NAS][CLASS] Adding IPv4 %d.%d.%d.%d -> %d.%d.%d.%d\n", saddr[0],saddr[1],saddr[2],saddr[3], daddr[0],daddr[1],daddr[2],daddr[3]); //#endif gc->splen=msgreq->splen; gc->dplen=msgreq->dplen; break; case 6: memcpy(&gc->saddr.ipv6,&msgreq->saddr.ipv6,16); memcpy(&gc->daddr.ipv6,&msgreq->daddr.ipv6,16); saddr32 = (unsigned int *)&gc->saddr.ipv6; daddr32 = (unsigned int *)&gc->daddr.ipv6; printk("[NAS][CLASS] Adding IPv6 %X:%X:%X:%X -> %X.%X.%X.%X\n", saddr32[0],saddr32[1],saddr32[2],saddr32[3], daddr32[0],daddr32[1],daddr32[2],daddr32[3]); gc->splen=msgreq->splen; gc->dplen=msgreq->dplen; break; case NAS_MPLS_VERSION_CODE: printk("[NAS][CLASS] Adding MPLS label %d with exp %d\n", msgreq->daddr.mpls_label,msgreq->dscp); gc->daddr.mpls_label = msgreq->daddr.mpls_label; break; case 0: gc->saddr.ipv6.s6_addr32[0]=0; gc->daddr.ipv6.s6_addr32[1]=0; gc->saddr.ipv6.s6_addr32[2]=0; gc->daddr.ipv6.s6_addr32[3]=0; gc->splen=0; gc->dplen=0; break; default: msgrep->status=-NAS_ERROR_NOTCORRECTVERSION; kfree(gc); return; } gc->protocol=msgreq->protocol; gc->protocol_message_type=msgreq->protocol_message_type; gc->sport=htons(msgreq->sport); gc->dport=htons(msgreq->dport); msgrep->status=0; }
void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst, struct nas_priv *gpriv) { //--------------------------------------------------------------------------- struct pdcp_data_req_header_s pdcph; struct nas_priv *priv=netdev_priv(nasdev[inst]); #ifdef LOOPBACK_TEST int i; #endif unsigned int bytes_wrote; //unsigned char j; // Start debug information #ifdef NAS_DEBUG_SEND printk("NAS_COMMON_QOS_SEND - inst %d begin \n",inst); #endif // if (cx->state!=NAS_STATE_CONNECTED) // <--- A REVOIR // { // priv->stats.tx_dropped ++; // printk("NAS_QOS_SEND: No connected, so message are dropped \n"); // return; // } if (skb==NULL) { #ifdef NAS_DEBUG_SEND printk("NAS_COMMON_QOS_SEND - input parameter skb is NULL \n"); #endif return; } if (gc==NULL) { #ifdef NAS_DEBUG_SEND printk("NAS_COMMON_QOS_SEND - input parameter gc is NULL \n"); #endif return; } if (cx==NULL) { #ifdef NAS_DEBUG_SEND printk("NAS_COMMON_QOS_SEND - input parameter cx is NULL \n"); #endif return; } // End debug information if (gc->rb==NULL) { gc->rb=nas_COMMON_search_rb(cx, gc->rab_id); if (gc->rb==NULL) { ++priv->stats.tx_dropped; printk("NAS_COMMON_QOS_SEND: No corresponding Radio Bearer, so message are dropped, rab_id=%u \n", gc->rab_id); return; } } #ifdef NAS_DEBUG_SEND printk("NAS_COMMON_QOS_SEND #1 :"); printk("lcr %u, rab_id %u, rab_id %u, skb_len %d\n", cx->lcr, (gc->rb)->rab_id, gc->rab_id,skb->len); nas_print_classifier(gc); #endif pdcph.data_size = skb->len; pdcph.rb_id = (gc->rb)->rab_id; pdcph.inst = inst; #ifdef PDCP_USE_NETLINK bytes_wrote = nas_netlink_send((char *)&pdcph,NAS_PDCPH_SIZE); #ifdef NAS_DEBUG_SEND printk("[NAS] Wrote %d bytes (header for %d byte skb) to PDCP via netlink\n", bytes_wrote,skb->len); #endif #else bytes_wrote = rtf_put(NAS2PDCP_FIFO, &pdcph, NAS_PDCPH_SIZE); #ifdef NAS_DEBUG_SEND printk("[NAS] Wrote %d bytes (header for %d byte skb) to PDCP fifo\n", bytes_wrote,skb->len); #endif #endif //PDCP_USE_NETLINK if (bytes_wrote != NAS_PDCPH_SIZE) { printk("NAS_COMMON_QOS_SEND: problem while writing PDCP's header (bytes wrote = %d )\n",bytes_wrote); printk("rb_id %d, Wrote %d, Header Size %lu\n", pdcph.rb_id , bytes_wrote, NAS_PDCPH_SIZE); #ifndef PDCP_USE_NETLINK rtf_reset(NAS2PDCP_FIFO); #endif //PDCP_USE_NETLINK return; } #ifdef PDCP_USE_NETLINK bytes_wrote += nas_netlink_send((char *)skb->data,skb->len); #else bytes_wrote += rtf_put(NAS2PDCP_FIFO, skb->data, skb->len); #endif //PDCP_USE_NETLINK if (bytes_wrote != skb->len+NAS_PDCPH_SIZE) { printk("NAS_COMMON_QOS_SEND: Inst %d, RB_ID %d: problem while writing PDCP's data, bytes_wrote = %d, Data_len %d, PDCPH_SIZE %lu\n", inst, pdcph.rb_id, bytes_wrote, skb->len, NAS_PDCPH_SIZE); // congestion #ifndef PDCP_USE_NETLINK rtf_reset(NAS2PDCP_FIFO); #endif //PDCP_USE_NETLINK return; } #ifdef NAS_DEBUG_SEND printk("NAS_SEND: Sending packet of size %d to PDCP \n",skb->len); for (j=0; j<skb->len; j++) printk("%2x ",((unsigned char *)(skb->data))[j]); printk("\n"); #endif priv->stats.tx_bytes += skb->len; priv->stats.tx_packets ++; #ifdef NAS_DEBUG_SEND printk("NAS_COMMON_QOS_SEND - end \n"); #endif }