device.c 13.6 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
Cedric Roux's avatar
Cedric Roux committed
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
 */

gauthier's avatar
gauthier committed
22
23
/*! \file device.c
* \brief Networking Device Driver for OpenAirInterface
nikaeinn's avatar
nikaeinn committed
24
* \author  navid nikaein,  Lionel Gauthier, raymond knopp
gauthier's avatar
gauthier committed
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>
thomasl's avatar
thomasl committed
36
#include <linux/version.h>
gauthier's avatar
gauthier committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#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
extern void ue_ip_netlink_release(void);
extern int ue_ip_netlink_init(void);
#endif

//---------------------------------------------------------------------------
59
60
61
int ue_ip_find_inst(struct net_device *dev_pP)
{
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
62
63
  int i;

64
  for (i=0; i<UE_IP_NB_INSTANCES_MAX; i++)
65
    if (ue_ip_dev[i] == dev_pP) {
gauthier's avatar
gauthier committed
66
      return(i);
67
    }
68

gauthier's avatar
gauthier committed
69
70
71
72
73
74
  return(-1);
}

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

#ifndef OAI_NW_DRIVER_USE_NETLINK
75
76
void *ue_ip_interrupt(void)
{
gauthier's avatar
gauthier committed
77
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
78
  uint8_t cxi;
gauthier's avatar
gauthier committed
79

gauthier's avatar
gauthier committed
80
  //  ue_ip_priv_t *priv_p=netdev_priv(dev_id);
gauthier's avatar
gauthier committed
81
  //  unsigned int flags;
gauthier's avatar
gauthier committed
82
  //  priv_p->lock = SPIN_LOCK_UNLOCKED;
gauthier's avatar
gauthier committed
83
84
85
86

#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT - begin\n");
#endif
gauthier's avatar
gauthier committed
87
  //  spin_lock_irqsave(&priv_p->lock,flags);
gauthier's avatar
gauthier committed
88
89
90
91
92
93
  cxi=0;
  //    mesh_GC_receive();
  //    mesh_DC_receive(naspriv->cx+cxi);
#ifndef OAI_NW_DRIVER_USE_NETLINK
  ue_ip_common_wireless2ip();
#endif
gauthier's avatar
gauthier committed
94
  //  spin_unlock_irqrestore(&priv_p->lock,flags);
gauthier's avatar
gauthier committed
95
96
97
98
99
100
101
#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT: end\n");
#endif
  //  return 0;
}
#endif //NETLINK
//---------------------------------------------------------------------------
102
103
void ue_ip_timer(unsigned long dataP)
{
gauthier's avatar
gauthier committed
104
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
105
106
107
108
109
110
111
  ue_ip_priv_t *priv_p=(ue_ip_priv_t *)dataP;
  spin_lock(&priv_p->lock);
  (priv_p->timer).function=ue_ip_timer;
  (priv_p->timer).expires=jiffies+UE_IP_TIMER_TICK;
  (priv_p->timer).data=dataP;
  add_timer(&priv_p->timer);
  spin_unlock(&priv_p->lock);
gauthier's avatar
gauthier committed
112
  return;
113
114
  //  add_timer(&gpriv->timer);
  //  spin_unlock(&gpriv->lock);
gauthier's avatar
gauthier committed
115
116
117
118
}

//---------------------------------------------------------------------------
// Called by ifconfig when the device is activated by ifconfig
119
120
int ue_ip_open(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
121
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
122
  ue_ip_priv_t *priv_p=netdev_priv(dev_pP);
gauthier's avatar
gauthier committed
123
124
125

  // Address has already been set at init
#ifndef OAI_NW_DRIVER_USE_NETLINK
126
127
128
129

  if (pdcp_2_ue_ip_irq==-EBUSY) {
    printk("[UE_IP_DRV][%s] : irq failure\n", __FUNCTION__);
    return -EBUSY;
gauthier's avatar
gauthier committed
130
  }
131

gauthier's avatar
gauthier committed
132
133
#endif //OAI_NW_DRIVER_USE_NETLINK

134
  if(!netif_queue_stopped(dev_pP)) {
135
    netif_start_queue(dev_pP);
136
  } else {
137
    netif_wake_queue(dev_pP);
138
  }
gauthier's avatar
gauthier committed
139

gauthier's avatar
gauthier committed
140
141
142
143
144
  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;
  //add_timer(&priv_p->timer);
gauthier's avatar
gauthier committed
145

gauthier's avatar
gauthier committed
146
  printk("[UE_IP_DRV][%s] name = %s\n", __FUNCTION__, dev_pP->name);
gauthier's avatar
gauthier committed
147
148
149
150
151
  return 0;
}

//---------------------------------------------------------------------------
// Called by ifconfig when the device is desactivated
152
153
int ue_ip_stop(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
154
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
155
  ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
gauthier's avatar
gauthier committed
156
157

  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
158
159
  del_timer(&(priv_p->timer));
  netif_stop_queue(dev_pP);
gauthier's avatar
gauthier committed
160
161
162
163
164
165
  //    MOD_DEC_USE_COUNT;
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
166
167
void ue_ip_teardown(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
168
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
169
  ue_ip_priv_t    *priv_p;
gauthier's avatar
gauthier committed
170
171
172
  int              inst;

  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
173

gauthier's avatar
gauthier committed
174
  if (dev_pP) {
175
176
    priv_p = netdev_priv(dev_pP);
    inst = ue_ip_find_inst(dev_pP);
gauthier's avatar
gauthier committed
177

178
179
180
181
    if ((inst<0) || (inst>=UE_IP_NB_INSTANCES_MAX)) {
      printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__);
      return;
    }
gauthier's avatar
gauthier committed
182

183
184

    printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
gauthier's avatar
gauthier committed
185
  } // check dev_pP
gauthier's avatar
gauthier committed
186
  else {
187
    printk("[UE_IP_DRV][%s] Device is null\n", __FUNCTION__);
gauthier's avatar
gauthier committed
188
189
190
  }
}
//---------------------------------------------------------------------------
191
192
int ue_ip_set_config(struct net_device *dev_pP, struct ifmap *map_pP)
{
gauthier's avatar
gauthier committed
193
194
  //---------------------------------------------------------------------------
  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
195

196
  if (dev_pP->flags & IFF_UP) {
197
    return -EBUSY;
198
  }
199

gauthier's avatar
gauthier committed
200
  if (map_pP->base_addr != dev_pP->base_addr) {
201
202
    printk(KERN_WARNING "[UE_IP_DRV][%s] Can't change I/O address\n", __FUNCTION__);
    return -EOPNOTSUPP;
gauthier's avatar
gauthier committed
203
  }
204

205
  if (map_pP->irq != dev_pP->irq) {
206
    dev_pP->irq = map_pP->irq;
207
  }
208

gauthier's avatar
gauthier committed
209
210
211
212
213
214
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
//
215
216
int ue_ip_hard_start_xmit(struct sk_buff *skb_pP, struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
217
218
219
  //---------------------------------------------------------------------------
  int inst;

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

  if ((inst>=0) && (inst<UE_IP_NB_INSTANCES_MAX)) {
228
229
230
#ifdef OAI_DRV_OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] inst %d,  begin\n", __FUNCTION__,inst);
#endif
gauthier's avatar
gauthier committed
231

232
233
234
235
236
237
238
    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);
oai's avatar
oai committed
239
#if  LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1796)
Cedric Roux's avatar
Cedric Roux committed
240
241
    netif_trans_update(dev_pP);
#else
242
    dev_pP->trans_start = jiffies;
Cedric Roux's avatar
Cedric Roux committed
243
#endif
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#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
gauthier's avatar
gauthier committed
259
  } else {
260
261
    printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__);
    return(-1);
gauthier's avatar
gauthier committed
262
  }
263

gauthier's avatar
gauthier committed
264
265
266
267
  return 0;
}

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

gauthier's avatar
gauthier committed
293
  dev_pP->mtu = mtuP;
gauthier's avatar
gauthier committed
294
295
296
  return 0;
}
//---------------------------------------------------------------------------
297
298
void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP)
{
gauthier's avatar
gauthier committed
299
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
300
301
302
  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;
gauthier's avatar
gauthier committed
303
304
305
}

//---------------------------------------------------------------------------
306
307
void ue_ip_tx_timeout(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
308
309
  //---------------------------------------------------------------------------
  // Transmitter timeout, serious problems.
gauthier's avatar
gauthier committed
310
  ue_ip_priv_t *priv_p =  netdev_priv(dev_pP);
gauthier's avatar
gauthier committed
311
312

  printk("[UE_IP_DRV][%s] begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
313
314
  //  (ue_ip_priv_t *)(dev_pP->priv_p)->stats.tx_errors++;
  (priv_p->stats).tx_errors++;
oai's avatar
oai committed
315
#if  LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1796)
Cedric Roux's avatar
Cedric Roux committed
316
317
  netif_trans_update(dev_pP);
#else
gauthier's avatar
gauthier committed
318
  dev_pP->trans_start = jiffies;
Cedric Roux's avatar
Cedric Roux committed
319
#endif
gauthier's avatar
gauthier committed
320
321
  netif_wake_queue(dev_pP);
  printk("[UE_IP_DRV][%s] transmit timed out %s\n", __FUNCTION__,dev_pP->name);
gauthier's avatar
gauthier committed
322
323
324
}

static const struct net_device_ops ue_ip_netdev_ops = {
325
326
327
328
329
330
331
332
333
334
335
  .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,
  .ndo_change_mtu         = ue_ip_change_mtu,
  .ndo_tx_timeout         = ue_ip_tx_timeout,
  .ndo_change_rx_flags    = ue_ip_change_rx_flags,
gauthier's avatar
gauthier committed
336
};
337
/*.ndo_set_multicast_list = NULL,*/
gauthier's avatar
gauthier committed
338
339
340

