device.c 14.2 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
/*! \file device.c
* \brief Networking Device Driver for OpenAirInterface
24
* \author  navid nikaein,  Lionel Gauthier, raymond knopp
25 26 27 28 29 30 31 32 33 34 35
* \company Eurecom
* \email: raymond.knopp@eurecom.fr, navid.nikaein@eurecom.fr, lionel.gauthier@eurecom.fr

*/
/*******************************************************************************/

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

#include <linux/kernel.h>
36
#include <linux/version.h>
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/moduleparam.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/delay.h>
#include <asm/unistd.h>
#include <linux/netdevice.h>



struct net_device *ue_ip_dev[UE_IP_NB_INSTANCES_MAX];

#ifdef OAI_NW_DRIVER_USE_NETLINK
54 55
  extern void ue_ip_netlink_release(void);
  extern int ue_ip_netlink_init(void);
56 57 58
#endif

//---------------------------------------------------------------------------
59
int ue_ip_find_inst(struct net_device *dev_pP) {
60
  //---------------------------------------------------------------------------
61 62
  int i;

63
  for (i=0; i<UE_IP_NB_INSTANCES_MAX; i++)
64
    if (ue_ip_dev[i] == dev_pP) {
65
      return(i);
66
    }
67

68 69 70 71 72 73
  return(-1);
}

//---------------------------------------------------------------------------

#ifndef OAI_NW_DRIVER_USE_NETLINK
74
void *ue_ip_interrupt(void) {
75
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
76 77
  uint8_t cxi;
  //  ue_ip_priv_t *priv_p=netdev_priv(dev_id);
78
  //  unsigned int flags;
Lionel Gauthier's avatar
Lionel Gauthier committed
79
  //  priv_p->lock = SPIN_LOCK_UNLOCKED;
80 81 82
#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT - begin\n");
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
83
  //  spin_lock_irqsave(&priv_p->lock,flags);
84 85 86 87 88 89
  cxi=0;
  //    mesh_GC_receive();
  //    mesh_DC_receive(naspriv->cx+cxi);
#ifndef OAI_NW_DRIVER_USE_NETLINK
  ue_ip_common_wireless2ip();
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
90
  //  spin_unlock_irqrestore(&priv_p->lock,flags);
91 92 93 94 95 96 97
#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT: end\n");
#endif
  //  return 0;
}
#endif //NETLINK
//---------------------------------------------------------------------------
98
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
99
  void ue_ip_timer(struct timer_list *t)
100
#else
101
  void ue_ip_timer(unsigned long dataP)
102
#endif
103
{
104
  //---------------------------------------------------------------------------
105 106 107 108 109
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
  ue_ip_priv_t *priv_p = from_timer(priv_p, t, timer);
#else
  ue_ip_priv_t *priv_p = (ue_ip_priv_t *)dataP;
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
110
  spin_lock(&priv_p->lock);
111 112 113 114 115 116
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
  mod_timer(&priv_p->timer, jiffies + UE_IP_TIMER_TICK);
#else
  (priv_p->timer).function = ue_ip_timer;
  (priv_p->timer).expires = jiffies + UE_IP_TIMER_TICK;
  (priv_p->timer).data = dataP;
Lionel Gauthier's avatar
Lionel Gauthier committed
117
  add_timer(&priv_p->timer);
118
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
119
  spin_unlock(&priv_p->lock);
120
  return;
121 122
  //  add_timer(&gpriv->timer);
  //  spin_unlock(&gpriv->lock);
123 124 125 126
}

