summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/net/rtl/fastpath/fastpath_common.c
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2012-09-13 00:40:35 +0300
committerRoman Yeryomin <roman@advem.lv>2012-12-03 00:13:21 +0200
commit5deb3317cb51ac52de922bb55f8492624018906d (patch)
treec2fbe6346699d9bb0f2100490c3029519bb8fde8 /target/linux/realtek/files/net/rtl/fastpath/fastpath_common.c
parent0239d37124f9184b478a42de8a7fa1bc85a6a6fe (diff)
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/net/rtl/fastpath/fastpath_common.c')
-rw-r--r--target/linux/realtek/files/net/rtl/fastpath/fastpath_common.c867
1 files changed, 867 insertions, 0 deletions
diff --git a/target/linux/realtek/files/net/rtl/fastpath/fastpath_common.c b/target/linux/realtek/files/net/rtl/fastpath/fastpath_common.c
new file mode 100644
index 000000000..4f17c5b45
--- /dev/null
+++ b/target/linux/realtek/files/net/rtl/fastpath/fastpath_common.c
@@ -0,0 +1,867 @@
+#if !defined(CONFIG_RTK_VLAN_SUPPORT)
+#include <net/rtl/rtl_types.h>
+#endif
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+#ifdef CONFIG_BRIDGE
+#include <bridge/br_private.h>
+#endif
+
+#if defined (FAST_PPTP) || defined(FAST_L2TP)
+ #include <net/ip.h>
+#endif
+
+#if defined(CONFIG_NET_SCHED)
+#include <linux/netfilter_ipv4/ip_tables.h>
+extern int gQosEnabled;
+#endif
+
+#include <net/rtl/fastpath/fastpath_core.h>
+#if defined(CONFIG_RTL_NF_CONNTRACK_GARBAGE_NEW)
+#include <net/rtl/features/rtl_features.h>
+#endif
+#include <net/rtl/rtl865x_nat.h>
+
+#if defined(CONFIG_RTL_NF_CONNTRACK_GARBAGE_NEW)
+static int rtl_fp_gc_rx_threshold;
+#endif
+static int fast_nat_fw = 1;
+
+#if defined(CONFIG_PROC_FS)
+static struct proc_dir_entry *res1=NULL;
+static int read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ #if defined(CONFIG_RTL_NF_CONNTRACK_GARBAGE_NEW)
+ len = sprintf(page, "fastpath %s, GC_RX_Count %d, Status: %d\n", fast_nat_fw!=0?"Enabled":"Disabled", rtl_fp_gc_rx_threshold, rtl_newGC_session_status_flags);
+ #else
+ len = sprintf(page, "fastpath: [%d]\n", fast_nat_fw+10);
+ #endif
+ len = fastpath_dump_napt_entry_num(page, len);
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+ return len;
+
+}
+static int write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ unsigned char tmpbuf[16];
+ struct net *net;
+
+ if (count < 2)
+ return -EFAULT;
+
+ memset(tmpbuf, 0, sizeof(tmpbuf));
+ if (buffer && !copy_from_user(tmpbuf, buffer, count)) {
+ if (tmpbuf[0] == '2'&&count==2){
+ /* first byte == 2, second byte == "enter" */
+ for_each_net(net) {
+ nf_conntrack_flush(net, 0, 0); //clean conntrack table
+ }
+ #if defined(CONFIG_RTL_LAYERED_DRIVER_L4) && defined(CONFIG_RTL_8198)
+ rtl865x_nat_reinit();
+ /* the following 2 values MUST set behind reinit nat module */
+ rtl_nat_expire_interval_update(RTL865X_PROTOCOL_TCP, tcp_get_timeouts_by_state(TCP_CONNTRACK_ESTABLISHED));
+ rtl_nat_expire_interval_update(RTL865X_PROTOCOL_UDP, nf_ct_udp_timeout>nf_ct_udp_timeout_stream?nf_ct_udp_timeout:nf_ct_udp_timeout_stream);
+ #endif
+ }else{
+ sscanf(tmpbuf, "%d", &fast_nat_fw);
+ #if defined(CONFIG_RTL_NF_CONNTRACK_GARBAGE_NEW)
+ if (fast_nat_fw>2) {
+ rtl_fp_gc_rx_threshold = fast_nat_fw;
+ }
+ #endif
+ }
+ return count;
+ }
+
+ return -EFAULT;
+}
+#endif
+
+#if defined(CONFIG_RTL_HW_QOS_SUPPORT)
+int32 rtl_qosGetSkbMarkByNaptEntry(rtl865x_napt_entry *naptEntry, rtl865x_qos_mark *qosMark, struct sk_buff *pskb)
+{
+ struct iphdr *iph;
+ struct tcphdr *tcphupuh; //just keep one , don't care tcp or udp //
+ u_int ori_saddr, ori_daddr;
+ u_short ori_sport, ori_dport;
+ struct net_device *lanDev, *wanDev;
+ struct dst_entry *dst_tmp;
+ unsigned char oriSrcMac[6],oriDstMac[6],resMac[14];
+ u_short proto;
+ unsigned char pppProto[2],ipProto[2];
+ __u32 oriSkbMark;
+ unsigned long irq_flags;
+ uint32 preMark, postMark;
+
+ if(pskb==NULL)
+ return FAILED;
+
+ //initial
+ pppProto[0]=0x00;
+ pppProto[1]=0x21;
+ ipProto[0]=0x08;
+ ipProto[1]=0x00;
+
+ lanDev=rtl865x_getLanDev();
+ wanDev=rtl865x_getWanDev();
+ proto = ntohs(pskb->protocol);
+ iph = ip_hdr(pskb);
+ tcphupuh = (struct tcphdr*)((__u32 *)iph + iph->ihl);
+
+ //To bak origal protol mac
+ memcpy(oriSrcMac,eth_hdr(pskb)->h_source,ETH_ALEN);
+ memcpy(oriDstMac,eth_hdr(pskb)->h_dest,ETH_ALEN);
+
+ //Bak orignal skb mark
+ oriSkbMark=pskb->mark;
+
+ //check ip-based qos rule at iptables mangle table
+ //To record original info
+ ori_saddr=iph->saddr;
+ ori_sport=tcphupuh->source;
+ ori_daddr=iph->daddr;
+ ori_dport=tcphupuh->dest;
+
+ /* for dst mac match, please refer to the xt_mac.c */
+ dst_tmp = pskb->dst;
+ pskb->dst = NULL;
+
+ //For uplink
+#if defined(CONFIG_NET_SCHED)
+ preMark = 0;
+ postMark= 0;
+ {
+ //Replace source addr to check uplink mark
+ iph->saddr=naptEntry->intIp;
+ tcphupuh->source=naptEntry->intPort;
+ iph->daddr=naptEntry->remIp;
+ tcphupuh->dest=naptEntry->remPort;
+
+ memset(resMac,0,14);
+ if((lanDev!=NULL)&&(arp_req_get_ha(naptEntry->intIp,lanDev,resMac)==0))
+ {
+ //Patch for pppoe wantype: run udp chariot
+ //bak skb mac header
+ if((memcmp(pskb->data-2, pppProto,2)==0) //equal 0x0021
+ &&(skb_mac_header_was_set(pskb)==1)
+ &&(eth_hdr(pskb)->h_proto!=ntohs(0x0800))) //not equal to 0x0800
+ {
+ skb_set_mac_header(pskb, -22);
+ }
+
+ //Replace source mac addr to check uplink mark
+ memcpy(eth_hdr(pskb)->h_source,resMac, ETH_ALEN);
+ memcpy(eth_hdr(pskb)->h_dest,lanDev->dev_addr, ETH_ALEN);
+ }
+
+ pskb->mark=0;//initial
+ if(proto == ETH_P_IP){
+ (list_empty(&nf_hooks[PF_INET][NF_IP_PRE_ROUTING]))?: \
+ ipt_do_table(pskb, NF_IP_PRE_ROUTING, lanDev,wanDev,\
+ dev_net(lanDev)->ipv4.iptable_mangle);
+ }
+
+ DEBUGP_API("[%s][%d]:[%s][%s][%s][%s][%d]\n", __FUNCTION__, __LINE__,
+ lanDev?lanDev->name:"NULL",
+ wanDev?wanDev->name:"NULL",
+ pskb->inDev?pskb->inDev->name:"NULL",
+ pskb->dev?pskb->dev->name:"NULL", pskb->mark);
+ preMark = pskb->mark;
+
+ //Replace dest addr to check uplink mark
+ iph->saddr=naptEntry->extIp;
+ tcphupuh->source=naptEntry->extPort;
+ iph->daddr=naptEntry->remIp;
+ tcphupuh->dest=naptEntry->remPort;
+
+ memset(resMac,0,14);
+ if((wanDev!=NULL)&&(arp_req_get_ha(naptEntry->remIp,wanDev,resMac)==0))
+ {
+ //Patch for pppoe wantype: run udp chariot
+ //bak skb mac header
+ if((memcmp(pskb->data-2, pppProto,2)==0) //equal 0x0021
+ &&(skb_mac_header_was_set(pskb)==1)
+ &&(eth_hdr(pskb)->h_proto!=ntohs(0x0800))) //not equal to 0x0800
+ {
+ skb_set_mac_header(pskb, -22);
+ }
+
+ //Replace source mac addr to check uplink mark
+ memcpy(eth_hdr(pskb)->h_dest,resMac, ETH_ALEN);
+ memcpy(eth_hdr(pskb)->h_source,wanDev->dev_addr, ETH_ALEN);
+ }
+
+ pskb->mark=0;//initial
+ if(proto == ETH_P_IP){
+ (list_empty(&nf_hooks[PF_INET][NF_IP_POST_ROUTING]))?: \
+ ipt_do_table(pskb, NF_IP_POST_ROUTING, lanDev, wanDev,\
+ dev_net(wanDev)->ipv4.iptable_mangle);
+ }
+ DEBUGP_API("[%s][%d]:[%s][%s][%s][%s][%d]\n", __FUNCTION__, __LINE__,
+ lanDev?lanDev->name:"NULL",
+ wanDev?wanDev->name:"NULL",
+ pskb->inDev?pskb->inDev->name:"NULL",
+ pskb->dev?pskb->dev->name:"NULL", pskb->mark);
+ postMark= pskb->mark;
+ }
+
+ qosMark->uplinkMark=(postMark?postMark:preMark);
+#endif
+
+ //for downlink
+#if defined(CONFIG_NET_SCHED)
+ preMark = 0;
+ postMark = 0;
+ {
+ //Replace source addr to check uplink mark
+ iph->saddr=naptEntry->remIp;
+ tcphupuh->source=naptEntry->remPort;
+ iph->daddr=naptEntry->extIp;
+ tcphupuh->dest=naptEntry->extPort;
+
+ memset(resMac,0,14);
+ if((wanDev!=NULL)&&(arp_req_get_ha(naptEntry->remIp,wanDev,resMac)==0))
+ {
+ //Patch for pppoe wantype: run udp chariot
+ if((memcmp(pskb->data-2, pppProto,2)==0) //equal 0x0021
+ &&(skb_mac_header_was_set(pskb)==1)
+ &&(eth_hdr(pskb)->h_proto!=ntohs(0x0800))) //not equal to 0x0800
+ {
+ skb_set_mac_header(pskb, -22);
+ }
+
+ //Replace source mac addr to check uplink mark
+ memcpy(eth_hdr(pskb)->h_source,resMac, ETH_ALEN);
+ memcpy(eth_hdr(pskb)->h_dest, wanDev->dev_addr, ETH_ALEN);
+ }
+
+ pskb->mark=0;//initial
+ if(proto == ETH_P_IP){
+ (list_empty(&nf_hooks[PF_INET][NF_IP_PRE_ROUTING]))?: \
+ ipt_do_table(pskb, NF_IP_PRE_ROUTING, wanDev,lanDev,\
+ dev_net(wanDev)->ipv4.iptable_mangle);
+ }
+ DEBUGP_API("[%s][%d]:[%s][%s][%s][%s][%d]\n", __FUNCTION__, __LINE__,
+ lanDev?lanDev->name:"NULL",
+ wanDev?wanDev->name:"NULL",
+ pskb->inDev?pskb->inDev->name:"NULL",
+ pskb->dev?pskb->dev->name:"NULL", pskb->mark);
+ preMark = pskb->mark;
+
+ //Replace dest addr to check uplink mark
+ iph->saddr=naptEntry->remIp;
+ tcphupuh->source=naptEntry->remPort;
+ iph->daddr=naptEntry->intIp;
+ tcphupuh->dest=naptEntry->intPort;
+
+ memset(resMac,0,14);
+ if ((lanDev!=NULL)&&(arp_req_get_ha(naptEntry->intIp,lanDev,resMac)==0))
+ {
+ //Patch for pppoe wantype: run udp chariot
+ if((memcmp(pskb->data-2, pppProto,2)==0) //equal 0x0021
+ &&(skb_mac_header_was_set(pskb)==1)
+ &&(eth_hdr(pskb)->h_proto!=ntohs(0x0800))) //not equal to 0x0800
+ {
+ skb_set_mac_header(pskb, -22);
+ }
+ //Replace dest mac addr and hh data mac to check uplink mark
+ memcpy(eth_hdr(pskb)->h_dest,resMac,ETH_ALEN);
+ memcpy(eth_hdr(pskb)->h_source, lanDev->dev_addr, ETH_ALEN);
+ }
+ pskb->mark=0;//initial
+
+ if(proto == ETH_P_IP){
+ (list_empty(&nf_hooks[PF_INET][NF_IP_POST_ROUTING]))?: \
+ ipt_do_table(pskb, NF_IP_POST_ROUTING, wanDev, lanDev,\
+ dev_net(lanDev)->ipv4.iptable_mangle);
+ }
+ DEBUGP_API("[%s][%d]:[%s][%s][%s][%s][%d]\n", __FUNCTION__, __LINE__,
+ lanDev?lanDev->name:"NULL",
+ wanDev?wanDev->name:"NULL",
+ pskb->inDev?pskb->inDev->name:"NULL",
+ pskb->dev?pskb->dev->name:"NULL", pskb->mark);
+ postMark= pskb->mark;
+ }
+ qosMark->downlinkMark=(postMark?postMark:preMark);
+#endif
+
+ //Back to original value
+ //Back to orignal protol mac
+ memcpy(eth_hdr(pskb)->h_source,oriSrcMac, ETH_ALEN);
+ memcpy(eth_hdr(pskb)->h_dest,oriDstMac, ETH_ALEN);
+
+ //Back to original skb mark
+ pskb->mark=oriSkbMark;
+
+ //back to original info
+ iph->saddr=ori_saddr;
+ tcphupuh->source=ori_sport;
+ iph->daddr=ori_daddr;
+ tcphupuh->dest=ori_dport;
+
+ pskb->dst = dst_tmp;
+
+ if(lanDev)
+ dev_put(lanDev);
+
+ if(wanDev)
+ dev_put(wanDev);
+
+ return SUCCESS;
+}
+#endif
+
+
+void fastpath_set_qos_mark(struct sk_buff *skb, unsigned int preRouteMark, unsigned int postRouteMark)
+{
+ if(skb->mark == 0)
+ skb->mark = (postRouteMark?postRouteMark:preRouteMark);
+}
+
+#if defined(FAST_L2TP)
+static inline void enter_fast_path_fast_l2tp_pre_process(struct sk_buff *skb)
+{
+ struct net_device *l2tprx_dev;
+ struct in_device *skbIn_dev;
+ struct net_device *skbNetDevice;
+
+ if(fast_l2tp_fw){
+ l2tprx_dev = skb->dev;
+ skbIn_dev = (struct in_device *)skb->dev->ip_ptr;
+ if(skbIn_dev == NULL){
+ if ((skbNetDevice = __dev_get_by_name(&init_net,l2tprx_dev->name)) != NULL){
+ if((skbIn_dev= (struct in_device*)skbNetDevice->ip_ptr) != NULL)
+ skb->dev->ip_ptr = (void *)skbIn_dev;
+ }
+ }
+ }
+}
+#endif
+
+#if defined(CONFIG_RTL_NF_CONNTRACK_GARBAGE_NEW)
+static inline int rtl_fp_gc_status_check_priority(uint32 sIp, uint32 dIp, uint16 sPort, uint16 dPort)
+{
+ extern unsigned int _br0_ip;
+
+ #define RTL_FP_GC_HIGH_PRIORITY_PORT_CHECK(__FP__GC__PORT__) ((sPort!=(__FP__GC__PORT__))&&dPort!=(__FP__GC__PORT__))
+
+ if ( (dIp!=_br0_ip && sIp!=_br0_ip) &&
+ (sPort>1024 && dPort>1024) &&
+ (sPort!=8080 && dPort!=8080) &&
+ (!(IS_CLASSD_ADDR(dIp))) &&
+ (!(IS_BROADCAST_ADDR(dIp))) &&
+ (!(IS_ALLZERO_ADDR(sIp))))
+ {
+ return NET_RX_DROP;
+ }
+ else
+ return NET_RX_SUCCESS;
+ #undef RTL_FP_GC_HIGH_PRIORITY_PORT_CHECK
+}
+
+static inline int rtl_fp_gc_status_check(struct iphdr *iph, struct tcphdr *tcph, struct sk_buff *skb)
+{
+ uint32 sIp, dIp;
+ uint16 sPort, dPort;
+ int ret;
+ static int rx_count=0;
+
+ ret = NET_RX_SUCCESS;
+ if ((rtl_newGC_session_status_flags!=RTL_FP_SESSION_LEVEL_IDLE)&&time_after_eq(rtl_newGC_session_status_time, jiffies)) {
+ sIp = iph->saddr;
+ dIp = iph->daddr;
+ sPort = tcph->source;
+ dPort = tcph->dest;
+ if (rtl_fp_gc_status_check_priority(sIp, dIp, sPort, dPort)==NET_RX_DROP) {
+ kfree_skb(skb);
+ ret = NET_RX_DROP;
+ }
+ } else {
+ if (rtl_newGC_session_status_flags==RTL_FP_SESSION_LEVEL3) {
+ if ((rx_count++)>rtl_fp_gc_rx_threshold) {
+ rx_count = 0;
+ rtl_newGC_session_status_time = jiffies+RTL_FP_SESSION_LEVEL3_INTERVAL;
+ }
+ } else if (rtl_newGC_session_status_flags==RTL_FP_SESSION_LEVEL1) {
+ rx_count += RTL_FP_SESSION_LEVEL1_RX_WEIGHT;
+ if ((rx_count)>rtl_fp_gc_rx_threshold) {
+ rx_count = 0;
+ rtl_newGC_session_status_time=jiffies+RTL_FP_SESSION_LEVEL1_INTERVAL;
+ }
+ }
+ }
+
+ return ret;
+}
+#endif
+
+int fast_path_pre_process_check(struct iphdr *iph, struct tcphdr *tcphupuh, struct sk_buff *skb)
+{
+ #if defined(FAST_L2TP)
+ enter_fast_path_fast_l2tp_pre_process(skb);
+ #endif
+
+ #if defined(CONFIG_RTL_NF_CONNTRACK_GARBAGE_NEW)
+ if ((iph->protocol==IPPROTO_TCP) &&
+ (tcphupuh->syn) && (!(tcphupuh->ack))) {
+ return rtl_fp_gc_status_check(iph, tcphupuh, skb);
+ }
+ #endif
+
+ return NET_RX_PASSBY;
+}
+
+
+#if defined(FAST_L2TP)
+static inline int enter_fast_path_fast_l2tp_post_process(struct sk_buff *skb)
+{
+ if (fast_l2tp_fw && skb->dev && (!memcmp(skb->dev->name, RTL_FASTPATH_PPP0_DEV_NAME, 4)) )
+ {
+ if (fast_l2tp_to_wan(skb)) // success
+ {
+ return NET_RX_DROP;
+ }
+ }
+ return NET_RX_SUCCESS;
+}
+#endif
+
+int fast_path_before_nat_check(struct sk_buff *skb, struct iphdr *iph, uint32 iphProtocol)
+{
+ #if defined(RTL_FP_CHECK_SPI_ENABLED) || defined(FAST_PATH_SPI_ENABLED)
+ int ret;
+ #endif
+ #if defined(FAST_PATH_SPI_ENABLED)
+ unsigned int dataoff;
+ #endif
+
+ #if defined(RTL_FP_CHECK_SPI_ENABLED)
+ ret = nf_conntrack_in(dev_net(skb->dev), PF_INET, NF_INET_PRE_ROUTING, skb);
+ switch (ret)
+ {
+ case NF_DROP:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ case NF_ACCEPT:
+ break;
+ default:
+ return NET_RX_DROP;
+ }
+ #endif
+
+ #if defined(FAST_PATH_SPI_ENABLED)
+ if (iphProtocol== IPPROTO_TCP){
+ dataoff = skb_network_offset(skb) + (iph->ihl<<2);
+ ret = rtl_nf_conntrack_in(dev_net(skb->dev), dataoff, NF_INET_PRE_ROUTING, skb);
+ switch (ret){
+ case NF_DROP:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ case NF_ACCEPT:
+ break;
+ default:
+ return NET_RX_DROP;
+ }
+ }
+ #endif
+
+ return NET_RX_PASSBY;
+}
+
+int fast_path_post_process_xmit_check(struct iphdr *iph, struct tcphdr *tcphupuh, struct sk_buff *skb)
+{
+ #if defined(FAST_L2TP)
+ return enter_fast_path_fast_l2tp_post_process(skb);
+ #else
+ return NET_RX_SUCCESS;
+ #endif
+}
+
+int fast_path_post_process_return_check(struct iphdr *iph, struct tcphdr *tcphupuh, struct sk_buff *skb)
+{
+ #if defined(CONFIG_RTL_NF_CONNTRACK_GARBAGE_NEW)
+ if (iph->protocol==IPPROTO_UDP)
+ return rtl_fp_gc_status_check(iph, tcphupuh, skb);
+ #endif
+
+ return NET_RX_SUCCESS;
+
+}
+
+int32 rtl_fp_dev_queue_xmit_check(struct sk_buff *skb, struct net_device *dev)
+{
+ #ifdef FAST_L2TP
+ if (l2tp_tx_id_hook != NULL)
+ l2tp_tx_id_hook(skb);
+ #endif
+
+ #ifdef FAST_PPTP
+ if (sync_tx_pptp_gre_seqno_hook != NULL)
+ sync_tx_pptp_gre_seqno_hook(skb);
+ #endif
+
+ return SUCCESS;
+}
+
+int32 rtl_fp_dev_hard_start_xmit_check(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq)
+{
+#if defined(FAST_L2TP)
+ #if defined(CONFIG_NET_SCHED)
+ if(!gQosEnabled)
+ #endif
+ if (l2tp_tx_id_hook != NULL)
+ l2tp_tx_id_hook(skb);
+#endif
+
+#if defined (CONFIG_RTL_LOCAL_PUBLIC)
+ if( (skb->srcLocalPublicIp!=0) &&
+ (rtl865x_curOpMode==GATEWAY_MODE) &&
+ #if defined(CONFIG_RTL_PUBLIC_SSID)
+ (strncmp(dev->name,RTL_GW_WAN_DEVICE_NAME, 3)==0)
+ #else
+ (strncmp(dev->name,RTL_PS_WAN0_DEV_NAME, 4)==0)
+ #endif
+ ) {
+ rtl865x_getLocalPublicMac(skb->srcLocalPublicIp, skb->data+6);
+ }
+#endif
+ return SUCCESS;
+}
+
+
+int ip_finish_output3(struct sk_buff *skb)
+{
+ struct dst_entry *dst;
+ struct hh_cache *hh;
+
+ dst = skb->dst;
+ hh = dst->hh;
+
+#if !defined(IMPROVE_QOS)
+#if defined(CONFIG_NET_SCHED)
+ if (gQosEnabled) {
+ u_short proto = ntohs(skb->protocol);
+ if(proto == ETH_P_IP){
+ (list_empty(&nf_hooks[PF_INET][NF_IP_POST_ROUTING]))?: \
+ ipt_do_table(skb, NF_IP_POST_ROUTING, skb->dev, NULL, \
+ dev_net(skb->dev)->ipv4.iptable_mangle);
+ }
+ }
+#endif
+#endif
+
+
+ if (hh) {
+// ------------------------------------------------
+#if 1
+ memcpy(skb->data - 16, hh->hh_data, 16);
+#else
+ memcpy((unsigned char*)UNCACHE(skb->data - 16), hh->hh_data, 16);
+#endif
+ skb_push(skb, hh->hh_len);
+
+#ifdef FAST_L2TP
+ if (fast_l2tp_fw)
+ l2tp_tx_id(skb);
+#endif
+
+ if (skb->dev->flags & IFF_UP) {
+#if defined(CONFIG_NET_SCHED)
+ if (gQosEnabled) {
+ // call dev_queue_xmit() instead of hard_start_xmit(), because I want the packets be sent through Traffic Control module
+ dev_queue_xmit(skb);
+ return 0;
+ } else
+#endif
+ {
+
+ #if defined(CONFIG_BRIDGE)
+ /* In order to improve performance
+ * We'd like to directly xmit and bypass the bridge check
+ */
+ if (skb->dev->priv_flags == IFF_EBRIDGE)
+ {
+ /* wan->lan */
+ struct net_bridge *br = netdev_priv(skb->dev);
+ const unsigned char *dest = skb->data;
+ struct net_bridge_fdb_entry *dst;
+
+ if ((dst = __br_fdb_get(br, dest)) != NULL)
+ {
+ //skb->dev->stats.tx_packets++;
+ //skb->dev->stats.tx_bytes += skb->len;
+ skb->dev = dst->dst->dev;
+ }
+ }
+ #endif
+ {
+ if(!skb->dev->netdev_ops->ndo_start_xmit(skb,skb->dev))
+ return 0;
+ }
+ }
+ }
+//------------------------------- david+2007-05-25
+
+ } else if (dst->neighbour) {
+ return dst->neighbour->output(skb);
+ }
+
+#if 0
+ if (net_ratelimit())
+ printk(KERN_DEBUG "ip_finish_output3: No header cache and no neighbour!\n");
+#endif
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+int FastPath_Enter(struct sk_buff **pskb)
+{
+ int ret;
+ struct sk_buff *skb;
+
+ skb=*pskb;
+ //skb->nh.raw = skb->data;
+ skb->transport_header=skb->data;
+ skb->network_header = skb->data;
+ //skb_reset_network_header(skb);
+
+//hyking:
+//bug fix:when port filter is enable,application will disable fast_nat_fw,at this moment,url filter is abnormal...
+#if defined (DOS_FILTER) || defined (URL_FILTER)
+ ret = filter_enter(skb);
+ if (ret == NF_DROP) {
+ kfree_skb(skb);
+ ret = 1;
+ goto out;
+ }
+#if defined(CONFIG_RTL_FAST_FILTER)
+ else if(ret == NF_FASTPATH)
+ {
+ //continue the fastpath
+ }
+ else if(ret == NF_OMIT)
+ {
+ //don't support this in driver now
+ ret = 0;
+ goto out;
+ }
+ else if(ret == NF_LINUX)
+ {
+ //don't do rtk fastpath
+ ret = 0;
+ goto out;
+ }
+#endif
+ else if(ret != NF_ACCEPT)
+ {
+ ret = 0;
+ goto out;
+ }
+#endif
+
+ if(!(skb->pkt_type == PACKET_HOST))
+ {
+ ret = 0;
+ goto out;
+ }
+
+ if (!fast_nat_fw)
+ {
+ ret = 0;
+ goto out;
+ }
+
+#ifdef FILTER_UPNP_BR
+ if (upnp_br_enabled && skb->dev && !memcmp(skb->dev->name, RTL_PS_WAN0_DEV_NAME, 4) && filter_upnp_and_fw(skb)){
+ ret = 1;
+ goto out;
+ }
+#endif
+
+#ifdef FAST_PPTP
+ if (fast_pptp_fw) {
+ fast_pptp_filter(skb);
+ ret = fast_pptp_to_lan(&skb);
+ if (ret < 0) // error, skb has been free
+ {
+ ret = 1;
+ goto out;
+ }
+ *pskb=skb;
+ }
+#endif
+
+#ifdef FAST_L2TP
+ if (fast_l2tp_fw)
+ fast_l2tp_rx(skb);
+#endif
+
+
+ ret = enter_fast_path(skb);
+#if 0
+ if(ret != NET_RX_DROP)
+ {
+ struct tcphdr *tcpudph;
+ printk("-------%s(%d),ret(%d), src(0x%x),dst(0x%x)\n",__FUNCTION__,__LINE__,ret,ip_hdr(skb)->saddr,ip_hdr(skb)->daddr);
+ if(ip_hdr(skb)->protocol == IPPROTO_TCP)
+ {
+ tcpudph = (struct tcphdr*)((__u32 *)skb->data + ip_hdr(skb)->ihl);
+ printk("===%s(%d),sport(%d),dport(%d),syn(%d),fin(%d),rst(%d)\n",__FUNCTION__,__LINE__,tcpudph->source,tcpudph->dest,tcpudph->syn,tcpudph->fin,tcpudph->rst);
+ }
+ }
+#endif
+#ifdef FAST_PPTP
+ if (fast_pptp_fw && ret == 0 && ip_hdr(skb)->protocol == IPPROTO_GRE && skb->len > sizeof(struct iphdr)&& pptp_tcp_finished==1)
+ if(Check_GRE_rx_net_device(skb))
+ {
+ fast_pptp_sync_rx_seq(skb);
+ }
+#endif
+
+out:
+ return ret;
+}
+
+//======================================
+static int __init fastpath_init(void)
+{
+ int ret;
+
+ #ifdef CONFIG_FAST_PATH_MODULE
+ fast_path_hook=FastPath_Enter;
+ FastPath_hook1=rtk_delRoute;
+ FastPath_hook2=rtk_modifyRoute;
+ FastPath_hook3=rtk_addRoute;
+ FastPath_hook4=rtk_delNaptConnection;
+ FastPath_hook5=rtk_addArp;
+ FastPath_hook6=rtk_addNaptConnection;
+ FastPath_hook7=rtk_delArp;
+ FastPath_hook8=rtk_modifyArp;
+ FastPath_hook9=Get_fast_pptp_fw;
+ FastPath_hook10=fast_pptp_to_wan;
+ FastPath_hook11=rtk_idleNaptConnection;
+ #endif
+
+ #ifdef DEBUG_PROCFILE
+ /* proc file for debug */
+ init_fastpath_debug_proc();
+ #endif /* DEBUG_PROCFILE */
+
+ #ifndef NO_ARP_USED
+ /* Arp-Table Init */
+ ret=init_table_arp(ARP_TABLE_LIST_MAX,ARP_TABLE_ENTRY_MAX);
+ if(ret!=0) {
+ DEBUGP_SYS("init_table_arp Failed!\n");
+ }
+ #endif
+
+ #ifndef DEL_ROUTE_TBL
+ /* Route-Table Init */
+ ret=init_table_route(ROUTE_TABLE_LIST_MAX, ROUTE_TABLE_ENTRY_MAX);
+ if(ret!=0) {
+ DEBUGP_SYS("init_table_route Failed!\n");
+ }
+ #endif
+
+ #ifndef DEL_NAPT_TBL
+ /* Napt-Table Init */
+ ret=init_table_napt(NAPT_TABLE_LIST_MAX, NAPT_TABLE_ENTRY_MAX);
+ if(ret!=0)
+ {
+ DEBUGP_SYS("init_table_napt Failed!\n");
+ }
+ #endif
+
+ /* Path-Table Init */
+ ret=init_table_path(PATH_TABLE_LIST_MAX, PATH_TABLE_ENTRY_MAX);
+ if(ret!=0) {
+ DEBUGP_SYS("init_table_path Failed!\n");
+ }
+
+ #ifdef CONFIG_UDP_FRAG_CACHE
+ if(!udp_fragCache_init(MAX_UDP_FRAG_ENTRY))
+ return -1;
+ #endif
+
+ #ifdef DOS_FILTER
+ filter_init();
+ #endif
+
+ #ifdef FAST_PPTP
+ fast_pptp_init();
+ #endif
+
+ #ifdef FAST_L2TP
+ fast_l2tp_init();
+ #endif
+
+ #ifdef CONFIG_PROC_FS
+ res1=create_proc_entry("fast_nat",0,NULL);
+ if (res1) {
+ res1->read_proc=read_proc;
+ res1->write_proc=write_proc;
+ }
+ #endif
+
+ #if defined(CONFIG_RTL_NF_CONNTRACK_GARBAGE_NEW)
+ rtl_fp_gc_rx_threshold = RTL_FP_SESSION_LEVEL3_ALLOW_COUNT;
+ #endif
+
+ return 0;
+}
+
+static void __exit fastpath_exit(void)
+{
+#ifdef CONFIG_FAST_PATH_MODULE
+ fast_path_hook=NULL;
+ FastPath_hook1=NULL;
+ FastPath_hook2=NULL;
+ FastPath_hook3=NULL;
+ FastPath_hook4=NULL;
+ FastPath_hook5=NULL;
+ FastPath_hook6=NULL;
+ FastPath_hook7=NULL;
+ FastPath_hook8=NULL;
+ FastPath_hook9=NULL;
+ FastPath_hook10=NULL;
+ FastPath_hook11=NULL;
+#endif
+
+#ifdef DEBUG_PROCFILE
+ /* proc file for debug */
+ remove_fastpath_debug_proc();
+#endif /* DEBUG_PROCFILE */
+
+#ifdef DOS_FILTER
+ filter_exit();
+#endif
+
+#ifdef FAST_PPTP
+ fast_pptp_exit();
+#endif
+
+#ifdef CONFIG_PROC_FS
+ if (res1) {
+ remove_proc_entry("fast_nat", res1);
+ res1 = NULL;
+ }
+#endif
+
+ //printk("%s %s removed!\n", MODULE_NAME, MODULE_VERSION);
+}
+
+module_init(fastpath_init);
+module_exit(fastpath_exit);
+MODULE_LICENSE("GPL");
+