common.c 12.1 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
/*! \file common.c
23
* \brief
24 25 26 27 28 29 30 31 32 33
* \author Navid Nikaein and Raymond Knopp, Lionel GAUTHIER
* \date 2013
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr, lionel.gauthier@eurecom.fr
*/

#include "local.h"
#include "proto_extern.h"
#ifndef OAI_NW_DRIVER_USE_NETLINK
34
  #include "rtai_fifos.h"
35 36 37 38 39 40 41 42 43
#endif


#include <linux/inetdevice.h>

#include <net/tcp.h>
#include <net/udp.h>

#define NIPADDR(addr) \
44 45 46 47
  (uint8_t)(addr & 0x000000FF), \
  (uint8_t)((addr & 0x0000FF00) >> 8), \
  (uint8_t)((addr & 0x00FF0000) >> 16), \
  (uint8_t)((addr & 0xFF000000) >> 24)
48 49

#define NIP6ADDR(addr) \
50 51 52 53 54 55 56 57
  ntohs((addr)->s6_addr16[0]), \
  ntohs((addr)->s6_addr16[1]), \
  ntohs((addr)->s6_addr16[2]), \
  ntohs((addr)->s6_addr16[3]), \
  ntohs((addr)->s6_addr16[4]), \
  ntohs((addr)->s6_addr16[5]), \
  ntohs((addr)->s6_addr16[6]), \
  ntohs((addr)->s6_addr16[7])
58 59 60 61


//#define OAI_DRV_DEBUG_SEND
//#define OAI_DRV_DEBUG_RECEIVE
Lionel Gauthier's avatar
Lionel Gauthier committed
62 63 64

