common.c 20.8 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 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
 */

22 23 24
/*! \file common.c
* \brief implementation of emultor tx and rx
* \author Navid Nikaein, Lionel GAUTHIER, and Raymomd Knopp
25
* \date 2011
26
* \version 1.0
27
* \company Eurecom
28 29
* \email: navid.nikaein@eurecom.fr, lionel.gauthier@eurecom.fr
*/
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

#include "local.h"
#include "proto_extern.h"

//#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>


45 46 47 48 49 50
void nas_COMMON_receive(uint16_t dlen,
                        void *pdcp_sdu,
                        int inst,
                        struct classifier_entity *rclass,
                        nasRadioBearerId_t rb_id)
{
51 52 53 54 55 56

  //---------------------------------------------------------------------------
  struct sk_buff *skb;
  struct ipversion *ipv;
  struct nas_priv *gpriv=netdev_priv(nasdev[inst]);

Cedric Roux's avatar
Cedric Roux committed
57
  //int i;
58 59 60 61

  unsigned char protocol;


Cedric Roux's avatar
Cedric Roux committed
62 63
  //struct udphdr *uh;
  //struct tcphdr *th;
64

65
  struct iphdr *network_header;
66 67 68 69 70 71

#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 );
72 73 74 75 76 77 78

  if(!skb) {
    printk("NAS_COMMON_RECEIVE: low on memory\n");
    ++gpriv->stats.rx_dropped;
    return;
  }

79 80 81 82
  skb_reserve(skb,2);
  memcpy(skb_put(skb, dlen), pdcp_sdu,dlen);

  skb->dev = nasdev[inst];
83

84
  skb_reset_mac_header(skb);
85
  //printk("[NAC_COMMIN_RECEIVE]: Packet Type %d (%d,%d)",skb->pkt_type,PACKET_HOST,PACKET_BROADCAST);
86 87 88 89 90 91 92 93
  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;
94 95 96

    switch (ipv->version) {
    case 6:
97
#ifdef NAS_DEBUG_RECEIVE
98
      printk("NAS_COMMON_RECEIVE: receive IPv6 message\n");
99 100 101
#endif


102 103 104 105
      skb_reset_network_header(skb);

      skb->protocol = htons(ETH_P_IPV6);
      //  printk("Writing packet with protocol %x\n",ntohs(skb->protocol));
106

107
      break;
108

109
    case 4:
110
#ifdef NAS_ADDRESS_FIX
111 112 113
      // Make the third byte of both the source and destination equal to the fourth of the destination


laurent's avatar
laurent committed
114
      unsigned char * ifaddr, *saddr, daddr;
115 116 117 118
      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;
laurent's avatar
laurent committed
119
      uint32_t odaddr,osaddr;
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
      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
        }
      }

138 139
#endif //NAS_ADDRESS_FIX
#ifdef NAS_DEBUG_RECEIVE
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
      //    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

      skb_reset_network_header(skb);
      network_header = (struct iphdr *)skb_network_header(skb);
      protocol = network_header->protocol;
162 163

#ifdef NAS_DEBUG_RECEIVE
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

      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

192 193 194
#ifdef NAS_ADDRESS_FIX

#ifdef NAS_DEBUG_RECEIVE
Cedric Roux's avatar
Cedric Roux committed
195
      printk("NAS_COMMON_RECEIVE: dumping the packet before the csum recalculation (len %d)\n",skb->len);
196 197 198 199 200

      for (i=0; i<skb->len; i++)
        printk("%2x ",((unsigned char *)(skb->data))[i]);

      printk("\n");
201 202 203
#endif //NAS_DEBUG_RECEIVE


204 205 206
      network_header->check = 0;
      network_header->check = ip_fast_csum((unsigned char *) network_header,
                                           network_header->ihl);
207
#ifdef NAS_DEBUG_RECEIVE
208
      printk("[NAS][COMMON][RECEIVE] IP Fast Checksum %x \n", network_header->check);
209 210
#endif

211 212
      //    if (!(skb->nh.iph->frag_off & htons(IP_OFFSET))) {

213 214


215 216 217 218 219

      switch(protocol) {

      case IPPROTO_TCP:

laurent's avatar
laurent committed
220
  uint16_t *cksum,check;
221
        cksum  = (uint16_t*)&(((struct tcphdr*)(((char *)network_header + (network_header->ihl<<2))))->check);
222
        //check  = csum_tcpudp_magic(((struct iphdr *)network_header)->saddr, ((struct iphdr *)network_header)->daddr, tcp_hdrlen(skb), IPPROTO_TCP, ~(*cksum));
223 224

#ifdef NAS_DEBUG_RECEIVE
225 226 227 228 229 230 231 232 233 234 235 236
        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);

