blob: 33a7cbf7afe31819e13f7880a5f0b873f4c94b5c [file] [log] [blame]
#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