/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface is distributed in the hope that 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 OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see . Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ /*! \file device.c * \brief Networking Device Driver for OpenAirInterface * \author navid nikaein, Lionel Gauthier, raymond knopp * \company Eurecom * \email: raymond.knopp@eurecom.fr, navid.nikaein@eurecom.fr, lionel.gauthier@eurecom.fr */ /*******************************************************************************/ #ifndef OAI_NW_DRIVER_USE_NETLINK #ifdef RTAI #include "rtai_posix.h" #define RTAI_IRQ 30 //try to get this irq with RTAI #endif // RTAI #endif // OAI_NW_DRIVER_USE_NETLINK #include "constant.h" #include "local.h" #include "proto_extern.h" #include #include #include #include #include #include #include #include #include #include #include #include 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 //--------------------------------------------------------------------------- int ue_ip_find_inst(struct net_device *dev_pP) { //--------------------------------------------------------------------------- int i; for (i=0;ilock = SPIN_LOCK_UNLOCKED; #ifdef OAI_DRV_DEBUG_INTERRUPT printk("INTERRUPT - begin\n"); #endif // spin_lock_irqsave(&priv_p->lock,flags); cxi=0; // mesh_GC_receive(); // mesh_DC_receive(naspriv->cx+cxi); #ifndef OAI_NW_DRIVER_USE_NETLINK ue_ip_common_wireless2ip(); #endif // spin_unlock_irqrestore(&priv_p->lock,flags); #ifdef OAI_DRV_DEBUG_INTERRUPT printk("INTERRUPT: end\n"); #endif // return 0; } #endif //NETLINK //--------------------------------------------------------------------------- void ue_ip_timer(unsigned long dataP){ //--------------------------------------------------------------------------- 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); return; // add_timer(&gpriv->timer); // spin_unlock(&gpriv->lock); } //--------------------------------------------------------------------------- // Called by ifconfig when the device is activated by ifconfig int ue_ip_open(struct net_device *dev_pP){ //--------------------------------------------------------------------------- ue_ip_priv_t *priv_p=netdev_priv(dev_pP); // Address has already been set at init #ifndef OAI_NW_DRIVER_USE_NETLINK if (pdcp_2_ue_ip_irq==-EBUSY){ printk("[UE_IP_DRV][%s] : irq failure\n", __FUNCTION__); return -EBUSY; } #endif //OAI_NW_DRIVER_USE_NETLINK if(!netif_queue_stopped(dev_pP)) netif_start_queue(dev_pP); else netif_wake_queue(dev_pP); 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); printk("[UE_IP_DRV][%s] name = %s\n", __FUNCTION__, dev_pP->name); return 0; } //--------------------------------------------------------------------------- // Called by ifconfig when the device is desactivated int ue_ip_stop(struct net_device *dev_pP){ //--------------------------------------------------------------------------- ue_ip_priv_t *priv_p = netdev_priv(dev_pP); printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__); del_timer(&(priv_p->timer)); netif_stop_queue(dev_pP); // MOD_DEC_USE_COUNT; printk("[UE_IP_DRV][%s] End\n", __FUNCTION__); return 0; } //--------------------------------------------------------------------------- void ue_ip_teardown(struct net_device *dev_pP){ //--------------------------------------------------------------------------- ue_ip_priv_t *priv_p; int inst; printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__); if (dev_pP) { priv_p = netdev_priv(dev_pP); inst = ue_ip_find_inst(dev_pP); if ((inst<0) || (inst>=UE_IP_NB_INSTANCES_MAX)) { printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__); return; } printk("[UE_IP_DRV][%s] End\n", __FUNCTION__); } // check dev_pP else { printk("[UE_IP_DRV][%s] Device is null\n", __FUNCTION__); } } //--------------------------------------------------------------------------- int ue_ip_set_config(struct net_device *dev_pP, struct ifmap *map_pP){ //--------------------------------------------------------------------------- printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__); if (dev_pP->flags & IFF_UP) return -EBUSY; if (map_pP->base_addr != dev_pP->base_addr) { printk(KERN_WARNING "[UE_IP_DRV][%s] Can't change I/O address\n", __FUNCTION__); return -EOPNOTSUPP; } if (map_pP->irq != dev_pP->irq) dev_pP->irq = map_pP->irq; printk("[UE_IP_DRV][%s] End\n", __FUNCTION__); return 0; } //--------------------------------------------------------------------------- // int ue_ip_hard_start_xmit(struct sk_buff *skb_pP, struct net_device *dev_pP){ //--------------------------------------------------------------------------- int inst; if (dev_pP) { inst = ue_ip_find_inst(dev_pP); } else { printk("[UE_IP_DRV][%s] ERROR, device is null\n", __FUNCTION__); return -1; } if ((inst>=0) && (insttrans_start = jiffies; #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 } else { printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__); return(-1); } return 0; } //--------------------------------------------------------------------------- struct net_device_stats *ue_ip_get_stats(struct net_device *dev_pP){ //--------------------------------------------------------------------------- ue_ip_priv_t *priv_p = netdev_priv(dev_pP); return &priv_p->stats; } //--------------------------------------------------------------------------- int ue_ip_set_mac_address(struct net_device *dev_pP, void *mac_pP) { //--------------------------------------------------------------------------- //struct sockaddr *addr = mac_pP; printk("[UE_IP_DRV][%s] CHANGE MAC ADDRESS UNSUPPORTED\n", __FUNCTION__); //memcpy(dev_pP->dev_addr, addr->sa_data, dev_pP->addr_len); return 0; } //--------------------------------------------------------------------------- int ue_ip_change_mtu(struct net_device *dev_pP, int mtuP){ //--------------------------------------------------------------------------- printk("[UE_IP_DRV][%s] CHANGE MTU %d bytes\n", __FUNCTION__, mtuP); if ((mtuP<50) || (mtuP>1500)) return -EINVAL; dev_pP->mtu = mtuP; return 0; } //--------------------------------------------------------------------------- void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP){ //--------------------------------------------------------------------------- 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; } //--------------------------------------------------------------------------- void ue_ip_tx_timeout(struct net_device *dev_pP){ //--------------------------------------------------------------------------- // Transmitter timeout, serious problems. ue_ip_priv_t *priv_p = netdev_priv(dev_pP); printk("[UE_IP_DRV][%s] begin\n", __FUNCTION__); // (ue_ip_priv_t *)(dev_pP->priv_p)->stats.tx_errors++; (priv_p->stats).tx_errors++; dev_pP->trans_start = jiffies; netif_wake_queue(dev_pP); printk("[UE_IP_DRV][%s] transmit timed out %s\n", __FUNCTION__,dev_pP->name); } static const struct net_device_ops ue_ip_netdev_ops = { .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, }; /*.ndo_set_multicast_list = NULL,*/ //--------------------------------------------------------------------------- // Initialisation of the network device void ue_ip_init(struct net_device *dev_pP){ //--------------------------------------------------------------------------- ue_ip_priv_t *priv_p = NULL; if (dev_pP) { priv_p = netdev_priv(dev_pP); memset(priv_p, 0, sizeof(ue_ip_priv_t)); spin_lock_init(&priv_p->lock); #ifdef KERNEL_VERSION_GREATER_THAN_2629 dev_pP->netdev_ops = &ue_ip_netdev_ops; #else #error "KERNEL VERSION MUST BE NEWER THAN 2.6.29" #endif 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; } } //--------------------------------------------------------------------------- int init_module (void) { //--------------------------------------------------------------------------- int err,inst; char devicename[100]; // Initialize parameters shared with RRC printk("[UE_IP_DRV][%s] Starting OAI IP driver", __FUNCTION__); for (inst=0;instname); }else{ printk("[UE_IP_DRV][%s] registering device %s, ifindex = %d\n\n", __FUNCTION__,ue_ip_dev[inst]->name, ue_ip_dev[inst]->ifindex); } } } printk("[UE_IP_DRV][%s] NETLINK INIT\n", __FUNCTION__); if ((err=ue_ip_netlink_init()) == -1) printk("[UE_IP_DRV][%s] NETLINK failed\n", __FUNCTION__); return err; } //--------------------------------------------------------------------------- void cleanup_module(void){ //--------------------------------------------------------------------------- int inst; printk("[UE_IP_DRV][CLEANUP]nasmesh_cleanup_module: begin\n"); for (inst=0;inst"DRV_COPYRIGHT