237
#ifdef NAS_DEBUG_RECEIVE
238 239 240
        printk("[NAS][COMMON] Inst %d TCP packet NEW CS %x\n",
               inst,
               *cksum);
241
#endif
242
        break;
243

244 245
      case IPPROTO_UDP:

246
        cksum  = (uint16_t*)&(((struct udphdr*)(((char *)network_header + (network_header->ihl<<2))))->check);
247
        // check = csum_tcpudp_magic(((struct iphdr *)network_header)->saddr, ((struct iphdr *)network_header)->daddr, udp_hdr(skb)->len, IPPROTO_UDP, ~(*cksum));
248
#ifdef NAS_DEBUG_RECEIVE
249 250 251 252 253 254 255 256 257 258 259
        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);
260 261

#ifdef NAS_DEBUG_RECEIVE
262 263 264 265 266 267
        printk("[NAS][COMMON] Inst %d UDP packet NEW CS %x\n",
               inst,
               *cksum);
#endif
        //    if ((check = *cksum) != 0) {
        // src, dst, len, proto, sum
268 269


270 271 272 273
        //    }

        break;

274
      default:
275
        break;
276
      }
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292

      //    }

#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
293 294 295 296 297 298 299

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

  }
300

301 302 303 304
  ++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);
305 306 307 308

  for (i=0; i<skb->len; i++)
    printk("%2x ",((unsigned char *)(skb->data))[i]);

309 310
  printk("\n");
#endif //NAS_DEBUG_RECEIVE
311
  netif_rx_ni(skb);
312 313 314 315 316 317 318
#ifdef NAS_DEBUG_RECEIVE
  printk("NAS_COMMON_RECEIVE: end\n");
#endif
}

//---------------------------------------------------------------------------
// Delete the data
319
void nas_COMMON_del_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *sp,int inst,struct nas_priv *gpriv)
320
{
321 322 323 324 325 326 327 328
  struct nas_priv *priv=netdev_priv(nasdev[inst]);
  //---------------------------------------------------------------------------
  ++priv->stats.tx_dropped;
}

//---------------------------------------------------------------------------
// Request the transfer of data (QoS SAP)

329
void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst, struct nas_priv *gpriv)
330
{
331
  //---------------------------------------------------------------------------
332
  struct pdcp_data_req_header_s     pdcph;
333 334 335 336 337
  struct nas_priv *priv=netdev_priv(nasdev[inst]);
#ifdef LOOPBACK_TEST
  int i;
#endif
  unsigned int bytes_wrote;
Cedric Roux's avatar
Cedric Roux committed
338
  //unsigned char j;
339 340 341 342
  // Start debug information
#ifdef NAS_DEBUG_SEND
  printk("NAS_COMMON_QOS_SEND - inst %d begin \n",inst);
#endif
343 344 345 346 347 348 349 350

  //  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) {
351 352 353 354 355
#ifdef NAS_DEBUG_SEND
    printk("NAS_COMMON_QOS_SEND - input parameter skb is NULL \n");
#endif
    return;
  }
356 357

  if (gc==NULL) {
358 359 360 361 362
#ifdef NAS_DEBUG_SEND
    printk("NAS_COMMON_QOS_SEND - input parameter gc is NULL \n");
#endif
    return;
  }
363 364

  if (cx==NULL) {
365 366 367 368 369
#ifdef NAS_DEBUG_SEND
    printk("NAS_COMMON_QOS_SEND - input parameter cx is NULL \n");
#endif
    return;
  }
370

371
  // End debug information
372 373 374 375 376 377 378
  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;
379
    }
380 381
  }

382 383 384 385 386 387 388 389
#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;
390 391 392 393 394
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
  pdcph.sourceL2Id = 0;
  pdcph.destinationL2Id = 0;
#endif

395 396


397
#ifdef PDCP_USE_NETLINK
398 399 400
  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",
401
         bytes_wrote,skb->len);
402 403 404 405 406
#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",
407
         bytes_wrote,skb->len);
408
#endif
409
#endif //PDCP_USE_NETLINK
410 411 412 413

  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);