void
ue_ip_common_class_wireless2ip(
65 66 67
  sdu_size_t data_lenP,
  void      *pdcp_sdu_pP,
  int        instP,
68
  rb_id_t    rb_idP) {
69
  //---------------------------------------------------------------------------
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  struct sk_buff      *skb_p           = NULL;
  ipversion_t         *ipv_p           = NULL;
  ue_ip_priv_t        *gpriv_p         = netdev_priv(ue_ip_dev[instP]);
  unsigned int         hard_header_len = 0;
#ifdef OAI_DRV_DEBUG_RECEIVE
  int                  i;
  unsigned char       *addr_p          = 0;
#endif
  unsigned char        protocol;
  struct iphdr        *network_header_p  = NULL;
#ifdef OAI_DRV_DEBUG_RECEIVE
  printk("[UE_IP_DRV][%s] begin RB %d Inst %d Length %d bytes\n",__FUNCTION__, rb_idP,instP,data_lenP);
#endif
  skb_p = dev_alloc_skb( data_lenP + 2 );

  if(!skb_p) {
    printk("[UE_IP_DRV][%s] low on memory\n",__FUNCTION__);
    ++gpriv_p->stats.rx_dropped;
    return;
  }

  skb_reserve(skb_p,2);
  memcpy(skb_put(skb_p, data_lenP), pdcp_sdu_pP,data_lenP);
  skb_p->dev = ue_ip_dev[instP];
  hard_header_len = ue_ip_dev[instP]->hard_header_len;
  skb_set_mac_header(skb_p, 0);
96
  skb_set_network_header(skb_p, hard_header_len);
97
  skb_p->mark = rb_idP;
98 99 100 101 102
  //printk("[NAC_COMMIN_RECEIVE]: Packet Type %d (%d,%d)",skb_p->pkt_type,PACKET_HOST,PACKET_BROADCAST);
  skb_p->pkt_type = PACKET_HOST;
#ifdef OAI_DRV_DEBUG_RECEIVE
  printk("[UE_IP_DRV][%s] Receiving packet of size %d from PDCP \n",__FUNCTION__, skb_p->len);

103
  for (i=0; i<skb_p->len; i++) {
104
    printk("%2x ",((unsigned char *)(skb_p->data))[i]);
105
  }
106 107 108 109 110 111 112 113 114

  printk("\n");
#endif
#ifdef OAI_DRV_DEBUG_RECEIVE
  printk("[UE_IP_DRV][%s] skb_p->data           @ %p\n",__FUNCTION__,  skb_p->data);
  printk("[UE_IP_DRV][%s] skb_p->mac_header     @ %p\n",__FUNCTION__,  skb_p->mac_header);
#endif
  // LG TEST skb_p->ip_summed = CHECKSUM_NONE;
  skb_p->ip_summed = CHECKSUM_UNNECESSARY;
115
  ipv_p = (ipversion_t *)((void *)&(skb_p->data[hard_header_len]));
116 117

  switch (ipv_p->version) {
118
    case 6:
119
#ifdef OAI_DRV_DEBUG_RECEIVE
120
      printk("[UE_IP_DRV][%s] receive IPv6 message\n",__FUNCTION__);
121
#endif
122 123 124
      skb_set_network_header(skb_p, hard_header_len);

      //skb_p->network_header_p = &skb_p->data[hard_header_len];
125

126 127 128
      if (hard_header_len == 0) {
        skb_p->protocol = htons(ETH_P_IPV6);
      } else {
129
#ifdef OAI_NW_DRIVER_TYPE_ETHERNET
130
        skb_p->protocol = eth_type_trans(skb_p, ue_ip_dev[instP]);
131 132
#else
#endif
133
      }
134

135 136
      //printk("Writing packet with protocol %x\n",ntohs(skb_p->protocol));
      break;
137

138
    case 4:
139
#ifdef OAI_DRV_DEBUG_RECEIVE
140 141
      //printk("NAS_TOOL_RECEIVE: receive IPv4 message\n");
      addr_p = (unsigned char *)&((struct iphdr *)&skb_p->data[hard_header_len])->saddr;
142

143 144 145
      if (addr_p) {
        printk("[UE_IP_DRV][%s] Source %d.%d.%d.%d\n",__FUNCTION__, addr_p[0],addr_p[1],addr_p[2],addr_p[3]);
      }
146

147
      addr_p = (unsigned char *)&((struct iphdr *)&skb_p->data[hard_header_len])->daddr;
148

149 150 151
      if (addr_p) {
        printk("[UE_IP_DRV][%s] Dest %d.%d.%d.%d\n",__FUNCTION__, addr_p[0],addr_p[1],addr_p[2],addr_p[3]);
      }
152

153
      printk("[UE_IP_DRV][%s] protocol  %d\n",__FUNCTION__, ((struct iphdr *)&skb_p->data[hard_header_len])->protocol);
154
#endif
155 156 157 158
      skb_set_network_header(skb_p, hard_header_len);
      //network_header_p = (struct iphdr *)skb_network_header(skb_p);
      network_header_p = (struct iphdr *)skb_network_header(skb_p);
      protocol = network_header_p->protocol;
159 160
#ifdef OAI_DRV_DEBUG_RECEIVE

161 162 163 164
      switch (protocol) {
        case IPPROTO_IP:
          printk("[UE_IP_DRV][%s] Received Raw IPv4 packet\n",__FUNCTION__);
          break;
165

166 167 168
        case IPPROTO_IPV6:
          printk("[UE_IP_DRV][%s] Received Raw IPv6 packet\n",__FUNCTION__);
          break;
169

170 171 172
        case IPPROTO_ICMP:
          printk("[UE_IP_DRV][%s] Received Raw ICMP packet\n",__FUNCTION__);
          break;
173

174 175 176
        case IPPROTO_TCP:
          printk("[UE_IP_DRV][%s] Received TCP packet\n",__FUNCTION__);
          break;
177

178 179 180
        case IPPROTO_UDP:
          printk("[UE_IP_DRV][%s] Received UDP packet\n",__FUNCTION__);
          break;
181

182 183 184
        default:
          break;
      }
185 186 187

#endif

188 189 190
      if (hard_header_len == 0) {
        skb_p->protocol = htons(ETH_P_IP);
      }
191

192 193
      //printk("[UE_IP_DRV][COMMON] Writing packet with protocol %x\n",ntohs(skb_p->protocol));
      break;
194

195 196 197
    default:
      printk("[UE_IP_DRV][%s] begin RB %d Inst %d Length %d bytes\n",__FUNCTION__,rb_idP,instP,data_lenP);
      printk("[UE_IP_DRV][%s] Inst %d: receive unknown message (version=%d)\n",__FUNCTION__,instP,ipv_p->version);
198 199 200 201 202 203 204
  }

  ++gpriv_p->stats.rx_packets;
  gpriv_p->stats.rx_bytes += data_lenP;
#ifdef OAI_DRV_DEBUG_RECEIVE
  printk("[UE_IP_DRV][%s] sending packet of size %d to kernel\n",__FUNCTION__,skb_p->len);

205
  for (i=0; i<skb_p->len; i++) {
206
    printk("%2x ",((unsigned char *)(skb_p->data))[i]);
207
  }
208 209 210

  printk("\n");
#endif //OAI_DRV_DEBUG_RECEIVE
211
  netif_rx_ni(skb_p);
212 213 214
#ifdef OAI_DRV_DEBUG_RECEIVE
  printk("[UE_IP_DRV][%s] end\n",__FUNCTION__);
#endif
215 216 217 218
}

