Files
openairinterface5g/openair2/NAS/DRIVER/CELLULAR/NASRG/nasrg_netlink.c
T
2015-04-10 13:18:11 +00:00

255 lines
8.2 KiB
C
Executable File

/***************************************************************************
nasrg_netlink.c - description
-------------------
***************************************************************************
Eurecom OpenAirInterface 2
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 450 route des Chappes, 06410 Biot Sophia Antipolis, France
*******************************************************************************/
/*! \file nasrg_netlink.c
* \brief Netlink socket functions for OpenAirInterface CELLULAR version - MT
* \author michelle.wetterwald, navid.nikaein, raymond.knopp, Lionel Gauthier
* \company Eurecom
* \email: michelle.wetterwald@eurecom.fr, raymond.knopp@eurecom.fr, navid.nikaein@eurecom.fr, lionel.gauthier@eurecom.fr
*/
/*******************************************************************************/
//#include <linux/config.h>
#include <linux/socket.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include "nasrg_variables.h"
#include "nasrg_proto.h"
static struct sock *nas_nl_sk = NULL;
static struct sock *nas_rrcnl_sk = NULL;
//static int exit_netlink_thread=0;
static DEFINE_MUTEX(nasrg_mutex);
// This can also be implemented using thread to get the data from PDCP without blocking.
//---------------------------------------------------------------------------
// Function for transfer with PDCP (from NASLITE)
static void nasrg_nl_data_ready (struct sk_buff *skb)
{
//---------------------------------------------------------------------------
struct nlmsghdr *nlh = NULL;
// Start debug information
#ifdef NETLINK_DEBUG
printk("nasrg_nl_data_ready - begin \n");
#endif
if (!skb) {
printk("nasrg_nl_data_ready - input parameter skb is NULL \n");
return;
}
// End debug information
#ifdef NETLINK_DEBUG
printk("nasrg_nl_data_ready - Received socket from PDCP\n");
#endif //NETLINK_DEBUG
nlh = (struct nlmsghdr *)skb->data;
nasrg_COMMON_QOS_receive(nlh);
}
//---------------------------------------------------------------------------
// Function for transfer with RRC
static void nasrg_rrcnl_data_ready (struct sk_buff *skb)
{
//---------------------------------------------------------------------------
struct nlmsghdr *nlh = NULL;
char target_sap;
uint8_t cxi;
// Start debug information
#ifdef NAS_DEBUG_RRCNL
printk("nasrg_rrcnl_data_ready - begin \n");
#endif
if (!skb) {
printk("nasrg_rrcnl_data_ready - input parameter skb is NULL \n");
return;
}
// End debug information
nlh = (struct nlmsghdr *)skb->data;
//pdcph = (struct pdcp_data_ind_header_t *)NLMSG_DATA(nlh);
//nasrg_TOOL_print_buffer((char *)NLMSG_DATA(nlh), 48);
target_sap = ((char*)NLMSG_DATA(nlh))[0];
#ifdef NAS_DEBUG_RRCNL
printk("nasrg_rrcnl_data_ready - Received on socket from RRC, SAP %d\n", target_sap);
#endif //NAS_DEBUG_RRCNL
switch (target_sap) {
case RRC_NAS_DC0_OUT:
//printk("nasrg_rrcnl_data_ready - Calling nasrg_ASCTL_DC_receive\n");
cxi = 0;
nasrg_ASCTL_DC_receive(gpriv->cx+cxi, &((char*)NLMSG_DATA(nlh))[1]);
break;
case RRC_NAS_DC1_OUT:
//printk("nasrg_rrcnl_data_ready - Calling nasrg_ASCTL_DC_receive\n");
cxi = 1;
nasrg_ASCTL_DC_receive(gpriv->cx+cxi, &((char*)NLMSG_DATA(nlh))[1]);
break;
case RRC_NAS_DC2_OUT:
//printk("nasrg_rrcnl_data_ready - Calling nasrg_ASCTL_DC_receive\n");
cxi = 2;
nasrg_ASCTL_DC_receive(gpriv->cx+cxi, &((char*)NLMSG_DATA(nlh))[1]);
break;
default:
printk("nasrg_rrcnl_data_ready - Invalid SAP value received\n");
}
}
//---------------------------------------------------------------------------
int nasrg_netlink_init(void)
{
//---------------------------------------------------------------------------
printk("nasrg_netlink_init - begin \n");
nas_nl_sk = netlink_kernel_create(&init_net,OAI_IP_DRIVER_NETLINK_ID, 0, nasrg_nl_data_ready,
&nasrg_mutex, // NULL
THIS_MODULE);
if (!nas_nl_sk) {
printk("nasrg_netlink_init - netlink_kernel_create failed for PDCP socket\n");
// TEMP printk("nasrg_netlink_init - netlink_kernel_create failed for PDCP socket %d\n", errno);
return(-1);
}
nas_rrcnl_sk = netlink_kernel_create(&init_net,NAS_RRCNL_ID, 0, nasrg_rrcnl_data_ready,
&nasrg_mutex, // NULL
THIS_MODULE);
if (!nas_rrcnl_sk) {
printk("nasrg_rrcnl_init - netlink_kernel_create failed for RRC socket\n");
return(-1);
}
return(0);
}
//---------------------------------------------------------------------------
void nasrg_netlink_release(void)
{
//---------------------------------------------------------------------------
printk("nasrg_netlink_release - begin \n");
//exit_netlink_thread=1;
printk("nasrg_netlink_release - Releasing netlink sockets\n");
if(nas_nl_sk) {
netlink_kernel_release(nas_nl_sk);
}
if(nas_rrcnl_sk) {
netlink_kernel_release(nas_rrcnl_sk);
}
}
//---------------------------------------------------------------------------
int nasrg_netlink_send(unsigned char *data_buffer, unsigned int data_length, int destination)
{
//---------------------------------------------------------------------------
struct sk_buff *nl_skb;
struct nlmsghdr *nlh;
int status;
// Start debug information
#ifdef NETLINK_DEBUG
printk("nasrg_netlink_send - begin \n");
#endif
if (!data_buffer) {
printk("nasrg_netlink_send - ERROR - input parameter data is NULL \n");
return(0);
}
if (!nas_nl_sk || !nas_rrcnl_sk) {
printk("nasrg_netlink_send - ERROR - socket is NULL\n");
return(0);
}
// End debug information
nl_skb = alloc_skb(NLMSG_SPACE(data_length),GFP_ATOMIC);
if (!nl_skb) {
printk("nasrg_netlink_send - ERROR - could not allocate skbuffer\n");
return(0);
}
nlh = (struct nlmsghdr *)nl_skb->data;
// printk("nasrg_netlink_send Sending %d bytes (%d)\n",data_length,NLMSG_SPACE(data_length));
skb_put(nl_skb, NLMSG_SPACE(data_length));
memcpy(NLMSG_DATA(nlh), data_buffer, data_length);
nlh->nlmsg_len = NLMSG_SPACE(data_length);
nlh->nlmsg_pid = 0; /* from kernel */
NETLINK_CB(nl_skb).pid = 0;
// destination 0 = PDCP, 1 = RRC
if (destination== NASNL_DEST_PDCP) {
#ifdef NETLINK_DEBUG
printk("nasrg_netlink_send - Sending to PDCP - nl_skb %p, nl_sk %p, nlh %p, nlh->nlmsg_len %d\n", nl_skb, nas_nl_sk, nlh, nlh->nlmsg_len);
#ifdef NAS_DEBUG_SEND_DETAIL
nasrg_TOOL_print_buffer(NLMSG_DATA(nlh),48);
#endif
#endif //DEBUG_NETLINK
status = netlink_unicast(nas_nl_sk, nl_skb, NL_DEST_PID, MSG_DONTWAIT);
} else {
#ifdef NAS_DEBUG_RRCNL
printk("nasrg_netlink_send - Sending to RRC - nl_skb %p, nas_rrcnl_sk %p, nlh %p, nlh->nlmsg_len %d\n", nl_skb, nas_rrcnl_sk, nlh, nlh->nlmsg_len);
nasrg_TOOL_print_buffer(NLMSG_DATA(nlh),data_length);
#endif //NAS_DEBUG_RRCNL
status = netlink_unicast(nas_rrcnl_sk, nl_skb, NL_DEST_RRC_PID, MSG_DONTWAIT);
}
if (status < 0) {
printk("nasrg_netlink_send - SEND status is %d\n",status);
return(0);
} else {
#ifdef NETLINK_DEBUG
printk("nasrg_netlink_send - SEND status is %d, data_length %d\n",status, data_length);
#endif
return data_length;
}
}