//---------------------------------------------------------------------------
// Called by ifconfig when the device is activated by ifconfig
127
int ue_ip_open(struct net_device *dev_pP) {
128
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
129
  ue_ip_priv_t *priv_p=netdev_priv(dev_pP);
130 131
  // Address has already been set at init
#ifndef OAI_NW_DRIVER_USE_NETLINK
132 133 134 135

  if (pdcp_2_ue_ip_irq==-EBUSY) {
    printk("[UE_IP_DRV][%s] : irq failure\n", __FUNCTION__);
    return -EBUSY;
136
  }
137

138 139
#endif //OAI_NW_DRIVER_USE_NETLINK

140
  if(!netif_queue_stopped(dev_pP)) {
141
    netif_start_queue(dev_pP);
142
  } else {
143
    netif_wake_queue(dev_pP);
144
  }
145

146 147 148 149
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
  timer_setup(&(priv_p->timer), ue_ip_timer, 0);
  (priv_p->timer).expires   = jiffies+UE_IP_TIMER_TICK;
#else
Lionel Gauthier's avatar
Lionel Gauthier committed
150 151 152 153
  init_timer(&priv_p->timer);
  (priv_p->timer).expires   = jiffies+UE_IP_TIMER_TICK;
  (priv_p->timer).data      = (unsigned long)priv_p;
  (priv_p->timer).function  = ue_ip_timer;
154
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
155 156
  //add_timer(&priv_p->timer);
  printk("[UE_IP_DRV][%s] name = %s\n", __FUNCTION__, dev_pP->name);
157 158 159 160 161
  return 0;
}

//---------------------------------------------------------------------------
// Called by ifconfig when the device is desactivated
162
int ue_ip_stop(struct net_device *dev_pP) {
163
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
164
  ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
165
  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
Lionel Gauthier's avatar
Lionel Gauthier committed
166 167
  del_timer(&(priv_p->timer));
  netif_stop_queue(dev_pP);
168 169 170 171 172 173
  //    MOD_DEC_USE_COUNT;
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
174
void ue_ip_teardown(struct net_device *dev_pP) {
175
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
176
  ue_ip_priv_t    *priv_p;
177 178
  int              inst;
  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
179

Lionel Gauthier's avatar
Lionel Gauthier committed
180
  if (dev_pP) {
181 182
    priv_p = netdev_priv(dev_pP);
    inst = ue_ip_find_inst(dev_pP);
183

184
    if ((inst<0) || (inst>=UE_IP_NB_INSTANCES_MAX)) {
185 186 187
      printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__);
      return;
    }
188

189
    printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
Lionel Gauthier's avatar
Lionel Gauthier committed
190
  } // check dev_pP
191
  else {
192
    printk("[UE_IP_DRV][%s] Device is null\n", __FUNCTION__);
193 194 195
  }
}
//---------------------------------------------------------------------------
196
int ue_ip_set_config(struct net_device *dev_pP, struct ifmap *map_pP) {
197 198
  //---------------------------------------------------------------------------
  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
199

200
  if (dev_pP->flags & IFF_UP) {
201
    return -EBUSY;
202
  }
203

Lionel Gauthier's avatar
Lionel Gauthier committed
204
  if (map_pP->base_addr != dev_pP->base_addr) {
205 206
    printk(KERN_WARNING "[UE_IP_DRV][%s] Can't change I/O address\n", __FUNCTION__);
    return -EOPNOTSUPP;
207
  }
208

209
  if (map_pP->irq != dev_pP->irq) {
210
    dev_pP->irq = map_pP->irq;
211
  }
212

213 214 215 216 217 218
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
//
219
int ue_ip_hard_start_xmit(struct sk_buff *skb_pP, struct net_device *dev_pP) {
220 221 222
  //---------------------------------------------------------------------------
  int inst;

Lionel Gauthier's avatar
Lionel Gauthier committed
223
  if (dev_pP) {
224
    inst = ue_ip_find_inst(dev_pP);
225
  } else {
226 227
    printk("[UE_IP_DRV][%s] ERROR, device is null\n", __FUNCTION__);
    return -1;
228 229
  }

230
  if ((inst>=0) && (inst<UE_IP_NB_INSTANCES_MAX)) {
231 232 233
#ifdef OAI_DRV_OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] inst %d,  begin\n", __FUNCTION__,inst);
#endif
234

235 236 237 238 239 240 241
    if (!skb_pP) {
      printk("[UE_IP_DRV][%s] input parameter skb is NULL\n", __FUNCTION__);
      return -1;
    }

    // End debug information
    netif_stop_queue(dev_pP);
242
#if  LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1796)
243 244
    netif_trans_update(dev_pP);
#else
245
    dev_pP->trans_start = jiffies;
246
#endif
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
#ifdef OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] step 1\n", __FUNCTION__);
#endif
    ue_ip_common_ip2wireless(skb_pP,inst);
#ifdef OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] step 2\n", __FUNCTION__);
#endif
    dev_kfree_skb(skb_pP);
#ifdef OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] step 3\n", __FUNCTION__);
#endif
    netif_wake_queue(dev_pP);
#ifdef OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] end\n", __FUNCTION__);
#endif
262
  } else {
263 264
    printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__);
    return(-1);
265
  }
266

267 268 269 270
  return 0;
}