//---------------------------------------------------------------------------
// Delete the data
219
void ue_ip_common_ip2wireless_drop(struct sk_buff *skb_pP,  int instP) {
220
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
221 222
  ue_ip_priv_t *priv_p=netdev_priv(ue_ip_dev[instP]);
  ++priv_p->stats.tx_dropped;
223 224 225 226
}

//---------------------------------------------------------------------------
// Request the transfer of data (QoS SAP)
Lionel Gauthier's avatar
Lionel Gauthier committed
227 228
void
ue_ip_common_ip2wireless(
229 230
  struct sk_buff *skb_pP,
  int instP
231
) {
232
  //---------------------------------------------------------------------------
233
  struct pdcp_data_req_header_s     pdcph;
Lionel Gauthier's avatar
Lionel Gauthier committed
234
  ue_ip_priv_t                     *priv_p=netdev_priv(ue_ip_dev[instP]);
235 236 237 238
  ipversion_t         *ipv_p             = NULL;
  unsigned int         hard_header_len   = 0;
  unsigned char       *src_addr          = 0;
  unsigned char       *dst_addr          = 0;
239 240 241 242 243 244 245 246 247
#ifdef LOOPBACK_TEST
  int i;
#endif
#ifdef OAI_DRV_DEBUG_SEND
  int j;
#endif
  unsigned int bytes_wrote;
  // Start debug information
#ifdef OAI_DRV_DEBUG_SEND
Lionel Gauthier's avatar
Lionel Gauthier committed
248
  printk("[UE_IP_DRV][%s] inst %d begin \n",__FUNCTION__,instP);
249 250
#endif

251
  if (skb_pP==NULL) {
252 253 254 255 256 257
#ifdef OAI_DRV_DEBUG_SEND
    printk("[UE_IP_DRV][%s] input parameter skb is NULL \n",__FUNCTION__);
#endif
    return;
  }

Lionel Gauthier's avatar
Lionel Gauthier committed
258
  pdcph.data_size  = skb_pP->len;
259

Lionel Gauthier's avatar
Lionel Gauthier committed
260
  if (skb_pP->mark) {
261
    pdcph.rb_id      = skb_pP->mark;
262
  } else {
263
    pdcph.rb_id      = UE_IP_DEFAULT_RAB_ID;
264
  }
265

Lionel Gauthier's avatar
Lionel Gauthier committed
266
  pdcph.inst       = instP;
267 268 269 270 271
  //pass source/destination IP addresses to PDCP header
  hard_header_len = ue_ip_dev[instP]->hard_header_len;
  ipv_p = (ipversion_t *)((void *)&(skb_pP->data[hard_header_len]));

  switch (ipv_p->version) {
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
    case 6:
      printk("[UE_IP_DRV][%s] receive IPv6 message\n",__FUNCTION__);
      //TODO
      break;

    case 4:
      src_addr = (unsigned char *)&((struct iphdr *)&skb_pP->data[hard_header_len])->saddr;

      if (src_addr) {
        printk("[UE_IP_DRV][%s] Source %d.%d.%d.%d\n",__FUNCTION__, src_addr[0],src_addr[1],src_addr[2],src_addr[3]);
      }

      dst_addr = (unsigned char *)&((struct iphdr *)&skb_pP->data[hard_header_len])->daddr;

      if (dst_addr) {
        printk("[UE_IP_DRV][%s] Dest %d.%d.%d.%d\n",__FUNCTION__, dst_addr[0],dst_addr[1],dst_addr[2],dst_addr[3]);
      }

      // modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator start
291
#ifdef UESIM_EXPANSION
292 293

      if ((src_addr[3] - 2)> instP) {
294
        pdcph.inst = src_addr[3] - 2;
295
        printk("[UE_IP_DRV] change INST from %d to %d\n",instP, pdcph.inst);
296
        instP = src_addr[3] - 2;
297
        priv_p=netdev_priv(ue_ip_dev[instP]);
298 299
      }

300
#endif
301 302 303 304 305 306 307
      // modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator end
      //get Ipv4 address and pass to PCDP header
      printk("[UE_IP_DRV] source Id: 0x%08x\n",pdcph.sourceL2Id );
      printk("[UE_IP_DRV] destinationL2Id Id: 0x%08x\n",pdcph.destinationL2Id );
      pdcph.sourceL2Id = ntohl( ((struct iphdr *)&skb_pP->data[hard_header_len])->saddr) & 0x00FFFFFF;
      pdcph.destinationL2Id = ntohl( ((struct iphdr *)&skb_pP->data[hard_header_len])->daddr) & 0x00FFFFFF;
      break;
308

309 310 311
    default:
      break;
  }
312 313 314 315

  bytes_wrote = ue_ip_netlink_send((char *)&pdcph,UE_IP_PDCPH_SIZE);
#ifdef OAI_DRV_DEBUG_SEND
  printk("[UE_IP_DRV][%s] Wrote %d bytes (header for %d byte skb) to PDCP via netlink\n",__FUNCTION__,
316
         bytes_wrote,skb_pP->len);
317 318
#endif

319 320
  if (bytes_wrote != UE_IP_PDCPH_SIZE) {
    printk("[UE_IP_DRV][%s] problem while writing PDCP's header (bytes wrote = %d)\n",__FUNCTION__,bytes_wrote);
321
    printk("rb_id %d, Wrote %d, Header Size %d \n", pdcph.rb_id, bytes_wrote, UE_IP_PDCPH_SIZE);
322 323 324
    priv_p->stats.tx_dropped ++;
    return;
  }
325

Lionel Gauthier's avatar
Lionel Gauthier committed
326
  bytes_wrote += ue_ip_netlink_send((char *)skb_pP->data,skb_pP->len);
327

328 329 330 331 332 333 334 335 336 337 338
  if (bytes_wrote != skb_pP->len+UE_IP_PDCPH_SIZE) {
    printk("[UE_IP_DRV][%s] Inst %d, RB_ID %d: problem while writing PDCP's data, bytes_wrote = %d, Data_len %d, PDCPH_SIZE %d\n",
           __FUNCTION__,
           instP,
           pdcph.rb_id,
           bytes_wrote,
           skb_pP->len,
           UE_IP_PDCPH_SIZE); // congestion
    priv_p->stats.tx_dropped ++;
    return;
  }
339 340

#ifdef OAI_DRV_DEBUG_SEND
Lionel Gauthier's avatar
Lionel Gauthier committed
341
  printk("[UE_IP_DRV][%s] Sending packet of size %d to PDCP \n",__FUNCTION__,skb_pP->len);
342

343
  for (j=0; j<skb_pP->len; j++) {
Lionel Gauthier's avatar
Lionel Gauthier committed
344
    printk("%2x ",((unsigned char *)(skb_pP->data))[j]);
345
  }
346

347 348
  printk("\n");
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
349 350
  priv_p->stats.tx_bytes   += skb_pP->len;
  priv_p->stats.tx_packets ++;
351 352 353 354 355 356
#ifdef OAI_DRV_DEBUG_SEND
  printk("[UE_IP_DRV][%s] end \n",__FUNCTION__);
#endif
}

//---------------------------------------------------------------------------
357
void ue_ip_common_wireless2ip(struct nlmsghdr *nlh_pP) {
358
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
359 360 361
  struct pdcp_data_ind_header_s     *pdcph_p = (struct pdcp_data_ind_header_s *)NLMSG_DATA(nlh_pP);
  ue_ip_priv_t                      *priv_p;
  priv_p = netdev_priv(ue_ip_dev[pdcph_p->inst]);
362 363
#ifdef OAI_DRV_DEBUG_RECEIVE
  printk("[UE_IP_DRV][%s] QOS receive from PDCP, size %d, rab %d, inst %d\n",__FUNCTION__,
Lionel Gauthier's avatar
Lionel Gauthier committed
364
         pdcph_p->data_size,pdcph_p->rb_id,pdcph_p->inst);
365
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
366
  ue_ip_common_class_wireless2ip(pdcph_p->data_size,
367
                                 (unsigned char *)NLMSG_DATA(nlh_pP) + UE_IP_PDCPH_SIZE,
Cedric Roux's avatar
Cedric Roux committed
368
                                 pdcph_p->inst,
369
                                 pdcph_p->rb_id);
370 371
}