#ifdef CM_CONFIG_TOE | |
#include "cm_tft.h" | |
#define UPGRADE_NR | |
#define TCP_PROTO 6 | |
#define UDP_PROTO 17 | |
#define ICMP_PROTO 1 | |
static UINT32 tftLogCtrlBitsMap = 1; | |
#define TFT_HASH_LOG_BIT (0x1) | |
#define TFT_PKT_INFO_LOG_BIT (0x2) | |
#define TFT_CMP_LOG_BIT (0x4) | |
#define TFT_HASH_LOG_ENABLE (tftLogCtrlBitsMap&TFT_HASH_LOG_BIT) | |
#define TFT_PKT_INFO_LOG_ENABLE (tftLogCtrlBitsMap&TFT_PKT_INFO_LOG_BIT) | |
#define TFT_CMP_INFO_LOG_ENABLE (tftLogCtrlBitsMap&TFT_CMP_LOG_BIT) | |
#define IP_MF_SmallEndian (0x0020) /* more fragments flag */ | |
#define IPV6_MF_SmallEndian (0x1) /* more fragments flag */ | |
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ | |
//IP TYPE 0-IPV4V6; 1---IPV4; 2-IPV6 | |
#define IPH_PROTO(hdr) ((hdr)->ip_p) | |
#define IPH_OFFSET(hdr) ((hdr)->ip_off) | |
#define IPH_ID(hdr) ((hdr)->ip_id) | |
#define IPH_HL(hdr) (((hdr)->ip_pvhl) & 0x0f) | |
#define IP_PROTO_ICMP 1 | |
#define IP_PROTO_IGMP 2 | |
#define IP_PROTO_UDP 17 | |
#define IP_PROTO_UDPLITE 136 | |
#define IP_PROTO_TCP 6 | |
#define IP_PROTO_GRE 47 | |
#define IP_PROTO_DESTOPTS 60 | |
#define IP_PROTO_ROUTING 43 | |
#define IP_PROTO_FRAGMENT 44 | |
#define IP_TYPE_IPV4V6 0 | |
#define IP_TYPE_IPV4 1 | |
#define IP_TYPE_IPV6 2 | |
#define IP4_DL_FILTER_COUNT (8) | |
#define IP6_DL_FILTER_COUNT (8) | |
#define STA_TFT_TABLE_SIZE (32) | |
#define CACHE_SIZE 1024 | |
#define CACHE_TIME 12 /* 50 sec */ | |
#define ENHASH | |
//#define DBG | |
//#define ntohs(x) (((((x) >> 8) & 0xFF) + ((x) << 8)) & 0xFFFF) | |
#if 0 | |
static TftInfoList CurcentTftList[STA_TFT_TABLE_SIZE]; | |
#endif | |
static TFTNode PFArryForEachPramaryCid[MAX_CID_COUNT_FOR_TFT]; //dedicated bearer filer rules and default bearer filer rules | |
static TFTNode PFArryForEachPramaryCid_1[MAX_CID_COUNT_FOR_TFT]; | |
static volatile unsigned CurrentTFTTableItemCount=0; | |
static volatile unsigned CurrentTFTTableItemCount_1=0; | |
#if defined(UPGRADE_NR) | |
unsigned char CurrentQoSTableItemCount=0; | |
unsigned char CurrentQoSTableItemCount_1=0; | |
static QoSNode QoSArryForEachPramaryCid_NR[MAX_CID_COUNT_FOR_TFT]; | |
static QoSNode QoSArryForEachPramaryCid_NR_1[MAX_CID_COUNT_FOR_TFT]; | |
#endif | |
void cm_tftinfo_init(void) | |
{ | |
int i; | |
for(i=0;i<MAX_CID_COUNT_FOR_TFT;i++) | |
{ | |
PFArryForEachPramaryCid[i].next=PFArryForEachPramaryCid[i].pre=&PFArryForEachPramaryCid[i]; | |
PFArryForEachPramaryCid_1[i].next=PFArryForEachPramaryCid_1[i].pre=&PFArryForEachPramaryCid_1[i]; | |
} | |
#if defined(UPGRADE_NR) | |
memset(QoSArryForEachPramaryCid_NR, 0, sizeof(QoSArryForEachPramaryCid_NR)); | |
memset(QoSArryForEachPramaryCid_NR_1, 0, sizeof(QoSArryForEachPramaryCid_NR_1)); | |
for(i=0;i<MAX_CID_COUNT_FOR_TFT;i++) | |
{ | |
QoSArryForEachPramaryCid_NR[i].next=QoSArryForEachPramaryCid_NR[i].pre=&QoSArryForEachPramaryCid_NR[i]; | |
QoSArryForEachPramaryCid_NR_1[i].next=QoSArryForEachPramaryCid_NR_1[i].pre=&QoSArryForEachPramaryCid_NR_1[i]; | |
QoSArryForEachPramaryCid_NR[i].tftNode.next=QoSArryForEachPramaryCid_NR[i].tftNode.pre=&QoSArryForEachPramaryCid_NR[i].tftNode; | |
QoSArryForEachPramaryCid_NR_1[i].tftNode.next=QoSArryForEachPramaryCid_NR_1[i].tftNode.pre=&QoSArryForEachPramaryCid_NR_1[i].tftNode; | |
} | |
#endif | |
} | |
#ifdef ENHASH | |
struct pf_cache { | |
int time; | |
int cid; | |
unsigned int hash_key; | |
#if defined(UPGRADE_NR) | |
unsigned char qfi; | |
unsigned char psi; | |
#endif | |
unsigned int src_port; | |
unsigned int dest_port; | |
unsigned int proto; | |
unsigned int ip; | |
}; | |
static struct pf_cache tft_cache[CACHE_SIZE] = {0}; | |
static int dirty_cnt = 0; | |
static inline unsigned int | |
make_rs_hash(const char *info, unsigned int len, unsigned int index) | |
{ | |
unsigned int b = 378551; | |
unsigned int a = 63689; | |
unsigned int hash = 0; | |
unsigned int i; | |
for (i = 0; i < len; i++) { | |
hash = (hash * a) + (info[i]); | |
a = a * b; | |
} | |
hash = hash * index; | |
return hash; | |
} | |
static inline int clear_tft_cache(unsigned char cid) | |
{ | |
if (cid == 0xff) { | |
/* Clear all tft cache */ | |
memset(tft_cache, 0, CACHE_SIZE*sizeof(tft_cache[0])); | |
dirty_cnt = 0; | |
} else { | |
int i; | |
for (i = 0; i < CACHE_SIZE; i++) { | |
if (tft_cache[i].cid== cid) { | |
tft_cache[i].cid = 0xff; | |
tft_cache[i].time = 0; | |
tft_cache[i].hash_key = 0; | |
dirty_cnt--; | |
if (dirty_cnt < 0) dirty_cnt = 0; | |
} | |
} | |
} | |
return 0; | |
} | |
#endif | |
static void TftAddNewItem_Nr(TftInfoList * pf, unsigned char count, QoSNode *pQosArry) | |
{ | |
int i; | |
int cid,findflag=0; | |
int filterId; | |
TFTNode* header, *testheader, *tempNode; | |
PacketFilterInfoNode* tftitem,*lasttftitem; | |
QoSNode *p_QoSArryForEachPramaryCid; | |
p_QoSArryForEachPramaryCid = pQosArry; | |
for(i=0;i<count;i++){ | |
cid=pf[i].cid; | |
filterId=pf[i].packetinfo.PfIdx; | |
findflag=0; | |
header=&p_QoSArryForEachPramaryCid->tftNode; | |
tempNode=header->next; | |
CM_Log(TftAddNewItem_Nr405,"TftAddNewItem_Nr: Try to find PF for cid[%d] pf id[%d], pcid %d",cid,filterId,pf->Pcid); | |
while(tempNode!=header) | |
{ | |
tftitem=((PacketFilterInfoNode*) tempNode); | |
if((tftitem->info.cid==cid)&&(tftitem->info.packetinfo.PfIdx==pf[i].packetinfo.PfIdx)) | |
{ | |
memcpy(&tftitem->info,&pf[i],sizeof(TftInfoList)); | |
CM_Log(TftAddNewItem_Nr417, "only reconfigure PF info"); | |
findflag=1; | |
break; | |
} | |
tempNode=tempNode->next; | |
} | |
if(findflag==1) | |
continue; | |
tftitem=malloc(sizeof(PacketFilterInfoNode)); | |
if(tftitem==NULL) | |
{ | |
CM_Log(TftAddNewItem_Nr430,"no memory for TFT info node"); | |
return; | |
} | |
tempNode=&tftitem->header; | |
tempNode->next=tempNode->pre=NULL; | |
memcpy(&tftitem->info,&pf[i],sizeof(TftInfoList)); | |
CM_Log(TftAddNewItem_Nr437,"header %lx, header->next %lx",header,header->next); | |
testheader=header->next; | |
while(testheader!=header) | |
{ | |
lasttftitem=((PacketFilterInfoNode*) (testheader)); | |
CM_Log(TftAddNewItem_Nr444,"header->next %lx epi %d",testheader,lasttftitem->info.packetinfo.EpIdx); | |
if(tftitem->info.packetinfo.EpIdx<=lasttftitem->info.packetinfo.EpIdx) | |
break; | |
else | |
testheader=testheader->next; | |
} | |
tempNode->next=testheader; | |
tempNode->pre=testheader->pre; | |
testheader->pre->next=tempNode; | |
testheader->pre=tempNode; | |
(p_QoSArryForEachPramaryCid->tftCnt)++; | |
CM_Log(TftAddNewItem_Nr458,"TftAddNewItem_Nr: total PF %d",p_QoSArryForEachPramaryCid->tftCnt); | |
} | |
return; | |
} | |
/* CI_PS_PRIM_TFT_REPORT_IND */ | |
void cm_qos_update_pf(TftInfoList *pf, BOOL sim2Flag) | |
{ | |
int cid,cid_tmp,findqosflag=0; | |
QoSNode *p_QoSArryForEachPramaryCid; | |
QoSNode* qosheader, *qostestheader, *qostempNode; | |
QoSNode* qositem; | |
UINT8 *p_CurrentQoSTableItemCount; | |
if(!pf->filter_num) | |
return ; | |
if(sim2Flag) | |
{ | |
p_QoSArryForEachPramaryCid = &QoSArryForEachPramaryCid_NR_1[0]; | |
p_CurrentQoSTableItemCount = &CurrentQoSTableItemCount_1; | |
} | |
else | |
{ | |
p_QoSArryForEachPramaryCid = &QoSArryForEachPramaryCid_NR[0]; | |
p_CurrentQoSTableItemCount = &CurrentQoSTableItemCount; | |
} | |
#ifdef ENHASH | |
clear_tft_cache(0xff); | |
#endif | |
cid=pf[0].cid; | |
if(pf[0].bearer_type==2) //dedicated bearer | |
{ | |
cid_tmp = pf[0].Pcid; | |
} | |
else{ //default bearer | |
cid_tmp = cid; | |
} | |
findqosflag = 0; | |
qosheader=&p_QoSArryForEachPramaryCid[cid_tmp]; | |
qostempNode=qosheader->next; | |
while(qostempNode!=qosheader) | |
{ | |
if((qostempNode->priority == pf->extend_info.priority) && (qostempNode->qfi == pf->extend_info.qfi)) | |
{ | |
findqosflag=1; | |
break; | |
} | |
qostempNode=qostempNode->next; | |
} | |
if(findqosflag==1) | |
{ | |
TftAddNewItem_Nr(pf, pf->filter_num, qostempNode); | |
return ; | |
} | |
qositem=malloc(sizeof(QoSNode)); | |
if(qositem==NULL) | |
{ | |
CM_Log(QosAddNewItem_Nr461,"no memory for QoS node"); | |
return; | |
} | |
qositem->next=qositem->pre=NULL; | |
qositem->tftNode.next=qositem->tftNode.pre=&qositem->tftNode; | |
qositem->qfi = pf->extend_info.qfi; | |
qositem->psi = pf->extend_info.pdu; | |
qositem->priority = pf->extend_info.priority; | |
qositem->tftCnt = 0; | |
CM_Log(QosAddNewItem_Nr529, "header %lx, header->next %lx",qosheader,qosheader->next); | |
qostestheader=qosheader->next; | |
while(qostestheader!=qosheader) | |
{ | |
/* sort by priority */ | |
if(qositem->priority<=qostestheader->priority) | |
break; | |
else | |
qostestheader=qostestheader->next; | |
} | |
qositem->next=qostestheader; | |
qositem->pre=qostestheader->pre; | |
qostestheader->pre->next=qositem; | |
qostestheader->pre=qositem; | |
(*p_CurrentQoSTableItemCount) ++; | |
TftAddNewItem_Nr(pf, pf->filter_num, qositem); | |
CM_Log(QosAddNewItem_Nr548, "total QoS %d",*p_CurrentQoSTableItemCount); | |
return; | |
} | |
void qos_delete_qos(unsigned char PrimCid,unsigned char targetCid, BOOL sim2Flag) | |
{ | |
QoSNode* qosheader, *qostempNode,*qosfreeNode=NULL; | |
TFTNode* header, *tempNode,*freeNode=NULL; | |
PacketFilterInfoNode* tftitem; | |
unsigned char *p_CurrentQoSTableItemCount; | |
QoSNode *p_QoSArryForEachPramaryCid; | |
unsigned char cid_tmp = 0; | |
if(sim2Flag) | |
{ | |
p_CurrentQoSTableItemCount = &CurrentQoSTableItemCount_1; | |
p_QoSArryForEachPramaryCid = QoSArryForEachPramaryCid_NR_1; | |
} | |
else | |
{ | |
p_CurrentQoSTableItemCount = &CurrentQoSTableItemCount; | |
p_QoSArryForEachPramaryCid = QoSArryForEachPramaryCid_NR; | |
} | |
CM_Log(qos_delete_qos564,"before delete, sim[%d] total QoS %d",sim2Flag, *p_CurrentQoSTableItemCount); | |
if((*p_CurrentQoSTableItemCount) ==0) | |
return; | |
#ifdef ENHASH | |
clear_tft_cache(0xff); | |
#endif | |
if(PrimCid==0xff) | |
{ | |
cid_tmp = targetCid; | |
} | |
else{ | |
cid_tmp = PrimCid; | |
} | |
qosheader = &p_QoSArryForEachPramaryCid[cid_tmp]; | |
qostempNode=qosheader->next; | |
CM_Log(qos_delete_qos585, "qos header 0x%lx, next 0x%lx", qosheader,qostempNode); | |
while(qostempNode!=qosheader) | |
{ | |
if(qostempNode->tftCnt == 0) | |
{ | |
CM_Log(qos_delete_qos592, "qostempNode 0x%lx, tftCnt %d, current Qos cnt %d", qostempNode,qostempNode->tftCnt,*p_CurrentQoSTableItemCount); | |
qostempNode->next->pre=qostempNode->pre; | |
qostempNode->pre->next=qostempNode->next; | |
qosfreeNode=qostempNode; | |
qostempNode=qostempNode->next; | |
(*p_CurrentQoSTableItemCount)--; | |
free(qosfreeNode); | |
continue ; | |
} | |
header=&qostempNode->tftNode; | |
tempNode=header->next; | |
while(tempNode!=header) | |
{ | |
tftitem=((PacketFilterInfoNode*) tempNode); | |
CM_Log(qos_delete_qos592, "tftitem->info.cid %d, tftitem->info.Pcid %d", tftitem->info.cid, tftitem->info.Pcid); | |
if((tftitem->info.cid==targetCid) && (tftitem->info.Pcid==PrimCid)) | |
{ | |
(qostempNode->tftCnt)--; | |
tempNode->next->pre=tempNode->pre; | |
tempNode->pre->next=tempNode->next; | |
freeNode=tempNode; | |
tempNode=tempNode->next; | |
free(freeNode); | |
}else{ | |
tempNode=tempNode->next; | |
} | |
} | |
if(qostempNode->tftCnt == 0) | |
{ | |
qostempNode->next->pre=qostempNode->pre; | |
qostempNode->pre->next=qostempNode->next; | |
qosfreeNode=qostempNode; | |
qostempNode=qostempNode->next; | |
(*p_CurrentQoSTableItemCount)--; | |
CM_Log(qos_delete_qos633, "delete qos 0x%lx, total QoS %d",qosfreeNode, *p_CurrentQoSTableItemCount); | |
free(qosfreeNode); | |
} | |
else | |
{ | |
qostempNode=qostempNode->next; | |
} | |
} | |
CM_Log(qos_delete_qos641, "after delete, sim[%d] total QoS %d",sim2Flag, *p_CurrentQoSTableItemCount); | |
return; | |
} | |
static int SearchQoSNodeToFindToeParam(void* Ipinfo,unsigned char ipverson,UINT8 cid, struct toe_tft_param *toe_param) | |
{ | |
TFTNode* header, *temp; | |
QoSNode* qosheader, *qostemp; | |
TftInfoList *Tftitem; | |
unsigned int dest_addr[4]; | |
UINT8 sim2Flag =(cid & 0x80)? 1 : 0; | |
QoSNode *p_QoSArryForEachPramaryCid; | |
BOOL matched = FALSE; | |
unsigned int *pAddr[4] = { 0 }; | |
unsigned int *pMask[4] = { 0 }; | |
CM_Log(SearchQoSNodeToFindToeParam673, "SearchQoSNodeToFindToeParam: org cid 0x%lx, sim[%d], ip %d", cid,sim2Flag,ipverson); | |
cid = cid&0x7F; | |
if(sim2Flag) | |
{ | |
p_QoSArryForEachPramaryCid = QoSArryForEachPramaryCid_NR_1; | |
} | |
else | |
{ | |
p_QoSArryForEachPramaryCid = QoSArryForEachPramaryCid_NR; | |
} | |
qosheader=&p_QoSArryForEachPramaryCid[cid]; | |
for(qostemp=qosheader->next;qostemp!=qosheader;qostemp=qostemp->next) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam692, "search qos 0x%lx, pri %d, qfi %d, psi %d, tft cnt %d", | |
qostemp, qostemp->priority,qostemp->qfi, qostemp->psi, qostemp->tftCnt); | |
if(qostemp->tftCnt == 0) | |
continue; | |
header=&qostemp->tftNode; | |
for(temp=header->next;temp!=header;temp=temp->next) | |
{ | |
Tftitem=&(((PacketFilterInfoNode*)temp)->info); | |
CM_Log(SearchQoSNodeToFindToeParam648,"direction %d, match all %d, pfId %d, epId %d", | |
Tftitem->packetinfo.direction, Tftitem->packetinfo.matchAll, Tftitem->packetinfo.PfIdx, Tftitem->packetinfo.EpIdx); | |
if ((Tftitem->packetinfo.direction != 1)&&(Tftitem->packetinfo.direction !=3)) | |
{ | |
continue; | |
} | |
toe_param->mcid = Tftitem->cid; | |
if(TRUE == Tftitem->packetinfo.matchAll) | |
{ | |
toe_param->qfi = qostemp->qfi; | |
toe_param->pdu = Tftitem->extend_info.pdu; | |
CM_Log(SearchQoSNodeToFindToeParam709,"SearchQoSNodeToFindToeParam : SIM[%d], [match_all] priority [%d],qfi [%d], psi [%d], cid [0x%lx], targetcid [0x%lx]", | |
sim2Flag,qostemp->priority,toe_param->qfi, toe_param->pdu, cid, toe_param->mcid); | |
return 0; | |
} | |
if(ipverson==4) | |
{ | |
struct espid_ip4_info* Ipinfo4=(struct espid_ip4_info* )Ipinfo; | |
/* pnNextHdr: ipv4 for protocol number,ipv6 for next header */ | |
/* For TOE, 0 means UDP, 1 means TCP */ | |
if ((Tftitem->packetinfo.pnNextHdrPresent!=0)&& | |
((Ipinfo4->proto == TOE_TCP && Tftitem->packetinfo.pnNextHdr != 6) || (Ipinfo4->proto == TOE_UDP && Tftitem->packetinfo.pnNextHdr != 17))) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam720,"proto mismatch: 0x%lx, 0x%lx",Ipinfo4->proto,Tftitem->packetinfo.pnNextHdr); | |
continue; | |
} | |
if (Tftitem->packetinfo.RemoteAddressPresent && Tftitem->packetinfo.SubnetMaskPresent) | |
{ | |
pAddr[0] = (unsigned int *)&(Tftitem->packetinfo.RemoteAddress[0]); | |
pMask[0] = (unsigned int *)&(Tftitem->packetinfo.SubnetMask[0]); | |
dest_addr[0] = (Ipinfo4->dest_ip & *pMask[0]); | |
if (dest_addr[0] == ((unsigned int)*pAddr[0] & (unsigned int)*pMask[0])) | |
{ | |
if (TFT_CMP_INFO_LOG_ENABLE) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam732,"IP4 match dest addr (masked) 0x%lx",dest_addr[0]); | |
} | |
}else{ | |
CM_Log(SearchQoSNodeToFindToeParam736, "IP4 no mach dest addr (masked) 0x%lx, tft remote addr (masked)0x%lx",dest_addr[0], (*pAddr[0] & *pMask[0])); | |
continue; | |
} | |
} | |
if (Tftitem->packetinfo.localPortRangePresent) | |
{ | |
if (!(Ipinfo4->src_port>=Tftitem->packetinfo.localPortRange.min && | |
Ipinfo4->src_port<=Tftitem->packetinfo.localPortRange.max)) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam745, "IP4 [0x%lx] no mach local port range 0x%lx-0x%lx", | |
Ipinfo4->src_port,Tftitem->packetinfo.localPortRange.min,Tftitem->packetinfo.localPortRange.max); | |
continue; | |
} | |
} | |
if (Tftitem->packetinfo.remotePortRangePresent) | |
{ | |
if (!(Ipinfo4->dest_port>=Tftitem->packetinfo.remotePortRange.min && | |
Ipinfo4->dest_port<=Tftitem->packetinfo.remotePortRange.max)) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam755, "IP4 [0x%lx] no mach remote port range 0x%lx-0x%lx", | |
Ipinfo4->dest_port,Tftitem->packetinfo.remotePortRange.min,Tftitem->packetinfo.remotePortRange.max); | |
continue; | |
} | |
} | |
matched = TRUE; | |
break; | |
}else if(ipverson==6) | |
{ | |
struct espid_ip6_info* Ipinfo6=(struct espid_ip6_info* )Ipinfo; | |
if ((Tftitem->packetinfo.pnNextHdrPresent!=0)&&(Tftitem->packetinfo.pnNextHdr!= Ipinfo6->proto)) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam770, "proto mismatch: 0x%lx, 0x%lx",Ipinfo6->proto,Tftitem->packetinfo.pnNextHdr); | |
continue; | |
} | |
if (Tftitem->packetinfo.RemoteAddressPresent && Tftitem->packetinfo.SubnetMaskPresent){ | |
pAddr[0] = (unsigned int *)&(Tftitem->packetinfo.RemoteAddress[0]); | |
pAddr[1] = (unsigned int *)&(Tftitem->packetinfo.RemoteAddress[4]); | |
pAddr[2] = (unsigned int *)&(Tftitem->packetinfo.RemoteAddress[8]); | |
pAddr[3] = (unsigned int *)&(Tftitem->packetinfo.RemoteAddress[12]); | |
pMask[0] = (unsigned int *)&(Tftitem->packetinfo.SubnetMask[0]); | |
pMask[1] = (unsigned int *)&(Tftitem->packetinfo.SubnetMask[4]); | |
pMask[2] = (unsigned int *)&(Tftitem->packetinfo.SubnetMask[8]); | |
pMask[3] = (unsigned int *)&(Tftitem->packetinfo.SubnetMask[12]); | |
dest_addr[0] = (Ipinfo6->dest_ip[0] & *pMask[0]); | |
dest_addr[1] = (Ipinfo6->dest_ip[1] & *pMask[1]); | |
dest_addr[2] = (Ipinfo6->dest_ip[2] & *pMask[2]); | |
dest_addr[3] = (Ipinfo6->dest_ip[3] & *pMask[3]); | |
if ((dest_addr[0] == (*pAddr[0] & *pMask[0]))&& | |
(dest_addr[1] == (*pAddr[1] & *pMask[1]))&& | |
(dest_addr[2] == (*pAddr[2] & *pMask[2]))&& | |
(dest_addr[3] == (*pAddr[3] & *pMask[3]))){ | |
if (TFT_CMP_INFO_LOG_ENABLE) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam788, "SIM[%d]:IP6 match for cid %d",sim2Flag, Tftitem->cid); | |
} | |
} else { | |
CM_Log(SearchQoSNodeToFindToeParam792, "SIM[%d]: IP6 no mach",sim2Flag); | |
continue; | |
} | |
} | |
if (Tftitem->packetinfo.localPortRangePresent) { | |
if (!(Ipinfo6->src_port>=Tftitem->packetinfo.localPortRange.min && | |
Ipinfo6->src_port<=Tftitem->packetinfo.localPortRange.max)) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam803, "SIM[%d]:src port no match",sim2Flag); | |
continue; | |
} | |
} | |
if (Tftitem->packetinfo.remotePortRangePresent) { | |
if (!(Ipinfo6->dest_port>=Tftitem->packetinfo.remotePortRange.min && | |
Ipinfo6->dest_port<=Tftitem->packetinfo.remotePortRange.max)) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam812, "SIM[%d]: dst port no match",sim2Flag); | |
continue; | |
} | |
} | |
if(TFT_CMP_INFO_LOG_ENABLE) | |
{ | |
CM_Log(SearchQoSNodeToFindToeParam819, "tft[0x%lx]: nrmode %d ",Tftitem); | |
} | |
matched = TRUE; | |
break; | |
} | |
} | |
if(matched == TRUE) | |
{ | |
toe_param->qfi = qostemp->qfi; | |
if (Tftitem) | |
toe_param->pdu = Tftitem->extend_info.pdu; | |
else | |
toe_param->pdu = qostemp->psi; | |
CM_Log(SearchQoSNodeToFindToeParam831, "SearchQoSNodeToFindToeParam831 : SIM[%d], match prio [%d], qfi [%d], psi [%d], cid [0x%lx], targetcid [0x%lx]", | |
sim2Flag,qostemp->priority, toe_param->qfi, toe_param->pdu, cid, toe_param->mcid); | |
return 0; | |
} | |
} | |
return -1; | |
} | |
static bool cm_get_toe_param_cache(u8 ip_version, void *ipinfo, struct toe_tft_param *toe_param, unsigned int *h_index, unsigned int *saved_key) | |
{ | |
#ifdef ENHASH | |
unsigned int hash_key = 0, hash_key_saved=0; | |
int i = 0, j=0, hit_cnt = 0; | |
/* Find packet filter in cache table */ | |
j = 0xffff; | |
hit_cnt = 0; | |
if (ip_version == 4) | |
hash_key = make_rs_hash((char *)ipinfo, sizeof(struct espid_ip4_info), 321); | |
else | |
hash_key = make_rs_hash((char *)ipinfo, sizeof(struct espid_ip6_info), 321); | |
for (i = 0; i < 4; i++) { | |
unsigned int hash_index = hash_key % (CACHE_SIZE - 1); | |
if (tft_cache[hash_index].time != 0) { | |
if (hash_key == tft_cache[hash_index].hash_key) { | |
tft_cache[hash_index].time = CACHE_TIME; | |
toe_param->mcid = tft_cache[hash_index].cid; | |
toe_param->qfi = tft_cache[hash_index].qfi; | |
toe_param->pdu = tft_cache[hash_index].psi; | |
*h_index = hash_index; | |
*saved_key = hash_key_saved; | |
return true; | |
} else { | |
if (TFT_HASH_LOG_ENABLE) | |
{ | |
CM_Log(cm_get_toe_param_cache1320, "[TFT]!!!WARNNING!!! TFT cache not invailed(%d), hash key 0x%lx,0xlx ", | |
hit_cnt,dirty_cnt,hash_key,tft_cache[hash_index].hash_key); | |
CM_Log(cm_get_toe_param_cache1323, "dest ip 0x%lx, src 0x%lx, dest 0x%lx, proto 0x%lx",tft_cache[hash_index].ip, | |
tft_cache[hash_index].src_port, tft_cache[hash_index].dest_port,tft_cache[hash_index].proto); | |
} | |
hit_cnt++; | |
} | |
} | |
/*coverity[Negative array index read]*/ | |
else if (j == 0xffff/*-1*/) { | |
/* Store cache index for insert to catch*/ | |
j = hash_index; | |
hash_key_saved = hash_key; | |
} | |
if (ip_version == 4) | |
hash_key = make_rs_hash((char *)ipinfo, sizeof(struct espid_ip4_info), i + 1); | |
else | |
hash_key = make_rs_hash((char *)ipinfo, sizeof(struct espid_ip6_info), i + 1); | |
} | |
*h_index = j; | |
*saved_key = hash_key_saved; | |
return false; | |
#endif | |
} | |
static void cm_set_toe_param_cache(u8 ip_version, void *ipinfo, struct toe_tft_param *toe_param, unsigned int h_index, unsigned int hash_key) | |
{ | |
#ifdef ENHASH | |
/*coverity[Negative array index read]*/ | |
if (h_index != 0xffff/*-1*/) | |
{ | |
tft_cache[h_index].cid= toe_param->mcid; | |
tft_cache[h_index].qfi= toe_param->qfi; | |
tft_cache[h_index].psi= toe_param->pdu; | |
tft_cache[h_index].time = CACHE_TIME; | |
tft_cache[h_index].hash_key = hash_key; | |
dirty_cnt++; | |
if (ip_version == 4) | |
{ | |
struct espid_ip4_info *ip4info = (struct espid_ip4_info *)ipinfo; | |
tft_cache[h_index].dest_port = ip4info->dest_port; | |
tft_cache[h_index].src_port = ip4info->src_port; | |
tft_cache[h_index].ip = ip4info->dest_ip; | |
tft_cache[h_index].proto = ip4info->proto; | |
} | |
else | |
{ | |
struct espid_ip6_info *ip6info = (struct espid_ip6_info *)ipinfo; | |
tft_cache[h_index].dest_port = ip6info->dest_port; | |
tft_cache[h_index].src_port = ip6info->src_port; | |
tft_cache[h_index].ip = ip6info->dest_ip[0]; | |
tft_cache[h_index].proto = ip6info->proto; | |
} | |
CM_Log(cm_set_toe_param_cache1344, "[TFT] Insert to index [0x%lx], IP 0x%lx, src port 0x%lx, dest port 0x%lx, proto %lx, hash 0x%lx", h_index, | |
tft_cache[h_index].ip, tft_cache[h_index].src_port, tft_cache[h_index].dest_port, tft_cache[h_index].proto, tft_cache[h_index].hash_key); | |
} else { | |
CM_Log(cm_set_toe_param_cache1345, "[TFT]!!!FAILED!!!"); | |
} | |
#endif | |
} | |
bool cm_ctx_toe_tuple_qos_match(int cid, struct toe_tuple_list *tuple, struct toe_tft_param *toe_param) | |
{ | |
struct espid_ip4_info ip4info; | |
struct espid_ip6_info ip6info; | |
UINT8 sim2Flag; | |
UINT8 cid_backup; | |
int ret; | |
UINT8 *p_CurrentQoSTableItemCount; | |
#ifdef ENHASH | |
unsigned int hash_index = 0, hash_key_saved = 0; | |
#endif | |
CM_Connection_Context *ctx = CM_GetCtxListHead(); | |
sim2Flag = (cid & 0x80)? 1: 0; | |
if(sim2Flag) | |
{ | |
p_CurrentQoSTableItemCount = &CurrentQoSTableItemCount_1; | |
} | |
else | |
{ | |
p_CurrentQoSTableItemCount = &CurrentQoSTableItemCount; | |
} | |
cid_backup = cid; | |
cid = cid & 0x7F; | |
if (*p_CurrentQoSTableItemCount==0 || tuple->tuple.in_pkt == PDU_PKT) | |
{ | |
return cm_ctx_toe_tuple_match(cid, tuple); | |
} | |
ctx = CM_GetCtxListHead(); | |
while(ctx) | |
{ | |
if ((ctx->connectStatus == CM_CONNECT_CONSUCCESS ||ctx->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR) | |
&& (ctx->pdpinfo->primaryCid -1) == cid) | |
{ | |
if (ctx->pdpinfo->IP_Type == tuple->type ||ctx->pdpinfo->IP_Type == IPV4V6) | |
{ | |
if (tuple->type == IPV4) | |
{ | |
/* uplink */ | |
if (tuple->tuple.nat == 1 && tuple->tuple.out_pkt == PDU_PKT) | |
{ | |
ip4info.src_ip = tuple->tuple.nat_ip; | |
ip4info.src_port = tuple->tuple.nat_port; | |
} | |
else | |
{ | |
ip4info.src_ip = tuple->tuple.src_ip; | |
ip4info.src_port = tuple->tuple.src_port; | |
} | |
ip4info.dest_ip = tuple->tuple.dst_ip; | |
ip4info.dest_port = tuple->tuple.dst_port; | |
ip4info.proto = tuple->tuple.prot; | |
#ifdef ENHASH | |
if (cm_get_toe_param_cache(4, (void *)&ip4info, toe_param, &hash_index,&hash_key_saved) == true) | |
return true; | |
#endif | |
ret = SearchQoSNodeToFindToeParam((void*)&ip4info,4, cid_backup, toe_param); | |
CM_Log(cm_ctx_toe_tuple_qos_match1422, "%s: [IPV4] ret %d, cid 0x%lx, targetCid 0x%lx, qfi 0x%lx, psi 0x%lx", | |
__func__, ret,cid_backup,toe_param->mcid, toe_param->qfi, toe_param->pdu); | |
if (ret != 0) | |
{ | |
/*how to handle? TODO*/ | |
return false; | |
} | |
#ifdef ENHASH | |
cm_set_toe_param_cache(4, &ip4info, toe_param, hash_index, hash_key_saved); | |
#endif | |
return true; | |
} | |
else if (tuple->type == IPV6) | |
{ | |
memcpy(ip6info.src_ip, tuple->tuple.src_ip6, sizeof(ip6info.src_ip)); | |
memcpy(ip6info.dest_ip, tuple->tuple.dst_ip6, sizeof(ip6info.dest_ip)); | |
ip6info.src_port = tuple->tuple.src_port; | |
ip6info.dest_port = tuple->tuple.dst_port; | |
ip6info.proto = tuple->tuple.prot; | |
#ifdef ENHASH | |
if (cm_get_toe_param_cache(6, (void *)&ip6info, toe_param, &hash_index,&hash_key_saved) == true) | |
return true; | |
#endif | |
ret = SearchQoSNodeToFindToeParam((void*)&ip6info,6, cid_backup, toe_param); | |
CM_Log(cm_ctx_toe_tuple_qos_match1423, "%s: [IPV6] ret %d, cid 0x%lx, targetCid 0x%lx, qfi 0x%lx, psi 0x%lx", | |
__func__, ret,cid_backup,toe_param->mcid, toe_param->qfi, toe_param->pdu); | |
if (ret != 0) | |
{ | |
/*how to handle? TODO*/ | |
return false; | |
} | |
#ifdef ENHASH | |
cm_set_toe_param_cache(6, &ip6info, toe_param, hash_index, hash_key_saved); | |
#endif | |
return true; | |
} | |
} | |
} | |
ctx = ctx->next; | |
} | |
return false; | |
} | |
#endif |