Cleaned some PDCP/driver code types parameters and vars Please see openair2/COMMON/platform_types.h for simple coding rules. please declare prototypes of functions in .h and include .h files in where the function is used and where it is implemented. git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5096 818b1a75-f10b-46b9-bf7c-635c3b92a50f
1017 lines
38 KiB
C
Executable File
1017 lines
38 KiB
C
Executable File
/***************************************************************************
|
|
nasrg_classifier.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_classifier.c
|
|
* \brief Flow classification functions for OpenAirInterface CELLULAR version - RG
|
|
* \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 "nasrg_variables.h"
|
|
#include "nasrg_proto.h"
|
|
|
|
#include <net/ip6_fib.h>
|
|
#include <net/route.h>
|
|
|
|
#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0)
|
|
#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000)
|
|
#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000)
|
|
#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
|
|
|
|
/* Address to accept any incoming messages. */
|
|
#define INADDR_ANY ((unsigned long int) 0x00000000)
|
|
|
|
#define NIPADDR(addr) \
|
|
(uint8_t)(addr & 0x000000FF), \
|
|
(uint8_t)((addr & 0x0000FF00) >> 8), \
|
|
(uint8_t)((addr & 0x00FF0000) >> 16), \
|
|
(uint8_t)((addr & 0xFF000000) >> 24)
|
|
|
|
#define NIP6ADDR(addr) \
|
|
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])
|
|
|
|
|
|
#define IN6_IS_ADDR_UNSPECIFIED(a) \
|
|
(((__const uint32_t *) (a))[0] == 0 \
|
|
&& ((__const uint32_t *) (a))[1] == 0 \
|
|
&& ((__const uint32_t *) (a))[2] == 0 \
|
|
&& ((__const uint32_t *) (a))[3] == 0)
|
|
|
|
#define IN6_ARE_ADDR_MASKED_EQUAL(a,b,m) \
|
|
(((((__const uint32_t *) (a))[0] & (((__const uint32_t *) (m))[0])) == (((__const uint32_t *) (b))[0] & (((__const uint32_t *) (m))[0]))) \
|
|
&& ((((__const uint32_t *) (a))[1] & (((__const uint32_t *) (m))[1])) == (((__const uint32_t *) (b))[1] & (((__const uint32_t *) (m))[1]))) \
|
|
&& ((((__const uint32_t *) (a))[2] & (((__const uint32_t *) (m))[2])) == (((__const uint32_t *) (b))[2] & (((__const uint32_t *) (m))[2]))) \
|
|
&& ((((__const uint32_t *) (a))[3] & (((__const uint32_t *) (m))[3])) == (((__const uint32_t *) (b))[3] & (((__const uint32_t *) (m))[3]))))
|
|
|
|
#define IN_ARE_ADDR_MASKED_EQUAL(a,b,m) \
|
|
(((((__const uint8_t *) (a))[0] & (((__const uint8_t *) (m))[0])) == (((__const uint8_t *) (b))[0] & (((__const uint8_t *) (m))[0]))) \
|
|
&& ((((__const uint8_t *) (a))[1] & (((__const uint8_t *) (m))[1])) == (((__const uint8_t *) (b))[1] & (((__const uint8_t *) (m))[1]))) \
|
|
&& ((((__const uint8_t *) (a))[2] & (((__const uint8_t *) (m))[2])) == (((__const uint8_t *) (b))[2] & (((__const uint8_t *) (m))[2]))) \
|
|
&& ((((__const uint8_t *) (a))[3] & (((__const uint8_t *) (m))[3])) == (((__const uint8_t *) (b))[3] & (((__const uint8_t *) (m))[3]))))
|
|
|
|
//---------------------------------------------------------------------------
|
|
void nasrg_create_mask_ipv6_addr(struct in6_addr *masked_addrP, int prefix_len){
|
|
//---------------------------------------------------------------------------
|
|
int u6_addr8_index;
|
|
int u6_addr1_index;
|
|
int index;
|
|
|
|
masked_addrP->s6_addr32[0] = 0xFFFFFFFF;
|
|
masked_addrP->s6_addr32[1] = 0xFFFFFFFF;
|
|
masked_addrP->s6_addr32[2] = 0xFFFFFFFF;
|
|
masked_addrP->s6_addr32[3] = 0xFFFFFFFF;
|
|
|
|
u6_addr8_index = prefix_len >> 3;
|
|
u6_addr1_index = prefix_len & 0x07;
|
|
|
|
for (index = u6_addr8_index + 1; index < 16; index++) {
|
|
masked_addrP->s6_addr[index] = 0;
|
|
}
|
|
if (u6_addr1_index > 0) {
|
|
masked_addrP->s6_addr[u6_addr8_index] = 0xFF << (8-u6_addr1_index);
|
|
}
|
|
#ifdef NAS_DEBUG_CLASS
|
|
//printk("nasrg_create_mask_ipv6_addr: MASK = %X:%X:%X:%X:%X:%X:%X:%X\n",NIP6ADDR(masked_addrP));
|
|
#endif
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void nasrg_create_mask_ipv4_addr(struct in_addr *masked_addrP, int prefix_len){
|
|
//---------------------------------------------------------------------------
|
|
if (prefix_len > 32) {
|
|
prefix_len = 32;
|
|
}
|
|
masked_addrP->s_addr = 0xFFFFFFFF << (32 - prefix_len);
|
|
#ifdef NAS_DEBUG_CLASS
|
|
//printk("nasrg_create_mask_ipv4_addr: MASK = %d.%d.%d.%d\n",NIPADDR(masked_addrP));
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Add a new classifier rule (send direction)
|
|
struct classifier_entity *nasrg_CLASS_add_sclassifier(struct cx_entity *cx, uint8_t dscp, uint16_t classref){
|
|
//---------------------------------------------------------------------------
|
|
struct classifier_entity *gc;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_sclassifier: begin for dscp %d, classref %d\n", dscp,classref);
|
|
#endif
|
|
if (cx==NULL){
|
|
printk("nasrg_CLASS_add_sclassifier - input parameter cx is NULL \n");
|
|
return NULL;
|
|
}
|
|
//***
|
|
for (gc=cx->sclassifier[dscp]; gc!=NULL; gc=gc->next){
|
|
if (gc->classref==classref){
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_sclassifier: classifier already exist for dscp %d, classref %d\n",dscp,classref);
|
|
#endif
|
|
return gc;
|
|
}
|
|
}
|
|
gc=(struct classifier_entity *)kmalloc(sizeof(struct classifier_entity), GFP_ATOMIC);
|
|
if (gc==NULL)
|
|
return NULL;
|
|
memset(gc, 0, sizeof(struct classifier_entity));
|
|
gc->next=cx->sclassifier[dscp];
|
|
gc->classref=classref;
|
|
cx->sclassifier[dscp]=gc;
|
|
++cx->nsclassifier;
|
|
++gpriv->next_sclassref; //increment send classref index - MW 15/01/07
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_sclassifier: classifier created for dscp %d, classref %d\n",dscp,classref);
|
|
#endif
|
|
return gc;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Add a new classifier rule (receive direction)
|
|
struct classifier_entity *nasrg_CLASS_add_rclassifier(uint8_t dscp, uint16_t classref){
|
|
//---------------------------------------------------------------------------
|
|
struct classifier_entity *gc;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_rclassifier: begin\n");
|
|
#endif
|
|
//***
|
|
for (gc=gpriv->rclassifier[dscp]; gc!=NULL; gc=gc->next)
|
|
{
|
|
if (gc->classref==classref){
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_rclassifier: classifier already exist for dscp %d, classref %d\n",dscp,classref);
|
|
#endif
|
|
return gc;
|
|
}
|
|
}
|
|
gc=(struct classifier_entity *)kmalloc(sizeof(struct classifier_entity), GFP_KERNEL);
|
|
if (gc==NULL)
|
|
return NULL;
|
|
gc->next=gpriv->rclassifier[dscp];
|
|
gc->classref=classref;
|
|
gpriv->rclassifier[dscp]=gc;
|
|
++gpriv->nrclassifier;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_rclassifier: classifier created for dscp %d, classref %d\n",dscp,classref);
|
|
#endif
|
|
return gc;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Add a new classifier rule (mbms direction)
|
|
struct classifier_entity *nasrg_CLASS_add_mbmsclassifier(int mbms_ix, uint16_t classref){
|
|
//---------------------------------------------------------------------------
|
|
struct classifier_entity *gc;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_mbmsclassifier: begin\n");
|
|
#endif
|
|
//***
|
|
for (gc=gpriv->mbmsclassifier[mbms_ix]; gc!=NULL; gc=gc->next)
|
|
{
|
|
if (gc->classref==classref){
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_mbmsclassifier: classifier already exist for service %d, classref %d\n",mbms_ix,classref);
|
|
#endif
|
|
return gc;
|
|
}
|
|
}
|
|
gc=(struct classifier_entity *)kmalloc(sizeof(struct classifier_entity), GFP_ATOMIC);
|
|
if (gc==NULL)
|
|
return NULL;
|
|
gc->next=gpriv->mbmsclassifier[mbms_ix];
|
|
gc->classref=classref;
|
|
gpriv->mbmsclassifier[mbms_ix]=gc;
|
|
++gpriv->nmbmsclassifier;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_add_mbmsclassifier: classifier created for service index %d, classref %d\n",mbms_ix,classref);
|
|
#endif
|
|
return gc;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void nasrg_CLASS_flush_sclassifier(struct cx_entity *cx){
|
|
//---------------------------------------------------------------------------
|
|
uint8_t dscpi;
|
|
struct classifier_entity *gc;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_flush_sclassifier: begin\n");
|
|
#endif
|
|
if (cx==NULL){
|
|
printk("nasrg_CLASS_flush_sclassifier - input parameter cx is NULL \n");
|
|
return;
|
|
}
|
|
//***
|
|
for (dscpi=0; dscpi<NAS_DSCP_MAX; ++dscpi){
|
|
for (gc=cx->sclassifier[dscpi]; gc!=NULL; gc=cx->sclassifier[dscpi]){
|
|
cx->sclassifier[dscpi]=gc->next;
|
|
kfree(gc);
|
|
}
|
|
}
|
|
cx->nsclassifier=0;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_flush_sclassifier: end\n");
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void nasrg_CLASS_flush_rclassifier(){
|
|
//---------------------------------------------------------------------------
|
|
uint8_t dscpi;
|
|
struct classifier_entity *gc;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_flush_rclassifier: begin\n");
|
|
#endif
|
|
//***
|
|
for (dscpi=0; dscpi<NAS_DSCP_MAX; ++dscpi){
|
|
for (gc=gpriv->rclassifier[dscpi]; gc!=NULL; gc=gpriv->rclassifier[dscpi]){
|
|
gpriv->rclassifier[dscpi]=gc->next;
|
|
kfree(gc);
|
|
}
|
|
}
|
|
gpriv->nrclassifier=0;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_flush_rclassifier: end\n");
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void nasrg_CLASS_flush_mbmsclassifier(){
|
|
//---------------------------------------------------------------------------
|
|
int mbmsi;
|
|
struct classifier_entity *gc;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_flush_mbmsclassifier: begin\n");
|
|
#endif
|
|
//***
|
|
for (mbmsi=0; mbmsi<NASRG_MBMS_SVCES_MAX; ++mbmsi){
|
|
for (gc=gpriv->mbmsclassifier[mbmsi]; gc!=NULL; gc=gpriv->mbmsclassifier[mbmsi]){
|
|
gpriv->mbmsclassifier[mbmsi]=gc->next;
|
|
kfree(gc);
|
|
}
|
|
}
|
|
gpriv->nmbmsclassifier=0;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_flush_mbmsclassifier: end\n");
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Delete a classifier rule (send direction)
|
|
void nasrg_CLASS_del_sclassifier(struct cx_entity *cx, uint8_t dscp, uint16_t classref){
|
|
//---------------------------------------------------------------------------
|
|
struct classifier_entity *p,*np;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_del_sclassifier: begin\n");
|
|
#endif
|
|
if (cx==NULL){
|
|
printk("nasrg_CLASS_del_sclassifier - input parameter cx is NULL \n");
|
|
return;
|
|
}
|
|
//***
|
|
p=cx->sclassifier[dscp];
|
|
if (p==NULL)
|
|
return;
|
|
if (p->classref==classref){
|
|
cx->sclassifier[dscp]=p->next;
|
|
kfree(p);
|
|
--cx->nsclassifier;
|
|
return;
|
|
}
|
|
for (np=p->next; np!=NULL; p=np){
|
|
if (np->classref==classref){
|
|
p->next=np->next;
|
|
kfree(np);
|
|
--cx->nsclassifier;
|
|
return;
|
|
}
|
|
}
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_del_sclassifier: end\n");
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Delete a classifier rule (receive direction)
|
|
void nasrg_CLASS_del_rclassifier(uint8_t dscp, uint16_t classref){
|
|
//---------------------------------------------------------------------------
|
|
struct classifier_entity *p,*np;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_del_rclassifier: begin\n");
|
|
#endif
|
|
//***
|
|
p=gpriv->rclassifier[dscp];
|
|
if (p==NULL)
|
|
return;
|
|
if (p->classref==classref){
|
|
gpriv->rclassifier[dscp]=p->next;
|
|
kfree(p);
|
|
--gpriv->nrclassifier;
|
|
return;
|
|
}
|
|
for (np=p->next; np!=NULL; p=np){
|
|
if (np->classref==classref){
|
|
p->next=np->next;
|
|
kfree(np);
|
|
--gpriv->nrclassifier;
|
|
return;
|
|
}
|
|
}
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_del_rclassifier: end\n");
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Delete a classifier rule (mbms direction)
|
|
void nasrg_CLASS_del_mbmsclassifier(int mbms_ix, uint16_t classref){
|
|
//---------------------------------------------------------------------------
|
|
struct classifier_entity *p,*np;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_del_mbmsclassifier: begin\n");
|
|
#endif
|
|
//***
|
|
p=gpriv->mbmsclassifier[mbms_ix];
|
|
if (p==NULL)
|
|
return;
|
|
if (p->classref==classref){
|
|
gpriv->mbmsclassifier[mbms_ix]=p->next;
|
|
kfree(p);
|
|
--gpriv->nmbmsclassifier;
|
|
return;
|
|
}
|
|
for (np=p->next; np!=NULL; p=np){
|
|
if (np->classref==classref){
|
|
p->next=np->next;
|
|
kfree(np);
|
|
--gpriv->nmbmsclassifier;
|
|
return;
|
|
}
|
|
}
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_del_mbmsclassifier: end\n");
|
|
#endif
|
|
}
|
|
|
|
/* ORIGINAL VERSION
|
|
//---------------------------------------------------------------------------
|
|
// Search the entity with the IPv4 address 'addr'
|
|
struct cx_entity *nasrg_CLASS_cx4(struct sk_buff *skb){
|
|
//---------------------------------------------------------------------------
|
|
uint8_t cxi;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx4: begin\n");
|
|
#endif
|
|
cxi=0;
|
|
return gpriv->cx+cxi;
|
|
//#endif
|
|
}*/
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Search the entity with the IPv4 address 'addr'
|
|
struct cx_entity *nasrg_CLASS_cx4(struct sk_buff *skb, unsigned char dscp, int *paddr_type, unsigned char *cx_index) {
|
|
//---------------------------------------------------------------------------
|
|
unsigned char cxi;
|
|
uint32_t daddr;
|
|
struct cx_entity *cx=NULL;
|
|
struct classifier_entity *pclassifier=NULL;
|
|
struct in_addr masked_addr;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx4: begin\n");
|
|
#endif
|
|
if (skb!=NULL) {
|
|
daddr = ((struct iphdr*)(skb_network_header(skb)))->daddr;
|
|
if (daddr != INADDR_ANY) {
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("SOURCE ADDR %d.%d.%d.%d",NIPADDR(ip_hdr(skb)->saddr));
|
|
printk(" DEST ADDR %d.%d.%d.%d\n",NIPADDR(ip_hdr(skb)->daddr));
|
|
#endif
|
|
if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
|
|
// TO BE CHECKED
|
|
*paddr_type = NAS_IPV4_ADDR_MC_SIGNALLING;
|
|
} else {
|
|
if (ipv4_is_lbcast(ip_hdr(skb)->daddr)) {
|
|
// TO BE CHECKED
|
|
*paddr_type = NAS_IPV4_ADDR_BROADCAST;
|
|
} else {
|
|
if (IN_CLASSA(ip_hdr(skb)->daddr) || IN_CLASSB(ip_hdr(skb)->daddr) || IN_CLASSC(ip_hdr(skb)->daddr)) {
|
|
*paddr_type = NAS_IPV4_ADDR_UNICAST;
|
|
for (cxi=*cx_index; cxi<NAS_CX_MAX; ++cxi) {
|
|
(*cx_index)++;
|
|
pclassifier = gpriv->cx[cxi].sclassifier[dscp];
|
|
while (pclassifier!=NULL) {
|
|
// verify that this is an IPv4 classifier
|
|
if ((pclassifier->version == NAS_VERSION_4) || (pclassifier->version == NAS_VERSION_DEFAULT)) {
|
|
nasrg_create_mask_ipv4_addr(&masked_addr, pclassifier->dplen);
|
|
if (IN_ARE_ADDR_MASKED_EQUAL(&ip_hdr(skb)->daddr, &(pclassifier->daddr.ipv4), &masked_addr)) {
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx4: IP MASK MATCHED: found cx %d: %d.%d.%d.%d/%d\n",cxi, NIPADDR(pclassifier->daddr.ipv4), pclassifier->dplen);
|
|
#endif
|
|
return &gpriv->cx[cxi];
|
|
}
|
|
}
|
|
// goto to next classification rule for the connection
|
|
pclassifier = pclassifier->next;
|
|
}
|
|
}
|
|
} else {
|
|
*paddr_type = NAS_IPV4_ADDR_UNKNOWN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return cx;
|
|
}
|
|
|
|
/* ORIGINAL VERSION
|
|
//---------------------------------------------------------------------------
|
|
// Search the entity corresponding to destination address in IPv6 header
|
|
struct cx_entity *nasrg_CLASS_cx6(struct sk_buff *skb, int* paddr_type, int* pmbms_ix){
|
|
//---------------------------------------------------------------------------
|
|
struct cx_entity * cx=NULL;
|
|
uint8_t cxi;
|
|
uint32_t mc_addr_hdr, uni_ifid1, uni_ifid2;
|
|
//int addr_type = NASRG_ADDR_UNKNOWN;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: begin\n");
|
|
#endif
|
|
if (!skb){
|
|
printk("nasrg_CLASS_cx6 - input parameter skb is NULL \n");
|
|
return cx;
|
|
}
|
|
*paddr_type = NASRG_ADDR_UNKNOWN;
|
|
//mc_addr_hdr = ntohl(skb->nh.ipv6h->daddr.in6_u.u6_addr32[0]);
|
|
mc_addr_hdr = ntohl(ipv6_hdr(skb)->daddr.in6_u.u6_addr32[0]);
|
|
// First check if multicast [1st octet is FF]
|
|
if ((mc_addr_hdr & 0xFF000000) == 0xFF000000) {
|
|
// packet type according to the scope of the multicast packet
|
|
// we don't consider RPT bits in second octet [maybe done later if needed]
|
|
switch(mc_addr_hdr & 0x000F0000) {
|
|
case (0x00020000):
|
|
*paddr_type = NASRG_ADDR_MC_SIGNALLING;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: multicast packet - signalling \n");
|
|
#endif
|
|
break;
|
|
case (0x000E0000):
|
|
*paddr_type = NASRG_ADDR_MC_MBMS;
|
|
*pmbms_ix = 0;
|
|
cx=gpriv->cx; // MBMS associate to Mobile 0
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: multicast packet - MBMS data \n");
|
|
#endif
|
|
break;
|
|
default:
|
|
*paddr_type = NASRG_ADDR_UNKNOWN;
|
|
*pmbms_ix = NASRG_MBMS_SVCES_MAX;
|
|
}
|
|
// This is not multicast, so we should be able to identify the MT
|
|
}else{
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: unicast packet\n");
|
|
#endif
|
|
*paddr_type = NASRG_ADDR_UNICAST;
|
|
uni_ifid1 = ntohl(ipv6_hdr(skb)->daddr.in6_u.u6_addr32[2]);
|
|
uni_ifid2 = ntohl(ipv6_hdr(skb)->daddr.in6_u.u6_addr32[3]);
|
|
for (cxi=0; cxi<NAS_CX_MAX; cxi++){
|
|
cx=gpriv->cx+cxi;
|
|
#ifdef NAS_DEBUG_SEND_DETAIL
|
|
printk("nasrg_CLASS_cx6: Compared addresses \n");
|
|
printk(" Daddr[2] %ul, Daddr[3] %ul\n",
|
|
ipv6_hdr(skb)->daddr.in6_u.u6_addr32[2],ipv6_hdr(skb)->daddr.in6_u.u6_addr32[3]);
|
|
printk(" ntohl Daddr[2] %ul, Daddr[3] %ul\n",uni_ifid1,uni_ifid2);
|
|
printk(" IIF[0] %ul, IIF[1] %ul\n",cx->iid6[0],cx->iid6[1]);
|
|
printk(" htonl IIF[0] %ul, IIF[1] %ul\n",htonl(cx->iid6[0]),htonl(cx->iid6[1]));
|
|
#endif
|
|
if (((cx->iid6[0] == uni_ifid1)&&(cx->iid6[1] == uni_ifid2))
|
|
|| ((htonl(cx->iid6[0]) == uni_ifid1)&&(htonl(cx->iid6[1]) == uni_ifid2))){
|
|
return cx;
|
|
}
|
|
}
|
|
}
|
|
return cx;
|
|
}*/
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Search the entity with the IPv6 address 'addr'
|
|
// Navid: the ipv6 classifier is not fully tested
|
|
struct cx_entity *nasrg_CLASS_cx6(struct sk_buff *skb, unsigned char dscp, int *paddr_type, unsigned char *cx_index, int* pmbms_ix) {
|
|
//---------------------------------------------------------------------------
|
|
uint8_t cxi;
|
|
struct cx_entity *cx = NULL;
|
|
struct classifier_entity *sclassifier= NULL;
|
|
uint32_t mc_addr_hdr;
|
|
struct in6_addr masked_addr;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: begin\n");
|
|
#endif
|
|
if (skb) {
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: SOURCE ADDR %X:%X:%X:%X:%X:%X:%X:%X",NIP6ADDR(&(ipv6_hdr(skb)->saddr)));
|
|
printk(" DEST ADDR %X:%X:%X:%X:%X:%X:%X:%X\n",NIP6ADDR(&(ipv6_hdr(skb)->daddr)));
|
|
#endif
|
|
mc_addr_hdr = ntohl(ipv6_hdr(skb)->daddr.in6_u.u6_addr32[0]);
|
|
// First check if multicast [1st octet is FF]
|
|
if ((mc_addr_hdr & 0xFF000000) == 0xFF000000) {
|
|
// packet type according to the scope of the multicast packet
|
|
// we don't consider RPT bits in second octet [maybe done later if needed]
|
|
switch(mc_addr_hdr & 0x000F0000) {
|
|
case (0x00020000):
|
|
*paddr_type = NAS_IPV6_ADDR_MC_SIGNALLING;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: multicast packet - signalling \n");
|
|
#endif
|
|
break;
|
|
case (0x000E0000):
|
|
*paddr_type = NAS_IPV6_ADDR_MC_MBMS;
|
|
*pmbms_ix = 0;
|
|
cx=gpriv->cx; // MBMS associate to Mobile 0
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: multicast packet - MBMS data \n");
|
|
#endif
|
|
break;
|
|
default:
|
|
printk("nasrg_CLASS_cx6: default multicast\n");
|
|
*paddr_type = NAS_IPV6_ADDR_UNKNOWN;
|
|
*pmbms_ix = NASRG_MBMS_SVCES_MAX;
|
|
}
|
|
} else {
|
|
// This is not multicast, so we should be able to identify the MT
|
|
*paddr_type = NAS_IPV6_ADDR_UNICAST;
|
|
for (cxi=*cx_index; cxi<NAS_CX_MAX; cxi++) {
|
|
//cxi = 0;
|
|
(*cx_index)++;
|
|
sclassifier = gpriv->cx[cxi].sclassifier[dscp];
|
|
|
|
while (sclassifier!=NULL) {
|
|
// verify that this is an IPv6 classifier
|
|
if ((sclassifier->version == NAS_VERSION_6) || (sclassifier->version == NAS_VERSION_DEFAULT)) {
|
|
/*LGif (IN6_IS_ADDR_UNSPECIFIED(&(sclassifier->daddr.ipv6))) {
|
|
printk("nas_CLASS_cx6: addr is null \n");
|
|
sclassifier = sclassifier->next;
|
|
continue;
|
|
}*/
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("cx %d : DSCP %d %X:%X:%X:%X:%X:%X:%X:%X\n",cxi, dscp, NIP6ADDR(&(sclassifier->daddr.ipv6)));
|
|
#endif //NAS_DEBUG_CLASS
|
|
//if ((dst = (unsigned int*)&(((struct rt6_info *)skbdst)->rt6i_gateway)) == 0){
|
|
// LG: STRANGE
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&ipv6_hdr(skb)->daddr)) {
|
|
printk("nasrg_CLASS_cx6: dst addr is null \n");
|
|
sclassifier = sclassifier->next;
|
|
continue;
|
|
}
|
|
nasrg_create_mask_ipv6_addr(&masked_addr, sclassifier->dplen);
|
|
// Modified MW to check only the iid6
|
|
masked_addr.s6_addr32[0] = 0x00000000;
|
|
masked_addr.s6_addr32[1] = 0x00000000;
|
|
|
|
if (IN6_ARE_ADDR_MASKED_EQUAL(&ipv6_hdr(skb)->daddr, &(sclassifier->daddr.ipv6), &masked_addr)) {
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_cx6: found cx %d: %X:%X:%X:%X:%X:%X:%X:%X\n",cxi, NIP6ADDR(&(sclassifier->daddr.ipv6)));
|
|
#endif //NAS_DEBUG_CLASS
|
|
return &gpriv->cx[cxi];
|
|
}
|
|
}
|
|
// Go to next classifier entry for connection
|
|
sclassifier = sclassifier->next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//printk("nas_CLASS_cx6 NOT FOUND: %X:%X:%X:%X:%X:%X:%X:%X\n",NIP6ADDR(&ipv6_hdr(skb)->daddr));
|
|
return cx;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Search the sending function for IP Packet
|
|
void nasrg_CLASS_send(struct sk_buff *skb){
|
|
//---------------------------------------------------------------------------
|
|
struct classifier_entity *pclassifier, *sp;
|
|
uint8_t *protocolh = NULL;
|
|
uint8_t version;
|
|
uint8_t protocol, dscp;
|
|
uint16_t classref;
|
|
struct cx_entity *cx;
|
|
unsigned int i;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
char sfct[10], sprotocol[10];
|
|
#endif
|
|
struct net_device *dev = gdev;
|
|
unsigned char cx_index,no_connection;
|
|
int addr_type;
|
|
int mbms_ix;
|
|
struct in6_addr masked6_addr;
|
|
struct in_addr masked_addr;
|
|
// RARP vars
|
|
struct arphdr *rarp;
|
|
unsigned char *rarp_ptr;
|
|
/* s for "source", t for "target" */
|
|
__be32 sip, tip;
|
|
unsigned char *sha, *tha;
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: begin -\n");
|
|
#endif
|
|
if (skb==NULL){
|
|
printk("nasrg_CLASS_send - input parameter skb is NULL \n");
|
|
return;
|
|
}
|
|
//***
|
|
#ifdef NAS_DEBUG_SEND
|
|
printk("nasrg_CLASS_send - Received IP packet to transmit, length %d\n", skb->len);
|
|
#endif
|
|
#ifdef NAS_DEBUG_SEND_DETAIL
|
|
if ((skb->data) != NULL){
|
|
if (skb->len<150)
|
|
nasrg_TOOL_print_buffer(skb->data,skb->len);
|
|
else
|
|
nasrg_TOOL_print_buffer(skb->data,150);
|
|
}
|
|
#endif
|
|
//***
|
|
// find all connections related to socket
|
|
cx_index = 0;
|
|
no_connection = 1;
|
|
cx = NULL;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: [before switch on IP protocol version] \n");
|
|
#endif
|
|
|
|
|
|
// Get mobile connexion entity, protocol and dscp from IP packet
|
|
switch (ntohs(skb->protocol)) {
|
|
case ETH_P_IPV6:
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send : skb->protocol : IPv6 \n");
|
|
#endif
|
|
version = NAS_VERSION_6;
|
|
addr_type = NAS_IPV6_ADDR_UNKNOWN;
|
|
protocolh = nasrg_TOOL_get_protocol6(ipv6_hdr(skb), &protocol);
|
|
dscp = nasrg_TOOL_get_dscp6 (ipv6_hdr(skb));
|
|
cx = nasrg_CLASS_cx6 (skb, dscp, &addr_type, &cx_index, &mbms_ix);
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send - ETH_P_IPV6 skb %p dscp %d gpriv %p cx_index %p \n",skb, dscp, gpriv, &cx_index);
|
|
#endif
|
|
// find in default DSCP a valid classification
|
|
if (cx == NULL) {
|
|
switch (addr_type) {
|
|
case NAS_IPV6_ADDR_MC_SIGNALLING:
|
|
case NAS_IPV6_ADDR_UNICAST:
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send - case NAS_IPV6_ADDR_MC_SIGNALLING | NAS_IPV6_ADDR_UNICAST\n");
|
|
#endif //NAS_DEBUG_CLASS
|
|
for (i=0; i<NAS_CX_MAX; i++){
|
|
pclassifier=(&gpriv->cx[i])->sclassifier[NAS_DSCP_DEFAULT];
|
|
while (pclassifier!=NULL) {
|
|
if ((pclassifier->version == NAS_VERSION_6) || (pclassifier->version == NAS_VERSION_DEFAULT)) {
|
|
// ok found default classifier for this packet
|
|
nasrg_create_mask_ipv6_addr(&masked6_addr, pclassifier->dplen);
|
|
// Modified MW to let everything go (pb with signalling)
|
|
masked6_addr.s6_addr32[0] = 0x00000000;
|
|
masked6_addr.s6_addr32[1] = 0x00000000;
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send - cx %d : DSCP NAS_DSCP_DEFAULT %X:%X:%X:%X:%X:%X:%X:%X\n",i, NIP6ADDR(&(pclassifier->daddr.ipv6)));
|
|
#endif //NAS_DEBUG_CLASS
|
|
|
|
if (IN6_ARE_ADDR_MASKED_EQUAL(&pclassifier->daddr.ipv6, &ipv6_hdr(skb)->daddr, &masked6_addr)) {
|
|
// then force dscp
|
|
cx = &gpriv->cx[i];
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send - ETH_P_IPV6 FOUND NAS_DSCP_DEFAULT with IN6_ARE_ADDR_MASKED_EQUAL(%d bits)\n",pclassifier->dplen);
|
|
#endif
|
|
dscp = NAS_DSCP_DEFAULT;
|
|
break;
|
|
} else {
|
|
if(IN6_IS_ADDR_UNSPECIFIED(&pclassifier->daddr.ipv6)) {
|
|
cx = &gpriv->cx[i];
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send - ETH_P_IPV6 FOUND NAS_DSCP_DEFAULT with IN6_IS_ADDR_UNSPECIFIED\n");
|
|
#endif
|
|
dscp = NAS_DSCP_DEFAULT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pclassifier = pclassifier->next;
|
|
}
|
|
}
|
|
break;
|
|
// MBMS is broken!!!! To be updated (these values will be over-ridden afterwards
|
|
case NAS_IPV6_ADDR_MC_MBMS:
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send - case NAS_IPV6_ADDR_MC_MBMS\n");
|
|
#endif //NAS_DEBUG_CLASS
|
|
pclassifier = gpriv->mbmsclassifier[mbms_ix];
|
|
printk("nasrg_CLASS_send: MBMS is broken!!!!\n\n\n");
|
|
sp = gpriv->mbmsclassifier[mbms_ix];
|
|
if (sp!= NULL){
|
|
classref=sp->classref;
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send: classifier found for multicast service %d \n", mbms_ix);
|
|
#endif
|
|
}else{
|
|
printk("nasrg_CLASS_send: No corresponding multicast bearer, so the message is dropped\n");
|
|
return;
|
|
}
|
|
break;
|
|
// should have found a valid classification rule
|
|
case NAS_IPV6_ADDR_UNKNOWN:
|
|
default:
|
|
printk("nasrg_CLASS_send: No corresponding address type\n");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ETH_P_ARP:
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send : skb->protocol : ARP \n");
|
|
#endif
|
|
version = NAS_VERSION_4;
|
|
addr_type = NAS_IPV4_ADDR_BROADCAST;
|
|
dscp = 0;
|
|
cx = NULL;
|
|
// Basic sanity checks can be done without the lock
|
|
rarp = (struct arphdr *)skb_network_header(skb);
|
|
if (rarp) {
|
|
if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)) {
|
|
printk("nasrg_CLASS_send: ARP PACKET WRONG ADDR LEN or WRONG ARP HEADER TYPE\n");
|
|
break;
|
|
}
|
|
} else {
|
|
printk("nasrg_CLASS_send: ARP HEADER POINTER IS NULL\n");
|
|
break;
|
|
}
|
|
// If it's not Ethernet, delete it.
|
|
if (rarp->ar_pro != htons(ETH_P_IP)) {
|
|
printk("nasrg_CLASS_send: ARP PACKET PROTOCOL IS NOT ETHERNET\n");
|
|
break;
|
|
}
|
|
rarp_ptr = (unsigned char *) (rarp + 1);
|
|
sha = rarp_ptr;
|
|
rarp_ptr += dev->addr_len;
|
|
memcpy(&sip, rarp_ptr, 4);
|
|
rarp_ptr += 4;
|
|
tha = rarp_ptr;
|
|
rarp_ptr += dev->addr_len;
|
|
memcpy(&tip, rarp_ptr, 4);
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: ARP DEST IP transport IP = %d.%d.%d.%d\n",NIPADDR(tip));
|
|
#endif
|
|
for (i=0; i<NAS_CX_MAX; i++){
|
|
pclassifier=(&gpriv->cx[i])->sclassifier[NAS_DSCP_DEFAULT];
|
|
while (pclassifier!=NULL) {
|
|
if ((pclassifier->version == NAS_VERSION_4) || (pclassifier->version == NAS_VERSION_DEFAULT)) {
|
|
// ok found default classifier for this packet
|
|
nasrg_create_mask_ipv4_addr(&masked_addr, pclassifier->dplen);
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: MASK = %d.%d.%d.%d\n",NIPADDR(masked_addr.s_addr));
|
|
#endif
|
|
//
|
|
if (IN_ARE_ADDR_MASKED_EQUAL(&pclassifier->daddr.ipv4, &tip, &masked_addr.s_addr)) {
|
|
// then force dscp
|
|
cx = &gpriv->cx[i];
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: ETH_P_ARP FOUND NAS_DSCP_DEFAULT with IN_ARE_ADDR_MASKED_EQUAL(%d bits)\n", pclassifier->dplen);
|
|
#endif
|
|
dscp = NAS_DSCP_DEFAULT;
|
|
break;
|
|
} else {
|
|
if (INADDR_ANY == pclassifier->daddr.ipv4) {
|
|
cx = &gpriv->cx[i];
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: ETH_P_ARP FOUND NAS_DSCP_DEFAULT with INADDR_ANY\n");
|
|
#endif
|
|
dscp = NAS_DSCP_DEFAULT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pclassifier = pclassifier->next;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ETH_P_IP:
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send : skb->protocol : IPv4 \n");
|
|
#endif
|
|
version = NAS_VERSION_4;
|
|
addr_type = NAS_IPV4_ADDR_UNKNOWN;
|
|
dscp = nasrg_TOOL_get_dscp4((struct iphdr *)(skb_network_header(skb)));
|
|
cx = nasrg_CLASS_cx4(skb, dscp, &addr_type, &cx_index);
|
|
protocolh = nasrg_TOOL_get_protocol4((struct iphdr *)(skb_network_header(skb)), &protocol);
|
|
// find in default DSCP a valid classification
|
|
if (cx == NULL) {
|
|
switch (addr_type) {
|
|
case NAS_IPV4_ADDR_MC_SIGNALLING:
|
|
case NAS_IPV4_ADDR_UNICAST:
|
|
case NAS_IPV4_ADDR_BROADCAST:
|
|
for (i=0; i<NAS_CX_MAX; i++){
|
|
pclassifier=(&gpriv->cx[i])->sclassifier[NAS_DSCP_DEFAULT];
|
|
while (pclassifier != NULL) {
|
|
if ((pclassifier->version == NAS_VERSION_4) || (pclassifier->version == NAS_VERSION_DEFAULT)) {
|
|
// ok found default classifier for this packet
|
|
nasrg_create_mask_ipv4_addr(&masked_addr, pclassifier->dplen);
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send : MASK = %d.%d.%d.%d\n", NIPADDR(masked_addr.s_addr));
|
|
#endif
|
|
if (IN_ARE_ADDR_MASKED_EQUAL(&pclassifier->daddr.ipv4, &ip_hdr(skb)->daddr, &masked_addr.s_addr)) {
|
|
// then force dscp
|
|
cx = &gpriv->cx[i];
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send : ETH_P_IP FOUND NAS_DSCP_DEFAULT with IN_ARE_ADDR_MASKED_EQUAL(%d bits)\n",pclassifier->dplen);
|
|
#endif
|
|
dscp = NAS_DSCP_DEFAULT;
|
|
break;
|
|
} else {
|
|
if(INADDR_ANY == pclassifier->daddr.ipv4) {
|
|
cx = &gpriv->cx[i];
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send : ETH_P_IP FOUND NAS_DSCP_DEFAULT with INADDR_ANY\n");
|
|
#endif
|
|
dscp = NAS_DSCP_DEFAULT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pclassifier = pclassifier->next;
|
|
}
|
|
}
|
|
break;
|
|
// should have found a valid classification rule
|
|
case NAS_IPV4_ADDR_UNKNOWN:
|
|
default:
|
|
printk("nasrg_CLASS_send: No corresponding address type\n");
|
|
}
|
|
}
|
|
#ifdef NAS_DEBUG_CLASS
|
|
if (cx)
|
|
printk("nasrg_CLASS_send: ETH_P_IP Received IPv4 packet (%02X), dscp = %d, cx = %d\n",ntohs(skb->protocol),dscp,cx->lcr);
|
|
else
|
|
printk("nasrg_CLASS_send: ETH_P_IP Received IPv4 packet (%02X), dscp = %d, No valid connection\n",ntohs(skb->protocol),dscp);
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
printk("nasrg_CLASS_send: Unknown IP version protocol\n");
|
|
version = 0;
|
|
return;
|
|
}
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send: [before if (cx != NULL)]\n");
|
|
#endif
|
|
|
|
//Next lines bypass classifiers to test the netlink socket
|
|
//#define DEBUG_NETLINKRG_TEST
|
|
#ifdef DEBUG_NETLINKRG_TEST
|
|
nasrg_COMMON_QOS_send_test_netlink(skb);
|
|
return;
|
|
#endif
|
|
|
|
// If a valid connection for the DSCP/EXP with destination address
|
|
// is found scan all protocol-based classification rules
|
|
if (cx != NULL) {
|
|
classref = 0;
|
|
sp = NULL;
|
|
if (cx->state!=NAS_CX_DCH){
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: UE not connected, in state %d. Packet is dropped\n",cx->state);
|
|
#endif
|
|
return;
|
|
}
|
|
if (addr_type==NAS_IPV6_ADDR_MC_MBMS){
|
|
sp = gpriv->mbmsclassifier[mbms_ix];
|
|
if (sp!= NULL){
|
|
classref=sp->classref;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: classifier found for multicast index %d, service %d\n", mbms_ix, gpriv->mbms_rb[mbms_ix].cnxid);
|
|
#endif
|
|
}else{
|
|
// Temp MEDIEVAL : use default classifier
|
|
sp = cx->sclassifier[NAS_DSCP_DEFAULT];
|
|
if (sp!= NULL){
|
|
classref=sp->classref;
|
|
#ifdef NAS_DEBUG_CLASS
|
|
printk("nasrg_CLASS_send: classifier for multicast service %d replaced by default %d\n", mbms_ix, classref);
|
|
#endif
|
|
#ifdef NAS_AUTO_MBMS
|
|
nasrg_ASCTL_start_default_mbms_service();
|
|
#endif
|
|
} else {
|
|
printk("nasrg_CLASS_send: No corresponding multicast bearer, so the message is dropped\n");
|
|
return;
|
|
}
|
|
}
|
|
}else{
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send: DSCP %d version %d: looking for classifier entry\n",dscp, version);
|
|
#endif
|
|
for (pclassifier=cx->sclassifier[dscp]; pclassifier!=NULL; pclassifier=pclassifier->next) {
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send: DSCP %d p->classref=%d,p->protocol=%d,p->version=%d\n",dscp,pclassifier->classref,pclassifier->protocol,pclassifier->version);
|
|
#endif
|
|
// normal rule checks that network protocol version matches
|
|
if ((pclassifier->version == version) || (pclassifier->version == NAS_VERSION_DEFAULT)){
|
|
//printk("nasrg_CLASS_send: IP version are equals\n");
|
|
sp=pclassifier;
|
|
classref=sp->classref;
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send: classifier found for dscp %u \n", dscp);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sp!=NULL) {
|
|
#ifdef NAS_DEBUG_CLASS
|
|
//char sfct[10], sprotocol[10];
|
|
// classifier entity found. Print its parameters
|
|
if (sp->fct==nasrg_COMMON_QOS_send)
|
|
strcpy(sfct, "data xfer");
|
|
if (sp->fct==nasrg_CTL_send)
|
|
strcpy(sfct, "iocontrol");
|
|
if (sp->fct==nasrg_COMMON_del_send)
|
|
strcpy(sfct, "delete");
|
|
if (sp->fct==nasrg_ASCTL_DC_send_sig_data_request)
|
|
strcpy(sfct, "DC-SAP");
|
|
|
|
switch(protocol) {
|
|
case NAS_PROTOCOL_UDP:strcpy(sprotocol, "udp");printk("udp packet\n");break;
|
|
case NAS_PROTOCOL_TCP:strcpy(sprotocol, "tcp");printk("tcp packet\n");break;
|
|
case NAS_PROTOCOL_ICMP4:strcpy(sprotocol, "icmp4");printk("icmp4 packet\n");break;
|
|
case NAS_PROTOCOL_ICMP6:strcpy(sprotocol, "icmp6"); nasrg_TOOL_pk_icmp6((struct icmp6hdr*)protocolh);break;
|
|
default:strcpy(sprotocol, "other L4");break;
|
|
}
|
|
printk("nasrg_CLASS_send: (dscp %u, %s) received, (classref %u, fct %s, drb_id %u) classifier rule\n",
|
|
dscp, sprotocol, sp->classref, sfct, sp->rab_id);
|
|
#endif
|
|
|
|
//forward packet to the correct entity
|
|
if (sp->fct!=NULL){
|
|
sp->fct(skb, cx, sp);
|
|
}else{
|
|
printk("\n\nnasrg_CLASS_send: ERROR : CLASSIFIER FUNCTION IS NULL\n\n");
|
|
}
|
|
no_connection = 0;
|
|
// end : if classifier entry match found
|
|
} else {
|
|
printk("nasrg_CLASS_send: no corresponding item in the classifier list, so the message is dropped\n");
|
|
printk("nasrg_CLASS_send: packet parameters: dscp %u, %s\n", dscp, sprotocol);
|
|
nasrg_COMMON_del_send(skb, cx, NULL); // Note MW: LG has commented this line. Why?
|
|
}
|
|
} // if connection found
|
|
|
|
#ifdef NAS_DEBUG_CLASS
|
|
if (no_connection == 1) {
|
|
printk("nasrg_CLASS_send: no corresponding connection, so the message is dropped\n");
|
|
}
|
|
#endif
|
|
#ifdef NAS_DEBUG_CLASS_DETAIL
|
|
printk("nasrg_CLASS_send: end\n");
|
|
#endif
|
|
}
|