//---------------------------------------------------------------------------
271
struct net_device_stats *ue_ip_get_stats(struct net_device *dev_pP) {
272
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
273 274
  ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
  return &priv_p->stats;
275 276
}
//---------------------------------------------------------------------------
277
int ue_ip_set_mac_address(struct net_device *dev_pP, void *mac_pP) {
278
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
279
  //struct sockaddr *addr = mac_pP;
280
  printk("[UE_IP_DRV][%s] CHANGE MAC ADDRESS UNSUPPORTED\n", __FUNCTION__);
Lionel Gauthier's avatar
Lionel Gauthier committed
281
  //memcpy(dev_pP->dev_addr, addr->sa_data, dev_pP->addr_len);
282 283 284
  return 0;
}
//---------------------------------------------------------------------------
285
int ue_ip_change_mtu(struct net_device *dev_pP, int mtuP) {
286
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
287
  printk("[UE_IP_DRV][%s] CHANGE MTU %d bytes\n", __FUNCTION__, mtuP);
288

289
  if ((mtuP<50) || (mtuP>1500)) {
290
    return -EINVAL;
291
  }
292

Lionel Gauthier's avatar
Lionel Gauthier committed
293
  dev_pP->mtu = mtuP;
294 295 296
  return 0;
}
//---------------------------------------------------------------------------
297
void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP) {
298
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
299 300 301
  ue_ip_priv_t *priv_p =  netdev_priv(dev_pP);
  printk("[UE_IP_DRV][%s] CHANGE RX FLAGS %08X\n", __FUNCTION__, flagsP);
  priv_p->rx_flags ^= flagsP;
302 303 304
}

//---------------------------------------------------------------------------
305
void ue_ip_tx_timeout(struct net_device *dev_pP) {
306 307
  //---------------------------------------------------------------------------
  // Transmitter timeout, serious problems.
Lionel Gauthier's avatar
Lionel Gauthier committed
308
  ue_ip_priv_t *priv_p =  netdev_priv(dev_pP);
309
  printk("[UE_IP_DRV][%s] begin\n", __FUNCTION__);
Lionel Gauthier's avatar
Lionel Gauthier committed
310 311
  //  (ue_ip_priv_t *)(dev_pP->priv_p)->stats.tx_errors++;
  (priv_p->stats).tx_errors++;
312
#if  LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1796)
313 314
  netif_trans_update(dev_pP);
#else
Lionel Gauthier's avatar
Lionel Gauthier committed
315
  dev_pP->trans_start = jiffies;
316
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
317 318
  netif_wake_queue(dev_pP);
  printk("[UE_IP_DRV][%s] transmit timed out %s\n", __FUNCTION__,dev_pP->name);
319 320 321
}

static const struct net_device_ops ue_ip_netdev_ops = {
322 323 324 325 326 327 328 329
  .ndo_open               = ue_ip_open,
  .ndo_stop               = ue_ip_stop,
  .ndo_start_xmit         = ue_ip_hard_start_xmit,
  .ndo_validate_addr      = NULL,
  .ndo_get_stats          = ue_ip_get_stats,
  .ndo_set_mac_address    = ue_ip_set_mac_address,
  .ndo_set_config         = ue_ip_set_config,
  .ndo_do_ioctl           = NULL,
330
#if (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1797)
331 332 333 334
  .extended.ndo_change_mtu         = ue_ip_change_mtu,
#else
  .ndo_change_mtu   = ue_ip_change_mtu,
#endif
335 336
  .ndo_tx_timeout         = ue_ip_tx_timeout,
  .ndo_change_rx_flags    = ue_ip_change_rx_flags,
337
};
338
/*.ndo_set_multicast_list = NULL,*/
339 340 341

