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

2961 lines
86 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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