//---------------------------------------------------------------------------
// Initialisation of the network device
341
342
void ue_ip_init(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
343
  //---------------------------------------------------------------------------
gauthier's avatar
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;
  }
gauthier's avatar
gauthier committed
360
361
}
//---------------------------------------------------------------------------
362
363
364
int init_module (void)
{
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
365
366
367
368
369
370
371
  int err,inst;
  char devicename[100];


  // Initialize parameters shared with RRC
  printk("[UE_IP_DRV][%s] Starting OAI IP driver", __FUNCTION__);

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

gauthier's avatar
gauthier committed
381
382
    //netif_stop_queue(ue_ip_dev[inst]);
    if (ue_ip_dev[inst] == NULL) {
383
      printk("[UE_IP_DRV][%s][INST %02d] alloc_netdev FAILED\n", __FUNCTION__,inst);
gauthier's avatar
gauthier committed
384
    } else {
385
386
387
388
389
390
391
392
      // 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);
      }
gauthier's avatar
gauthier committed
393
394
395
396
    }
  }

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

398
  if ((err=ue_ip_netlink_init()) == -1) {
gauthier's avatar
gauthier committed
399
    printk("[UE_IP_DRV][%s] NETLINK failed\n", __FUNCTION__);
400
  }
gauthier's avatar
gauthier committed
401
402
403
404
405
406

  return err;

}

//---------------------------------------------------------------------------
407
408
409
410
void cleanup_module(void)
{
  //---------------------------------------------------------------------------
  int inst;
gauthier's avatar
gauthier committed
411

412
  printk("[UE_IP_DRV][CLEANUP] begin\n");
gauthier's avatar
gauthier committed
413

414
  for (inst=0; inst<UE_IP_NB_INSTANCES_MAX; inst++) {
gauthier's avatar
gauthier committed
415
#ifdef OAI_DRV_DEBUG_DEVICE
416
    printk("[UE_IP_DRV][CLEANUP]  unregister and free net device instance %d\n",inst);
gauthier's avatar
gauthier committed
417
#endif
418
419
420
421
422

    if (ue_ip_dev[inst]) {
      unregister_netdev(ue_ip_dev[inst]);
      ue_ip_teardown(ue_ip_dev[inst]);
      free_netdev(ue_ip_dev[inst]);
gauthier's avatar
gauthier committed
423
    }
424
425
426
  }

  ue_ip_netlink_release();
427
  printk("[UE_IP_DRV][CLEANUP] end\n");
gauthier's avatar
gauthier committed
428
429
430
431
432
433
434
435
436
}

#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