diff options
author | Roman Yeryomin <roman@advem.lv> | 2012-09-13 00:40:35 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2013-05-26 00:44:46 +0300 |
commit | a27354c9021a8423ef8c7d2bffad49cbf639eec1 (patch) | |
tree | 2355929a4b8cf1888cd0797cfabdb42e0077c524 /target/linux/realtek/files/drivers/net/rtl819x/l3Driver | |
parent | 24a776baeb5d3cd903b144c89ceb11c5bc36a49e (diff) |
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/net/rtl819x/l3Driver')
13 files changed, 6185 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/Makefile b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/Makefile new file mode 100644 index 000000000..ad10ae661 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/Makefile @@ -0,0 +1,52 @@ +# +# Makefile for the Tulip ethernet driver +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... +#Add mips16 Support + +DIR_RTLASIC = $(TOPDIR)/drivers/net/rtl819x/ +ifdef CONFIG_RTL865X_KERNEL_MIPS16_LAYERDRIVER + CFLAGS_rtl865x_arp.o = -mips16 + CFLAGS_rtl865x_ip.o = -mips16 + CFLAGS_rtl865x_ppp.o = -mips16 + CFLAGS_rtl865x_nexthop.o = -mips16 + CFLAGS_rtl865x_route.o = -mips16 + CFLAGS_rtl865x_multicast.o = -mips16 +endif + + obj-$(CONFIG_RTL_HARDWARE_MULTICAST) := rtl865x_multicast.o + + ifdef CONFIG_RTL_LAYERED_DRIVER_L3 + obj-y += rtl865x_arp.o rtl865x_ip.o rtl865x_ppp.o rtl865x_nexthop.o rtl865x_route.o + endif +ifdef CONFIG_RTL_MULTIPLE_WAN + obj-y += rtl865x_multipleWan.o +endif +ifdef CONFIG_RTL_LOCAL_PUBLIC + obj-y += rtl865x_localPublic.o +endif + +EXTRA_CFLAGS += -O1 -DRTL_TBLDRV -D__linux__ -mno-memcpy -DRTL865X_OVER_KERNEL -DRTL865X_OVER_LINUX -Werror +#EXTRA_CFLAGS += -I$(DIR_LINUX) +#EXTRA_CFLAGS += -I$(DIR_RTLASIC)/AsicDriver +#EXTRA_CFLAGS += -I$(DIR_RTLASIC)/common +#EXTRA_CFLAGS += -I$(DIR_RTLASIC)/l2Driver +#EXTRA_CFLAGS += -I$(DIR_RTLASIC)/igmpsnooping +EXTRA_CFLAGS += -I$(DIR_RTLASIC) + +ifeq ($(CONFIG_RTL865X_MODULE_ROMEDRV),y) + EXTRA_CFLAGS += -D__KERNEL__ + EXTRA_CFLAGS += -G 0 + EXTRA_CFLAGS += -DMODULE + EXTRA_CFLAGS += -mlong-calls + EXTRA_CFLAGS += -DEXPORT_SYMTAB + EXTRA_CFLAGS += -DCONFIG_RTL865X_MODULE_INTERNAL +# EXTRA_CFLAGS += -DMODVERSIONS +# EXTRA_CFLAGS += -include $(DIR_LINUX)/include/linux/modversions.h +endif + +EXTRA_AFLAGS += $(EXTRA_CFLAGS) diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.c b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.c new file mode 100644 index 000000000..fab41bcc2 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.c @@ -0,0 +1,658 @@ + +/* @doc RTL_LAYEREDDRV_API + + @module rtl865x_arp.c - RTL865x Home gateway controller Layered driver API documentation | + This document explains the API interface of the table driver module. Functions with rtl865x prefix + are external functions. + @normal Hyking Liu (Hyking_liu@realsil.com.cn) <date> + + Copyright <cp>2008 Realtek<tm> Semiconductor Cooperation, All Rights Reserved. + + @head3 List of Symbols | + Here is a list of all functions and variables in this module. + + @index | RTL_LAYEREDDRV_API +*/ + +#include <net/rtl/rtl_types.h> +#include "common/rtl_errno.h" + +#include "common/mbuf.h" +//#include "assert.h" + +//#include "rtl865xc_swNic.h" +#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER +#include "AsicDriver/rtl865x_asicCom.h" +#include "AsicDriver/rtl865x_asicL2.h" +#include "AsicDriver/rtl865x_asicL3.h" +#else +#include "rtl865xC_tblAsicDrv.h" +#include "common/rtl8651_aclLocal.h" +#endif + +#include "AsicDriver/rtl865x_hwPatch.h" /* define for chip related spec */ + +#include "common/rtl865x_eventMgr.h" + +#include "common/rtl865x_vlan.h" +#include <net/rtl/rtl865x_netif.h> +#include "common/rtl865x_netif_local.h" + +#include "l2Driver/rtl865x_fdb.h" + +#include "rtl865x_ppp_local.h" +#include "rtl865x_route.h" +#include "rtl865x_arp.h" + +#if defined(CONFIG_RTL_MULTIPLE_WAN) +#include <net/rtl/rtl865x_multipleWan_api.h> +#include "rtl865x_multipleWan.h" +#include "rtl865x_nexthop.h" +#endif +#include <net/rtl/rtl865x_fdb_api.h> + +static int32 rtl865x_arp_hash(ipaddr_t ip, uint32 *index); + +static int32 rtl865x_arp_callbackFn_for_del_fdb(void *param); +static int32 rtl865x_arp_register_event(void); + +static struct rtl865x_arp_table arpTables; +#if defined(CONFIG_RTL_MULTIPLE_WAN) +static int (*rtl_callback_for_ps_arp)(ipaddr_t ip,rtl865x_arpMapping_entry_t *arp); +#endif + +static int32 rtl865x_arp_callbackFn_for_del_fdb(void *param) +{ + int i; + rtl865x_filterDbTableEntry_t *fdbEntry; + + if(param==NULL) + { + return EVENT_CONTINUE_EXECUTE; + } + + fdbEntry=(rtl865x_filterDbTableEntry_t *)param; + + for(i=0;i<RTL8651_ARPTBL_SIZE;i++) + { + /*be careful of dead loop, the delete fdb event maybe caused by arp time out*/ + if(memcmp(&(fdbEntry->macAddr),&(arpTables.mappings[i].mac), 6)==0) + { + rtl865x_delArp(arpTables.mappings[i].ip); + } + + } + + return EVENT_CONTINUE_EXECUTE; + +} + +static int32 rtl865x_arp_unRegister_event(void) +{ + rtl865x_event_Param_t eventParam; + eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID; + eventParam.eventId=EVENT_DEL_FDB; + eventParam.eventPriority=0; + eventParam.event_action_fn=rtl865x_arp_callbackFn_for_del_fdb; + rtl865x_unRegisterEvent(&eventParam); + return SUCCESS; + +} +static int32 rtl865x_arp_register_event(void) +{ + rtl865x_event_Param_t eventParam; + eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID; + eventParam.eventId=EVENT_DEL_FDB; + eventParam.eventPriority=0; + eventParam.event_action_fn=rtl865x_arp_callbackFn_for_del_fdb; + rtl865x_registerEvent(&eventParam); + return SUCCESS; + +} + + +int32 rtl865x_arp_init(void) +{ + int i; + rtl865x_arp_unRegister_event(); + memset(arpTables.allocBitmap, 0, 64); + memset(arpTables.mappings, 0, RTL8651_ARPTBL_SIZE * sizeof(rtl865x_arpMapping_entry_t)); + for(i=0; i<RTL8651_ARPTBL_SIZE; i++) + { + rtl8651_delAsicArp(i); + } + rtl865x_arp_register_event(); + #if defined(CONFIG_RTL_MULTIPLE_WAN) + rtl_callback_for_ps_arp = NULL; + #endif + return SUCCESS; +} + +int32 rtl865x_arp_reinit(void) +{ + return rtl865x_arp_init(); +} + +int32 rtl865x_arp_tbl_alloc(rtl865x_route_t *route) +{ + uint32 netSize, entry, bestSize=0, bestStartPos=0xffffffff; + uint32 curSize, curStartPos; + if(route==NULL) + { + return FAILED; + } + + /* process definition(000: PPPoE, 001: L2, 010: ARP, 100: CPU, 101: NextHop, 110: Drop)*/ + if((route->process!=2)) + { + return FAILED; + } + + for(entry=0; entry<32; entry++) + { + if(route->ipMask & (1<<entry)) + break; + } + + if ((netSize = (1<<entry)) > 1) + { + curStartPos = bestSize = curSize = 0; + for(entry = 0; entry <= 64; entry++) + { + if((entry == 64) || arpTables.allocBitmap[entry]) + { + if(curSize > bestSize) + { + bestStartPos = curStartPos; + bestSize = curSize; + } + curStartPos = entry+1; + curSize = 0; + } else curSize++; + } + } + + if (netSize>1 && ((bestSize<<3) >= netSize)) + { + route->un.arp.arpsta= bestStartPos<<3; + route->un.arp.arpend = (bestStartPos + (netSize>>3) - ((netSize&0x7)==0? 1: 0))<<3; + for(entry=route->un.arp.arpsta>>3; entry<=route->un.arp.arpend>>3; entry++) + { + arpTables.allocBitmap[entry] = 1; + } + return SUCCESS; + } + return FAILED; + +} + +int32 rtl865x_arp_tbl_free(rtl865x_route_t *route) +{ + rtl865x_vlan_entry_t *vlan; + uint32 index; + int32 i, j; + + if(route==NULL) + { + return FAILED; + } + if((route->valid!=1) || (route->process!=2) || (route->dstNetif==NULL) ) + { + return FAILED; + } + + for(i=route->un.arp.arpsta>>3; i<=route->un.arp.arpend>>3; i++) + { + arpTables.allocBitmap[i] = 0; + for(j=0; j<8; j++) + { + index = (i<<3)+j; + if(arpTables.mappings[index].ip!=0) + { + rtl8651_delAsicArp(index); + vlan = _rtl8651_getVlanTableEntry(route->dstNetif->vid); + rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEII, vlan->fid, &(arpTables.mappings[index].mac)); + memset(&(arpTables.mappings[index]),0,sizeof(rtl865x_arpMapping_entry_t)); + } + else + { + memset(&(arpTables.mappings[index]),0,sizeof(rtl865x_arpMapping_entry_t)); + } + } + } + + return SUCCESS; +} + +static int32 rtl865x_arp_hash(ipaddr_t ip, uint32 *index) +{ + rtl865x_route_t rt_entry,*route; + uint32 arpIndex; + int32 retval = FAILED; + + route = &rt_entry; + memset(route,0,sizeof(rtl865x_route_t)); + retval =rtl865x_getRouteEntry(ip, route); + + if (retval != SUCCESS) + return retval; + if((route->valid!=1) || (route->process!=2) ||(route->dstNetif==NULL)) + { + return FAILED; + } + arpIndex=((route->un.arp.arpsta)+(ip&~route->ipMask)); + if(arpIndex>=RTL8651_ARPTBL_SIZE) + { + return FAILED; + } + *index=arpIndex; + return SUCCESS; +} + +int32 rtl865x_getArpMapping(ipaddr_t ip, rtl865x_arpMapping_entry_t * arp_mapping) +{ + + rtl865x_route_t *route,rt_entry; + uint32 hash; + int32 retval = FAILED; + + if(arp_mapping==NULL) + { + return FAILED; + } + memset(arp_mapping, 0, sizeof(rtl865x_arpMapping_entry_t)); + route= &rt_entry; + memset(route,0,sizeof(rtl865x_route_t)); + retval=rtl865x_getRouteEntry(ip,route); + + if(retval != SUCCESS) + return retval; + + + if((route->valid!=1) || (route->process!=2) ||(route->dstNetif==NULL)) + { + return FAILED; + } + + if(rtl865x_arp_hash(ip,&hash)==FAILED) + { + return FAILED; + } + + if(arpTables.mappings[hash].ip==ip) + { + memcpy(arp_mapping,&(arpTables.mappings[hash]),sizeof(rtl865x_arpMapping_entry_t)); + } + else + return FAILED; + + return SUCCESS; +} + + +int32 rtl865x_getAsicArpEntry(ipaddr_t ip,rtl865x_tblAsicDrv_arpParam_t *asicArpEntry) +{ + + rtl865x_route_t *route,rt_entry; + uint32 hash; + int32 retval; + + if(asicArpEntry==NULL) + { + return FAILED; + } + + route = &rt_entry; + memset(route,0,sizeof(rtl865x_route_t)); + memset(asicArpEntry, 0, sizeof(rtl865x_tblAsicDrv_arpParam_t)); + + retval = rtl865x_getRouteEntry(ip,route); + if(retval != SUCCESS) + return retval; + + if((route==NULL)||(route->valid!=1) || (route->process!=2) ||(route->dstNetif==NULL)) + { + return FAILED; + } + + if(rtl865x_arp_hash(ip,&hash)==FAILED) + { + return FAILED; + } + + rtl8651_getAsicArp(hash, asicArpEntry); + + return SUCCESS; + +} + +int32 rtl865x_mapIpToMac(ipaddr_t ip,ether_addr_t * mac) +{ + uint32 hash; + + if(mac==NULL) + { + return FAILED; + } + + memset(mac, 0, sizeof(ether_addr_t)); + + if(rtl865x_arp_hash(ip, &hash)!=SUCCESS) + { + return FAILED; + } + + if(arpTables.mappings[hash].ip==ip) + { + memcpy(mac,&(arpTables.mappings[hash].mac),sizeof(ether_addr_t)); + return SUCCESS; + } + + return FAILED; +} + +static int32 rtl865x_getArpFid(ipaddr_t ip, uint16 *fid) +{ + rtl865x_route_t *route,rt_entry; + rtl865x_vlan_entry_t *vlan; + int32 retval = FAILED; + + + if(ip==0) + { + return FAILED; + } + + route = &rt_entry; + memset(route,0,sizeof(rtl865x_route_t)); + retval = rtl865x_getRouteEntry(ip,route); + if(retval != SUCCESS) + return retval; + + if((route->valid!=1) || (route->process!=2) ||(route->dstNetif==NULL)) + { + return FAILED; + } + + + vlan = _rtl8651_getVlanTableEntry(route->dstNetif->vid); + *fid = vlan->fid; + return SUCCESS; +} +#if defined(CONFIG_RTL_MULTIPLE_WAN) +int32 rtl_set_callback_for_ps_arp(int (*call_back_fn)(u32 ip,rtl865x_arpMapping_entry_t *entry)) +{ + if(NULL == call_back_fn) + { + return FAILED; + } + + rtl_callback_for_ps_arp = call_back_fn; + return SUCCESS; +} + +int32 rtl865x_get_ps_arpMapping(ipaddr_t ip,rtl865x_arpMapping_entry_t *entry) +{ + if(rtl_callback_for_ps_arp) + return rtl_callback_for_ps_arp(ip,entry); + + return FAILED; +} +#endif +int32 rtl865x_addArp(ipaddr_t ip, ether_addr_t * mac) +{ + uint32 i; + uint32 hash; + uint16 fid = 0; + + rtl865x_arpMapping_entry_t oldArpMapping; + rtl865x_arpMapping_entry_t newArpMapping; + + rtl865x_tblAsicDrv_arpParam_t asicArpEntry; + + uint32 fdb_type[]={ FDB_STATIC, FDB_DYNAMIC }; + + uint32 column; + rtl865x_tblAsicDrv_l2Param_t fdbEntry; + rtl865x_filterDbTableEntry_t l2temp_entry; + + if((ip==0) ||(mac==NULL)) + { + return RTL_EINVALIDINPUT; + } + + #if defined(CONFIG_RTL_MULTIPLE_WAN) + if(rtl_get_advRt_entry_by_nexthop(ip)) + { + newArpMapping.ip=ip; + memcpy(&newArpMapping.mac,mac,sizeof(ether_addr_t)); + rtl865x_eventHandle_addArp_for_multiWan(&newArpMapping); + } + #endif + + if(rtl865x_arp_hash(ip, &hash)==FAILED) + { + return FAILED; + } + + //printk("%s:%d+++++++++++++++++++++++++++++\n",__FUNCTION__,__LINE__); + + /*check the old arp mapping first*/ + memcpy(&oldArpMapping,&(arpTables.mappings[hash] ),sizeof(rtl865x_arpMapping_entry_t)); + if((oldArpMapping.ip!=ip) ||(memcmp(&(oldArpMapping.mac),mac, 6)!=0)) + { + /*delete old arp mapping*/ + if(oldArpMapping.ip!=0) + { + /*should clear old arp mapping before delete fdb entry and raise arp event*/ + rtl8651_delAsicArp(hash); + memset(&(arpTables.mappings[hash] ),0,sizeof(rtl865x_arpMapping_entry_t)); + + if(rtl865x_getArpFid(oldArpMapping.ip,&fid)==SUCCESS) + { + rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEI|RTL865x_L2_TYPEII, fid, &oldArpMapping.mac); + } + rtl865x_raiseEvent(EVENT_DEL_ARP,(void*)(&oldArpMapping)); + } + } + /*here to handle the new arp mapping*/ + newArpMapping.ip=ip; + memcpy(&newArpMapping.mac,mac,sizeof(ether_addr_t)); + if(rtl865x_getArpFid(newArpMapping.ip, &fid)!=SUCCESS) + { + return FAILED; + } + + for(i=0; i<2; i++) + { + /* + printk("%s:%d\n,fid(%d),mac(%02x:%02x:%02x:%02x:%02x:%02x)\n",__FUNCTION__,__LINE__,fid,mac->octet[0],mac->octet[1], + mac->octet[2],mac->octet[3],mac->octet[4],mac->octet[5]); + + printk("%s:%d\n",__FUNCTION__,__LINE__); + */ + if(rtl865x_Lookup_fdb_entry(fid, mac, fdb_type[i], &column,&fdbEntry) != SUCCESS) + { + continue; + } + + /*indicate new arp mapping*/ + if((oldArpMapping.ip!=ip) ||(memcmp(&(oldArpMapping.mac),mac, 6)!=0)) + { + /*in case of layer2 auto learn, add hardware entry to layer 2 software table*/ + l2temp_entry.l2type = (fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII; + l2temp_entry.process = FDB_TYPE_FWD; + l2temp_entry.memberPortMask = fdbEntry.memberPortMask; + l2temp_entry.auth = fdbEntry.auth; + l2temp_entry.SrcBlk = fdbEntry.srcBlk; + memcpy(&(l2temp_entry.macAddr), mac, sizeof(ether_addr_t)); +#ifdef CONFIG_RTL865X_SYNC_L2 +#else +// rtl865x_addFilterDatabaseEntryExtension(fid, &l2temp_entry); +#endif +// _rtl865x_addFilterDatabaseEntry((fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII, fid, mac, FDB_TYPE_FWD, fdbEntry.memberPortMask, fdbEntry.auth,fdbEntry.srcBlk); + + } + + /*update or reflesh arp mapping*/ + asicArpEntry.nextHopColumn = column; + asicArpEntry.aging = 300; + asicArpEntry.nextHopRow=rtl865x_getHWL2Index(mac, fid); + rtl8651_setAsicArp(hash, &asicArpEntry); + rtl865x_refleshHWL2Table(mac, FDB_DYNAMIC|FDB_STATIC,fid); + /*update mapping table*/ + memcpy(&(arpTables.mappings[hash]),&newArpMapping,sizeof(rtl865x_arpMapping_entry_t)); + rtl865x_raiseEvent(EVENT_ADD_ARP,(void*)(&newArpMapping)); + return SUCCESS; + + } + + return FAILED; +} + + + +int32 rtl865x_delArp(ipaddr_t ip) +{ + uint32 hash; + uint16 fid = 0; + + rtl865x_arpMapping_entry_t arpMapping; + + if(ip==0) + { + return FAILED; + } + + + #if defined(CONFIG_RTL_MULTIPLE_WAN) + if(rtl_get_advRt_entry_by_nexthop(ip)) + { + arpMapping.ip = ip; + memset(arpMapping.mac.octet,0,ETHER_ADDR_LEN); + rtl865x_eventHandle_delArp_for_multiWan(&arpMapping); + } + #endif + + if(rtl865x_arp_hash(ip,&hash)==FAILED) + { + return FAILED; + } + + //printk("%s:%d***************************************\n",__FUNCTION__,__LINE__); + memcpy(&arpMapping, &arpTables.mappings[hash], sizeof(rtl865x_arpMapping_entry_t)); + + if(arpMapping.ip!=ip) + { + return FAILED; + } + + if(rtl865x_getArpFid(ip, &fid)!=SUCCESS) + { + return FAILED; + } + + /*should clear old arp mapping before delete fdb entry and raise arp event*/ + rtl8651_delAsicArp(hash); + memset(&arpTables.mappings[hash], 0, sizeof(rtl865x_arpMapping_entry_t)); + +#ifdef CONFIG_RTL865X_SYNC_L2 +#else +// rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEI|RTL865x_L2_TYPEII, fid, &arpMapping.mac); +#endif + rtl865x_raiseEvent(EVENT_DEL_ARP,(void *)(&arpMapping)); + + + return SUCCESS; +} + +uint32 rtl865x_arpSync(ipaddr_t ip, uint32 refresh ) +{ + uint32 hash; + rtl865x_arpMapping_entry_t arpMapping; + rtl865x_tblAsicDrv_arpParam_t asicArpEntry; + + uint16 fid; + rtl865x_tblAsicDrv_l2Param_t l2entry; + uint32 age=0; + + if(ip==0) + { + return 0; + } + + if(rtl865x_arp_hash(ip,&hash)==FAILED) + { + return 0; + } + + memcpy(&arpMapping, &(arpTables.mappings[hash]), sizeof(rtl865x_arpMapping_entry_t)); + + if(arpMapping.ip!=ip) + { + return 0; + } + + /*asic arp entry is invalid*/ + if (rtl8651_getAsicArp(hash, &asicArpEntry)!=SUCCESS) + { + goto delete_and_out; + + } + + if(rtl865x_getHWL2Table(asicArpEntry.nextHopRow, asicArpEntry.nextHopColumn, &l2entry)!=SUCCESS) + { + /*the old fdb entry has timed out*/ + goto delete_and_out; + } + + if(memcmp(&(l2entry.macAddr), &(arpMapping.mac), 6)!= 0) + { + /*this layer 2 entry has different mac address, + also indicates the old fdb entry has timed out*/ + goto delete_and_out; + } + + age = l2entry.ageSec; + if (refresh) + { + rtl865x_refleshHWL2Table(&(l2entry.macAddr), FDB_DYNAMIC|FDB_STATIC,l2entry.fid); + age=150; + } + else + { + if(age>=300) + { + age=age-150; + } + else + { + age=0; + + /*to make sure linux arp entry time out before fdb entry*/ + /*asic fdb entry's age is 150 seconds*/ + /*since linux protocol stack arp entry has timed out and l2 entry's precision is also 150 second, + we should delete both arp and fdb to sync between linux protocol stack and asic*/ + //goto delete_and_out; + } + } + return age; + + +delete_and_out: + + if(rtl865x_getArpFid(ip, &fid)==SUCCESS) + { + /*should clear old arp mapping before delete fdb entry and raise arp event*/ + rtl8651_delAsicArp(hash); + memset(&arpTables.mappings[hash], 0, sizeof(rtl865x_arpMapping_entry_t)); + + rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEI|RTL865x_L2_TYPEII, fid, &arpMapping.mac); + rtl865x_raiseEvent(EVENT_DEL_ARP,(void *)(&arpMapping)); + } + + return 0; + +} + + diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.h b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.h new file mode 100644 index 000000000..52efbd6e8 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.h @@ -0,0 +1,18 @@ +#ifndef RTL865X_ARP_H
+#define RTL865X_ARP_H
+
+#include <net/rtl/rtl865x_arp_api.h>
+/*for driver initialization*/
+int32 rtl865x_arp_init(void);
+int32 rtl865x_arp_reinit(void);
+
+/*for routing module usage*/
+int32 rtl865x_arp_tbl_alloc(rtl865x_route_t *route);
+int32 rtl865x_arp_tbl_free(rtl865x_route_t *route);
+
+#if defined(CONFIG_RTL_MULTIPLE_WAN)
+int32 rtl865x_get_ps_arpMapping(ipaddr_t ip,rtl865x_arpMapping_entry_t *entry);
+#endif
+
+#endif
+
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ip.c b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ip.c new file mode 100644 index 000000000..9a54d4eeb --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ip.c @@ -0,0 +1,303 @@ +/*
+* Copyright c Realtek Semiconductor Corporation, 2008
+* All rights reserved.
+*
+* Program : ip table driver
+* Abstract :
+* Author : hyking (hyking_liu@realsil.com.cn)
+*/
+
+/* @doc RTL_LAYEREDDRV_API
+
+ @module rtl865x_ip.c - RTL865x Home gateway controller Layered driver API documentation |
+ This document explains the API interface of the table driver module. Functions with rtl865x prefix
+ are external functions.
+ @normal Hyking Liu (Hyking_liu@realsil.com.cn) <date>
+
+ Copyright <cp>2008 Realtek<tm> Semiconductor Cooperation, All Rights Reserved.
+
+ @head3 List of Symbols |
+ Here is a list of all functions and variables in this module.
+
+ @index | RTL_LAYEREDDRV_API
+*/
+#include <net/rtl/rtl_types.h>
+#include <net/rtl/rtl_glue.h>
+#include "common/rtl_errno.h"
+//#include "rtl_utils.h"
+//#include <net/rtl/rtl865x_ip_api.h>
+#include "rtl865x_ip.h"
+#if defined (CONFIG_RTL_LOCAL_PUBLIC)
+#include <net/rtl/rtl865x_localPublic.h>
+#endif
+#include "common/rtl865x_eventMgr.h" /*call back function....*/
+
+#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER
+#include "AsicDriver/rtl865x_asicCom.h"
+#include "AsicDriver/rtl865x_asicL3.h"
+#else
+#include "AsicDriver/rtl865xC_tblAsicDrv.h"
+#endif
+
+static rtl865x_ip_entry_t *rtl865x_ipTable;
+
+#define IP_TABLE_INDEX(entry) (entry - rtl865x_ipTable)
+static RTL_DECLARE_MUTEX(ip_sem);
+
+static int32 _rtl865x_delIp(ipaddr_t extIp);
+
+/*
+@func int32 | rtl865x_initIpTable | initialize ip table.
+@rvalue SUCCESS | Success.
+@rvalue FAILED | Failed,system should be reboot.
+*/
+int32 rtl865x_initIpTable(void)
+{
+ TBL_MEM_ALLOC(rtl865x_ipTable, rtl865x_ip_entry_t, IP_NUMBER);
+ memset(rtl865x_ipTable,0,sizeof(rtl865x_ip_entry_t)*IP_NUMBER);
+ return SUCCESS;
+}
+
+/*
+@func int32 | rtl865x_initIpTable | reinitialize ip table.
+@rvalue SUCCESS | Success.
+@rvalue FAILED | Failed.
+*/
+int32 rtl865x_reinitIpTable(void)
+{
+ int32 i ;
+ for(i = 0; i < IP_NUMBER; i++)
+ {
+ if(rtl865x_ipTable[i].valid)
+ _rtl865x_delIp(rtl865x_ipTable[i].extIp);
+ }
+ return SUCCESS;
+}
+
+
+static int32 _rtl865x_addIp(ipaddr_t intIp, ipaddr_t extIp, uint32 ip_type)
+{
+ int i;
+ rtl865x_ip_entry_t *entry = NULL;
+ rtl865x_tblAsicDrv_extIntIpParam_t asicIp;
+ int32 retval = FAILED;
+
+ if(ip_type < IP_TYPE_NAPT || ip_type > IP_TYPE_LOCALSERVER)
+ return RTL_EINVALIDINPUT;
+
+ /*duplicate check*/
+ /*found a valid entry*/
+ for(i = 0; i < IP_NUMBER; i++)
+ {
+ if(rtl865x_ipTable[i].valid == 0)
+ {
+ entry = &rtl865x_ipTable[i];
+ break;
+ }
+ else
+ {
+ if(rtl865x_ipTable[i].extIp == extIp)
+ return RTL_EENTRYALREADYEXIST;
+
+ if(ip_type == IP_TYPE_NAPT && rtl865x_ipTable[i].type == IP_TYPE_NAPT && rtl865x_ipTable[i].defNaptIp == 1)
+ return RTL_EENTRYALREADYEXIST;
+ }
+ }
+
+ if(entry == NULL)
+ return RTL_ENOFREEBUFFER;
+
+
+ /*update releated information*/
+ entry->valid = 1;
+ entry->intIp = intIp;
+ entry->extIp = extIp;
+ entry->type = ip_type;
+
+ /*from 865xC, this field is invalid...*/
+ entry->nexthop = NULL;
+
+
+ /*add this ip entry to asic*/
+ /* Set asic */
+ bzero(&asicIp, sizeof(rtl865x_tblAsicDrv_extIntIpParam_t));
+ asicIp.extIpAddr = extIp;
+ asicIp.intIpAddr = intIp;
+ asicIp.localPublic = (ip_type == IP_TYPE_LOCALSERVER)? TRUE: FALSE;
+ asicIp.nat = (ip_type == IP_TYPE_NAT)? TRUE: FALSE;
+ asicIp.nhIndex = 0;
+
+ retval = rtl8651_setAsicExtIntIpTable(IP_TABLE_INDEX(entry), &asicIp);
+
+ if(ip_type == IP_TYPE_NAPT)
+ rtl8651_setAsicOperationLayer(4);
+
+ return SUCCESS;
+
+}
+
+static int32 _rtl865x_ipTableIsNull(void)
+{
+ int i;
+
+ /*found the entry*/
+ for(i = 0; i < IP_NUMBER; i++)
+ {
+ if(rtl865x_ipTable[i].valid == 1)
+ {
+ return FAILED;
+ }
+ }
+
+ return SUCCESS;
+}
+
+static int32 _rtl865x_delIp(ipaddr_t extIp)
+{
+ int i;
+ rtl865x_ip_entry_t *entry = NULL;
+
+ /*found the entry*/
+ for(i = 0; i < IP_NUMBER; i++)
+ {
+ if(rtl865x_ipTable[i].valid == 1 && rtl865x_ipTable[i].extIp == extIp)
+ {
+ entry = &rtl865x_ipTable[i];
+ break;
+ }
+ }
+
+ /*update asic ip table*/
+ if(entry!=NULL)
+ {
+ rtl8651_delAsicExtIntIpTable(IP_TABLE_INDEX(entry));
+ memset(entry,0,sizeof(rtl865x_ip_entry_t));
+ }
+ else
+ return RTL_EENTRYNOTFOUND;
+
+ //no entry in ip table, set operation to layer 2
+ if(_rtl865x_ipTableIsNull() == SUCCESS)
+ {
+ #if defined(CONFIG_RTL_HARDWARE_MULTICAST)
+ rtl8651_setAsicOperationLayer(3);
+ #else
+ rtl8651_setAsicOperationLayer(2);
+ #endif
+ }
+
+ return SUCCESS;
+
+}
+
+static rtl865x_ip_entry_t* _rtl865x_getIpEntryByExtIp(ipaddr_t extIp)
+{
+ int32 i;
+ rtl865x_ip_entry_t *entry = NULL;
+
+ for(i = 0; i < IP_NUMBER; i++)
+ if(rtl865x_ipTable[i].valid == 1 && rtl865x_ipTable[i].extIp == extIp)
+ {
+ entry = &rtl865x_ipTable[i];
+ break;
+ }
+ return entry;
+
+}
+
+/*
+@func rtl865x_ip_entry_t* | rtl865x_getIpEntryByIp | get ip entry .
+@parm ipaddr_t | extIp | ip address
+@rvalue ip_entry | Success.
+@rvalue NULL | Failed
+*/
+rtl865x_ip_entry_t* rtl865x_getIpEntryByIp(ipaddr_t extIp)
+{
+ return _rtl865x_getIpEntryByExtIp(extIp);
+}
+
+
+/*
+@func int32 | rtl865x_getIpIdxByExtIp | get asic idex .
+@parm ipaddr_t | extIp | ip address
+@parm int32* | idx | index
+@rvalue SUCCESS | Success.
+@rvalue FAILED | Failed
+*/
+int32 rtl865x_getIpIdxByExtIp(ipaddr_t extIp, int32 *idx)
+{
+ int32 retval = FAILED;
+ rtl865x_ip_entry_t *entry = NULL;
+
+ entry = _rtl865x_getIpEntryByExtIp(extIp);
+ if(entry)
+ {
+ if(idx)
+ *idx = IP_TABLE_INDEX(entry);
+ retval = SUCCESS;
+ }
+
+ return retval;
+}
+
+/*
+@func int32 | rtl865x_addIp | add ip table entry.
+@parm ipaddr_t | intIp | internal ip address
+@parm ipaddr_t | extIp | external ip address
+@parm uint32 | ip_type | entry type. support IP_TYPE_NAPT/IP_TYPE_NAT/IP_TYPE_LOCALSERVER
+@rvalue SUCCESS | Success.
+@rvalue RTL_EINVALIDINPUT | Invalid input.
+@rvalue RTL_EENTRYALREADYEXIST | entry already exist.
+@rvalue RTL_ENOFREEBUFFER | not enough buffer in System.
+@rvalue FAILED | Failed.
+@comm
+the extIp is the primary key of the ip table.
+*/
+int32 rtl865x_addIp(ipaddr_t intIp, ipaddr_t extIp, uint32 ip_type)
+{
+ int32 retval = FAILED;
+ unsigned long flags;
+ //rtl_down_interruptible(&ip_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_addIp(intIp, extIp, ip_type);
+ //rtl_up(&ip_sem);
+ local_irq_restore(flags);
+ return retval;
+
+}
+
+/*
+@func int32 | rtl865x_delIp | delete ip table entry.
+@parm ipaddr_t | extIp | external ip address
+@rvalue SUCCESS | Success.
+@rvalue RTL_EINVALIDINPUT | Invalid input.
+@rvalue RTL_EENTRYNOTFOUND | not found.
+@rvalue FAILED | Failed.
+@comm
+the extIp is the primary key of the ip table.
+*/
+int32 rtl865x_delIp(ipaddr_t extIp)
+{
+ int32 retval = FAILED;
+ unsigned long flags;
+ //rtl_down_interruptible(&ip_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_delIp(extIp);
+ //rtl_up(&ip_sem);
+ local_irq_restore(flags);
+ return retval;
+
+}
+
+int32 rtl865x_getIPIdx(rtl865x_ip_entry_t *entry, int32 *idx)
+{
+ if(idx)
+ {
+ *idx =IP_TABLE_INDEX(entry);
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+
+
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ip.h b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ip.h new file mode 100644 index 000000000..cf62525a8 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ip.h @@ -0,0 +1,53 @@ +/* +* Copyright c Realtek Semiconductor Corporation, 2008 +* All rights reserved. +* +* Program : ip table driver +* Abstract : +* Author : hyking (hyking_liu@realsil.com.cn) +*/ +#ifndef RTL865X_IP_H +#define RTL865X_IP_H + +#include <net/rtl/rtl865x_ip_api.h> + +#if !defined(REDUCE_MEMORY_SIZE_FOR_16M) +#define REDUCE_MEMORY_SIZE_FOR_16M +#endif +#if defined (CONFIG_RTL_LOCAL_PUBLIC) +#define IP_NUMBER 8 +#else +#if defined(REDUCE_MEMORY_SIZE_FOR_16M) +#define IP_NUMBER 2 +#else +#define IP_NUMBER 8 +#endif +#endif + +typedef struct rtl865x_ip_entry_s +{ + ipaddr_t intIp; /*internal ip address*/ + ipaddr_t extIp; /*external ip address*/ + uint32 valid:1, /*valid*/ + type:2, /*napt/nat/ls/reserved*/ + defNaptIp:1; /*this ip entry is default napt ip address?*/ + +#if 1 + /*now, this information is invalid...*/ + void *nexthop; /*point to a nexthop entry,in preversion SoC, + *used for multiple session hardware forwarding... + */ +#endif +}rtl865x_ip_entry_t; + + +int32 rtl865x_initIpTable(void); +int32 rtl865x_reinitIpTable(void); +//int32 rtl865x_addIp(ipaddr_t intIp, ipaddr_t extIp, uint32 ip_type); +//int32 rtl865x_delIp(ipaddr_t extIp); +int32 rtl865x_getIPIdx(rtl865x_ip_entry_t *entry, int32 *idx); +int32 rtl865x_getIpIdxByExtIp(ipaddr_t extIp, int32 *idx); + + +#endif + diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_multicast.c b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_multicast.c new file mode 100644 index 000000000..872073807 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_multicast.c @@ -0,0 +1,1824 @@ +
+
+/* @doc RTL_LAYEREDDRV_API
+
+ @module rtl865x_multicast.c - RTL865x Home gateway controller Layered driver API documentation |
+ This document explains the API interface of the table driver module. Functions with rtl865x prefix
+ are external functions.
+ @normal Hyking Liu (Hyking_liu@realsil.com.cn) <date>
+
+ Copyright <cp>2008 Realtek<tm> Semiconductor Cooperation, All Rights Reserved.
+
+ @head3 List of Symbols |
+ Here is a list of all functions and variables in this module.
+
+ @index | RTL_LAYEREDDRV_API
+*/
+
+#ifdef __linux__ +#include <linux/config.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/proc_fs.h>
+#endif
+
+
+
+#include <net/rtl/rtl_types.h> +#include <net/rtl/rtl_glue.h> +//#include "common/rtl_utils.h"
+//#include "common/assert.h"
+
+#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER
+#include "AsicDriver/rtl865x_asicCom.h"
+#include "AsicDriver/rtl865x_asicL3.h"
+#else
+#include "AsicDriver/rtl865xC_tblAsicDrv.h"
+#include "common/rtl865x_tblDrvPatch.h"
+#endif
+
+#include "AsicDriver/asicRegs.h"
+#include "AsicDriver/asicTabs.h"
+
+#include "common/rtl8651_tblDrvProto.h"
+
+#include "common/rtl865x_eventMgr.h"
+#include "common/rtl865x_vlan.h"
+#include <net/rtl/rtl865x_netif.h> +
+#include "l3Driver/rtl865x_ip.h"
+
+#ifdef RTL865X_TEST
+#include <string.h>
+#endif
+
+#include <net/rtl/rtl865x_multicast.h> +#include <net/rtl/rtl865x_igmpsnooping.h> +/********************************************************/
+/* Multicast Related Global Variable */
+/********************************************************/
+
+static rtl865x_mcast_fwd_descriptor_t *rtl865x_mcastFwdDescPool=NULL;
+static mcast_fwd_descriptor_head_t free_mcast_fwd_descriptor_head;
+static struct rtl865x_multicastTable mCastTbl;
+static uint32 rtl865x_externalMulticastPortMask = 0;
+#if defined(__linux__) && defined(__KERNEL__)
+static struct timer_list rtl865x_mCastSysTimer; /*igmp timer*/
+#endif
+
+static int32 _rtl865x_initMCastFwdDescPool(void)
+{
+ int32 i;
+
+
+ MC_LIST_INIT(&free_mcast_fwd_descriptor_head);
+
+ TBL_MEM_ALLOC(rtl865x_mcastFwdDescPool, rtl865x_mcast_fwd_descriptor_t,MAX_MCAST_FWD_DESCRIPTOR_CNT);
+
+ if(rtl865x_mcastFwdDescPool!=NULL)
+ {
+ memset( rtl865x_mcastFwdDescPool, 0, MAX_MCAST_FWD_DESCRIPTOR_CNT * sizeof(rtl865x_mcast_fwd_descriptor_t));
+ }
+ else
+ {
+ return FAILED;
+ }
+
+ for(i = 0; i<MAX_MCAST_FWD_DESCRIPTOR_CNT;i++)
+ {
+ MC_LIST_INSERT_HEAD(&free_mcast_fwd_descriptor_head, &rtl865x_mcastFwdDescPool[i], next);
+ }
+
+ return SUCCESS;
+}
+
+static rtl865x_mcast_fwd_descriptor_t *_rtl865x_allocMCastFwdDesc(void)
+{
+ rtl865x_mcast_fwd_descriptor_t *retDesc=NULL;
+ retDesc = MC_LIST_FIRST(&free_mcast_fwd_descriptor_head);
+ if(retDesc!=NULL)
+ {
+ MC_LIST_REMOVE(retDesc, next);
+ memset(retDesc,0,sizeof(rtl865x_mcast_fwd_descriptor_t));
+ }
+ return retDesc;
+}
+
+static int32 _rtl865x_freeMCastFwdDesc(rtl865x_mcast_fwd_descriptor_t *descPtr)
+{
+ if(descPtr==NULL)
+ {
+ return SUCCESS;
+ }
+ memset(descPtr,0,sizeof(rtl865x_mcast_fwd_descriptor_t));
+ MC_LIST_INSERT_HEAD(&free_mcast_fwd_descriptor_head, descPtr, next);
+
+ return SUCCESS;
+}
+
+static int32 _rtl865x_flushMCastFwdDescChain(mcast_fwd_descriptor_head_t * descChainHead)
+{
+ rtl865x_mcast_fwd_descriptor_t * curDesc,*nextDesc;
+
+ if(descChainHead==NULL)
+ {
+ return SUCCESS;
+ }
+
+ curDesc=MC_LIST_FIRST(descChainHead);
+ while(curDesc)
+ {
+ nextDesc=MC_LIST_NEXT(curDesc, next );
+ /*remove from the old descriptor chain*/
+ MC_LIST_REMOVE(curDesc, next);
+ /*return to the free descriptor chain*/
+ _rtl865x_freeMCastFwdDesc(curDesc);
+ curDesc = nextDesc;
+ }
+
+ return SUCCESS;
+}
+
+
+
+static int32 _rtl865x_mCastFwdDescEnqueue(mcast_fwd_descriptor_head_t * queueHead,
+ rtl865x_mcast_fwd_descriptor_t * enqueueDesc)
+{
+
+ rtl865x_mcast_fwd_descriptor_t *newDesc;
+ rtl865x_mcast_fwd_descriptor_t *curDesc,*nextDesc;
+ if(queueHead==NULL)
+ {
+ return FAILED;
+ }
+
+ if(enqueueDesc==NULL)
+ {
+ return SUCCESS;
+ }
+
+ /*multicast forward descriptor is internal maintained,always alloc new one*/
+ newDesc=_rtl865x_allocMCastFwdDesc();
+
+ if(newDesc!=NULL)
+ {
+ memcpy(newDesc, enqueueDesc,sizeof(rtl865x_mcast_fwd_descriptor_t ));
+ //memset(&(newDesc->next), 0, sizeof(MC_LIST_ENTRY(rtl865x_mcast_fwd_descriptor_s)));
+ newDesc->next.le_next=NULL;
+ newDesc->next.le_prev=NULL;
+ }
+ else
+ {
+ /*no enough memory*/
+ return FAILED;
+ }
+
+
+ for(curDesc=MC_LIST_FIRST(queueHead);curDesc!=NULL;curDesc=nextDesc)
+ {
+
+ nextDesc=MC_LIST_NEXT(curDesc, next);
+
+ /*merge two descriptor*/
+ // if((strcmp(curDesc->netifName,newDesc->netifName)==0) && (curDesc->vid==newDesc->vid))
+ if(strcmp(curDesc->netifName,newDesc->netifName)==0)
+ {
+
+ if(newDesc->descPortMask==0)
+ {
+ newDesc->descPortMask=curDesc->descPortMask;
+ }
+ MC_LIST_REMOVE(curDesc, next);
+ _rtl865x_freeMCastFwdDesc(curDesc);
+
+ }
+ }
+
+ /*not matched descriptor is found*/
+ MC_LIST_INSERT_HEAD(queueHead, newDesc, next);
+
+ return SUCCESS;
+
+}
+
+
+static int32 _rtl865x_mergeMCastFwdDescChain(mcast_fwd_descriptor_head_t * targetChainHead ,
+ rtl865x_mcast_fwd_descriptor_t *srcChain)
+{
+ rtl865x_mcast_fwd_descriptor_t *curDesc;
+
+ if(targetChainHead==NULL)
+ {
+ return FAILED;
+ }
+
+ for(curDesc=srcChain; curDesc!=NULL; curDesc=MC_LIST_NEXT(curDesc,next))
+ {
+
+ _rtl865x_mCastFwdDescEnqueue(targetChainHead, curDesc);
+
+ }
+
+ return SUCCESS;
+}
+
+
+
+
+static int32 _rtl865x_initMCastEntryPool(void)
+{
+ int32 index;
+ rtl865x_tblDrv_mCast_t *multiCast_t;
+
+ TBL_MEM_ALLOC(multiCast_t, rtl865x_tblDrv_mCast_t ,MAX_MCAST_TABLE_ENTRY_CNT);
+ TAILQ_INIT(&mCastTbl.freeList.freeMultiCast);
+ for(index=0; index<MAX_MCAST_TABLE_ENTRY_CNT; index++)
+ {
+ memset( &multiCast_t[index], 0, sizeof(rtl865x_tblDrv_mCast_t));
+ TAILQ_INSERT_HEAD(&mCastTbl.freeList.freeMultiCast, &multiCast_t[index], nextMCast);
+ }
+
+ TBL_MEM_ALLOC(multiCast_t, rtl865x_tblDrv_mCast_t, RTL8651_MULTICASTTBL_SIZE);
+ memset(multiCast_t, 0,RTL8651_MULTICASTTBL_SIZE* sizeof(rtl865x_tblDrv_mCast_t));
+ mCastTbl.inuseList.mCastTbl = (void *)multiCast_t;
+
+ for(index=0; index<RTL8651_MULTICASTTBL_SIZE; index++)
+ {
+ TAILQ_INIT(&mCastTbl.inuseList.mCastTbl[index]);
+ }
+
+ return SUCCESS;
+}
+
+static rtl865x_tblDrv_mCast_t * _rtl865x_allocMCastEntry(uint32 hashIndex)
+{
+ rtl865x_tblDrv_mCast_t *newEntry;
+ newEntry=TAILQ_FIRST(&mCastTbl.freeList.freeMultiCast);
+ if (newEntry == NULL)
+ {
+ return NULL;
+ }
+
+ TAILQ_REMOVE(&mCastTbl.freeList.freeMultiCast, newEntry, nextMCast);
+
+
+ /*initialize it*/
+ if(MC_LIST_FIRST(&newEntry->fwdDescChain)!=NULL)
+ {
+ _rtl865x_flushMCastFwdDescChain(&newEntry->fwdDescChain);
+ }
+ MC_LIST_INIT(&newEntry->fwdDescChain);
+
+ memset(newEntry, 0, sizeof(rtl865x_tblDrv_mCast_t));
+
+ TAILQ_INSERT_TAIL(&mCastTbl.inuseList.mCastTbl[hashIndex], newEntry, nextMCast);
+
+ return newEntry;
+}
+
+static int32 _rtl865x_flushMCastEntry(rtl865x_tblDrv_mCast_t *mCastEntry)
+{
+ if(mCastEntry==NULL)
+ {
+ return SUCCESS;
+ }
+
+ _rtl865x_flushMCastFwdDescChain(&mCastEntry->fwdDescChain);
+
+ memset(mCastEntry, 0, sizeof(rtl865x_tblDrv_mCast_t));
+ return SUCCESS;
+}
+
+static int32 _rtl865x_freeMCastEntry(rtl865x_tblDrv_mCast_t * mCastEntry, uint32 hashIndex)
+{
+ if(mCastEntry==NULL)
+ {
+ return SUCCESS;
+ }
+
+ TAILQ_REMOVE(&mCastTbl.inuseList.mCastTbl[hashIndex], mCastEntry, nextMCast);
+ _rtl865x_flushMCastEntry(mCastEntry);
+ TAILQ_INSERT_HEAD(&mCastTbl.freeList.freeMultiCast, mCastEntry, nextMCast);
+ return SUCCESS;
+}
+
+
+static uint32 _rtl865x_doMCastEntrySrcVlanPortFilter(rtl865x_tblDrv_mCast_t *mCastEntry)
+{
+ rtl865x_mcast_fwd_descriptor_t * curDesc,*nextDesc;
+ if(mCastEntry==NULL)
+ {
+ return SUCCESS;
+ }
+
+ for(curDesc=MC_LIST_FIRST(&mCastEntry->fwdDescChain);curDesc!=NULL;curDesc=nextDesc)
+ {
+ nextDesc=MC_LIST_NEXT(curDesc, next);
+ {
+ curDesc->fwdPortMask=curDesc->fwdPortMask & (~(1<<mCastEntry->port));
+ if(curDesc->fwdPortMask==0)
+ {
+ /*remove from the old chain*/
+ MC_LIST_REMOVE(curDesc, next);
+ /*return to the free descriptor chain*/
+ _rtl865x_freeMCastFwdDesc(curDesc);
+
+ }
+ }
+
+ }
+
+ return SUCCESS;
+}
+
+
+static uint32 rtl865x_genMCastEntryAsicFwdMask(rtl865x_tblDrv_mCast_t *mCastEntry)
+{
+ uint32 asicFwdPortMask=0;
+ rtl865x_mcast_fwd_descriptor_t * curDesc;
+ if(mCastEntry==NULL)
+ {
+ return 0;
+ }
+
+ MC_LIST_FOREACH(curDesc, &(mCastEntry->fwdDescChain), next)
+ {
+ if(curDesc->toCpu==0)
+ {
+ asicFwdPortMask|=(curDesc->fwdPortMask & ((1<<RTL8651_MAC_NUMBER)-1));
+ }
+ else
+ {
+ asicFwdPortMask|=( 0x01<<RTL8651_MAC_NUMBER);
+ }
+ }
+ asicFwdPortMask = asicFwdPortMask & (~(1<<mCastEntry->port));
+ return asicFwdPortMask;
+}
+
+static uint16 rtl865x_genMCastEntryCpuFlag(rtl865x_tblDrv_mCast_t *mCastEntry)
+{
+ uint16 cpuFlag=FALSE;
+ rtl865x_mcast_fwd_descriptor_t * curDesc;
+ if(mCastEntry==NULL)
+ {
+ return 0;
+ }
+
+ if(mCastEntry->cpuHold==TRUE)
+ {
+ cpuFlag=TRUE;
+ }
+
+ MC_LIST_FOREACH(curDesc, &(mCastEntry->fwdDescChain), next)
+ {
+ if( (curDesc->toCpu==TRUE) ||
+ (memcmp(curDesc->netifName, RTL_WLAN_NAME,4)==0) )
+ {
+ cpuFlag=TRUE;
+ }
+ }
+
+ return cpuFlag;
+}
+
+/*for linux bridge level igmp snooping usage*/
+static uint32 rtl865x_getMCastEntryDescPortMask(rtl865x_tblDrv_mCast_t *mCastEntry)
+{
+ uint32 descPortMask=0;
+ rtl865x_mcast_fwd_descriptor_t * curDesc;
+ if(mCastEntry==NULL)
+ {
+ return 0;
+ }
+
+ MC_LIST_FOREACH(curDesc, &(mCastEntry->fwdDescChain), next)
+ {
+ descPortMask=descPortMask | curDesc->descPortMask;
+ }
+
+ return descPortMask;
+}
+
+
+/*=======================================
+ * Multicast Table APIs
+ *=======================================*/
+#define RTL865X_MULTICASE_TABLE_APIs
+
+static void _rtl865x_setASICMulticastPortStatus(void) {
+ uint32 index;
+
+ for (index=0; index<RTL8651_PORT_NUMBER+rtl8651_totalExtPortNum; index++) {
+ rtl8651_setAsicMulticastPortInternal(index, (rtl865x_externalMulticastPortMask&(1<<index))?FALSE:TRUE);
+ }
+}
+
+void rtl865x_arrangeMulticastPortStatus(void) {
+
+ rtl865x_externalMulticastPortMask=rtl865x_getExternalPortMask();
+ _rtl865x_setASICMulticastPortStatus();
+}
+
+/* +@func int32 | rtl865x_addMulticastExternalPort | API to add a hardware multicast external port.
+@parm uint32 | extPort | External port number to be added.
+@rvalue SUCCESS |Add hardware multicast external port successfully.
+@rvalue FAILED |Add hardware multicast external port failed.
+*/
+int32 rtl865x_addMulticastExternalPort(uint32 extPort)
+{
+ rtl865x_externalMulticastPortMask |= (1<<extPort);
+ _rtl865x_setASICMulticastPortStatus();
+ return SUCCESS;
+}
+
+/* +@func int32 | rtl865x_delMulticastExternalPort | API to delete a hardware multicast external port.
+@parm uint32 | extPort | External port number to be deleted.
+@rvalue SUCCESS |Delete external port successfully.
+@rvalue FAILED |Delete external port failed.
+*/
+int32 rtl865x_delMulticastExternalPort(uint32 extPort)
+{
+ rtl865x_externalMulticastPortMask &= ~(1<<extPort);
+ _rtl865x_setASICMulticastPortStatus();
+ return SUCCESS;
+}
+
+/* +@func int32 | rtl865x_setMulticastExternalPortMask | API to set hardware multicast external port mask.
+@parm uint32 | extPortMask | External port mask to be set.
+@rvalue SUCCESS |Set external port mask successfully.
+@rvalue FAILED |Set external port mask failed.
+*/
+int32 rtl865x_setMulticastExternalPortMask(uint32 extPortMask)
+{
+ rtl865x_externalMulticastPortMask =extPortMask;
+ _rtl865x_setASICMulticastPortStatus();
+ return SUCCESS;
+}
+
+/* +@func int32 | rtl865x_addMulticastExternalPortMask | API to add hardware multicast external port mask.
+@parm uint32 | extPortMask | External port mask to be added.
+@rvalue SUCCESS |Add external port mask successfully.
+@rvalue FAILED |Add external port mask failed.
+*/
+int32 rtl865x_addMulticastExternalPortMask(uint32 extPortMask)
+{
+ rtl865x_externalMulticastPortMask|= extPortMask;
+ _rtl865x_setASICMulticastPortStatus();
+ return SUCCESS;
+}
+
+/* +@func int32 | rtl865x_delMulticastExternalPortMask | API to delete hardware multicast external port mask.
+@parm uint32 | extPortMask | External port mask to be deleted.
+@rvalue SUCCESS |Delete external port mask successfully.
+@rvalue FAILED |Delete external port mask failed.
+*/
+int32 rtl865x_delMulticastExternalPortMask(uint32 extPortMask)
+{
+ rtl865x_externalMulticastPortMask &= ~extPortMask;
+ _rtl865x_setASICMulticastPortStatus();
+ return SUCCESS;
+}
+
+int32 rtl865x_getMulticastExternalPortMask(void)
+{
+ return rtl865x_externalMulticastPortMask ;
+}
+
+static inline void _rtl865x_patchPppoeWeak(rtl865x_tblDrv_mCast_t *mCast_t)
+{
+ rtl865x_mcast_fwd_descriptor_t * curDesc;
+ uint32 netifType;
+ /* patch: keep cache in software if one vlan's interface is pppoe */
+ MC_LIST_FOREACH(curDesc, &(mCast_t->fwdDescChain), next)
+ {
+ if(rtl865x_getNetifType(curDesc->netifName, &netifType)==SUCCESS)
+ {
+ /*how about pptp,l2tp?*/
+ if(netifType==IF_PPPOE)
+ {
+ mCast_t->flag |= RTL865X_MULTICAST_PPPOEPATCH_CPUBIT;
+ return;
+ }
+ }
+
+ }
+
+ mCast_t->flag &= ~RTL865X_MULTICAST_PPPOEPATCH_CPUBIT;
+}
+#if 0
+static int _rtl865x_checkMulticastEntryEqual(rtl865x_tblDrv_mCast_t * mCastEntry1, rtl865x_tblDrv_mCast_t * mCastEntry2)
+{
+ if((mCastEntry1==NULL) && (mCastEntry2==NULL))
+ {
+ return TRUE;
+ }
+
+ if((mCastEntry1==NULL) && (mCastEntry2!=NULL))
+ {
+ return FALSE;
+ }
+
+ if((mCastEntry1!=NULL) && (mCastEntry2==NULL))
+ {
+ return FALSE;
+ }
+
+ if(mCastEntry1->sip!=mCastEntry2->sip)
+ {
+ return FALSE;
+ }
+
+ if(mCastEntry1->dip!=mCastEntry2->dip)
+ {
+ return FALSE;
+ }
+
+ if(mCastEntry1->svid!=mCastEntry2->svid)
+ {
+ return FALSE;
+ }
+
+ if(mCastEntry1->port!=mCastEntry2->port)
+ {
+ return FALSE;
+ }
+
+ if(mCastEntry1->mbr!=mCastEntry2->mbr)
+ {
+ return FALSE;
+ }
+
+ if(mCastEntry1->cpu!=mCastEntry2->cpu)
+ {
+ return FALSE;
+ }
+
+ if(mCastEntry1->extIp!=mCastEntry2->extIp)
+ {
+ return FALSE;
+ }
+
+ if(mCastEntry1->flag!=mCastEntry2->flag)
+ {
+ return FALSE;
+ }
+
+
+ if(mCastEntry1->inAsic!=mCastEntry2->inAsic)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif
+#ifdef CONFIG_PROC_FS
+static unsigned int mcastAddOpCnt=0;
+unsigned int _rtl865x_getAddMcastOpCnt(void)
+{
+ return mcastAddOpCnt;
+}
+
+static unsigned int mcastDelOpCnt=0;
+unsigned int _rtl865x_getDelMcastOpCnt(void)
+{
+ return mcastDelOpCnt;
+}
+#endif
+/* re-select Multicast entry to ASIC for the index ""entryIndex */
+static void _rtl865x_arrangeMulticast(uint32 entryIndex)
+{
+ rtl865x_tblAsicDrv_multiCastParam_t asic_mcast;
+ rtl865x_tblDrv_mCast_t *mCast_t=NULL;
+ rtl865x_tblDrv_mCast_t *select_t=NULL;
+ rtl865x_tblDrv_mCast_t *swapOutEntry=NULL;
+ int32 retval;
+
+ TAILQ_FOREACH(mCast_t, &mCastTbl.inuseList.mCastTbl[entryIndex], nextMCast)
+ {
+ if ((mCast_t->cpu == 0) && !(mCast_t->flag & RTL865X_MULTICAST_PPPOEPATCH_CPUBIT))
+ { /* Ignore cpu=1 */
+
+ if(mCast_t->inAsic==TRUE)
+ {
+ if(swapOutEntry==NULL)
+ {
+ swapOutEntry=mCast_t;
+ }
+ else
+ {
+ /*impossible, two flow in one asic entry*/
+ swapOutEntry->inAsic=FALSE;
+ mCast_t->inAsic = FALSE;
+ }
+ }
+
+ if (select_t)
+ {
+#if 1
+ if ((mCast_t->unKnownMCast==TRUE) && (select_t->unKnownMCast==TRUE))
+ {
+ /*unknown multicast, select the heavy load*/
+ if (mCast_t->maxPPS > select_t->maxPPS)
+ {
+ select_t = mCast_t;
+ }
+ }
+ else if ((mCast_t->unKnownMCast==FALSE) && (select_t->unKnownMCast==TRUE))
+ {
+ /*replace unknown multicast*/
+ select_t = mCast_t;
+ }
+ else if((mCast_t->unKnownMCast==FALSE) && (select_t->unKnownMCast==FALSE))
+ {
+ /*select the heavy load*/
+ if (mCast_t->maxPPS > select_t->maxPPS)
+ {
+ select_t = mCast_t;
+ }
+ }
+ else if((mCast_t->unKnownMCast==TRUE) && (select_t->unKnownMCast==FALSE))
+ {
+ /*this stream is unknown multicast,needn't change candidate*/
+ }
+#else
+ if ((mCast_t->mbr==0) && (select_t->mbr==0))
+ {
+ /*unknown multicast, select the heavy load*/
+ if (mCast_t->maxPPS > select_t->maxPPS)
+ {
+ select_t = mCast_t;
+ }
+ }
+ else if ((mCast_t->mbr!=0) && (select_t->mbr==0))
+ {
+ /*replace unknown multicast*/
+ select_t = mCast_t;
+ }
+ else if((mCast_t->mbr!=0) && (select_t->mbr!=0))
+ {
+ /*select the heavy load*/
+ if (mCast_t->maxPPS > select_t->maxPPS)
+ {
+ select_t = mCast_t;
+ }
+ }
+ else if((mCast_t->mbr==0) && (select_t->mbr!=0))
+ {
+ /*this stream is unknown multicast,needn't change candidate*/
+ }
+#endif
+
+
+ }
+ else
+ {
+ select_t = mCast_t;
+ }
+
+ //printk("mCast_t->dip is 0x%x,mCast_t->inAsic is %d,mCast_t->maxPPS is %d\n\n\n",mCast_t->dip,mCast_t->inAsic,mCast_t->maxPPS);
+ }
+ else
+ {
+ mCast_t->inAsic = FALSE; /* reset "inAsic" bit */
+ }
+
+
+ }
+ /*
+ if(swapOutEntry)
+ {
+ printk("%s:%d,swapOutEntry->dip is 0x%x,swapOutEntry->mbr is 0x%x\n",__FUNCTION__,__LINE__,swapOutEntry->dip,swapOutEntry->mbr);
+
+ }
+
+ if (select_t)
+ {
+ printk("%s:%d,select_t->dip is 0x%x,select_t->mbr is 0x%x\n",__FUNCTION__,__LINE__,select_t->dip,select_t->mbr);
+ }
+ */
+ if (select_t)
+ {
+ if((swapOutEntry==NULL) ||(select_t==swapOutEntry))
+ {
+ select_t->age = RTL865X_MULTICAST_TABLE_ASIC_AGE;
+ bzero(&asic_mcast, sizeof(rtl865x_tblAsicDrv_multiCastParam_t));
+ memcpy(&asic_mcast, select_t, (uint32)&(((rtl865x_tblDrv_mCast_t *)0)->extIp));
+ if (select_t->extIp)
+ {
+
+#ifdef CONFIG_RTL_LAYERED_DRIVER_L3
+ int32 ipIdx;
+ if(rtl865x_getIpIdxByExtIp(select_t->extIp, &ipIdx)==SUCCESS)
+ {
+ asic_mcast.extIdx=(uint16)ipIdx;
+ }
+#else
+ asic_mcast.extIdx=0;
+#endif
+
+ }
+ retval = rtl8651_setAsicIpMulticastTable(&asic_mcast);
+
+#ifdef CONFIG_PROC_FS
+ mcastAddOpCnt++;
+#endif
+ assert(retval == SUCCESS);
+ if(retval==SUCCESS)
+ {
+ select_t->inAsic = TRUE;
+ }
+ else
+ {
+ select_t->inAsic = FALSE;
+ rtl8651_delAsicIpMulticastTable(entryIndex);
+#ifdef CONFIG_PROC_FS
+ mcastDelOpCnt++;
+#endif
+ }
+
+ assert(retval == SUCCESS);
+ TAILQ_REMOVE(&mCastTbl.inuseList.mCastTbl[entryIndex], select_t, nextMCast);
+ TAILQ_INSERT_HEAD(&mCastTbl.inuseList.mCastTbl[entryIndex], select_t, nextMCast);
+ }
+ else/*(swapOutEntry!=NULL) && (select_t!=swapOutEntry)*/
+ {
+ /*disable swap and only explicit joined mulicast flow can replace unknown multicast flow*/
+ if((swapOutEntry->unKnownMCast==TRUE) &&(select_t->unKnownMCast==FALSE))
+ {
+ /*don't forget to set swapOutEntry's inAsic flag*/
+ swapOutEntry->inAsic=FALSE;
+
+ select_t->age = RTL865X_MULTICAST_TABLE_ASIC_AGE;
+ bzero(&asic_mcast, sizeof(rtl865x_tblAsicDrv_multiCastParam_t));
+ memcpy(&asic_mcast, select_t, (uint32)&(((rtl865x_tblDrv_mCast_t *)0)->extIp));
+
+ if (select_t->extIp)
+ {
+#ifdef CONFIG_RTL_LAYERED_DRIVER_L3
+ int32 ipIdx;
+ if(rtl865x_getIpIdxByExtIp(select_t->extIp, &ipIdx)==SUCCESS)
+ {
+ asic_mcast.extIdx=(uint16)ipIdx;
+ }
+#else
+ asic_mcast.extIdx=0;
+#endif
+ }
+
+ retval = rtl8651_setAsicIpMulticastTable(&asic_mcast);
+#ifdef CONFIG_PROC_FS
+ mcastAddOpCnt++;
+#endif
+ assert(retval == SUCCESS);
+ if(retval==SUCCESS)
+ {
+ select_t->inAsic = TRUE;
+ }
+ else
+ {
+ select_t->inAsic = FALSE;
+ rtl8651_delAsicIpMulticastTable(entryIndex);
+#ifdef CONFIG_PROC_FS
+ mcastDelOpCnt++;
+#endif
+ }
+
+ TAILQ_REMOVE(&mCastTbl.inuseList.mCastTbl[entryIndex], select_t, nextMCast);
+ TAILQ_INSERT_HEAD(&mCastTbl.inuseList.mCastTbl[entryIndex], select_t, nextMCast);
+
+ }
+ else
+ {
+ if(swapOutEntry->inAsic == FALSE)
+ {
+ /*maybe something is wrong, we remove the asic entry*/
+ rtl8651_delAsicIpMulticastTable(entryIndex);
+#ifdef CONFIG_PROC_FS
+ mcastDelOpCnt++;
+#endif
+ }
+
+ }
+
+ }
+
+ }
+ else
+ {
+ if(swapOutEntry!=NULL)
+ {
+ swapOutEntry->inAsic=FALSE;
+ }
+ rtl8651_delAsicIpMulticastTable(entryIndex);
+#ifdef CONFIG_PROC_FS
+ mcastDelOpCnt++;
+#endif
+ }
+}
+
+
+static void _rtl865x_mCastEntryReclaim(void)
+{
+ uint32 index;
+ uint32 freeCnt=0;
+ uint32 asicFwdPortMask=0;
+ uint32 needReArrange=FALSE;
+ rtl865x_tblDrv_mCast_t *curMCastEntry, *nextMCastEntry;
+
+ /*free unused software forward entry*/
+ for(index=0; index<RTL8651_MULTICASTTBL_SIZE; index++)
+ {
+ curMCastEntry = TAILQ_FIRST(&mCastTbl.inuseList.mCastTbl[index]);
+ while (curMCastEntry)
+ {
+ nextMCastEntry = TAILQ_NEXT(curMCastEntry, nextMCast);
+ if((curMCastEntry->inAsic==FALSE) && (curMCastEntry->count==0))
+ {
+ _rtl865x_freeMCastEntry(curMCastEntry, index);
+ freeCnt++;
+ }
+ curMCastEntry = nextMCastEntry;
+ }
+
+ }
+
+ if(freeCnt>0)
+ {
+ return;
+ }
+
+ for(index=0; index<RTL8651_MULTICASTTBL_SIZE; index++)
+ {
+ curMCastEntry = TAILQ_FIRST(&mCastTbl.inuseList.mCastTbl[index]);
+ needReArrange=FALSE;
+ while (curMCastEntry)
+ {
+ nextMCastEntry = TAILQ_NEXT(curMCastEntry, nextMCast);
+ if(curMCastEntry->inAsic)
+ {
+ asicFwdPortMask=rtl865x_genMCastEntryAsicFwdMask(curMCastEntry);
+ if(asicFwdPortMask==0)
+ {
+ _rtl865x_freeMCastEntry(curMCastEntry, index);
+ needReArrange=TRUE;
+ }
+ }
+ curMCastEntry = nextMCastEntry;
+ }
+
+ if(needReArrange==TRUE)
+ {
+ _rtl865x_arrangeMulticast(index);
+ }
+ }
+
+ return;
+}
+/* +@func rtl865x_tblDrv_mCast_t * | rtl865x_findMCastEntry | API to find a hardware multicast entry.
+@parm ipaddr_t | mAddr | Multicast stream destination group address.
+@parm ipaddr_t | sip | Multicast stream source ip address.
+@parm uint16 | svid | Multicast stream input vlan index.
+@parm uint16 | sport | Multicast stream input port number.
+*/
+rtl865x_tblDrv_mCast_t *rtl865x_findMCastEntry(ipaddr_t mAddr, ipaddr_t sip, uint16 svid, uint16 sport)
+{
+ rtl865x_tblDrv_mCast_t *mCast_t;
+ uint32 entry = rtl8651_ipMulticastTableIndex(sip, mAddr);
+ TAILQ_FOREACH(mCast_t, &mCastTbl.inuseList.mCastTbl[entry], nextMCast) {
+ if (mCast_t->dip==mAddr && mCast_t->sip==sip && mCast_t->svid==svid && mCast_t->port==sport)
+ {
+ if (mCast_t->inAsic == FALSE)
+ {
+ mCast_t->age = RTL865X_MULTICAST_TABLE_AGE;
+ mCast_t->count ++;
+ }
+
+ return mCast_t;
+ }
+
+ mCast_t->count ++;
+ if(mCast_t->maxPPS<mCast_t->count)
+ {
+ /*update maxPPS*/
+ mCast_t->maxPPS=mCast_t->count ;
+ }
+
+ }
+ return (rtl865x_tblDrv_mCast_t *)NULL;
+}
+
+/* +@func int32 | rtl865x_addMulticastEntry | API to add a hardwawre multicast forwarding entry.
+@parm ipaddr_t | mAddr | Multicast flow Destination group address.
+@parm ipaddr_t | sip | Multicast flow source ip address.
+@parm uint16 | svid | Multicast flow input vlan index.
+@parm uint16 | sport | Multicast flow input port number.
+@parm rtl865x_mcast_fwd_descriptor_t * | newFwdDescChain | Multicast flow forwarding descriptor chain to be added.
+@parm int32 | flushOldChain | Flag to indicate to flush old mulicast forwarding descriptor chain or not. 1 is to flush old chain, and 0 is not to.
+@parm ipaddr_t | extIp | External source ip address used when forward multicast data from lan to wan.
+@parm int8 | toCpu | Cpu forwarding flag, 1 is to forward multicast data by cpu,and 0 is not.
+@parm int8 | flag | For future usage, set to 0 at present.
+@rvalue SUCCESS |Add hardware multicast forwarding entry successfully.
+@rvalue FAILED |Add hardware multicast forwarding entry failed.
+*/
+int32 rtl865x_addMulticastEntry(ipaddr_t mAddr, ipaddr_t sip, uint16 svid, uint16 sport,
+ rtl865x_mcast_fwd_descriptor_t * newFwdDescChain,
+ int32 flushOldChain, ipaddr_t extIp, char cpuHold, uint8 flag)
+{
+
+ rtl865x_tblDrv_mCast_t *mCast_t;
+ uint32 hashIndex = rtl8651_ipMulticastTableIndex(sip, mAddr);
+ struct rtl_groupInfo groupInfo;
+ /*windows xp upnp:239.255.255.0*/
+ if(mAddr==0xEFFFFFFA)
+ {
+ return FAILED;
+ }
+#if 0
+ /*reserved multicast address 224.0.0.x*/
+ if((mAddr & 0xFFFFFF00) == 0xE0000000)
+ {
+ return FAILED;
+ }
+#endif
+ /*try to match hash line*/
+ TAILQ_FOREACH(mCast_t, &mCastTbl.inuseList.mCastTbl[hashIndex], nextMCast)
+ {
+ if (mCast_t->sip==sip && mCast_t->dip==mAddr && mCast_t->svid==svid && mCast_t->port==sport)
+ break;
+ }
+
+ if (mCast_t == NULL)
+ {
+ mCast_t=_rtl865x_allocMCastEntry(hashIndex);
+ if (mCast_t == NULL)
+ {
+ _rtl865x_mCastEntryReclaim();
+ mCast_t=_rtl865x_allocMCastEntry(hashIndex);
+ if(mCast_t == NULL)
+ {
+ return FAILED;
+ }
+ }
+ mCast_t->sip = sip;
+ mCast_t->dip = mAddr;
+ mCast_t->svid = svid;
+ mCast_t->port = sport;
+ mCast_t->mbr = 0;
+ mCast_t->count = 0;
+ mCast_t->maxPPS = 0;
+ mCast_t->inAsic = FALSE;
+ }
+
+ if(flushOldChain)
+ {
+ _rtl865x_flushMCastFwdDescChain(&mCast_t->fwdDescChain);
+
+ }
+
+ _rtl865x_mergeMCastFwdDescChain(&mCast_t->fwdDescChain,newFwdDescChain);
+ _rtl865x_doMCastEntrySrcVlanPortFilter(mCast_t);
+
+ mCast_t->mbr = rtl865x_genMCastEntryAsicFwdMask(mCast_t);
+ mCast_t->extIp = extIp;
+
+ mCast_t->age = RTL865X_MULTICAST_TABLE_AGE;
+#if 0
+ mCast_t->cpu = (toCpu==TRUE? 1: 0);
+#else
+ mCast_t->cpuHold = cpuHold;
+ mCast_t->cpu = rtl865x_genMCastEntryCpuFlag(mCast_t);
+#endif
+ mCast_t->flag = flag;
+
+ if (extIp)
+ mCast_t->flag |= RTL865X_MULTICAST_EXTIP_SET;
+ else
+ mCast_t->flag &= ~RTL865X_MULTICAST_EXTIP_SET;
+
+ rtl_getGroupInfo(mAddr, &groupInfo);
+ if(groupInfo.ownerMask==0)
+ {
+ mCast_t->unKnownMCast=TRUE;
+ }
+ else
+ {
+ mCast_t->unKnownMCast=FALSE;
+ }
+
+ _rtl865x_patchPppoeWeak(mCast_t);
+ _rtl865x_arrangeMulticast(hashIndex);
+ return SUCCESS;
+}
+
+
+/* +@func int32 | rtl865x_delMulticastEntry | API to delete multicast forwarding entry related with a certain group address.
+@parm ipaddr_t | mcast_addr | Group address to be mached in deleting hardware multicast forwarding entry.
+@rvalue SUCCESS |Delete hardware multicast forwarding entry successfully.
+@rvalue FAILED |Delete hardware multicast forwarding entry failed.
+*/
+int32 rtl865x_delMulticastEntry(ipaddr_t mcast_addr)
+{
+
+ rtl865x_tblDrv_mCast_t *mCastEntry, *nextMCastEntry;
+ uint32 entry;
+ uint32 deleteFlag=FALSE;
+
+ for(entry=0; entry<RTL8651_MULTICASTTBL_SIZE; entry++)
+ {
+ deleteFlag=FALSE;
+ mCastEntry = TAILQ_FIRST(&mCastTbl.inuseList.mCastTbl[entry]);
+ while (mCastEntry)
+ {
+ nextMCastEntry = TAILQ_NEXT(mCastEntry, nextMCast);
+ if (!mcast_addr || mCastEntry->dip == mcast_addr)
+ {
+ deleteFlag=TRUE;
+ _rtl865x_freeMCastEntry(mCastEntry, entry);
+ }
+
+ mCastEntry = nextMCastEntry;
+ }
+
+ if(deleteFlag==TRUE)
+ {
+ _rtl865x_arrangeMulticast(entry);
+ }
+ }
+
+ return SUCCESS;
+}
+
+#if 0
+/*the following function maybe used in future*/
+
+int32 rtl865x_addMulticastFwdDesc(ipaddr_t mcast_addr, rtl865x_mcast_fwd_descriptor_t * newFwdDesc)
+{
+
+ rtl865x_tblDrv_mCast_t *mCast_t;
+ uint32 entry, matchedIdx = 0;
+ uint32 oldFwdPortMask,newFwdPortMask;
+ if(newFwdDesc==NULL)
+ {
+ return SUCCESS;
+ }
+
+ for (entry=0; entry< RTL8651_MULTICASTTBL_SIZE; entry++)
+ {
+ TAILQ_FOREACH(mCast_t, &mCastTbl.inuseList.mCastTbl[entry], nextMCast)
+ {
+ if (mCast_t->dip != mcast_addr)
+ continue;
+
+ oldFwdPortMask=mCast_t->mbr;
+
+ _rtl865x_mergeMCastFwdDescChain(&mCast_t->fwdDescChain,newFwdDesc);
+ _rtl865x_doMCastEntrySrcVlanPortFilter(mCast_t);
+
+ mCast_t->mbr = rtl865x_genMCastEntryFwdMask(mCast_t);
+ newFwdPortMask = mCast_t->mbr ;
+#ifndef RTL8651_MCAST_ALWAYS2UPSTREAM
+ if (mCast_t->flag & RTL865X_MULTICAST_UPLOADONLY)
+ { /* remove upload term*/
+ if(oldFwdPortMask!=newFwdPortMask)
+ {
+ mCast_t->flag &= ~RTL865X_MULTICAST_UPLOADONLY;
+ /* we assume multicast member will NEVER in External interface, so we remove
+ external ip now */
+ mCast_t->flag &= ~RTL865X_MULTICAST_EXTIP_SET;
+ mCast_t->extIp= 0;
+ }
+ }
+#endif /* RTL8651_MCAST_ALWAYS2UPSTREAM */
+
+ _rtl865x_patchPppoeWeak(mCast_t);
+ _rtl865x_arrangeMulticast(entry);
+ matchedIdx = entry;
+ }
+ }
+
+ if (matchedIdx)
+ {
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+int32 rtl865x_delMulticastFwdDesc(ipaddr_t mcast_addr, rtl865x_mcast_fwd_descriptor_t * deadFwdDesc)
+{
+
+ uint32 index;
+ rtl865x_tblDrv_mCast_t *mCastEntry, *nextMCastEntry;
+ uint32 oldFwdPortMask,newFwdPortMask;
+
+ for(index=0; index<RTL8651_MULTICASTTBL_SIZE; index++)
+ {
+
+ for (mCastEntry = TAILQ_FIRST(&mCastTbl.inuseList.mCastTbl[index]); mCastEntry; mCastEntry = nextMCastEntry)
+ {
+ nextMCastEntry=TAILQ_NEXT(mCastEntry, nextMCast);
+
+ if ((mcast_addr) && (mCastEntry->dip != mcast_addr))
+ {
+ continue;
+ }
+
+ oldFwdPortMask=mCastEntry->mbr;
+
+ _rtl865x_subMCastFwdDescChain(&mCastEntry->fwdDescChain, deadFwdDesc);
+
+ mCastEntry->mbr=rtl865x_genMCastEntryFwdMask(mCastEntry);
+ newFwdPortMask=mCastEntry->mbr;
+ if (mCastEntry->mbr == 0)
+ {
+ /*to-do:unknown multicast hardware blocking*/
+ _rtl865x_freeMCastEntry(mCastEntry, index);
+ mCastEntry=NULL;
+ _rtl865x_arrangeMulticast(index);
+ }
+ else
+ {
+
+ _rtl865x_patchPppoeWeak(mCastEntry);
+ }
+
+ }
+
+ _rtl865x_arrangeMulticast(index);
+ }
+
+ return SUCCESS;
+}
+
+int32 rtl865x_delMulticastUpStream(ipaddr_t mcast_addr, ipaddr_t sip, uint16 svid, uint16 sport)
+{
+ uint32 index;
+ rtl865x_tblDrv_mCast_t *mCast_t;
+
+ for(index=0; index<RTL8651_MULTICASTTBL_SIZE; index++)
+ {
+ TAILQ_FOREACH(mCast_t, &mCastTbl.inuseList.mCastTbl[index], nextMCast)
+ {
+ if ((!mcast_addr || mCast_t->dip == mcast_addr) &&
+ (!sip || mCast_t->sip==sip) &&
+ (!svid || mCast_t->svid==svid) &&
+ mCast_t->port==sport)
+ {
+ _rtl865x_freeMCastEntry(mCast_t, index);
+ _rtl865x_arrangeMulticast(index);
+ return SUCCESS;
+ }
+ }
+ }
+ return FAILED;
+}
+
+int32 rtl865x_delMulticastByVid(uint32 vid)
+{
+ uint16 sport;
+ uint32 sportMask;
+ rtl865x_mcast_fwd_descriptor_t vlanFwdDesc;
+ memset(&vlanFwdDesc,0,sizeof(rtl865x_mcast_fwd_descriptor_t));
+
+ /* delete all upstream related to vid */
+ sport = 0;
+ sportMask=rtl865x_getVlanPortMask(vid);
+ while (sportMask)
+ {
+ if (sportMask & 1)
+ {
+ rtl865x_delMulticastUpStream(0, 0, vid, sport);
+ }
+
+ sportMask = sportMask >> 1;
+ sport ++;
+ }
+
+ /* delete all downstream related to vid*/
+ vlanFwdDesc.vid=vid;
+ vlanFwdDesc.fwdPortMask=rtl865x_getVlanPortMask(vid);
+ rtl865x_delMulticastFwdDesc(0, &vlanFwdDesc);
+
+ return FAILED;
+}
+
+int32 rtl865x_delMulticastByPort(uint32 port)
+{
+
+ rtl865x_mcast_fwd_descriptor_t portFwdDesc;
+ memset(&portFwdDesc,0,sizeof(rtl865x_mcast_fwd_descriptor_t));
+
+ /* delete all upstream related to this port */
+ rtl865x_delMulticastUpStream(0, 0, 0, port);
+
+ /* delete all downstream related to this port*/
+ portFwdDesc.vid=0;
+ portFwdDesc.fwdPortMask=1<<port;
+ rtl865x_delMulticastFwdDesc(0, &portFwdDesc);
+
+ return SUCCESS;
+}
+
+int32 rtl865x_setMGroupAttribute(ipaddr_t groupIp, int8 toCpu)
+{
+ uint32 index;
+ rtl865x_tblDrv_mCast_t *mCast_t;
+
+ for(index=0; index<RTL8651_MULTICASTTBL_SIZE; index++)
+ {
+ TAILQ_FOREACH(mCast_t, &mCastTbl.inuseList.mCastTbl[index], nextMCast)
+ {
+ if (mCast_t->dip == groupIp)
+ {
+ mCast_t->cpu = (toCpu==TRUE? 1: 0);
+ }
+ }
+ _rtl865x_arrangeMulticast(index);
+ }
+ return SUCCESS;
+}
+
+
+static int32 _rtl865x_subMCastFwdDescChain(mcast_fwd_descriptor_head_t * targetChainHead,rtl865x_mcast_fwd_descriptor_t *srcChain)
+{
+ rtl865x_mcast_fwd_descriptor_t *curDesc;
+ if(targetChainHead==NULL)
+ {
+ return FAILED;
+ }
+
+ for(curDesc=srcChain; curDesc!=NULL; curDesc=MC_LIST_NEXT(curDesc,next))
+ {
+ _rtl865x_mCastFwdDescDequeue(targetChainHead, curDesc);
+ }
+
+ return SUCCESS;
+}
+
+static int32 _rtl865x_mCastFwdDescDequeue(mcast_fwd_descriptor_head_t * queueHead,rtl865x_mcast_fwd_descriptor_t * dequeueDesc)
+{
+ rtl865x_mcast_fwd_descriptor_t *curDesc,*nextDesc;
+
+ if(queueHead==NULL)
+ {
+ return FAILED;
+ }
+
+ if(dequeueDesc==NULL)
+ {
+ return FAILED;
+ }
+
+ for(curDesc=MC_LIST_FIRST(queueHead);curDesc!=NULL;curDesc=nextDesc)
+ {
+ nextDesc=MC_LIST_NEXT(curDesc, next );
+ if((strcmp(curDesc->netifName,dequeueDesc->netifName)==0) ||
+ ((dequeueDesc->vid==0 ) ||(curDesc->vid==dequeueDesc->vid)))
+ {
+ curDesc->fwdPortMask &= (~dequeueDesc->fwdPortMask);
+ if(curDesc->fwdPortMask==0)
+ {
+ /*remove from the old descriptor chain*/
+ MC_LIST_REMOVE(curDesc, next);
+ /*return to the free descriptor chain*/
+ _rtl865x_freeMCastFwdDesc(curDesc);
+
+ }
+
+ return SUCCESS;
+ }
+ }
+
+ /*never reach here*/
+ return SUCCESS;
+}
+
+#endif
+
+static int32 rtl865x_multicastCallbackFn(void *param)
+{
+ uint32 index;
+ uint32 oldDescPortMask,newDescPortMask;/*for device decriptor forwarding usage*/
+
+ uint32 oldAsicFwdPortMask,newAsicFwdPortMask;/*for physical port forwarding usage*/
+ uint32 oldCpuFlag,newCpuFlag;
+
+ rtl_multicastEventContext_t mcastEventContext;
+
+ rtl865x_mcast_fwd_descriptor_t newFwdDesc;
+ struct rtl_multicastDataInfo multicastDataInfo;
+ struct rtl_multicastFwdInfo multicastFwdInfo;
+ rtl865x_tblDrv_mCast_t *mCastEntry,*nextMCastEntry;
+ struct rtl_multicastDeviceInfo_s bridgeMCastDev;
+
+ struct rtl_groupInfo groupInfo;
+ int32 retVal=FAILED;
+
+ if(param==NULL)
+ {
+ return EVENT_CONTINUE_EXECUTE;
+ }
+ memcpy(&mcastEventContext,param,sizeof(rtl_multicastEventContext_t));
+ /*check device name's validity*/
+ if(strlen(mcastEventContext.devName)==0)
+ {
+ return EVENT_CONTINUE_EXECUTE;
+ }
+ #ifdef CONFIG_RTL865X_MUTLICAST_DEBUG
+ printk("%s:%d,mcastEventContext.devName is %s, mcastEventContext.groupAddr is 0x%x,mcastEventContext.sourceAdd is 0x%x,mcastEventContext.portMask is 0x%x\n",__FUNCTION__,__LINE__,mcastEventContext.devName, mcastEventContext.groupAddr[0], mcastEventContext.sourceAddr[0], mcastEventContext.portMask);
+ #endif
+ /*case 1:this is multicast event from bridge(br0) */
+ /*sync wlan and ethernet*/
+ //hyking:[Fix me] the RTL_BR_NAME...
+ if(memcmp(mcastEventContext.devName,RTL_BR_NAME,3)==0)
+ {
+
+ for (index=0; index< RTL8651_MULTICASTTBL_SIZE; index++)
+ {
+ for (mCastEntry = TAILQ_FIRST(&mCastTbl.inuseList.mCastTbl[index]); mCastEntry; mCastEntry = nextMCastEntry)
+ {
+ nextMCastEntry=TAILQ_NEXT(mCastEntry, nextMCast);
+
+ if ((mcastEventContext.groupAddr!=0) && (mCastEntry->dip != mcastEventContext.groupAddr[0]))
+ {
+ continue;
+ }
+
+ rtl_getGroupInfo(mCastEntry->dip, &groupInfo);
+ if(groupInfo.ownerMask==0)
+ {
+ mCastEntry->unKnownMCast=TRUE;
+ }
+ else
+ {
+ mCastEntry->unKnownMCast=FALSE;
+ }
+
+ oldDescPortMask=rtl865x_getMCastEntryDescPortMask( mCastEntry);
+
+ /*sync with control plane*/
+ memset(&newFwdDesc, 0 ,sizeof(rtl865x_mcast_fwd_descriptor_t));
+ strcpy(newFwdDesc.netifName,mcastEventContext.devName);
+ multicastDataInfo.ipVersion=4;
+ multicastDataInfo.sourceIp[0]= mCastEntry->sip;
+ multicastDataInfo.groupAddr[0]= mCastEntry->dip;
+ retVal= rtl_getMulticastDataFwdInfo(mcastEventContext.moduleIndex, &multicastDataInfo, &multicastFwdInfo);
+
+
+ if(retVal!=SUCCESS)
+ {
+ continue;
+ }
+
+ retVal= rtl_getIgmpSnoopingModuleDevInfo(mcastEventContext.moduleIndex, &bridgeMCastDev);
+ if(retVal!=SUCCESS)
+ {
+ continue;
+ }
+ newDescPortMask=multicastFwdInfo.fwdPortMask;
+ if( (oldDescPortMask != newDescPortMask) &&
+ ( ((newDescPortMask & bridgeMCastDev.swPortMask)!=0) ||
+ (((oldDescPortMask & bridgeMCastDev.swPortMask) !=0) && ((newDescPortMask & bridgeMCastDev.swPortMask)==0))) )
+ {
+ /*this multicast entry should be re-generated at linux protocol stack bridge level*/
+ _rtl865x_freeMCastEntry(mCastEntry, index);
+ _rtl865x_arrangeMulticast(index);
+ }
+
+ }
+ }
+
+ return EVENT_CONTINUE_EXECUTE;
+ }
+
+ /*case 2:this is multicast event from ethernet (eth0)*/
+ /*update ethernet forwarding port mask*/
+ if(memcmp(mcastEventContext.devName,"eth*",4)==0)
+ {
+ #ifdef CONFIG_RTL865X_MUTLICAST_DEBUG
+ printk("%s:%d,multicast event from ethernet (%s),mcastEventContext.groupAddr[0] is 0x%x\n",__FUNCTION__,__LINE__,mcastEventContext.devName,mcastEventContext.groupAddr[0]);
+ #endif
+
+ for (index=0; index< RTL8651_MULTICASTTBL_SIZE; index++)
+ {
+ for (mCastEntry = TAILQ_FIRST(&mCastTbl.inuseList.mCastTbl[index]); mCastEntry; mCastEntry = nextMCastEntry)
+ {
+ nextMCastEntry=TAILQ_NEXT(mCastEntry, nextMCast);
+
+ if ((mcastEventContext.groupAddr!=0) && (mCastEntry->dip != mcastEventContext.groupAddr[0]))
+ {
+ continue;
+ }
+
+ memset(&newFwdDesc, 0 ,sizeof(rtl865x_mcast_fwd_descriptor_t));
+ strcpy(newFwdDesc.netifName,mcastEventContext.devName);
+
+ /*save old multicast entry forward port mask*/
+ oldAsicFwdPortMask=mCastEntry->mbr;
+ oldCpuFlag=mCastEntry->cpu;
+
+ /*sync with control plane*/
+ multicastDataInfo.ipVersion=4;
+ multicastDataInfo.sourceIp[0]= mCastEntry->sip;
+ multicastDataInfo.groupAddr[0]= mCastEntry->dip;
+ retVal= rtl_getMulticastDataFwdInfo(mcastEventContext.moduleIndex, &multicastDataInfo, &multicastFwdInfo);
+
+ newFwdDesc.fwdPortMask=multicastFwdInfo.fwdPortMask & (~(1<<mCastEntry->port));
+ newFwdDesc.toCpu=multicastFwdInfo.cpuFlag;
+
+ /*update/replace old forward descriptor*/
+
+ _rtl865x_mergeMCastFwdDescChain(&mCastEntry->fwdDescChain,&newFwdDesc);
+ mCastEntry->mbr = rtl865x_genMCastEntryAsicFwdMask(mCastEntry);
+ mCastEntry->cpu = rtl865x_genMCastEntryCpuFlag(mCastEntry);
+
+ newAsicFwdPortMask = mCastEntry->mbr ;
+ newCpuFlag =mCastEntry->cpu;
+
+ #ifdef CONFIG_RTL865X_MUTLICAST_DEBUG
+ printk("%s:%d,oldAsicFwdPortMask is %d,newAsicFwdPortMask is %d\n",__FUNCTION__,__LINE__,oldAsicFwdPortMask,newAsicFwdPortMask);
+ #endif
+
+#ifndef RTL8651_MCAST_ALWAYS2UPSTREAM
+ if (mCastEntry->flag & RTL865X_MULTICAST_UPLOADONLY)
+ { /* remove upload term*/
+ if((newAsicFwdPortMask!=0) && (newAsicFwdPortMask!=oldAsicFwdPortMask))
+ {
+ mCastEntry->flag &= ~RTL865X_MULTICAST_UPLOADONLY;
+ /* we assume multicast member will NEVER in External interface, so we remove
+ external ip now */
+ mCastEntry->flag &= ~RTL865X_MULTICAST_EXTIP_SET;
+ mCastEntry->extIp= 0;
+ }
+ }
+#endif /* RTL8651_MCAST_ALWAYS2UPSTREAM */
+
+ rtl_getGroupInfo(mCastEntry->dip, &groupInfo);
+ if(groupInfo.ownerMask==0)
+ {
+ mCastEntry->unKnownMCast=TRUE;
+ }
+ else
+ {
+ mCastEntry->unKnownMCast=FALSE;
+ }
+
+
+ if((oldCpuFlag != newCpuFlag)||(newAsicFwdPortMask!=oldAsicFwdPortMask))
+ {
+ _rtl865x_patchPppoeWeak(mCastEntry);
+
+ /*reset inAsic flag to re-select or re-write this hardware asic entry*/
+ if(newAsicFwdPortMask==0)
+ {
+ _rtl865x_freeMCastEntry(mCastEntry, index);
+ }
+
+ _rtl865x_arrangeMulticast(index);
+ }
+ }
+
+
+
+ }
+ }
+
+ return EVENT_CONTINUE_EXECUTE;
+}
+
+static int32 _rtl865x_multicastUnRegisterEvent(void)
+{
+ rtl865x_event_Param_t eventParam;
+
+ eventParam.eventLayerId=DEFAULT_LAYER3_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_UPDATE_MCAST;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=rtl865x_multicastCallbackFn;
+ rtl865x_unRegisterEvent(&eventParam);
+
+ return SUCCESS;
+}
+
+static int32 _rtl865x_multicastRegisterEvent(void)
+{
+ rtl865x_event_Param_t eventParam;
+
+ eventParam.eventLayerId=DEFAULT_LAYER3_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_UPDATE_MCAST;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=rtl865x_multicastCallbackFn;
+ rtl865x_registerEvent(&eventParam);
+
+ return SUCCESS;
+}
+
+
+void _rtl865x_timeUpdateMulticast(uint32 secPassed)
+{
+
+ rtl865x_tblDrv_mCast_t *mCast_t, *nextMCast_t;
+ uint32 entry;
+ uint32 needReArrange=FALSE;
+ /* check to Aging and HW swapping */
+ for (entry=0; entry< RTL8651_MULTICASTTBL_SIZE; entry++) {
+ needReArrange=FALSE;
+ mCast_t = TAILQ_FIRST(&mCastTbl.inuseList.mCastTbl[entry]);
+ while (mCast_t) {
+ /*save the next entry first*/
+ nextMCast_t=TAILQ_NEXT(mCast_t, nextMCast);
+
+ if (mCast_t->inAsic == TRUE)
+ {
+ /* Entry is in the ASIC */
+ if (mCast_t->age <= secPassed)
+ {
+ if(mCast_t->mbr==0)
+ {
+ _rtl865x_freeMCastEntry(mCast_t, entry);
+ needReArrange=TRUE;
+ }
+ else
+ {
+ mCast_t->age = RTL865X_MULTICAST_TABLE_AGE;
+ }
+ }
+ else
+ {
+ mCast_t->age -= secPassed;
+ }
+ }
+ else
+ {
+ /* Entry is not in the ASIC */
+ if(mCast_t->maxPPS<mCast_t->count)
+ {
+ mCast_t->maxPPS=mCast_t->count ;
+ }
+
+ if(mCast_t->maxPPS>0)
+ {
+ mCast_t->maxPPS--;
+ }
+
+ if (mCast_t->age <= secPassed)
+ { /* aging out */
+ _rtl865x_freeMCastEntry(mCast_t, entry);
+ }
+ else
+ {
+ mCast_t->age -= secPassed;
+ }
+ }
+
+ mCast_t->count = 0;
+ mCast_t = nextMCast_t;
+ }
+
+ if(needReArrange==TRUE)
+ {
+ _rtl865x_arrangeMulticast(entry);
+ }
+
+ }
+}
+
+#if defined(__linux__) && defined(__KERNEL__)
+static void _rtl865x_mCastSysTimerExpired(uint32 expireDada)
+{ +
+ _rtl865x_timeUpdateMulticast(1);
+ mod_timer(&rtl865x_mCastSysTimer, jiffies+HZ);
+ +} + +static void _rtl865x_initMCastSysTimer(void)
+{ +
+ init_timer(&rtl865x_mCastSysTimer);
+ rtl865x_mCastSysTimer.data=rtl865x_mCastSysTimer.expires;
+ rtl865x_mCastSysTimer.expires=jiffies+HZ;
+ rtl865x_mCastSysTimer.function=(void*)_rtl865x_mCastSysTimerExpired;
+ add_timer(&rtl865x_mCastSysTimer);
+} + +static void _rtl865x_destroyMCastSysTimer(void)
+{ + del_timer(&rtl865x_mCastSysTimer);
+} + +#endif +
+/* +@func int32 | rtl865x_initMulticast | Init hardware ip multicast module.
+@parm rtl865x_mCastConfig_t * | mCastConfigPtr | Pointer of hardware multicast configuration.
+@rvalue SUCCESS |Initialize successfully.
+@rvalue FAILED |Initialize failed.
+*/
+int32 rtl865x_initMulticast(rtl865x_mCastConfig_t * mCastConfigPtr)
+{
+ _rtl865x_multicastUnRegisterEvent();
+ _rtl865x_initMCastEntryPool();
+ _rtl865x_initMCastFwdDescPool();
+ rtl865x_setMulticastExternalPortMask(0);
+ if(mCastConfigPtr!=NULL)
+ {
+ rtl865x_setMulticastExternalPortMask(mCastConfigPtr->externalPortMask);
+ }
+ #if defined(__linux__) && defined(__KERNEL__)
+ _rtl865x_initMCastSysTimer();
+ #endif
+ rtl8651_setAsicMulticastMTU(1522);
+ rtl8651_setAsicMulticastEnable(TRUE);
+ rtl865x_setAsicMulticastAging(TRUE);
+ _rtl865x_multicastRegisterEvent();
+ return SUCCESS;
+}
+
+/* +@func int32 | rtl865x_reinitMulticast | Re-init hardware ip multicast module.
+@rvalue SUCCESS |Re-initialize successfully.
+@rvalue FAILED |Re-initialize failed.
+*/
+int32 rtl865x_reinitMulticast(void)
+{
+ _rtl865x_multicastUnRegisterEvent();
+ /*delete all multicast entry*/
+ rtl8651_setAsicMulticastEnable(FALSE);
+ rtl865x_delMulticastEntry(0);
+
+ #if defined(__linux__) && defined(__KERNEL__)
+ _rtl865x_destroyMCastSysTimer();
+ _rtl865x_initMCastSysTimer();
+ #endif
+
+ /*regfster twice won't cause any side-effect,
+ because event management module will handle duplicate event issue*/
+ rtl8651_setAsicMulticastMTU(1522);
+ rtl8651_setAsicMulticastEnable(TRUE);
+ rtl865x_setAsicMulticastAging(TRUE);
+ _rtl865x_multicastRegisterEvent();
+ return SUCCESS;
+}
+
+
+
+#ifdef CONFIG_PROC_FS
+extern int32 rtl8651_getAsicMulticastSpanningTreePortState(uint32 port, uint32 *portState);
+int32 rtl_dumpSwMulticastInfo(void)
+{
+ uint32 mCastMtu=0;
+ uint32 mCastEnable=FALSE;
+ uint32 index;
+ int8 isInternal;
+ uint32 portStatus;
+ uint32 internalPortMask=0;
+ uint32 externalPortMask=0;
+ int32 ret=FAILED;
+
+ rtl865x_tblDrv_mCast_t *mCast_t, *nextMCast_t;
+ rtl865x_mcast_fwd_descriptor_t *curDesc,*nextDesc;
+ uint32 entry;
+ uint32 cnt;
+ printk("----------------------------------------------------\n");
+ printk("Asic Operation Layer :%d\n", rtl8651_getAsicOperationLayer());
+
+ ret=rtl8651_getAsicMulticastEnable(&mCastEnable);
+ if(ret==SUCCESS)
+ {
+ printk("Asic Multicast Table:%s\n", (mCastEnable==TRUE)?"Enable":"Disable");
+ }
+ else
+ {
+ printk("Read Asic Multicast Table Enable Bit Error\n");
+ }
+
+ ret=rtl8651_getAsicMulticastMTU(&mCastMtu);
+ if(ret==SUCCESS)
+ {
+ printk("Asic Multicast MTU:%d\n", mCastMtu);
+ }
+ else
+ {
+ printk("Read Asic Multicast MTU Error\n");
+ }
+
+ for (index=0; index<RTL8651_PORT_NUMBER+rtl8651_totalExtPortNum; index++)
+ {
+ ret=rtl8651_getAsicMulticastPortInternal(index, &isInternal);
+ if(ret==SUCCESS)
+ {
+ if(isInternal==TRUE)
+ {
+ internalPortMask |= 1<<index;
+ }
+ else
+ {
+ externalPortMask |= 1<<index;
+ }
+ }
+
+ }
+
+ printk("Internal Port Mask:0x%x\nExternal Port Mask:0x%x\n", internalPortMask,externalPortMask);
+ printk("----------------------------------------------------\n");
+ printk("Multicast STP State:\n");
+ for (index=0; index<RTL8651_PORT_NUMBER+rtl8651_totalExtPortNum; index++)
+ {
+ ret= rtl8651_getAsicMulticastSpanningTreePortState(index, &portStatus);
+ if(ret==SUCCESS)
+ {
+ printk("port[%d]:",index);
+ if(portStatus==RTL8651_PORTSTA_DISABLED)
+ {
+ printk("disabled\n");
+ }
+ else if(portStatus==RTL8651_PORTSTA_BLOCKING)
+ {
+ printk("blocking\n");
+ }
+ else if(portStatus==RTL8651_PORTSTA_LEARNING)
+ {
+ printk("learning\n");
+ }
+ else if(portStatus==RTL8651_PORTSTA_FORWARDING)
+ {
+ printk("forwarding\n");
+ }
+ }
+
+ }
+ printk("----------------------------------------------------\n");
+ printk("Software Multicast Table:\n");
+ /* check to Aging and HW swapping */
+ for (entry=0; entry< RTL8651_MULTICASTTBL_SIZE; entry++) {
+ mCast_t = TAILQ_FIRST(&mCastTbl.inuseList.mCastTbl[entry]);
+ while (mCast_t) {
+ /*save the next entry first*/
+ nextMCast_t=TAILQ_NEXT(mCast_t, nextMCast);
+ printk("\t[%2d] dip:%d.%d.%d.%d, sip:%d.%d.%d.%d, mbr:0x%x, svid:%d, spa:%d, \n", entry,
+ mCast_t->dip>>24, (mCast_t->dip&0x00ff0000)>>16, (mCast_t->dip&0x0000ff00)>>8, (mCast_t->dip&0xff),
+ mCast_t->sip>>24, (mCast_t->sip&0x00ff0000)>>16, (mCast_t->sip&0x0000ff00)>>8, (mCast_t->sip&0xff),
+ mCast_t->mbr,mCast_t->svid, mCast_t->port);
+ printk("\t extIP:0x%x,age:%d, cpu:%d, maxPPS:%d, inAsic:%d, (%s)\n",
+ mCast_t->extIp,mCast_t->age, mCast_t->cpu,mCast_t->maxPPS,mCast_t->inAsic,mCast_t->unKnownMCast?"UnknownMCast":"KnownMCast");
+
+ cnt=0;
+ curDesc=MC_LIST_FIRST(&mCast_t->fwdDescChain);
+ while(curDesc)
+ {
+ nextDesc=MC_LIST_NEXT(curDesc, next );
+ printk("\t netif(%s),descPortMask(0x%x),toCpu(%d),fwdPortMask(0x%x)\n",curDesc->netifName,curDesc->descPortMask,curDesc->toCpu,curDesc->fwdPortMask);
+ curDesc = nextDesc;
+ }
+
+ printk("\n");
+ mCast_t = nextMCast_t;
+ }
+
+ }
+
+ return SUCCESS;
+}
+#endif +
+int rtl865x_genVirtualMCastFwdDescriptor(unsigned int forceToCpu, uint32 fwdPortMask, rtl865x_mcast_fwd_descriptor_t *fwdDescriptor) +{ + + if(fwdDescriptor==NULL) + { + return FAILED; + } + + memset(fwdDescriptor, 0, sizeof(rtl865x_mcast_fwd_descriptor_t )); + fwdDescriptor->toCpu=forceToCpu; + fwdDescriptor->fwdPortMask=fwdPortMask; + return SUCCESS; + +}
+
+int rtl865x_blockMulticastFlow(unsigned int srcVlanId, unsigned int srcPort,unsigned int srcIpAddr, unsigned int destIpAddr)
+{
+ rtl865x_mcast_fwd_descriptor_t fwdDescriptor;
+ rtl865x_tblDrv_mCast_t * existMCastEntry=NULL;
+ existMCastEntry=rtl865x_findMCastEntry(destIpAddr, srcIpAddr, (uint16)srcVlanId, (uint16)srcPort);
+ if(existMCastEntry!=NULL)
+ {
+ if(existMCastEntry->mbr==0)
+ {
+ return SUCCESS;
+ }
+ }
+ memset(&fwdDescriptor, 0, sizeof(rtl865x_mcast_fwd_descriptor_t ));
+ rtl865x_addMulticastEntry(destIpAddr, srcIpAddr, (unsigned short)srcVlanId, (unsigned short)srcPort, &fwdDescriptor, TRUE, 0, 0, 0);
+ return SUCCESS;
+}
+
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_multipleWan.c b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_multipleWan.c new file mode 100644 index 000000000..d10e3d845 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_multipleWan.c @@ -0,0 +1,800 @@ +/* +* Copyright c Realtek Semiconductor Corporation, 2010 +* All rights reserved. +* +* Program : multiple wan +* Abstract : +* Author : hyking (hyking_liu@realsil.com.cn) +*/ + +/* @doc RTL_LAYEREDDRV_API + + @module rtl865x_multipleWan.c - RTL865x Home gateway controller Layered driver API documentation | + This document explains the API interface of the table driver module. Functions with rtl865x prefix + are external functions. + @normal Hyking Liu (Hyking_liu@realsil.com.cn) <date> + + Copyright <cp>2010 Realtek<tm> Semiconductor Cooperation, All Rights Reserved. + + @head3 List of Symbols | + Here is a list of all functions and variables in this module. + + @index | RTL_LAYEREDDRV_API +*/ +#include <linux/proc_fs.h> +//#include <linux/seq_file.h> + + +#include <net/rtl/rtl_types.h> +#include <net/rtl/rtl_glue.h> +#include "common/rtl_errno.h" +#include <net/rtl/rtl865x_netif.h> +#include "common/rtl865x_netif_local.h" +#include "rtl865x_ppp_local.h" +#include "rtl865x_route.h" +#include "rtl865x_nexthop.h" +#include <net/rtl/rtl865x_arp_api.h> +#include "rtl865x_arp.h" + +#include <net/rtl/rtl865x_multipleWan_api.h> +#include "rtl865x_multipleWan.h" + +#include "AsicDriver/rtl865x_asicCom.h" +#include "AsicDriver/asicRegs.h" +#include "AsicDriver/rtl865x_asicBasic.h" + + + +static rtl_advRoute_entry_t rtl_advRt_table[RTL_ADVRT_MAX_NUM]; +static enum ENUM_NETDEC_POLICY oldNetDecision; +static struct proc_dir_entry *adv_rt_entry; +extern int32 rtl865x_getAsicFun(uint32 *enable); + +static void rtl_show_advRoute(rtl_advRoute_entry_t *rule) +{ + switch(rule->ruleType_) + { + case RTL_ADVRT_MAC: + printk("rule type: %s\n", "MAC based"); + printk("\tether type: %x ether type mask: %x\n", rule->advrt_typeLen_, rule->advrt_typeLenMask_); + printk("\tDMAC: %x:%x:%x:%x:%x:%x DMACM: %x:%x:%x:%x:%x:%x\n", + rule->advrt_dstMac_.octet[0], rule->advrt_dstMac_.octet[1], rule->advrt_dstMac_.octet[2], + rule->advrt_dstMac_.octet[3], rule->advrt_dstMac_.octet[4], rule->advrt_dstMac_.octet[5], + rule->advrt_dstMacMask_.octet[0], rule->advrt_dstMacMask_.octet[1], rule->advrt_dstMacMask_.octet[2], + rule->advrt_dstMacMask_.octet[3], rule->advrt_dstMacMask_.octet[4], rule->advrt_dstMacMask_.octet[5] + ); + + printk( "\tSMAC: %x:%x:%x:%x:%x:%x SMACM: %x:%x:%x:%x:%x:%x\n", + rule->advrt_srcMac_.octet[0], rule->advrt_srcMac_.octet[1], rule->advrt_srcMac_.octet[2], + rule->advrt_srcMac_.octet[3], rule->advrt_srcMac_.octet[4], rule->advrt_srcMac_.octet[5], + rule->advrt_srcMacMask_.octet[0], rule->advrt_srcMacMask_.octet[1], rule->advrt_srcMacMask_.octet[2], + rule->advrt_srcMacMask_.octet[3], rule->advrt_srcMacMask_.octet[4], rule->advrt_srcMacMask_.octet[5] + ); + break; + + case RTL_ADVRT_IP: + printk("rule type: %s\n", "IP"); + printk( "\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x ipProto: %x ipProtoM: %x ipFlag: %x ipFlagM: %x\n", + rule->advrt_tos_, rule->advrt_tosMask_, rule->advrt_ipProto_, rule->advrt_ipProtoMask_, rule->advrt_ipFlag_, rule->advrt_ipFlagMask_ + ); + + printk("\t<FOP:%x> <FOM:%x> <http:%x> <httpM:%x> <IdentSdip:%x> <IdentSdipM:%x> \n", + rule->advrt_ipFOP_, rule->advrt_ipFOM_, rule->advrt_ipHttpFilter_, rule->advrt_ipHttpFilterM_, rule->advrt_ipIdentSrcDstIp_, + rule->advrt_ipIdentSrcDstIpM_ + ); + printk( "\t<DF:%x> <MF:%x>\n", rule->advrt_ipDF_, rule->advrt_ipMF_); + break; + + case RTL_ADVRT_IP_RANGE: + printk("rule type: %s \n", "IP Range"); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x ipProto: %x ipProtoM: %x ipFlag: %x ipFlagM: %x\n", + rule->advrt_tos_, rule->advrt_tosMask_, rule->advrt_ipProto_, rule->advrt_ipProtoMask_, rule->advrt_ipFlag_, rule->advrt_ipFlagMask_ + ); + printk("\t<FOP:%x> <FOM:%x> <http:%x> <httpM:%x> <IdentSdip:%x> <IdentSdipM:%x> \n", + rule->advrt_ipFOP_, rule->advrt_ipFOM_, rule->advrt_ipHttpFilter_, rule->advrt_ipHttpFilterM_, rule->advrt_ipIdentSrcDstIp_, + rule->advrt_ipIdentSrcDstIpM_ + ); + printk("\t<DF:%x> <MF:%x>\n", rule->advrt_ipDF_, rule->advrt_ipMF_); + break; + case RTL_ADVRT_ICMP: + printk("rule type: %s\n", "ICMP"); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x type: %x typeM: %x code: %x codeM: %x\n", + rule->advrt_tos_, rule->advrt_tosMask_, rule->advrt_icmpType_, rule->advrt_icmpTypeMask_, + rule->advrt_icmpCode_, rule->advrt_icmpCodeMask_); + break; + case RTL_ADVRT_ICMP_IPRANGE: + printk("rule type: %s\n","ICMP IP RANGE"); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x type: %x typeM: %x code: %x codeM: %x\n", + rule->advrt_tos_, rule->advrt_tosMask_, rule->advrt_icmpType_, rule->advrt_icmpTypeMask_, + rule->advrt_icmpCode_, rule->advrt_icmpCodeMask_); + break; + case RTL_ADVRT_IGMP: + printk("rule type: %s\n", "IGMP"); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x type: %x typeM: %x\n", rule->advrt_tos_, rule->advrt_tosMask_, + rule->advrt_igmpType_, rule->advrt_igmpTypeMask_ + ); + break; + + + case RTL_ADVRT_IGMP_IPRANGE: + printk(" rule type: %s\n", "IGMP IP RANGE"); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x type: %x typeM: %x\n", rule->advrt_tos_, rule->advrt_tosMask_, + rule->advrt_igmpType_, rule->advrt_igmpTypeMask_ + ); + break; + + case RTL_ADVRT_TCP: + printk("rule type: %s\n","TCP"); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos:%x TosM:%x sportL:%d sportU:%d dportL:%d dportU:%d\n", + rule->advrt_tos_, rule->advrt_tosMask_, rule->advrt_tcpSrcPortLB_, rule->advrt_tcpSrcPortUB_, + rule->advrt_tcpDstPortLB_, rule->advrt_tcpDstPortUB_ + ); + printk("\tflag: %x flagM: %x <URG:%x> <ACK:%x> <PSH:%x> <RST:%x> <SYN:%x> <FIN:%x>\n", + rule->advrt_tcpFlag_, rule->advrt_tcpFlagMask_, rule->advrt_tcpURG_, rule->advrt_tcpACK_, + rule->advrt_tcpPSH_, rule->advrt_tcpRST_, rule->advrt_tcpSYN_, rule->advrt_tcpFIN_ + ); + break; + case RTL_ADVRT_TCP_IPRANGE: + printk("rule type: %s\n","TCP IP RANGE"); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos:%x TosM:%x sportL:%d sportU:%d dportL:%d dportU:%d\n", + rule->advrt_tos_, rule->advrt_tosMask_, rule->advrt_tcpSrcPortLB_, rule->advrt_tcpSrcPortUB_, + rule->advrt_tcpDstPortLB_, rule->advrt_tcpDstPortUB_ + ); + printk("\tflag: %x flagM: %x <URG:%x> <ACK:%x> <PSH:%x> <RST:%x> <SYN:%x> <FIN:%x>\n", + rule->advrt_tcpFlag_, rule->advrt_tcpFlagMask_, rule->advrt_tcpURG_, rule->advrt_tcpACK_, + rule->advrt_tcpPSH_, rule->advrt_tcpRST_, rule->advrt_tcpSYN_, rule->advrt_tcpFIN_ + ); + break; + + case RTL_ADVRT_UDP: + printk("rule type: %s\n","UDP"); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos:%x TosM:%x sportL:%d sportU:%d dportL:%d dportU:%d\n", + rule->advrt_tos_, rule->advrt_tosMask_, rule->advrt_udpSrcPortLB_, rule->advrt_udpSrcPortUB_, + rule->advrt_udpDstPortLB_, rule->advrt_udpDstPortUB_ + ); + break; + case RTL_ADVRT_UDP_IPRANGE: + printk("rule type: %s\n","UDP IP RANGE"); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->advrt_dstIpAddr_>>24), + ((rule->advrt_dstIpAddr_&0x00ff0000)>>16), ((rule->advrt_dstIpAddr_&0x0000ff00)>>8), + (rule->advrt_dstIpAddr_&0xff), (rule->advrt_dstIpAddrMask_>>24), ((rule->advrt_dstIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_dstIpAddrMask_&0x0000ff00)>>8), (rule->advrt_dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->advrt_srcIpAddr_>>24), + ((rule->advrt_srcIpAddr_&0x00ff0000)>>16), ((rule->advrt_srcIpAddr_&0x0000ff00)>>8), + (rule->advrt_srcIpAddr_&0xff), (rule->advrt_srcIpAddrMask_>>24), ((rule->advrt_srcIpAddrMask_&0x00ff0000)>>16), + ((rule->advrt_srcIpAddrMask_&0x0000ff00)>>8), (rule->advrt_srcIpAddrMask_&0xff) + ); + printk("\tTos:%x TosM:%x sportL:%d sportU:%d dportL:%d dportU:%d\n", + rule->advrt_tos_, rule->advrt_tosMask_, rule->advrt_udpSrcPortLB_, rule->advrt_udpSrcPortUB_, + rule->advrt_udpDstPortLB_, rule->advrt_udpDstPortUB_ + ); + break; + + default: + printk("rule->ruleType_(0x%x)\n", rule->ruleType_); + + } + + printk("\tNexthop(%u.%u.%u.%u),extip(%u.%u.%u.%u),outif(%s),Op(%d)\n", NIPQUAD(rule->nexthop),NIPQUAD(rule->extIp),rule->outIfName,rule->pktOpApp_); + +} +void rtl_show_advRt_table(void) +{ + rtl_advRoute_entry_t *tmp_entry; + int i; + + for(i = 0; i < RTL_ADVRT_MAX_NUM; i++) + { + tmp_entry = &rtl_advRt_table[i]; + if(tmp_entry->valid_) + { + printk("idx(%d):\n",i); + rtl_show_advRoute(tmp_entry); + } + + } +} + +static int8 _rtl_same_AdvRt_rule(rtl_advRoute_entry_t *rule1, rtl_advRoute_entry_t *rule2) +{ + + if (rule1->ruleType_ != rule2->ruleType_) + return FALSE; + + switch(rule1->ruleType_) + { + case RTL_ADVRT_MAC: + if (rule1->advrt_typeLen_ != rule2->advrt_typeLen_ || rule1->advrt_typeLenMask_ != rule2->advrt_typeLenMask_) + return FALSE; + if (memcmp(&rule1->advrt_dstMac_, &rule2->advrt_dstMac_, sizeof(ether_addr_t)) || + memcmp(&rule1->advrt_dstMacMask_, &rule2->advrt_dstMacMask_, sizeof(ether_addr_t)) || + memcmp(&rule1->advrt_srcMac_, &rule2->advrt_srcMac_, sizeof(ether_addr_t)) || + memcmp(&rule1->advrt_srcMacMask_, &rule2->advrt_srcMacMask_, sizeof(ether_addr_t)) ) + return FALSE; + return TRUE; + case RTL_ADVRT_IP: + case RTL_ADVRT_IP_RANGE: + if (rule1->advrt_ipProto_ != rule2->advrt_ipProto_ || rule1->advrt_ipProtoMask_ != rule2->advrt_ipProtoMask_ || + rule1->advrt_ipFlag_ != rule2->advrt_ipFlag_ || rule1->advrt_ipFlagMask_ != rule2->advrt_ipFlagMask_) + return FALSE; + break; + + case RTL_ADVRT_ICMP: + case RTL_ADVRT_ICMP_IPRANGE: + if (rule1->advrt_icmpType_ != rule2->advrt_icmpType_ || rule1->advrt_icmpTypeMask_ != rule2->advrt_icmpTypeMask_ || + rule1->advrt_icmpCode_ != rule2->advrt_icmpCode_ || rule1->advrt_icmpCodeMask_ != rule2->advrt_icmpCodeMask_) + return FALSE; + break; + + case RTL_ADVRT_IGMP: + case RTL_ADVRT_IGMP_IPRANGE: + if(rule1->advrt_igmpType_ != rule2->advrt_igmpType_ || rule1->advrt_igmpTypeMask_ != rule2->advrt_igmpTypeMask_) + return FALSE; + break; + case RTL_ADVRT_TCP: + case RTL_ADVRT_TCP_IPRANGE: + if(rule1->advrt_tcpFlag_ != rule2->advrt_tcpFlag_ || rule1->advrt_tcpFlagMask_ != rule2->advrt_tcpFlagMask_ || + rule1->advrt_tcpSrcPortUB_ != rule2->advrt_tcpSrcPortUB_ || rule1->advrt_tcpSrcPortLB_ != rule2->advrt_tcpSrcPortLB_ || + rule1->advrt_tcpDstPortUB_ != rule2->advrt_tcpDstPortUB_ || rule1->advrt_tcpDstPortLB_ != rule2->advrt_tcpDstPortLB_) + return FALSE; + break; + case RTL_ADVRT_UDP: + case RTL_ADVRT_UDP_IPRANGE: + if(rule1->advrt_udpSrcPortUB_ != rule2->advrt_udpSrcPortUB_ || rule1->advrt_udpSrcPortLB_ != rule2->advrt_udpSrcPortLB_ || + rule1->advrt_udpDstPortUB_ != rule2->advrt_udpDstPortUB_ || rule1->advrt_udpDstPortLB_ != rule2->advrt_udpDstPortLB_) + return FALSE; + break; + + case RTL_ADVRT_SRCFILTER: + case RTL_ADVRT_SRCFILTER_IPRANGE: + if((rule1->advrt_srcFilterPort_ != rule2->advrt_srcFilterPort_)|| + memcmp(&rule1->advrt_srcFilterMac_, &rule2->advrt_srcFilterMac_, sizeof(ether_addr_t)) != 0|| + memcmp(&rule1->advrt_srcFilterMacMask_, &rule2->advrt_srcFilterMacMask_,sizeof(ether_addr_t)) != 0|| + (rule1->advrt_srcFilterVlanIdx_ != rule2->advrt_srcFilterVlanIdx_)|| + (rule1->advrt_srcFilterVlanIdxMask_ != rule2->advrt_srcFilterVlanIdxMask_)|| + (rule1->advrt_srcFilterIgnoreL3L4_ != rule2->advrt_srcFilterIgnoreL3L4_)|| + (rule1->advrt_srcFilterIgnoreL4_ != rule2->advrt_srcFilterIgnoreL4_)) + { + return FALSE; + } + + if(rule1->advrt_srcFilterIgnoreL4_==0 && rule1->advrt_srcFilterIgnoreL3L4_==0) + { + if((rule1->advrt_srcFilterPortUpperBound_ != rule2->advrt_srcFilterPortUpperBound_)|| + (rule1->advrt_srcFilterPortLowerBound_ != rule2->advrt_srcFilterPortLowerBound_)) + return FALSE; + } + + if(rule1->advrt_srcFilterIgnoreL3L4_==0) + { + if((rule1->advrt_srcFilterIpAddr_ != rule2->advrt_srcFilterIpAddr_)|| + (rule2->advrt_srcFilterIpAddrMask_ != rule2->advrt_srcFilterIpAddrMask_)) + return FALSE; + } + + break; + + case RTL_ADVRT_DSTFILTER: + case RTL_ADVRT_DSTFILTER_IPRANGE: + if( memcmp(&rule1->advrt_dstFilterMac_, &rule2->advrt_dstFilterMac_, sizeof(ether_addr_t)) != 0|| + memcmp(&rule1->advrt_dstFilterMacMask_, &rule2->advrt_dstFilterMacMask_,sizeof(ether_addr_t)) != 0|| + (rule1->advrt_dstFilterVlanIdx_ != rule2->advrt_dstFilterVlanIdx_)|| + (rule1->advrt_dstFilterVlanIdxMask_ != rule2->advrt_dstFilterVlanIdxMask_)|| + (rule1->advrt_dstFilterIgnoreL3L4_ != rule2->advrt_dstFilterIgnoreL3L4_)|| + (rule1->advrt_dstFilterIgnoreL4_ != rule2->advrt_dstFilterIgnoreL4_)) + { + return FALSE; + } + + if(rule1->advrt_dstFilterIgnoreL4_==0 && rule1->advrt_dstFilterIgnoreL4_==0) + { + if((rule1->advrt_dstFilterPortUpperBound_ != rule2->advrt_dstFilterPortUpperBound_)|| + (rule1->advrt_dstFilterPortLowerBound_ != rule2->advrt_dstFilterPortLowerBound_)) + return FALSE; + } + + if(rule1->advrt_dstFilterIgnoreL3L4_==0) + { + if((rule1->advrt_dstFilterIpAddr_ != rule2->advrt_dstFilterIpAddr_)|| + (rule2->advrt_dstFilterIpAddrMask_ != rule2->advrt_dstFilterIpAddrMask_)) + return FALSE; + } + + break; + default: return FALSE; /* Unknown rule type */ + + } + /* Compare common part */ + if (rule1->advrt_srcIpAddr_ != rule2->advrt_srcIpAddr_ || rule1->advrt_srcIpAddrMask_ != rule2->advrt_srcIpAddrMask_ || + rule1->advrt_dstIpAddr_ != rule2->advrt_dstIpAddr_ || rule1->advrt_dstIpAddrMask_ != rule2->advrt_dstIpAddrMask_ || + rule1->advrt_tos_ != rule2->advrt_tos_ || rule1->advrt_tosMask_ != rule2->advrt_tosMask_ ) + return FALSE; + return TRUE; +} + +static int _rtl_advRt_to_acl(rtl_advRoute_entry_t *advRt, rtl865x_AclRule_t *acl) +{ + if(NULL == advRt || NULL == acl) + return RTL_EINVALIDINPUT; + + switch(advRt->ruleType_) + { + case RTL_ADVRT_IP: + case RTL_ADVRT_IP_RANGE: + memcpy(&acl->un_ty,&advRt->un_ty,sizeof(advRt->un_ty)); + acl->pktOpApp_ = advRt->pktOpApp_; + + if(advRt->ruleType_ == RTL_ADVRT_IP) + acl->ruleType_ = RTL865X_ACL_IP; + else + acl->ruleType_ = RTL865X_ACL_IP_RANGE; + + break; + default: + printk("ruletype(0x%x) is NOT support now!\n",advRt->ruleType_); + } + + return SUCCESS; +} + +static int _rtl_advRt_fullMatch_with_route(rtl_advRoute_entry_t *entry) +{ + int retval = FAILED; + rtl865x_netif_local_t *dstNetif; + rtl865x_route_t rt; + + memset(&rt,0,sizeof(rtl865x_route_t)); + + retval = rtl865x_getRouteEntry(entry->nexthop,&rt); + if(SUCCESS == retval) + { + dstNetif = _rtl865x_getNetifByName(entry->outIfName); + if(rt.dstNetif == dstNetif) + return SUCCESS; + } + + return FAILED; +} + +static int _rtl_flush_multiWan_redirectACL(void) +{ + rtl_advRoute_entry_t *entry; + rtl865x_netif_local_t *netif; + int nexthopIdx; + int i; + + /*delete nexthop entry which used for redirectacl*/ + for(i = 0; i < RTL_ADVRT_MAX_NUM; i++) + { + entry = &rtl_advRt_table[i]; + if(entry->valid_) + { + if(SUCCESS == _rtl_advRt_fullMatch_with_route(entry)) + continue; + + netif = _rtl865x_getSWNetifByName(entry->outIfName); + if(NULL == netif) + { + printk("====%s(%d),netif(%s) is NULL\n",__FUNCTION__,__LINE__,entry->outIfName); + continue; + } + + nexthopIdx = rtl865x_getNxtHopIdx(NEXTHOP_DEFREDIRECT_ACL,netif,entry->nexthop); + if(nexthopIdx == -1) + { + printk("====%s(%d),get nxthop error, nxthop(%u.%u.%u.%u)!!\n",__FUNCTION__,__LINE__,NIPQUAD(entry->nexthop)); + continue; + } + + rtl865x_delNxtHop(NEXTHOP_DEFREDIRECT_ACL,nexthopIdx); + } + } + + /*delete all acl rule*/ + rtl865x_flush_allAcl_fromChain(RTL_DRV_LAN_NETIF_NAME,RTL865X_ACL_MULTIWAN_USED,RTL865X_ACL_INGRESS); + + return SUCCESS; +} + +static int _rtl_rearrange_multiWan_redirectACL(void) +{ + rtl865x_AclRule_t acl_entry; + rtl_advRoute_entry_t *entry; + rtl865x_netif_local_t *netif; + int nexthopIdx; + int i,ret; + rtl865x_arpMapping_entry_t arp; + + for(i = 0; i < RTL_ADVRT_MAX_NUM; i++) + { + entry = &rtl_advRt_table[i]; + if(entry->valid_) + { + if(SUCCESS == _rtl_advRt_fullMatch_with_route(entry)) + continue; + + netif = _rtl865x_getSWNetifByName(entry->outIfName); + if(NULL == netif) + { + printk("====%s(%d),netif(%s) is NULL\n",__FUNCTION__,__LINE__,entry->outIfName); + continue; + } + + /*add nexthop entry*/ + rtl865x_addNxtHop(NEXTHOP_DEFREDIRECT_ACL,NULL,netif,entry->nexthop,entry->extIp); + nexthopIdx = rtl865x_getNxtHopIdx(NEXTHOP_DEFREDIRECT_ACL,netif,entry->nexthop); + if(nexthopIdx == -1) + { + printk("====%s(%d),get nxthop error, nxthop(%u.%u.%u.%u)!!\n",__FUNCTION__,__LINE__,NIPQUAD(entry->nexthop)); + continue; + } + + //add acl + memset(&acl_entry,0,sizeof(rtl865x_AclRule_t)); + _rtl_advRt_to_acl(entry,&acl_entry); + + acl_entry.actionType_ = RTL865X_ACL_DEFAULT_REDIRECT; + acl_entry.nexthopIdx_ = nexthopIdx; + + ret = rtl865x_add_acl(&acl_entry,RTL_DRV_LAN_NETIF_NAME,RTL865X_ACL_MULTIWAN_USED); + if(SUCCESS != ret) + { + rtl865x_delNxtHop(NEXTHOP_DEFREDIRECT_ACL,nexthopIdx); + continue; + } + + /*callback function for sync arp/l2*/ + memset(&arp,0,sizeof(rtl865x_arpMapping_entry_t)); + ret = rtl865x_get_ps_arpMapping(entry->nexthop,&arp); + if(SUCCESS == ret) + { + rtl865x_eventHandle_addArp_for_multiWan(&arp); + } + + + } + } + + return SUCCESS; +} + +#if 0 +static int _rtl_get_advRt_num(void) +{ + int cnt = 0; + int i = 0; + for(i = 0; i < RTL_ADVRT_MAX_NUM; i++) + { + if(rtl_advRt_table[i].valid_) + { + cnt++; + } + } + + return cnt; +} +#endif + +static int32 adv_rt_read( char *page, char **start, off_t off, int count, int *eof, void *data ) +{ + int len = 0; + rtl_show_advRt_table(); + return len; +} + +static int32 adv_rt_write( struct file *filp, const char *buff,unsigned long len, void *data ) +{ + char tmpbuf[128]; + char cmd[8]; + char outif_name[16]; + char netif_name[MAX_IFNAMESIZE]; + int srcip_start[4]; + int srcip_end[4]; + int dst_start[4]; + int dst_end[4]; + int ext_ip[4]; + int nexthop_ip[4]; + int num = 0; + int retval = 0; + rtl_advRoute_entry_t rule; + + if (buff && !copy_from_user(tmpbuf, buff, len)) + { + tmpbuf[len -1] = '\0'; + num= sscanf(tmpbuf, "%s %d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d %s", cmd, + &srcip_start[0], &srcip_start[1], &srcip_start[2], &srcip_start[3], + &srcip_end[0], &srcip_end[1], &srcip_end[2], &srcip_end[3], + &dst_start[0], &dst_start[1], &dst_start[2], &dst_start[3], + &dst_end[0], &dst_end[1], &dst_end[2], &dst_end[3], + &ext_ip[0], &ext_ip[1], &ext_ip[2], &ext_ip[3], + &nexthop_ip[0], &nexthop_ip[1], &nexthop_ip[2], &nexthop_ip[3], + outif_name); + + if (num != 26) + return -EFAULT; + + if(strlen(outif_name) >= 15) + return -EFAULT; + + + retval = rtl865x_get_drvNetifName_by_psName(outif_name,netif_name); + if(retval != SUCCESS) + return -EFAULT; + + memset(&rule,0,sizeof(rtl_advRoute_entry_t)); + rule.extIp = (ext_ip[0]<<24)|(ext_ip[1]<<16)|(ext_ip[2]<<8)|(ext_ip[3]<<0); + rule.nexthop = (nexthop_ip[0]<<24)|(nexthop_ip[1]<<16)|(nexthop_ip[2]<<8)|(nexthop_ip[3]<<0); + rule.pktOpApp_ = 6; + memcpy(rule.outIfName,netif_name,strlen(netif_name)); + rule.outIfName[strlen(netif_name)+1] ='\0'; + + rule.ruleType_ = RTL_ADVRT_IP_RANGE; + rule.valid_ = 1; + + rule.advrt_srcIpAddrStart_ = (srcip_start[0]<<24)|(srcip_start[1]<<16)|(srcip_start[2]<<8)|(srcip_start[3]<<0); + rule.advrt_srcIpAddrEnd_ = (srcip_end[0]<<24)|(srcip_end[1]<<16)|(srcip_end[2]<<8)|(srcip_end[3]<<0); + rule.advrt_dstIpAddrStart_ = (dst_start[0]<<24)|(dst_start[1]<<16)|(dst_start[2]<<8)|(dst_start[3]<<0); + rule.advrt_dstIpAddrEnd_ = (dst_end[0]<<24)|(dst_end[1]<<16)|(dst_end[2]<<8)|(dst_end[3]<<0); + + + if((strcmp(cmd, "add")==0) || (strcmp(cmd, "ADD")==0)) + { + rtl_add_advRt_entry(&rule); + } + else if((strcmp(cmd, "del")==0) || (strcmp(cmd, "DEL")==0)) + { + rtl_del_advRt_entry(&rule); + } + + } + return len; +} + +int rtl_exit_advRt(void) +{ + _rtl_flush_multiWan_redirectACL(); + /*unregist the acl chain*/ + rtl865x_unRegist_aclChain(RTL_DRV_LAN_NETIF_NAME,RTL865X_ACL_MULTIWAN_USED,RTL865X_ACL_INGRESS); + memset(rtl_advRt_table,0,RTL_ADVRT_MAX_NUM*sizeof(rtl_advRoute_entry_t)); + /*switch back old netdecision policy*/ + rtl865xC_setNetDecisionPolicy(oldNetDecision); + if(adv_rt_entry) + { + remove_proc_entry("adv_rt",NULL); + adv_rt_entry = NULL; + } + return SUCCESS; +} + +int rtl_init_advRt(void) +{ +#if 1 + uint32 enable; + rtl865x_getAsicFun(&enable); + + if(!(enable & ALL_NAT)) + return FAILED; +#endif + + adv_rt_entry = create_proc_entry("adv_rt", 0, NULL); + if(adv_rt_entry) + { + adv_rt_entry->read_proc = adv_rt_read; + adv_rt_entry->write_proc = adv_rt_write; + + } + memset(rtl_advRt_table,0,RTL_ADVRT_MAX_NUM*sizeof(rtl_advRoute_entry_t)); + rtl865x_regist_aclChain(RTL_DRV_LAN_NETIF_NAME,RTL865X_ACL_MULTIWAN_USED,RTL865X_ACL_INGRESS); + //switch to mac based + rtl865xC_getNetDecisionPolicy(&oldNetDecision); + rtl865xC_setNetDecisionPolicy(NETIF_MAC_BASED ); + rtl865x_setDefACLForNetDecisionMiss(RTL865X_ACLTBL_PERMIT_ALL,RTL865X_ACLTBL_PERMIT_ALL,RTL865X_ACLTBL_PERMIT_ALL,RTL865X_ACLTBL_PERMIT_ALL); + return SUCCESS; +} + +rtl_advRoute_entry_t* rtl_get_advRt_entry_by_nexthop(ipaddr_t nexthop) +{ + int i; + rtl_advRoute_entry_t *tmp_entry; + for(i = 0; i < RTL_ADVRT_MAX_NUM; i++) + { + tmp_entry = &rtl_advRt_table[i]; + if(tmp_entry->valid_) + { + if(tmp_entry->nexthop == nexthop) + return tmp_entry; + } + } + return NULL; +} + +int rtl_add_advRt_entry(rtl_advRoute_entry_t *entry) +{ + int i; + rtl_advRoute_entry_t *tmp_entry,*ready_entry; + if(NULL == entry) + return RTL_EINVALIDINPUT; + + ready_entry = NULL; + + /*duplicate check & try to find a usable entry*/ + for(i = 0; i < RTL_ADVRT_MAX_NUM; i++) + { + tmp_entry = &rtl_advRt_table[i]; + if(tmp_entry->valid_) + { + if(_rtl_same_AdvRt_rule(entry,tmp_entry)) + return RTL_EENTRYALREADYEXIST; + } + else + { + if(NULL==ready_entry) + ready_entry = &rtl_advRt_table[i]; + } + } + + if(NULL == ready_entry) + return RTL_ENOFREEBUFFER; + + /*flush acl firstly*/ + _rtl_flush_multiWan_redirectACL(); + + /*add entry*/ + memcpy(ready_entry,entry,sizeof(rtl_advRoute_entry_t)); + ready_entry->valid_ = 1; + + _rtl_rearrange_multiWan_redirectACL(); + + return SUCCESS; +} + +int rtl_del_advRt_entry(rtl_advRoute_entry_t *entry) +{ + int i; + rtl_advRoute_entry_t *tmp_entry; + if(NULL == entry) + return RTL_EINVALIDINPUT; + + for(i = 0; i < RTL_ADVRT_MAX_NUM; i++) + { + tmp_entry = &rtl_advRt_table[i]; + if(tmp_entry->valid_) + { + if(_rtl_same_AdvRt_rule(entry,tmp_entry)) + break; + } + } + + if(RTL_ADVRT_MAX_NUM == i) + return RTL_EENTRYNOTFOUND; + + /*flush acl firstly*/ + _rtl_flush_multiWan_redirectACL(); + + /*delete entry*/ + memset(tmp_entry,0,sizeof(rtl_advRoute_entry_t)); + + /*rearrange for redirect acl*/ + _rtl_rearrange_multiWan_redirectACL(); + return SUCCESS; +} + +int rtl_enable_advRt_by_netifName(const char *name) +{ + int i; + _rtl_flush_multiWan_redirectACL(); + for(i = 0;i < RTL_ADVRT_MAX_NUM;i++) + { + if(strcmp(rtl_advRt_table[i].outIfName,name) == 0) + rtl_advRt_table[i].valid_ = 1; + } + _rtl_rearrange_multiWan_redirectACL(); + + return SUCCESS; +} +int rtl_disable_advRt_by_netifName(const char *name) +{ + int i; + _rtl_flush_multiWan_redirectACL(); + for(i = 0;i < RTL_ADVRT_MAX_NUM;i++) + { + if(strcmp(rtl_advRt_table[i].outIfName,name) == 0) + rtl_advRt_table[i].valid_ = 0; + } + _rtl_rearrange_multiWan_redirectACL(); + + return SUCCESS; +} + + diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_nexthop.c b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_nexthop.c new file mode 100644 index 000000000..e3f67cbfe --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_nexthop.c @@ -0,0 +1,739 @@ +/*
+* Copyright c Realtek Semiconductor Corporation, 2008
+* All rights reserved.
+*
+* Program : nexthop table driver
+* Abstract :
+* Author : hyking (hyking_liu@realsil.com.cn)
+*/
+
+/* @doc RTL_LAYEREDDRV_API
+
+ @module rtl865x_nexthop.c - RTL865x Home gateway controller Layered driver API documentation |
+ This document explains the API interface of the table driver module. Functions with rtl865x prefix
+ are external functions.
+ @normal Hyking Liu (Hyking_liu@realsil.com.cn) <date>
+
+ Copyright <cp>2008 Realtek<tm> Semiconductor Cooperation, All Rights Reserved.
+
+ @head3 List of Symbols |
+ Here is a list of all functions and variables in this module.
+
+ @index | RTL_LAYEREDDRV_API
+*/
+#include <net/rtl/rtl_types.h>
+#include <net/rtl/rtl_glue.h>
+#include <net/rtl/rtl865x_netif.h>
+#include "common/rtl_errno.h"
+#include "common/rtl865x_netif_local.h"
+#include "rtl865x_ip.h"
+#include "rtl865x_nexthop.h"
+//#include "rtl865x_ppp.h"
+#include "rtl865x_ppp_local.h"
+#include "rtl865x_route.h"
+#include "rtl865x_arp.h"
+
+#include "common/rtl865x_vlan.h"
+#include "common/rtl865x_eventMgr.h" /*call back function....*/
+
+#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER
+#include "AsicDriver/rtl865x_asicCom.h"
+#include "AsicDriver/rtl865x_asicL2.h"
+#include "AsicDriver/rtl865x_asicL3.h"
+#else
+#include "AsicDriver/rtl865xC_tblAsicDrv.h"
+#endif
+#include "l2Driver/rtl865x_fdb.h"
+#include <net/rtl/rtl865x_fdb_api.h>
+
+static rtl865x_nextHopEntry_t *rtl865x_nxtHopTable;
+
+#define NEXTHOP_TABLE_INDEX(entry) (entry - rtl865x_nxtHopTable)
+static int32 _rtl865x_nextHop_register_event(void);
+static int32 _rtl865x_nextHop_unRegister_event(void);
+static int32 _rtl865x_delNxtHop(uint32 attr, uint32 entryIdx);
+
+static RTL_DECLARE_MUTEX(nxthop_sem);
+
+#if 0
+static void _print_softNxtHop(void)
+{
+ int32 i = 0;
+ rtl865x_nextHopEntry_t *entry = rtl865x_nxtHopTable;
+ printk("software nextHop table:\n");
+ for(i = 0; i < NXTHOP_ENTRY_NUM; i++,entry++)
+ {
+ printk("idx(%d): valid(%d),dst(%s),nexthop(%d),nexthopType(%d),refCnt(%d)\n",i,entry->valid,entry->dstNetif->name,
+ entry->nexthop,entry->nextHopType,entry->refCnt);
+ }
+}
+#endif
+
+/*
+@func int32 | rtl865x_initNxtHopTable |initialize the nexthop table
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed. system should reboot.
+@comm
+*/
+int32 rtl865x_initNxtHopTable(void)
+{
+ TBL_MEM_ALLOC(rtl865x_nxtHopTable, rtl865x_nextHopEntry_t, NXTHOP_ENTRY_NUM);
+ memset(rtl865x_nxtHopTable,0,sizeof(rtl865x_nextHopEntry_t)*NXTHOP_ENTRY_NUM);
+ _rtl865x_nextHop_register_event();
+ return SUCCESS;
+}
+
+/*
+@func int32 | rtl865x_reinitNxtHopTable |reinitialize the nexthop table
+@rvalue SUCCESS | success.
+@comm
+*/
+int32 rtl865x_reinitNxtHopTable(void)
+{
+ int32 i;
+ _rtl865x_nextHop_unRegister_event();
+
+ for(i = 0; i < NXTHOP_ENTRY_NUM; i++)
+ {
+ if(rtl865x_nxtHopTable[i].valid)
+ _rtl865x_delNxtHop(NEXTHOP_L3,i);
+ }
+
+ _rtl865x_nextHop_register_event();
+ return SUCCESS;
+}
+#if defined CONFIG_RTL_LOCAL_PUBLIC
+extern int rtl865x_getLocalPublicArpMapping(unsigned int ip, rtl865x_arpMapping_entry_t * arp_mapping);
+#endif
+static int32 _rtl865x_synNxtHopToAsic(rtl865x_nextHopEntry_t *entry_t)
+{
+ rtl865x_tblAsicDrv_nextHopParam_t asic;
+ ether_addr_t reservedMac;
+ rtl865x_tblAsicDrv_l2Param_t asic_l2;
+ rtl865x_netif_local_t *dstNetif;
+ uint32 fid = 0;
+ uint32 columIdx = 0;
+ int32 retval = 0;
+ int32 ipIdx = 0;
+
+ retval = rtl865x_getReserveMacAddr(&reservedMac);
+
+ bzero(&asic, sizeof(rtl865x_tblAsicDrv_nextHopParam_t));
+
+ if(entry_t == NULL)
+ {
+ return RTL_EINVALIDINPUT;
+ }
+
+ if (entry_t->nextHopType == IF_ETHER)
+ {
+ rtl865x_arpMapping_entry_t arp_t;
+ int32 ret_arpFound = FAILED;
+
+ /*if the arp info of nexthop is not found, reserved to cpu Mac is used for trap packet to CPU*/
+#if defined (CONFIG_RTL_LOCAL_PUBLIC)
+ if(entry_t->nexthop)
+ {
+ ret_arpFound = rtl865x_getArpMapping(entry_t->nexthop,&arp_t);
+ if(ret_arpFound!=SUCCESS)
+ {
+ /*try to match local pulbic ip*/
+ ret_arpFound = rtl865x_getLocalPublicArpMapping(entry_t->nexthop, &arp_t);
+
+ }
+ }
+#else
+ if(entry_t->nexthop)
+ ret_arpFound = rtl865x_getArpMapping(entry_t->nexthop,&arp_t);
+#endif
+
+ rtl865x_getVlanFilterDatabaseId(entry_t->dstNetif->vid,&fid);
+ retval = rtl865x_Lookup_fdb_entry(fid, (ret_arpFound == SUCCESS)? &arp_t.mac : &reservedMac, FDB_DYNAMIC, &columIdx,&asic_l2);
+
+ asic.nextHopRow = rtl8651_filterDbIndex( (ret_arpFound == SUCCESS)? &arp_t.mac : &reservedMac, fid );
+ asic.nextHopColumn = (retval == SUCCESS)? columIdx: 0;
+
+ asic.isPppoe = FALSE;
+ asic.pppoeIdx = 0;
+ }
+ else
+ {
+ /*session based interface type*/
+ rtl865x_ppp_t pppoe;
+ int32 pppidx = 0;
+
+ memset(&pppoe,0,sizeof(rtl865x_ppp_t));
+
+ if(entry_t->nexthop)
+ retval = rtl865x_getPppBySessionId(entry_t->nexthop,&pppoe);
+
+ rtl865x_getVlanFilterDatabaseId(entry_t->dstNetif->vid,&fid);
+
+
+ retval =rtl865x_Lookup_fdb_entry(fid, (pppoe.valid)? &pppoe.server_mac : &reservedMac, FDB_DYNAMIC, &columIdx,&asic_l2);
+
+ asic.nextHopRow = rtl8651_filterDbIndex( (pppoe.valid)? &pppoe.server_mac : &reservedMac, fid);
+ asic.nextHopColumn = (pppoe.valid)? columIdx: 0;
+ asic.isPppoe = (pppoe.type == IF_PPPOE)? TRUE: FALSE;
+
+ retval = rtl865x_getPppIdx(&pppoe, &pppidx);
+
+ //printk("%s(%d): pppoeIdx(%d), pppoeType(%d), pppoevalid(%d),pppoeSid(%d)\n",__FUNCTION__,__LINE__,pppidx,pppoe.type,pppoe.valid,pppoe.sessionId);
+ asic.pppoeIdx = (pppoe.type == IF_PPPOE)? pppidx: 0;
+ }
+
+ if(entry_t->dstNetif->is_slave == 1)
+ {
+ dstNetif = entry_t->dstNetif->master;
+
+ if(dstNetif == NULL)
+ dstNetif = _rtl865x_getDefaultWanNetif();
+ }
+ else
+ dstNetif = entry_t->dstNetif;
+
+ if(dstNetif == NULL)
+ printk("_%s(%d), BUG!!!!!!",__FUNCTION__,__LINE__);
+
+ asic.dvid = dstNetif->asicIdx;
+
+ if(entry_t->srcIp)
+ retval = rtl865x_getIpIdxByExtIp(entry_t->srcIp, &ipIdx);
+
+ asic.extIntIpIdx = entry_t->srcIp? ipIdx: 0;
+
+ //printk("%s(%d), entryIdx(%d),asic.isPPPoe(%d),asic.pppoeIdx(%d),asic.dvid(%d)\n", __FUNCTION__,__LINE__,entry_t->entryIndex,asic.isPppoe,asic.pppoeIdx,asic.dvid);
+ rtl8651_setAsicNextHopTable(entry_t->entryIndex, &asic);
+
+ return SUCCESS;
+}
+
+
+static int32 _rtl865x_arrangeNxtHop(uint32 start, uint32 num)
+{
+ int32 idx;
+ rtl865x_nextHopEntry_t *entry = NULL;
+
+ if(start < 0 || start + num >= NXTHOP_ENTRY_NUM)
+ return RTL_EINVALIDINPUT;
+ for(idx = start; idx < start + num; idx++)
+ {
+ entry = &rtl865x_nxtHopTable[idx];
+
+ if(entry->valid)
+ _rtl865x_synNxtHopToAsic(entry);
+ }
+
+ return SUCCESS;
+}
+
+static int32 _rtl865x_addNxtHop(uint32 attr, void *ref_ptr, rtl865x_netif_local_t *netif, uint32 nexthop,uint32 srcIp)
+{
+ int entryIdx;
+ rtl865x_nextHopEntry_t *entry = NULL, *entry1 = NULL;
+ rtl865x_route_t *rt_t = NULL;
+
+ /*
+ * NOTE:
+ * parameter description:
+ * (1) attr: why need to add the nexthop entry? NEXTHOP_L3 or NEXTHOP_DEFREDIRECT_ACL?
+ * (2) ref_ptr: when attr = NEXTHOP_L3, ref_ptr point to a route structure,
+ * attr = NEXTHOP_DEFREDIRECT_ACL, ref_ptr = NULL,
+ * attr = others, ref_ptr = NULL
+ * (3) netif: destination network interface
+ * (4) nexthop:
+ * a) netif->if_type == IF_ETHER, nexthop = nexthop ip address,
+ * b) netif->if_type == session based type, nexthop = session Id,
+ *
+ * following case should be NOTED now:
+ * (1) ETHERNET type network interface:
+ * a) If nexthop != NULL , it means the entry is added for:
+ * nexthop ip&mac information, nextHop = arp entry of nexthop ip address.
+ * b) If nexthop == 0, use default route's nexthop or nexthop TOCPU
+ *
+ * (2) PPPoE/PPTP/L2TP type network interface:
+ * The "nexthop" will explicitly specify the PPPoE session (PPTP/L2TP session).
+ */
+
+ if(netif == NULL)
+ return RTL_EINVALIDINPUT;
+
+ /* Allocate an empty entry for new one */
+ /*Note: all nexthop entry referenced by L3 must be 2 entries aligned(reference l3 Datasheet)*/
+ for(entryIdx = 0; entryIdx < NXTHOP_ENTRY_NUM; entryIdx++)
+ {
+ if(rtl865x_nxtHopTable[entryIdx].valid == 0)
+ {
+ switch(attr)
+ {
+ case NEXTHOP_L3:
+ if( entryIdx%2 == 0 && (entryIdx + 1) < NXTHOP_ENTRY_NUM && rtl865x_nxtHopTable[entryIdx+1].valid == 0)
+ {
+ entry = &rtl865x_nxtHopTable[entryIdx];
+ goto found;
+ }
+ break;
+
+ case NEXTHOP_DEFREDIRECT_ACL:
+ entry = &rtl865x_nxtHopTable[entryIdx];
+ goto found;
+ break;
+
+ default:
+ printk("attr(%d) is not support.....\n",attr);
+ break;
+ }
+ }
+ }
+
+ /*if not found proper nextHop entry, return*/
+ entry = NULL;
+
+found:
+ if(entry == NULL)
+ return RTL_ENOFREEBUFFER;
+
+ entry->valid = 1;
+ entry->dstNetif = netif;
+ entry->entryIndex = entryIdx;
+ entry->nextHopType = netif->if_type;
+ entry->srcIp = srcIp;
+ entry->refCnt = 1;
+ entry->flag = attr;
+
+ switch(netif->if_type)
+ {
+ case IF_ETHER:
+ entry->nexthop = nexthop;
+ break;
+ case IF_PPPOE:
+ case IF_PPTP:
+ case IF_L2TP:
+ /*nexthop is sessionId*/
+ entry->nexthop = nexthop;
+ break;
+
+ }
+
+ if(attr == NEXTHOP_L3)
+ {
+ entry1 = &rtl865x_nxtHopTable[entryIdx+1];
+ memcpy(entry1,entry,sizeof(rtl865x_nextHopEntry_t));
+ entry1->entryIndex = entryIdx + 1;
+
+ _rtl865x_arrangeNxtHop(entryIdx, 2);
+
+ /*entry1 used netif,update reference netif*/
+ rtl865x_referNetif(netif->name);
+ /*entry1 used pppoe!, update reference pppoe*/
+ if((entry1->nextHopType == IF_PPPOE)
+ || (entry1->nextHopType == IF_PPTP)
+ || (entry1->nextHopType == IF_L2TP)
+ )
+ rtl865x_referPpp(nexthop);
+
+ /*FIXME_hyking:lazy, update the route information right here....*/
+ rt_t = (rtl865x_route_t *)ref_ptr;
+ rt_t ->un.nxthop.nxtHopSta = entryIdx;
+ rt_t ->un.nxthop.nxtHopEnd = entryIdx + 1;
+ }
+ else
+ _rtl865x_arrangeNxtHop(entryIdx, 1);
+
+ /*update reference dstnetif&pppoe arp?*/
+ rtl865x_referNetif(netif->name);
+ if((entry->nextHopType == IF_PPPOE)
+ || (entry->nextHopType == IF_PPTP)
+ || (entry->nextHopType == IF_L2TP)
+ )
+ rtl865x_referPpp(nexthop);
+
+ return SUCCESS;
+
+}
+
+static int32 _rtl865x_delNxtHop(uint32 attr, uint32 entryIdx)
+{
+ rtl865x_nextHopEntry_t *entry;
+ //int32 retval = 0;
+
+ if(entryIdx >= NXTHOP_ENTRY_NUM)
+ return RTL_EINVALIDINPUT;
+
+ entry = &rtl865x_nxtHopTable[entryIdx];
+
+ if(entry->valid == 0)
+ return RTL_EENTRYNOTFOUND;
+
+ if(entry->refCnt > 1)
+ {
+ printk("%s(%d),refcnt(%d)\n",__FUNCTION__,__LINE__,entry->refCnt);
+ return SUCCESS;
+ }
+
+ /*now delete the entry*/
+ //if(entry->srcIp_t)
+ //retval = rtl865x_delIp(entry->srcIp_t->extIp);
+
+ if((entry->nextHopType == IF_PPPOE)
+ || (entry->nextHopType == IF_PPTP)
+ || (entry->nextHopType == IF_L2TP)
+ )
+ {
+ rtl865x_deReferPpp(entry->nexthop);
+
+ }
+
+ rtl865x_deReferNetif(entry->dstNetif->name);
+ memset(entry,0,sizeof(rtl865x_nextHopEntry_t));
+
+ /*update asic nextHop table*/
+ //_rtl865x_arrangeNxtHop(entryIdx,1);
+
+ return SUCCESS;
+
+}
+
+#if defined(CONFIG_RTL_MULTIPLE_WAN)
+static int32 _rtl865x_synNxtHop_by_arp_entry(rtl865x_nextHopEntry_t *entry_t,rtl865x_arpMapping_entry_t *arp)
+{
+ rtl865x_tblAsicDrv_nextHopParam_t asic;
+ ether_addr_t reservedMac;
+ ether_addr_t zero_mac ={{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+ rtl865x_tblAsicDrv_l2Param_t asic_l2;
+ rtl865x_netif_local_t *dstNetif;
+ uint32 fid = 0;
+ uint32 columIdx = 0;
+ int32 retval = 0;
+ int32 ipIdx = 0;
+
+ retval = rtl865x_getReserveMacAddr(&reservedMac);
+
+ bzero(&asic, sizeof(rtl865x_tblAsicDrv_nextHopParam_t));
+
+ if(entry_t == NULL || arp == NULL)
+ {
+ return RTL_EINVALIDINPUT;
+ }
+
+ if (entry_t->nextHopType == IF_ETHER)
+ {
+ int mac_valid = 0;
+ mac_valid = memcmp(arp->mac.octet,zero_mac.octet,ETHER_ADDR_LEN);
+
+ rtl865x_getVlanFilterDatabaseId(entry_t->dstNetif->vid,&fid);
+ retval = rtl865x_Lookup_fdb_entry(fid, (mac_valid)? &arp->mac : &reservedMac, FDB_DYNAMIC, &columIdx,&asic_l2);
+
+ asic.nextHopRow = rtl8651_filterDbIndex( (mac_valid)? &arp->mac : &reservedMac, fid );
+ asic.nextHopColumn = (retval == SUCCESS)? columIdx: 0;
+
+ asic.isPppoe = FALSE;
+ asic.pppoeIdx = 0;
+ }
+ else
+ {
+ /*session based interface type*/
+ rtl865x_ppp_t pppoe;
+ int32 pppidx = 0;
+
+ memset(&pppoe,0,sizeof(rtl865x_ppp_t));
+
+ if(entry_t->nexthop)
+ retval = rtl865x_getPppBySessionId(entry_t->nexthop,&pppoe);
+
+ rtl865x_getVlanFilterDatabaseId(entry_t->dstNetif->vid,&fid);
+
+
+ retval =rtl865x_Lookup_fdb_entry(fid, (pppoe.valid)? &pppoe.server_mac : &reservedMac, FDB_DYNAMIC, &columIdx,&asic_l2);
+
+ asic.nextHopRow = rtl8651_filterDbIndex( (pppoe.valid)? &pppoe.server_mac : &reservedMac, fid);
+ asic.nextHopColumn = (pppoe.valid)? columIdx: 0;
+ asic.isPppoe = (pppoe.type == IF_PPPOE)? TRUE: FALSE;
+
+ retval = rtl865x_getPppIdx(&pppoe, &pppidx);
+
+ //printk("%s(%d): pppoeIdx(%d), pppoeType(%d), pppoevalid(%d),pppoeSid(%d)\n",__FUNCTION__,__LINE__,pppidx,pppoe.type,pppoe.valid,pppoe.sessionId);
+ asic.pppoeIdx = (pppoe.type == IF_PPPOE)? pppidx: 0;
+ }
+
+ if(entry_t->dstNetif->is_slave == 1)
+ {
+ dstNetif = entry_t->dstNetif->master;
+
+ if(dstNetif == NULL)
+ dstNetif = _rtl865x_getDefaultWanNetif();
+ }
+ else
+ dstNetif = entry_t->dstNetif;
+
+ if(dstNetif == NULL)
+ printk("_%s(%d), BUG!!!!!!",__FUNCTION__,__LINE__);
+
+ asic.dvid = dstNetif->asicIdx;
+
+ if(entry_t->srcIp)
+ retval = rtl865x_getIpIdxByExtIp(entry_t->srcIp, &ipIdx);
+
+ asic.extIntIpIdx = entry_t->srcIp? ipIdx: 0;
+
+ //printk("%s(%d), entryIdx(%d),asic.isPPPoe(%d),asic.pppoeIdx(%d),asic.dvid(%d)\n", __FUNCTION__,__LINE__,entry_t->entryIndex,asic.isPppoe,asic.pppoeIdx,asic.dvid);
+ rtl8651_setAsicNextHopTable(entry_t->entryIndex, &asic);
+
+ return SUCCESS;
+}
+
+int32 rtl865x_eventHandle_addArp_for_multiWan(void *param)
+{
+ rtl865x_arpMapping_entry_t *arp;
+ rtl865x_nextHopEntry_t *entry;
+ int32 i;
+
+ if(param == NULL)
+ return EVENT_CONTINUE_EXECUTE;
+
+ arp = (rtl865x_arpMapping_entry_t *)param;
+ entry = rtl865x_nxtHopTable;
+
+ for(i = 0; i < NXTHOP_ENTRY_NUM; i++,entry++)
+ {
+ if(entry->valid && entry->nextHopType == IF_ETHER)
+ {
+ /*update nexthop*/
+ if(entry->nexthop == arp->ip)
+ {
+ _rtl865x_synNxtHop_by_arp_entry(entry,arp);
+ }
+ }
+ }
+ return EVENT_CONTINUE_EXECUTE;
+}
+
+int32 rtl865x_eventHandle_delArp_for_multiWan(void *param)
+{
+ rtl865x_arpMapping_entry_t *arp;
+ rtl865x_nextHopEntry_t *entry;
+ int32 i;
+
+ if(param == NULL)
+ return EVENT_CONTINUE_EXECUTE;
+
+ arp = (rtl865x_arpMapping_entry_t *)param;
+ entry = rtl865x_nxtHopTable;
+
+ //set mac to 0 for sync nexthop
+ memset(arp->mac.octet,0,ETHER_ADDR_LEN);
+
+ for(i = 0; i < NXTHOP_ENTRY_NUM; i++,entry++)
+ {
+ if(entry->valid && entry->nextHopType == IF_ETHER)
+ {
+ /*update nexthop*/
+ if(entry->nexthop == arp->ip)
+ _rtl865x_synNxtHop_by_arp_entry(entry,arp);
+ }
+ }
+ return EVENT_CONTINUE_EXECUTE;
+}
+
+#endif
+
+static int32 _rtl865x_eventHandle_addArp(void *param)
+{
+ rtl865x_arpMapping_entry_t *arp;
+ rtl865x_nextHopEntry_t *entry;
+ int32 i;
+
+ if(param == NULL)
+ return EVENT_CONTINUE_EXECUTE;
+
+ arp = (rtl865x_arpMapping_entry_t *)param;
+
+ entry = rtl865x_nxtHopTable;
+ for(i = 0; i < NXTHOP_ENTRY_NUM; i++,entry++)
+ {
+ if(entry->valid && entry->nextHopType == IF_ETHER)
+ {
+ /*update nexthop*/
+ if(entry->nexthop == arp->ip)
+ _rtl865x_synNxtHopToAsic(entry);
+ }
+ }
+ return EVENT_CONTINUE_EXECUTE;
+}
+
+static int32 _rtl865x_eventHandle_delArp(void *param)
+{
+ rtl865x_arpMapping_entry_t *arp;
+ rtl865x_nextHopEntry_t *entry;
+ int32 i;
+
+ if(param == NULL)
+ return EVENT_CONTINUE_EXECUTE;
+
+ arp = (rtl865x_arpMapping_entry_t *)param;
+
+ entry = rtl865x_nxtHopTable;
+ for(i = 0; i < NXTHOP_ENTRY_NUM; i++,entry++)
+ {
+ if(entry->valid && entry->nextHopType == IF_ETHER)
+ {
+ /*update nexthop*/
+ if(entry->nexthop == arp->ip)
+ _rtl865x_synNxtHopToAsic(entry);
+ }
+ }
+ return EVENT_CONTINUE_EXECUTE;
+}
+
+static int32 _rtl865x_eventHandle_delPpp(void *param)
+{
+ rtl865x_ppp_t *pppoe;
+ rtl865x_nextHopEntry_t *entry;
+ int32 i;
+
+ if(param == NULL)
+ return EVENT_CONTINUE_EXECUTE;
+
+ pppoe = (rtl865x_ppp_t *)param;
+
+ entry = rtl865x_nxtHopTable;
+ for(i = 0; i < NXTHOP_ENTRY_NUM; i++,entry++)
+ {
+ if(entry->valid )
+ if((entry->nextHopType == IF_PPPOE)
+ || (entry->nextHopType == IF_PPTP)
+ || (entry->nextHopType == IF_L2TP)
+ )
+ {
+ /*update nexthop*/
+ if(entry->nexthop == pppoe->sessionId)
+ {
+ /*update the action(TOCPU)*/
+ entry->nexthop = 0;
+ _rtl865x_synNxtHopToAsic(entry);
+ }
+ }
+ }
+
+ return EVENT_CONTINUE_EXECUTE;
+}
+
+static int32 _rtl865x_nextHop_register_event(void)
+{
+ rtl865x_event_Param_t eventParam;
+ eventParam.eventLayerId=DEFAULT_LAYER3_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_DEL_ARP;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=_rtl865x_eventHandle_delArp;
+ rtl865x_registerEvent(&eventParam);
+
+ memset(&eventParam,0,sizeof(rtl865x_event_Param_t));
+ eventParam.eventLayerId=DEFAULT_LAYER3_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_ADD_ARP;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=_rtl865x_eventHandle_addArp;
+ rtl865x_registerEvent(&eventParam);
+
+ memset(&eventParam,0,sizeof(rtl865x_event_Param_t));
+ eventParam.eventLayerId=DEFAULT_LAYER3_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_DEL_PPP;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=_rtl865x_eventHandle_delPpp;
+ rtl865x_registerEvent(&eventParam);
+
+ return SUCCESS;
+
+}
+
+static int32 _rtl865x_nextHop_unRegister_event(void)
+{
+ rtl865x_event_Param_t eventParam;
+ eventParam.eventLayerId=DEFAULT_LAYER3_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_DEL_ARP;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=_rtl865x_eventHandle_delArp;
+ rtl865x_unRegisterEvent(&eventParam);
+
+ memset(&eventParam,0,sizeof(rtl865x_event_Param_t));
+ eventParam.eventLayerId=DEFAULT_LAYER3_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_ADD_ARP;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=_rtl865x_eventHandle_addArp;
+ rtl865x_unRegisterEvent(&eventParam);
+
+ memset(&eventParam,0,sizeof(rtl865x_event_Param_t));
+ eventParam.eventLayerId=DEFAULT_LAYER3_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_DEL_PPP;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=_rtl865x_eventHandle_delPpp;
+ rtl865x_unRegisterEvent(&eventParam);
+
+ return SUCCESS;
+
+}
+
+
+/*
+@func int32 | rtl865x_addNxtHop |add a nexthop entry
+@parm uint32 | attr | attribute. NEXTHOP_L3/NEXTHOP_REDIRECT.
+@parm void* | ref_ptr | entry pointer who refer this nexthop entry.
+@parm rtl865x_netif_local_t* | netif | network interface.
+@parm uint32 | nexthop | nexthop. ip address when linktype is ethernet, session id when linktype is ppp session based.
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed.
+@comm
+*/
+int32 rtl865x_addNxtHop(uint32 attr, void *ref_ptr, rtl865x_netif_local_t *netif, uint32 nexthop,uint32 srcIp)
+{
+ int32 ret = FAILED;
+ unsigned long flags;
+ //rtl_down_interruptible(&nxthop_sem);
+ local_irq_save(flags);
+ ret = _rtl865x_addNxtHop(attr,ref_ptr,netif,nexthop,srcIp);
+ //rtl_up(&nxthop_sem);
+ local_irq_restore(flags);
+ return ret;
+}
+
+/*
+@func int32 | rtl865x_delNxtHop |delete nexthop entry
+@parm uint32 | attr | attribute. NEXTHOP_L3/NEXTHOP_REDIRECT.
+@parm uint32 | entryIdx | entry index.
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed.
+@comm
+*/
+int32 rtl865x_delNxtHop(uint32 attr, uint32 entryIdx)
+{
+ int32 retval = FAILED;
+ unsigned long flags;
+ //rtl_down_interruptible(&nxthop_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_delNxtHop(attr,entryIdx);
+ //rtl_up(&nxthop_sem);
+ local_irq_restore(flags);
+ return retval;
+}
+
+#if defined (CONFIG_RTL_LOCAL_PUBLIC) || defined(CONFIG_RTL_MULTIPLE_WAN)
+int32 rtl865x_getNxtHopIdx(uint32 attr, rtl865x_netif_local_t *netif, uint32 nexthop)
+{
+ rtl865x_nextHopEntry_t *entry;
+ int32 i;
+
+ entry = rtl865x_nxtHopTable;
+ for(i = 0; i < NXTHOP_ENTRY_NUM; i++,entry++)
+ {
+ if( (entry->valid) &&
+ (entry->flag == attr)&&
+ (entry->dstNetif == netif) &&
+ (entry->nexthop== nexthop))
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+#endif
+
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_nexthop.h b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_nexthop.h new file mode 100644 index 000000000..8ff49fbfe --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_nexthop.h @@ -0,0 +1,59 @@ +/* +* Copyright c Realtek Semiconductor Corporation, 2008 +* All rights reserved. +* +* Program : nexthop table driver +* Abstract : +* Author : hyking (hyking_liu@realsil.com.cn) +*/ +#ifndef RTL865X_NEXTHOP_H +#define RTL865X_NEXTHOP_H + +#if !defined(REDUCE_MEMORY_SIZE_FOR_16M) +#define REDUCE_MEMORY_SIZE_FOR_16M +#endif + + +typedef struct rtl865x_nextHopEntry_s +{ + rtl865x_netif_local_t *dstNetif; /* dst network interface*/ + uint32 nexthop; /* ethernet: nexthop ip address, pppoe: session Id */ + //rtl865x_ip_entry_t *srcIp_t; /* for nexthop source ip table index, it's invalid now*/ + uint32 srcIp; /* for nexthop source ip table index*/ + + uint16 valid:1, /* 0: Invalid, 1: Invalid */ + nextHopType:3, /* IF_ETHER, IF_PPPOE */ + flag:3; /* bit0:referenced by l3, bit2:referenced by acl */ + + uint16 refCnt; /* Reference Count */ + uint32 entryIndex; /* Entry Index */ + +} rtl865x_nextHopEntry_t; + +#define NEXTHOP_L3 0x01 +#define NEXTHOP_DEFREDIRECT_ACL 0x02 +#if defined (CONFIG_RTL_LOCAL_PUBLIC) +#define NXTHOP_ENTRY_NUM 16 +#else +#if defined(REDUCE_MEMORY_SIZE_FOR_16M) +#define NXTHOP_ENTRY_NUM 4 +#else +#define NXTHOP_ENTRY_NUM 16 +#endif +#endif +int32 rtl865x_initNxtHopTable(void); +int32 rtl865x_reinitNxtHopTable(void); +int32 rtl865x_addNxtHop(uint32 attr, void *ref_ptr, rtl865x_netif_local_t *netif, uint32 nexthop,uint32 srcIp); +int32 rtl865x_delNxtHop(uint32 attr, uint32 entryIdx); + +#if defined(CONFIG_RTL_LOCAL_PUBLIC) || defined(CONFIG_RTL_MULTIPLE_WAN) +int32 rtl865x_getNxtHopIdx(uint32 attr, rtl865x_netif_local_t *netif, uint32 nexthop); +#endif + +#if defined(CONFIG_RTL_MULTIPLE_WAN) +int32 rtl865x_eventHandle_addArp_for_multiWan(void *param); +int32 rtl865x_eventHandle_delArp_for_multiWan(void *param); +#endif + +#endif + diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ppp.c b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ppp.c new file mode 100644 index 000000000..e8fcfadb5 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ppp.c @@ -0,0 +1,579 @@ +/*
+* Copyright c Realtek Semiconductor Corporation, 2008
+* All rights reserved.
+*
+* Program : ppp table driver
+* Abstract :
+* Author : hyking (hyking_liu@realsil.com.cn)
+*/
+
+/* @doc RTL_LAYEREDDRV_API
+
+ @module rtl865x_ppp.c - RTL865x Home gateway controller Layered driver API documentation |
+ This document explains the API interface of the table driver module. Functions with rtl865x prefix
+ are external functions.
+ @normal Hyking Liu (Hyking_liu@realsil.com.cn) <date>
+
+ Copyright <cp>2008 Realtek<tm> Semiconductor Cooperation, All Rights Reserved.
+
+ @head3 List of Symbols |
+ Here is a list of all functions and variables in this module.
+
+ @index | RTL_LAYEREDDRV_API
+*/
+#include <net/rtl/rtl_types.h>
+#include <net/rtl/rtl_glue.h>
+#include <net/rtl/rtl865x_ppp.h>
+#include <net/rtl/rtl865x_netif.h>
+#include <net/rtl/rtl865x_fdb_api.h>
+
+#include "common/rtl_errno.h"
+#include "common/rtl865x_netif_local.h"
+#include "rtl865x_ppp_local.h"
+
+#include "common/rtl865x_eventMgr.h" /*call back function....*/
+
+#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER
+#include "AsicDriver/rtl865x_asicCom.h"
+#include "AsicDriver/rtl865x_asicL2.h"
+#include "AsicDriver/rtl865x_asicL3.h"
+#else
+#include "AsicDriver/rtl865xC_tblAsicDrv.h"
+#endif
+
+#include "common/rtl865x_vlan.h"
+#include "l2Driver/rtl865x_fdb.h"
+
+static rtl865x_ppp_t *rtl865x_pppTable;
+
+#define PPP_TABLE_INDEX(entry) (entry - rtl865x_pppTable)
+static RTL_DECLARE_MUTEX(ppp_sem);
+
+static int32 _rtl865x_ppp_register_event(void);
+static int32 _rtl865x_ppp_unRegister_event(void);
+static int32 _rtl865x_delPpp(uint32 sessionId);
+
+/*
+@func int32 | rtl865x_initPppTable | initialize ppp table.
+@rvalue SUCCESS | Success.
+@rvalue FAILED | Failed.
+*/
+int32 rtl865x_initPppTable(void)
+{
+ TBL_MEM_ALLOC(rtl865x_pppTable, rtl865x_ppp_t, PPP_NUMBER);
+ memset(rtl865x_pppTable,0,sizeof(rtl865x_ppp_t)*PPP_NUMBER);
+
+ /*event regist....*/
+ _rtl865x_ppp_register_event();
+ return SUCCESS;
+}
+
+/*
+@func int32 | rtl865x_reinitPppTable | reinitialize ppp table.
+@rvalue SUCCESS | Success.
+@rvalue FAILED | Failed.
+*/
+int32 rtl865x_reinitPppTable(void)
+{
+ int32 i;
+ _rtl865x_ppp_unRegister_event();
+
+ for(i = 0; i < PPP_NUMBER; i++)
+ {
+ if(rtl865x_pppTable[i].valid == 1)
+ _rtl865x_delPpp(rtl865x_pppTable[i].sessionId);
+ }
+
+ _rtl865x_ppp_register_event();
+ return SUCCESS;
+}
+
+
+
+static int32 _rtl865x_delPpp(uint32 sessionId)
+{
+ int i;
+ rtl865x_ppp_t *entry = NULL;
+ rtl865x_tblAsicDrv_pppoeParam_t asicppp;
+ int32 retval = FAILED;
+ uint32 fid;
+
+ /*found the entry*/
+ for(i = 0; i < PPP_NUMBER; i++)
+ {
+ if(rtl865x_pppTable[i].valid == 1 && rtl865x_pppTable[i].sessionId== sessionId)
+ {
+ entry = &rtl865x_pppTable[i];
+ break;
+ }
+ }
+
+ if (entry==NULL)
+ return SUCCESS;
+ /*check reference count*/
+ if(entry->refCnt > 1)
+ {
+ printk("Please del other table entry which referenced me...ppp sessionId(%d)\n",sessionId);
+ return RTL_EREFERENCEDBYOTHER;
+ }
+
+
+ /*del asic ppp table*/
+ asicppp.age = 0;
+ asicppp.sessionId = 0;
+ rtl8651_setAsicPppoe(PPP_TABLE_INDEX(entry), &asicppp);
+
+ /*FIXME_hyking:dereference netif & mac*/
+ retval = rtl865x_deReferNetif(entry->netif->name);
+
+ retval = rtl865x_getVlanFilterDatabaseId(entry->netif->vid, &fid);
+
+ retval = rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEII, fid, &entry->server_mac);
+
+
+ /*raise event??*/
+ rtl865x_raiseEvent(EVENT_DEL_PPP,(void *)entry);
+
+ memset(entry,0,sizeof(rtl865x_ppp_t));
+
+
+ return SUCCESS;
+
+}
+static int32 _rtl865x_addPpp(uint8 *ifname, ether_addr_t *mac, uint32 sessionId, int32 type)
+{
+ int i;
+ rtl865x_netif_local_t *netif;
+ rtl865x_ppp_t *entry = NULL;
+ rtl865x_tblAsicDrv_pppoeParam_t asicPpp;
+ rtl865x_tblAsicDrv_l2Param_t fdbEntry;
+ rtl865x_filterDbTableEntry_t l2temp_entry;
+ uint32 fid,column;
+ int32 retval;
+ uint32 fdb_type[]={ FDB_STATIC, FDB_DYNAMIC };
+
+/*printk("%s(%d): ifname(%s),mac(%02x:%02x:%02x:%02x:%02x:%02x),sid(%d),type(%d)",__FUNCTION__,__LINE__,ifname,
+ mac->octet[0],mac->octet[1],mac->octet[2],mac->octet[3],mac->octet[4],mac->octet[5], sessionId,type);*/
+
+ /*duplicate check*/
+ for(i = 0; i < PPP_NUMBER; i++)
+ {
+ if(rtl865x_pppTable[i].valid && rtl865x_pppTable[i].sessionId == sessionId)
+ return RTL_EENTRYALREADYEXIST;
+ }
+
+ netif = _rtl865x_getSWNetifByName(ifname);
+ if(netif == NULL)
+ return RTL_ENETIFINVALID;
+
+ if(netif->if_type != IF_PPPOE)
+ return RTL_ELINKTYPESHOULDBERESET;
+
+ /*found a valid entry*/
+ for(i = 0; i < PPP_NUMBER; i++)
+ if(rtl865x_pppTable[i].valid == 0)
+ {
+ entry = &rtl865x_pppTable[i];
+ break;
+ }
+
+ if(entry == NULL)
+ return RTL_ENOFREEBUFFER;
+
+
+
+ /*update releated information*/
+ entry->valid = 1;
+ entry->netif = netif;
+ memcpy(&entry->server_mac,mac,sizeof(ether_addr_t));
+ entry->sessionId = sessionId;
+ entry->type = type;
+ entry->refCnt = 1;
+
+ /*add this ip entry to asic*/
+ /* Set asic */
+ bzero(&asicPpp, sizeof(rtl865x_tblAsicDrv_pppoeParam_t));
+ asicPpp.sessionId = sessionId;
+ asicPpp.age = 300;
+
+ rtl8651_setAsicPppoe(PPP_TABLE_INDEX(entry), &asicPpp);
+
+
+ /*FIXME_hyking:reference netif & mac*/
+ retval = rtl865x_referNetif(netif->name);
+
+ /*add fdb entry...*/
+ fid = 0;
+ column = 0;
+ retval = rtl865x_getVlanFilterDatabaseId(netif->vid,&fid);
+
+ for(i = 0; i < 2; i++)
+ {
+ /*
+ printk("%s:%d\n,fid(%d),mac(%02x:%02x:%02x:%02x:%02x:%02x)\n",__FUNCTION__,__LINE__,fid,mac->octet[0],mac->octet[1],
+ mac->octet[2],mac->octet[3],mac->octet[4],mac->octet[5]);
+
+ printk("%s:%d\n",__FUNCTION__,__LINE__);
+ */
+ if(rtl865x_Lookup_fdb_entry(fid, mac, fdb_type[i], &column,&fdbEntry) != SUCCESS)
+ {
+ continue;
+ }
+
+
+ /*in case of layer2 auto learn, add hardware entry to layer 2 software table*/
+ l2temp_entry.l2type = (fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII;
+ l2temp_entry.process = FDB_TYPE_FWD;
+ l2temp_entry.memberPortMask = fdbEntry.memberPortMask;
+ l2temp_entry.auth = fdbEntry.auth;
+ l2temp_entry.SrcBlk = fdbEntry.srcBlk;
+ memcpy(&(l2temp_entry.macAddr), mac, sizeof(ether_addr_t));
+ rtl865x_addFilterDatabaseEntryExtension(fid, &l2temp_entry);
+// retval = _rtl865x_addFilterDatabaseEntry((fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII, fid, mac, FDB_TYPE_FWD, fdbEntry.memberPortMask, fdbEntry.auth,fdbEntry.srcBlk);
+ rtl865x_refleshHWL2Table(mac, FDB_DYNAMIC|FDB_STATIC,fid);
+ }
+
+ /*raise event??*/
+ rtl865x_raiseEvent(EVENT_ADD_PPP, (void*)entry);
+
+ return SUCCESS;
+
+}
+
+static int32 _rtl865x_eventHandle_delNetif(void *para)
+{
+ rtl865x_netif_local_t *netif;
+ rtl865x_ppp_t *entry = NULL;
+ int32 i = 0;
+ if(para == NULL)
+ return EVENT_CONTINUE_EXECUTE;
+
+ netif = (rtl865x_netif_local_t *)para;
+
+ entry = rtl865x_pppTable;
+ for(i = 0 ; i < PPP_NUMBER;i++,entry++)
+ {
+ if((entry->valid) && entry->netif == netif)
+ printk("%s(%d): BUG....deleted netif is referenced by ppp table!\n",__FUNCTION__,__LINE__);
+ }
+ return EVENT_CONTINUE_EXECUTE;
+}
+
+static int32 _rtl865x_eventHandle_delL2Fdb(void * param)
+{
+ rtl865x_filterDbTableEntry_t *fdbEntry;
+ rtl865x_ppp_t *entry = NULL;
+ int32 i;
+
+ if(param == NULL)
+ return EVENT_CONTINUE_EXECUTE;
+
+ fdbEntry = (rtl865x_filterDbTableEntry_t *)param;
+
+ entry = rtl865x_pppTable;
+ for(i = 0; i < PPP_NUMBER; i++,entry++)
+ {
+ if((entry->valid) && memcmp(&entry->server_mac,&fdbEntry->macAddr,sizeof(ether_addr_t)) == 0)
+ printk("%s(%d): BUG....deleted l2 fdb is referenced by ppp table!\n",__FUNCTION__,__LINE__);
+ }
+
+ return EVENT_CONTINUE_EXECUTE;
+}
+
+static int32 rtl865x_ppp_eventHandle_delNetif(void *para)
+{
+ int32 retval = EVENT_CONTINUE_EXECUTE;
+ //rtl_down_interruptible(&ppp_sem);
+ retval = _rtl865x_eventHandle_delNetif(para);
+ //rtl_up(&ppp_sem);
+ return retval;
+}
+
+static int32 rtl865x_ppp_eventHandle_delL2Fdb(void *para)
+{
+ int32 retval = EVENT_CONTINUE_EXECUTE;
+ //rtl_down_interruptible(&ppp_sem);
+ retval = _rtl865x_eventHandle_delL2Fdb(para);
+ //rtl_up(&ppp_sem);
+ return retval;
+}
+
+
+static int32 _rtl865x_ppp_register_event(void)
+{
+ rtl865x_event_Param_t eventParam;
+ eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_DEL_FDB;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=rtl865x_ppp_eventHandle_delL2Fdb;
+ rtl865x_registerEvent(&eventParam);
+
+ memset(&eventParam,0,sizeof(rtl865x_event_Param_t));
+ eventParam.eventLayerId=DEFAULT_COMMON_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_DEL_NETIF;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=rtl865x_ppp_eventHandle_delNetif;
+ rtl865x_registerEvent(&eventParam);
+
+ return SUCCESS;
+
+}
+
+static int32 _rtl865x_ppp_unRegister_event(void)
+{
+ rtl865x_event_Param_t eventParam;
+ eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_DEL_FDB;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=rtl865x_ppp_eventHandle_delL2Fdb;
+ rtl865x_unRegisterEvent(&eventParam);
+
+ memset(&eventParam,0,sizeof(rtl865x_event_Param_t));
+ eventParam.eventLayerId=DEFAULT_COMMON_EVENT_LIST_ID;
+ eventParam.eventId=EVENT_DEL_NETIF;
+ eventParam.eventPriority=0;
+ eventParam.event_action_fn=rtl865x_ppp_eventHandle_delNetif;
+ rtl865x_unRegisterEvent(&eventParam);
+
+ return SUCCESS;
+}
+
+static int32 _rtl865x_referPpp(uint32 sessionId)
+{
+ int i;
+ rtl865x_ppp_t *entry = NULL;
+
+ entry = rtl865x_pppTable;
+ for(i = 0; i < PPP_NUMBER; i++,entry++)
+ if(entry->valid && (entry->sessionId == sessionId))
+ {
+ entry->refCnt++;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+static int32 _rtl865x_deReferPpp(uint32 sessionId)
+{
+ int i;
+ rtl865x_ppp_t *entry = NULL;
+
+ entry = rtl865x_pppTable;
+ for(i = 0; i < PPP_NUMBER; i++,entry++)
+ if(entry->valid && (entry->sessionId == sessionId))
+ {
+ entry->refCnt--;
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/*
+@func int32 | rtl865x_referPpp |refer ppp table entry.
+@parm uint32 | sessionId | ppp session ID
+@rvalue SUCCESS | Success.
+@rvalue FAILED | Failed
+@comm
+*/
+int32 rtl865x_referPpp(uint32 sessionId)
+{
+ int32 retval = FAILED;
+ unsigned long flags;
+ //rtl_down_interruptible(&ppp_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_referPpp(sessionId);
+ //rtl_up(&ppp_sem);
+ local_irq_restore(flags);
+ return retval;
+}
+/*
+@func int32 | rtl865x_deReferPpp |dereference ppp table entry.
+@parm uint32 | sessionId | ppp session ID
+@rvalue SUCCESS | Success.
+@rvalue FAILED | Failed
+@comm
+*/
+int32 rtl865x_deReferPpp(uint32 sessionId)
+{
+ int32 retval = FAILED;
+ unsigned long flags;
+ //rtl_down_interruptible(&ppp_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_deReferPpp(sessionId);
+ //rtl_up(&ppp_sem);
+ local_irq_restore(flags);
+ return retval;
+}
+
+/*
+@func int32 | rtl865x_addPpp |add ppp session information.
+@parm uint8* | ifname | network interface name
+@parm ether_addr_t* | mac | MAC Address of ppp session server
+@parm uint32 | sessionId | ppp session ID
+@parm int32 | type | connect type. should be IF_PPPOE/IF_PPTP/IF_L2TP
+@rvalue SUCCESS | Success.
+@rvalue RTL_EENTRYALREADYEXIST | entry already exist.
+@rvalue RTL_ELINKTYPESHOULDBERESET | link type is error.
+@rvalue RTL_ENOFREEBUFFER | no enough memory buffer in system.
+@rvalue FAILED | Failed
+@comm
+*/
+int32 rtl865x_addPpp(uint8 *ifname, ether_addr_t *mac, uint32 sessionId, int32 type)
+{
+ int32 retval = FAILED;
+ unsigned long flags;
+ //printk("====================%s(%d): sessionId(%d) ifname(%s) retval(%d)\n",__FUNCTION__,__LINE__,sessionId,ifname,retval);
+ //rtl_down_interruptible(&ppp_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_addPpp(ifname, mac, sessionId, type);
+ //rtl_up(&ppp_sem);
+ local_irq_restore(flags);
+ //printk("====================%s(%d): sessionId(%d) retval(%d)\n",__FUNCTION__,__LINE__,sessionId,retval);
+ return retval;
+
+}
+
+/*
+@func int32 | rtl865x_delPpp |delete ppp session information.
+@parm uint32 | sessionId | ppp session ID
+@rvalue SUCCESS | Success.
+@rvalue RTL_EREFERENCEDBYOTHER | entry is refered by other table entry.
+@rvalue FAILED | Failed
+@comm
+*/
+int32 rtl865x_delPpp(uint32 sessionId)
+{
+ int32 retval = FAILED;
+ unsigned long flags;
+ //rtl_down_interruptible(&ppp_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_delPpp(sessionId);
+ //rtl_up(&ppp_sem);
+ local_irq_restore(flags);
+ //printk("====================%s(%d): sessionId(%d) retval(%d)\n",__FUNCTION__,__LINE__,sessionId,retval);
+ return retval;
+
+}
+
+/*
+@func int32 | rtl865x_delPppbyIfName |delete ppp session by network interface name.
+@parm char* | name | network interface name.
+@rvalue SUCCESS | Success.
+@rvalue RTL_EREFERENCEDBYOTHER | entry is refered by other table entry.
+@rvalue FAILED | Failed
+@comm
+*/
+int32 rtl865x_delPppbyIfName(char *name)
+{
+ int i;
+ rtl865x_ppp_t *entry = NULL;
+ int32 retval = FAILED;
+ unsigned long flags;
+ //rtl_down_interruptible(&ppp_sem);
+ local_irq_save(flags);
+ for(i = 0; i < PPP_NUMBER; i++)
+ if(rtl865x_pppTable[i].valid && (memcmp(rtl865x_pppTable[i].netif->name,name,sizeof(name)) == 0))
+ {
+ entry = &rtl865x_pppTable[i];
+ break;
+ }
+
+ if(entry)
+ retval = _rtl865x_delPpp(entry->sessionId);
+ //rtl_up(&ppp_sem);
+ local_irq_restore(flags);
+ return retval;
+}
+
+/*
+@func int32 | rtl865x_getPppBySessionId |get ppp session information by session ID.
+@parm uint32 | sessionId | ppp session ID
+@parm rtl865x_ppp_t* | entry | ppp entry.
+@rvalue SUCCESS | Success.
+@rvalue FAILED | Failed
+@comm
+*/
+int32 rtl865x_getPppBySessionId(uint32 sessionId,rtl865x_ppp_t *entry)
+{
+ rtl865x_ppp_t *ppp = NULL;
+ int32 retval = FAILED;
+ int i;
+
+ for(i = 0; i < PPP_NUMBER; i++)
+ {
+ if(rtl865x_pppTable[i].valid && rtl865x_pppTable[i].sessionId== sessionId)
+ ppp = &rtl865x_pppTable[i];
+ }
+
+ if(ppp && entry)
+ {
+ memcpy(entry,ppp,sizeof(rtl865x_ppp_t));
+ retval = SUCCESS;
+ }
+
+ return retval;
+
+}
+
+/*
+@func rtl865x_ppp_t* | rtl865x_getPppByNetifName |get ppp session information by network interface name.
+@parm char* | name | network interface name.
+@rvalue NULL | Failed
+@comm
+*/
+rtl865x_ppp_t* rtl865x_getPppByNetifName(char *name)
+{
+ rtl865x_ppp_t *ppp = NULL;
+ int i;
+
+ for(i = 0; i < PPP_NUMBER; i++)
+ {
+ if(rtl865x_pppTable[i].valid && (memcmp(rtl865x_pppTable[i].netif->name,name,sizeof(name)) == 0))
+ {
+ ppp = &rtl865x_pppTable[i];
+ break;
+ }
+ }
+
+ return ppp;
+
+}
+
+/*
+@func int32 | rtl865x_getPppIdx |get ppp session entry index.
+@parm rtl865x_ppp_t* | ppp | ppp entry.
+@parm int32* | idx | return value for index.
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed.
+@comm
+*/
+int32 rtl865x_getPppIdx(rtl865x_ppp_t *ppp, int32 *idx)
+{
+ int32 i = 0;
+ rtl865x_ppp_t *entry;
+ entry = rtl865x_pppTable;
+ for(i = 0; i < PPP_NUMBER; i++,entry++)
+ {
+ if(entry->valid && entry->sessionId == ppp->sessionId)
+ {
+ if(idx)
+ *idx = i;
+ return SUCCESS;
+ }
+ }
+
+ return FAILED;
+}
+
+/*
+int32 rtl865x_printPpp(void)
+{
+ int i;
+ for(i = 0; i < PPP_NUMBER; i++)
+ {
+ printk("====idx(%d),rtl865x_pppTable.valid(%d),refcnt(%d),session(%d),type(%d)\n", i,rtl865x_pppTable[i].valid,rtl865x_pppTable[i].refCnt,rtl865x_pppTable[i].sessionId,rtl865x_pppTable[i].type);
+ }
+ return SUCCESS;
+}
+*/
+
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ppp_local.h b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ppp_local.h new file mode 100644 index 000000000..d38abb4a5 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_ppp_local.h @@ -0,0 +1,33 @@ +/* + * Copyright c Realtek Semiconductor Corporation, 2008 + * All rights reserved. + * + * Program : ppoe table driver + * Abstract : + * Author : hyking (hyking_liu@realsil.com.cn) + */ +#ifndef RTL865X_PPP_LOCAL_H +#define RTL865X_PPP_LOCAL_H + +typedef struct rtl865x_ppp_s +{ + rtl865x_netif_local_t *netif; /*dest network interface*/ + ether_addr_t server_mac; /*server mac address*/ + uint32 sessionId; + uint16 valid:1, + type:5; /*PPPOE, PPTP, L2TP */ + + uint16 refCnt; +} rtl865x_ppp_t; + +int32 rtl865x_getPppIdx(rtl865x_ppp_t *entry, int32 *idx); +int32 rtl865x_getPppBySessionId(uint32 sessionId,rtl865x_ppp_t *entry); +rtl865x_ppp_t* rtl865x_getPppByNetifName(char *name); + +int32 rtl865x_initPppTable(void); +int32 rtl865x_reinitPppTable(void); +int32 rtl865x_referPpp(uint32 sessionId); +int32 rtl865x_deReferPpp(uint32 sessionId); + + +#endif diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_route.c b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_route.c new file mode 100644 index 000000000..04e63d001 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_route.c @@ -0,0 +1,970 @@ +/*
+* Copyright c Realtek Semiconductor Corporation, 2008
+* All rights reserved.
+*
+* Program : route table driver
+* Abstract :
+* Author : hyking (hyking_liu@realsil.com.cn)
+*/
+/* @doc RTL_LAYEREDDRV_API
+
+ @module rtl865x_route.c - RTL865x Home gateway controller Layered driver API documentation |
+ This document explains the API interface of the table driver module. Functions with rtl865x prefix
+ are external functions.
+ @normal Hyking Liu (Hyking_liu@realsil.com.cn) <date>
+
+ Copyright <cp>2008 Realtek<tm> Semiconductor Cooperation, All Rights Reserved.
+
+ @head3 List of Symbols |
+ Here is a list of all functions and variables in this module.
+
+ @index | RTL_LAYEREDDRV_API
+*/
+#include <net/rtl/rtl_types.h>
+#include <net/rtl/rtl_glue.h>
+//#include <net/rtl/rtl865x_ppp.h>
+#include <net/rtl/rtl865x_netif.h>
+#include "common/rtl_errno.h"
+//#include "rtl_utils.h"
+#include "common/rtl865x_netif_local.h"
+#include "rtl865x_ppp_local.h"
+#include "rtl865x_route.h"
+#include "rtl865x_ip.h"
+#include "rtl865x_nexthop.h"
+#include "rtl865x_arp.h"
+
+//#include "common/rtl_glue.h"
+#include "common/rtl865x_eventMgr.h" /*call back function....*/
+#include "common/rtl865x_vlan.h"
+#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER
+#include "AsicDriver/rtl865x_asicCom.h"
+#include "AsicDriver/rtl865x_asicL2.h"
+#include "AsicDriver/rtl865x_asicL3.h"
+#else
+#include "AsicDriver/rtl865xC_tblAsicDrv.h"
+#endif
+#include "l2Driver/rtl865x_fdb.h"
+#include "AsicDriver/rtl865xc_asicregs.h"
+#include <net/rtl/rtl865x_fdb_api.h>
+
+static rtl865x_route_t *rtl865x_route_freeHead;
+static rtl865x_route_t *rtl865x_route_inusedHead;
+static RTL_DECLARE_MUTEX(route_sem);
+
+#if 0
+void _rtl865x_route_print(void)
+{
+ int32 i;
+ rtl865x_route_t *rt = NULL;
+ rt = rtl865x_route_inusedHead;
+
+ printk("=============inused list:\n");
+ while(rt)
+ {
+ printk("asicIdx(%d),ip(0x%x),mask(0x%x),nextHop(0x%x),process(0x%x),dst(%s) valid(%d)\n",rt->asicIdx, rt->ipAddr,rt->ipMask,rt->nextHop,rt->process,rt->dstNetif->name,rt->valid);
+ rt = rt->next;
+ }
+
+ i = 0;
+ rt = rtl865x_route_freeHead;
+ while(rt)
+ {
+ i++;
+ rt = rt->next;
+ }
+
+ printk("=======free list count(%d)\n",i);
+}
+#endif
+
+
+static rtl865x_route_t* _rtl865x_getDefaultRoute(void)
+{
+ rtl865x_route_t *rt = NULL;
+ rt = rtl865x_route_inusedHead;
+
+ while(rt)
+ {
+ if((rt->valid==1)&&(rt->asicIdx == RT_ASIC_ENTRY_NUM -1))
+ return rt;
+ rt = rt->next;
+ }
+
+ return NULL;
+}
+
+static rtl865x_route_t* _rtl865x_getRouteEntry(ipaddr_t ipAddr, ipaddr_t ipMask)
+{
+ rtl865x_route_t *rt = NULL;
+ rt = rtl865x_route_inusedHead;
+
+ while(rt)
+ {
+ if((rt->valid==1)&&((rt->ipAddr&rt->ipMask)==(ipAddr&ipMask))&&(rt->ipMask==ipMask))
+ return rt;
+ rt = rt->next;
+ }
+ return NULL;
+}
+
+
+static int32 _rtl865x_synRouteToAsic(rtl865x_route_t *rt_t)
+{
+ int32 ret = FAILED;
+ rtl865x_tblAsicDrv_routingParam_t asic_t;
+ rtl865x_tblAsicDrv_l2Param_t asic_l2;
+ rtl865x_netif_local_t *dstNetif = NULL;
+ uint32 columIdx,fid;
+ int32 pppIdx = 0;
+
+ bzero(&asic_t, sizeof(rtl865x_tblAsicDrv_routingParam_t));
+
+ if(rt_t == NULL)
+ {
+ printk("%s(%d):NULL!!!!!!!!!!!!!!!!\n",__FUNCTION__,__LINE__);
+ }
+ /*common information*/
+ asic_t.ipAddr = rt_t->ipAddr;
+ asic_t.ipMask = rt_t->ipMask;
+ asic_t.ipAddr = rt_t->ipAddr;
+ asic_t.ipMask = rt_t->ipMask;
+ /*if the dstNetif is attach on another interface, the netifIdx should the master interface's index*/
+ if(rt_t->dstNetif->is_slave == 1)
+ {
+ //printk("========%s(%d), ip(0x%x),mask(0x%x),netif(%s)\n",__FUNCTION__,__LINE__,rt_t->ipAddr,rt_t->ipMask,rt_t->dstNetif->name);
+ dstNetif = _rtl865x_getNetifByName(rt_t->dstNetif->name);
+ if(dstNetif == NULL)
+ dstNetif = _rtl865x_getDefaultWanNetif();
+ }
+ else
+ dstNetif = rt_t->dstNetif;
+
+ if(dstNetif == NULL)
+ printk("%s(%d) BUG!!!!!!\n",__FUNCTION__,__LINE__);
+
+ asic_t.vidx = dstNetif->asicIdx;
+ asic_t.internal = rt_t->dstNetif->is_wan? 0 : 1;
+ asic_t.DMZFlag = rt_t->dstNetif->dmz? 1 : 0;
+ asic_t.process = rt_t->process;
+
+ switch (rt_t->process)
+ {
+ case RT_PPPOE:
+ ret = rtl865x_getPppIdx(rt_t->un.pppoe.pppInfo, &pppIdx);
+
+ asic_t.pppoeIdx = pppIdx;
+ /*
+ *if process==RT_PPPOE, the mac address of pppoe server is add in pppoe module,
+ *so, we read the FDB information directly....
+ */
+ ret = rtl865x_getVlanFilterDatabaseId(rt_t->dstNetif->vid,&fid);
+ ret = rtl865x_Lookup_fdb_entry(fid, (ether_addr_t *)rt_t->un.pppoe.macInfo, FDB_DYNAMIC, &columIdx,&asic_l2);
+
+ if(ret != SUCCESS)
+ printk("can't get l2 entry by mac.....\n");
+
+ /*FIXME_hyking: update mac/fdb table reference count*/
+ asic_t.nextHopRow = rtl8651_filterDbIndex( rt_t->un.pppoe.macInfo,fid);
+ asic_t.nextHopColumn = columIdx;
+ break;
+
+ case RT_L2:
+ /*
+ * NOTE:this type not used now...
+ * if we want to use it, please add FDB entry to sure this L2 entry in both software FDB table and Asic L2 table.
+ */
+ ret = rtl865x_getVlanFilterDatabaseId(rt_t->dstNetif->vid,&fid);
+ ret = rtl865x_Lookup_fdb_entry(fid, (ether_addr_t *)rt_t->un.direct.macInfo, FDB_STATIC, &columIdx,&asic_l2);
+ if(ret != SUCCESS)
+ printk("can't get l2 entry by mac.....\n");
+
+ /*FIXME_hyking: update mac/fdb table reference count*/
+ asic_t.nextHopRow = rtl8651_filterDbIndex(rt_t->un.direct.macInfo,fid);
+ asic_t.nextHopColumn = columIdx;
+
+ break;
+
+ case RT_ARP:
+ /*FIXME_hyking: update arp table reference count??*/
+ asic_t.arpStart = rt_t->un.arp.arpsta;
+ asic_t.arpEnd = rt_t->un.arp.arpend;
+ asic_t.arpIpIdx = rt_t->un.arp.arpIpIdx;
+ break;
+
+ case RT_CPU:
+ case RT_DROP:
+ /*do nothing*/
+ break;
+
+ case RT_NEXTHOP:
+ asic_t.nhStart = rt_t->un.nxthop.nxtHopSta;
+ asic_t.nhNum = rt_t->un.nxthop.nxtHopEnd - rt_t->un.nxthop.nxtHopSta + 1;
+ asic_t.nhNxt = asic_t.nhStart;
+ asic_t.ipDomain = rt_t->un.nxthop.ipDomain;
+ asic_t.nhAlgo = rt_t->un.nxthop.nhalog;
+
+ break;
+
+ default:
+ printk("Process_Type(%d) is not support!\n",rt_t->process);
+ }
+
+ if(rt_t->asicIdx > RT_ASIC_ENTRY_NUM-1)
+ {
+ printk("BUG!! %s(%d)....", __FUNCTION__,__LINE__);
+ return FAILED;
+ }
+
+ ret = rtl8651_setAsicRouting(rt_t->asicIdx, &asic_t);
+
+ return ret;
+
+}
+
+static int32 _rtl865x_updateDefaultRoute(rtl865x_route_t *rt, int32 action)
+{
+ int32 i;
+ rtl865x_route_t *entry;
+ int32 retval = FAILED;
+
+ entry = rt;
+ if(entry == NULL)
+ return RTL_EINVALIDINPUT;
+
+ /*delete nexthop which is add by default route*/
+ if(rt->process == RT_NEXTHOP)
+ for ( i = entry->un.nxthop.nxtHopSta; i <= entry->un.nxthop.nxtHopEnd && entry->un.nxthop.nxtHopEnd != 0; i++)
+ {
+ retval = rtl865x_delNxtHop(NEXTHOP_L3, i);
+ }
+
+ entry->un.nxthop.nxtHopSta = 0;
+ entry->un.nxthop.nxtHopEnd = 0;
+ switch(action)
+ {
+ case RT_DEFAULT_RT_NEXTHOP_CPU:
+ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)entry, entry->dstNetif, 0,entry->srcIp);
+ break;
+
+ case RT_DEFAULT_RT_NEXTHOP_NORMAL:
+ {
+ rt->process = RT_NEXTHOP;
+ switch(rt->dstNetif->if_type)
+ {
+ case IF_ETHER:
+ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, rt->dstNetif, rt->nextHop,entry->srcIp);
+ break;
+ case IF_PPPOE:
+ {
+ rtl865x_ppp_t *pppoe;
+
+ pppoe = rtl865x_getPppByNetifName(rt->dstNetif->name);
+
+ if(pppoe != NULL)
+ {
+ /*got pppoe session*/
+ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, rt->dstNetif, pppoe->sessionId,entry->srcIp);
+ }
+ else
+ /*nexthop's action is to CPU*/
+ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, rt->dstNetif, 0,entry->srcIp);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ retval = _rtl865x_synRouteToAsic(entry);
+
+ return retval;
+}
+
+static int32 _rtl865x_arrangeRoute(rtl865x_route_t *start_rt, int32 start_idx)
+{
+ int32 count;
+ rtl865x_route_t *rt = NULL;
+
+ rt = start_rt;
+ count = 0;
+ while(rt)
+ {
+ if(rt->valid)
+ {
+ /*if the rule is default route...*/
+ if(rt->ipMask == 0)
+ rt->asicIdx = RT_ASIC_ENTRY_NUM-1;
+ else
+ {
+ /* entry number more than asic table's capacity*/
+ /* entry index=RT_ASIC_ENTRY_NUM-1 is reserved for default route*/
+ if((start_idx + count > RT_ASIC_ENTRY_NUM-2))
+ break;
+
+ /*delete old asic entry firstly...*/
+ if(start_idx+count < rt->asicIdx && rt->asicIdx < RT_ASIC_ENTRY_NUM-1)
+ rtl8651_delAsicRouting(rt->asicIdx);
+
+ rt->asicIdx = start_idx+count;
+ _rtl865x_synRouteToAsic(rt);
+ }
+ }
+
+ /*next entry*/
+ rt= rt->next;
+ count++;
+ }
+
+
+ /*more route entry need to add?*/
+ if(rt)
+ {
+ /*not enough asic table entry! have to update default route's action TOCPU*/
+ rt = _rtl865x_getDefaultRoute();
+ _rtl865x_updateDefaultRoute(rt, RT_DEFAULT_RT_NEXTHOP_CPU);
+ }
+ else
+ {
+ rt = _rtl865x_getDefaultRoute();
+ _rtl865x_updateDefaultRoute(rt, RT_DEFAULT_RT_NEXTHOP_NORMAL);
+ }
+
+ return SUCCESS;
+}
+
+static int32 _rtl865x_addRouteToInusedList(rtl865x_route_t *rt)
+{
+ int32 retval = FAILED;
+ int32 start_idx = 0;
+ rtl865x_route_t *entry,*fore_rt,*start_rt;
+
+ fore_rt = NULL;
+ entry = rtl865x_route_inusedHead;
+
+ /*always set 0x0f when init..., this value would be reset in arrange route*/
+ rt->asicIdx = 0x0f;
+ rt->next = NULL;
+
+ /*find the right position...*/
+ while(entry)
+ {
+ if(entry->valid == 1)
+ {
+ if(entry->ipMask < rt->ipMask)
+ {
+ break;
+ }
+ }
+ fore_rt = entry;
+ entry = entry->next;
+ }
+
+ /*insert this rule after insert_entry*/
+ if(fore_rt)
+ {
+ rt->next = fore_rt->next;
+ fore_rt->next = rt;
+ start_idx = fore_rt->asicIdx+1;
+ start_rt = rt;
+ }
+ else
+ {
+ /*insert head...*/
+ rt->next = rtl865x_route_inusedHead;
+ rtl865x_route_inusedHead = rt;
+
+ start_idx = 0;
+ start_rt = rtl865x_route_inusedHead;
+ }
+
+ retval = _rtl865x_arrangeRoute(start_rt, start_idx);
+
+ //_rtl865x_route_print();
+ return retval;
+
+}
+
+static int32 _rtl865x_delRouteFromInusedList(rtl865x_route_t * rt)
+{
+ int32 retval,start_idx;
+ rtl865x_route_t *fore_rt = NULL,*entry = NULL,*start_rt = NULL;
+
+ entry = rtl865x_route_inusedHead;
+ while(entry)
+ {
+ if(entry == rt)
+ break;
+
+ fore_rt = entry;
+ entry = entry->next;
+ }
+
+ /*fore_rt == NULL means delete list head*/
+ if(fore_rt == NULL)
+ {
+ rtl865x_route_inusedHead = rtl865x_route_inusedHead->next;
+ start_rt = rtl865x_route_inusedHead;
+ start_idx = 0;
+ }
+ else
+ {
+ fore_rt->next = rt->next;
+ start_rt = fore_rt->next;
+ start_idx = fore_rt->asicIdx + 1;
+ }
+
+ /*delete route from asic*/
+ if(rt->asicIdx < RT_ASIC_ENTRY_NUM)
+ rtl8651_delAsicRouting(rt->asicIdx);
+
+ retval = _rtl865x_arrangeRoute(start_rt, start_idx);
+ rt->asicIdx = 0x0f;
+
+ //_rtl865x_route_print();
+
+ return retval;
+
+}
+
+
+static int32 _rtl865x_usedNetifInRoute(int8 *ifname)
+{
+
+ rtl865x_route_t *rt = NULL;
+ rt = rtl865x_route_inusedHead;
+
+ while(rt)
+ {
+ if(memcmp(rt->dstNetif->name,ifname,strlen(ifname)) == 0)
+ return SUCCESS;
+ rt = rt->next;
+ }
+ return FAILED;
+}
+
+static int32 _rtl865x_addRoute(ipaddr_t ipAddr, ipaddr_t ipMask, ipaddr_t nextHop, int8 * ifName,ipaddr_t srcIp)
+{
+ rtl865x_netif_local_t *netif = NULL;
+ rtl865x_route_t *rt = NULL,*tmp_rt = NULL;
+ int32 idx;
+ int32 netSize = 0, usedArpCnt = 0;
+ int32 retval = FAILED;
+
+ /*para check*/
+ if(ifName == NULL)
+ netif = _rtl865x_getDefaultWanNetif();
+ else
+ netif = _rtl865x_getSWNetifByName(ifName);
+
+ if(netif == NULL)
+ return RTL_EINVALIDINPUT;
+
+ if(netif->if_type == IF_NONE)
+ return RTL_ENOLLTYPESPECIFY;
+
+ idx = 0;
+ for(idx = 0; idx < 32; idx++)
+ if((1<<idx) & ipMask)
+ break;
+
+ netSize = 1<<idx;
+
+ if(netSize > RT_MAX_ARP_SIZE)
+ return RTL_EINVALIDINPUT;
+
+
+ /*
+ *duplicate entry check:
+ * in Driver system, default route is always exist.
+ * so if ipMask == 0, it's means that default route should be update...
+ */
+ if(ipMask != 0 && (rt = _rtl865x_getRouteEntry(ipAddr, ipMask)) != NULL)
+ {
+ //rt->ref_count++;
+ return RTL_EENTRYALREADYEXIST;
+ }
+
+ /*add default route: just update the default route becase the default route always exist!*/
+ if(ipMask == 0)
+ {
+ rt = _rtl865x_getDefaultRoute();
+ /*deference rt's orginal netif*/
+ if(rt && rt->dstNetif)
+ rtl865x_deReferNetif(rt->dstNetif->name);
+ }
+
+ /*allocate a new buffer for adding entry*/
+ if(rt == NULL)
+ {
+ rt = rtl865x_route_freeHead;
+
+ if(rt)
+ {
+ rtl865x_route_freeHead = rt->next;
+
+ }
+ }
+
+ if(rt == NULL)
+ {
+ /*no buffer, default route should be TOCPU?*/
+ return RTL_ENOFREEBUFFER;
+ }
+
+
+ /*common information*/
+ rt->ipAddr = ipAddr & ipMask;
+ rt->ipMask = ipMask;
+ rt->nextHop = nextHop;
+ rt->srcIp = srcIp;
+ rt->dstNetif = netif;
+
+ /*don't specify the nexthop ip address, it's means that:
+ * all packet match this route entry should be forward by network interface with arp
+ */
+
+ if(nextHop == 0 && ipMask != 0)
+ {
+ switch(netif->if_type)
+ {
+ case IF_ETHER:
+
+ rt->process = RT_ARP;
+ tmp_rt = rtl865x_route_inusedHead;
+ while(tmp_rt)
+ {
+ if(tmp_rt->valid && tmp_rt->process == RT_ARP && tmp_rt->dstNetif == netif)
+ usedArpCnt += tmp_rt->un.arp.arpend - tmp_rt->un.arp.arpend + 1;
+
+ tmp_rt = tmp_rt->next;
+ }
+
+ if((usedArpCnt + netSize) > RT_MAX_ARP_SIZE)
+ {
+ printk("!!!!ERROR!!!usedArp(%d),netsize(%d)\n",usedArpCnt,netSize);
+ goto addFailed;
+ }
+
+ /*allocate arp entry for this route rule...*/
+
+ retval = rtl865x_arp_tbl_alloc(rt);
+ if( retval != SUCCESS)
+ {
+ printk("error!!can't allocate arp for this route entry....retval(%d)\n",retval);
+ goto addFailed;
+ }
+
+ rt->un.arp.arpIpIdx = 0; /*FIXME_hyking[this field is invalid, right?]*/
+
+ break;
+
+ case IF_PPPOE:
+ {
+ rtl865x_ppp_t *ppp = NULL;
+
+ rt->process = RT_PPPOE;
+ ppp = rtl865x_getPppByNetifName(netif->name);
+
+ if(ppp == NULL)
+ {
+ printk("error!!can't get pppoe session information by interface name(%s)\n",netif->name);
+ goto addFailed;
+ }
+
+ rt->un.pppoe.macInfo = &ppp->server_mac;
+ rt->un.pppoe.pppInfo = ppp;
+
+ /*update reference...*/
+ rtl865x_referPpp(ppp->sessionId);
+ }
+ break;
+ case IF_PPTP:
+ case IF_L2TP:
+ {
+ rtl865x_ppp_t *ppp = NULL;
+
+ rt->process = RT_L2;
+ ppp = rtl865x_getPppByNetifName(netif->name);
+
+ if(ppp == NULL)
+ {
+ /*printk("Warning!!CAn't get pptp/l2tp session information by interface name(%s)\n",netif->name);*/
+ goto addFailed;
+ }
+
+ rt->un.direct.macInfo = &ppp->server_mac;
+ }
+ break;
+
+ default:
+ printk("lltype(%d) is not support now....\n",netif->if_type);
+ goto addFailed;
+ }
+
+ }
+ else
+ {
+ /*if default is valid, delete nexthop firstly...*/
+ if(rt->valid == 1 && rt->process == RT_NEXTHOP)
+ {
+ int i;
+ for ( i = rt->un.nxthop.nxtHopSta; i <= rt->un.nxthop.nxtHopEnd; i++)
+ {
+ retval = rtl865x_delNxtHop(NEXTHOP_L3, i);
+ }
+ }
+
+ /*use nexthop type*/
+ rt->process = RT_NEXTHOP;
+ switch(netif->if_type)
+ {
+ case IF_ETHER:
+ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, netif, nextHop,srcIp);
+ break;
+ case IF_PPPOE:
+ case IF_PPTP:
+ case IF_L2TP:
+ {
+ rtl865x_ppp_t *pppoe;
+
+ pppoe = rtl865x_getPppByNetifName(netif->name);
+
+ if(pppoe != NULL)
+ {
+ /*got pppoe session*/
+ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, netif, pppoe->sessionId,srcIp);
+ }
+ else
+ /*nexthop's action is to CPU*/
+ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, netif, 0,srcIp);
+ }
+ break;
+
+ default:
+ retval = FAILED;
+ break;
+
+ }
+
+ if(retval != SUCCESS)
+ {
+ printk("error!!add nexthop error! retval (%d)\n",retval);
+ goto addFailed;
+ }
+ rt->un.nxthop.nhalog = RT_ALOG_SIP; /* use per-source IP */
+ rt->un.nxthop.ipDomain = RT_DOMAIN_16_1;
+ }
+
+ rt->valid = 1;
+ rt->ref_count = 1;
+ /*update reference....*/
+ rtl865x_referNetif(netif->name);
+ if(ipMask == 0)
+ _rtl865x_setDefaultWanNetif(netif->name);
+
+ /**/
+ if(rt->asicIdx == RT_ASIC_ENTRY_NUM-1)
+ {
+ retval = _rtl865x_synRouteToAsic(rt);
+ }
+ else
+ {
+ /*insert the adding route to inused list*/
+ retval = _rtl865x_addRouteToInusedList(rt);
+ }
+
+ /*if route is add, please enable Routing for the releated netif*/
+ retval = rtl865x_enableNetifRouting(netif);
+ return retval;
+
+addFailed:
+ if(rt->asicIdx == RT_ASIC_ENTRY_NUM -1)
+ {
+ _rtl865x_updateDefaultRoute(rt, RT_DEFAULT_RT_NEXTHOP_CPU);
+ }
+ else
+ {
+ /*free this route entry and return error code...*/
+ memset(rt,0,sizeof(rtl865x_route_t));
+ rt->next = rtl865x_route_freeHead;
+ rtl865x_route_freeHead = rt;
+ }
+ return retval;
+
+}
+
+static int32 _rtl865x_delRoute( ipaddr_t ipAddr, ipaddr_t ipMask )
+{
+ rtl865x_route_t *entry;
+ int32 i;
+ int32 retval = 0;
+
+ entry = _rtl865x_getRouteEntry(ipAddr, ipMask);
+
+ if(entry == NULL)
+ return RTL_EENTRYNOTFOUND;
+
+ if(entry->asicIdx == RT_ASIC_ENTRY_NUM-1)
+ {
+ /*if default route
+ * 1. reset default route
+ * 2. reset entry->netif...
+ */
+ rtl865x_netif_local_t *netif = NULL;
+ _rtl865x_clearDefaultWanNetif(entry->dstNetif->name);
+
+ netif = _rtl865x_getDefaultWanNetif();
+ if(netif==NULL)
+ {
+ return RTL_EINVNETIFNAME;
+ }
+
+ if(netif != entry->dstNetif)
+ {
+ rtl865x_deReferNetif(entry->dstNetif->name);
+ entry->dstNetif = netif;
+ rtl865x_referNetif(netif->name);
+ }
+
+ retval = _rtl865x_updateDefaultRoute(entry, RT_DEFAULT_RT_NEXTHOP_CPU);
+ }
+ else
+ {
+ /*not default route*/
+ switch(entry->process)
+ {
+ case RT_PPPOE:
+ {
+ rtl865x_ppp_t *ppp = entry->un.pppoe.pppInfo;
+ if(ppp)
+ rtl865x_deReferPpp(ppp->sessionId);
+ }
+ break;
+ case RT_L2:
+ /*
+ * NOTE:this type not used now...
+ * if we want to use it, please DELETE FDB entry to sure this L2 entry is deleted both software FDB table and Asic L2 table.
+ */
+ break;
+ case RT_ARP:
+ /*free arp*/
+ retval = rtl865x_arp_tbl_free(entry);
+ if( retval != SUCCESS)
+ {
+ printk("======error!!can't FREE arp entry for this route entry....retval(%d)\n",retval);
+ }
+ break;
+
+ case RT_CPU:
+ case RT_DROP:
+ /*do nothing*/
+
+ break;
+
+ case RT_NEXTHOP:
+ /*delete nexthop which is add by l3*/
+ for ( i = entry->un.nxthop.nxtHopSta; i <= entry->un.nxthop.nxtHopEnd; i++)
+ {
+ retval = rtl865x_delNxtHop(NEXTHOP_L3, i);
+ }
+ break;
+ }
+
+ /*FIXME_hyking: update netif reference count*/
+ rtl865x_deReferNetif(entry->dstNetif->name);
+
+
+ /*remove from inused list...*/
+ _rtl865x_delRouteFromInusedList(entry);
+
+ if(_rtl865x_usedNetifInRoute(entry->dstNetif->name) == FAILED)
+ rtl865x_disableNetifRouting(entry->dstNetif);
+
+ /*add to free list*/
+ memset(entry,0,sizeof(rtl865x_route_t));
+ entry->next = rtl865x_route_freeHead;
+ rtl865x_route_freeHead = entry;
+
+ retval = SUCCESS;
+ }
+
+ //_rtl865x_route_print();
+ return retval;
+
+}
+
+rtl865x_route_t* _rtl85x_getRouteEntry(ipaddr_t dst)
+{
+ rtl865x_route_t *tmpRtEntry = NULL;
+ rtl865x_route_t *rt=rtl865x_route_inusedHead;
+ uint32 mask;
+
+ mask = 0;
+ while(rt)
+ {
+ if (rt->valid == 1 && rt->ipAddr == (rt->ipMask & dst) && mask <= rt->ipMask) {
+ mask = rt->ipMask;
+ tmpRtEntry = rt;
+ }
+ rt = rt->next;
+ }
+ return tmpRtEntry;
+}
+
+/*
+@func int32 | rtl865x_addRoute |add a route entry.
+@parm ipaddr_t | ipAddr | ip address.
+@parm ipaddr_t | ipMask | ip mask.
+@parm ipaddr_t | nextHop | the route's next hop.
+@parm int8* | ifName | destination network interface.
+@parm ipaddr_t | srcIp |source IP
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed.
+@rvalue RTL_EINVALIDINPUT | invalid input.
+@rvalue RTL_ENOLLTYPESPECIFY | network interface's link type is not specified.
+@rvalue RTL_EENTRYALREADYEXIST | route entry is already exist.
+@rvalue RTL_ENOFREEBUFFER | not enough memory in system.
+@comm
+ if ifName=NULL, it means the destionation network interface of route entry with ip/ipMask/nextHop is default wan.
+*/
+int32 rtl865x_addRoute(ipaddr_t ipAddr, ipaddr_t ipMask, ipaddr_t nextHop,int8 * ifName,ipaddr_t srcIp)
+{
+ int32 retval = 0;
+ unsigned long flags;
+ //printk("========%s(%d), ip(0x%x),mask(0x%x),ifname(%s),nxthop(0x%x)\n",__FUNCTION__,__LINE__,ipAddr,ipMask,ifName,nextHop);
+ //rtl_down_interruptible(&route_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_addRoute(ipAddr,ipMask,nextHop,ifName,srcIp);
+ //rtl_up(&route_sem);
+ local_irq_restore(flags);
+ //printk("========%s(%d), ip(0x%x),mask(0x%x),ifname(%s),nxthop(0x%x),retval(%d)\n",__FUNCTION__,__LINE__,ipAddr,ipMask,ifName,nextHop,retval);
+ //_rtl865x_route_print();
+ return retval;
+}
+/*
+@func int32 | rtl865x_delRoute |delete a route entry.
+@parm ipaddr_t | ipAddr | ipAddress.
+@parm ipaddr_t | ipMask | ipMask.
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed.
+@rvalue RTL_EENTRYNOTFOUND | not found the entry.
+@comm
+*/
+int32 rtl865x_delRoute(ipaddr_t ipAddr, ipaddr_t ipMask)
+{
+
+ int32 retval = 0;
+ unsigned long flags;
+ //printk("========%s(%d), ip(0x%x),mask(0x%x)\n",__FUNCTION__,__LINE__,ipAddr,ipMask);
+ //rtl_down_interruptible(&route_sem);
+ local_irq_save(flags);
+ retval = _rtl865x_delRoute(ipAddr,ipMask);
+ //rtl_up(&route_sem);
+ local_irq_restore(flags);
+ //printk("==================================retval(%d)\n",retval);
+ return retval;
+
+}
+
+/*
+@func int32 | rtl865x_getRouteEntry |according the destination ip address, get the matched route entry.
+@parm ipaddr_t | dst | destionation ip address.
+@parm rtl865x_route_t* | rt | retrun value: route entry pointer
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed.
+@comm
+*/
+int32 rtl865x_getRouteEntry(ipaddr_t dst,rtl865x_route_t *rt)
+{
+ int32 retval = FAILED;
+ rtl865x_route_t *ret_entry = NULL;
+
+ ret_entry = _rtl85x_getRouteEntry(dst);
+ if(ret_entry && rt)
+ {
+ memcpy(rt,ret_entry,sizeof(rtl865x_route_t));
+ retval = SUCCESS;
+ }
+ return retval;
+}
+
+/*
+@func int32 | rtl865x_initRouteTable |initialize route tabel.
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed.
+@comm
+*/
+int32 rtl865x_initRouteTable(void)
+{
+ int32 i;
+ rtl865x_route_t *rt;
+ rtl865x_route_freeHead = NULL;
+ rtl865x_route_inusedHead = NULL;
+
+ /*malloc buffer*/
+ TBL_MEM_ALLOC(rt, rtl865x_route_t, RT_DRV_ENTRY_NUM);
+ memset(rt,0,sizeof(rtl865x_route_t)*RT_DRV_ENTRY_NUM);
+ for(i = 0; i < RT_DRV_ENTRY_NUM; i++)
+ {
+ rt[i].next = rtl865x_route_freeHead;
+ rtl865x_route_freeHead = &rt[i];
+ }
+
+ return SUCCESS;
+}
+
+/*
+@func int32 | rtl865x_reinitRouteTable |reinitialize route tabel.
+@rvalue SUCCESS | success.
+@rvalue FAILED | failed.
+@comm
+*/
+int32 rtl865x_reinitRouteTable(void)
+{
+ rtl865x_route_t *rt;
+
+ rt = rtl865x_route_inusedHead;
+ while(rt && rt->asicIdx != RT_ASIC_ENTRY_NUM -1)
+ {
+ _rtl865x_delRoute(rt->ipAddr,rt->ipMask);
+ rt = rtl865x_route_inusedHead;
+ }
+
+ /*delete the last route*/
+ rt = rtl865x_route_inusedHead;
+ if(rt)
+ {
+ /*FIXME_hyking: update netif reference count*/
+ rtl865x_deReferNetif(rt->dstNetif->name);
+
+ /*remove from inused list...*/
+ _rtl865x_delRouteFromInusedList(rt);
+
+ /*add to free list*/
+ memset(rt,0,sizeof(rtl865x_route_t));
+ rt->next = rtl865x_route_freeHead;
+ rtl865x_route_freeHead = rt;
+ }
+ return SUCCESS;
+}
+
+#if defined (CONFIG_RTL_LOCAL_PUBLIC)
+int rtl865x_getLanRoute(rtl865x_route_t routeTbl[], int tblSize )
+{
+ int cnt=0;
+ rtl865x_route_t *rt = NULL;
+ rt = rtl865x_route_inusedHead;
+
+ while(rt)
+ {
+
+ if((rt->valid==1) && (rt->dstNetif->is_wan==0))
+ {
+ memcpy(&routeTbl[cnt], rt, sizeof(rtl865x_route_t) );
+ cnt++;
+ }
+ rt = rt->next;
+ }
+ return cnt;
+}
+#endif
+
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_route.h b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_route.h new file mode 100644 index 000000000..b67ffe941 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_route.h @@ -0,0 +1,97 @@ +/* +* Copyright c Realtek Semiconductor Corporation, 2008 +* All rights reserved. +* +* Program : route table driver +* Abstract : +* Author : hyking (hyking_liu@realsil.com.cn) +*/ +#ifndef RTL865X_ROUTE_H +#define RTL865X_ROUTE_H +#include <net/rtl/rtl865x_route_api.h> + +typedef struct rtl865x_route_s +{ + struct rtl865x_route_s *next; + ipaddr_t ipAddr; /* Destination IP Address */ + ipaddr_t ipMask; /* Network mask */ + ipaddr_t nextHop; /* next hop IP address */ + ipaddr_t srcIp; /* source IP address,only for multiple wan now*/ + uint32 valid:1, + process:4, /* 000: PPPoE, 001: L2, 010: ARP, 100: CPU, 101: NextHop, 110: Drop*/ + asicIdx:4; + + uint32 ref_count; /*referrence count*/ + rtl865x_netif_local_t *dstNetif; /*destination network interface*/ + + + /* nexthop informaiton */ + union { + struct + { + uint32 arpsta; /* ARP Table Starting address */ + uint32 arpend; /* ARP Table Ending address */ + uint32 arpIpIdx; /* External IP selection index */ + } arp; + + struct + { + void *macInfo; /*direct nexthop's mac information*/ + }direct; + + struct + { + void *macInfo; /*pppoe server's mac information*/ + rtl865x_ppp_t *pppInfo; + }pppoe; + + struct + { + + uint32 nxtHopSta; /* pointer to Nexthop table: starting range */ + uint32 nxtHopEnd; /* pointer to Nexthop table: ending range */ + uint8 nhalog; /* algo. for load balance */ + uint8 ipDomain; /* IP domain */ + } nxthop; + + } un; + +} rtl865x_route_t; + +#define RT_DEFAULT_RT_NEXTHOP_CPU 0x00 +#define RT_DEFAULT_RT_NEXTHOP_NORMAL 0x01 + +/* process: */ +#define RT_PPPOE 0x00 +#define RT_L2 0x01 +#define RT_ARP 0x02 +#define RT_CPU 0x04 +#define RT_NEXTHOP 0x05 +#define RT_DROP 0x06 + +/* nhalog: */ +#define RT_ALOG_PACKET 0x00 +#define RT_ALOG_SESSION 0x01 +#define RT_ALOG_SIP 0x02 + +/* ipDomain: */ +#define RT_DOMAIN_4_1 0x00 +#define RT_DOMAIN_4_2 0x01 +#define RT_DOMAIN_4_3 0x02 +#define RT_DOMAIN_4_4 0x03 +#define RT_DOMAIN_8_1 0x04 +#define RT_DOMAIN_8_2 0x05 +#define RT_DOMAIN_16_1 0x06 + +int32 rtl865x_initRouteTable(void); +int32 rtl865x_reinitRouteTable(void); + +//int32 rtl865x_addRoute(ipaddr_t ipAddr, ipaddr_t ipMask, ipaddr_t nextHop, int8 * ifName); +//int32 rtl865x_delRoute(ipaddr_t ipAddr, ipaddr_t ipMask); +int32 rtl865x_getRouteEntry(ipaddr_t dst, rtl865x_route_t *rt); + +#if defined (CONFIG_RTL_LOCAL_PUBLIC) +int rtl865x_getLanRoute(rtl865x_route_t routeTbl[], int tblSize); +#endif + +#endif |