414
#ifndef PDCP_USE_NETLINK
415
    rtf_reset(NAS2PDCP_FIFO);
416
#endif //PDCP_USE_NETLINK
417 418 419
    return;
  }

420
#ifdef  PDCP_USE_NETLINK
421 422 423
  bytes_wrote += nas_netlink_send((char *)skb->data,skb->len);
#else
  bytes_wrote += rtf_put(NAS2PDCP_FIFO, skb->data, skb->len);
424
#endif //PDCP_USE_NETLINK
425

426 427 428 429 430 431 432
  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
433
#ifndef PDCP_USE_NETLINK
434
    rtf_reset(NAS2PDCP_FIFO);
435
#endif //PDCP_USE_NETLINK
436 437 438
    return;
  }

439 440
#ifdef NAS_DEBUG_SEND
  printk("NAS_SEND: Sending packet of size %d to PDCP \n",skb->len);
441 442 443 444

  for (j=0; j<skb->len; j++)
    printk("%2x ",((unsigned char *)(skb->data))[j]);

445 446 447 448 449 450 451 452 453 454
  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
}

455
#ifndef PDCP_USE_NETLINK
456
//---------------------------------------------------------------------------
457 458
void nas_COMMON_QOS_receive()
{
459
  //---------------------------------------------------------------------------
460
  uint8_t sapi;
461
  struct pdcp_data_ind_header_s     pdcph;
462 463 464 465 466 467 468 469 470
  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
471

472
  // End debug information
473

474
  bytes_read =  rtf_get(PDCP2PDCP_USE_RT_FIFO,&pdcph, NAS_PDCPH_SIZE);
475

476
  while (bytes_read>0) {
477 478 479 480 481
    if (bytes_read != NAS_PDCPH_SIZE) {
      printk("NAS_COMMON_QOS_RECEIVE: problem while reading PDCP header\n");
      return;
    }

482 483
    priv=netdev_priv(nasdev[pdcph.inst]);
    rclass = nas_COMMON_search_class_for_rb(pdcph.rb_id,priv);
484

485
    bytes_read+= rtf_get(PDCP2PDCP_USE_RT_FIFO,
486 487 488
                         data_buffer,
                         pdcph.data_size);

489 490
#ifdef NAS_DEBUG_RECEIVE
    printk("NAS_COMMON_QOS_RECEIVE - Got header for RB %d, Inst %d \n",
491 492
           pdcph.rb_id,
           pdcph.inst);
493
#endif
494

495 496 497 498
    if (rclass) {
#ifdef NAS_DEBUG_RECEIVE
      printk("[NAS][COMMON] Found corresponding connection in classifier for RAB\n");
#endif //NAS_DEBUG_RECEIVE
499 500 501 502 503 504

      nas_COMMON_receive(pdcph.data_size,
                         (void *)data_buffer,
                         pdcph.inst,
                         rclass,
                         pdcph.rb_id);
505
    }
506

507
    bytes_read =  rtf_get(PDCP2PDCP_USE_RT_FIFO, &pdcph, NAS_PDCPH_SIZE);
508
  }
509 510 511



512 513 514 515 516 517 518 519 520
#ifdef NAS_DEBUG_RECEIVE
  printk("NAS_COMMON_QOS_RECEIVE - end \n");
#endif
}

#else
void nas_COMMON_QOS_receive(struct nlmsghdr *nlh)
{

521
  struct pdcp_data_ind_header_s     *pdcph = (struct pdcp_data_ind_header_s *)NLMSG_DATA(nlh);
522 523 524 525 526 527 528 529
  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",
530
         pdcph->data_size,pdcph->rb_id,pdcph->inst);
531 532 533 534 535 536 537 538
#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
539 540 541 542 543 544 545

    nas_COMMON_receive(pdcph->data_size,
                       (unsigned char *)NLMSG_DATA(nlh) + NAS_PDCPH_SIZE,
                       pdcph->inst,
                       rclass,
                       pdcph->rb_id);
  }
546 547

}
548
#endif //PDCP_USE_NETLINK
549 550

//---------------------------------------------------------------------------
551 552
struct cx_entity *nas_COMMON_search_cx(nasLocalConnectionRef_t lcr,struct nas_priv *priv)
{
553 554 555 556
  //---------------------------------------------------------------------------
#ifdef NAS_DEBUG_CLASS
  printk("NAS_COMMON_SEARCH_CX - lcr %d\n",lcr);
#endif
557

558 559 560 561 562 563 564 565
  if (lcr<NAS_CX_MAX)
    return priv->cx+lcr;
  else
    return NULL;
}

