2961 lines
86 KiB
C
2961 lines
86 KiB
C
#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
|