diff options
author | Roman Yeryomin <roman@advem.lv> | 2012-09-13 00:40:35 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2012-12-03 00:13:21 +0200 |
commit | 5deb3317cb51ac52de922bb55f8492624018906d (patch) | |
tree | c2fbe6346699d9bb0f2100490c3029519bb8fde8 /target/linux/realtek/files/drivers/net/rtl819x/l2Driver | |
parent | 0239d37124f9184b478a42de8a7fa1bc85a6a6fe (diff) |
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/net/rtl819x/l2Driver')
5 files changed, 3855 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/Makefile b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/Makefile new file mode 100644 index 000000000..a9702aaf5 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/Makefile @@ -0,0 +1,50 @@ +# +# 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_fdb.o = -mips16 + #CFLAGS_rtl865x_outputQueue.o = -mips16 +endif + + ifdef CONFIG_RTL_LAYERED_DRIVER_L2 + obj-y := rtl865x_fdb.o + ifdef CONFIG_RTL_HW_QOS_SUPPORT + obj-y += rtl865x_outputQueue.o + endif + endif + +ifeq ($(CONFIG_RTL_STP),y) + obj-y += rtl865x_stp.o +endif +ifeq ($(CONFIG_RTL_HW_STP),y) + obj-y += rtl865x_stp.o +endif + +EXTRA_CFLAGS += -O1 -DRTL_TBLDRV -D__linux__ -mno-memcpy -DRTL865X_OVER_KERNEL -DRTL865X_OVER_LINUX -Werror +#EXTRA_CFLAGS += -I$(DIR_RTLASIC)/AsicDriver +#EXTRA_CFLAGS += -I$(DIR_RTLASIC)/l2Driver +#EXTRA_CFLAGS += -I$(DIR_RTLASIC)/common +#EXTRA_CFLAGS += -I$(DIR_RTLASIC)/cle +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/l2Driver/rtl865x_fdb.c b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_fdb.c new file mode 100644 index 000000000..264dcc06e --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_fdb.c @@ -0,0 +1,2022 @@ +/* @doc RTL_LAYEREDDRV_API + + @module rtl865x_fdb.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 <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> + +#include <net/rtl/rtl_types.h> +#include <net/rtl/rtl_glue.h> +#include <net/rtl/rtl865x_fdb_api.h> +#include "AsicDriver/asicRegs.h" +//#include <common/rtl8651_aclLocal.h> +#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER +//#include <net/rtl/rtl_queue.h> +#include "AsicDriver/rtl865x_asicCom.h" +#include "AsicDriver/rtl865x_asicL2.h" +#else +#include <AsicDriver/rtl865xC_tblAsicDrv.h> +#include <AsicDriver/rtl8651_tblAsicDrv.h> +#include "rtl8651_tblDrvPatch.h" +#endif + +#include <net/rtl/rtl865x_netif.h> +#include "common/rtl865x_eventMgr.h" +#include "common/mbuf.h" +#include "rtl865x_fdb.h" +#include "common/rtl_errno.h" + +#if defined(CONFIG_RTL865X_LANPORT_RESTRICTION) +lan_restrict_info lan_restrict_tbl[LAN_RESTRICT_PORT_NUMBER]; +#endif + +struct rtl865x_L2Tables sw_FDB_Table; +int32 arpAgingTime = 450; +ether_addr_t cpu_mac = { {0x00, 0x00, 0x0a, 0x00, 0x00, 0x0f} }; +rtl865x_tblAsicDrv_l2Param_t tmpL2buff; + +static RTL_DECLARE_MUTEX(l2_sem); +int32 _rtl865x_fdb_alloc(void) +{ + int32 index = 0; + memset( &sw_FDB_Table, 0, sizeof( sw_FDB_Table ) ); + #ifdef __KERNEL__ + TBL_MEM_ALLOC(sw_FDB_Table.filterDB, rtl865x_filterDbTable_t, RTL865x_FDB_NUMBER); + #else + sw_FDB_Table.filterDB = (rtl865x_filterDbTable_t *)malloc(RTL865x_FDB_NUMBER * sizeof(rtl865x_filterDbTable_t)); + #endif + {//Initial free filter database entry + rtl865x_filterDbTableEntry_t * tempFilterDb = NULL; + #ifdef __KERNEL__ + TBL_MEM_ALLOC(tempFilterDb, rtl865x_filterDbTableEntry_t, RTL8651_L2TBL_ROW); + #else + #endif + SLIST_INIT(&sw_FDB_Table.freefdbList.filterDBentry); + for(index=0; index<RTL8651_L2TBL_ROW; index++) + SLIST_INSERT_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, &tempFilterDb[index], nextFDB); + } + + return SUCCESS; + +} + +int32 rtl865x_getReserveMacAddr(ether_addr_t *macAddr) +{ + memcpy( macAddr, &cpu_mac, sizeof(ether_addr_t)); + return SUCCESS; +} + +int32 _rtl865x_layer2_patch(void) +{ + + int32 retval = 0; + ether_addr_t mac = { {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} }; + uint32 portmask=RTL_WANPORT_MASK|RTL_LANPORT_MASK; + + retval = _rtl865x_addFilterDatabaseEntry(RTL865x_L2_TYPEII, RTL_LAN_FID, &mac, FDB_TYPE_TRAPCPU, portmask, TRUE, FALSE); +#if defined (CONFIG_RTL_IVL_SUPPORT) + retval = _rtl865x_addFilterDatabaseEntry(RTL865x_L2_TYPEII, RTL_WAN_FID, &mac, FDB_TYPE_TRAPCPU, portmask, TRUE, FALSE); +#endif + + retval = _rtl865x_addFilterDatabaseEntry(RTL865x_L2_TYPEII, RTL_LAN_FID, &cpu_mac, FDB_TYPE_TRAPCPU, 0, TRUE, FALSE); +#if defined (CONFIG_RTL_IVL_SUPPORT) + retval = _rtl865x_addFilterDatabaseEntry(RTL865x_L2_TYPEII, RTL_WAN_FID, &cpu_mac, FDB_TYPE_TRAPCPU, 0, TRUE, FALSE); +#endif + assert(retval == SUCCESS); + + return SUCCESS; +} + +int32 _rtl865x_fdb_collect(void) +{ + int32 index = 0; + int32 index1 = 0; + + rtl865x_filterDbTable_t *filterDbPtr; + rtl865x_filterDbTableEntry_t * tempFilterDbPtr; + for(index=0,filterDbPtr=&sw_FDB_Table.filterDB[0]; index<RTL865x_FDB_NUMBER; index++,filterDbPtr++) { + for(index1=0; index1<RTL8651_L2TBL_ROW; index1++) + while(SLIST_FIRST(&(filterDbPtr->database[index1]))) { + tempFilterDbPtr = SLIST_FIRST(&(filterDbPtr->database[index1])); + SLIST_REMOVE_HEAD(&(filterDbPtr->database[index1]), nextFDB); + SLIST_INSERT_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, tempFilterDbPtr, nextFDB); + } + } + + return SUCCESS; + +} + +int32 _rtl865x_fdb_init(void) +{ + int32 index, index1; + /*Initial Filter database*/ + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[0]; + for(index=0; index<RTL865x_FDB_NUMBER; index++, fdb_t++) { + for(index1=0; index1<RTL8651_L2TBL_ROW; index1++) + SLIST_INIT(&(fdb_t->database[index1])); + fdb_t->valid = 1; + } + + return SUCCESS; +} + +int32 _rtl865x_clearHWL2Table(void) +{ + int i, j; + + for (i = 0; i < RTL8651_L2TBL_ROW; i++) + for (j = 0; j < RTL8651_L2TBL_COLUMN; j++) + { + rtl8651_delAsicL2Table(i, j); + } + + return SUCCESS; +} + +int32 rtl865x_layer2_init(void) +{ + + _rtl865x_fdb_alloc(); + + _rtl865x_fdb_init(); + + _rtl865x_layer2_patch(); + + return SUCCESS; +} + +int32 rtl865x_layer2_reinit(void) +{ + _rtl865x_clearHWL2Table(); + + _rtl865x_fdb_collect(); + + //_rtl865x_fdb_alloc(); + + _rtl865x_fdb_init(); + + _rtl865x_layer2_patch(); + + return SUCCESS; +} + + uint32 rtl865x_getHWL2Index(ether_addr_t * macAddr, uint16 fid) + { + return (rtl8651_filterDbIndex(macAddr, fid)); + } + +int32 rtl865x_setHWL2Table(uint32 row, uint32 column, rtl865x_tblAsicDrv_l2Param_t *l2p) +{ + return (rtl8651_setAsicL2Table(row, column, l2p)); +} + +int32 rtl865x_getHWL2Table(uint32 row, uint32 column, rtl865x_tblAsicDrv_l2Param_t *l2p) +{ + return rtl8651_getAsicL2Table(row, column, l2p); +} + +int32 rtl865x_refleshHWL2Table(ether_addr_t * macAddr, uint32 flags,uint16 fid) +{ + + rtl865x_tblAsicDrv_l2Param_t L2temp, *L2buff; + uint32 rowIdx, col_num; + uint32 colIdx = 0; + uint32 found = FALSE; + + L2buff = &L2temp; + memset(L2buff, 0, sizeof(rtl865x_tblAsicDrv_l2Param_t)); + rowIdx = rtl8651_filterDbIndex(macAddr, fid); + + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) { + if ((rtl8651_getAsicL2Table(rowIdx, colIdx, L2buff))!=SUCCESS || + memcmp(&(L2buff->macAddr), macAddr, 6)!= 0) + continue; + + if (((flags&FDB_STATIC) && L2buff->isStatic) || + ((flags&FDB_DYNAMIC) && !L2buff->isStatic)) { + assert(colIdx); + col_num = colIdx; + found = TRUE; + break; + } + } + + if (found == TRUE) + { + L2buff->ageSec = 450; + rtl8651_setAsicL2Table(rowIdx, colIdx, L2buff); + return SUCCESS; + } + else + { + return FAILED; + } +} + +int32 rtl_get_hw_fdb_age(uint32 fid,ether_addr_t *mac, uint32 flags) +{ + uint32 rowIdx; + uint32 colIdx = 0; + int32 retval = 0; + rtl865x_tblAsicDrv_l2Param_t L2buff; + + memset(&L2buff,0,sizeof(rtl865x_tblAsicDrv_l2Param_t)); + + rowIdx = rtl8651_filterDbIndex(mac, fid); + + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + retval = rtl8651_getAsicL2Table(rowIdx, colIdx, &L2buff); + + if (retval !=SUCCESS || + memcmp(&(L2buff.macAddr), mac, 6)!= 0) + continue; + if (((flags&FDB_DYNAMIC) && !L2buff.isStatic)||((flags&FDB_STATIC) && L2buff.isStatic)) + { + retval = L2buff.ageSec; + break; + } + + } + + return retval; +} + +int32 rtl865x_Lookup_fdb_entry(uint32 fid, ether_addr_t *mac, uint32 flags, uint32 *col_num, rtl865x_tblAsicDrv_l2Param_t *L2buff) +{ + uint32 rowIdx; + uint32 colIdx; + int32 retval; + + rowIdx = rtl8651_filterDbIndex(mac, fid); + colIdx = 0; + + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + retval = rtl8651_getAsicL2Table(rowIdx, colIdx, L2buff); + + if (retval !=SUCCESS || + memcmp(&(L2buff->macAddr), mac, 6)!= 0) + continue; + if (((flags&FDB_STATIC) && L2buff->isStatic) || + ((flags&FDB_DYNAMIC) && !L2buff->isStatic)) { + assert(colIdx); + *col_num = colIdx; + return SUCCESS; + } + + } + return FAILED; +} + +/* +@func enum RTL_RESULT | rtl865x_addFdbEntry | Add an MAC address, said Filter Database Entry +@parm uint32 | fid | The filter database index (valid: 0~3) +@parm ether_addr_t * | mac | The MAC address to be added +@parm uint32 | portmask | The portmask of this MAC address belongs to +@parm uint32 | type | fdb entry type +@rvalue SUCCESS | Add success +@rvalue FAILED | General failure +@comm + Add a Filter Database Entry to L2 Table(1024-Entry) +@devnote + (under construction) +*/ +int32 rtl865x_addFilterDatabaseEntry( uint32 fid, ether_addr_t * mac, uint32 portmask, uint32 type ) +{ + int32 retval; + unsigned long flags; + if (type != FDB_TYPE_FWD && type != FDB_TYPE_SRCBLK && type != FDB_TYPE_TRAPCPU) + return RTL_EINVALIDINPUT; /* Invalid parameter */ + + if (fid >= RTL865x_FDB_NUMBER) + return RTL_EINVALIDINPUT; + if (mac == (ether_addr_t *)NULL) + return RTL_EINVALIDINPUT; + if (sw_FDB_Table.filterDB[fid].valid == 0) + return RTL_EINVALIDFID; + /*l2 lock*/ + //rtl_down_interruptible(&l2_sem); + local_irq_save(flags); +#ifdef CONFIG_RTL865X_LANPORT_RESTRICTION + retval = _rtl865x_addFilterDatabaseEntry(RTL865x_L2_TYPEII, fid, mac, type, portmask, TRUE, FALSE); +#else + retval = _rtl865x_addFilterDatabaseEntry(RTL865x_L2_TYPEII, fid, mac, type, portmask, FALSE, FALSE); +#endif + /*l2 unlock*/ + //rtl_up(&l2_sem); + local_irq_restore(flags); + return retval; +} + +int32 rtl865x_addFilterDatabaseEntryExtension( uint16 fid, rtl865x_filterDbTableEntry_t * L2entry) +{ + int32 retval; + unsigned long flags; + if (L2entry->process != FDB_TYPE_FWD && L2entry->process != FDB_TYPE_SRCBLK && L2entry->process != FDB_TYPE_TRAPCPU) + return RTL_EINVALIDINPUT; /* Invalid parameter */ + + if (fid >= RTL865x_FDB_NUMBER) + return RTL_EINVALIDINPUT; + if (&(L2entry->macAddr) == (ether_addr_t *)NULL) + return RTL_EINVALIDINPUT; + if (sw_FDB_Table.filterDB[fid].valid == 0) + return RTL_EINVALIDFID; + /*l2 lock*/ + //rtl_down_interruptible(&l2_sem); + local_irq_save(flags); + retval = _rtl865x_addFilterDatabaseEntry( L2entry->l2type, + fid, + &(L2entry->macAddr), + L2entry->process, + L2entry->memberPortMask, + L2entry->auth, + L2entry->SrcBlk); + + /*l2 unlock*/ + //rtl_up(&l2_sem); + local_irq_restore(flags); + return retval; +} + + +#if 0 +int32 rtl865x_addFilterDatabaseEntry( uint32 fid, ether_addr_t * mac, uint32 portmask, uint32 type , uint32 isStatic) +{ + int32 retval; + + if (type != FDB_TYPE_FWD && type != FDB_TYPE_SRCBLK && type != FDB_TYPE_TRAPCPU) + return RTL_EINVALIDINPUT; /* Invalid parameter */ + + if (fid >= RTL865x_FDB_NUMBER) + return RTL_EINVALIDINPUT; + if (mac == (ether_addr_t *)NULL) + return RTL_EINVALIDINPUT; + if (sw_FDB_Table.filterDB[fid].valid == 0) + return RTL_EINVALIDFID; + /*l2 lock*/ + +#ifdef RTL865XC_LAN_PORT_NUM_RESTRIT + retval = _rtl865x_addFilterDatabaseEntry(isStatic == TRUE? RTL865x_L2_TYPEII:RTL865x_L2_TYPEI, fid, mac, type, portmask, TRUE, FALSE); +#else + retval = _rtl865x_addFilterDatabaseEntry(isStatic == TRUE? RTL865x_L2_TYPEII:RTL865x_L2_TYPEI, fid, mac, type, portmask, FALSE, FALSE); + +#endif + /*l2 unlock*/ + + + return retval; +} +#endif + + +int32 _rtl865x_removeFilterDatabaseEntry(uint16 fid, ether_addr_t * mac, uint32 rowIdx) +{ + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[fid]; + rtl865x_filterDbTableEntry_t * l2entry_t ; + + if (SLIST_FIRST(&(fdb_t->database[rowIdx]))) + { + SLIST_FOREACH(l2entry_t, &(fdb_t->database[rowIdx]), nextFDB) + { + if (memcmp(&(l2entry_t->macAddr), mac, 6)== 0) + { + SLIST_REMOVE( + &(fdb_t->database[rowIdx]), + l2entry_t, + rtl865x_filterDbTableEntry_s, + nextFDB + ); + SLIST_INSERT_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, l2entry_t, nextFDB); + + rtl865x_raiseEvent(EVENT_DEL_FDB, (void *)(l2entry_t)); + + return SUCCESS; + } + } + } + + return FAILED; +} + +int32 rtl865x_lookup_FilterDatabaseEntry(uint16 fid, ether_addr_t * mac, rtl865x_filterDbTableEntry_t *l2_entry) +{ + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[fid]; + rtl865x_filterDbTableEntry_t * l2entry_t ; + uint32 rowIdx; + + rowIdx = rtl8651_filterDbIndex(mac, fid); + + if (SLIST_FIRST(&(fdb_t->database[rowIdx]))) + { + SLIST_FOREACH(l2entry_t, &(fdb_t->database[rowIdx]), nextFDB) + { + if (memcmp(&(l2entry_t->macAddr), mac, 6)== 0) + { + l2_entry->asicPos = l2entry_t->asicPos; + l2_entry->auth = l2entry_t->auth; + l2_entry->l2type = l2entry_t->l2type; + l2_entry->linkId = l2entry_t->linkId; + l2_entry->memberPortMask = l2entry_t->memberPortMask; + l2_entry->nhFlag = l2entry_t->nhFlag; + l2_entry->process = l2entry_t->process; + l2_entry->SrcBlk = l2entry_t->SrcBlk; + l2_entry->vid = l2entry_t->vid; + return SUCCESS; + } + } + } + + memset(l2_entry, 0, sizeof(rtl865x_filterDbTableEntry_t)); + return FAILED; +} + +int32 _rtl865x_addFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr, uint32 type, uint32 portMask, uint8 auth, uint8 SrcBlk) +{ + uint32 rowIdx = 0; + uint32 colIdx = 0; + uint32 col_num = 0; + uint32 col_tmp = 0; + uint16 tmp_age = 0xffff; + int32 found = FALSE; + int32 flag = FALSE; + int32 nexthp_flag = FALSE; + int32 isStatic = FALSE; + int32 toCpu = FALSE; + rtl865x_filterDbTableEntry_t * l2entry_t = NULL; + rtl865x_filterDbTableEntry_t *tmpL2; + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[fid]; + rtl865x_tblAsicDrv_l2Param_t l2entry_tmp,*L2buff; + int32 retval = 0; + + L2buff = &l2entry_tmp; + memset(L2buff,0,sizeof(rtl865x_tblAsicDrv_l2Param_t)); + rowIdx = rtl8651_filterDbIndex(macAddr, fid); + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + retval = rtl8651_getAsicL2Table(rowIdx, colIdx, L2buff); + if ((retval)==SUCCESS) + { + /*check whether mac address has been learned to HW or not*/ + if (memcmp(&(L2buff->macAddr), macAddr, 6)== 0) + { + /*the entry has been auto learned*/ + if (L2buff->memberPortMask==portMask) + { + /*the entry has been auto learned */ + found = TRUE; + col_tmp = colIdx; + } + else + /*portmask is different , it should be overwrited*/ + { + found = FALSE; + flag = TRUE; + } + break; + } + /*no matched entry, try get minimum aging time L2 Asic entry*/ + if (tmp_age> L2buff->ageSec) + { + tmp_age = L2buff->ageSec; + col_num = colIdx; + } + } + else + { + /*there is still empty l2 asic entry*/ + flag = TRUE; + break; + } + } + + switch(l2Type) { + case RTL865x_L2_TYPEI: + nexthp_flag = FALSE;isStatic = FALSE; + break; + case RTL865x_L2_TYPEII: + nexthp_flag = TRUE; isStatic = TRUE; + break; + case RTL865x_L2_TYPEIII: + nexthp_flag = FALSE;isStatic = TRUE; + break; + default: assert(0); + } + + switch(type) { + case FDB_TYPE_FWD: + toCpu = FALSE; + break; + case FDB_TYPE_DSTBLK: + toCpu = FALSE; + break; + case FDB_TYPE_SRCBLK: + toCpu = FALSE; + break; + case FDB_TYPE_TRAPCPU: + toCpu = TRUE; + break; + default: assert(0); + } + + if (found == FALSE) + { +#if 0 + /*no empty entry, overwrite the biggest aging time asic l2 entry*/ + if(flag == FALSE) + { + /*delete the biggest aging time software entry*/ + rtl8651_getAsicL2Table(rowIdx, col_num, L2buff); + _rtl865x_removeFilterDatabaseEntry(fid, &(L2buff->macAddr), rowIdx); + + /*overwrite asic entry*/ + rtl8651_setAsicL2Table_Patch( + rowIdx, + col_num, + macAddr, + toCpu, + SrcBlk, + portMask, + arpAgingTime, + isStatic, + nexthp_flag, + fid, + auth); + col_tmp = col_num; + } + else +#endif + /*portmask is different , so it should overwrite the original asic entry. Or there is empty entry, set it to asic*/ + if(flag == TRUE) + { + rtl8651_setAsicL2Table_Patch( + rowIdx, + colIdx, + macAddr, + toCpu, + SrcBlk, + portMask, + arpAgingTime, + isStatic, + nexthp_flag, + fid, + auth); + col_tmp = colIdx; + } + } + /*find the same asic entry, should update the aging time*/ + else + { + rtl8651_setAsicL2Table_Patch( + rowIdx, + col_tmp, + macAddr, + toCpu, + SrcBlk, + portMask, + arpAgingTime, + isStatic, + nexthp_flag, + fid, + auth); + } + +/* + colIdx=0; + + tmpL2 = SLIST_FIRST(&(fdb_t->database[rowIdx])); + tmpL2->nextFDB.sle_next = NULL; + + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + if ((rtl8651_getAsicL2Table(rowIdx, colIdx, L2buff))==SUCCESS) + { + l2entry_t->asicPos =colIdx; + l2entry_t->auth = L2buff->auth; + l2entry_t->configToAsic = 0; + l2entry_t->memberPortMask = L2buff->memberPortMask; + l2entry_t->SrcBlk = L2buff->srcBlk; + memcpy(&l2entry_t->macAddr, &L2buff->macAddr, sizeof(ether_addr_t)); + + tmpL2->nextFDB.sle_next = l2entry_t; + l2entry_t->nextFDB.sle_next = NULL; + tmpL2 = l2entry_t; + } + } +*/ + + if (SLIST_FIRST(&sw_FDB_Table.freefdbList.filterDBentry) == NULL) + return RTL_ENOFREEBUFFER; + + /*config the SW l2 entry */ + l2entry_t = SLIST_FIRST(&sw_FDB_Table.freefdbList.filterDBentry); + SLIST_REMOVE_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, nextFDB); + + l2entry_t->asicPos =col_tmp; + l2entry_t->auth = auth; + l2entry_t->configToAsic = 0; + l2entry_t->memberPortMask = portMask; + l2entry_t->l2type = l2Type; + l2entry_t->nhFlag = nexthp_flag; + + l2entry_t->SrcBlk = FALSE; + memcpy(&l2entry_t->macAddr, macAddr, sizeof(ether_addr_t)); + switch(type) { + case FDB_TYPE_FWD: + l2entry_t->process = FDB_TYPE_FWD; + l2entry_t->memberPortMask = portMask; + break; + case FDB_TYPE_DSTBLK: + l2entry_t->process = FDB_TYPE_DSTBLK; + l2entry_t->memberPortMask = 0; + break; + case FDB_TYPE_SRCBLK: + l2entry_t->process = FDB_TYPE_SRCBLK; + l2entry_t->memberPortMask = 0; + break; + case FDB_TYPE_TRAPCPU: + l2entry_t->process = FDB_TYPE_TRAPCPU; + l2entry_t->memberPortMask = portMask; + break; + default: assert(0); + } + + /*write the SW l2 entry */ + + if (SLIST_FIRST(&(fdb_t->database[rowIdx]))) + { + SLIST_FOREACH(tmpL2, &(fdb_t->database[rowIdx]), nextFDB) + { + if (memcmp(&(tmpL2->macAddr), macAddr, 6)== 0) + { + if( (tmpL2->auth != auth) || + (tmpL2->process != type) || + (tmpL2->SrcBlk != SrcBlk) || + (tmpL2->memberPortMask != portMask) || + (tmpL2->l2type != l2Type) ) + { + tmpL2->auth = auth; + tmpL2->process = type; + tmpL2->SrcBlk = SrcBlk; + tmpL2->memberPortMask = portMask; + tmpL2->l2type = l2Type; + + /*duplicate entry,avoid memory leak*/ + SLIST_INSERT_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, l2entry_t, nextFDB); + break; +/* tmpL2 ->refCount = 1;*/ + } + else + { +/* tmpL2->refCount +=1;*/ + + /*duplicate entry,avoid memory leak*/ + SLIST_INSERT_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, l2entry_t, nextFDB); + return SUCCESS; + } + } + else if (tmpL2->nextFDB.sle_next == NULL) + { +/* l2entry_t ->refCount = 1;*/ + tmpL2->nextFDB.sle_next = l2entry_t; + l2entry_t->nextFDB.sle_next = NULL; + break; + } + } + } + else + { +/* l2entry_t ->refCount = 1;*/ + SLIST_INSERT_HEAD(&(fdb_t->database[rowIdx]), l2entry_t, nextFDB); + } + + /* TypeII entry can not exceed RTL8651_L2TBL_COLUMN */ +/* if (typeII == RTL8651_L2TBL_COLUMN && l2Type == RTL8651_L2_TYPEII) + return RTL_NOFREEBUFFER; +*/ + rtl865x_raiseEvent(EVENT_ADD_FDB, (void *)(l2entry_t)); + + return SUCCESS; +} + +/* +@func int32 | rtl8651_delFilterDatabaseEntry | Remove a filter database entry. +@parm uint16 | fid | Filter database entry. +@parm ether_addr_t * | macAddr | Pointer to a MAC Address. +@rvalue RTL_EINVALIDFID | Filter database ID. +@rvalue RTL_NULLMACADDR | The specified MAC address is NULL. +@rvalue RTL_EINVALIDINPUT | Invalid input parameter. +*/ +int32 rtl865x_delFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr) { + int32 retval; + unsigned long flags; + if (fid >= RTL865x_FDB_NUMBER) + return RTL_EINVALIDINPUT; + if (macAddr == (ether_addr_t *)NULL) + return RTL_EINVALIDINPUT; + if (sw_FDB_Table.filterDB[fid].valid == 0) + return RTL_EINVALIDFID; + +/* L2 lock */ + //rtl_down_interruptible(&l2_sem); + local_irq_save(flags); + retval = _rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEII, fid, macAddr); +/* L2 unlock */ + //rtl_up(&l2_sem); + local_irq_restore(flags); + return retval; +} + +int32 _rtl865x_delFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr) +{ + uint32 rowIdx = 0; + uint32 colIdx = 0; + rtl865x_tblAsicDrv_l2Param_t L2temp, *L2buff ; + rtl865x_filterDbTableEntry_t * l2entry_t = NULL; + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[fid]; + int32 found = FALSE; + + rowIdx = rtl8651_filterDbIndex(macAddr, fid); + + L2buff = &L2temp; + memset(L2buff, 0 , sizeof (rtl865x_tblAsicDrv_l2Param_t)); + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + if ((rtl8651_getAsicL2Table(rowIdx, colIdx, L2buff))==SUCCESS) + { + /*check whether mac address has been learned to SW or not*/ + if (memcmp(&(L2buff->macAddr), macAddr, 6)== 0) + { + /*the entry has been auto learned*/ + found = TRUE; + break; + } + } + } + + /* + when a sta from eth0 to wlan0, the layer driver fdb will be deleted, but linux bridge fdb still exist, + so delete the asic entry anyway to avoid layer connection issue. + eg: + first moment .sta is at eth0 + second moment:connect sta to wlan0, the layer driver fdb will be deleted, but linux bridge fdb still there + third moment:move sta to eth0 again, layer driver fdb won't be created due to linux bridge fdb already exist. + */ + if (found == TRUE) + { + rtl8651_delAsicL2Table(rowIdx, colIdx); + } + + SLIST_FOREACH(l2entry_t, &(fdb_t->database[rowIdx]), nextFDB) + { + if (!memcmp(&l2entry_t->macAddr, macAddr, sizeof(ether_addr_t))) + { + /* l2entry_t->refCount -= 1;*/ + /* if (l2entry_t->refCount == 0)*/ + { + SLIST_REMOVE( + &(fdb_t->database[rowIdx]), + l2entry_t, + rtl865x_filterDbTableEntry_s, + nextFDB + ); + SLIST_INSERT_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, l2entry_t, nextFDB); + + rtl865x_raiseEvent(EVENT_DEL_FDB, (void *)(l2entry_t)); + } + break; + } + } + return SUCCESS; +} + +#ifdef CONFIG_RTL865X_SYNC_L2 +int32 rtl865x_arrangeFdbEntry(const unsigned char *timeout_addr, int32 *port) +{ + int32 found = FAILED; + ether_addr_t *macAddr; + int32 column; + rtl865x_tblAsicDrv_l2Param_t fdbEntry; + rtl865x_filterDbTableEntry_t l2temp_entry; + int32 rowIdx; + + macAddr = (ether_addr_t *)(timeout_addr); + rowIdx = rtl8651_filterDbIndex(macAddr, RTL_LAN_FID); + found = rtl865x_Lookup_fdb_entry(RTL_LAN_FID, macAddr, FDB_DYNAMIC, &column, &fdbEntry); + if (found != SUCCESS) + { + if (rtl865x_lookup_FilterDatabaseEntry(RTL_LAN_FID, macAddr, &l2temp_entry) == SUCCESS) + { +/* printk("\nlook up sw fdb success\n"); + printk("\nport mask is %x\n", l2temp_entry.memberPortMask); +*/ + *port = rtl865x_ConvertPortMasktoPortNum(l2temp_entry.memberPortMask); + return RTL865X_FDBENTRY_TIMEOUT; + } + + } + else + { + if(fdbEntry.ageSec == 450) + { + return RTL865X_FDBENTRY_450SEC; + } + if(fdbEntry.ageSec == 300) + { + return RTL865X_FDBENTRY_300SEC; + } + if(fdbEntry.ageSec == 150) + { + return RTL865X_FDBENTRY_150SEC; + } + } + return FAILED; +} + +void update_hw_l2table(const char *srcName,const unsigned char *addr) +{ + + //int32 found = FAILED; + ether_addr_t *macAddr; + int32 ret = 0; +#if defined (CONFIG_RTL_LAYERED_DRIVER) && defined (CONFIG_RTL_LAYERED_DRIVER_L2) + int32 column; + rtl865x_tblAsicDrv_l2Param_t fdbEntry; +#endif + macAddr = (ether_addr_t *)(addr); + + if (memcmp(srcName, RTL_WLAN_NAME, 4) ==0) + { + +#if defined (CONFIG_RTL_LAYERED_DRIVER) +#if defined (CONFIG_RTL_LAYERED_DRIVER_L2) + if (rtl865x_Lookup_fdb_entry(RTL_LAN_FID, macAddr, FDB_DYNAMIC, &column,&fdbEntry) == SUCCESS) +#endif +#else + if (rtl8651_lookupL2table(0, macAddr, FDB_DYNAMIC) == SUCCESS) +#endif + { + + if((fdbEntry.memberPortMask & RTL8651_PHYSICALPORTMASK)!=0) + { +#if defined (CONFIG_RTL_LAYERED_DRIVER) +#if defined (CONFIG_RTL_LAYERED_DRIVER_L2) + ret = rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEII, RTL_LAN_FID, macAddr); +#endif +#else + ret = rtl8651_delFilterDatabaseEntry(0, macAddr); +#endif + } + + } + +#if defined (CONFIG_RTL_IVL_SUPPORT) + +#if defined (CONFIG_RTL_LAYERED_DRIVER) +#if defined (CONFIG_RTL_LAYERED_DRIVER_L2) + if (rtl865x_Lookup_fdb_entry(RTL_WAN_FID, macAddr, FDB_DYNAMIC, &column,&fdbEntry) == SUCCESS) +#endif +#endif + { + + if((fdbEntry.memberPortMask & RTL8651_PHYSICALPORTMASK)!=0) + { +#if defined (CONFIG_RTL_LAYERED_DRIVER) +#if defined (CONFIG_RTL_LAYERED_DRIVER_L2) + ret = rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEII, RTL_WAN_FID, macAddr); +#endif +#endif + } + + } +#endif + + } + + +} + + +int32 rtl865x_addFDBEntry(const unsigned char *addr) +{ + int32 found = FAILED; + ether_addr_t *macAddr; + int32 ret=FAILED; + int8 port_num = -1; + int32 column; + rtl865x_tblAsicDrv_l2Param_t fdbEntry; + rtl865x_filterDbTableEntry_t l2temp_entry; + + if (addr == NULL) + return RTL_EINVALIDINPUT; + + macAddr = (ether_addr_t *)(addr); + found = rtl865x_Lookup_fdb_entry(RTL_LAN_FID, macAddr, FDB_DYNAMIC, &column, &fdbEntry); + if (found == SUCCESS ) + { + port_num = rtl865x_ConvertPortMasktoPortNum(fdbEntry.memberPortMask); + +/* printk("\nbefore rtl865x_lookup_FilterDatabaseEntry, port is %d\n", port_num); */ + if (rtl865x_lookup_FilterDatabaseEntry(fdbEntry.fid, macAddr, &l2temp_entry) != SUCCESS) + { + 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 = TRUE;*/ +/* l2temp_entry.SrcBlk = FALSE;*/ + memcpy(&(l2temp_entry.macAddr), macAddr, sizeof(ether_addr_t)); + ret =_rtl865x_addFilterDatabaseEntry( l2temp_entry.l2type, + fdbEntry.fid, + &(l2temp_entry.macAddr), + l2temp_entry.process, + l2temp_entry.memberPortMask, + FALSE, + FALSE); + } + } + else + { + /*add */ + } + return ret; +} + + +int32 rtl865x_delLanFDBEntry(uint16 l2Type, const unsigned char *addr) +{ + int32 ret=FAILED; + ether_addr_t *macAddr; + + if (addr == NULL) + { + return RTL_EINVALIDINPUT; + } + macAddr = (ether_addr_t *)(addr); + + ret =_rtl865x_delFilterDatabaseEntry( l2Type, RTL_LAN_FID, macAddr); + + return ret; +} + +int32 rtl865x_ConvertPortMasktoPortNum(int32 portmask) +{ + int32 i = 0; + + for (i = PHY0; i < EXT3; i++) + { + if(((portmask >> i) & 0x01) == 1) + { + return i; + } + } + return FAILED; +} + +#if defined(CONFIG_RTL865X_LANPORT_RESTRICTION) +int32 rtl_check_fdb_entry_check_exist(uint32 fid, ether_addr_t *mac, uint32 flags) +{ + uint32 rowIdx; + uint32 colIdx; + int32 retval; + rtl865x_tblAsicDrv_l2Param_t L2buff; + + rowIdx = rtl8651_filterDbIndex(mac, fid); + colIdx = 0; + + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + retval = rtl8651_getAsicL2Table(rowIdx, colIdx, &L2buff); + + if (retval !=SUCCESS || + memcmp(&(L2buff.macAddr), mac, 6)!= 0) + continue; + if (((flags&FDB_STATIC) && L2buff.isStatic) || + ((flags&FDB_DYNAMIC) && !L2buff.isStatic)) { + return SUCCESS; + } + + } + return FAILED; +} + +int32 rtl_check_fdb_entry_check_srcBlock(uint32 fid, ether_addr_t *mac, int32 *SrcBlk) +{ + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[fid]; + rtl865x_filterDbTableEntry_t * l2entry_t ; + uint32 rowIdx; + + rowIdx = rtl8651_filterDbIndex(mac, fid); + + if (SLIST_FIRST(&(fdb_t->database[rowIdx]))) + { + SLIST_FOREACH(l2entry_t, &(fdb_t->database[rowIdx]), nextFDB) + { + if (memcmp(&(l2entry_t->macAddr), mac, 6)== 0) + { + *SrcBlk = l2entry_t->SrcBlk; + return SUCCESS; + } + } + } + return FAILED; +} + +int32 lanrestrict_callbackFn_for_add_fdb(void *param) +{ + int32 port_num; + rtl865x_filterDbTableEntry_t *fdbEntry; + + if(param==NULL) + { + return EVENT_CONTINUE_EXECUTE; + } + + fdbEntry=(rtl865x_filterDbTableEntry_t *)param; + + port_num = rtl865x_ConvertPortMasktoPortNum(fdbEntry->memberPortMask); + + if (lan_restrict_tbl[port_num].enable == TRUE) + { +/* printk("\nadd authed port[%d], num:%d\n", port_num, lan_restrict_tbl[port_num].curr_num);*/ + lan_restrict_tbl[port_num].curr_num ++; + } + + return SUCCESS; +} + +int32 lanrestrict_callbackFn_for_del_fdb(void *param) +{ + int32 port_num; + rtl865x_filterDbTableEntry_t *fdbEntry; + + if(param==NULL) + { + return EVENT_CONTINUE_EXECUTE; + } + + fdbEntry=(rtl865x_filterDbTableEntry_t *)param; + + port_num = rtl865x_ConvertPortMasktoPortNum(fdbEntry->memberPortMask); + if (lan_restrict_tbl[port_num].enable == TRUE) + { +/* printk("\ndel authed port[%d], num:%d\n", port_num, lan_restrict_tbl[port_num].curr_num);*/ + lan_restrict_tbl[port_num].curr_num --; + if (lan_restrict_tbl[port_num].curr_num < 0) + { + lan_restrict_tbl[port_num].curr_num = 0; + } + } + return SUCCESS; +} + +static int32 lanrestrict_authadd_unRegister_event(void) +{ + rtl865x_event_Param_t eventParam; + eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID; + eventParam.eventId=EVENT_ADD_AUTHED_FDB; + eventParam.eventPriority=0; + eventParam.event_action_fn=lanrestrict_callbackFn_for_add_fdb; + rtl865x_unRegisterEvent(&eventParam); + return SUCCESS; +} + +static int32 lanrestrict_authdel_unRegister_event(void) +{ + rtl865x_event_Param_t eventParam; + eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID; + eventParam.eventId=EVENT_DEL_AUTHED_FDB; + eventParam.eventPriority=0; + eventParam.event_action_fn=lanrestrict_callbackFn_for_del_fdb; + rtl865x_unRegisterEvent(&eventParam); + return SUCCESS; +} + +int32 lanrestrict_unRegister_event(void) +{ + lanrestrict_authadd_unRegister_event(); + lanrestrict_authdel_unRegister_event(); + return SUCCESS; +} + +static int32 lanrestrict_authadd_register_event(void) +{ + rtl865x_event_Param_t eventParam; + eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID; + eventParam.eventId=EVENT_ADD_AUTHED_FDB; + eventParam.eventPriority=0; + eventParam.event_action_fn=lanrestrict_callbackFn_for_add_fdb; + rtl865x_registerEvent(&eventParam); + return SUCCESS; +} + +static int32 lanrestrict_authdel_register_event(void) +{ + rtl865x_event_Param_t eventParam; + eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID; + eventParam.eventId=EVENT_DEL_AUTHED_FDB; + eventParam.eventPriority=0; + eventParam.event_action_fn=lanrestrict_callbackFn_for_del_fdb; + rtl865x_registerEvent(&eventParam); + return SUCCESS; +} + +int32 lanrestrict_register_event(void) +{ + lanrestrict_authadd_register_event(); + lanrestrict_authdel_register_event(); + return SUCCESS; +} + +int32 _rtl865x_addAuthFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr, uint32 type, uint32 portMask, uint8 auth, uint8 SrcBlk) +{ + uint32 rowIdx = 0; + uint32 colIdx = 0; + uint32 col_num = 0; + uint32 col_tmp = 0; + uint16 tmp_age = 0xffff; + int32 found = FALSE; + int32 flag = FALSE; + int32 nexthp_flag = FALSE; + int32 isStatic = FALSE; + int32 toCpu = FALSE; + rtl865x_filterDbTableEntry_t * l2entry_t = NULL; + rtl865x_filterDbTableEntry_t *tmpL2; + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[fid]; + rtl865x_tblAsicDrv_l2Param_t l2entry_tmp,*L2buff; + int32 retval = 0; + int32 overwite_blk_flag = FALSE; + + L2buff = &l2entry_tmp; + memset(L2buff,0,sizeof(rtl865x_tblAsicDrv_l2Param_t)); + rowIdx = rtl8651_filterDbIndex(macAddr, fid); + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + retval = rtl8651_getAsicL2Table(rowIdx, colIdx, L2buff); + if ((retval)==SUCCESS) + { + /*check whether mac address has been learned to HW or not*/ + if (memcmp(&(L2buff->macAddr), macAddr, 6)== 0) + { + /*the entry has been auto learned*/ + if (L2buff->memberPortMask==portMask) + { + /*the entry has been auto learned */ + if ((L2buff->srcBlk == TRUE) && (L2buff->auth == FALSE)) + { + overwite_blk_flag = TRUE; + } + found = TRUE; + col_tmp = colIdx; + } + else + /*portmask is different , it should be overwrited*/ + { + found = FALSE; + flag = TRUE; + } + break; + } + /*no matched entry, try get minimum aging time L2 Asic entry*/ + if (tmp_age> L2buff->ageSec) + { + tmp_age = L2buff->ageSec; + col_num = colIdx; + } + } + else + { + /*there is still empty l2 asic entry*/ + flag = TRUE; + break; + } + } + + switch(l2Type) { + case RTL865x_L2_TYPEI: + nexthp_flag = FALSE;isStatic = FALSE; + break; + case RTL865x_L2_TYPEII: + nexthp_flag = TRUE; isStatic = TRUE; + break; + case RTL865x_L2_TYPEIII: + nexthp_flag = FALSE;isStatic = TRUE; + break; + default: assert(0); + } + + switch(type) { + case FDB_TYPE_FWD: + toCpu = FALSE; + break; + case FDB_TYPE_DSTBLK: + toCpu = FALSE; + break; + case FDB_TYPE_SRCBLK: + toCpu = FALSE; + break; + case FDB_TYPE_TRAPCPU: + toCpu = TRUE; + break; + default: assert(0); + } + + if (found == FALSE) + { + /*no empty entry, overwrite the biggest aging time asic l2 entry*/ + if(flag == FALSE) + { + /*delete the biggest aging time software entry*/ + rtl8651_getAsicL2Table(rowIdx, col_num, L2buff); + _rtl865x_removeFilterDatabaseEntry(fid, &(L2buff->macAddr), rowIdx); + + /*overwrite asic entry*/ + rtl8651_setAsicL2Table_Patch( + rowIdx, + col_num, + macAddr, + toCpu, + SrcBlk, + portMask, + arpAgingTime, + isStatic, + nexthp_flag, + fid, + auth); + col_tmp = col_num; + } + /*portmask is different , so it should overwrite the original asic entry. Or there is empty entry, set it to asic*/ + else if(flag == TRUE) + { + rtl8651_setAsicL2Table_Patch( + rowIdx, + colIdx, + macAddr, + toCpu, + SrcBlk, + portMask, + arpAgingTime, + isStatic, + nexthp_flag, + fid, + auth); + col_tmp = colIdx; + } + } + /*find the same asic entry, should update the aging time*/ + else + { + rtl8651_setAsicL2Table_Patch( + rowIdx, + col_tmp, + macAddr, + toCpu, + SrcBlk, + portMask, + arpAgingTime, + isStatic, + nexthp_flag, + fid, + auth); + } + +/* + colIdx=0; + + tmpL2 = SLIST_FIRST(&(fdb_t->database[rowIdx])); + tmpL2->nextFDB.sle_next = NULL; + + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + if ((rtl8651_getAsicL2Table(rowIdx, colIdx, L2buff))==SUCCESS) + { + l2entry_t->asicPos =colIdx; + l2entry_t->auth = L2buff->auth; + l2entry_t->configToAsic = 0; + l2entry_t->memberPortMask = L2buff->memberPortMask; + l2entry_t->SrcBlk = L2buff->srcBlk; + memcpy(&l2entry_t->macAddr, &L2buff->macAddr, sizeof(ether_addr_t)); + + tmpL2->nextFDB.sle_next = l2entry_t; + l2entry_t->nextFDB.sle_next = NULL; + tmpL2 = l2entry_t; + } + } +*/ + + if (SLIST_FIRST(&sw_FDB_Table.freefdbList.filterDBentry) == NULL) + return RTL_ENOFREEBUFFER; + + /*config the SW l2 entry */ + l2entry_t = SLIST_FIRST(&sw_FDB_Table.freefdbList.filterDBentry); + SLIST_REMOVE_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, nextFDB); + + l2entry_t->asicPos =col_tmp; + l2entry_t->auth = auth; + l2entry_t->configToAsic = 0; + l2entry_t->memberPortMask = portMask; + l2entry_t->l2type = l2Type; + l2entry_t->nhFlag = nexthp_flag; + + l2entry_t->SrcBlk = SrcBlk; + memcpy(&l2entry_t->macAddr, macAddr, sizeof(ether_addr_t)); + switch(type) { + case FDB_TYPE_FWD: + l2entry_t->process = FDB_TYPE_FWD; + l2entry_t->memberPortMask = portMask; + break; + case FDB_TYPE_DSTBLK: + l2entry_t->process = FDB_TYPE_DSTBLK; + l2entry_t->memberPortMask = 0; + break; + case FDB_TYPE_SRCBLK: + l2entry_t->process = FDB_TYPE_SRCBLK; + l2entry_t->memberPortMask = 0; + break; + case FDB_TYPE_TRAPCPU: + l2entry_t->process = FDB_TYPE_TRAPCPU; + l2entry_t->memberPortMask = portMask; + break; + default: assert(0); + } + + /*write the SW l2 entry */ +check_swfdb: + if (SLIST_FIRST(&(fdb_t->database[rowIdx]))) + { + SLIST_FOREACH(tmpL2, &(fdb_t->database[rowIdx]), nextFDB) + { + if (memcmp(&(tmpL2->macAddr), macAddr, 6)== 0) + { + if( (tmpL2->auth != auth) || + (tmpL2->process != type) || + (tmpL2->SrcBlk != SrcBlk) || + (tmpL2->memberPortMask != portMask) || + (tmpL2->l2type != l2Type) ) + { + tmpL2->auth = auth; + tmpL2->process = type; + tmpL2->SrcBlk = SrcBlk; + tmpL2->memberPortMask = portMask; + tmpL2->l2type = l2Type; +/* tmpL2 ->refCount = 0;*/ + break; + } + else + { + goto out; + } + } + /*try to check whether there is timeout sw fdb entry*/ + else if(tmpL2->asicPos == col_tmp) + { +/* if ((tmpL2->SrcBlk == TRUE) && (tmpL2->auth == FALSE))*/ + { + _rtl865x_removeFilterDatabaseEntry(fid, &(tmpL2->macAddr), rowIdx); + goto check_swfdb; + } + } + else if (tmpL2->nextFDB.sle_next == NULL) + { +/* l2entry_t->refCount = 0;*/ + tmpL2->nextFDB.sle_next = l2entry_t; + l2entry_t->nextFDB.sle_next = NULL; + break; + } + } + } + else + { +/* l2entry_t ->refCount = 0;*/ + SLIST_INSERT_HEAD(&(fdb_t->database[rowIdx]), l2entry_t, nextFDB); + } + + /* TypeII entry can not exceed RTL8651_L2TBL_COLUMN */ +/* if (typeII == RTL8651_L2TBL_COLUMN && l2Type == RTL8651_L2_TYPEII) + return RTL_NOFREEBUFFER; +*/ + if (!((l2entry_t->SrcBlk == TRUE) && (l2entry_t->auth == FALSE))) + { + rtl865x_raiseEvent(EVENT_ADD_FDB, (void *)(l2entry_t)); + } + + if (overwite_blk_flag != TRUE) + { + rtl865x_raiseEvent(EVENT_ADD_AUTHED_FDB, (void *)(l2entry_t)); + } + else + { +/* printk("\nover blk entry, no raise event\n");*/ + } + +out: + return SUCCESS; +} + + +int32 _rtl865x_addAuthSWl2Entry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr, uint32 type, int32 port, uint8 auth, uint8 SrcBlk) +{ + uint32 rowIdx = 0; + int32 nexthp_flag = FALSE; + rtl865x_filterDbTableEntry_t * l2entry_t = NULL; + rtl865x_filterDbTableEntry_t *tmpL2; + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[fid]; + rtl865x_tblAsicDrv_l2Param_t l2entry_tmp,*L2buff; + int32 overwite_blk_flag = FALSE; + + L2buff = &l2entry_tmp; + memset(L2buff,0,sizeof(rtl865x_tblAsicDrv_l2Param_t)); + rowIdx = rtl8651_filterDbIndex(macAddr, fid); + + + if (SLIST_FIRST(&sw_FDB_Table.freefdbList.filterDBentry) == NULL) + return RTL_ENOFREEBUFFER; + + /*config the SW l2 entry */ + l2entry_t = SLIST_FIRST(&sw_FDB_Table.freefdbList.filterDBentry); + SLIST_REMOVE_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, nextFDB); + + l2entry_t->auth = auth; + l2entry_t->configToAsic = 0; + l2entry_t->memberPortMask = 1<<port; + l2entry_t->l2type = l2Type; + l2entry_t->nhFlag = nexthp_flag; + + l2entry_t->SrcBlk = SrcBlk; + memcpy(&l2entry_t->macAddr, macAddr, sizeof(ether_addr_t)); + switch(type) { + case FDB_TYPE_FWD: + l2entry_t->process = FDB_TYPE_FWD; + l2entry_t->memberPortMask = 1<<port; + break; + case FDB_TYPE_DSTBLK: + l2entry_t->process = FDB_TYPE_DSTBLK; + l2entry_t->memberPortMask = 0; + break; + case FDB_TYPE_SRCBLK: + l2entry_t->process = FDB_TYPE_SRCBLK; + l2entry_t->memberPortMask = 0; + break; + case FDB_TYPE_TRAPCPU: + l2entry_t->process = FDB_TYPE_TRAPCPU; + l2entry_t->memberPortMask = 1<<port; + break; + default: assert(0); + } + + /*write the SW l2 entry */ + if (SLIST_FIRST(&(fdb_t->database[rowIdx]))) + { + SLIST_FOREACH(tmpL2, &(fdb_t->database[rowIdx]), nextFDB) + { + if (memcmp(&(tmpL2->macAddr), macAddr, 6)== 0) + { + if( (tmpL2->auth != auth) || + (tmpL2->process != type) || + (tmpL2->SrcBlk != SrcBlk) || + (tmpL2->memberPortMask != 1<<port) || + (tmpL2->l2type != l2Type) ) + { + + if ( ( tmpL2->auth == FALSE) && (tmpL2->SrcBlk == TRUE)) + { + overwite_blk_flag = TRUE; + } + tmpL2->auth = auth; + tmpL2->process = type; + tmpL2->SrcBlk = SrcBlk; + tmpL2->memberPortMask = 1<<port; + tmpL2->l2type = l2Type; +/* tmpL2 ->refCount = 0;*/ + break; + } + else + { + SLIST_INSERT_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, l2entry_t, nextFDB); + goto out; + } + } + + else if (tmpL2->nextFDB.sle_next == NULL) + { +/* l2entry_t->refCount = 0;*/ + tmpL2->nextFDB.sle_next = l2entry_t; + l2entry_t->nextFDB.sle_next = NULL; + break; + } + } + } + else + { +/* l2entry_t ->refCount = 0;*/ + SLIST_INSERT_HEAD(&(fdb_t->database[rowIdx]), l2entry_t, nextFDB); + } + + /* TypeII entry can not exceed RTL8651_L2TBL_COLUMN */ +/* if (typeII == RTL8651_L2TBL_COLUMN && l2Type == RTL8651_L2_TYPEII) + return RTL_NOFREEBUFFER; +*/ + + rtl865x_raiseEvent(EVENT_ADD_FDB, (void *)(l2entry_t)); + + + if (overwite_blk_flag != TRUE) + { + rtl865x_raiseEvent(EVENT_ADD_AUTHED_FDB, (void *)(l2entry_t)); + } + else + { +/* printk("\nover blk entry, no raise event\n");*/ + } + +out: + return SUCCESS; +} + + +int32 rtl865x_addAuthFilterDatabaseEntryExtension( uint16 fid, rtl865x_filterDbTableEntry_t * L2entry) +{ + int32 retval; + unsigned long flags; + if (L2entry->process != FDB_TYPE_FWD && L2entry->process != FDB_TYPE_SRCBLK && L2entry->process != FDB_TYPE_TRAPCPU) + return RTL_EINVALIDINPUT; /* Invalid parameter */ + + if (fid >= RTL865x_FDB_NUMBER) + return RTL_EINVALIDINPUT; + if (&(L2entry->macAddr) == (ether_addr_t *)NULL) + return RTL_EINVALIDINPUT; + if (sw_FDB_Table.filterDB[fid].valid == 0) + return RTL_EINVALIDFID; + + /*l2 lock*/ + //rtl_down_interruptible(&l2_sem); + local_irq_save(flags); + retval = _rtl865x_addAuthFilterDatabaseEntry( L2entry->l2type, + fid, + &(L2entry->macAddr), + L2entry->process, + L2entry->memberPortMask, + L2entry->auth, + L2entry->SrcBlk); + /*l2 unlock*/ + //rtl_up(&l2_sem); + local_irq_restore(flags); + return retval; +} + + +/* +@func int32 | rtl8651_delFilterDatabaseEntry | Remove a filter database entry. +@parm uint16 | fid | Filter database entry. +@parm ether_addr_t * | macAddr | Pointer to a MAC Address. +@rvalue RTL_EINVALIDFID | Filter database ID. +@rvalue RTL_NULLMACADDR | The specified MAC address is NULL. +@rvalue RTL_EINVALIDINPUT | Invalid input parameter. +*/ +int32 rtl865x_delAuthFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr) { + int32 retval; + unsigned long flags; + if (fid >= RTL865x_FDB_NUMBER) + return RTL_EINVALIDINPUT; + if (macAddr == (ether_addr_t *)NULL) + return RTL_EINVALIDINPUT; + if (sw_FDB_Table.filterDB[fid].valid == 0) + return RTL_EINVALIDFID; + +/* L2 lock */ + //rtl_down_interruptible(&l2_sem); + local_irq_save(flags); + retval = _rtl865x_delAuthFilterDatabaseEntry(RTL865x_L2_TYPEII, fid, macAddr); +/* L2 unlock */ + //rtl_up(&l2_sem); + local_irq_restore(flags); + return retval; +} + + +int32 _rtl865x_delAuthFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr) +{ + uint32 rowIdx = 0; + uint32 colIdx = 0; + rtl865x_tblAsicDrv_l2Param_t L2temp, *L2buff ; + rtl865x_filterDbTableEntry_t * l2entry_t = NULL; + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[fid]; + int32 found = FALSE; + + rowIdx = rtl8651_filterDbIndex(macAddr, fid); + + L2buff = &L2temp; + memset(L2buff, 0 , sizeof (rtl865x_tblAsicDrv_l2Param_t)); + for(colIdx=0; colIdx<RTL8651_L2TBL_COLUMN; colIdx++) + { + if ((rtl8651_getAsicL2Table(rowIdx, colIdx, L2buff))==SUCCESS) + { + /*check whether mac address has been learned to SW or not*/ + if (memcmp(&(L2buff->macAddr), macAddr, 6)== 0) + { + /*the entry has been auto learned*/ + found = TRUE; + break; + } + } + } + + SLIST_FOREACH(l2entry_t, &(fdb_t->database[rowIdx]), nextFDB) + if (!memcmp(&l2entry_t->macAddr, macAddr, sizeof(ether_addr_t))) + { +/* l2entry_t->refCount -= 1;*/ +/* if (l2entry_t->refCount == 0)*/ + { + SLIST_REMOVE( + &(fdb_t->database[rowIdx]), + l2entry_t, + rtl865x_filterDbTableEntry_s, + nextFDB + ); + SLIST_INSERT_HEAD(&sw_FDB_Table.freefdbList.filterDBentry, l2entry_t, nextFDB); + if (found == TRUE) + { + rtl8651_delAsicL2Table(rowIdx, colIdx); + } + rtl865x_raiseEvent(EVENT_DEL_FDB, (void *)(l2entry_t)); +/* printk("raise event EVENT_DEL_AUTHED_FDB : %x", l2entry_t->memberPortMask);*/ + rtl865x_raiseEvent(EVENT_DEL_AUTHED_FDB, (void *)(l2entry_t)); + + } + break; + } + + return SUCCESS; +} + +int32 rtl865x_check_authfdbentry_Byport(int32 port_num, const unsigned char *macAddr) +{ + uint32 rowIdx; + int32 retval = FAILED; + rtl865x_tblAsicDrv_l2Param_t *L2buff, l2temp; + rtl865x_filterDbTable_t *fdb_t = &sw_FDB_Table.filterDB[0]; + rtl865x_filterDbTableEntry_t * l2entry_t ; + + L2buff = &l2temp; + memset(L2buff, 0, sizeof(rtl865x_tblAsicDrv_l2Param_t)); + for(rowIdx=0; rowIdx<RTL8651_L2TBL_ROW; rowIdx++) + { + if (SLIST_FIRST(&(fdb_t->database[rowIdx]))) + { + SLIST_FOREACH(l2entry_t, &(fdb_t->database[rowIdx]), nextFDB) + { + if ((l2entry_t ->auth == FALSE) && (l2entry_t->SrcBlk == TRUE)) + { + memcpy((ether_addr_t *)macAddr, &(l2entry_t->macAddr), sizeof(ether_addr_t)); +#if 0 + printk("\nfind block entry, rowIdx is %d, address2 is %x %x %x %x %x %x\n", rowIdx, ((ether_addr_t *)macAddr)->octet[0], + ((ether_addr_t *)macAddr)->octet[1], + ((ether_addr_t *)macAddr)->octet[2], + ((ether_addr_t *)macAddr)->octet[3], + ((ether_addr_t *)macAddr)->octet[4], + ((ether_addr_t *)macAddr)->octet[5]); +#endif + + + retval = SUCCESS; + break; + } + } + } + + } + return retval; +} + +int32 rtl865x_addAuthFDBEntry(const unsigned char *addr, int32 auth, int32 port) +{ + int32 found = FAILED; + ether_addr_t *macAddr; + int32 ret=FAILED; + int8 port_num = -1; + int32 column; + rtl865x_tblAsicDrv_l2Param_t fdbEntry; + rtl865x_filterDbTableEntry_t l2temp_entry; + int32 srcblk; + + if (addr == NULL) + return RTL_EINVALIDINPUT; + + macAddr = (ether_addr_t *)(addr); + found = rtl865x_Lookup_fdb_entry(RTL_LAN_FID, macAddr, FDB_DYNAMIC, &column, &fdbEntry); + if (auth == TRUE) + srcblk = FALSE; + else + srcblk = TRUE; + + if (found == SUCCESS ) + { + port_num = rtl865x_ConvertPortMasktoPortNum(fdbEntry.memberPortMask); + +/* printk("\nbefore rtl865x_lookup_FilterDatabaseEntry, port is %d, auth is %d\n", port_num, auth); */ + if (rtl865x_lookup_FilterDatabaseEntry(fdbEntry.fid, macAddr, &l2temp_entry) != SUCCESS) + { + 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 = TRUE;*/ +/* l2temp_entry.SrcBlk = FALSE;*/ + memcpy(&(l2temp_entry.macAddr), macAddr, sizeof(ether_addr_t)); + ret =_rtl865x_addAuthFilterDatabaseEntry( l2temp_entry.l2type, + fdbEntry.fid, + &(l2temp_entry.macAddr), + l2temp_entry.process, + l2temp_entry.memberPortMask, + auth, + srcblk); + + } +#if 1 + else + { + if ((l2temp_entry.auth == FALSE) && (l2temp_entry.SrcBlk == TRUE)) + { + l2temp_entry.l2type = (fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII; + l2temp_entry.process = FDB_TYPE_FWD; + l2temp_entry.memberPortMask = fdbEntry.memberPortMask; + memcpy(&(l2temp_entry.macAddr), macAddr, sizeof(ether_addr_t)); + ret =_rtl865x_addAuthFilterDatabaseEntry( l2temp_entry.l2type, + fdbEntry.fid, + &(l2temp_entry.macAddr), + l2temp_entry.process, + l2temp_entry.memberPortMask, + auth, + srcblk); + } + } +#endif + } + else + { + /*just add sw l2 table */ + l2temp_entry.l2type = RTL865x_L2_TYPEII; + l2temp_entry.process = FDB_TYPE_FWD; +/* l2temp_entry.auth = TRUE;*/ +/* l2temp_entry.SrcBlk = FALSE;*/ + memcpy(&(l2temp_entry.macAddr), macAddr, sizeof(ether_addr_t)); + ret =_rtl865x_addAuthSWl2Entry( l2temp_entry.l2type, + 0, + &(l2temp_entry.macAddr), + l2temp_entry.process, + 1<<port, + auth, + srcblk); + } + return ret; +} + + +int32 rtl865x_delAuthLanFDBEntry(uint16 l2Type, const unsigned char *addr) +{ + int32 ret=FAILED; + ether_addr_t *macAddr; + + if (addr == NULL) + { + return RTL_EINVALIDINPUT; + } + macAddr = (ether_addr_t *)(addr); + + ret =_rtl865x_delAuthFilterDatabaseEntry( l2Type, RTL_LAN_FID, macAddr); + + return ret; +} + +int32 rtl865x_BlkCheck(const unsigned char *addr) +{ + ether_addr_t *macAddr; + rtl865x_filterDbTableEntry_t l2temp_entry; + + if (addr == NULL) + return RTL_EINVALIDINPUT; + + macAddr = (ether_addr_t *)(addr); +#if 0 + printk("\nin rtl865x_BlkCheck, address2 is %x %x %x %x %x %x\n", ((ether_addr_t *)macAddr)->octet[0], + ((ether_addr_t *)macAddr)->octet[1], + ((ether_addr_t *)macAddr)->octet[2], + ((ether_addr_t *)macAddr)->octet[3], + ((ether_addr_t *)macAddr)->octet[4], + ((ether_addr_t *)macAddr)->octet[5]); +#endif + + if(rtl865x_lookup_FilterDatabaseEntry(RTL_LAN_FID, macAddr, &l2temp_entry) == SUCCESS) + { + if (l2temp_entry.SrcBlk == TRUE) + { + return TRUE; + } + } + return FALSE; +} +/* +@func int32 | rtl865x_enableLanPortNumRestrict | enable max guest number restrict feature. +@parm uint8 | isEnable | enable feature or not. +@rvalue SUCCESS | enable feature. +@comm This API may change wan & lan port 802.1x mac base ablity +*/ +int32 rtl865x_enableLanPortNumRestrict(uint8 isEnable) +{ + if( isEnable == TRUE) + { + rtl8651_setAsic802D1xMacBaseDirection(Dot1xMAC_OPDIR_IN); + rtl8651_setAsicGuestVlanProcessControl(EN_8021X_TOCPU); + } + else + { + rtl8651_setAsic802D1xMacBaseDirection(Dot1xMAC_OPDIR_BOTH); + rtl8651_setAsicGuestVlanProcessControl( EN_8021X_DROP); + } + + return SUCCESS; +} + + +/* +@func int32 | rtl865x_setRestrictPortNum | set per port max guest number for max host restrict feature. +@parm int32 | port | set port number . +@parm int8 | isEnable | enable max host restrict feature or not +@parm int32 | number | set max guest number +@rvalue SUCCESS | set number for this port ok. +*/ +int32 rtl865x_setRestrictPortNum(int32 port, uint8 isEnable, int32 number) +{ + int32 i = 0; + + if(isEnable==TRUE) + { + + for (i = PHY0; i < EXT3; i++) + { + if( i == port) + { + rtl8651_setAsic802D1xMacBaseAbility(i, TRUE); + break; + } + } + } + + if(isEnable==FALSE) + { + + for (i = PHY0; i < EXT3; i++) + { + if( i == port) + { + rtl8651_setAsic802D1xMacBaseAbility(i, FALSE); + break; + } + } + + } + return SUCCESS; +} +#endif + +#endif + +#ifdef CONFIG_RTL_LINKCHG_PROCESS +int32 _rtl865x_ClearFDBEntryByPort(int32 port_num) +{ + int i, j; + rtl865x_tblAsicDrv_l2Param_t l2entry_tmp,*L2buff; + + L2buff = &l2entry_tmp; + for (i = 0; i < RTL8651_L2TBL_ROW; i++) + for (j = 0; j < RTL8651_L2TBL_COLUMN; j++) + { + if ((rtl8651_getAsicL2Table(i, j, L2buff))!=SUCCESS) + continue; + + if ((rtl865x_ConvertPortMasktoPortNum(L2buff->memberPortMask)) != port_num) + continue; + + if (L2buff->isStatic == TRUE) + continue; + + rtl8651_delAsicL2Table(i, j); + _rtl865x_removeFilterDatabaseEntry(RTL_LAN_FID, &(L2buff->macAddr), i); + } + + return SUCCESS; + +} + +int32 rtl865x_LinkChange_Process(void) +{ + uint32 i, status; + + /* Check each port. */ + for ( i = 0; i < RTL8651_MAC_NUMBER; i++ ) + { + /* Read Port Status Register to know the port is link-up or link-down. */ + status = READ_MEM32( PSRP0 + i * 4 ); + if ( ( status & PortStatusLinkUp ) == FALSE ) + { + /* Link is down. */ + rtl8651_setAsicEthernetLinkStatus( i, FALSE ); + _rtl865x_ClearFDBEntryByPort(i); + } + else + { + /* Link is up. */ + rtl8651_setAsicEthernetLinkStatus( i, TRUE ); + } + } + + return SUCCESS; + +} +#endif + +#ifdef CONFIG_RTL_PROC_DEBUG +int32 rtl865x_sw_l2_proc_read( char *page, char **start, off_t off, int count, int *eof, void *data ) +{ + int32 index = 0; + int32 index1 = 0; + int len=0; + uint32 port, m=0; + rtl865x_filterDbTable_t *filterDbPtr; + rtl865x_filterDbTableEntry_t *tempFilterDbPtr; + + len = sprintf(page, "%s\n", "sw l2 table:"); + + for(index=0,filterDbPtr=&sw_FDB_Table.filterDB[0]; index<RTL865x_FDB_NUMBER; index++,filterDbPtr++) { + for(index1=0; index1<RTL8651_L2TBL_ROW; index1++) + if (SLIST_FIRST(&(filterDbPtr->database[index1]))) + { + SLIST_FOREACH(tempFilterDbPtr, &(filterDbPtr->database[index1]), nextFDB) + { + len += sprintf(page + len, "%4d.[%3d,%d] %02x:%02x:%02x:%02x:%02x:%02x FID:%x mbr(",m, index1, tempFilterDbPtr->asicPos, + tempFilterDbPtr->macAddr.octet[0], tempFilterDbPtr->macAddr.octet[1], tempFilterDbPtr->macAddr.octet[2], + tempFilterDbPtr->macAddr.octet[3], tempFilterDbPtr->macAddr.octet[4], tempFilterDbPtr->macAddr.octet[5], index); + + m++; + + for (port = 0 ; port < RTL8651_PORT_NUMBER + rtl8651_totalExtPortNum ; port ++) + { + if (tempFilterDbPtr->memberPortMask & (1<<port)) + { + len += sprintf(page + len,"%d ", port); + } + } + len += sprintf(page + len,")"); + + switch(tempFilterDbPtr->process) + { + case FDB_TYPE_FWD: + len += sprintf(page + len,"%s ", "FWD"); + break; + case FDB_TYPE_DSTBLK: + len += sprintf(page + len,"%s ", "DSTBLK"); + break; + case FDB_TYPE_SRCBLK: + len += sprintf(page + len,"%s ", "SRCBLK"); + break; + case FDB_TYPE_TRAPCPU: + len += sprintf(page + len,"%s ", "CPU"); + break; + } +// len += sprintf(page + len,"%s %s %s",tempFilterDbPtr->process?"CPU":"FWD", tempFilterDbPtr->l2type?"STA":"DYN", tempFilterDbPtr->SrcBlk?"BLK":""); + len += sprintf(page + len,"%s ", (tempFilterDbPtr->l2type != RTL865x_L2_TYPEI)?"STA":"DYN"); + len += sprintf(page + len,"%s ", (tempFilterDbPtr->l2type == RTL865x_L2_TYPEII)?"NH":""); + + len += sprintf(page + len,"%s ", tempFilterDbPtr->SrcBlk?"BLK":""); + + if (tempFilterDbPtr->auth) + { + len += sprintf(page + len,"AUTH:%d ",tempFilterDbPtr->auth); + } + +/* len += sprintf(page + len,"reference count:%d",tempFilterDbPtr->refCount);*/ + len += sprintf(page + len,"\n"); + } + } + } + + return len; +} + +int32 rtl865x_sw_l2_proc_write( struct file *filp, const char *buff,unsigned long len, void *data ) +{ + return len; +} +#endif + diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_fdb.h b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_fdb.h new file mode 100644 index 000000000..6c2a3e6aa --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_fdb.h @@ -0,0 +1,125 @@ +#ifndef RTL8651_FDB_H
+#define RTL8651_FDB_H
+#define RTL8651_MAC_NUMBER 6
+#define RTL8651_PORT_NUMBER RTL8651_MAC_NUMBER
+#define RTL8651_MII_PORTNUMBER 5
+#define RTL8651_MII_PORTMASK 0x20
+#define RTL8651_PHY_NUMBER 5
+//#define RTL8651_AGGREGATOR_NUMBER (RTL8651_PORT_NUMBER+rtl8651_totalExtPortNum)
+//#define RTL8651_PSOFFLOAD_RESV_PORT (RTL8651_PORT_NUMBER+rtl8651_totalExtPortNum+1) /* port reserved for protocol stack offloading */
+#define RTL8651_ALLPORTMASK ((1<<RTL8651_AGGREGATOR_NUMBER)-1)
+#define RTL8651_PHYSICALPORTMASK ((1<<RTL8651_MAC_NUMBER)-1)
+#define RTL8651_L2TBL_ROW 256
+#define RTL8651_L2TBL_COLUMN 4
+#define RTL8651_MAX_AGGREGATION_NUM 1
+#define RTL8651_VLAN_NUMBER 8
+#define RTL865XC_NETINTERFACE_NUMBER 8
+#define RTL865XC_MAC_NETINTERFACE_NUMBER 4
+#define RTL865XC_PORT_NUMBER 9
+#define RTL865XC_VLAN_NUMBER 4096
+#define RTL865XC_LAGHASHIDX_NUMBER 8 /* There are 8 hash values in RTL865xC Link Aggregation. */
+#define RTL8651_CPU_PORTNUMBER RTL8651_MAC_NUMBER
+
+#define RTL8651_L2_NUMBER 1024
+
+#define FDB_TYPE_FWD 0x00
+#define FDB_TYPE_SRCBLK 0x01
+#define FDB_TYPE_DSTBLK 0x02
+#define FDB_TYPE_TRAPCPU 0x03
+
+#define RTL865x_FDB_NUMBER 4
+#define RTL865x_L2_TYPEI 0x0001 /* Referenced by ARP/PPPoE */
+#define RTL865x_L2_TYPEII 0x0002 /* Referenced by Protocol */
+#define RTL865x_L2_TYPEIII 0x0004 /* Referenced by PCI/Extension Port */
+
+#define RTL865X_FDBENTRY_TIMEOUT 0x1001 /*fdb entry time out*/
+#define RTL865X_FDBENTRY_450SEC 0x1002 /*fdb entry 450s timing*/
+#define RTL865X_FDBENTRY_300SEC 0x1004 /*fdb entry 300s timing*/
+#define RTL865X_FDBENTRY_150SEC 0x1008 /*fdb entry 150s timing*/
+#define RTL865X_FDBENTRY_SWAP 0x1010 /*fdb entry swap */
+#define CONFIG_RTL865X_SYNC_L2 1
+
+//#define CONFIG_RTL865X_LANPORT_RESTRICTION
+/*
+Note:
+1. Entry property toCpu, srcBlocking destination blocking (memberPortMask) and normal forwarding (Neither toCpu nor srcBlocking) are
+ mutually exclusive. Therefore, only 2-bit to represent this situation.
+2. All entries are static configuration
+3. Unable to process conflict macAddress entry process, return fail when following operation are conflict with current one.
+*/
+typedef struct rtl865x_filterDbTableEntry_s {
+ ether_addr_t macAddr;
+ uint16 l2type; // see bleow definition
+ uint16 process:2, //0: Normal forwarding, 1: destination blocking 2: source blocking 3: toCpu
+ //Management flag
+ refCount:8, //Referenced by other table, such as
+ configToAsic:1, //This entry is configured to ASIC
+ asicPos:2, //The entry position of the ASIC. Since rtl8651 only provides 4-entry. Only 2-bit is required
+ SrcBlk:1,
+ auth:1,
+ nhFlag:1;
+ uint16 vid; //0: don't care. 1~4094: vid of this entry
+ uint32 linkId; //For WLAN WDS.
+ //cfliu: What is link Id? link Id is a virtual port number which represents a WDS link for wireless application.
+ //since 8650 uses MII loopback port and 8650B has only 3 ext ports, it is always insufficient to map 8650B ext ports
+ //to typical 8 WDS links.
+
+ uint32 memberPortMask;
+ SLIST_ENTRY(rtl865x_filterDbTableEntry_s) nextFDB;
+} rtl865x_filterDbTableEntry_t;
+
+
+typedef struct rtl865x_filterDbTable_s {
+ uint16 sid;// Spanning tree ID, 0: CIST id, 1-4096 MST ID
+ uint32 valid:1; //Whether this filter database is valid
+ SLIST_HEAD(, rtl865x_filterDbTableEntry_s) database[RTL8651_L2TBL_ROW];
+} rtl865x_filterDbTable_t;
+
+struct rtl865x_L2Tables{
+ rtl865x_filterDbTable_t *filterDB;
+ struct freefdbEntryList_s {
+ SLIST_HEAD( _FreeFDBEntry, rtl865x_filterDbTableEntry_s) filterDBentry;
+ } freefdbList;
+};
+int32 rtl865x_layer2_init(void);
+int32 _rtl865x_addFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr, uint32 type, uint32 portMask, uint8 auth, uint8 SrcBlk);
+int32 _rtl865x_addAuthFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr, uint32 type, uint32 portMask, uint8 auth, uint8 SrcBlk);
+int32 _rtl865x_delAuthFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr);
+int32 rtl865x_addAuthFilterDatabaseEntryExtension( uint16 fid, rtl865x_filterDbTableEntry_t * L2entry);
+int32 rtl865x_delAuthFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr);
+int32 _rtl865x_delFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr);
+uint32 rtl865x_getHWL2Index(ether_addr_t * macAddr, uint16 fid);
+int32 rtl865x_setHWL2Table(uint32 row, uint32 column, rtl865x_tblAsicDrv_l2Param_t *l2p);
+int32 rtl865x_getHWL2Table(uint32 row, uint32 column, rtl865x_tblAsicDrv_l2Param_t *l2p);
+int32 rtl865x_refleshHWL2Table(ether_addr_t * macAddr, uint32 flags,uint16 fid);
+extern int32 rtl865x_Lookup_fdb_entry(uint32 fid, ether_addr_t *mac, uint32 flags, uint32 *col_num, rtl865x_tblAsicDrv_l2Param_t *L2buff);
+//int32 rtl865x_addFilterDatabaseEntry( uint32 fid, ether_addr_t * mac, uint32 portmask, uint32 type , uint32 isStatic);
+int32 rtl865x_addFilterDatabaseEntry( uint32 fid, ether_addr_t * mac, uint32 portmask, uint32 type );
+int32 rtl865x_addFilterDatabaseEntryExtension( uint16 fid, rtl865x_filterDbTableEntry_t * L2entry);
+int32 rtl865x_getReserveMacAddr(ether_addr_t *macAddr);
+int32 rtl865x_delFilterDatabaseEntry(uint16 l2Type, uint16 fid, ether_addr_t * macAddr);
+int32 rtl865x_ConvertPortMasktoPortNum(int32 portmask);
+int32 rtl865x_delLanFDBEntry(uint16 l2Type, const unsigned char *addr);
+int32 rtl865x_delAuthLanFDBEntry(uint16 l2Type, const unsigned char *addr);
+int32 rtl865x_addFDBEntry(const unsigned char *addr);
+int32 rtl865x_arrangeFdbEntry(const unsigned char *timeout_addr, int32 *port);
+int32 rtl865x_lookup_FilterDatabaseEntry(uint16 fid, ether_addr_t * mac, rtl865x_filterDbTableEntry_t *l2_entry);
+
+#ifdef CONFIG_RTL_LINKCHG_PROCESS
+int32 rtl865x_LinkChange_Process(void);
+#endif
+
+#define CONFIG_RTL_CUSTOM_PASSTHRU
+//#define CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE
+#ifdef CONFIG_RTL_CUSTOM_PASSTHRU
+#define PASSTHRU_VLAN_ID 100
+
+#define IP6_PASSTHRU_RULEID 5
+#define PPPOE_PASSTHRU_RULEID1 3
+#define PPPOE_PASSTHRU_RULEID2 4
+#define IP6_PASSTHRU_MASK 0x1
+#define PPPOE_PASSTHRU_MASK 0x1<<1
+#endif
+
+#endif
+
diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_outputQueue.c b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_outputQueue.c new file mode 100644 index 000000000..ce1afe969 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_outputQueue.c @@ -0,0 +1,1614 @@ + +/* @doc RTL_LAYEREDDRV_API + + @module rtl865x_outputQueue.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 <linux/config.h> +#include <net/rtl/rtl_types.h> +#include <net/rtl/rtl_glue.h> +#include <common/rtl8651_tblDrvProto.h> +#include <common/rtl865x_eventMgr.h> +#include <common/rtl865x_vlan.h> +#include <net/rtl/rtl865x_netif.h> +#include <common/rtl865x_netif_local.h> +#include <net/rtl/rtl865x_outputQueue.h> +//#include "assert.h" +//#include "rtl_utils.h" +#include <common/rtl_errno.h> +#if defined (CONFIG_RTL_LOCAL_PUBLIC) +#include <l3Driver/rtl865x_localPublic.h> +#endif + +#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER +#include <AsicDriver/asicRegs.h> +#include <AsicDriver/rtl865x_asicCom.h> +#include <AsicDriver/rtl865x_asicL2.h> +#else +#include <AsicDriver/asicRegs.h> +#include <AsicDriver/rtl8651_tblAsicDrv.h> +#endif + +#if defined(CONFIG_RTL_HW_QOS_SUPPORT) +#include <net/pkt_cls.h> +#endif + +uint8 netIfNameArray[NETIF_NUMBER][IFNAMSIZ] = {{0}}; +static int8 (*rtl865x_compFunc)(rtl865x_qos_t *entry1, rtl865x_qos_t *entry2); +static uint8 priorityMatrix[RTL8651_OUTPUTQUEUE_SIZE][TOTAL_VLAN_PRIORITY_NUM] = + {{0,0,0,0,0,0,0,0}, + {0,0,0,0,5,5,5,5}, + {0,0,0,0,1,1,5,5}, + {0,0,0,1,2,2,5,5}, + {0,0,0,1,2,3,5,5}, + {0,0,1,2,3,4,5,5}}; + +static int32 queueMatrix[RTL8651_OUTPUTQUEUE_SIZE][RTL8651_OUTPUTQUEUE_SIZE] = + {{0, -1, -1, -1, -1, -1}, + {0, -1, -1, -1, -1, 5}, + {0, 4, -1, -1, -1, 6}, + {0, 3, 4, -1, -1, 6}, + {0, 3, 4, 5, -1, 6}, + {0, 2, 3, 4, 5 ,6}}; + +static uint8 priorityDecisionArray[] = { 2, /* port base */ + 8, /* 802.1p base */ +#if defined (CONFIG_RTK_VOIP_QOS) + 8, /* dscp base */ +#else + 4, /* dscp base */ +#endif + 8, /* acl base */ + 8 /* nat base */ + }; + +static uint32 defPriority[NETIF_NUMBER] = {0}; +static uint32 queueNumber[NETIF_NUMBER] = {0}; +static uint32 priority2HandleMapping[NETIF_NUMBER][TOTAL_VLAN_PRIORITY_NUM] = {{0}}; +static rtl_qos_mark_info_t mark2Priority[NETIF_NUMBER][MAX_MARK_NUM_PER_DEV] = {{{0}}}; + +rtl865x_qos_rule_t *rtl865x_qosRuleHead = NULL; +static int32 _rtl865x_qosArrangeRuleByNetif(uint8 *netIfName); + +int32 rtl865x_qosSetBandwidth(uint8 *netIfName, uint32 bps) +{ + uint32 memberPort, wanMemberPort; + rtl865x_netif_local_t *netIf, *wanNetIf; + rtl865x_vlan_entry_t *vlan; + uint32 port; + uint32 asicBandwidth; + uint32 wanPortAsicBandwidth; + + netIf = _rtl865x_getNetifByName(netIfName); + if(netIf == NULL) + return FAILED; + vlan = _rtl8651_getVlanTableEntry(netIf->vid); + if(vlan == NULL) + return FAILED; + + memberPort = vlan->memberPortMask; + + /////////////////////////////////////////////// + /* Egress bandwidth granularity was 64Kbps */ + asicBandwidth = bps>>EGRESS_BANDWIDTH_GRANULARITY_BITLEN; + if (asicBandwidth>0 && (bps&(1<<(EGRESS_BANDWIDTH_GRANULARITY_BITLEN-1)))!=0) + { + asicBandwidth++; + } + +#if defined(CONFIG_RTL_PUBLIC_SSID) + if(strcmp(netIfName,RTL_GW_WAN_DEVICE_NAME) == 0) +#else + if(strcmp(netIfName,RTL_DRV_WAN0_NETIF_NAME)==0) +#endif + { + //Adjust for wan port egress asic bandwidth + asicBandwidth+=3; + } + if(strcmp(netIfName,RTL_DRV_LAN_NETIF_NAME)==0) + { + //Adjust for lan port egress asic bandwidth + asicBandwidth++; + } + //////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////// + /* Ingress bandwidth granularity was 16Kbps */ + wanPortAsicBandwidth=bps>>INGRESS_BANDWIDTH_GRANULARITY_BITLEN; + if (wanPortAsicBandwidth>0 && (bps&(1<<(INGRESS_BANDWIDTH_GRANULARITY_BITLEN-1)))!=0) + { + wanPortAsicBandwidth++; + } + + //Adjust for wan port ingress asic bandwidth + wanPortAsicBandwidth+=5; + + if(strcmp(netIfName,RTL_DRV_LAN_NETIF_NAME)==0) + { + //To set wan port ingress asic bandwidth +#if defined(CONFIG_RTL_PUBLIC_SSID) + wanNetIf= _rtl865x_getNetifByName(RTL_GW_WAN_DEVICE_NAME); +#else + wanNetIf= _rtl865x_getNetifByName(RTL_DRV_WAN0_NETIF_NAME); +#endif + if(wanNetIf != NULL) + { + wanMemberPort=rtl865x_getVlanPortMask(wanNetIf->vid); + for(port=0;port<=CPU;port++) + { + if(((1<<port)&wanMemberPort)==0) + continue; + rtl8651_setAsicPortIngressBandwidth(port,wanPortAsicBandwidth); + } + } + } + //////////////////////////////////////////////////////////////// + + rtl865xC_lockSWCore(); + for(port=0;port<=CPU;port++) + { + if(((1<<port)&memberPort)==0) + continue; + rtl8651_setAsicPortEgressBandwidth(port, asicBandwidth); + } + rtl865xC_waitForOutputQueueEmpty(); + rtl8651_resetAsicOutputQueue(); + rtl865xC_unLockSWCore(); + return SUCCESS; +} + +int32 rtl865x_qosFlushBandwidth(uint8 *netIfName) +{ + uint32 memberPort, wanMemberPort; + rtl865x_netif_local_t *netIf, *wanNetIf; + rtl865x_vlan_entry_t *vlan; + uint32 port; + + //If flush lan interface qos rules, wan port ingress bandwidth should be set to full speed. + if(strcmp(netIfName,RTL_DRV_LAN_NETIF_NAME)==0) + { +#if defined(CONFIG_RTL_PUBLIC_SSID) + wanNetIf= _rtl865x_getNetifByName(RTL_GW_WAN_DEVICE_NAME); +#else + wanNetIf= _rtl865x_getNetifByName(RTL_DRV_WAN0_NETIF_NAME); +#endif + if(wanNetIf != NULL) + { + wanMemberPort=rtl865x_getVlanPortMask(wanNetIf->vid); + for(port=0;port<=CPU;port++) + { + if(((1<<port)&wanMemberPort)==0) + continue; + rtl8651_setAsicPortIngressBandwidth(port,0); + } + } + } + + netIf = _rtl865x_getNetifByName(netIfName); + if(netIf == NULL) + return FAILED; + vlan = _rtl8651_getVlanTableEntry(netIf->vid); + if(vlan == NULL) + return FAILED; + + memberPort = vlan->memberPortMask; + + rtl865xC_lockSWCore(); + for(port=0;port<=CPU;port++) + { + if(((1<<port)&memberPort)==0) + continue; + + rtl8651_setAsicPortEgressBandwidth(port, APR_MASK>>APR_OFFSET); + } + + rtl865x_raiseEvent(EVENT_FLUSH_QOSRULE, NULL); + + rtl865xC_waitForOutputQueueEmpty(); + rtl8651_resetAsicOutputQueue(); + rtl865xC_unLockSWCore(); + return SUCCESS; +} +#if 0 +int32 rtl865x_qosGetPriorityByHandle(uint8 *priority, uint32 handle) +{ + int j; + + for(j=0; j < TOTAL_VLAN_PRIORITY_NUM; j++) + { + if (priority2HandleMapping[j] == handle) + { + *priority = j; + break; + } + } + if (j<TOTAL_VLAN_PRIORITY_NUM) + return SUCCESS; + else + return FAILED; +} +#else +static int32 _rtl865x_qosGetPriorityByHandle(int32 idx, uint32 handle) +{ + int j; + + for(j=0; j < TOTAL_VLAN_PRIORITY_NUM; j++) + { + if (priority2HandleMapping[idx][j] == handle) + { + return j; + } + } + + return 0; +} +#endif + +int32 rtl_qosGetPriorityByMark(uint8 *netIfName, int32 mark) +{ + int netifIdx, i; + + //Especil for ppp0 which attach at eth1 + netifIdx = _rtl865x_getNetifIdxByNameExt(netIfName); + + if (queueNumber[netifIdx] <=1) + return defPriority[netifIdx]; + + for(i=0;i<MAX_MARK_NUM_PER_DEV;i++) + { + if (mark2Priority[netifIdx][i].mark==mark) + return mark2Priority[netifIdx][i].priority; + } + + return defPriority[netifIdx]; +} + +int32 rtl_qosGetPriorityByVid(int32 vid, int32 mark) +{ + int netifIdx, i; + + netifIdx = _rtl865x_getNetifIdxByVid(vid); + if (queueNumber[netifIdx] <=1) + return defPriority[netifIdx]; + for(i=0;i<MAX_MARK_NUM_PER_DEV;i++) + { + if (mark2Priority[netifIdx][i].mark==mark) + return mark2Priority[netifIdx][i].priority; + } + + return defPriority[netifIdx]; +} + +int32 rtl_qosSetPriorityByMark(uint8 *netIfName, int32 mark, int32 handler, int32 enable) +{ + int netifIdx, i; + + //Especil for ppp0 which attach at eth1 + netifIdx = _rtl865x_getNetifIdxByNameExt(netIfName); + + for(i=0;i<MAX_MARK_NUM_PER_DEV;i++) + { + if (mark2Priority[netifIdx][i].mark==mark) + { + if (enable==TRUE) + { + mark2Priority[netifIdx][i].priority = _rtl865x_qosGetPriorityByHandle(netifIdx, handler); + } + else + { + mark2Priority[netifIdx][i].mark = 0; + mark2Priority[netifIdx][i].priority = 0; + } + break; + } + } + + if (i==MAX_MARK_NUM_PER_DEV&&enable==TRUE) + { + for(i=0;i<MAX_MARK_NUM_PER_DEV;i++) + { + if (mark2Priority[netifIdx][i].mark==0) + { + mark2Priority[netifIdx][i].mark = mark; + mark2Priority[netifIdx][i].priority = _rtl865x_qosGetPriorityByHandle(netifIdx, handler); + break; + } + } + + if (i==MAX_MARK_NUM_PER_DEV) + { + return FAILED; + } + } + return SUCCESS; +} + +#if 1 +/* + _rtl865x_compare2Entry Return Value: + >0 means entry1 > entry2 + <0 means entry1 < entry2 + =0 means entry1 = entry2 +*/ +static int8 _rtl865x_compare2Entry(rtl865x_qos_t *entry1, rtl865x_qos_t *entry2) +{ +#if 0 + if (entry1->handle>entry2->handle) + return 1; + else if (entry1->handle<entry2->handle) + return -1; + else + return 0; +#else + if (entry1->bandwidth<entry2->bandwidth) + return 1; + else if (entry1->bandwidth>entry2->bandwidth) + return -1; + else + return 0; +#endif +} + +int32 rtl865x_registerQosCompFunc(int8 (*p_cmpFunc)(rtl865x_qos_t *entry1, rtl865x_qos_t *entry2)) +{ + if (p_cmpFunc==NULL) + rtl865x_compFunc = _rtl865x_compare2Entry; + else + rtl865x_compFunc = p_cmpFunc; + + return SUCCESS; +} + +static int my_gcd(int numA, int numB) +{ + int tmp; + int divisor; + + if (numA<numB) + { + tmp = numA; + numA = numB; + numB = tmp; + } + + divisor = numA%numB; + while(divisor) + { + numA = numB; + numB = divisor; + divisor = numA%numB; + } + + return numB; +} + +static struct net_device *rtl865x_getDevByName(char *devName) +{ + struct net_device * dev=NULL; + + if(devName != NULL) + { + dev=dev_get_by_name(&init_net, devName); + } + + return dev; +} + +static int32 _rtl865x_qosArrangeQueue(rtl865x_qos_t *qosInfo) +{ + uint32 queueOrder[RTL8651_OUTPUTQUEUE_SIZE] = {0}; + uint32 entry; + int32 nStart, nEnd; + int32 mStart, mEnd; + int32 i=0, j=0, cnt=0; + int32 queueNum; + int32 qosMarkNumIdx; + uint32 tmpHandle; + struct net_device *qosDev, * tmpDev; + rtl865x_qos_t *outputQueue; + rtl865x_qos_t tmp_qosInfo[RTL8651_OUTPUTQUEUE_SIZE]; + const int32 idx = _rtl865x_getNetifIdxByNameExt(qosInfo->ifname); + + /* Process the queue type & ratio */ + { + int divisor; + + if ((qosInfo[0].flags&QOS_DEF_QUEUE)!=0) + divisor = qosInfo[0].ceil; + else + divisor = qosInfo[0].bandwidth; + + for(queueNum=0; queueNum<RTL8651_OUTPUTQUEUE_SIZE; queueNum++) + { + if ((qosInfo[queueNum].flags&QOS_VALID_MASK)==0) + break; + /* Currently, we set all queue as WFQ */ + if ((qosInfo[queueNum].flags&QOS_TYPE_MASK)==QOS_TYPE_WFQ) + { + if ((qosInfo[queueNum].flags&QOS_DEF_QUEUE)!=0) + { + qosInfo[queueNum].bandwidth=qosInfo[queueNum].ceil; + } + divisor = my_gcd(qosInfo[queueNum].bandwidth, divisor); + } + } + + /* process WFQ type ratio */ + { + if (divisor) + { + int maxBandwidth; + int queueNumBackup; + maxBandwidth = 0; + queueNumBackup = queueNum; + + while(queueNum>0) + { + if ((qosInfo[queueNum-1].flags&QOS_TYPE_MASK) + ==QOS_TYPE_WFQ) + { + qosInfo[queueNum-1].bandwidth = (qosInfo[queueNum-1].bandwidth/divisor); + if (maxBandwidth<qosInfo[queueNum-1].bandwidth) + maxBandwidth = qosInfo[queueNum-1].bandwidth; + } + queueNum--; + } + + if (maxBandwidth>EGRESS_WFQ_MAX_RATIO) + { + queueNum = queueNumBackup; + divisor = (maxBandwidth/EGRESS_WFQ_MAX_RATIO) + + ((maxBandwidth%EGRESS_WFQ_MAX_RATIO)>(EGRESS_WFQ_MAX_RATIO>>1)?1:0); + while(queueNum>0) + { + if ((qosInfo[queueNum-1].flags&QOS_TYPE_MASK) + ==QOS_TYPE_WFQ) + { + qosInfo[queueNum-1].bandwidth = + (qosInfo[queueNum-1].bandwidth/divisor); + + if (qosInfo[queueNum-1].bandwidth==0) + qosInfo[queueNum-1].bandwidth = 1; + else if (qosInfo[queueNum-1].bandwidth>EGRESS_WFQ_MAX_RATIO) + qosInfo[queueNum-1].bandwidth = EGRESS_WFQ_MAX_RATIO; + } + queueNum--; + } + } + } + } + + divisor = 0; + for(queueNum=0; queueNum<RTL8651_OUTPUTQUEUE_SIZE; queueNum++) + { + if ((qosInfo[queueNum].flags&QOS_DEF_QUEUE)!=0) + { + qosInfo[queueNum].bandwidth = 1; + } + else if ((qosInfo[queueNum].flags&QOS_VALID_MASK)!=0) + { + continue; + } + break; + } + } + + nStart = nEnd = mStart = mEnd = 0; /* reserver 0 for default queue */ + queueOrder[0] = 0; + outputQueue = qosInfo; + + for(entry=0; entry<RTL8651_OUTPUTQUEUE_SIZE; entry++, outputQueue++) + { + if ((outputQueue->flags&QOS_VALID_MASK)==0) + break; + + /* rtlglue_printf("index %d, queueType %d.\n", entry, outputQueue->queueType); */ + if ((outputQueue->flags&QOS_TYPE_MASK)==QOS_TYPE_WFQ) + { + /* Do not exceed the max value: 1 ~ 128 */ + if (outputQueue->bandwidth>((WEIGHT0_MASK>>WEIGHT0_OFFSET)+1)) + outputQueue->bandwidth = (WEIGHT0_MASK>>WEIGHT0_OFFSET)+1; + + /* this is a NQueue entry */ + { + /* process m Queue */ + if (mEnd>mStart) + { + i = mEnd-1; + while(i>=mStart) + { + queueOrder[i+1] = queueOrder[i]; + i--; + } + } + mEnd++; + mStart++; + + /* process n Queue */ + i = nEnd; + { + while(i>nStart) + { + if(rtl865x_compFunc(outputQueue, &outputQueue[queueOrder[i-1]])>0) + { + queueOrder[i] = queueOrder[i-1]; + i--; + continue; + } + break; + } + } + nEnd++; + queueOrder[i] = entry; + } + } else if ((outputQueue->flags&QOS_TYPE_MASK)==QOS_TYPE_STR) + { + i = mEnd; + { + while(i>mStart) + { + if (rtl865x_compFunc(outputQueue, &outputQueue[queueOrder[i-1]])>0) + { + queueOrder[i] = queueOrder[i-1]; + i--; + continue; + } + break; + } + } + mEnd++; + queueOrder[i] = entry; + } + } + + queueNumber[idx] = mEnd; + + queueNum = 1; + for(i=0;i<NETIF_NUMBER;i++) + { + if (queueNum<queueNumber[i]) + queueNum = queueNumber[i]; + } + + memset((void*)tmp_qosInfo, 0, RTL8651_OUTPUTQUEUE_SIZE*sizeof(rtl865x_qos_t)); + + /* Record the priority <-> handle mapping relationship */ + for(i=0;i<mEnd;i++) + { + cnt = -1; + for(j=0;j<RTL8651_OUTPUTQUEUE_SIZE;j++) + { + if (queueMatrix[queueNum-1][j]>=0) + cnt++; + else + continue; + + if (cnt==i) + { + memcpy(&tmp_qosInfo[j], &qosInfo[queueOrder[i]], sizeof(rtl865x_qos_t)); + priority2HandleMapping[idx][queueMatrix[queueNum-1][j]] = tmp_qosInfo[j].handle; + tmp_qosInfo[j].queueId = j; + } + } + } + + memcpy(qosInfo, tmp_qosInfo, RTL8651_OUTPUTQUEUE_SIZE*sizeof(rtl865x_qos_t)); + + /* Set default priority */ + for(i=0;i<RTL8651_OUTPUTQUEUE_SIZE;i++) + { + if (!(qosInfo[i].flags&QOS_DEF_QUEUE)) + continue; + + for(j=0; j < TOTAL_VLAN_PRIORITY_NUM; j++) + { + if (priority2HandleMapping[idx][j] == qosInfo[i].handle) + break; + } + + /* If we do not find the default queue priority + * just keep the default priority 0 + */ + if (j==TOTAL_VLAN_PRIORITY_NUM) + j = 0; + + /* Set default queue priority */ + defPriority[idx] = j; + } + + //To update mark2Priority + qosDev=rtl865x_getDevByName(qosInfo->ifname); + if(qosDev) + { + for(qosMarkNumIdx=0;qosMarkNumIdx<MAX_MARK_NUM_PER_DEV;qosMarkNumIdx++) + { + if(mark2Priority[idx][qosMarkNumIdx].mark != 0) + { + if(tc_getHandleByKey(mark2Priority[idx][qosMarkNumIdx].mark, &tmpHandle, qosDev, &tmpDev) == 0) + { + mark2Priority[idx][qosMarkNumIdx].priority=_rtl865x_qosGetPriorityByHandle(idx, tmpHandle); + } + else + { + mark2Priority[idx][qosMarkNumIdx].mark=0; + } + } + } + + dev_put(qosDev); + } + + return SUCCESS; +} +#endif + +int32 rtl865x_qosProcessQueue(uint8 *netIfName, rtl865x_qos_t *qosInfo) +{ + uint32 memberPort; + rtl865x_netif_local_t *netIf; + rtl865x_vlan_entry_t *vlan; + uint32 port, queue, i; + uint32 queueNum; + rtl865x_qos_t *tmp_info; + int32 asicBandwidth; + + if (qosInfo==NULL) + return FAILED; + + netIf = _rtl865x_getNetifByName(netIfName); + if(netIf == NULL) + return FAILED; + vlan = _rtl8651_getVlanTableEntry(netIf->vid); + if(vlan == NULL) + return FAILED; + + rtl865xC_lockSWCore(); + rtl865x_closeQos(netIfName); + + memberPort = vlan->memberPortMask; + tmp_info = qosInfo; + queueNum = 0; + + _rtl865x_qosArrangeQueue(qosInfo); + _rtl865x_qosArrangeRuleByNetif(netIfName); + + /* Since we use napt base priority, + * the queue number of each network interface should be the same. + * So we had to select the max queue number to set to each netif. + */ + queueNum = 1; + for(i=0;i<NETIF_NUMBER;i++) + { + if (queueNum<queueNumber[i]) + queueNum = queueNumber[i]; + } + + for(port=0;port<=CPU;port++) + { + if(((1<<port)&memberPort)==0) + continue; + + rtl8651_setAsicOutputQueueNumber(port, queueNum); + + for (queue=0;queue<RTL8651_OUTPUTQUEUE_SIZE;queue++) + { + if ((qosInfo[queue].flags&QOS_VALID_MASK)==0 || qosInfo[queue].ceil==0) /* un-used queue */ + continue; + + /* Egress bandwidth granularity was 64Kbps */ + asicBandwidth = ((qosInfo[queue].ceil)>>(EGRESS_BANDWIDTH_GRANULARITY_BITLEN)) - 1; + if ((qosInfo[queue].ceil)&(1<<(EGRESS_BANDWIDTH_GRANULARITY_BITLEN-1))) + asicBandwidth += 1; +#if 0 + if (asicBandwidth<EGRESS_WFQ_MAX_RATIO && ((qosInfo[queue].ceil<<3)&(1<<(EGRESS_BANDWIDTH_GRANULARITY_BITLEN-1)))!=0) + { + asicBandwidth++; + } +#endif + +#if 0 + if(qosInfo[queue].bandwidth==1) + { + //Default queue + rtl8651_setAsicQueueRate(port, qosInfo[queue].queueId, + PPR_MASK>>PPR_OFFSET, + L1_MASK>>L1_OFFSET, + asicBandwidth); + } + else +#endif + if ((qosInfo[queue].flags&QOS_TYPE_MASK)==QOS_TYPE_STR) + { + rtl8651_setAsicQueueRate(port, qosInfo[queue].queueId, + PPR_MASK>>PPR_OFFSET, + L1_MASK>>L1_OFFSET, + asicBandwidth); + rtl8651_setAsicQueueWeight(port, qosInfo[queue].queueId, STR_PRIO, 0); + } + else + { + rtl8651_setAsicQueueRate(port, qosInfo[queue].queueId, + 1>>PPR_OFFSET, + L1_MASK>>L1_OFFSET, + asicBandwidth); + rtl8651_setAsicQueueWeight(port, qosInfo[queue].queueId, WFQ_PRIO, qosInfo[queue].bandwidth-1); + } + } + } + + rtl865xC_waitForOutputQueueEmpty(); + rtl8651_resetAsicOutputQueue(); + rtl865xC_unLockSWCore(); + + return SUCCESS; +} + +int32 rtl865x_qosArrangeRuleByNetif(void) +{ + int i; + + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + rtl865x_flush_allAcl_fromChain(netIfNameArray[i], RTL865X_ACL_QOS_USED0, RTL865X_ACL_INGRESS); + rtl865x_flush_allAcl_fromChain(netIfNameArray[i], RTL865X_ACL_QOS_USED1, RTL865X_ACL_INGRESS); + } + } + + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + _rtl865x_qosArrangeRuleByNetif(netIfNameArray[i]); + } + } + + return SUCCESS; +} + +static int32 _rtl865x_qosArrangeRuleByNetif(uint8 *netIfName) +{ + rtl865x_qos_rule_t *qosRule; + int32 priority; + int32 i; + const int32 idx = _rtl865x_getNetifIdxByNameExt(netIfName); + int32 tmp_idx; + + for(qosRule = rtl865x_qosRuleHead; qosRule; qosRule=qosRule->next) + { + if (qosRule->handle==0) + continue; + if ((priority=_rtl865x_qosGetPriorityByHandle(idx, qosRule->handle))==0) + continue; + + if(qosRule->outIfname[0]!='\0') + { + /* assigned egress netif */ + tmp_idx = _rtl865x_getNetifIdxByNameExt(qosRule->outIfname); + if (tmp_idx!=idx) + continue; + } + +#if defined(CONFIG_RTL_QOS_8021P_SUPPORT) + if (qosRule->rule->ruleType_==RTL865X_ACL_802D1P) + { + rtl8651_setAsicDot1qAbsolutelyPriority(qosRule->rule->vlanTagPri_, priority); + continue; + } +#endif + { + qosRule->rule->priority_ = priority; + if (qosRule->inIfname[0]!='\0') + { + /* assigned ingress netif */ + rtl865x_del_acl(qosRule->rule, qosRule->inIfname, RTL865X_ACL_QOS_USED0); + rtl865x_add_acl(qosRule->rule, qosRule->inIfname, RTL865X_ACL_QOS_USED0); + #if defined (CONFIG_RTL_LOCAL_PUBLIC) + #if defined(CONFIG_RTL_PUBLIC_SSID) + if (memcmp(RTL_GW_WAN_DEVICE_NAME, qosRule->inIfname, 4)==0 + &&qosRule->rule->direction_==RTL_ACL_INGRESS) + #else + if (memcmp(RTL_DRV_WAN0_NETIF_NAME, qosRule->inIfname, 4)==0 + &&qosRule->rule->direction_==RTL_ACL_INGRESS) + #endif + { + rtl_checkLocalPublicNetifIngressRule(qosRule->rule); + } + #endif + } + else + { + /* do not assigned ingress netif */ + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + tmp_idx = _rtl865x_getNetifIdxByNameExt(netIfNameArray[i]); + if (tmp_idx>=0&&tmp_idx<NETIF_NUMBER&&tmp_idx!=idx) + { + rtl865x_del_acl(qosRule->rule, netIfNameArray[i], RTL865X_ACL_QOS_USED0); + rtl865x_add_acl(qosRule->rule, netIfNameArray[i], RTL865X_ACL_QOS_USED0); + } + } + } + #if defined (CONFIG_RTL_LOCAL_PUBLIC) + if (qosRule->rule->direction_==RTL_ACL_INGRESS) + { + rtl_checkLocalPublicNetifIngressRule(qosRule->rule); + } + #endif + } + } + } + + /* Add default priority */ + { + rtl865x_AclRule_t aclRule; + int i; + + memset(&aclRule, 0, sizeof(rtl865x_AclRule_t)); + aclRule.actionType_ = RTL865X_ACL_PRIORITY; + aclRule.pktOpApp_ = RTL865X_ACL_ALL_LAYER; + aclRule.priority_ = defPriority[idx]; + i = 0; + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + tmp_idx = _rtl865x_getNetifIdxByNameExt(netIfNameArray[i]); + if (tmp_idx>=0&&tmp_idx<NETIF_NUMBER&&tmp_idx!=idx) + { + rtl865x_add_acl(&aclRule, netIfNameArray[i], RTL865X_ACL_QOS_USED1); + } + } + } + } + + rtl865x_raiseEvent(EVENT_CHANGE_QOSRULE, NULL); + + return SUCCESS; +} + +int32 rtl865x_qosAddMarkRule(rtl865x_qos_rule_t *rule) +{ + rtl865x_AclRule_t *qosAclRule; + int i; + + qosAclRule = kmalloc(sizeof(rtl865x_AclRule_t), GFP_ATOMIC); + if (qosAclRule==NULL) + { + return RTL_ENOFREEBUFFER; + } + memcpy(qosAclRule, rule->rule, sizeof(rtl865x_AclRule_t)); + qosAclRule->pktOpApp_ = RTL865X_ACL_ALL_LAYER; + qosAclRule->actionType_ = RTL865X_ACL_PRIORITY; + qosAclRule->aclIdx = 0; + + if (rtl865x_qosRuleHead==NULL) + { + rtl865x_qosRuleHead = rtl_malloc(sizeof(rtl865x_qos_rule_t)); + if (rtl865x_qosRuleHead==NULL) + { + rtl_free(qosAclRule); + return RTL_ENOFREEBUFFER; + } + memcpy(rtl865x_qosRuleHead, rule, sizeof(rtl865x_qos_rule_t)); + rtl865x_qosRuleHead->rule = qosAclRule; + rtl865x_qosRuleHead->next = NULL; + } + else + { + rtl865x_qos_rule_t *qosRule, *lastQosRule; + + qosRule = rtl_malloc(sizeof(rtl865x_qos_rule_t)); + if (qosRule==NULL) + { + rtl_free(qosAclRule); + return RTL_ENOFREEBUFFER; + } + lastQosRule = rtl865x_qosRuleHead; + while(lastQosRule->next) + lastQosRule = lastQosRule->next; + + lastQosRule->next = qosRule; + memcpy(qosRule, rule, sizeof(rtl865x_qos_rule_t)); + qosRule->rule = qosAclRule; + qosRule->next = NULL; + } + + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + _rtl865x_qosArrangeRuleByNetif(netIfNameArray[i]); + } + } + + return SUCCESS; +} + +int32 rtl865x_qosCheckNaptPriority(rtl865x_AclRule_t *qosRule) +{ + rtl865x_AclRule_t *rule_p; + + rule_p = rtl865x_matched_layer4_aclChain(netIfNameArray[qosRule->netifIdx_], RTL865X_ACL_QOS_USED0, RTL865X_ACL_INGRESS, qosRule); + + if (!rule_p) + rule_p = rtl865x_matched_layer2_aclChain(netIfNameArray[qosRule->netifIdx_], RTL865X_ACL_QOS_USED0, RTL865X_ACL_INGRESS, qosRule); + + if (rule_p) + { + qosRule->priority_ = rule_p->priority_; + qosRule->aclIdx = rule_p->aclIdx; + qosRule->upDown_=rule_p->upDown_; + return SUCCESS; + } + else + { + qosRule->priority_ = defPriority[qosRule->netifIdx_]; + return FAILED; + } +} + +int32 rtl865x_qosFlushMarkRule(void) +{ + rtl865x_qos_rule_t *qosRule; + int i; + + while(rtl865x_qosRuleHead) + { + qosRule = rtl865x_qosRuleHead->next; + rtl_free(rtl865x_qosRuleHead->rule); + rtl_free(rtl865x_qosRuleHead); + rtl865x_qosRuleHead = qosRule; + } + + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + rtl865x_flush_allAcl_fromChain(netIfNameArray[i], RTL865X_ACL_QOS_USED0, RTL865X_ACL_INGRESS); + rtl865x_flush_allAcl_fromChain(netIfNameArray[i], RTL865X_ACL_QOS_USED1, RTL865X_ACL_INGRESS); + _rtl865x_qosArrangeRuleByNetif(netIfNameArray[i]); + } + } + + rtl865x_raiseEvent(EVENT_FLUSH_QOSRULE, NULL); + + return SUCCESS; +} + +#if defined (CONFIG_RTL_HW_QOS_SUPPORT) // sync from voip customer for multiple ppp +int32 rtl865x_qosFlushMarkRuleByDev(uint8 *netIfName) +{ + int i; + rtl865x_qosFlushMarkRule(); + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0 && (strcmp(netIfName,netIfNameArray[i])!=0)) + { + _rtl865x_qosArrangeRuleByNetif(netIfNameArray[i]); + } + } + + return SUCCESS; +} + +int32 rtl865x_qosRearrangeRule(void) +{ + int i; + rtl865x_qosFlushMarkRule(); + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + _rtl865x_qosArrangeRuleByNetif(netIfNameArray[i]); + } + } + + return SUCCESS; +} +#endif + +int32 rtl865x_closeQos(uint8 *netIfName) +{ + uint32 memberPort; + rtl865x_netif_local_t *netIf; + rtl865x_vlan_entry_t *vlan; + uint32 i, port; + const int32 idx = _rtl865x_getNetifIdxByNameExt(netIfName); + int32 tmp_idx; + + netIf = _rtl865x_getNetifByName(netIfName); + if(netIf == NULL) + return FAILED; + vlan = _rtl8651_getVlanTableEntry(netIf->vid); + if(vlan == NULL) + return FAILED; + /* clear all acl rules */ +#if defined(CONFIG_RTL_QOS_8021P_SUPPORT) + rtl8651_flushAsicDot1qAbsolutelyPriority(); +#endif + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + tmp_idx = _rtl865x_getNetifIdxByNameExt(netIfNameArray[i]); + if (tmp_idx>=0&&tmp_idx<NETIF_NUMBER&&tmp_idx!=idx) + { + rtl865x_flush_allAcl_fromChain(netIfNameArray[i], RTL865X_ACL_QOS_USED0, RTL865X_ACL_INGRESS); + rtl865x_flush_allAcl_fromChain(netIfNameArray[i], RTL865X_ACL_QOS_USED1, RTL865X_ACL_INGRESS); + } + } + } + + + defPriority[idx] = 0; + queueNumber[idx] = 0; + memset(priority2HandleMapping[idx], 0, TOTAL_VLAN_PRIORITY_NUM*sizeof(int)); + for(i=0;i<MAX_MARK_NUM_PER_DEV;i++) + mark2Priority[idx][i].priority=0; //Only clear priority here, mark need to be stored here. + + /* keep the rule of RTL865X_ACL_QOS_USED2 untouched */ + + memberPort = vlan->memberPortMask; + + rtl865xC_lockSWCore(); + for(port=0;port<=CPU;port++) + { + if(((1<<port)&memberPort)==0) + continue; + + for(i=0;i<RTL8651_OUTPUTQUEUE_SIZE;i++) + { + rtl8651_setAsicQueueWeight(port, i, STR_PRIO, 0); + rtl8651_setAsicQueueRate(port,i, PPR_MASK>>PPR_OFFSET, L1_MASK>>L1_OFFSET,APR_MASK>>APR_OFFSET); + } + + rtl8651_setAsicOutputQueueNumber(port, 1); + } + + rtl865xC_waitForOutputQueueEmpty(); + rtl8651_resetAsicOutputQueue(); + rtl865xC_unLockSWCore(); + return SUCCESS; +} + +int __init rtl865x_initOutputQueue(uint8 **netIfName) +{ + int i,j; + + rtl865xC_lockSWCore(); + for(i=0;i<RTL8651_OUTPUTQUEUE_SIZE;i++) + { + for(j=0;j<TOTAL_VLAN_PRIORITY_NUM;j++) + rtl8651_setAsicPriorityToQIDMappingTable(i+1, j, priorityMatrix[i][j]); + } +#if 0 + for(i=CPU;i<=MULTEXT;i++) + { + /* mapping all priority to cpu port output queue 0 */ + for(j=0;j<TOTAL_VLAN_PRIORITY_NUM;j++) + if(j < 4) + rtl8651_setAsicCPUPriorityToQIDMappingTable(i, j, 0); + else + rtl8651_setAsicCPUPriorityToQIDMappingTable(i,j,5); + } +#endif + for(j=0;j<8;j++) + rtl8651_setAsicCPUPriorityToQIDMappingTable(CPU, j, j<4?0:5); + + rtl8651_setAsicPriorityDecision(priorityDecisionArray[PORT_BASE], + priorityDecisionArray[D1P_BASE], priorityDecisionArray[DSCP_BASE], + priorityDecisionArray[ACL_BASE], priorityDecisionArray[NAT_BASE]); + +#if defined(CONFIG_RTL_QOS_8021P_SUPPORT) + rtl8651_flushAsicDot1qAbsolutelyPriority(); +#endif + + for(i =0; i < RTL8651_OUTPUTQUEUE_SIZE; i++) + { + for(j=PHY0;j<=CPU;j++) + { + /* 1. If disable hw queue flow control, issues as follows: + * 1) 1Gbps ether port to 100Mbps ether port chariot traffic not stable. + * 2) hw qos not so precise + * 2. If enable hw queue flow control, note as follows: + * 1) for hw qos and using 2 chariot tcp downlink traffic, + * the no-matched traffic throughput will be pull-down because of the hw queue flow control. + * + * So we enable hw queue flow control as default setting at present. + * 2011-04-02, zj + */ + if (rtl8651_setAsicQueueFlowControlConfigureRegister(j, i, TRUE)!=SUCCESS) + { + QOS_DEBUGP("Set Queue Flow Control Para Error.\n"); + } + } + } + + rtl865xC_waitForOutputQueueEmpty(); + rtl8651_resetAsicOutputQueue(); + rtl865xC_unLockSWCore(); + + memcpy(netIfNameArray, netIfName, NETIF_NUMBER*IFNAMSIZ); + + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + rtl865x_regist_aclChain(netIfNameArray[i], RTL865X_ACL_QOS_USED0, RTL865X_ACL_INGRESS); + rtl865x_regist_aclChain(netIfNameArray[i], RTL865X_ACL_QOS_USED1, RTL865X_ACL_INGRESS); + } + } + + memset(defPriority, 0, NETIF_NUMBER*sizeof(uint32)); + memset(queueNumber, 0, NETIF_NUMBER*sizeof(uint32)); + memset(priority2HandleMapping, 0, NETIF_NUMBER*TOTAL_VLAN_PRIORITY_NUM*sizeof(int)); + memset(mark2Priority, 0, NETIF_NUMBER*MAX_MARK_NUM_PER_DEV*sizeof(rtl_qos_mark_info_t)); + + rtl865x_qosRuleHead = NULL; + if (rtl865x_compFunc==NULL) + rtl865x_compFunc = _rtl865x_compare2Entry; + + return SUCCESS; +} + +void __exit rtl865x_exitOutputQueue(void) +{ + int i; + + for(i=0;i<NETIF_NUMBER;i++) + { + if (netIfNameArray[i][0]!=0) + { + rtl865x_unRegist_aclChain(netIfNameArray[i], RTL865X_ACL_QOS_USED0, RTL865X_ACL_INGRESS); + rtl865x_unRegist_aclChain(netIfNameArray[i], RTL865X_ACL_QOS_USED1, RTL865X_ACL_INGRESS); + rtl865x_qosFlushBandwidth(netIfNameArray[i]); + rtl865x_closeQos(netIfNameArray[i]); + } + } +} + +#if defined (CONFIG_RTL_HW_QOS_SUPPORT) && defined(CONFIG_RTL_QOS_PATCH) +void rtl865x_reinitOutputQueuePatchForQoS(uint32 qosEnabled) +{ + int32 port, queue; + int32 i; + int32 tmp_idx; + rtl865x_AclRule_t aclRule; + + rtl865xC_lockSWCore(); + + if(qosEnabled == TRUE) + { + /* qos enabled */ + for(i=0;i<NETIF_NUMBER;i++) + { + queueNumber[i]=DEF_QUEUE_NUM; + } + for ( port = PHY0 ; port <= CPU ; port ++ ) + { + rtl8651_setAsicOutputQueueNumber(port, DEF_QUEUE_NUM); + + for ( queue = QUEUE0 ; queue <= QUEUE5 ; queue ++ ) + { + rtl8651_setAsicQueueWeight(port, queue, STR_PRIO, 0); + rtl8651_setAsicQueueRate(port,queue, PPR_MASK>>PPR_OFFSET, L1_MASK>>L1_OFFSET,APR_MASK>>APR_OFFSET); + } + } + + } + else + { + /* qos disabled */ + for(i=0;i<NETIF_NUMBER;i++) + { + queueNumber[i]=MAX_QOS_PATCH_QUEUE_NUM; + } + + for ( port = PHY0 ; port <= CPU ; port ++ ) + { + rtl8651_setAsicOutputQueueNumber(port, MAX_QOS_PATCH_QUEUE_NUM); + + for ( queue = QUEUE0 ; queue <= QUEUE5 ; queue ++ ) + { + if((queue == QUEUE0) || (queue == QUEUE5)) + rtl8651_setAsicQueueRate(port, queue,PPR_MASK>>PPR_OFFSET, L1_MASK>>L1_OFFSET, APR_MASK>>APR_OFFSET); // full speed + } + } + + // Add ACL rule for tcp dport(80) highest priority 7 to accelarate webpage access when heavy traffic load + memset(&aclRule, 0, sizeof(rtl865x_AclRule_t)); + aclRule.ruleType_ = RTL865X_ACL_TCP; + aclRule.tcpSrcPortUB_=65535; + aclRule.tcpSrcPortLB_=0; + aclRule.tcpDstPortUB_=80; + aclRule.tcpDstPortLB_=80; + aclRule.actionType_ = RTL865X_ACL_PRIORITY; + aclRule.pktOpApp_ = RTL865X_ACL_ALL_LAYER; + aclRule.priority_ = 7; + i = 0; + for(i=0;i<NETIF_NUMBER;i++) //For all interfaces + { + if (netIfNameArray[i][0]!=0) + { + tmp_idx = _rtl865x_getNetifIdxByNameExt(netIfNameArray[i]); + if (tmp_idx>=0&&tmp_idx<NETIF_NUMBER) + { + rtl865x_add_acl(&aclRule, netIfNameArray[i], RTL865X_ACL_QOS_USED1); + } + } + } + } + + rtl865xC_waitForOutputQueueEmpty(); + rtl8651_resetAsicOutputQueue(); + rtl865xC_unLockSWCore(); +} +#endif + +#if defined(CONFIG_RTL_PROC_DEBUG) +int32 rtl865x_show_allQosAcl(void) +{ + rtl865x_qos_rule_t *qosRule; + rtl865x_AclRule_t *rule; + int8 *actionT[] = { "permit", "redirect to ether", "drop", "to cpu", "legacy drop", + "drop for log", "mirror", "redirect to pppoe", "default redirect", "mirror keep match", + "drop rate exceed pps", "log rate exceed pps", "drop rate exceed bps", "log rate exceed bps","priority " + }; + + for(qosRule = rtl865x_qosRuleHead;qosRule;qosRule=qosRule->next) + { + rule = qosRule->rule; + switch(rule->ruleType_) + { + case RTL865X_ACL_MAC: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "Ethernet", actionT[rule->actionType_]); + printk("\tether type: %x ether type mask: %x\n", rule->typeLen_, rule->typeLenMask_); + printk("\tDMAC: %x:%x:%x:%x:%x:%x DMACM: %x:%x:%x:%x:%x:%x\n", + rule->dstMac_.octet[0], rule->dstMac_.octet[1], rule->dstMac_.octet[2], + rule->dstMac_.octet[3], rule->dstMac_.octet[4], rule->dstMac_.octet[5], + rule->dstMacMask_.octet[0], rule->dstMacMask_.octet[1], rule->dstMacMask_.octet[2], + rule->dstMacMask_.octet[3], rule->dstMacMask_.octet[4], rule->dstMacMask_.octet[5] + ); + + printk( "\tSMAC: %x:%x:%x:%x:%x:%x SMACM: %x:%x:%x:%x:%x:%x\n", + rule->srcMac_.octet[0], rule->srcMac_.octet[1], rule->srcMac_.octet[2], + rule->srcMac_.octet[3], rule->srcMac_.octet[4], rule->srcMac_.octet[5], + rule->srcMacMask_.octet[0], rule->srcMacMask_.octet[1], rule->srcMacMask_.octet[2], + rule->srcMacMask_.octet[3], rule->srcMacMask_.octet[4], rule->srcMacMask_.octet[5] + ); + break; + + case RTL865X_ACL_IP: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "IP", actionT[rule->actionType_]); + printk( "\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x ipProto: %x ipProtoM: %x ipFlag: %x ipFlagM: %x\n", + rule->tos_, rule->tosMask_, rule->ipProto_, rule->ipProtoMask_, rule->ipFlag_, rule->ipFlagMask_ + ); + + printk("\t<FOP:%x> <FOM:%x> <http:%x> <httpM:%x> <IdentSdip:%x> <IdentSdipM:%x> \n", + rule->ipFOP_, rule->ipFOM_, rule->ipHttpFilter_, rule->ipHttpFilterM_, rule->ipIdentSrcDstIp_, + rule->ipIdentSrcDstIpM_ + ); + printk( "\t<DF:%x> <MF:%x>\n", rule->ipDF_, rule->ipMF_); + break; + + case RTL865X_ACL_IP_RANGE: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "IP Range", actionT[rule->actionType_]); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x ipProto: %x ipProtoM: %x ipFlag: %x ipFlagM: %x\n", + rule->tos_, rule->tosMask_, rule->ipProto_, rule->ipProtoMask_, rule->ipFlag_, rule->ipFlagMask_ + ); + printk("\t<FOP:%x> <FOM:%x> <http:%x> <httpM:%x> <IdentSdip:%x> <IdentSdipM:%x> \n", + rule->ipFOP_, rule->ipFOM_, rule->ipHttpFilter_, rule->ipHttpFilterM_, rule->ipIdentSrcDstIp_, + rule->ipIdentSrcDstIpM_ + ); + printk("\t<DF:%x> <MF:%x>\n", rule->ipDF_, rule->ipMF_); + break; + case RTL865X_ACL_ICMP: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "ICMP", actionT[rule->actionType_]); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x type: %x typeM: %x code: %x codeM: %x\n", + rule->tos_, rule->tosMask_, rule->icmpType_, rule->icmpTypeMask_, + rule->icmpCode_, rule->icmpCodeMask_); + break; + case RTL865X_ACL_ICMP_IPRANGE: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "ICMP IP RANGE", actionT[rule->actionType_]); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x type: %x typeM: %x code: %x codeM: %x\n", + rule->tos_, rule->tosMask_, rule->icmpType_, rule->icmpTypeMask_, + rule->icmpCode_, rule->icmpCodeMask_); + break; + case RTL865X_ACL_IGMP: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "IGMP", actionT[rule->actionType_]); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x type: %x typeM: %x\n", rule->tos_, rule->tosMask_, + rule->igmpType_, rule->igmpTypeMask_ + ); + break; + + + case RTL865X_ACL_IGMP_IPRANGE: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "IGMP IP RANGE", actionT[rule->actionType_]); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos: %x TosM: %x type: %x typeM: %x\n", rule->tos_, rule->tosMask_, + rule->igmpType_, rule->igmpTypeMask_ + ); + break; + + case RTL865X_ACL_TCP: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "TCP", actionT[rule->actionType_]); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos:%x TosM:%x sportL:%d sportU:%d dportL:%d dportU:%d\n", + rule->tos_, rule->tosMask_, rule->tcpSrcPortLB_, rule->tcpSrcPortUB_, + rule->tcpDstPortLB_, rule->tcpDstPortUB_ + ); + printk("\tflag: %x flagM: %x <URG:%x> <ACK:%x> <PSH:%x> <RST:%x> <SYN:%x> <FIN:%x>\n", + rule->tcpFlag_, rule->tcpFlagMask_, rule->tcpURG_, rule->tcpACK_, + rule->tcpPSH_, rule->tcpRST_, rule->tcpSYN_, rule->tcpFIN_ + ); + break; + case RTL865X_ACL_TCP_IPRANGE: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "TCP IP RANGE", actionT[rule->actionType_]); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos:%x TosM:%x sportL:%d sportU:%d dportL:%d dportU:%d\n", + rule->tos_, rule->tosMask_, rule->tcpSrcPortLB_, rule->tcpSrcPortUB_, + rule->tcpDstPortLB_, rule->tcpDstPortUB_ + ); + printk("\tflag: %x flagM: %x <URG:%x> <ACK:%x> <PSH:%x> <RST:%x> <SYN:%x> <FIN:%x>\n", + rule->tcpFlag_, rule->tcpFlagMask_, rule->tcpURG_, rule->tcpACK_, + rule->tcpPSH_, rule->tcpRST_, rule->tcpSYN_, rule->tcpFIN_ + ); + break; + + case RTL865X_ACL_UDP: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx,"UDP", actionT[rule->actionType_]); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos:%x TosM:%x sportL:%d sportU:%d dportL:%d dportU:%d\n", + rule->tos_, rule->tosMask_, rule->udpSrcPortLB_, rule->udpSrcPortUB_, + rule->udpDstPortLB_, rule->udpDstPortUB_ + ); + break; + case RTL865X_ACL_UDP_IPRANGE: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "UDP IP RANGE", actionT[rule->actionType_]); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->dstIpAddr_>>24), + ((rule->dstIpAddr_&0x00ff0000)>>16), ((rule->dstIpAddr_&0x0000ff00)>>8), + (rule->dstIpAddr_&0xff), (rule->dstIpAddrMask_>>24), ((rule->dstIpAddrMask_&0x00ff0000)>>16), + ((rule->dstIpAddrMask_&0x0000ff00)>>8), (rule->dstIpAddrMask_&0xff) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->srcIpAddr_>>24), + ((rule->srcIpAddr_&0x00ff0000)>>16), ((rule->srcIpAddr_&0x0000ff00)>>8), + (rule->srcIpAddr_&0xff), (rule->srcIpAddrMask_>>24), ((rule->srcIpAddrMask_&0x00ff0000)>>16), + ((rule->srcIpAddrMask_&0x0000ff00)>>8), (rule->srcIpAddrMask_&0xff) + ); + printk("\tTos:%x TosM:%x sportL:%d sportU:%d dportL:%d dportU:%d\n", + rule->tos_, rule->tosMask_, rule->udpSrcPortLB_, rule->udpSrcPortUB_, + rule->udpDstPortLB_, rule->udpDstPortUB_ + ); + break; + + + case RTL865X_ACL_SRCFILTER: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "Source Filter", actionT[rule->actionType_]); + printk("\tSMAC: %x:%x:%x:%x:%x:%x SMACM: %x:%x:%x:%x:%x:%x\n", + rule->srcFilterMac_.octet[0], rule->srcFilterMac_.octet[1], rule->srcFilterMac_.octet[2], + rule->srcFilterMac_.octet[3], rule->srcFilterMac_.octet[4], rule->srcFilterMac_.octet[5], + rule->srcFilterMacMask_.octet[0], rule->srcFilterMacMask_.octet[1], rule->srcFilterMacMask_.octet[2], + rule->srcFilterMacMask_.octet[3], rule->srcFilterMacMask_.octet[4], rule->srcFilterMacMask_.octet[5] + ); + printk("\tsvidx: %d svidxM: %x sport: %d sportM: %x ProtoType: %x\n", + rule->srcFilterVlanIdx_, rule->srcFilterVlanIdxMask_, rule->srcFilterPort_, rule->srcFilterPortMask_, + (rule->srcFilterIgnoreL3L4_==TRUE? 2: (rule->srcFilterIgnoreL4_ == 1? 1: 0)) + ); + printk("\tsip: %d.%d.%d.%d sipM: %d.%d.%d.%d\n", (rule->srcFilterIpAddr_>>24), + ((rule->srcFilterIpAddr_&0x00ff0000)>>16), ((rule->srcFilterIpAddr_&0x0000ff00)>>8), + (rule->srcFilterIpAddr_&0xff), (rule->srcFilterIpAddrMask_>>24), + ((rule->srcFilterIpAddrMask_&0x00ff0000)>>16), ((rule->srcFilterIpAddrMask_&0x0000ff00)>>8), + (rule->srcFilterIpAddrMask_&0xff) + ); + printk("\tsportL: %d sportU: %d\n", rule->srcFilterPortLowerBound_, rule->srcFilterPortUpperBound_); + break; + + case RTL865X_ACL_SRCFILTER_IPRANGE: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "Source Filter(IP RANGE)", actionT[rule->actionType_]); + printk("\tSMAC: %x:%x:%x:%x:%x:%x SMACM: %x:%x:%x:%x:%x:%x\n", + rule->srcFilterMac_.octet[0], rule->srcFilterMac_.octet[1], rule->srcFilterMac_.octet[2], + rule->srcFilterMac_.octet[3], rule->srcFilterMac_.octet[4], rule->srcFilterMac_.octet[5], + rule->srcFilterMacMask_.octet[0], rule->srcFilterMacMask_.octet[1], rule->srcFilterMacMask_.octet[2], + rule->srcFilterMacMask_.octet[3], rule->srcFilterMacMask_.octet[4], rule->srcFilterMacMask_.octet[5] + ); + printk("\tsvidx: %d svidxM: %x sport: %d sportM: %x ProtoType: %x\n", + rule->srcFilterVlanIdx_, rule->srcFilterVlanIdxMask_, rule->srcFilterPort_, rule->srcFilterPortMask_, + (rule->srcFilterIgnoreL3L4_==TRUE? 2: (rule->srcFilterIgnoreL4_ == 1? 1: 0)) + ); + printk("\tsipU: %d.%d.%d.%d sipL: %d.%d.%d.%d\n", (rule->srcFilterIpAddr_>>24), + ((rule->srcFilterIpAddr_&0x00ff0000)>>16), ((rule->srcFilterIpAddr_&0x0000ff00)>>8), + (rule->srcFilterIpAddr_&0xff), (rule->srcFilterIpAddrMask_>>24), + ((rule->srcFilterIpAddrMask_&0x00ff0000)>>16), ((rule->srcFilterIpAddrMask_&0x0000ff00)>>8), + (rule->srcFilterIpAddrMask_&0xff) + ); + printk("\tsportL: %d sportU: %d\n", rule->srcFilterPortLowerBound_, rule->srcFilterPortUpperBound_); + break; + + case RTL865X_ACL_DSTFILTER: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "Deatination Filter", actionT[rule->actionType_]); + printk("\tDMAC: %x:%x:%x:%x:%x:%x DMACM: %x:%x:%x:%x:%x:%x\n", + rule->dstFilterMac_.octet[0], rule->dstFilterMac_.octet[1], rule->dstFilterMac_.octet[2], + rule->dstFilterMac_.octet[3], rule->dstFilterMac_.octet[4], rule->dstFilterMac_.octet[5], + rule->dstFilterMacMask_.octet[0], rule->dstFilterMacMask_.octet[1], rule->dstFilterMacMask_.octet[2], + rule->dstFilterMacMask_.octet[3], rule->dstFilterMacMask_.octet[4], rule->dstFilterMacMask_.octet[5] + ); + printk("\tdvidx: %d dvidxM: %x ProtoType: %x dportL: %d dportU: %d\n", + rule->dstFilterVlanIdx_, rule->dstFilterVlanIdxMask_, + (rule->dstFilterIgnoreL3L4_==TRUE? 2: (rule->dstFilterIgnoreL4_ == 1? 1: 0)), + rule->dstFilterPortLowerBound_, rule->dstFilterPortUpperBound_ + ); + printk("\tdip: %d.%d.%d.%d dipM: %d.%d.%d.%d\n", (rule->dstFilterIpAddr_>>24), + ((rule->dstFilterIpAddr_&0x00ff0000)>>16), ((rule->dstFilterIpAddr_&0x0000ff00)>>8), + (rule->dstFilterIpAddr_&0xff), (rule->dstFilterIpAddrMask_>>24), + ((rule->dstFilterIpAddrMask_&0x00ff0000)>>16), ((rule->dstFilterIpAddrMask_&0x0000ff00)>>8), + (rule->dstFilterIpAddrMask_&0xff) + ); + break; + case RTL865X_ACL_DSTFILTER_IPRANGE: + printk(" [%d] rule type: %s rule action: %s\n", rule->aclIdx, "Deatination Filter(IP Range)", actionT[rule->actionType_]); + printk("\tDMAC: %x:%x:%x:%x:%x:%x DMACM: %x:%x:%x:%x:%x:%x\n", + rule->dstFilterMac_.octet[0], rule->dstFilterMac_.octet[1], rule->dstFilterMac_.octet[2], + rule->dstFilterMac_.octet[3], rule->dstFilterMac_.octet[4], rule->dstFilterMac_.octet[5], + rule->dstFilterMacMask_.octet[0], rule->dstFilterMacMask_.octet[1], rule->dstFilterMacMask_.octet[2], + rule->dstFilterMacMask_.octet[3], rule->dstFilterMacMask_.octet[4], rule->dstFilterMacMask_.octet[5] + ); + printk("\tdvidx: %d dvidxM: %x ProtoType: %x dportL: %d dportU: %d\n", + rule->dstFilterVlanIdx_, rule->dstFilterVlanIdxMask_, + (rule->dstFilterIgnoreL3L4_==TRUE? 2: (rule->dstFilterIgnoreL4_ == 1? 1: 0)), + rule->dstFilterPortLowerBound_, rule->dstFilterPortUpperBound_ + ); + printk("\tdipU: %d.%d.%d.%d dipL: %d.%d.%d.%d\n", (rule->dstFilterIpAddr_>>24), + ((rule->dstFilterIpAddr_&0x00ff0000)>>16), ((rule->dstFilterIpAddr_&0x0000ff00)>>8), + (rule->dstFilterIpAddr_&0xff), (rule->dstFilterIpAddrMask_>>24), + ((rule->dstFilterIpAddrMask_&0x00ff0000)>>16), ((rule->dstFilterIpAddrMask_&0x0000ff00)>>8), + (rule->dstFilterIpAddrMask_&0xff) + ); + break; + + default: + printk("rule->ruleType_(0x%x)\n", rule->ruleType_); + + } + + switch (rule->actionType_) + { + case RTL865X_ACL_PERMIT: + case RTL865X_ACL_REDIRECT_ETHER: + case RTL865X_ACL_DROP: + case RTL865X_ACL_TOCPU: + case RTL865X_ACL_LEGACY_DROP: + case RTL865X_ACL_DROPCPU_LOG: + case RTL865X_ACL_MIRROR: + case RTL865X_ACL_REDIRECT_PPPOE: + case RTL865X_ACL_MIRROR_KEEP_MATCH: + printk("\tnetifIdx: %d pppoeIdx: %d l2Idx:%d ", rule->netifIdx_, rule->pppoeIdx_, rule->L2Idx_); + break; + + case RTL865X_ACL_PRIORITY: + printk("\tprioirty: %d ", rule->priority_) ; + break; + + case RTL865X_ACL_DEFAULT_REDIRECT: + printk("\tnextHop:%d ", rule->nexthopIdx_); + break; + + case RTL865X_ACL_DROP_RATE_EXCEED_PPS: + case RTL865X_ACL_LOG_RATE_EXCEED_PPS: + case RTL865X_ACL_DROP_RATE_EXCEED_BPS: + case RTL865X_ACL_LOG_RATE_EXCEED_BPS: + printk("\tratelimitIdx: %d ", rule->ratelimtIdx_); + break; + default: + ; + + } + printk("pktOpApp: %d handler:0x%x Mark: %d\n", rule->pktOpApp_, qosRule->handle, qosRule->mark); + printk("InDev: %s OutDev: %s\n", qosRule->inIfname[0]==0?"NULL":qosRule->inIfname, qosRule->outIfname[0]==0?"NULL":qosRule->outIfname); + + rule = rule->next; + } + + return SUCCESS; + +} +#endif + diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_stp.c b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_stp.c new file mode 100644 index 000000000..2b84d8245 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_stp.c @@ -0,0 +1,44 @@ +/*add by lu yang*/
+/* @doc RTL_LAYEREDDRV_API
+
+ @module rtl865x_stp.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 "rtl_utils.h"
+#include <net/rtl/rtl_types.h>
+#include <net/rtl/rtl_glue.h>
+#include "AsicDriver/asicRegs.h"
+#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER
+#include "AsicDriver/rtl865x_asicCom.h"
+#include "AsicDriver/rtl865x_asicL2.h"
+#else
+#include <common/rtl8651_aclLocal.h>
+#include <AsicDriver/rtl865xC_tblAsicDrv.h>
+#endif
+
+#include <net/rtl/rtk_stp.h>
+
+int32 rtl865x_setSpanningEnable(int8 spanningTreeEnabled)
+{
+ return rtl8651_setAsicSpanningEnable(spanningTreeEnabled);
+}
+
+int32 rtl865x_setSpanningTreePortState(uint32 port, uint32 portState)
+{
+ return rtl865xC_setAsicSpanningTreePortState(port, portState);
+}
+
+int32 rtl865x_setMulticastSpanningTreePortState(uint32 port, uint32 portState)
+{
+ return rtl8651_setAsicMulticastSpanningTreePortState(port, portState);
+}
|