summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/drivers/net/rtl819x/l2Driver
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2012-09-13 00:40:35 +0300
committerRoman Yeryomin <roman@advem.lv>2012-12-03 00:13:21 +0200
commit5deb3317cb51ac52de922bb55f8492624018906d (patch)
treec2fbe6346699d9bb0f2100490c3029519bb8fde8 /target/linux/realtek/files/drivers/net/rtl819x/l2Driver
parent0239d37124f9184b478a42de8a7fa1bc85a6a6fe (diff)
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/net/rtl819x/l2Driver')
-rw-r--r--target/linux/realtek/files/drivers/net/rtl819x/l2Driver/Makefile50
-rw-r--r--target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_fdb.c2022
-rw-r--r--target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_fdb.h125
-rw-r--r--target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_outputQueue.c1614
-rw-r--r--target/linux/realtek/files/drivers/net/rtl819x/l2Driver/rtl865x_stp.c44
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);
+}