With folowwing implicit rule drb id = x => correspondind lc id = x+2, eps bearer id = x+4 Changed RLC inner structs, no more statically allocated array, now it is dynamic via malloc and collection of RLC entities are stored in a hashtable. Changed misc simple types Started compiling with all warning setted and treated as errors, still working on RLC and around... Add const qualifier wherever suitable (for example param frame, module id, const pointers, etc) Thinking about a type of context parameter in procedure calls in L2 data plane (modules id, frame, srb flag, enb flag, etc)... git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5222 818b1a75-f10b-46b9-bf7c-635c3b92a50f
709 lines
21 KiB
C
Executable File
709 lines
21 KiB
C
Executable File
/*******************************************************************************
|
|
|
|
Eurecom OpenAirInterface 2
|
|
Copyright(c) 1999 - 2010 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, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
|
|
|
|
*******************************************************************************/
|
|
|
|
/***************************************************************************
|
|
/*! \file nas_common.c
|
|
* \brief implementation of emultor tx and rx
|
|
* \author Navid Nikaein and Raymomd Knopp
|
|
* \date 2011
|
|
* \version 1.0
|
|
* \company Eurecom
|
|
* \email: navid.nikaein@eurecom.fr
|
|
*/
|
|
|
|
//#include "nas_common.h"
|
|
#include "local.h"
|
|
#include "proto_extern.h"
|
|
#ifndef NAS_NETLINK
|
|
#include "rtai_fifos.h"
|
|
#endif
|
|
|
|
//#define NAS_DEBUG_RECEIVE 1
|
|
//#define NAS_DEBUG_SEND 1
|
|
//#define NAS_DEBUG_CLASS 1
|
|
//#define NAS_ADDRESS_FIX 1
|
|
|
|
#include <linux/inetdevice.h>
|
|
|
|
#include <net/tcp.h>
|
|
#include <net/udp.h>
|
|
|
|
|
|
void nas_COMMON_receive(uint16_t dlen,
|
|
void *pdcp_sdu,
|
|
int inst,
|
|
struct classifier_entity *rclass,
|
|
nasRadioBearerId_t rb_id) {
|
|
|
|
//---------------------------------------------------------------------------
|
|
struct sk_buff *skb;
|
|
struct ipversion *ipv;
|
|
struct nas_priv *gpriv=netdev_priv(nasdev[inst]);
|
|
uint32_t odaddr,osaddr;
|
|
|
|
int i;
|
|
|
|
unsigned char protocol;
|
|
|
|
unsigned char *addr,*daddr,*saddr,*ifaddr,sn;
|
|
|
|
struct udphdr *uh;
|
|
struct tcphdr *th;
|
|
uint16_t *cksum,check;
|
|
|
|
struct iphdr *network_header;
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
|
|
printk("NAS_COMMON_RECEIVE: begin RB %d Inst %d Length %d bytes\n",rb_id,inst,dlen);
|
|
#endif
|
|
skb = dev_alloc_skb( dlen + 2 );
|
|
if(!skb)
|
|
{
|
|
printk("NAS_COMMON_RECEIVE: low on memory\n");
|
|
++gpriv->stats.rx_dropped;
|
|
return;
|
|
}
|
|
skb_reserve(skb,2);
|
|
memcpy(skb_put(skb, dlen), pdcp_sdu,dlen);
|
|
|
|
skb->dev = nasdev[inst];
|
|
|
|
#ifdef KERNEL_VERSION_GREATER_THAN_2622
|
|
skb_reset_mac_header(skb);
|
|
#else
|
|
skb->mac.raw = skb->data;
|
|
#endif
|
|
//printk("[NAC_COMMIN_RECEIVE]: Packet Type %d (%d,%d)",skb->pkt_type,PACKET_HOST,PACKET_BROADCAST);
|
|
skb->pkt_type = PACKET_HOST;
|
|
|
|
if (rclass->version != NAS_MPLS_VERSION_CODE) { // This is an IP packet
|
|
|
|
skb->ip_summed = CHECKSUM_NONE;
|
|
|
|
|
|
ipv = (struct ipversion *)skb->data;
|
|
switch (ipv->version)
|
|
{
|
|
case 6:
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("NAS_COMMON_RECEIVE: receive IPv6 message\n");
|
|
#endif
|
|
|
|
|
|
#ifdef KERNEL_VERSION_GREATER_THAN_2622
|
|
skb_reset_network_header(skb);
|
|
#else
|
|
skb->nh.ipv6h = (struct ipv6hdr *)skb->data;
|
|
#endif
|
|
|
|
skb->protocol = htons(ETH_P_IPV6);
|
|
// printk("Writing packet with protocol %x\n",ntohs(skb->protocol));
|
|
|
|
break;
|
|
case 4:
|
|
#ifdef NAS_ADDRESS_FIX
|
|
// Make the third byte of both the source and destination equal to the fourth of the destination
|
|
|
|
|
|
|
|
daddr = (unsigned char *)&((struct iphdr *)skb->data)->daddr;
|
|
odaddr = ((struct iphdr *)skb->data)->daddr;
|
|
// sn = addr[3];
|
|
saddr = (unsigned char *)&((struct iphdr *)skb->data)->saddr;
|
|
osaddr = ((struct iphdr *)skb->data)->saddr;
|
|
|
|
if (daddr[0] == saddr[0]) {// same network
|
|
daddr[2] = daddr[3]; // set third byte of destination to that of local machine so that local IP stack accepts the packet
|
|
saddr[2] = daddr[3]; // set third byte of source to that of local machine so that local IP stack accepts the packet
|
|
}
|
|
else { // get the 3rd byte from device address in net_device structure
|
|
ifaddr = (unsigned char *)(&(((struct in_device *)((nasdev[inst])->ip_ptr))->ifa_list->ifa_local));
|
|
if (saddr[0] == ifaddr[0]) { // source is in same network as local machine
|
|
daddr[0] += saddr[3]; // fix address of remote destination to undo change at source
|
|
saddr[2] = ifaddr[2]; // set third byte to that of local machine so that local IP stack accepts the packet
|
|
}
|
|
else { // source is remote machine from outside network
|
|
saddr[0] -= daddr[3]; // fix address of remote source to be understood by destination
|
|
daddr[2] = daddr[3]; // fix 3rd byte of local address to be understood by IP stack of
|
|
// destination
|
|
}
|
|
}
|
|
|
|
#endif //NAS_ADDRESS_FIX
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
// printk("NAS_TOOL_RECEIVE: receive IPv4 message\n");
|
|
addr = (unsigned char *)&((struct iphdr *)skb->data)->saddr;
|
|
if (addr) {
|
|
// addr[2]^=0x01;
|
|
printk("[NAS][COMMON][RECEIVE] Source %d.%d.%d.%d\n",addr[0],addr[1],addr[2],addr[3]);
|
|
}
|
|
addr = (unsigned char *)&((struct iphdr *)skb->data)->daddr;
|
|
if (addr){
|
|
// addr[2]^=0x01;
|
|
printk("[NAS][COMMON][RECEIVE] Dest %d.%d.%d.%d\n",addr[0],addr[1],addr[2],addr[3]);
|
|
}
|
|
printk("[NAS][COMMON][RECEIVE] protocol %d\n",((struct iphdr *)skb->data)->protocol);
|
|
|
|
#endif
|
|
|
|
#ifdef KERNEL_VERSION_GREATER_THAN_2622
|
|
skb_reset_network_header(skb);
|
|
network_header = (struct iphdr *)skb_network_header(skb);
|
|
protocol = network_header->protocol;
|
|
#else
|
|
skb->nh.iph = (struct iphdr *)skb->data;
|
|
protocol=skb->nh.iph->protocol;
|
|
#endif
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
switch (protocol) {
|
|
case IPPROTO_IP:
|
|
printk("[NAS][COMMON][RECEIVE] Received Raw IPv4 packet\n");
|
|
break;
|
|
case IPPROTO_IPV6:
|
|
printk("[NAS][COMMON][RECEIVE] Received Raw IPv6 packet\n");
|
|
break;
|
|
case IPPROTO_ICMP:
|
|
printk("[NAS][COMMON][RECEIVE] Received Raw ICMP packet\n");
|
|
break;
|
|
case IPPROTO_TCP:
|
|
printk("[NAS][COMMON][RECEIVE] Received TCP packet\n");
|
|
break;
|
|
case IPPROTO_UDP:
|
|
printk("[NAS][COMMON][RECEIVE] Received UDP packet\n");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef NAS_ADDRESS_FIX
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("NAS_COMMON_RECEIVE: dumping the packet before the csum recalculation\n",skb->len);
|
|
for (i=0;i<skb->len;i++)
|
|
printk("%2x ",((unsigned char *)(skb->data))[i]);
|
|
printk("\n");
|
|
#endif //NAS_DEBUG_RECEIVE
|
|
|
|
|
|
#ifdef KERNEL_VERSION_GREATER_THAN_2622
|
|
network_header->check = 0;
|
|
network_header->check = ip_fast_csum((unsigned char *) network_header,
|
|
network_header->ihl);
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON][RECEIVE] IP Fast Checksum %x \n", network_header->check);
|
|
#endif
|
|
|
|
#else
|
|
skb->nh.iph->check = 0;
|
|
skb->nh.iph->check = ip_fast_csum((unsigned char *)skb->data,
|
|
skb->nh.iph->ihl);
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON][RECEIVE] IP Fast Checksum %x \n", skb->nh.iph->check);
|
|
#endif
|
|
|
|
#endif
|
|
// if (!(skb->nh.iph->frag_off & htons(IP_OFFSET))) {
|
|
|
|
|
|
|
|
|
|
switch(protocol)
|
|
{
|
|
|
|
case IPPROTO_TCP:
|
|
|
|
#ifdef KERNEL_VERSION_GREATER_THAN_2622
|
|
cksum = (uint16_t*)&(((struct tcphdr*)((network_header + (network_header->ihl<<2))))->check);
|
|
//check = csum_tcpudp_magic(((struct iphdr *)network_header)->saddr, ((struct iphdr *)network_header)->daddr, tcp_hdrlen(skb), IPPROTO_TCP, ~(*cksum));
|
|
#else
|
|
cksum = (uint16_t*)&(((struct tcphdr*)((skb->data + (skb->nh.iph->ihl<<2))))->check);
|
|
//check = csum_tcpudp_magic(((struct iphdr *)skb->data)->saddr, ((struct iphdr *)skb->data)->daddr,tcp_hdrlen(skb), IPPROTO_TCP, ~(*cksum));
|
|
#endif
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON] Inst %d TCP packet calculated CS %x, CS = %x (before), SA (%x)%x, DA (%x)%x\n",
|
|
inst,
|
|
network_header->check,
|
|
*cksum,
|
|
osaddr,
|
|
((struct iphdr *)skb->data)->saddr,
|
|
odaddr,
|
|
((struct iphdr *)skb->data)->daddr);
|
|
#endif
|
|
check = csum_tcpudp_magic(((struct iphdr *)skb->data)->saddr, ((struct iphdr *)skb->data)->daddr,0,0, ~(*cksum));
|
|
*cksum = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON] Inst %d TCP packet NEW CS %x\n",
|
|
inst,
|
|
*cksum);
|
|
#endif
|
|
break;
|
|
|
|
case IPPROTO_UDP:
|
|
|
|
#ifdef KERNEL_VERSION_GREATER_THAN_2622
|
|
cksum = (uint16_t*)&(((struct udphdr*)((network_header + (network_header->ihl<<2))))->check);
|
|
// check = csum_tcpudp_magic(((struct iphdr *)network_header)->saddr, ((struct iphdr *)network_header)->daddr, udp_hdr(skb)->len, IPPROTO_UDP, ~(*cksum));
|
|
#else
|
|
cksum = (uint16_t*)&(((struct udphdr*)((skb->data + (skb->nh.iph->ihl<<2))))->check);
|
|
//check = csum_tcpudp_magic(((struct iphdr *)skb->data)->saddr, ((struct iphdr *)skb->data)->daddr, udp_hdr(skb)->len, IPPROTO_UDP, ~(*cksum));
|
|
#endif
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON] Inst %d UDP packet CS = %x (before), SA (%x)%x, DA (%x)%x\n",
|
|
inst,
|
|
*cksum,
|
|
osaddr,
|
|
((struct iphdr *)skb->data)->saddr,
|
|
odaddr,
|
|
((struct iphdr *)skb->data)->daddr);
|
|
#endif
|
|
check = csum_tcpudp_magic(((struct iphdr *)skb->data)->saddr, ((struct iphdr *)skb->data)->daddr, 0,0, ~(*cksum));
|
|
*cksum= csum_tcpudp_magic(~osaddr, ~odaddr,0,0, ~check);
|
|
//*cksum= csum_tcpudp_magic(~osaddr, ~odaddr,udp_hdr(skb)->len, IPPROTO_UDP, ~check);
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON] Inst %d UDP packet NEW CS %x\n",
|
|
inst,
|
|
*cksum);
|
|
#endif
|
|
// if ((check = *cksum) != 0) {
|
|
// src, dst, len, proto, sum
|
|
|
|
|
|
// }
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
// }
|
|
|
|
//#endif // KERNEL VERSION > 22
|
|
#endif //NAS_ADDRESS_FIX
|
|
|
|
skb->protocol = htons(ETH_P_IP);
|
|
// printk("[NAS][COMMON] Writing packet with protocol %x\n",ntohs(skb->protocol));
|
|
break;
|
|
default:
|
|
printk("NAS_COMMON_RECEIVE: begin RB %d Inst %d Length %d bytes\n",rb_id,inst,dlen);
|
|
|
|
printk("[NAS][COMMON] Inst %d: receive unknown message (version=%d)\n",inst,ipv->version);
|
|
|
|
}
|
|
}
|
|
else { // This is an MPLS packet
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("NAS_COMMON_RECEIVE: Received an MPLS packet on RB %d\n",rb_id);
|
|
#endif
|
|
skb->protocol = htons(ETH_P_MPLS_UC);
|
|
|
|
}
|
|
++gpriv->stats.rx_packets;
|
|
gpriv->stats.rx_bytes += dlen;
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("NAS_COMMON_RECEIVE: sending packet of size %d to kernel\n",skb->len);
|
|
for (i=0;i<skb->len;i++)
|
|
printk("%2x ",((unsigned char *)(skb->data))[i]);
|
|
printk("\n");
|
|
#endif //NAS_DEBUG_RECEIVE
|
|
netif_rx(skb);
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("NAS_COMMON_RECEIVE: end\n");
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Delete the data
|
|
void nas_COMMON_del_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *sp,int inst){
|
|
struct nas_priv *priv=netdev_priv(nasdev[inst]);
|
|
|
|
//---------------------------------------------------------------------------
|
|
++priv->stats.tx_dropped;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Request the transfer of data (QoS SAP)
|
|
|
|
void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst){
|
|
//---------------------------------------------------------------------------
|
|
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 NAS_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 //NAS_NETLINK
|
|
|
|
if (bytes_wrote != NAS_PDCPH_SIZE)
|
|
{
|
|
printk("NAS_COMMON_QOS_SEND: problem while writing PDCP's header (bytes wrote = %d to fifo %d)\n",bytes_wrote,NAS2PDCP_FIFO);
|
|
printk("rb_id %d, Wrote %d, Header Size %lu\n", pdcph.rb_id , bytes_wrote, NAS_PDCPH_SIZE);
|
|
#ifndef NAS_NETLINK
|
|
rtf_reset(NAS2PDCP_FIFO);
|
|
#endif //NAS_NETLINK
|
|
return;
|
|
}
|
|
#ifdef NAS_NETLINK
|
|
bytes_wrote += nas_netlink_send((char *)skb->data,skb->len);
|
|
#else
|
|
bytes_wrote += rtf_put(NAS2PDCP_FIFO, skb->data, skb->len);
|
|
#endif //NAS_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 NAS_NETLINK
|
|
rtf_reset(NAS2PDCP_FIFO);
|
|
#endif //NAS_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
|
|
}
|
|
|
|
#ifndef NAS_NETLINK
|
|
//---------------------------------------------------------------------------
|
|
void nas_COMMON_QOS_receive(){
|
|
//---------------------------------------------------------------------------
|
|
uint8_t sapi;
|
|
struct pdcp_data_ind_header_s pdcph;
|
|
unsigned char data_buffer[2048];
|
|
struct classifier_entity *rclass;
|
|
struct nas_priv *priv;
|
|
int bytes_read;
|
|
|
|
// Start debug information
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("NAS_COMMON_QOS_RECEIVE - begin \n");
|
|
#endif
|
|
|
|
// End debug information
|
|
|
|
bytes_read = rtf_get(PDCP2NAS_FIFO,&pdcph, NAS_PDCPH_SIZE);
|
|
|
|
while (bytes_read>0) {
|
|
if (bytes_read != NAS_PDCPH_SIZE)
|
|
{
|
|
printk("NAS_COMMON_QOS_RECEIVE: problem while reading PDCP header\n");
|
|
return;
|
|
}
|
|
|
|
priv=netdev_priv(nasdev[pdcph.inst]);
|
|
rclass = nas_COMMON_search_class_for_rb(pdcph.rb_id,priv);
|
|
|
|
bytes_read+= rtf_get(PDCP2NAS_FIFO,
|
|
data_buffer,
|
|
pdcph.data_size);
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("NAS_COMMON_QOS_RECEIVE - Got header for RB %d, Inst %d \n",
|
|
pdcph.rb_id,
|
|
pdcph.inst);
|
|
#endif
|
|
|
|
if (rclass) {
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON] Found corresponding connection in classifier for RAB\n");
|
|
#endif //NAS_DEBUG_RECEIVE
|
|
|
|
nas_COMMON_receive(pdcph.data_size,
|
|
(void *)data_buffer,
|
|
pdcph.inst,
|
|
rclass,
|
|
pdcph.rb_id);
|
|
}
|
|
|
|
bytes_read = rtf_get(PDCP2NAS_FIFO, &pdcph, NAS_PDCPH_SIZE);
|
|
}
|
|
|
|
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("NAS_COMMON_QOS_RECEIVE - end \n");
|
|
#endif
|
|
}
|
|
|
|
#else
|
|
void nas_COMMON_QOS_receive(struct nlmsghdr *nlh)
|
|
{
|
|
|
|
struct pdcp_data_ind_header_s *pdcph = (struct pdcp_data_ind_header_s *)NLMSG_DATA(nlh);
|
|
struct classifier_entity *rclass;
|
|
struct nas_priv *priv;
|
|
|
|
priv = netdev_priv(nasdev[pdcph->inst]);
|
|
|
|
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON][NETLINK] QOS receive from PDCP, size %d, rab %d, inst %d\n",
|
|
pdcph->data_size,pdcph->rb_id,pdcph->inst);
|
|
#endif //NAS_DEBUG_RECEIVE
|
|
|
|
rclass = nas_COMMON_search_class_for_rb(pdcph->rb_id,priv);
|
|
|
|
if (rclass) {
|
|
#ifdef NAS_DEBUG_RECEIVE
|
|
printk("[NAS][COMMON][NETLINK] Found corresponding connection in classifier for RAB\n");
|
|
#endif //NAS_DEBUG_RECEIVE
|
|
|
|
nas_COMMON_receive(pdcph->data_size,
|
|
(unsigned char *)NLMSG_DATA(nlh) + NAS_PDCPH_SIZE,
|
|
pdcph->inst,
|
|
rclass,
|
|
pdcph->rb_id);
|
|
}
|
|
|
|
}
|
|
#endif //NAS_NETLINK
|
|
|
|
//---------------------------------------------------------------------------
|
|
struct cx_entity *nas_COMMON_search_cx(nasLocalConnectionRef_t lcr,struct nas_priv *priv){
|
|
//---------------------------------------------------------------------------
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("NAS_COMMON_SEARCH_CX - lcr %d\n",lcr);
|
|
#endif
|
|
if (lcr<NAS_CX_MAX)
|
|
return priv->cx+lcr;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Search a Radio Bearer
|
|
struct rb_entity *nas_COMMON_search_rb(struct cx_entity *cx, nasRadioBearerId_t rab_id){
|
|
//---------------------------------------------------------------------------
|
|
struct rb_entity *rb;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("NAS_COMMON_SEARCH_RB - rab_id %d\n", rab_id);
|
|
#endif
|
|
for (rb=cx->rb; rb!=NULL; rb=rb->next) {
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS\n");
|
|
printk("NAS_COMMON_SEARCH_RB - rab_id %d Comparing rb_entity.rab_id %u \n", rb->rab_id);
|
|
printk("NAS_COMMON_SEARCH_RB - rab_id %d Comparing rb_entity.sapi %u \n", rb->sapi;
|
|
printk("NAS_COMMON_SEARCH_RB - rab_id %d Comparing rb_entity.qos %u \n", rb->qos;
|
|
printk("NAS_COMMON_SEARCH_RB - rab_id %d Comparing rb_entity.state %u \n", rb->state;
|
|
printk("NAS_COMMON_SEARCH_RB - rab_id %d Comparing rb_entity.retry %u \n", rb->retry;
|
|
printk("NAS_COMMON_SEARCH_RB - rab_id %d Comparing rb_entity.countimer %u \n\n", rb->countimer;);
|
|
#endif
|
|
if (rb->rab_id==rab_id)
|
|
return rb;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Search for a classifier with corresponding radio bearer
|
|
|
|
struct classifier_entity *nas_COMMON_search_class_for_rb(nasRadioBearerId_t rab_id,struct nas_priv *priv) {
|
|
|
|
struct rb_entity *rb;
|
|
int dscp;
|
|
struct classifier_entity *rclass;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("[NAS][COMMON] NAS_COMMON_SEARCH_CLASS_FOR_RB - rab_id %d\n", rab_id);
|
|
#endif
|
|
for (dscp=0;dscp<NAS_DSCP_MAX;dscp++) {
|
|
|
|
// printk("[NAS][COMMON] priv->rclassifier[%d] = %p\n",dscp,priv->rclassifier[dscp]);
|
|
for (rclass=priv->rclassifier[dscp]; rclass!=NULL; rclass=rclass->next) {
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("[NAS][COMMON] NAS_COMMON_SEARCH_CLASS_FOR_RB - dscp %d, rb %d\n", dscp,rclass->rab_id);
|
|
#endif
|
|
if (rclass->rab_id==rab_id)
|
|
return rclass;
|
|
}
|
|
}
|
|
return NULL;
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
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;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void nas_COMMON_flush_rb(struct cx_entity *cx){
|
|
//---------------------------------------------------------------------------
|
|
struct rb_entity *rb;
|
|
struct classifier_entity *gc;
|
|
uint8_t dscp;
|
|
// End debug information
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("NAS_COMMON_FLUSH_RB - begin\n");
|
|
#endif
|
|
if (cx==NULL){
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("NAS_COMMON_FLUSH_RB - input parameter cx is NULL \n");
|
|
#endif
|
|
return;
|
|
}
|
|
// End debug information
|
|
for (rb=cx->rb; rb!=NULL; rb=cx->rb){
|
|
printk("NAS_COMMON_FLUSH_RB: del rab_id %u\n", rb->rab_id);
|
|
cx->rb=rb->next;
|
|
kfree(rb);
|
|
}
|
|
cx->num_rb=0;
|
|
cx->rb=NULL;
|
|
for(dscp=0; dscp<NAS_DSCP_MAX; ++dscp)
|
|
{
|
|
for (gc=cx->sclassifier[dscp]; gc!=NULL; gc=gc->next)
|
|
gc->rb=NULL;
|
|
}
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("NAS_COMMON_FLUSH_RB - end\n");
|
|
#endif
|
|
}
|