spbx/roms/srcs/images/ethernet/gianfar_eth/hook_p1010.c

2961 lines
86 KiB
C
Raw Normal View History

2019-03-11 00:13:23 +00:00
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/udp.h>
#include <net/arp.h>
#include "gianfar.h"
#include "debug_info.h"
#include "log.h"
#include "hook.h"
#define USED_MALLOC_CHDETIAL (0)
#define PROC_NAME ("gfar")
#define SEND_SEQ_POS (0x2C)
#define RECV_SEQ_POS (SEND_SEQ_POS - 0x0E)
static int irq_flags;
static struct ipstack_hook_t ipstack_hook_p1010[UMB_MAX_GETH];
static struct gfar_private* g_geths[UMB_MAX_GETH];
static int g_geths_ref[UMB_MAX_GETH];
struct irq_hook
{
void* (*hook)(int, void*) ;
void* data;
int per_of_ms;
};
static struct irq_hook irq_hooks[32];
static volatile uint32_t poll_hook_bitmap = 0xffffffff;
static int g_irq_cnt = 0;
static int g_1ms_timer = -1;
#ifdef EN_SIP_SWITCH
#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;
#if !USED_MALLOC_CHDETIAL
static SIP_CH_DETIAL g_SIPDetial[MAX_SIP_CH];
#endif
const char g_DTMFTable[17] =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'*', '#',
'A', 'B', 'C', 'D',
'F' // Flash
};
static int ipstack_hook_udp_recv_sip(struct sk_buff* skb);
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);
#endif
static struct sk_buff* dev_new_skb(struct gfar_private* priv);
static int DbgFS_GianfarARPShow(struct seq_file* seq, void* token);
static int DbgFS_GianfarChRTPShow(struct seq_file* seq, void* token);
static int DbgFS_GianfarChPortShow(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 DBGFS_PRIV g_DbgFSConfig[] =
{
{
"arp_mac", 0, NULL, NULL,
DbgFS_GianfarARPShow, NULL, NULL
},
{
"ch_rtp", 0, NULL, NULL,
DbgFS_GianfarChRTPShow, NULL, NULL
},
{
"ch_port", 0, NULL, NULL,
DbgFS_GianfarChPortShow, NULL, NULL
},
#ifdef EN_SIP_SWITCH
{
"sip_ch", 0, NULL, NULL,
DbgFS_GianfarSipPortShow, NULL, NULL
},
{
"sip_arp", 0, NULL, NULL,
DbgFS_SipArpShow, NULL, NULL
},
#endif
};
static int make_arp_request(unsigned int ethId, __be32 dest_ip)
{
struct sk_buff* skb = NULL;
if(ethId > ETH_INTERFACE_2)
{
return 0;
}
skb = arp_create(ARPOP_REQUEST,
ETH_P_ARP,
dest_ip,
g_geths[ethId]->ndev,
g_geths[ethId]->chIpAddr,
NULL,
g_geths[ethId]->ndev->dev_addr,
NULL);
if(skb)
{
arp_xmit(skb);
}
else
{
printk("...");
}
return 0;
}
static int get_mac_form_ip(unsigned char* haddr, ETH_INTERFACE ethId, __be32 ipaddr, int id)
{
struct neighbour* n;
struct gfar_private* ugeth = g_geths[ethId];
__be32 oldip = ipaddr;
//memset(haddr, 0xFF, ETH_ALEN);
if(ugeth->chGWIpAddr != 0)
{
if((ipaddr & ugeth->chGWMask) != (ugeth->chIpAddr & ugeth->chGWMask))
{
if(id == 4 || id == 3)
{
printk("ipaddr = 0x%08X, ugeth->chGWMask = 0x%08X, ugeth->chIpAddr = 0x%08X\n",
ipaddr, ugeth->chGWMask, ugeth->chIpAddr);
}
ipaddr = ugeth->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, ugeth->ndev, 1);
if(n != NULL)
{
n->used = jiffies;
if(n->nud_state & NUD_VALID)
{
read_lock_bh(&n->lock);
memcpy(haddr, n->ha, ugeth->ndev->addr_len);
read_unlock_bh(&n->lock);
neigh_release(n);
return 0;
}
}
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);
}
make_arp_request(ethId, ipaddr);
return -1;
}
struct ipstack_hook_t* ipstack_hook_get(int ucc_num)
{
return &ipstack_hook_p1010[ucc_num];
}
EXPORT_SYMBOL(ipstack_hook_get);
static PRTP_CH_DETAILS ipstack_hook_get_grtp(struct gfar_private* ugeth)
{
if(ipstack_hook_p1010[ugeth->ucc_num].pRtpChDetails == NULL)
{
printk("%d RTP Detailse is NULL\n", ugeth->ucc_num);
}
return ipstack_hook_p1010[ugeth->ucc_num].pRtpChDetails;
}
static int is_rtp_kbuf(void* p, int ucc_num)
{
struct ipstack_hook_t* gfar_hook = ipstack_hook_get(ucc_num);
//under 1G is phys addr
if(p < (void*)gfar_hook->kmap_addr || p > (void*)gfar_hook->kmap_end)
{
return 0;
}
return 1;
}
static int walk_rtp_list(struct gfar_private* ugeth)
{
int ch = ugeth->current_tx;
unsigned short seq_index;
struct ipstack_hook_t* pGfarHook = &ipstack_hook_p1010[ugeth->ucc_num];
PRTP_CH_DETAILS pBase = pGfarHook->pRtpChDetails;
PRTP_CH_DETAILS rtp_ch = pBase + ch;
register struct rtp_tx_buf_t* ktx = rtp_ch->current_ktx;
if(ktx->status & IP_SENDING_FLAGS || ktx->status == 0)
{
return NETDEV_TX_LOCKED;
}
if(pGfarHook->rtpChDbgs[ch].uSendBytes % 1000 == 0
|| pGfarHook->rtpChDbgs[ch].uSendBytes % 1001 == 0)
{
get_mac_form_ip(ktx->data, ugeth->ucc_num, pGfarHook->linkIPAddr[ch], 1);
}
//this will be clean by reclaim the tx skb
ktx->status |= IP_SENDING_FLAGS;
if(pGfarHook->hook_xmit(ktx, RTP_BUFF_TYPE, rtp_ch->netdev) == NETDEV_TX_OK)
{
seq_index = *(unsigned short*)(ktx->data + SEND_SEQ_POS);
if(pGfarHook->sendIndex[ch] != 0xFFFFFFFF)
{
if(seq_index != pGfarHook->sendIndex[ch] + 1)
{
pGfarHook->rtpChDbgs[ch].uSendSeqLost++;
}
}
pGfarHook->sendIndex[ch] = seq_index;
if(ktx == &rtp_ch->tx[1])
{
ktx = &rtp_ch->tx[0];
}
else
{
ktx = &rtp_ch->tx[1];
}
rtp_ch->current_ktx = ktx;
pGfarHook->rtpChDbgs[ch].uSendBytes++;
return NETDEV_TX_OK;
}
ktx->status &= (~IP_SENDING_FLAGS);
return NETDEV_TX_BUSY;
}
void geth_timer_hook(uint32_t irq_cnt)
{
int i = 0, k = 0;
uint32_t bits, qlen;
struct ipstack_hook_t* priv = NULL;
for(i = 0; i < UMB_MAX_GETH; i++)
{
struct gfar_private* ugeth = g_geths[i];
if(ugeth && ugeth->opened_ref && !xchg(&g_geths_ref[i], 1))
{
struct ipstack_hook_t* pGarHook = &ipstack_hook_p1010[ugeth->ucc_num];
int procCh = pGarHook->rtpCfgCh;
int weight = procCh / 10;
for(k = 0; k < weight; k++)
{
if(walk_rtp_list(ugeth) == NETDEV_TX_BUSY)
{
break;
}
ugeth->current_tx++;
ugeth->current_tx %= procCh;
}
priv = ipstack_hook_get(i);
qlen = skb_queue_len(&priv->qtx);
if(qlen > 0)
{
pGarHook->backlog_xmit(ugeth, qlen);
}
gfar_netpoll(ugeth);
g_geths_ref[i] = 0;
}
}
bits = ~poll_hook_bitmap;
while((i = fls(bits) - 1) >= 0)
{
if(irq_hooks[i].per_of_ms > 1)
{
if((irq_cnt % irq_hooks[i].per_of_ms) == 0)
{
irq_hooks[i].hook(irq_cnt, irq_hooks[i].data);
}
}
else
{
irq_hooks[i].hook(irq_cnt, irq_hooks[i].data);
}
bits &= ~(1 << i);
}
return ;
}
int register_irq_poll(void * (*hooks)(int, void* obj), void* data,
unsigned int per_of_ms)
{
int ret = -ENOSPC;
int idx = 0;
if((idx = fls(poll_hook_bitmap) - 1) >= 0)
{
poll_hook_bitmap &= ~(1 << idx);
irq_hooks[idx].hook = hooks;
irq_hooks[idx].data = data;
irq_hooks[idx].per_of_ms = per_of_ms;
ret = idx;
}
return ret;
}
EXPORT_SYMBOL(register_irq_poll);
int unregister_irq_poll(int idx, void * (*hooks)(int, void* obj))
{
int ret = -EINVAL;
if(!(poll_hook_bitmap & (1 << idx)))
{
irq_hooks[idx].hook = NULL;
poll_hook_bitmap |= (1 << idx);
}
return ret;
}
EXPORT_SYMBOL(unregister_irq_poll);
int config_rtp_port(int ethId, unsigned short index, unsigned short port,
unsigned short port_base, unsigned short port_step,
unsigned int bReConfig)
{
int portIndex = 0;
struct ipstack_hook_t* pGfarHook = ipstack_hook_get(ethId);
//printk(" port %d, base %d, index %d\n", port, port_base, index);
if(bReConfig)
{
pGfarHook->rtpBasePort = port_base;
pGfarHook->rtpCfgCh = 0;
pGfarHook->rtpPortStep = port_step;
}
#if 0
if(pGfarHook->rtpBasePort == 0xFFFF)
{
pGfarHook->rtpBasePort = port_base;
}
else if(pGfarHook->rtpBasePort != port_base && port_base != 0xFFFF)
{
printk("%s(%d): port_base pre init to %d, now is %d\n", __FUNCTION__, __LINE__,
port_base, pGfarHook->rtpBasePort);
return -1;
}
#endif
if(index < pGfarHook->rtpMaxCh)
{
if(pGfarHook->rtpCfgCh < pGfarHook->rtpMaxCh)
{
pGfarHook->rtpCfgCh++;
portIndex = (port - pGfarHook->rtpBasePort) / pGfarHook->rtpPortStep;
pGfarHook->rtpPortIndex[portIndex] = index;
}
// printk("pGfarHook->rtpPortIndex[%d] = %d\n", portIndex, index);
return 0;
}
return -1;
}
EXPORT_SYMBOL(config_rtp_port);
static struct sk_buff* dev_new_skb(struct gfar_private* priv)
{
unsigned int alignamount;
struct sk_buff* skb = NULL;
skb = netdev_alloc_skb(priv->ndev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
if(!skb)
{
return NULL;
}
alignamount = RXBUF_ALIGNMENT -
(((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1));
/* We need the data buffer to be aligned properly. We will reserve
* as many bytes as needed to align the data properly
* Do only if not already aligned */
if(alignamount != RXBUF_ALIGNMENT)
{
skb_reserve(skb, alignamount);
}
GFAR_CB(skb)->alignamount = alignamount;
/* Keep incoming device pointer for recycling */
skb->skb_owner = priv->ndev;
return skb;
}
static int ipstack_hook_backlog_xmit(struct gfar_private* ugeth, int len)
{
struct ipstack_hook_t* priv = ipstack_hook_get(ugeth->ucc_num);
int i;
for(i = 0; i < len; i++)
{
struct sk_buff* skb = skb_dequeue(&priv->qtx);
if(skb)
{
if(priv->hook_xmit((void*)skb, SKB_BUFF_TYPE, skb->dev) == NETDEV_TX_OK)
{
continue;
}
}
break;
}
return i;
}
static int ipstack_hook_udp_recv(struct sk_buff* skb)
{
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 int src_ip = *(unsigned int*)&skb->data[12];
unsigned short seq_index = *(unsigned short*)&skb->data[RECV_SEQ_POS];
int dif = ((struct gfar_private*)netdev_priv(skb->dev))->ucc_num;
struct ipstack_hook_t* pGfarHook = ipstack_hook_get(dif);
int ch = -1;
struct sk_buff* pOutSKB = NULL;
PRTP_CH_DETAILS rtp_ch;
struct rtp_rx_buf_t* krx;
struct sk_buff* skbSIP;
int udp_len = udphdr->len;
int port = (udphdr->dest - pGfarHook->rtpBasePort);
#ifdef EN_SIP_SWITCH
// stun package
if((pUdpData[0] & 0xC0) == 0
&& pUdpData[4] == 0x21
&& pUdpData[5] == 0x12
&& pUdpData[6] == 0xA4
&& pUdpData[7] == 0x42)
{
return 0;
}
// SPI Ch Package
if(udphdr->dest >= g_SIPChInfo.iPortBase &&
udphdr->dest < g_SIPChInfo.iPortBase +
(g_SIPChInfo.iTotalCh * g_SIPChInfo.iPortStep))
{
int sipCh = (udphdr->dest - g_SIPChInfo.iPortBase) / g_SIPChInfo.iPortStep;
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.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 < 0 || pCh->sipETHId > ETH_INTERFACE_2)
{
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(iphdr->saddr == pCh->portB2B.chLinkInfo.dstTarget.ipAddr
|| iphdr->saddr == pCh->portIPR.chLinkInfo.dstTarget.ipAddr
|| 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 udphdr->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 udphdr->len;
}
pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_SWITCH_ERR;
}
}
}
return 0;
}
#endif
if(port >= 0 && port < (pGfarHook->rtpCfgCh * pGfarHook->rtpPortStep))
{
ch = pGfarHook->rtpPortIndex[port / 3];
if(ch < 0 || ch >= pGfarHook->rtpCfgCh)
{
return 0;
}
if(src_ip != pGfarHook->linkIPAddr[ch])
{
return 0;
}
}
if(ch >= 0 && ch < pGfarHook->rtpCfgCh)
{
rtp_ch = pGfarHook->pRtpChDetails + ch;
pGfarHook->rtpChDbgs[ch].uUDPRecPackages++;
if(rtp_ch->sk)
{
if(!rtp_ch->current_krx->status)
{
krx = rtp_ch->current_krx;
//memcpy(krx->data, (char*)udphdr, udphdr->len);
krx->data = (char*)udphdr;//iphdr;
krx->len = udphdr->len;
pOutSKB = krx->skb;
krx->skb = skb;
krx->status = 1;
dev_kfree_skb_any(pOutSKB);
if(pGfarHook->recvIndex[ch] != 0xFFFFFFFF)
{
if(seq_index != pGfarHook->recvIndex[ch] + 1)
{
pGfarHook->rtpChDbgs[ch].uRecvSeqLost++;
}
}
pGfarHook->recvIndex[ch] = seq_index;
pGfarHook->rtpChDbgs[ch].uRecBytes++;
if(&rtp_ch->rx[2] == krx)
{
krx = &rtp_ch->rx[0];
}
else
{
krx++;
}
rtp_ch->current_krx = krx;
ret = udphdr->len;
}
else
{
pGfarHook->rtpChDbgs[ch].uLostPackages++;
pGfarHook->rtpChDbgs[ch].uBufStatus = (rtp_ch->rx[2].status << 2) |
(rtp_ch->rx[1].status << 1) |
(rtp_ch->rx[0].status);
ret = 0;
}
}
}
return ret;
}
static int ipstack_hook_backlog(struct sk_buff* skb)
{
struct gfar_private* ugeth = netdev_priv(skb->dev);
uint32_t qlen = 0;
uint32_t ucc_num = ugeth->ucc_num;
struct ipstack_hook_t* priv = ipstack_hook_get(ucc_num);
skb_queue_tail(&priv->qtx, skb);
qlen = skb_queue_len(&priv->qtx);
if(qlen >= 240)
{
if(qlen > 240)
{
printk("ipstack_hook_backlog qlen:%u \n", qlen);
}
if(!netif_queue_stopped(ugeth->ndev))
{
netif_stop_queue(ugeth->ndev);
}
}
return NETDEV_TX_OK;
}
static int ipstack_hook_xmit_filter_eth2(struct sk_buff* skb)
{
ipstack_hook_backlog(skb);
return NETDEV_TX_OK;
}
static int ipstack_hook_xmit_filter(struct sk_buff* skb)
{
uint16_t ip_prot;
uint8_t udp_prot;
uint32_t first_magic;
uint32_t second_magic;
uint16_t ch;
uint16_t rtp_port;
int j, rtplen, tp;
struct gfar_private* ugeth = netdev_priv(skb->dev);
struct ipstack_hook_t* pGfarHook = &ipstack_hook_p1010[ugeth->ucc_num];
//uint32_t ucc_num = ugeth->ucc_num;
ip_prot = *(uint16_t*)&skb->data[0xc];
rtplen = skb->len - 54;
tp = (rtplen % 80 == 0) ? rtplen / 80 : -1;
if(tp > 0 && tp < 5)
{
first_magic = *(uint32_t*)&skb->data[0x2a];
if(first_magic == 0x58694327)
{
second_magic = *(uint32_t*)&skb->data[0x32];
//ip_prot =*(uint16_t*)&skb->data[0xc];
udp_prot = *(uint8_t*)&skb->data[0x17];
if((udp_prot == IPPROTO_UDP) && (cpu_to_be16(ip_prot) == ETH_P_IP)
&& (second_magic == 0x58694327))
{
// PRTP_CH_DETAILS g_rtp = ipstack_hook_get_grtp(ugeth);
ch = *(uint16_t*)&skb->data[0x2e];
rtp_port = *(uint16_t*)&skb->data[0x30];
if(ch >= 0 && ch < pGfarHook->rtpCfgCh)
{
PRTP_CH_DETAILS rtp_ch = ipstack_hook_get_grtp(ugeth) + ch;
rtp_ch->netdev = skb->dev;
rtp_ch->current_ktx->status = 0;
rtp_ch->current_ktx->len = skb->len;
rtp_ch->current_utx = rtp_ch->current_ktx;
for(j = 0; j < sizeof(rtp_ch->tx) / sizeof(rtp_ch->tx[0]); j++)
{
memcpy(rtp_ch->tx[j].data , &skb->data[0], skb->len);
}
rtp_ch->current_krx->len = 0;
rtp_ch->current_urx = rtp_ch->current_krx;
for(j = 0; j < sizeof(rtp_ch->rx) / sizeof(rtp_ch->rx[0]); j++)
{
rtp_ch->rx[j].len = 0;
rtp_ch->rx[j].status = 0;
}
rtp_ch->sk = skb->sk;
skb->sk->sk_user_data = (void*)rtp_ch;
pGfarHook->linkIPAddr[ch] = *(unsigned int*)&skb->data[0x1E];
pGfarHook->rtpChDbgs[ch].uRecBytes = 0;
pGfarHook->rtpChDbgs[ch].uSendBytes = 0;
pGfarHook->rtpChDbgs[ch].uUDPRecPackages = 0;
pGfarHook->rtpChDbgs[ch].uLostPackages = 0;
pGfarHook->rtpChDbgs[ch].uRecvSeqLost = 0;
pGfarHook->rtpChDbgs[ch].uSendSeqLost = 0;
pGfarHook->sendIndex[ch] = 0xFFFFFFFF;
pGfarHook->recvIndex[ch] = 0xFFFFFFFF;
// printk("ch %d dest ip = 0x%08X\n", ch, g_DestIpAddr[ch]);
}
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
}
}
pGfarHook->backlog(skb);
return NETDEV_TX_OK;
}
static int g_rtp_init(struct gfar_private* ugeth)
{
PRTP_CH_DETAILS rtp_tmp;
struct txfcb* fcb = NULL;
struct ipstack_hook_t* pGfarHook = ipstack_hook_get(ugeth->ucc_num);
int j, k, i;
i = ugeth->ucc_num;
rtp_tmp = ipstack_hook_get_grtp(ugeth);
if(!rtp_tmp)
{
return -ENOMEM;
}
memset(rtp_tmp, 0, sizeof(RTP_CH_DETAILS) * MAX_RTP_CH);
memset(pGfarHook->rtpPortIndex, 0xFF, sizeof(pGfarHook->rtpPortIndex));
for(j = 0; j < pGfarHook->rtpMaxCh; j++)
{
PRTP_CH_DETAILS rtp_ch = rtp_tmp + j;
rtp_ch->current_ktx = &rtp_ch->tx[0];
rtp_ch->current_utx = &rtp_ch->tx[0];
rtp_ch->current_krx = &rtp_ch->rx[0];
rtp_ch->current_urx = &rtp_ch->rx[0];
rtp_ch->sk = NULL;
for(k = 0; k < sizeof(rtp_ch->tx) / sizeof(rtp_ch->tx[0]); k++)
{
fcb = (struct txfcb*)rtp_ch->tx[k].fcb;
fcb->flags = TXFCB_DEFAULT | TXFCB_UDP | TXFCB_TUP | TXFCB_CTU;
fcb->l3os = 14;
fcb->l4os = 20;
rtp_ch->tx[k].status = 0;
rtp_ch->tx[k].len = 0;
}
for(k = 0; k < sizeof(rtp_ch->rx) / sizeof(rtp_ch->rx[0]); k++)
{
rtp_ch->rx[k].status = 0;
rtp_ch->rx[k].len = 0;
rtp_ch->rx[k].data = (char*)dev_new_skb(ugeth);
rtp_ch->rx[k].skb = rtp_ch->rx[k].data;
}
pGfarHook->rtpChDbgs[j].uRecBytes = 0;
pGfarHook->rtpChDbgs[j].uSendBytes = 0;
pGfarHook->rtpChDbgs[j].uUDPRecPackages = 0;
pGfarHook->rtpChDbgs[j].uLostPackages = 0;
pGfarHook->rtpPortIndex[j] = 0xFFFF;
}
return 0;
}
static int ipstack_hook_init(struct gfar_private* ugeth)
{
int i = ugeth->ucc_num;
int ret = 0;
struct ipstack_hook_t* priv = ipstack_hook_get(i);
if(i > UMB_MAX_GETH || i < 0)
{
return 1;
}
//skb_queue_head_init(&priv->qtx[i]);
skb_queue_head_init(&priv->qtx);
while(xchg(&g_geths_ref[i], 1))
{
msleep(2);
}
ret = g_rtp_init(ugeth);
g_geths[i] = ugeth;
g_geths_ref[i] = 0;
printk("ucc %d hook = %p\n", i, ipstack_hook_p1010[i].do_sock_recv);
#ifdef EN_SIP_SWITCH
g_SIPChInfo.iTotalCh = 0;
#if USED_MALLOC_CHDETIAL
g_SIPChInfo.pSipChDetial = NULL;
#else
g_SIPChInfo.pSipChDetial = g_SIPDetial;
#endif
g_SIPChInfo.iPortBase = -1;
g_SIPChInfo.iPortStep = -1;
#endif
return ret;
}
static int ipstack_hook_exit(struct gfar_private* ugeth)
{
struct sk_buff* skb;
int i = ugeth->ucc_num;
struct ipstack_hook_t* priv = ipstack_hook_get(i);
#ifdef EN_SIP_SWITCH
g_SIPChInfo.iTotalCh = 0;
g_SIPChInfo.iPortBase = -1;
g_SIPChInfo.iPortStep = -1;
#if USED_MALLOC_CHDETIAL
if(g_SIPChInfo.pSipChDetial != NULL)
{
kfree(g_SIPChInfo.pSipChDetial);
}
#endif
#endif
if(i > UMB_MAX_GETH || i < 0)
{
return 1;
}
do
{
skb = skb_dequeue(&priv->qtx);
if(skb)
{
kfree_skb(skb);
}
}
while(skb);
while(xchg(&g_geths_ref[i], 1))
{
msleep(2);
}
g_geths[i] = NULL;
/* driver auto free device's all skb, so.... */
//g_rtp_exit(ugeth);
g_geths_ref[i] = 0;
return 0;
}
#if 0
static int gfar_proc_show(struct seq_file* m, void* v)
{
unsigned int i = 0;
PRTP_CH_DETAILS pRtp = NULL;
seq_printf(m, "--------GFAR ETH DRIVER INFO--------\n");
seq_puts(m, "\n");
seq_printf(m, "irq cnt: %u\n", g_irq_cnt);
seq_printf(m, "RTP PORT BASE = %d(0x%08X)\n", g_RtpPortBase, g_RtpPortBase);
for(i = 0; i < UMB_MAX_RTP_CFG; i++)
{
if(g_RtpPortIndex[i] != 0xFFFF)
{
seq_printf(m, "Ch %u Port %d\n", g_RtpPortIndex[i], i);
}
}
#if 1
for(i = 0; i < UMB_MAX_RTP_CH; i++)
{
pRtp = ipstack_hook_get_grtp(g_geths[0]) + i;
if(pRtp->sk != NULL)
{
seq_printf(m, "Ch %d Send MAC: %02X:%02X:%02X:%02X:%02X:%02X/%02X:%02X:%02X:%02X:%02X:%02X\n\n",
i,
pRtp->tx[0].data[0],
pRtp->tx[0].data[1],
pRtp->tx[0].data[2],
pRtp->tx[0].data[3],
pRtp->tx[0].data[4],
pRtp->tx[0].data[5],
pRtp->tx[1].data[0],
pRtp->tx[1].data[1],
pRtp->tx[1].data[2],
pRtp->tx[1].data[3],
pRtp->tx[1].data[4],
pRtp->tx[1].data[5]);
}
}
for(i = 0; i < UMB_MAX_RTP_CH; i++)
{
pRtp = ipstack_hook_get_grtp(g_geths[0]) + i;
if(pRtp->sk != NULL)
{
seq_printf(m, "ch[%u] current_krx:%p,status:%x,len:%x,sk@%p, send:%u, recv:%u, seq_send:%u, seq_recv:%u, lost:%u, buf:0x%02X, udprecv:%u\n",
i,
pRtp->current_krx,
pRtp->current_krx->status,
pRtp->current_krx->len,
pRtp->sk,
g_RtpChDbgs[i].uSendBytes,
g_RtpChDbgs[i].uRecBytes,
g_RtpChDbgs[i].uSendSeqLost,
g_RtpChDbgs[i].uRecvSeqLost,
g_RtpChDbgs[i].uLostPackages,
g_RtpChDbgs[i].uBufStatus,
g_RtpChDbgs[i].uUDPRecPackages++
);
}
}
#endif
return 0;
}
static int gfar_proc_open(struct inode* inode, struct file* file)
{
return single_open(file, gfar_proc_show, NULL);
}
static ssize_t gfar_proc_write(struct file* file, const char __user* userbuf,
size_t count, loff_t* data)
{
char buf[20];
if(count >= sizeof(buf))
{
printk("Input Params Error:count = %d, max size = %d\n", count, sizeof(buf));
return -1;
}
if(copy_from_user(buf, userbuf, count))
{
printk("Copy Data To Kernel Error\n");
return -2;
}
buf[count] = '\0';
if(strict_strtoul(buf, 0, (long unsigned int*)&g_GfarOption))
{
return -3;
}
printk("Set Options To [%u]\n", g_GfarOption);
return count;
}
static const struct file_operations gfar_proc_fops =
{
.open = gfar_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = gfar_proc_write,
};
#endif
static int rtp_kbuf_init(void)
{
int i;
InitDebugInfoProc("gfar");
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);
}
}
for(i = 0; i < UMB_MAX_GETH; i++)
{
struct ipstack_hook_t* pGfarHook = &ipstack_hook_p1010[i];
pGfarHook->kmap_len = sizeof(RTP_CH_DETAILS) * MAX_RTP_CH;
pGfarHook->kmap_addr = (uint8_t*)__get_free_pages(GFP_DMA32 | GFP_ATOMIC,
get_order(pGfarHook->kmap_len));
if(pGfarHook->kmap_addr)
{
pGfarHook->kmap_phy = virt_to_phys(pGfarHook->kmap_addr);
}
pGfarHook->kmap_end = (pGfarHook->kmap_addr + pGfarHook->kmap_len);
memset(pGfarHook->kmap_addr, 0, pGfarHook->kmap_len);
pGfarHook->pRtpChDetails = (PRTP_CH_DETAILS)pGfarHook->kmap_addr;
}
return 0;
}
static int rtp_kbuf_exit(void)
{
int i;
for(i = 0; i < UMB_MAX_GETH; i++)
{
struct ipstack_hook_t* pGfarHook = &ipstack_hook_p1010[i];
if(pGfarHook->kmap_addr)
{
free_pages((unsigned long)pGfarHook->kmap_addr,
get_order(pGfarHook->kmap_len));
pGfarHook->pRtpChDetails = NULL;
}
}
for(i = 0; i < sizeof(g_DbgFSConfig) / sizeof(g_DbgFSConfig[0]); i++)
{
DebugFsUnRegister(&g_DbgFSConfig[i]);
}
DeInitDebugInfoProc();
return 0;
}
static int timer_1ms_handle(void* pData)
{
/*
if(g_irq_cnt % 1000 == 0)
{
struct timeval ts;
//printk("%d.%d - %d.%d\n", ts.tv_sec, ts.tv_usec, g_Clock.tv_sec, g_Clock.tv_usec);
//printk("need = %d, rlt = %d, newTimerCnt = %d\n", need, rlt, newTimerCnt);
do_gettimeofday(&ts);
printk("Cnt = %d, Time:%d.%d\n", g_irq_cnt, ts.tv_sec, ts.tv_usec / 1000);
}
*/
if(irq_flags & IRQ_STOP)
{
#ifdef USED_FSL_TIMER
unregister_mpic_timer_irq(g_1ms_timer);
#else
unregister_ext_timer_irq(g_1ms_timer);
#endif
return 0;
}
g_irq_cnt++;
geth_timer_hook(g_irq_cnt);
if(irq_flags & IRQ_STOP)
{
#ifdef USED_FSL_TIMER
unregister_mpic_timer_irq(g_1ms_timer);
#else
unregister_ext_timer_irq(g_1ms_timer);
#endif
return 0;
}
return 0;
}
int geth_timer_init(int ms)
{
LOG_EX(LOG_Info, "USED MPIC TIMER......\n");
mrs_irq_init();
#ifdef USED_FSL_TIMER
g_1ms_timer = register_mpic_timer_irq(timer_1ms_handle, NULL);
#else
g_1ms_timer = register_ext_timer_irq(timer_1ms_handle, NULL);
#endif
rtp_kbuf_init();
return 0;
}
int geth_timer_exit(void)
{
irq_flags |= IRQ_STOP;
#ifdef USED_FSL_TIMER
unregister_mpic_timer_irq(g_1ms_timer);
#else
unregister_ext_timer_irq(g_1ms_timer);
#endif
msleep(10);
rtp_kbuf_exit();
mrs_irq_exit();
return 0;
}
static struct ipstack_hook_t ipstack_hook_p1010[UMB_MAX_GETH] =
{
{
.hook_init = ipstack_hook_init,
.hook_exit = ipstack_hook_exit,
.xmit_filter = ipstack_hook_xmit_filter,
.backlog = ipstack_hook_backlog,
.hook_xmit = NULL,
.backlog_xmit = ipstack_hook_backlog_xmit,
.get_grtp = ipstack_hook_get_grtp,
.gptimer_init = geth_timer_init,
.gptimer_exit = geth_timer_exit,
.is_rtp_kbuf = is_rtp_kbuf,
.do_sock_send = NULL,
.do_sock_recv = ipstack_hook_udp_recv,
.rtpMaxCh = MAX_RTP_CH,
.rtpBasePort = 0xFFFF,
.rtpPortStep = 0,
.rtpCfgCh = 0,
},
{
.hook_init = ipstack_hook_init,
.hook_exit = ipstack_hook_exit,
.xmit_filter = ipstack_hook_xmit_filter_eth2,
.backlog = ipstack_hook_backlog,
.hook_xmit = NULL,
.backlog_xmit = ipstack_hook_backlog_xmit,
.get_grtp = ipstack_hook_get_grtp,
.gptimer_init = geth_timer_init,
.gptimer_exit = geth_timer_exit,
.is_rtp_kbuf = is_rtp_kbuf,
.do_sock_send = NULL,
.do_sock_recv = ipstack_hook_udp_recv_sip,
.rtpMaxCh = MAX_SIP_CH,
.rtpBasePort = 0xFFFF,
.rtpPortStep = 0,
.rtpCfgCh = 0,
},
{
.hook_init = ipstack_hook_init,
.hook_exit = ipstack_hook_exit,
.backlog = ipstack_hook_backlog,
.xmit_filter = ipstack_hook_xmit_filter_eth2,
.hook_xmit = NULL,
.backlog_xmit = ipstack_hook_backlog_xmit,
.get_grtp = ipstack_hook_get_grtp,
.gptimer_init = geth_timer_init,
.gptimer_exit = geth_timer_exit,
.is_rtp_kbuf = is_rtp_kbuf,
.do_sock_send = NULL,
.do_sock_recv = ipstack_hook_udp_recv_sip,
.rtpMaxCh = MAX_SIP_CH,
.rtpBasePort = 0xFFFF,
.rtpPortStep = 0,
.rtpCfgCh = 0,
},
};
static int DbgFS_GianfarARPShow(struct seq_file* seq, void* token)
{
unsigned int opt = g_DbgFSConfig[0].params;
int i = 0;
int ucc = opt > 2 ? 0 : opt;
PRTP_CH_DETAILS pRtpBase = ipstack_hook_get_grtp(g_geths[ucc]);
struct ipstack_hook_t* pGfarHook = ipstack_hook_get(ucc);
if(token == SEQ_START_TOKEN)
{
seq_printf(seq, "Gainfar ETH%d RTP Ch ARP Mac Info:\n", ucc);
seq_printf(seq, "---------------------------------------------------\n");
for(i = 0; i < pGfarHook->rtpCfgCh; i++)
{
PRTP_CH_DETAILS pRtp = pRtpBase + i;
if(pRtp->sk != NULL)
{
seq_printf(seq, "Ch %d Send MAC: %02X:%02X:%02X:%02X:%02X:%02X/%02X:%02X:%02X:%02X:%02X:%02X\n\n",
i,
pRtp->tx[0].data[0],
pRtp->tx[0].data[1],
pRtp->tx[0].data[2],
pRtp->tx[0].data[3],
pRtp->tx[0].data[4],
pRtp->tx[0].data[5],
pRtp->tx[1].data[0],
pRtp->tx[1].data[1],
pRtp->tx[1].data[2],
pRtp->tx[1].data[3],
pRtp->tx[1].data[4],
pRtp->tx[1].data[5]);
}
}
}
return 0;
}
static int DbgFS_GianfarChRTPShow(struct seq_file* seq, void* token)
{
unsigned int opt = g_DbgFSConfig[1].params;
int i = 0;
int ucc = opt > 2 ? 0 : opt;
struct ipstack_hook_t* pGfarHook = ipstack_hook_get(ucc);
PRTP_CH_DETAILS pRtpBase = ipstack_hook_get_grtp(g_geths[ucc]);
if(token == SEQ_START_TOKEN)
{
seq_printf(seq, "irq cnt: %u\n", g_irq_cnt);
seq_printf(seq, "Gainfar ETH%d Ch RTP Info:\n", ucc);
seq_printf(seq, "---------------------------------------------------\n");
for(i = 0; i < pGfarHook->rtpMaxCh; i++)
{
PRTP_CH_DETAILS pRtp = pRtpBase + i;
if(pRtp->sk != NULL)
{
seq_printf(seq, "ch[%u] current_krx:%p,status:%x,len:%x,sk@%p, send:%u, recv:%u, seq_send:%u, seq_recv:%u, lost:%u, buf:0x%02X, udprecv:%u\n",
i,
pRtp->current_krx,
pRtp->current_krx->status,
pRtp->current_krx->len,
pRtp->sk,
pGfarHook->rtpChDbgs[i].uSendBytes,
pGfarHook->rtpChDbgs[i].uRecBytes,
pGfarHook->rtpChDbgs[i].uSendSeqLost,
pGfarHook->rtpChDbgs[i].uRecvSeqLost,
pGfarHook->rtpChDbgs[i].uLostPackages,
pGfarHook->rtpChDbgs[i].uBufStatus,
pGfarHook->rtpChDbgs[i].uUDPRecPackages
);
}
}
}
return 0;
}
static int DbgFS_GianfarChPortShow(struct seq_file* seq, void* token)
{
unsigned int opt = g_DbgFSConfig[2].params;
int i = 0;
int ucc = opt > 2 ? 0 : opt;
struct ipstack_hook_t* pGfarHook = ipstack_hook_get(ucc);
if(token == SEQ_START_TOKEN)
{
seq_printf(seq, "Gainfar ETH%d Ch Port Info:\n", ucc);
seq_printf(seq, "---------------------------------------------------\n");
seq_printf(seq, "RTP PORT BASE = %u, Max Ch = %u, Configured Ch = %u\n",
pGfarHook->rtpBasePort,
pGfarHook->rtpMaxCh,
pGfarHook->rtpCfgCh);
for(i = 0; i < pGfarHook->rtpMaxCh; i++)
{
if(pGfarHook->rtpPortIndex[i] != 0xFFFF)
{
seq_printf(seq, "Ch %u Port %d\n", pGfarHook->rtpPortIndex[i],
pGfarHook->rtpBasePort + (i * pGfarHook->rtpPortStep));
}
}
}
return 0;
}
#ifdef EN_SIP_SWITCH
static int DbgFS_SipArpShow(struct seq_file* seq, void* token)
{
unsigned int opt = g_DbgFSConfig[4].params;
unsigned char mac[12];
int ret, i = 0;
if(token == SEQ_START_TOKEN)
{
for(i = 0; i < 3; i++)
{
if(g_geths[i] != NULL)
{
ret = get_mac_form_ip(mac, i, g_geths[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_geths[i]->ucc_num,
(g_geths[i]->chGWIpAddr >> 24) & 0xFF,
(g_geths[i]->chGWIpAddr >> 16) & 0xFF,
(g_geths[i]->chGWIpAddr >> 8) & 0xFF,
g_geths[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, 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, 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);
}
}
}
static int DbgFS_GianfarSipPortShow(struct seq_file* seq, void* token)
{
unsigned int opt = g_DbgFSConfig[3].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_geths[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_geths[i], g_geths[i]->ucc_num,
(g_geths[i]->chIpAddr >> 24) & 0xFF,
(g_geths[i]->chIpAddr >> 16) & 0xFF,
(g_geths[i]->chIpAddr >> 8) & 0xFF,
g_geths[i]->chIpAddr & 0xFF,
(g_geths[i]->chGWIpAddr >> 24) & 0xFF,
(g_geths[i]->chGWIpAddr >> 16) & 0xFF,
(g_geths[i]->chGWIpAddr >> 8) & 0xFF,
g_geths[i]->chGWIpAddr & 0xFF,
(g_geths[i]->chGWMask >> 24) & 0xFF,
(g_geths[i]->chGWMask >> 16) & 0xFF,
(g_geths[i]->chGWMask >> 8) & 0xFF,
g_geths[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 In IP: %d.%d.%d.%d\n",
(pCh->portRTP.chLinkInfo.inTarget.ipAddr >> 24) & 0xFF,
(pCh->portRTP.chLinkInfo.inTarget.ipAddr >> 16) & 0xFF,
(pCh->portRTP.chLinkInfo.inTarget.ipAddr >> 8) & 0xFF,
pCh->portRTP.chLinkInfo.inTarget.ipAddr & 0xFF);
seq_printf(seq, "RTP In Port: %d\n", pCh->portRTP.chLinkInfo.inTarget.ipPort);
seq_printf(seq, "RTP In Mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
pCh->portRTP.chLinkInfo.inTarget.ethAddr[0],
pCh->portRTP.chLinkInfo.inTarget.ethAddr[1],
pCh->portRTP.chLinkInfo.inTarget.ethAddr[2],
pCh->portRTP.chLinkInfo.inTarget.ethAddr[3],
pCh->portRTP.chLinkInfo.inTarget.ethAddr[4],
pCh->portRTP.chLinkInfo.inTarget.ethAddr[5]);
seq_printf(seq, "RTP Used Target: 0x%08X\n\n", pCh->portRTP.chLinkInfo.usdTarget);
seq_printf(seq, "RTP Stun Tag: %d\n", pCh->portRTP.chLinkInfo.stunTags);
seq_printf(seq, "ETH0 Recv: %d\n", pCh->sipDebug.cnt_eth0_recv);
seq_printf(seq, "ETH0 Switch: %d\n", pCh->sipDebug.cnt_eth0_2_ethx);
seq_printf(seq, "ETH0 Mask: 0x%08X\n", pCh->sipDebug.mask_eth0_2_ethx);
seq_printf(seq, "ETH0 lost: %d\n", pCh->sipDebug.eth0_seq_error);
seq_printf(seq, "ETH0 drop: %d\n\n", pCh->sipDebug.eth0_drop_src);
seq_printf(seq, "ETHx Recv: %d\n", pCh->sipDebug.cnt_ethx_recv);
seq_printf(seq, "ETHx Switch: %d\n", pCh->sipDebug.cnt_ethx_2_eth0);
seq_printf(seq, "ETHx Mask: 0x%08X\n", pCh->sipDebug.mask_ethx_2_eth0);
seq_printf(seq, "ETHx lost: %d\n", pCh->sipDebug.ethx_seq_error);
seq_printf(seq, "ETHx drop: %d\n\n", pCh->sipDebug.ethx_drop_src);
if(g_CheckRFC2833)
{
seq_printf(seq, "ETHx Error Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_error);
seq_printf(seq, "ETHx Drv Err Dtmf: %d\n", pCh->sipDebug.drv_rcv_rfc2833_error);
}
seq_printf(seq, "ETHx Rcv Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_recv);
seq_printf(seq, "ETHx Rcv lost Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_rcv_lost);
seq_printf(seq, "ETHx Snd lost Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_snd_lost);
seq_printf(seq, "ETHx 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);
if(pCh->dtmfSendFifo.buffer != NULL)
{
kfifo_free(&pCh->dtmfSendFifo);
}
rlt = kfifo_alloc(&pCh->dtmfSendFifo, MAX_DTMF_SEND_BUF, GFP_KERNEL);
if(pCh->dtmfRecvFifo.buffer != NULL)
{
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)
{
#if USED_MALLOC_CHDETIAL
if(g_SIPChInfo.pSipChDetial != NULL)
{
kfree(g_SIPChInfo.pSipChDetial);
g_SIPChInfo.pSipChDetial = NULL;
}
g_SIPChInfo.pSipChDetial = kmalloc(sizeof(SIP_CH_DETIAL) * maxSIPCh,
GFP_ATOMIC);
if(g_SIPChInfo.pSipChDetial == NULL)
{
return -1;
}
#endif
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 != ETH_INTERFACE_2 && ethId != ETH_INTERFACE_1)
{
return -1;
}
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(pCh->portRTP.chStatus == CH_STATUS_UNKONWN)
{
return -1;
}
get_mac_form_ip(macAddr, pCh->sipETHId, 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;
memset(pCh->portRTP.chLinkInfo.inTarget.ethAddr, 0xFF, ETH_ALEN);
pCh->portRTP.chLinkInfo.inTarget.ipAddr = 0;
pCh->portRTP.chLinkInfo.inTarget.ipPort = 0;
pCh->portRTP.chLinkInfo.usdTarget = 0;
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];
get_mac_form_ip(macAddr, ETH_INTERFACE_0, 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);
memset(pPort->chLinkInfo.inTarget.ethAddr, 0xFF, 6);
pPort->chLinkInfo.inTarget.ipAddr = 0;
pPort->chLinkInfo.inTarget.ipPort = 0;
}
}
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 config_eth_ipaddr(unsigned int ethId, __be32 ipaddr, __be32 gwaddr, __be32 gwmask)
{
struct gfar_private* pGfar = NULL;
if(ethId <= ETH_INTERFACE_2)
{
pGfar = g_geths[ethId];
if(pGfar != NULL)
{
pGfar->chIpAddr = ipaddr;
pGfar->chGWIpAddr = gwaddr;
pGfar->chGWMask = gwmask;
}
if(gwaddr != 0)
{
make_arp_request(ethId, gwaddr);
}
}
return -1;
}
EXPORT_SYMBOL(config_eth_ipaddr);
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;
}
rlt = kfifo_out(&pCh->dtmfRecvFifo, &value, 4);
if(rlt == 4)
{
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];
}
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]);
if(kfifo_in(&pCh->dtmfSendFifo, &dtmf, 1) != 1)
{
pCh->sipDebug.ethx_rfc2833_snd_lost++;
return -1;
}
}
return i;
}
EXPORT_SYMBOL(sip_send_dtmf);
static 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);
}
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 = *(unsigned short*)(skb->data + 30 + 4);
timeStamp = *(unsigned int*)(skb->data + 32 + 4);
syncId = *(unsigned int*)(skb->data + 36 + 4);
}
else
{
dtmfIndex = *(unsigned char*)(skb->data + 40);
endFlag = *(unsigned char*)(skb->data + 41);
seqNumber = *(unsigned short*)(skb->data + 30);
timeStamp = *(unsigned int*)(skb->data + 32);
syncId = *(unsigned int*)(skb->data + 36);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>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);
}
}
// <20>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD>
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++)
{
// ͬһ<CDAC><D2BB>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))
{
if(kfifo_in(&pCh->dtmfRecvFifo, &dtmfIndex, 4) != 4)
{
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)
{
PIP_ADDR_INFO pIpAddr = NULL;
if(pPort->chLinkInfo.dstTarget.ipAddr == 0xFFFFFFFF
|| ethId == ETH_INTERFACE_0)
{
pIpAddr = &pPort->chLinkInfo.inTarget;
pPort->chLinkInfo.usdTarget |= 1 << 3;
}
else
{
pIpAddr = &pPort->chLinkInfo.dstTarget;
pPort->chLinkInfo.usdTarget |= 1 << 4;
}
if(pIpAddr->ethAddr[0] == 0xFF
&& pIpAddr->ethAddr[1] == 0xFF
&& pIpAddr->ethAddr[2] == 0xFF
&& pIpAddr->ethAddr[3] == 0xFF
&& pIpAddr->ethAddr[4] == 0xFF
&& pIpAddr->ethAddr[5] == 0xFF
)
{
return get_mac_form_ip(pIpAddr->ethAddr,
ethId,
pIpAddr->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;
PIP_ADDR_INFO pIpAddr = NULL;
PSIP_CH_DETIAL pCh = &g_SIPChInfo.pSipChDetial[sipCh];
struct sk_buff* skbSIP = skb_clone(skb, GFP_ATOMIC);
struct gfar_private* ucc_drv = g_geths[ethId];
if(skbSIP == NULL)
{
return NULL;
}
dev_kfree_skb_any(skb);
skbSIP->dev = ucc_drv->ndev;
eth_header(skbSIP, ucc_drv->ndev, ETH_P_IP, NULL, NULL, skbSIP->len);
pHead = (PPACKAGE_HEAD)skbSIP->data;
if(pPort->chLinkInfo.dstTarget.ipAddr == 0xFFFFFFFF)
{
pIpAddr = &pPort->chLinkInfo.inTarget;
pPort->chLinkInfo.usdTarget = 1 << 1;
if(pIpAddr->ipAddr == 0 || pIpAddr->ipPort == 0)
{
dev_kfree_skb_any(skbSIP);
return NULL;
}
}
else
{
pIpAddr = &pPort->chLinkInfo.dstTarget;
pPort->chLinkInfo.usdTarget = 1 << 2;
}
if(pPort->chLinkInfo.toRTPCh.isUpdate == 0)
{
if(pIpAddr->ethAddr[0] == 0xFF
&& pIpAddr->ethAddr[1] == 0xFF
&& pIpAddr->ethAddr[2] == 0xFF
&& pIpAddr->ethAddr[3] == 0xFF
&& pIpAddr->ethAddr[4] == 0xFF
&& pIpAddr->ethAddr[5] == 0xFF
)
{
get_mac_form_ip(pIpAddr->ethAddr,
ETH_INTERFACE_0,
pIpAddr->ipAddr, 5);
}
memcpy(pHead->ethHead.h_dest,
pIpAddr->ethAddr, ETH_ALEN);
pHead->ipHead.saddr = ucc_drv->chIpAddr;
pHead->ipHead.daddr = pIpAddr->ipAddr;
pHead->udpHead.source = g_SIPChInfo.iRTPPortBase + sipCh;
pHead->udpHead.dest = pIpAddr->ipPort;
memcpy(&pPort->chLinkInfo.toRTPCh.headValue,
pHead,
sizeof(PACKAGE_HEAD));
pPort->chLinkInfo.toRTPCh.isUpdate = 1;
}
else
{
PACKAGE_HEAD ipHead = *pHead;
if((pIpAddr->ethAddr[0] == 0xFF
&& pIpAddr->ethAddr[1] == 0xFF
&& pIpAddr->ethAddr[2] == 0xFF
&& pIpAddr->ethAddr[3] == 0xFF
&& pIpAddr->ethAddr[4] == 0xFF
&& pIpAddr->ethAddr[5] == 0xFF)
|| pCh->sipDebug.cnt_eth0_2_ethx % 1000 == 0
)
{
if(get_mac_form_ip(pIpAddr->ethAddr,
ethId,
pIpAddr->ipAddr, 6) == 0)
{
memcpy(&pPort->chLinkInfo.toRTPCh.headValue,
pIpAddr->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)
{
int rlt = kfifo_out(&pCh->dtmfSendFifo,
&pCh->rfc2833DTMF.dtmfSendBuf.dtmfValue, 1);
if(rlt == 1)
{
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 = 24;
pHead->udpHead.check = 0;
pHead->ipHead.tot_len = 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 = *(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 = pCh->portRTP.chLinkInfo.stunTags;
pTags++;
*pTags = pHead->udpHead.len - 8;
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(ipstack_hook_backlog(skbSIP) == 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);
struct gfar_private* ucc_drv = g_geths[ETH_INTERFACE_0];
PSIP_CH_DETIAL pCh = &g_SIPChInfo.pSipChDetial[sipCh];
if(skbSIP == NULL)
{
return NULL;
}
dev_kfree_skb_any(skb);
skbSIP->dev = ucc_drv->ndev;
eth_header(skbSIP, ucc_drv->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,
ETH_INTERFACE_0,
pPort->chLinkInfo.dstTarget.ipAddr, 7);
}
memcpy(pHead->ethHead.h_dest,
pPort->chLinkInfo.dstTarget.ethAddr, ETH_ALEN);
pHead->ipHead.saddr = ucc_drv->chIpAddr;
pHead->ipHead.daddr = pPort->chLinkInfo.dstTarget.ipAddr;
pHead->udpHead.source = pPort->ipPort;
pHead->udpHead.dest = 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,
ETH_INTERFACE_0,
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(ipstack_hook_backlog(skbSIP) == NETDEV_TX_OK)
{
pCh->sipDebug.cnt_ethx_2_eth0++;
}
return skbSIP;
}
static int ipstack_hook_udp_recv_sip(struct sk_buff* skb)
{
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;
struct gfar_private* ucc_drv = g_geths[ETH_INTERFACE_0];
int ucc = ((struct gfar_private*)netdev_priv(skb->dev))->ucc_num;
struct sk_buff* skbSIP;
unsigned short seq_index = *(unsigned short*)&skb->data[RECV_SEQ_POS];
unsigned char* pUdpData = (unsigned char*)(skb->data + 28);
int udp_len = udphdr->len;
// 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(iphdr->daddr != g_geths[ucc]->chIpAddr)
{
return 0;
}
// SPI Ch Package
if(udphdr->dest >= g_SIPChInfo.iRTPPortBase &&
udphdr->dest < (g_SIPChInfo.iRTPPortBase + g_SIPChInfo.iTotalCh))
{
int sipCh = (udphdr->dest - g_SIPChInfo.iRTPPortBase);
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 = 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 != 0xFFFFFFFF)
{
if(pCh->portRTP.chLinkInfo.dstTarget.ipAddr != iphdr->saddr
|| pCh->portRTP.chLinkInfo.dstTarget.ipPort != udphdr->source)
{
pCh->sipDebug.ethx_drop_src++;
dev_kfree_skb_any(skb);
return udp_len;
}
}
pCh->portRTP.chLinkInfo.inTarget.ipAddr = iphdr->saddr;
pCh->portRTP.chLinkInfo.inTarget.ipPort = udphdr->source;
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
{
int iStatus = 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, ETH_INTERFACE_0) == -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 == ucc_drv->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, ETH_INTERFACE_0) == -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, ETH_INTERFACE_0) == -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;
}
#endif