//---------------------------------------------------------------------------
// Search a Radio Bearer
566 567
struct rb_entity *nas_COMMON_search_rb(struct cx_entity *cx, nasRadioBearerId_t rab_id)
{
568 569 570 571 572
  //---------------------------------------------------------------------------
  struct rb_entity *rb;
#ifdef NAS_DEBUG_CLASS
  printk("NAS_COMMON_SEARCH_RB - rab_id %d\n", rab_id);
#endif
573

574 575
  for (rb=cx->rb; rb!=NULL; rb=rb->next) {
#ifdef NAS_DEBUG_CLASS
576
    printk("SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS\n");
Cedric Roux's avatar
Cedric Roux committed
577 578 579 580 581 582
    printk("NAS_COMMON_SEARCH_RB - rab_id %d Comparing  rb_entity.rab_id %u \n", rb->rab_id, 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);
583 584 585 586
#endif

                                if (rb->rab_id==rab_id)
                                return rb;
587
  }
588 589

                     return NULL;
590 591
}

592 593
              //
              // Search for a classifier with corresponding radio bearer
594

595 596
              struct classifier_entity *nas_COMMON_search_class_for_rb(nasRadioBearerId_t rab_id,struct nas_priv *priv)
{
597

Cedric Roux's avatar
Cedric Roux committed
598
  //struct rb_entity *rb;
599 600 601 602 603 604 605
  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

606 607 608
  for (dscp=0; dscp<NAS_DSCP_MAX; dscp++) {

    //      printk("[NAS][COMMON] priv->rclassifier[%d] = %p\n",dscp,priv->rclassifier[dscp]);
609 610 611 612
    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
613

614
      if (rclass->rab_id==rab_id)
615
        return rclass;
616 617
    }
  }
618

619
  return NULL;
620

621 622 623
}

//---------------------------------------------------------------------------
624 625
struct rb_entity *nas_COMMON_add_rb(struct cx_entity *cx, nasRadioBearerId_t rab_id, nasQoSTrafficClass_t qos)
{
626 627 628 629 630
  //--------------------------------------------------------------------------
  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
631 632

  if (cx==NULL) {
633 634 635 636 637
#ifdef NAS_DEBUG_CLASS
    printk("NAS_COMMON_ADD_RB - input parameter cx is NULL \n");
#endif
    return NULL;
  }
638

639
  rb=nas_COMMON_search_rb(cx, rab_id);
640 641 642 643 644 645 646 647 648

  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);
649
#ifdef NAS_DEBUG_DC
650 651 652 653 654 655 656 657 658 659 660 661
      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");
  }

662 663 664 665 666 667 668
#ifdef NAS_DEBUG_CLASS
  printk("NAS_COMMON_ADD_RB - end \n" );
#endif
  return rb;
}

//---------------------------------------------------------------------------
669 670
void nas_COMMON_flush_rb(struct cx_entity *cx)
{
671 672 673
  //---------------------------------------------------------------------------
  struct rb_entity *rb;
  struct classifier_entity *gc;
674
  uint8_t dscp;
675 676 677 678
  // End debug information
#ifdef NAS_DEBUG_CLASS
  printk("NAS_COMMON_FLUSH_RB - begin\n");
#endif
679 680

  if (cx==NULL) {
681 682 683 684 685
#ifdef NAS_DEBUG_CLASS
    printk("NAS_COMMON_FLUSH_RB - input parameter cx is NULL \n");
#endif
    return;
  }
686

687
  // End debug information
688
  for (rb=cx->rb; rb!=NULL; rb=cx->rb) {
689 690 691 692
    printk("NAS_COMMON_FLUSH_RB: del rab_id %u\n", rb->rab_id);
    cx->rb=rb->next;
    kfree(rb);
  }
693

694 695
  cx->num_rb=0;
  cx->rb=NULL;
696 697 698 699 700 701

  for(dscp=0; dscp<NAS_DSCP_MAX; ++dscp) {
    for (gc=cx->sclassifier[dscp]; gc!=NULL; gc=gc->next)
      gc->rb=NULL;
  }

702 703 704 705
#ifdef NAS_DEBUG_CLASS
  printk("NAS_COMMON_FLUSH_RB - end\n");
#endif
}