#include #include #include #include #include #include #include #include #include #include #include "debug_info.h" #include "log.h" #if defined(PLATFORM_MV78460) #include "mv_netdev.h" #elif defined(PLATFORM_P1010) #include "gianfar.h" #endif #include "hook.h" #define P1010_CPU_COUNT_PER_MS (50000) #define SEND_SEQ_POS (0x2C) #define RECV_SEQ_POS (SEND_SEQ_POS - 0x0E) static int DbgFS_RtpPortShow(struct seq_file* seq, void* token); static int DbgFS_GianfarSipPortShow(struct seq_file* seq, void* token); static int DbgFS_SipArpShow(struct seq_file* seq, void* token); static int DbgFS_NICCfgShow(struct seq_file* seq, void* token); static int DbgFS_EthIrqShow(struct seq_file* seq, void* token); static int DbgFS_EthIrqHelp(struct seq_file* seq, void* token); static int DbgFS_EthIrqIoctl(struct seq_file* seq, char* cmd, char* params); #ifdef PLATFORM_MV78460 static unsigned char g_spbxNetId = ETH_INTERFACE_2; #else static unsigned char g_spbxNetId = ETH_INTERFACE_0; #endif static PNIC_RCV_RTP_DATA g_pRcvRtpHook = NULL; static spinlock_t g_RegHookLock; PNIC_PRIVATE g_NICInfo[MAX_ETH_PORT]; typedef enum __DBGFS_ID { DBG_SIP_CH, DBG_SIP_ARP, DBG_RTP_PORT, DBG_NIC_CFG, DBG_ETH_IRQ, } DBGFS_ID; static DBGFS_PRIV g_DbgFSConfig[] = { { "sip_ch", 0, NULL, NULL, DbgFS_GianfarSipPortShow, NULL, NULL }, { "sip_arp", 0, NULL, NULL, DbgFS_SipArpShow, NULL, NULL }, { "rtp_port", 0, NULL, NULL, DbgFS_RtpPortShow, NULL, NULL }, { "nic_config", 0, NULL, NULL, DbgFS_NICCfgShow, NULL, NULL }, { "eth_irq", 0, NULL, NULL, DbgFS_EthIrqShow, DbgFS_EthIrqIoctl, DbgFS_EthIrqHelp }, }; int NIC_GetInfo(const char* pNIC, PNIC_INFO pInfo) { int iRet = 0; struct socket* sock; struct ifreq ifr; mm_segment_t oldCfg; struct net_device* dev; if(!pNIC || !pInfo) { LOG_EX(LOG_Error, "Input Params Error:%p, %p", pNIC, pInfo); return -1; } memset(pInfo, 0, sizeof(NIC_INFO)); memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, pNIC); iRet = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); if(iRet < 0 || NULL == sock) { LOG_EX(LOG_Error, "sock_create_kern Error:%d\n", iRet); return -1; } dev = dev_get_by_name(sock_net(sock->sk), pNIC); if(dev == NULL) { LOG_EX(LOG_Error, "dev_get_by_name Error\n"); return -1; } pInfo->devIfIndex = dev->ifindex; memcpy(pInfo->macAddr, dev->dev_addr, 6); oldCfg = get_fs(); set_fs(KERNEL_DS); if((iRet = inet_ioctl(sock, SIOCGIFADDR, (unsigned long)&ifr)) != 0) { LOG_EX(LOG_Error, "Get Ip Addr Error: %d\n", iRet); } pInfo->ipAddr = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr; if((iRet = inet_ioctl(sock, SIOCGIFBRDADDR, (unsigned long)&ifr)) != 0) { LOG_EX(LOG_Error, "Get Board Addr Error: %d\n", iRet); } pInfo->boardAddr = ((struct sockaddr_in*)&ifr.ifr_broadaddr)->sin_addr.s_addr; if((iRet = inet_ioctl(sock, SIOCGIFNETMASK, (unsigned long)&ifr)) != 0) { LOG_EX(LOG_Error, "Get Netmask Addr Error: %d\n", iRet); } pInfo->netMask = ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr; set_fs(oldCfg); sock_release(sock); return 0; } EXPORT_SYMBOL(NIC_GetInfo); int make_arp_request_ex(unsigned int ethId, __be32 dest_ip) { struct sk_buff* skb = NULL; NIC_INFO nicInfo; if(!IS_VALUABLED_ETH(ethId)) { return -1; } if(g_NICInfo[ethId] == NULL) { return -2; } if(g_NICInfo[ethId]->opened_ref == 0) { return -3; } memset(&nicInfo, 0, sizeof(NIC_INFO)); NIC_GetInfo(g_NICInfo[ethId]->ndev->name, &nicInfo); skb = arp_create(ARPOP_REQUEST, ETH_P_ARP, dest_ip, g_NICInfo[ethId]->ndev, nicInfo.ipAddr, NULL, nicInfo.macAddr, NULL); if(skb) { arp_xmit(skb); } else { return -3; } return 0; } EXPORT_SYMBOL(make_arp_request_ex); int make_arp_request(unsigned int ethId, __be32 dest_ip) { struct sk_buff* skb = NULL; if(!IS_VALUABLED_ETH(ethId)) { return -1; } if(g_NICInfo[ethId] == NULL) { return -2; } if(g_NICInfo[ethId]->opened_ref == 0) { return -3; } skb = arp_create(ARPOP_REQUEST, ETH_P_ARP, dest_ip, g_NICInfo[ethId]->ndev, g_NICInfo[ethId]->chIpAddr, NULL, g_NICInfo[ethId]->ndev->dev_addr, NULL); if(skb) { arp_xmit(skb); } return 0; } EXPORT_SYMBOL(make_arp_request); int get_eth_mac(unsigned char* haddr, ETH_INTERFACE ethId) { struct net_device* pDev = NULL; if(!IS_VALUABLED_ETH(ethId)) { return -1; } if(g_NICInfo[ethId] == NULL) { return -2; } if(g_NICInfo[ethId]->opened_ref == 0) { return -3; } if(haddr) { pDev = g_NICInfo[ethId]->ndev; memcpy(haddr, pDev->dev_addr, pDev->addr_len); return pDev->addr_len; } return 0; } EXPORT_SYMBOL(get_eth_mac); int get_mac_form_ip(unsigned char* haddr, ETH_INTERFACE ethId, __be32 ipaddr, int id) { struct neighbour* n; PNIC_PRIVATE pEthInfo = NULL; __be32 oldip = ipaddr; if(!IS_VALUABLED_ETH(ethId)) { return -1; } pEthInfo = g_NICInfo[ethId]; if(pEthInfo == NULL) { return -2; } if(id == 4 || id == 3) { printk("ethId = %d, ipaddr = 0x%08X\n", ethId, ipaddr); } //memset(haddr, 0xFF, ETH_ALEN); if(pEthInfo->chGWIpAddr != 0) { if((ntohl(ipaddr) & pEthInfo->chGWMask) != (pEthInfo->chIpAddr & pEthInfo->chGWMask)) { if(id == 4 || id == 3) { printk("ipaddr = 0x%08X, pEthInfo->chGWMask = 0x%08X, pEthInfo->chIpAddr = 0x%08X\n", ipaddr, pEthInfo->chGWMask, pEthInfo->chIpAddr); } ipaddr = pEthInfo->chGWIpAddr; } } if(id == 4 || id == 3) { printk("eth %d ipaddr 0x%08X get ip 0x%08X arp call by %d\n", ethId, oldip, ipaddr, id); } if(haddr != NULL) { n = __neigh_lookup(&arp_tbl, &ipaddr, pEthInfo->ndev, 1); if(n != NULL) { n->used = jiffies; if(n->nud_state & NUD_VALID) { memcpy(haddr, n->ha, pEthInfo->ndev->addr_len); neigh_release(n); return 0; } else { neigh_release(n); } } else if(id == 4 || id == 3) { printk("__neigh_lookup is null\n"); } } if(id == 4 || id == 3) { printk("eth %d ipaddr 0x%08X get ip 0x%08X arp call by %d Error\n", ethId, oldip, ipaddr, id); } return -1; } EXPORT_SYMBOL(get_mac_form_ip); unsigned short get_ip_checksum(unsigned short* buffer, int size) { unsigned long cksum = 0; while(size > 1) { cksum += *buffer++; size -= sizeof(unsigned short); } if(size) { cksum += *(unsigned short*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return (unsigned short)(~cksum); } EXPORT_SYMBOL(get_ip_checksum); #define RECV_RFC2833_RECV_NEW (0) #define RECV_RFC2833_RECV_REP (1) #define RECV_RFC2833_RECV_DROP (2) #define RECV_RFC2833_RECV_UNRECV (4) #define CHK_CH_STATUS (1 << 0) #define CHK_CH_DSTTARGET (1 << 1) #define CHK_CH_NEEDSWITCH (1 << 2) #define CHK_CH_SWITCH_OK (1 << 3) #define CHK_CH_SWITCH_ERR (1 << 4) #define CHK_CH_RFC2833 (1 << 5) #define CHK_CH_NEEDSWITCH_SAMEBOARD (1 << 6) #define CHK_CH_RECVUDP (1 << 7) #define CHK_CH_DROP_WAITARP (1 << 8) static SIP_CH_INFO g_SIPChInfo; static int g_DebugRFC2833 = 0; static int g_CheckRFC2833 = 0; static SIP_CH_DETIAL g_SIPDetial[MAX_SIP_CH]; const char g_DTMFTable[17] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', 'A', 'B', 'C', 'D', 'F' // Flash }; static struct sk_buff* switch_to_sip(int sipCh, struct sk_buff* skb, ETH_INTERFACE ethId, PCH_PORT_INFO pPort); static int CheckMacAddress(PCH_PORT_INFO pPort, ETH_INTERFACE ethId); static int DbgFS_SipArpShow(struct seq_file* seq, void* token) { unsigned int opt = g_DbgFSConfig[DBG_SIP_ARP].params; unsigned char mac[12]; int ret, i = 0; if(token == SEQ_START_TOKEN) { for(i = 0; i < 3; i++) { if(g_NICInfo[i] != NULL) { ret = get_mac_form_ip(mac, i, htonl(g_NICInfo[i]->chGWIpAddr), 2); seq_printf(seq, "eth %d request arp %d.%d.%d.%d is %02X:%02X:%02X:%02X:%02X:%02X ret %d\n", g_NICInfo[i]->port, (g_NICInfo[i]->chGWIpAddr >> 24) & 0xFF, (g_NICInfo[i]->chGWIpAddr >> 16) & 0xFF, (g_NICInfo[i]->chGWIpAddr >> 8) & 0xFF, g_NICInfo[i]->chGWIpAddr & 0xFF, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ret); } } if(opt >= 0 && opt < g_SIPChInfo.iTotalCh) { PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + opt; seq_printf(seq, "pCh->portB2B.chStatus = %d, pCh->portB2B.chStatus = %d\n", pCh->portB2B.chStatus, pCh->portRTP.chStatus); if(pCh->portB2B.chStatus == 2) { ret = get_mac_form_ip(mac, 0, htonl(pCh->portB2B.chLinkInfo.dstTarget.ipAddr), 3); seq_printf(seq, "eth %d request arp %d.%d.%d.%d is %02X:%02X:%02X:%02X:%02X:%02X ret %d\n", 0, (pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 24) & 0xFF, (pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 16) & 0xFF, (pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 8) & 0xFF, pCh->portB2B.chLinkInfo.dstTarget.ipAddr & 0xFF, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ret); } if(pCh->portRTP.chStatus == 2) { ret = get_mac_form_ip(mac, pCh->sipETHId, htonl(pCh->portRTP.chLinkInfo.dstTarget.ipAddr), 4); seq_printf(seq, "eth %d request arp %d.%d.%d.%d is %02X:%02X:%02X:%02X:%02X:%02X ret %d\n", pCh->sipETHId, (pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 24) & 0xFF, (pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 16) & 0xFF, (pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 8) & 0xFF, pCh->portRTP.chLinkInfo.dstTarget.ipAddr & 0xFF, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ret); } } else { seq_printf(seq, "opt = %d\n", opt); } } return 0; } static int DbgFS_GianfarSipPortShow(struct seq_file* seq, void* token) { unsigned int opt = g_DbgFSConfig[DBG_SIP_CH].params; int i = 0; if(token == SEQ_START_TOKEN) { if(opt == 1) { seq_printf(seq, "g_DebugRFC2833 Off\n"); g_DebugRFC2833 = 0; } else if(opt == 2) { seq_printf(seq, "g_DebugRFC2833 On\n"); g_DebugRFC2833 = 1; } else if(opt == 3) { seq_printf(seq, "g_CheckRFC2833 Off\n"); g_CheckRFC2833 = 0; } else if(opt == 4) { seq_printf(seq, "g_CheckRFC2833 On\n"); g_CheckRFC2833 = 1; } else if(opt == 5) { seq_printf(seq, "g_CheckRFC2833 Clean\n"); for(i = 0; i < g_SIPChInfo.iTotalCh; i++) { g_SIPChInfo.pSipChDetial[i].sipDebug.ethx_rfc2833_error = 0; } } else { seq_printf(seq, "g_CheckRFC2833 = %d, g_DebugRFC2833 = %d\n", g_CheckRFC2833, g_DebugRFC2833); } seq_printf(seq, "SPI Info:\n"); for(i = 0; i < 3; i++) { if(g_NICInfo[i] != NULL) { seq_printf(seq, "ucc=%p, index=%d ipaddr=%d.%d.%d.%d gw=%d.%d.%d.%d gw mask=%d.%d.%d.%d\n", g_NICInfo[i], g_NICInfo[i]->port, (g_NICInfo[i]->chIpAddr >> 24) & 0xFF, (g_NICInfo[i]->chIpAddr >> 16) & 0xFF, (g_NICInfo[i]->chIpAddr >> 8) & 0xFF, g_NICInfo[i]->chIpAddr & 0xFF, (g_NICInfo[i]->chGWIpAddr >> 24) & 0xFF, (g_NICInfo[i]->chGWIpAddr >> 16) & 0xFF, (g_NICInfo[i]->chGWIpAddr >> 8) & 0xFF, g_NICInfo[i]->chGWIpAddr & 0xFF, (g_NICInfo[i]->chGWMask >> 24) & 0xFF, (g_NICInfo[i]->chGWMask >> 16) & 0xFF, (g_NICInfo[i]->chGWMask >> 8) & 0xFF, g_NICInfo[i]->chGWMask & 0xFF); } } seq_printf(seq, "Total Ch: %d\n", g_SIPChInfo.iTotalCh); seq_printf(seq, "Port Base: %d\n", g_SIPChInfo.iPortBase); seq_printf(seq, "Port Step: %d\n", g_SIPChInfo.iPortStep); seq_printf(seq, "RTP Port Base: %d\n", g_SIPChInfo.iRTPPortBase); for(i = 0; i < g_SIPChInfo.iTotalCh; i++) { PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + i; if(pCh->portB2B.chStatus != 2 && pCh->portRTP.chStatus != 2) { continue; } seq_printf(seq, "++++++++++++++++Ch %d Info+++++++++++++\n", i); seq_printf(seq, "B2B Status: %d\n", pCh->portB2B.chStatus); seq_printf(seq, "B2B IP Port: %d\n", pCh->portB2B.ipPort); seq_printf(seq, "B2B Link IP: %d.%d.%d.%d\n", (pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 24) & 0xFF, (pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 16) & 0xFF, (pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 8) & 0xFF, pCh->portB2B.chLinkInfo.dstTarget.ipAddr & 0xFF); seq_printf(seq, "B2B Link Port: %d\n", pCh->portB2B.chLinkInfo.dstTarget.ipPort); seq_printf(seq, "B2B Link Mac: %02X:%02X:%02X:%02X:%02X:%02X\n\n", pCh->portB2B.chLinkInfo.dstTarget.ethAddr[0], pCh->portB2B.chLinkInfo.dstTarget.ethAddr[1], pCh->portB2B.chLinkInfo.dstTarget.ethAddr[2], pCh->portB2B.chLinkInfo.dstTarget.ethAddr[3], pCh->portB2B.chLinkInfo.dstTarget.ethAddr[4], pCh->portB2B.chLinkInfo.dstTarget.ethAddr[5]); seq_printf(seq, "RTP Status: %d\n", pCh->portRTP.chStatus); seq_printf(seq, "RTP ETH: %d\n", pCh->sipETHId); seq_printf(seq, "RTP IP Port: %d\n", pCh->portRTP.ipPort); seq_printf(seq, "RTP Link IP: %d.%d.%d.%d\n", (pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 24) & 0xFF, (pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 16) & 0xFF, (pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 8) & 0xFF, pCh->portRTP.chLinkInfo.dstTarget.ipAddr & 0xFF); seq_printf(seq, "RTP Link Port: %d\n", pCh->portRTP.chLinkInfo.dstTarget.ipPort); seq_printf(seq, "RTP Link Mac: %02X:%02X:%02X:%02X:%02X:%02X\n\n", pCh->portRTP.chLinkInfo.dstTarget.ethAddr[0], pCh->portRTP.chLinkInfo.dstTarget.ethAddr[1], pCh->portRTP.chLinkInfo.dstTarget.ethAddr[2], pCh->portRTP.chLinkInfo.dstTarget.ethAddr[3], pCh->portRTP.chLinkInfo.dstTarget.ethAddr[4], pCh->portRTP.chLinkInfo.dstTarget.ethAddr[5]); seq_printf(seq, "RTP Stun Tag: %d\n", pCh->portRTP.chLinkInfo.stunTags); seq_printf(seq, "ETH(spbx) Recv: %d\n", pCh->sipDebug.cnt_eth0_recv); seq_printf(seq, "ETH(spbx) Switch: %d\n", pCh->sipDebug.cnt_eth0_2_ethx); seq_printf(seq, "ETH(spbx) Mask: 0x%08X\n", pCh->sipDebug.mask_eth0_2_ethx); seq_printf(seq, "ETH(spbx) lost: %d\n", pCh->sipDebug.eth0_seq_error); seq_printf(seq, "ETH(spbx) drop: %d\n\n", pCh->sipDebug.eth0_drop_src); seq_printf(seq, "ETH(sip) Recv: %d\n", pCh->sipDebug.cnt_ethx_recv); seq_printf(seq, "ETH(sip) Switch: %d\n", pCh->sipDebug.cnt_ethx_2_eth0); seq_printf(seq, "ETH(sip) Mask: 0x%08X\n", pCh->sipDebug.mask_ethx_2_eth0); seq_printf(seq, "ETH(sip) lost: %d\n", pCh->sipDebug.ethx_seq_error); seq_printf(seq, "ETH(sip) drop: %d\n\n", pCh->sipDebug.ethx_drop_src); if(g_CheckRFC2833) { seq_printf(seq, "ETH(sip) Error Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_error); seq_printf(seq, "ETH(sip) Drv Err Dtmf: %d\n", pCh->sipDebug.drv_rcv_rfc2833_error); } seq_printf(seq, "ETH(sip) Rcv Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_recv); seq_printf(seq, "ETH(sip) Rcv lost Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_rcv_lost); seq_printf(seq, "ETH(sip) Snd lost Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_snd_lost); seq_printf(seq, "ETH(sip) Drv Rcv Dtmf: %d\n\n", pCh->sipDebug.drv_rcv_rfc2833_recv); } } return 0; } static char GetDTMFValue(char dtmf) { switch(dtmf) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; case '*': return 10; case '#': return 11; case 'A': case 'a': return 12; case 'B': case 'b': return 13; case 'C': case 'c': return 14; case 'D': case 'd': return 15; case 'F': case 'f': return 16; } return -1; } static void InitIPAddrInfo(PIP_ADDR_INFO pAddrInfo) { if(pAddrInfo) { memset(pAddrInfo->ethAddr, 0xFF, ETH_ALEN); pAddrInfo->ipAddr = 0; pAddrInfo->ipPort = -1; } } static void InitChDTMFRecvInfoBuf(PCH_DTMF_INFO pChDtmf, int i) { pChDtmf->dtmfRecvBuf[i].refStatus = RFC2833_RECV_IDLE; pChDtmf->dtmfRecvBuf[i].dtmfValue = 0xFF; pChDtmf->dtmfRecvBuf[i].refCount = 0; pChDtmf->dtmfRecvBuf[i].synIdentifier = 0; pChDtmf->dtmfRecvBuf[i].timeStamps = 0; pChDtmf->dtmfRecvBuf[i].seqNumber = 0; pChDtmf->dtmfRecvBuf[i].payloadType = 0xFF; } static void InitChDTMFRecvInfo(PCH_DTMF_INFO pChDtmf) { int i = 0; for(i = 0; i < MAX_DTMF_RECV_BUF; i++) { // pChDtmf->dtmfRecvValue[i] = 0xFF; pChDtmf->dtmfRecvBuf[i].refStatus = RFC2833_RECV_IDLE; pChDtmf->dtmfRecvBuf[i].dtmfValue = 0xFF; pChDtmf->dtmfRecvBuf[i].refCount = 0; pChDtmf->dtmfRecvBuf[i].synIdentifier = 0; pChDtmf->dtmfRecvBuf[i].timeStamps = 0; pChDtmf->dtmfRecvBuf[i].seqNumber = 0; pChDtmf->dtmfRecvBuf[i].payloadType = 0xFF; } } static void InitChDTMFInfo(PCH_DTMF_INFO pChDtmf) { if(pChDtmf) { pChDtmf->refSendMask = 0; pChDtmf->drvRfc2833ChkVal = 0; pChDtmf->nicRfc2833ChkVal = 0; pChDtmf->dtmfSendBuf.dtmfValue = 0xFF; pChDtmf->dtmfSendBuf.refCount = 7; pChDtmf->dtmfSendBuf.refStatus = RFC2833_SEND_IDLE; pChDtmf->dtmfSendBuf.synIdentifier = 0; pChDtmf->dtmfSendBuf.timeStamps = 0; pChDtmf->dtmfSendBuf.payloadType = 101; pChDtmf->curSendIndex = -1; pChDtmf->srcIp = 0; pChDtmf->srcPort = 0; InitChDTMFRecvInfo(pChDtmf); } } static void InitChPortInfo(PCH_PORT_INFO pPort, PORT_TYPE portType) { if(pPort) { pPort->portType = portType; pPort->ipPort = -1; pPort->chStatus = CH_STATUS_UNKONWN; pPort->chLinkInfo.linkCh = -1; } } static void InitSIPChDetial(PSIP_CH_DETIAL pCh) { int rlt = 0; if(pCh) { memset(pCh, 0, sizeof(SIP_CH_DETIAL)); pCh->chId = -1; pCh->sipETHId = -1; InitChPortInfo(&pCh->portB2B, PORT_TYPE_B2B); InitChPortInfo(&pCh->portIPR, PORT_TYPE_IPR); InitChPortInfo(&pCh->portT38, PORT_TYPE_T38); InitChPortInfo(&pCh->portRTP, PORT_TYPE_SIPRTP); InitChDTMFInfo(&pCh->rfc2833DTMF); kfifo_free(&pCh->dtmfSendFifo); rlt = kfifo_alloc(&pCh->dtmfSendFifo, MAX_DTMF_SEND_BUF, GFP_KERNEL); kfifo_free(&pCh->dtmfRecvFifo); rlt = kfifo_alloc(&pCh->dtmfRecvFifo, MAX_DTMF_RECV_BUF * 4, GFP_KERNEL); } } int config_sip_ch(unsigned int maxSIPCh, unsigned int portBase, unsigned int portStep, unsigned int rtpPortBase) { int i = 0; if(maxSIPCh > MAX_SIP_CH) { maxSIPCh = MAX_SIP_CH; } if(maxSIPCh > 0) { for(i = 0; i < maxSIPCh; i++) { InitSIPChDetial(&g_SIPChInfo.pSipChDetial[i]); g_SIPChInfo.pSipChDetial[i].sipDebug.ethx_rfc2833_error = 0; } g_SIPChInfo.iTotalCh = maxSIPCh; g_SIPChInfo.iPortBase = portBase; g_SIPChInfo.iPortStep = portStep; g_SIPChInfo.iRTPPortBase = rtpPortBase; return 0; } return -1; } EXPORT_SYMBOL(config_sip_ch); int config_sip_port(unsigned int chId, unsigned int ethId, unsigned short chPort, unsigned short sipChPort) { if(ethId == g_spbxNetId) { return -1; } if(g_NICInfo[ethId] == NULL) { return -2; } if(g_SIPChInfo.pSipChDetial != NULL && chId < g_SIPChInfo.iTotalCh) { PSIP_CH_DETIAL pChDetail = g_SIPChInfo.pSipChDetial + chId; pChDetail->chId = chId; pChDetail->sipETHId = ethId; pChDetail->portIPR.ipPort = chPort + 0; pChDetail->portB2B.ipPort = chPort + 1; pChDetail->portT38.ipPort = chPort + 2; pChDetail->portRTP.ipPort = sipChPort; pChDetail->portIPR.chStatus = CH_STATUS_CONFIGUREED; pChDetail->portB2B.chStatus = CH_STATUS_CONFIGUREED; pChDetail->portT38.chStatus = CH_STATUS_CONFIGUREED; pChDetail->portRTP.chStatus = CH_STATUS_CONFIGUREED; return 0; } return -1; } EXPORT_SYMBOL(config_sip_port); int eth_sip_link(unsigned int sipCh, __be32 dst_ipAddr, __be16 dst_ipPort, __be16 stun_tags) { PSIP_CH_DETIAL pCh = NULL; unsigned char macAddr[24]; if(g_SIPChInfo.pSipChDetial == NULL || sipCh >= g_SIPChInfo.iTotalCh) { return -1; } pCh = &g_SIPChInfo.pSipChDetial[sipCh]; if(g_NICInfo[pCh->sipETHId] == NULL) { return -2; } if(g_NICInfo[pCh->sipETHId]->opened_ref == 0) { return -3; } if(pCh->portRTP.chStatus == CH_STATUS_UNKONWN) { return -1; } make_arp_request(pCh->sipETHId, htonl(dst_ipAddr)); get_mac_form_ip(macAddr, pCh->sipETHId, htonl(dst_ipAddr), 21); memset(pCh->portRTP.chLinkInfo.dstTarget.ethAddr, 0xFF, ETH_ALEN); pCh->portRTP.chLinkInfo.dstTarget.ipAddr = dst_ipAddr; pCh->portRTP.chLinkInfo.dstTarget.ipPort = dst_ipPort; pCh->portRTP.chLinkInfo.toRTPCh.isUpdate = 0; pCh->portRTP.chLinkInfo.fromRTPCh.isUpdate = 0; pCh->portRTP.chLinkInfo.stunTags = stun_tags; pCh->portRTP.chStatus = CH_STATUS_LINKED; pCh->sipDebug.cnt_ethx_recv = 0; pCh->sipDebug.cnt_ethx_2_eth0 = 0; pCh->sipDebug.mask_ethx_2_eth0 = 0; pCh->sipDebug.ethx_seq_index = 0; pCh->sipDebug.ethx_seq_error = 0; return 0; } EXPORT_SYMBOL(eth_sip_link); int eth_link(unsigned int chId, PORT_TYPE portType, __be32 dst_ipAddr, __be16 dst_ipPort) { PSIP_CH_DETIAL pCh = NULL; unsigned char macAddr[24]; if(g_SIPChInfo.pSipChDetial == NULL || chId >= g_SIPChInfo.iTotalCh) { return -1; } pCh = &g_SIPChInfo.pSipChDetial[chId]; if(g_NICInfo[pCh->sipETHId] == NULL) { return -2; } if(g_NICInfo[pCh->sipETHId]->opened_ref == 0) { return -3; } make_arp_request(g_spbxNetId, htonl(dst_ipAddr)); get_mac_form_ip(macAddr, g_spbxNetId, htonl(dst_ipAddr), 20); if(portType == PORT_TYPE_B2B) { memset(pCh->portB2B.chLinkInfo.dstTarget.ethAddr, 0xFF, ETH_ALEN); pCh->portB2B.chLinkInfo.dstTarget.ipAddr = dst_ipAddr; pCh->portB2B.chLinkInfo.dstTarget.ipPort = dst_ipPort; pCh->portB2B.chLinkInfo.toRTPCh.isUpdate = 0; pCh->portB2B.chLinkInfo.fromRTPCh.isUpdate = 0; pCh->portB2B.chStatus = CH_STATUS_LINKED; } else if(portType == PORT_TYPE_IPR) { memset(pCh->portIPR.chLinkInfo.dstTarget.ethAddr, 0xFF, ETH_ALEN); pCh->portIPR.chLinkInfo.dstTarget.ipAddr = dst_ipAddr; pCh->portIPR.chLinkInfo.dstTarget.ipPort = dst_ipPort; pCh->portIPR.chLinkInfo.toRTPCh.isUpdate = 0; pCh->portIPR.chLinkInfo.fromRTPCh.isUpdate = 0; pCh->portIPR.chStatus = CH_STATUS_LINKED; } else if(portType == PORT_TYPE_T38) { memset(pCh->portT38.chLinkInfo.dstTarget.ethAddr, 0xFF, ETH_ALEN); pCh->portT38.chLinkInfo.dstTarget.ipAddr = dst_ipAddr; pCh->portT38.chLinkInfo.dstTarget.ipPort = dst_ipPort; pCh->portT38.chLinkInfo.toRTPCh.isUpdate = 0; pCh->portT38.chLinkInfo.fromRTPCh.isUpdate = 0; pCh->portT38.chStatus = CH_STATUS_LINKED; } kfifo_reset(&pCh->dtmfSendFifo); kfifo_reset(&pCh->dtmfRecvFifo); InitChDTMFInfo(&pCh->rfc2833DTMF); pCh->sipDebug.cnt_eth0_2_ethx = 0; pCh->sipDebug.cnt_eth0_recv = 0; pCh->sipDebug.mask_eth0_2_ethx = 0; pCh->sipDebug.eth0_seq_index = 0; pCh->sipDebug.eth0_seq_error = 0; return 0; } EXPORT_SYMBOL(eth_link); static void InitSIPLinkReset(PCH_PORT_INFO pPort) { if(pPort) { pPort->chStatus = CH_STATUS_IDLE; pPort->chLinkInfo.linkCh = -1; InitIPAddrInfo(&pPort->chLinkInfo.dstTarget); pPort->chLinkInfo.fromRTPCh.isUpdate = 0; pPort->chLinkInfo.toRTPCh.isUpdate = 0; pPort->chLinkInfo.stunTags = 0; memset(&pPort->chLinkInfo.fromRTPCh.headValue, 0, sizeof(PACKAGE_HEAD)); memset(&pPort->chLinkInfo.toRTPCh.headValue, 0, sizeof(PACKAGE_HEAD)); memset(pPort->chLinkInfo.dstTarget.ethAddr, 0xFF, 6); } } int eth_unlink(unsigned int chId, int portType) { PSIP_CH_DETIAL pCh = NULL; if(g_SIPChInfo.pSipChDetial == NULL || chId >= g_SIPChInfo.iTotalCh) { return -1; } pCh = &g_SIPChInfo.pSipChDetial[chId]; switch(portType) { case PORT_TYPE_IPR: if(pCh->portIPR.chStatus == CH_STATUS_LINKED) { InitSIPLinkReset(&pCh->portIPR); } break; case PORT_TYPE_B2B: if(pCh->portB2B.chStatus == CH_STATUS_LINKED) { InitSIPLinkReset(&pCh->portB2B); } break; case PORT_TYPE_T38: if(pCh->portT38.chStatus == CH_STATUS_LINKED) { InitSIPLinkReset(&pCh->portT38); } break; case PORT_TYPE_SIPRTP: if(pCh->portRTP.chStatus == CH_STATUS_LINKED) { InitSIPLinkReset(&pCh->portRTP); } break; } kfifo_reset(&pCh->dtmfSendFifo); kfifo_reset(&pCh->dtmfRecvFifo); InitChDTMFInfo(&pCh->rfc2833DTMF); return 0; } EXPORT_SYMBOL(eth_unlink); int sip_recv_dtmf(unsigned int sipCh) { char value = -1, rlt = 0; PSIP_CH_DETIAL pCh = NULL; if(g_SIPChInfo.pSipChDetial == NULL || sipCh >= g_SIPChInfo.iTotalCh) { return -1; } pCh = &g_SIPChInfo.pSipChDetial[sipCh]; if(pCh->portRTP.chStatus != CH_STATUS_LINKED) { return -1; } #ifdef PLATFORM_MV78460 rlt = kfifo_get(&pCh->dtmfRecvFifo, &value); if(rlt != 0) #else rlt = kfifo_out(&pCh->dtmfRecvFifo, &value, 4); if(rlt == 4) #endif { if(g_CheckRFC2833) { if(pCh->rfc2833DTMF.drvRfc2833ChkVal != value) { pCh->sipDebug.drv_rcv_rfc2833_error++; if(sipCh == 0 && g_DebugRFC2833 != 0) { printk("ch %d rcv 2833 Error: rcv %d need %d\n", sipCh, value, pCh->rfc2833DTMF.drvRfc2833ChkVal); } } if(value == 11) { pCh->rfc2833DTMF.drvRfc2833ChkVal = 0; } else { pCh->rfc2833DTMF.drvRfc2833ChkVal++; } } pCh->sipDebug.drv_rcv_rfc2833_recv++; return (int)g_DTMFTable[value & 0x0F]; } else { return -1; } } EXPORT_SYMBOL(sip_recv_dtmf); int sip_send_dtmf(unsigned int sipCh, char* pDtmfChar, int numChars) { int i = 0; PSIP_CH_DETIAL pCh = NULL; if(g_SIPChInfo.pSipChDetial == NULL || sipCh >= g_SIPChInfo.iTotalCh || numChars > MAX_DTMF_SEND_BUF) { return -1; } if(pDtmfChar == NULL) { if(kfifo_is_empty(&pCh->dtmfSendFifo)) { return 0; } else { return kfifo_len(&pCh->dtmfSendFifo); } } pCh = &g_SIPChInfo.pSipChDetial[sipCh]; pCh->rfc2833DTMF.dtmfSendBuf.refStatus = RFC2833_SEND_IDLE; //kfifo_reset(&pCh->dtmfSendFifo); // GetDTMFValue for(i = 0; i < numChars; i++) { char dtmf = GetDTMFValue(pDtmfChar[i]); #ifdef PLATFORM_MV78460 if(kfifo_put(&pCh->dtmfSendFifo, &dtmf) == 0) #else if(kfifo_in(&pCh->dtmfSendFifo, &dtmf, 1) != 1) #endif { pCh->sipDebug.ethx_rfc2833_snd_lost++; return -1; } } return i; } EXPORT_SYMBOL(sip_send_dtmf); static int recv_dtmf_from_sip(int sipCh, struct sk_buff* skb) { unsigned short seqNumber; unsigned int timeStamp, syncId; unsigned char dtmfIndex; unsigned char endFlag; int i = 0; int bRecved = RECV_RFC2833_RECV_UNRECV; struct iphdr* iphdr = (struct iphdr*)skb->data; struct udphdr* udphdr = (struct udphdr*)(skb->data + iphdr->ihl * 4); PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + sipCh; if(pCh->portRTP.chLinkInfo.stunTags != 0) { dtmfIndex = *(unsigned char*)(skb->data + 40 + 4); endFlag = *(unsigned char*)(skb->data + 41 + 4); seqNumber = ntohs(*(unsigned short*)(skb->data + 30 + 4)); timeStamp = ntohl(*(unsigned int*)(skb->data + 32 + 4)); syncId = ntohl(*(unsigned int*)(skb->data + 36 + 4)); } else { dtmfIndex = *(unsigned char*)(skb->data + 40); endFlag = *(unsigned char*)(skb->data + 41); seqNumber = ntohs(*(unsigned short*)(skb->data + 30)); timeStamp = ntohl(*(unsigned int*)(skb->data + 32)); syncId = ntohl(*(unsigned int*)(skb->data + 36)); } // ?????RFC2833 for(i = 0; i < MAX_DTMF_RECV_BUF; i++) { if(pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus != RFC2833_RECV_IDLE && pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber != 0) { if(pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber + 1000 < seqNumber || (endFlag & 0x80)) { InitChDTMFRecvInfoBuf(&pCh->rfc2833DTMF, i); } } // 收到结束标记的清理 if(pCh->rfc2833DTMF.dtmfRecvBuf[i].synIdentifier == syncId && (endFlag & 0x80)) { InitChDTMFRecvInfoBuf(&pCh->rfc2833DTMF, i); return RECV_RFC2833_RECV_DROP; } } for(i = 0; i < MAX_DTMF_RECV_BUF; i++) { // 同一个DTMF if(pCh->rfc2833DTMF.dtmfRecvBuf[i].synIdentifier == syncId && pCh->rfc2833DTMF.dtmfRecvBuf[i].timeStamps == timeStamp && abs(seqNumber - pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber) < 100 ) { if(pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus == RFC2833_RECVING) { if(pCh->rfc2833DTMF.dtmfRecvBuf[i].dtmfValue == dtmfIndex) { pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber = seqNumber; pCh->rfc2833DTMF.dtmfRecvBuf[i].refCount++; bRecved = RECV_RFC2833_RECV_REP; if((pCh->rfc2833DTMF.dtmfRecvBuf[i].refCount >= 2) && (pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus != RFC2833_RECV_LOCK)) { #ifdef PLATFORM_MV78460 if(kfifo_put(&pCh->dtmfRecvFifo, &dtmfIndex) == 0) #else if(kfifo_in(&pCh->dtmfRecvFifo, &dtmfIndex, 4) != 4) #endif { printk("ch %d RFC2833 FIFO Full, lost dtmf %c(%d)\n", sipCh, g_DTMFTable[dtmfIndex], dtmfIndex); pCh->sipDebug.ethx_rfc2833_rcv_lost++; } pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus = RFC2833_RECV_LOCK; pCh->sipDebug.ethx_rfc2833_recv++; if(sipCh == 0 && g_DebugRFC2833 != 0) { printk("ch %d recv rfc2833 %c(%d) ssrc = 0x%08X time = 0x%08X seq = %d \ ip = 0x%08X, Port = %d, dstip = 0x%08X, dstPort = %d, len = %d \ link_ip = 0x%08X, link_port = %d\n", sipCh, g_DTMFTable[dtmfIndex], dtmfIndex, syncId, timeStamp, seqNumber, iphdr->saddr, udphdr->source, iphdr->daddr, udphdr->dest, iphdr->tot_len, pCh->portRTP.chLinkInfo.dstTarget.ipAddr, pCh->portRTP.chLinkInfo.dstTarget.ipPort); } if(g_CheckRFC2833) { if(pCh->rfc2833DTMF.nicRfc2833ChkVal != dtmfIndex) { pCh->sipDebug.ethx_rfc2833_error++; if(sipCh == 0 && g_DebugRFC2833 != 0) { printk("ch %d array %d rcv 2833 Error: rcv %d need %d, \ ip = 0x%08X, Port = %d, srcip = 0x%08X, srcPort = %d, \ link_ip = 0x%08X, link_port = %d\ ssrc = 0x%08X time = 0x%08X seq = %d\n", sipCh, i, dtmfIndex, pCh->rfc2833DTMF.nicRfc2833ChkVal, iphdr->saddr, udphdr->source, pCh->rfc2833DTMF.srcIp, pCh->rfc2833DTMF.srcPort, pCh->portRTP.chLinkInfo.dstTarget.ipAddr, pCh->portRTP.chLinkInfo.dstTarget.ipPort, syncId, timeStamp, seqNumber); } } if(pCh->rfc2833DTMF.nicRfc2833ChkVal == 11) { pCh->rfc2833DTMF.nicRfc2833ChkVal = 0; } else { pCh->rfc2833DTMF.nicRfc2833ChkVal++; } } } } else { bRecved = RECV_RFC2833_RECV_DROP; } } else { bRecved = RECV_RFC2833_RECV_DROP; } break; } } if(bRecved == RECV_RFC2833_RECV_UNRECV) { for(i = 0; i < MAX_DTMF_RECV_BUF; i++) { if(pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus == RFC2833_RECV_IDLE && (endFlag & 0x80) == 0) { InitChDTMFRecvInfoBuf(&pCh->rfc2833DTMF, i); pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber = seqNumber; pCh->rfc2833DTMF.dtmfRecvBuf[i].synIdentifier = syncId; pCh->rfc2833DTMF.dtmfRecvBuf[i].timeStamps = timeStamp; pCh->rfc2833DTMF.srcIp = iphdr->saddr; pCh->rfc2833DTMF.srcPort = udphdr->source; pCh->rfc2833DTMF.dtmfRecvBuf[i].dtmfValue = dtmfIndex; pCh->rfc2833DTMF.dtmfRecvBuf[i].refCount = 1; pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus = RFC2833_RECVING; bRecved = RECV_RFC2833_RECV_NEW; break; } } } return bRecved; } static int CheckMacAddress(PCH_PORT_INFO pPort, ETH_INTERFACE ethId) { if(pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF ) { return get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr, ethId, htonl(pPort->chLinkInfo.dstTarget.ipAddr), 30); } return 0; } static struct sk_buff* switch_to_sip(int sipCh, struct sk_buff* skb, ETH_INTERFACE ethId, PCH_PORT_INFO pPort) { PPACKAGE_HEAD pHead = NULL; PRFC2833_INFO pDTMF = NULL; unsigned char* pPayload = NULL; PSIP_CH_DETIAL pCh = &g_SIPChInfo.pSipChDetial[sipCh]; struct sk_buff* skbSIP = skb_clone(skb, GFP_ATOMIC); PNIC_PRIVATE pEthInfo = g_NICInfo[ethId]; if(skbSIP == NULL) { return NULL; } dev_kfree_skb_any(skb); skbSIP->dev = pEthInfo->ndev; eth_header(skbSIP, pEthInfo->ndev, ETH_P_IP, NULL, NULL, skbSIP->len); pHead = (PPACKAGE_HEAD)skbSIP->data; if(pPort->chLinkInfo.toRTPCh.isUpdate == 0) { if(pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF ) { get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr, ethId, htonl(pPort->chLinkInfo.dstTarget.ipAddr), 5); } memcpy(pHead->ethHead.h_dest, pPort->chLinkInfo.dstTarget.ethAddr, ETH_ALEN); pHead->ipHead.saddr = htonl(pEthInfo->chIpAddr); pHead->ipHead.daddr = htonl(pPort->chLinkInfo.dstTarget.ipAddr); pHead->udpHead.source = htons(g_SIPChInfo.iRTPPortBase + sipCh); pHead->udpHead.dest = htons(pPort->chLinkInfo.dstTarget.ipPort); memcpy(&pPort->chLinkInfo.toRTPCh.headValue, pHead, sizeof(PACKAGE_HEAD)); pPort->chLinkInfo.toRTPCh.isUpdate = 1; } else { PACKAGE_HEAD ipHead = *pHead; if((pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF) || pCh->sipDebug.cnt_eth0_2_ethx % 1000 == 0 ) { if(get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr, ethId, htonl(pPort->chLinkInfo.dstTarget.ipAddr), 6) == 0) { memcpy(&pPort->chLinkInfo.toRTPCh.headValue, pPort->chLinkInfo.dstTarget.ethAddr, ETH_ALEN); } } memcpy(pHead, &pPort->chLinkInfo.toRTPCh.headValue, sizeof(PACKAGE_HEAD)); pHead->ipHead.id = ipHead.ipHead.id; pHead->ipHead.frag_off = ipHead.ipHead.frag_off; pHead->ipHead.tot_len = ipHead.ipHead.tot_len; pHead->udpHead.len = ipHead.udpHead.len; } if(!kfifo_is_empty(&pCh->dtmfSendFifo)) { if(pCh->rfc2833DTMF.dtmfSendBuf.refStatus == RFC2833_SEND_IDLE) { #ifdef PLATFORM_MV78460 int rlt = kfifo_get(&pCh->dtmfSendFifo, &pCh->rfc2833DTMF.dtmfSendBuf.dtmfValue); if(rlt != 0) #else int rlt = kfifo_out(&pCh->dtmfSendFifo, &pCh->rfc2833DTMF.dtmfSendBuf.dtmfValue, 1); if(rlt == 1) #endif { pCh->rfc2833DTMF.dtmfSendBuf.synIdentifier = 0; pCh->rfc2833DTMF.dtmfSendBuf.timeStamps = 0; pCh->rfc2833DTMF.dtmfSendBuf.refCount = 7; pCh->rfc2833DTMF.dtmfSendBuf.payloadType = 101; pCh->rfc2833DTMF.dtmfSendBuf.refStatus = RFC2833_SEND_BEGING; } } } if(pCh->rfc2833DTMF.dtmfSendBuf.refStatus != RFC2833_SEND_IDLE) { pDTMF = &pCh->rfc2833DTMF.dtmfSendBuf; pPayload = (unsigned char*)(skbSIP->data + 42); pHead->udpHead.len = htons(24); pHead->udpHead.check = 0; pHead->ipHead.tot_len = htons(44); pPayload[1] = 101; if(pDTMF->refCount == 7) { pPayload[1] |= 1 << 7; pDTMF->timeStamps = *(int*)(&pPayload[4]); } memcpy(&pPayload[4], &pDTMF->timeStamps, 4); pPayload[12] = pDTMF->dtmfValue; pPayload[13] = 0x0a; if(pDTMF->refCount <= 3) { pPayload[13] |= 1 << 7; pPayload[2] = (pCh->rfc2833DTMF.dtmfSendBuf.seqNumber + 1) >> 8; pPayload[3] = (pCh->rfc2833DTMF.dtmfSendBuf.seqNumber + 1) & 0xFF; pPayload[14] = ((8 - 3) * 80) >> 8; pPayload[15] = ((8 - 3) * 80) & 0xFF; } else { pCh->rfc2833DTMF.dtmfSendBuf.seqNumber = ntohs(*(unsigned short*)(&pPayload[2])); pPayload[14] = ((8 - pDTMF->refCount) * 80) >> 8; pPayload[15] = ((8 - pDTMF->refCount) * 80) & 0xFF; } // pskb_trim(skbSIP, skbSIP->len - 76); pskb_trim(skbSIP, 58); pDTMF->refCount--; if(pDTMF->refCount > 0) { pDTMF->refStatus = RFC2833_SENDING; } else { pDTMF->refStatus = RFC2833_SEND_IDLE; if(pCh->rfc2833DTMF.refSendMask > 0) { pCh->rfc2833DTMF.refSendMask &= ~(pCh->rfc2833DTMF.curSendIndex << 1); } pCh->rfc2833DTMF.refSendMask = 0; } } if(pCh->portRTP.chLinkInfo.stunTags != 0) { unsigned short* pTags = NULL; skb_push(skbSIP, 4); memmove(skbSIP->data, pHead, 42); pHead = (PPACKAGE_HEAD)skbSIP->data; pTags = (unsigned short*)(skbSIP->data + 42); *pTags = htons(pCh->portRTP.chLinkInfo.stunTags); pTags++; *pTags = htons(pHead->udpHead.len - 8); pHead->udpHead.len += htons(4); pHead->ipHead.tot_len += htons(4); } pHead->udpHead.check = 0; pHead->ipHead.check = 0; pHead->ipHead.check = get_ip_checksum((unsigned short*)&pHead->ipHead, 20); if(eth_tx_skb(skbSIP, pEthInfo->ndev) == NETDEV_TX_OK) { pCh->sipDebug.cnt_eth0_2_ethx++; } return skbSIP; } static struct sk_buff* switch_from_sip(int sipCh, struct sk_buff* skb, PCH_PORT_INFO pPort) { PPACKAGE_HEAD pHead = NULL; struct sk_buff* skbSIP = skb_clone(skb, GFP_ATOMIC); PNIC_PRIVATE pEthInfo = g_NICInfo[g_spbxNetId]; PSIP_CH_DETIAL pCh = &g_SIPChInfo.pSipChDetial[sipCh]; if(skbSIP == NULL) { return NULL; } dev_kfree_skb_any(skb); skbSIP->dev = pEthInfo->ndev; eth_header(skbSIP, pEthInfo->ndev, ETH_P_IP, NULL, NULL, skb->len); pHead = (PPACKAGE_HEAD)skbSIP->data; if(pPort->chLinkInfo.fromRTPCh.isUpdate == 0) { if(pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF ) { get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr, g_spbxNetId, htonl(pPort->chLinkInfo.dstTarget.ipAddr), 7); } memcpy(pHead->ethHead.h_dest, pPort->chLinkInfo.dstTarget.ethAddr, ETH_ALEN); pHead->ipHead.saddr = htonl(pEthInfo->chIpAddr); pHead->ipHead.daddr = htonl(pPort->chLinkInfo.dstTarget.ipAddr); pHead->udpHead.source = htons(pPort->ipPort); pHead->udpHead.dest = htons(pPort->chLinkInfo.dstTarget.ipPort); memcpy(&pPort->chLinkInfo.fromRTPCh.headValue, pHead, sizeof(PACKAGE_HEAD)); pPort->chLinkInfo.fromRTPCh.isUpdate = 1; } else { PACKAGE_HEAD ipHead = *pHead; if((pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF && pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF) || pCh->sipDebug.cnt_ethx_2_eth0 % 1000 == 0 ) { if(get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr, g_spbxNetId, htonl(pPort->chLinkInfo.dstTarget.ipAddr), 8) == 0) { memcpy(&pPort->chLinkInfo.fromRTPCh.headValue, pPort->chLinkInfo.dstTarget.ethAddr, ETH_ALEN); } } memcpy(pHead, &pPort->chLinkInfo.fromRTPCh.headValue, sizeof(PACKAGE_HEAD)); pHead->ipHead.id = ipHead.ipHead.id; pHead->ipHead.frag_off = ipHead.ipHead.frag_off; pHead->ipHead.tot_len = ipHead.ipHead.tot_len; pHead->udpHead.len = ipHead.udpHead.len; } if(pCh->portRTP.chLinkInfo.stunTags != 0) { unsigned short* pTags = (unsigned short*)(skbSIP->data + 42); unsigned short* pLen = (unsigned short*)(skbSIP->data + 44); if(*pTags == pCh->portRTP.chLinkInfo.stunTags && *pLen == pHead->udpHead.len - 12) { memcpy(&skbSIP->data[42], &skbSIP->data[46], *pLen); pskb_trim(skbSIP, skbSIP->len - 4); pHead->udpHead.len -= 4; pHead->ipHead.tot_len -= 4; } } pHead->udpHead.check = 0; pHead->ipHead.check = 0; pHead->ipHead.check = get_ip_checksum((unsigned short*)&pHead->ipHead, 20); if(eth_tx_skb(skbSIP, pEthInfo->ndev) == NETDEV_TX_OK) { pCh->sipDebug.cnt_ethx_2_eth0++; } return skbSIP; } //static int ipstack_hook_udp_recv_sip(struct sk_buff* skb, int* rlt) static int ipstack_hook_udp_recv_sip(struct sk_buff* skb, PNIC_PRIVATE pp) { unsigned char dtmfIndex; struct iphdr* iphdr = (struct iphdr*)skb->data; struct udphdr* udphdr = (struct udphdr*)(skb->data + iphdr->ihl * 4); char payloadType = 0;// *(char*)(skb->data + 29) & 0x7F; PNIC_PRIVATE pEthInfo = g_NICInfo[g_spbxNetId]; int ucc = pp->port; struct sk_buff* skbSIP; unsigned short seq_index = ntohs(*(unsigned short*)&skb->data[RECV_SEQ_POS]); unsigned char* pUdpData = (unsigned char*)(skb->data + 28); int udp_len = ntohs(udphdr->len); int sipCh; // stun package if((pUdpData[0] & 0xC0) == 0 && pUdpData[4] == 0x21 && pUdpData[5] == 0x12 && pUdpData[6] == 0xA4 && pUdpData[7] == 0x42) { return 0; } // not this nic package if(ntohl(iphdr->daddr) != g_NICInfo[ucc]->chIpAddr) { return 0; } sipCh = (ntohs(udphdr->dest) - g_SIPChInfo.iRTPPortBase); // SPI Ch Package if(sipCh >= 0 && sipCh < g_SIPChInfo.iTotalCh) { PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + sipCh; pCh->sipDebug.cnt_ethx_recv++; if(pCh->sipDebug.ethx_seq_index == 0 || pCh->sipDebug.ethx_seq_index == 0xFFFF) { pCh->sipDebug.ethx_seq_index = seq_index; } else { if(pCh->sipDebug.ethx_seq_index != seq_index - 1) { pCh->sipDebug.ethx_seq_error++; } pCh->sipDebug.ethx_seq_index = seq_index; } pCh->sipDebug.mask_ethx_2_eth0 = CHK_CH_RECVUDP; if(pCh->portRTP.chStatus != CH_STATUS_LINKED) { dev_kfree_skb_any(skb); return udp_len; } if(pCh->portRTP.chLinkInfo.dstTarget.ipAddr != ntohl(iphdr->saddr) || pCh->portRTP.chLinkInfo.dstTarget.ipPort != ntohs(udphdr->source)) { pCh->sipDebug.ethx_drop_src++; dev_kfree_skb_any(skb); return udp_len; } if(pCh->portRTP.chLinkInfo.stunTags != 0) { payloadType = *(char*)(skb->data + 29 + 4) & 0x7F; dtmfIndex = *(unsigned char*)(skb->data + 40 + 4); } else { payloadType = *(char*)(skb->data + 29) & 0x7F; dtmfIndex = *(unsigned char*)(skb->data + 40); } if(payloadType >= 96 && dtmfIndex < 17) // RFC2833 DTMF { recv_dtmf_from_sip(sipCh, skb); pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_RFC2833; dev_kfree_skb_any(skb); return udp_len; } else { if(pCh->portT38.chStatus == CH_STATUS_LINKED) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_STATUS | CHK_CH_NEEDSWITCH; if(CheckMacAddress(&pCh->portT38, g_spbxNetId) == -1) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_DROP_WAITARP; dev_kfree_skb_any(skb); return udp_len; } skbSIP = switch_from_sip(sipCh, skb, &pCh->portT38); if(skbSIP != NULL) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_OK; //*rlt = 1; } else { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_ERR; } return udp_len; } else { if(pCh->portB2B.chStatus == CH_STATUS_LINKED) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_STATUS; if(pCh->portB2B.chLinkInfo.dstTarget.ipAddr == pEthInfo->chIpAddr) { int b2bCh = (pCh->portB2B.chLinkInfo.dstTarget.ipPort - g_SIPChInfo.iPortBase) / g_SIPChInfo.iPortStep; pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_NEEDSWITCH_SAMEBOARD; if(b2bCh >= 0 && b2bCh <= g_SIPChInfo.iTotalCh) { PSIP_CH_DETIAL pB2BCh = g_SIPChInfo.pSipChDetial + b2bCh; if(pB2BCh->portB2B.chStatus == CH_STATUS_LINKED) { if(CheckMacAddress(&pB2BCh->portRTP, pB2BCh->sipETHId) == -1) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_DROP_WAITARP; dev_kfree_skb_any(skb); return udphdr->len; } skbSIP = switch_to_sip(b2bCh, skb, pB2BCh->sipETHId, &pB2BCh->portRTP); if(skbSIP != NULL) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_OK; //*rlt = 1; } else { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_ERR; } return udp_len; } } } else { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_STATUS | CHK_CH_NEEDSWITCH; if(CheckMacAddress(&pCh->portB2B, g_spbxNetId) == -1) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_DROP_WAITARP; dev_kfree_skb_any(skb); return udp_len; } // skbSIP = switch_from_sip(sipCh, skb, &pCh->portB2B); if(skbSIP != NULL) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_OK; //*rlt = 1; } else { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_ERR; } return udp_len; } } if(pCh->portIPR.chStatus == CH_STATUS_LINKED) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_STATUS | CHK_CH_NEEDSWITCH; if(CheckMacAddress(&pCh->portIPR, g_spbxNetId) == -1) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_DROP_WAITARP; dev_kfree_skb_any(skb); return udp_len; } skbSIP = switch_from_sip(sipCh, skb, &pCh->portIPR); if(skbSIP != NULL) { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_OK; //*rlt = 1; } else { pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_ERR; } return udp_len; } } } } return 0; } static int ipstack_hook_udp_recv_spbx(struct sk_buff* skb, PNIC_PRIVATE pp) { int ret = 0; struct iphdr* iphdr = (struct iphdr*)skb->data; struct udphdr* udphdr = (struct udphdr*)(skb->data + iphdr->ihl * 4); unsigned char* pUdpData = (unsigned char*)(skb->data + 28); unsigned short seq_index = ntohs(*(unsigned short*)&skb->data[RECV_SEQ_POS]); struct sk_buff* skbSIP; int udp_len = ntohs(udphdr->len); int sipCh; // stun package if((pUdpData[0] & 0xC0) == 0 && pUdpData[4] == 0x21 && pUdpData[5] == 0x12 && pUdpData[6] == 0xA4 && pUdpData[7] == 0x42) { return 0; } // not this nic package if(ntohl(iphdr->daddr) != g_NICInfo[pp->port]->chIpAddr) { return 0; } sipCh = (ntohs(udphdr->dest) - g_SIPChInfo.iPortBase) / g_SIPChInfo.iPortStep; // SPI Ch Package if(sipCh >= 0 && sipCh < g_SIPChInfo.iTotalCh) { PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + sipCh; pCh->sipDebug.mask_eth0_2_ethx = CHK_CH_RECVUDP; pCh->sipDebug.cnt_eth0_recv++; if(pCh->sipDebug.eth0_seq_index == 0 || pCh->sipDebug.ethx_seq_index == 0xFFFF) { pCh->sipDebug.eth0_seq_index = seq_index; } else { if(pCh->sipDebug.eth0_seq_index != seq_index - 1) { pCh->sipDebug.eth0_seq_error++; } pCh->sipDebug.eth0_seq_index = seq_index; } if(pCh->sipETHId == g_spbxNetId) { dev_kfree_skb_any(skb); return udp_len; } if(pCh->portRTP.chStatus == CH_STATUS_LINKED) { pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_STATUS; if(ntohl(iphdr->saddr) == pCh->portB2B.chLinkInfo.dstTarget.ipAddr || ntohl(iphdr->saddr) == pCh->portIPR.chLinkInfo.dstTarget.ipAddr || ntohl(iphdr->saddr) == pCh->portT38.chLinkInfo.dstTarget.ipAddr) { pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_NEEDSWITCH; if(CheckMacAddress(&pCh->portRTP, pCh->sipETHId) == -1) { pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_DROP_WAITARP; dev_kfree_skb_any(skb); return udp_len; } skbSIP = switch_to_sip(sipCh, skb, pCh->sipETHId, &pCh->portRTP); if(skbSIP != NULL) { pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_SWITCH_OK; return udp_len; } pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_SWITCH_ERR; } } } return ret; } int ipstack_hook_udp_recv(struct sk_buff* skb, PNIC_PRIVATE pp) { struct iphdr* iphdr = (struct iphdr*)skb->data; struct udphdr* udphdr = (struct udphdr*)(skb->data + iphdr->ihl * 4); unsigned long flags; int port = ntohs(udphdr->dest); int rcvBytes = 0; if(pp->port == g_spbxNetId) { if(port >= g_SIPChInfo.iPortBase && port < g_SIPChInfo.iPortBase + (g_SIPChInfo.iTotalCh * g_SIPChInfo.iPortStep)) { return ipstack_hook_udp_recv_spbx(skb, pp); } else if(port >= pp->rtpCfg.rtpBasePort && port < pp->rtpCfg.rtpBasePort + (pp->rtpCfg.rtpCfgCh * pp->rtpCfg.rtpPortStep)) { if(g_pRcvRtpHook != NULL) { int ch = (port - pp->rtpCfg.rtpBasePort) / pp->rtpCfg.rtpPortStep; if(ch < 0 || ch >= pp->rtpCfg.rtpCfgCh) { return 0; } spin_lock_irqsave(&g_RegHookLock, flags); rcvBytes = g_pRcvRtpHook(pp->port, ch, (unsigned char*)iphdr, iphdr->tot_len); spin_unlock_irqrestore(&g_RegHookLock, flags); if(rcvBytes > 0) { dev_kfree_skb_any(skb); } return rcvBytes; } } } else { if(ntohs(udphdr->dest) >= g_SIPChInfo.iRTPPortBase && ntohs(udphdr->dest) < (g_SIPChInfo.iRTPPortBase + g_SIPChInfo.iTotalCh)) { return ipstack_hook_udp_recv_sip(skb, pp); } } return 0; } void ipstack_hook_init(void) { int i; g_SIPChInfo.iTotalCh = 0; g_SIPChInfo.pSipChDetial = g_SIPDetial; g_SIPChInfo.iPortBase = -1; g_SIPChInfo.iPortStep = -1; InitDebugInfoProc("hook_netdrv"); for(i = 0; i < sizeof(g_DbgFSConfig) / sizeof(g_DbgFSConfig[0]); i++) { if(DebugFsRegister(&g_DbgFSConfig[i]) != ERR_DBGFS_NO_ERROR) { LOG_EX(LOG_Error, "%d Regisetr %s Error\n", i, g_DbgFSConfig[i].name); } } spin_lock_init(&g_RegHookLock) ; } void ipstack_hook_exit(void) { int i; g_SIPChInfo.iTotalCh = 0; g_SIPChInfo.iPortBase = -1; g_SIPChInfo.iPortStep = -1; for(i = 0; i < sizeof(g_DbgFSConfig) / sizeof(g_DbgFSConfig[0]); i++) { DebugFsUnRegister(&g_DbgFSConfig[i]); } DeInitDebugInfoProc(); } ETH_IRQ_MODE eth_get_irq_mode(int ethId) { #if defined(PLATFORM_MV78460) struct eth_port* pp = NULL; #elif defined(PLATFORM_P1010) struct gfar_private* pp = NULL; #endif if(ethId < 0 || ethId >= MAX_ETH_PORT) { return IRQ_MODE_ERROR; } pp = GET_ETH_PRIVATE(ethId); if(pp == NULL) { return IRQ_MODE_ERROR; } return pp->devPrivate.irqMode; } EXPORT_SYMBOL(eth_get_irq_mode); const char* eth_get_irq_aliase(ETH_IRQ_MODE irqMode) { switch(irqMode) { case IRQ_MODE_1MS: return "IRQ_MODE_1MS"; case IRQ_MODE_MAC: return "IRQ_MODE_MAC"; default: return "IRQ_MODE_ERROR"; } return "IRQ_MODE_UNKNOWN"; } EXPORT_SYMBOL(eth_get_irq_aliase); int config_eth_rtp(int ethId, unsigned short maxCh, unsigned short port_base, unsigned short port_step) { g_NICInfo[ethId]->rtpCfg.rtpBasePort = port_base; g_NICInfo[ethId]->rtpCfg.rtpCfgCh = maxCh; g_NICInfo[ethId]->rtpCfg.rtpPortStep = port_step; } EXPORT_SYMBOL(config_eth_rtp); PNIC_PRIVATE eth_get_hook_info(int ethId) { if(ethId >= 0 && ethId <= MAX_ETH_PORT) { return g_NICInfo[ethId]; } return NULL; } EXPORT_SYMBOL(eth_get_hook_info); void register_rcv_rtp_hook(PNIC_RCV_RTP_DATA phook) { unsigned long flags; spin_lock_irqsave(&g_RegHookLock, flags); g_pRcvRtpHook = phook; spin_unlock_irqrestore(&g_RegHookLock, flags); } EXPORT_SYMBOL(register_rcv_rtp_hook); void unregister_rcv_rtp_hook(void) { unsigned long flags; spin_lock_irqsave(&g_RegHookLock, flags); g_pRcvRtpHook = NULL; spin_unlock_irqrestore(&g_RegHookLock, flags); } EXPORT_SYMBOL(unregister_rcv_rtp_hook); int config_eth_ipaddr(unsigned int ethId, __be32 ipaddr, __be32 gwaddr, __be32 gwmask) { PNIC_PRIVATE pGfar = NULL; if(ethId < MAX_ETH_PORT) { pGfar = g_NICInfo[ethId]; if(pGfar == NULL) { return -1; } else { pGfar->chIpAddr = ipaddr; pGfar->chGWIpAddr = gwaddr; pGfar->chGWMask = gwmask; if(gwaddr != 0) { make_arp_request(ethId, gwaddr); } } } return 0; } EXPORT_SYMBOL(config_eth_ipaddr); void eth_set_hook_info(int ethId, PNIC_PRIVATE pp) { if(ethId >= 0 && ethId <= MAX_ETH_PORT) { g_NICInfo[ethId] = pp; } } void eth_init_hook_info(void) { int i; for(i = 0; i < MAX_ETH_PORT; i++) { g_NICInfo[i] = NULL; } } static int DbgFS_RtpPortShow(struct seq_file* seq, void* token) { int i = 0; if(token == SEQ_START_TOKEN) { for(i = 0; i < MAX_ETH_PORT; i++) { if(g_NICInfo[i]) { seq_printf(seq, "Eth%d: Port Base = %d, Port Step = %d, CfgCh = %d\n", i, g_NICInfo[i]->rtpCfg.rtpBasePort, g_NICInfo[i]->rtpCfg.rtpPortStep, g_NICInfo[i]->rtpCfg.rtpCfgCh); } else { seq_printf(seq, "ETH%d: unused\n", i); } } } return 0; } static int DbgFS_NICCfgShow(struct seq_file* seq, void* token) { int i = 0; if(token == SEQ_START_TOKEN) { for(i = 0; i < MAX_ETH_PORT; i++) { if(g_NICInfo[i] != NULL) { seq_printf(seq, "ETH%d: \n", i); seq_printf(seq, "IP Addr : %d.%d.%d.%d\n", (g_NICInfo[i]->chIpAddr >> 24) & 0xFF, (g_NICInfo[i]->chIpAddr >> 16) & 0xFF, (g_NICInfo[i]->chIpAddr >> 8) & 0xFF, g_NICInfo[i]->chIpAddr & 0xFF); seq_printf(seq, "GW Addr : %d.%d.%d.%d\n", (g_NICInfo[i]->chGWIpAddr >> 24) & 0xFF, (g_NICInfo[i]->chGWIpAddr >> 16) & 0xFF, (g_NICInfo[i]->chGWIpAddr >> 8) & 0xFF, g_NICInfo[i]->chGWIpAddr & 0xFF); seq_printf(seq, "Netmask Addr : %d.%d.%d.%d\n", (g_NICInfo[i]->chGWMask >> 24) & 0xFF, (g_NICInfo[i]->chGWMask >> 16) & 0xFF, (g_NICInfo[i]->chGWMask >> 8) & 0xFF, g_NICInfo[i]->chGWMask & 0xFF); seq_printf(seq, "Mac Addr : %02X:%02X:%02X:%02X:%02X:%02X\n", g_NICInfo[i]->ndev->dev_addr[0], g_NICInfo[i]->ndev->dev_addr[1], g_NICInfo[i]->ndev->dev_addr[2], g_NICInfo[i]->ndev->dev_addr[3], g_NICInfo[i]->ndev->dev_addr[4], g_NICInfo[i]->ndev->dev_addr[5]); } else { seq_printf(seq, "ETH%d: unused\n", i); } } } return 0; } static int DbgFS_EthIrqShow(struct seq_file* seq, void* token) { unsigned int eth_id = g_DbgFSConfig[DBG_ETH_IRQ].params; if(token == SEQ_START_TOKEN) { if(IS_VALUABLED_ETH(eth_id)) { ETH_IRQ_MODE irqMode = eth_get_irq_mode(eth_id); seq_printf(seq, "ETH%d current work on %s(%d) irq mode.\n", eth_id, (char*)eth_get_irq_aliase(irqMode), (int)irqMode); } else { seq_printf(seq, "Error eth id: %d\n", eth_id); } } return 0; } static int DbgFS_EthIrqHelp(struct seq_file* seq, void* token) { printk("==============Options Helps=============\n"); printk("usage: echo \"\" > /proc/hook_netdrv/eth_irq\n"); printk("eth_id:\n"); printk("\t[0..%d]: Show eth0..eth:%d Current IrqMode.\n", MAX_ETH_PORT, MAX_ETH_PORT); printk("\nusage: echo \"set \" > /proc/hook_netdrv/eth_irq\n"); printk("irq_mode:\n"); printk("\t[1ms]: Set ethx receive and send used 1ms irq.\n"); printk("\t[mac]: Set ethx receive and send used chipset irq.\n"); return 0; } static int DbgFS_EthIrqIoctl(struct seq_file* seq, char* cmd, char* params) { unsigned int eth_id = g_DbgFSConfig[DBG_ETH_IRQ].params; int ret = 0; char tmpBuf[64]; if(!IS_VALUABLED_ETH(eth_id)) { LOG_EX(LOG_Error, "Error: Current ETH is %d\n", eth_id); return -ERR_PARA_OUTOFRANGE; } if(strcmp(cmd, "set") == 0) { ETH_IRQ_MODE irqMode; ret = GetStringParamValue(params, 0, tmpBuf, 64); if(ret != ERR_DBGFS_NO_ERROR) { LOG_EX(LOG_Error, "get %d params(%s) error\n", 0, params); return -ERR_PARA_OUTOFRANGE; } if(strcmp(tmpBuf, "1ms") == 0) { ret = eth_switch_irq_to_1ms(eth_id); irqMode = IRQ_MODE_1MS; } else if(strcmp(tmpBuf, "mac") == 0) { ret = eth_switch_irq_to_mac(eth_id); irqMode = IRQ_MODE_MAC; } else { LOG_EX(LOG_Error, "Error IRQ_MODE(1ms/mac) (%s)\n", tmpBuf); return 0; } LOG_EX((ret == 0) ? LOG_Info : LOG_Error, "ETH%d Switch IRQ Mode To %s %s\n", eth_id, (char*)eth_get_irq_aliase(irqMode), (ret == 0) ? "OK" : "Error"); } else { LOG_EX(LOG_Error, "Unknown command (%s)\n", cmd); } return 0; } int SetLocalNICId(int id) { if(id >= 0 && id < MAX_ETH_PORT) { g_spbxNetId = id; return 0; } return -1; } EXPORT_SYMBOL(SetLocalNICId); unsigned long long get_cpu_tick(void) { uint32_t h = 0; uint32_t l = 0; uint32_t h1 = 0; asm volatile("1: \n" "mftbu %0 \n" "mftb %1 \n" "mftbu %2 \n" "cmpw %0,%2 \n" "bne 1b \n" :"=r"(h), "=r"(l), "=r"(h1):); return (((unsigned long long)h) << 32) | l; } EXPORT_SYMBOL(get_cpu_tick); unsigned long long cpu_tick_to_ms(unsigned long long tick) { return div64_u64(tick, P1010_CPU_COUNT_PER_MS); } EXPORT_SYMBOL(get_cpu_tick_of_ms);