//---------------------------------------------------------------------------
// Initialisation of the network device
342
void ue_ip_init(struct net_device *dev_pP) {
343
  //---------------------------------------------------------------------------
Lionel Gauthier's avatar
Lionel Gauthier committed
344
  ue_ip_priv_t *priv_p = NULL;
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359

  if (dev_pP) {
    priv_p = netdev_priv(dev_pP);
    memset(priv_p, 0, sizeof(ue_ip_priv_t));
    spin_lock_init(&priv_p->lock);
    dev_pP->netdev_ops = &ue_ip_netdev_ops;
    dev_pP->hard_header_len = 0;
    dev_pP->addr_len = UE_IP_ADDR_LEN;
    dev_pP->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP;
    dev_pP->tx_queue_len = UE_IP_TX_QUEUE_LEN;
    dev_pP->mtu = UE_IP_MTU;
  } else {
    printk("[UE_IP_DRV][%s] ERROR, Device is NULL!!\n", __FUNCTION__);
    return;
  }
360 361
}
//---------------------------------------------------------------------------
362
int init_module (void) {
363
  //---------------------------------------------------------------------------
364 365 366 367 368
  int err,inst;
  char devicename[100];
  // Initialize parameters shared with RRC
  printk("[UE_IP_DRV][%s] Starting OAI IP driver", __FUNCTION__);

369
  for (inst=0; inst<UE_IP_NB_INSTANCES_MAX; inst++) {
370
    printk("[UE_IP_DRV][%s] begin init instance %d\n", __FUNCTION__,inst);
371
    sprintf(devicename,"oip%d",inst+1);
372
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
Lionel Gauthier's avatar
Lionel Gauthier committed
373
    ue_ip_dev[inst]  = alloc_netdev(sizeof(ue_ip_priv_t),devicename, ue_ip_init);
374 375 376
#else
    ue_ip_dev[inst]  = alloc_netdev(sizeof(ue_ip_priv_t),devicename, NET_NAME_PREDICTABLE,ue_ip_init);
#endif
377

378 379
    //netif_stop_queue(ue_ip_dev[inst]);
    if (ue_ip_dev[inst] == NULL) {
380
      printk("[UE_IP_DRV][%s][INST %02d] alloc_netdev FAILED\n", __FUNCTION__,inst);
381
    } else {
382 383 384 385 386 387 388 389
      // linux/net/core/dev.c line 4767
      err= register_netdev(ue_ip_dev[inst]);

      if (err) {
        printk("[UE_IP_DRV][%s] (inst %d): error %i registering device %s\n", __FUNCTION__, inst,err, ue_ip_dev[inst]->name);
      } else {
        printk("[UE_IP_DRV][%s] registering device %s, ifindex = %d\n\n", __FUNCTION__,ue_ip_dev[inst]->name, ue_ip_dev[inst]->ifindex);
      }
390 391 392 393
    }
  }

  printk("[UE_IP_DRV][%s] NETLINK INIT\n", __FUNCTION__);
394

395
  if ((err=ue_ip_netlink_init()) == -1) {
396
    printk("[UE_IP_DRV][%s] NETLINK failed\n", __FUNCTION__);
397
  }
398 399 400 401 402

  return err;
}

//---------------------------------------------------------------------------
403
void cleanup_module(void) {
404 405
  //---------------------------------------------------------------------------
  int inst;
406
  printk("[UE_IP_DRV][CLEANUP] begin\n");
407

408
  for (inst=0; inst<UE_IP_NB_INSTANCES_MAX; inst++) {
409
#ifdef OAI_DRV_DEBUG_DEVICE
410
    printk("[UE_IP_DRV][CLEANUP]  unregister and free net device instance %d\n",inst);
411
#endif
412 413 414 415 416

    if (ue_ip_dev[inst]) {
      unregister_netdev(ue_ip_dev[inst]);
      ue_ip_teardown(ue_ip_dev[inst]);
      free_netdev(ue_ip_dev[inst]);
417
    }
418 419 420
  }

  ue_ip_netlink_release();
421
  printk("[UE_IP_DRV][CLEANUP] end\n");
422 423 424 425 426 427 428 429 430
}

#define DRV_NAME        "ue_ip"
#define DRV_VERSION     "1.0"DRV_NAME
#define DRV_DESCRIPTION "OPENAIR UE IP Device Driver"
#define DRV_COPYRIGHT   "-Copyright(c) GNU GPL Eurecom 2013"
#define DRV_AUTHOR      "Lionel GAUTHIER: <firstname.name@eurecom.fr>"DRV_COPYRIGHT