From a27354c9021a8423ef8c7d2bffad49cbf639eec1 Mon Sep 17 00:00:00 2001 From: Roman Yeryomin Date: Thu, 13 Sep 2012 00:40:35 +0300 Subject: Add realtek target files Signed-off-by: Roman Yeryomin --- .../drivers/net/rtl819x/l3Driver/rtl865x_arp.c | 658 +++++++++++++++++++++ 1 file changed, 658 insertions(+) create mode 100644 target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.c (limited to 'target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.c') diff --git a/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.c b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.c new file mode 100644 index 000000000..fab41bcc2 --- /dev/null +++ b/target/linux/realtek/files/drivers/net/rtl819x/l3Driver/rtl865x_arp.c @@ -0,0 +1,658 @@ + +/* @doc RTL_LAYEREDDRV_API + + @module rtl865x_arp.c - RTL865x Home gateway controller Layered driver API documentation | + This document explains the API interface of the table driver module. Functions with rtl865x prefix + are external functions. + @normal Hyking Liu (Hyking_liu@realsil.com.cn) + + Copyright 2008 Realtek 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 +#include "common/rtl_errno.h" + +#include "common/mbuf.h" +//#include "assert.h" + +//#include "rtl865xc_swNic.h" +#ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER +#include "AsicDriver/rtl865x_asicCom.h" +#include "AsicDriver/rtl865x_asicL2.h" +#include "AsicDriver/rtl865x_asicL3.h" +#else +#include "rtl865xC_tblAsicDrv.h" +#include "common/rtl8651_aclLocal.h" +#endif + +#include "AsicDriver/rtl865x_hwPatch.h" /* define for chip related spec */ + +#include "common/rtl865x_eventMgr.h" + +#include "common/rtl865x_vlan.h" +#include +#include "common/rtl865x_netif_local.h" + +#include "l2Driver/rtl865x_fdb.h" + +#include "rtl865x_ppp_local.h" +#include "rtl865x_route.h" +#include "rtl865x_arp.h" + +#if defined(CONFIG_RTL_MULTIPLE_WAN) +#include +#include "rtl865x_multipleWan.h" +#include "rtl865x_nexthop.h" +#endif +#include + +static int32 rtl865x_arp_hash(ipaddr_t ip, uint32 *index); + +static int32 rtl865x_arp_callbackFn_for_del_fdb(void *param); +static int32 rtl865x_arp_register_event(void); + +static struct rtl865x_arp_table arpTables; +#if defined(CONFIG_RTL_MULTIPLE_WAN) +static int (*rtl_callback_for_ps_arp)(ipaddr_t ip,rtl865x_arpMapping_entry_t *arp); +#endif + +static int32 rtl865x_arp_callbackFn_for_del_fdb(void *param) +{ + int i; + rtl865x_filterDbTableEntry_t *fdbEntry; + + if(param==NULL) + { + return EVENT_CONTINUE_EXECUTE; + } + + fdbEntry=(rtl865x_filterDbTableEntry_t *)param; + + for(i=0;imacAddr),&(arpTables.mappings[i].mac), 6)==0) + { + rtl865x_delArp(arpTables.mappings[i].ip); + } + + } + + return EVENT_CONTINUE_EXECUTE; + +} + +static int32 rtl865x_arp_unRegister_event(void) +{ + rtl865x_event_Param_t eventParam; + eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID; + eventParam.eventId=EVENT_DEL_FDB; + eventParam.eventPriority=0; + eventParam.event_action_fn=rtl865x_arp_callbackFn_for_del_fdb; + rtl865x_unRegisterEvent(&eventParam); + return SUCCESS; + +} +static int32 rtl865x_arp_register_event(void) +{ + rtl865x_event_Param_t eventParam; + eventParam.eventLayerId=DEFAULT_LAYER2_EVENT_LIST_ID; + eventParam.eventId=EVENT_DEL_FDB; + eventParam.eventPriority=0; + eventParam.event_action_fn=rtl865x_arp_callbackFn_for_del_fdb; + rtl865x_registerEvent(&eventParam); + return SUCCESS; + +} + + +int32 rtl865x_arp_init(void) +{ + int i; + rtl865x_arp_unRegister_event(); + memset(arpTables.allocBitmap, 0, 64); + memset(arpTables.mappings, 0, RTL8651_ARPTBL_SIZE * sizeof(rtl865x_arpMapping_entry_t)); + for(i=0; iprocess!=2)) + { + return FAILED; + } + + for(entry=0; entry<32; entry++) + { + if(route->ipMask & (1< 1) + { + curStartPos = bestSize = curSize = 0; + for(entry = 0; entry <= 64; entry++) + { + if((entry == 64) || arpTables.allocBitmap[entry]) + { + if(curSize > bestSize) + { + bestStartPos = curStartPos; + bestSize = curSize; + } + curStartPos = entry+1; + curSize = 0; + } else curSize++; + } + } + + if (netSize>1 && ((bestSize<<3) >= netSize)) + { + route->un.arp.arpsta= bestStartPos<<3; + route->un.arp.arpend = (bestStartPos + (netSize>>3) - ((netSize&0x7)==0? 1: 0))<<3; + for(entry=route->un.arp.arpsta>>3; entry<=route->un.arp.arpend>>3; entry++) + { + arpTables.allocBitmap[entry] = 1; + } + return SUCCESS; + } + return FAILED; + +} + +int32 rtl865x_arp_tbl_free(rtl865x_route_t *route) +{ + rtl865x_vlan_entry_t *vlan; + uint32 index; + int32 i, j; + + if(route==NULL) + { + return FAILED; + } + if((route->valid!=1) || (route->process!=2) || (route->dstNetif==NULL) ) + { + return FAILED; + } + + for(i=route->un.arp.arpsta>>3; i<=route->un.arp.arpend>>3; i++) + { + arpTables.allocBitmap[i] = 0; + for(j=0; j<8; j++) + { + index = (i<<3)+j; + if(arpTables.mappings[index].ip!=0) + { + rtl8651_delAsicArp(index); + vlan = _rtl8651_getVlanTableEntry(route->dstNetif->vid); + rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEII, vlan->fid, &(arpTables.mappings[index].mac)); + memset(&(arpTables.mappings[index]),0,sizeof(rtl865x_arpMapping_entry_t)); + } + else + { + memset(&(arpTables.mappings[index]),0,sizeof(rtl865x_arpMapping_entry_t)); + } + } + } + + return SUCCESS; +} + +static int32 rtl865x_arp_hash(ipaddr_t ip, uint32 *index) +{ + rtl865x_route_t rt_entry,*route; + uint32 arpIndex; + int32 retval = FAILED; + + route = &rt_entry; + memset(route,0,sizeof(rtl865x_route_t)); + retval =rtl865x_getRouteEntry(ip, route); + + if (retval != SUCCESS) + return retval; + if((route->valid!=1) || (route->process!=2) ||(route->dstNetif==NULL)) + { + return FAILED; + } + arpIndex=((route->un.arp.arpsta)+(ip&~route->ipMask)); + if(arpIndex>=RTL8651_ARPTBL_SIZE) + { + return FAILED; + } + *index=arpIndex; + return SUCCESS; +} + +int32 rtl865x_getArpMapping(ipaddr_t ip, rtl865x_arpMapping_entry_t * arp_mapping) +{ + + rtl865x_route_t *route,rt_entry; + uint32 hash; + int32 retval = FAILED; + + if(arp_mapping==NULL) + { + return FAILED; + } + memset(arp_mapping, 0, sizeof(rtl865x_arpMapping_entry_t)); + route= &rt_entry; + memset(route,0,sizeof(rtl865x_route_t)); + retval=rtl865x_getRouteEntry(ip,route); + + if(retval != SUCCESS) + return retval; + + + if((route->valid!=1) || (route->process!=2) ||(route->dstNetif==NULL)) + { + return FAILED; + } + + if(rtl865x_arp_hash(ip,&hash)==FAILED) + { + return FAILED; + } + + if(arpTables.mappings[hash].ip==ip) + { + memcpy(arp_mapping,&(arpTables.mappings[hash]),sizeof(rtl865x_arpMapping_entry_t)); + } + else + return FAILED; + + return SUCCESS; +} + + +int32 rtl865x_getAsicArpEntry(ipaddr_t ip,rtl865x_tblAsicDrv_arpParam_t *asicArpEntry) +{ + + rtl865x_route_t *route,rt_entry; + uint32 hash; + int32 retval; + + if(asicArpEntry==NULL) + { + return FAILED; + } + + route = &rt_entry; + memset(route,0,sizeof(rtl865x_route_t)); + memset(asicArpEntry, 0, sizeof(rtl865x_tblAsicDrv_arpParam_t)); + + retval = rtl865x_getRouteEntry(ip,route); + if(retval != SUCCESS) + return retval; + + if((route==NULL)||(route->valid!=1) || (route->process!=2) ||(route->dstNetif==NULL)) + { + return FAILED; + } + + if(rtl865x_arp_hash(ip,&hash)==FAILED) + { + return FAILED; + } + + rtl8651_getAsicArp(hash, asicArpEntry); + + return SUCCESS; + +} + +int32 rtl865x_mapIpToMac(ipaddr_t ip,ether_addr_t * mac) +{ + uint32 hash; + + if(mac==NULL) + { + return FAILED; + } + + memset(mac, 0, sizeof(ether_addr_t)); + + if(rtl865x_arp_hash(ip, &hash)!=SUCCESS) + { + return FAILED; + } + + if(arpTables.mappings[hash].ip==ip) + { + memcpy(mac,&(arpTables.mappings[hash].mac),sizeof(ether_addr_t)); + return SUCCESS; + } + + return FAILED; +} + +static int32 rtl865x_getArpFid(ipaddr_t ip, uint16 *fid) +{ + rtl865x_route_t *route,rt_entry; + rtl865x_vlan_entry_t *vlan; + int32 retval = FAILED; + + + if(ip==0) + { + return FAILED; + } + + route = &rt_entry; + memset(route,0,sizeof(rtl865x_route_t)); + retval = rtl865x_getRouteEntry(ip,route); + if(retval != SUCCESS) + return retval; + + if((route->valid!=1) || (route->process!=2) ||(route->dstNetif==NULL)) + { + return FAILED; + } + + + vlan = _rtl8651_getVlanTableEntry(route->dstNetif->vid); + *fid = vlan->fid; + return SUCCESS; +} +#if defined(CONFIG_RTL_MULTIPLE_WAN) +int32 rtl_set_callback_for_ps_arp(int (*call_back_fn)(u32 ip,rtl865x_arpMapping_entry_t *entry)) +{ + if(NULL == call_back_fn) + { + return FAILED; + } + + rtl_callback_for_ps_arp = call_back_fn; + return SUCCESS; +} + +int32 rtl865x_get_ps_arpMapping(ipaddr_t ip,rtl865x_arpMapping_entry_t *entry) +{ + if(rtl_callback_for_ps_arp) + return rtl_callback_for_ps_arp(ip,entry); + + return FAILED; +} +#endif +int32 rtl865x_addArp(ipaddr_t ip, ether_addr_t * mac) +{ + uint32 i; + uint32 hash; + uint16 fid = 0; + + rtl865x_arpMapping_entry_t oldArpMapping; + rtl865x_arpMapping_entry_t newArpMapping; + + rtl865x_tblAsicDrv_arpParam_t asicArpEntry; + + uint32 fdb_type[]={ FDB_STATIC, FDB_DYNAMIC }; + + uint32 column; + rtl865x_tblAsicDrv_l2Param_t fdbEntry; + rtl865x_filterDbTableEntry_t l2temp_entry; + + if((ip==0) ||(mac==NULL)) + { + return RTL_EINVALIDINPUT; + } + + #if defined(CONFIG_RTL_MULTIPLE_WAN) + if(rtl_get_advRt_entry_by_nexthop(ip)) + { + newArpMapping.ip=ip; + memcpy(&newArpMapping.mac,mac,sizeof(ether_addr_t)); + rtl865x_eventHandle_addArp_for_multiWan(&newArpMapping); + } + #endif + + if(rtl865x_arp_hash(ip, &hash)==FAILED) + { + return FAILED; + } + + //printk("%s:%d+++++++++++++++++++++++++++++\n",__FUNCTION__,__LINE__); + + /*check the old arp mapping first*/ + memcpy(&oldArpMapping,&(arpTables.mappings[hash] ),sizeof(rtl865x_arpMapping_entry_t)); + if((oldArpMapping.ip!=ip) ||(memcmp(&(oldArpMapping.mac),mac, 6)!=0)) + { + /*delete old arp mapping*/ + if(oldArpMapping.ip!=0) + { + /*should clear old arp mapping before delete fdb entry and raise arp event*/ + rtl8651_delAsicArp(hash); + memset(&(arpTables.mappings[hash] ),0,sizeof(rtl865x_arpMapping_entry_t)); + + if(rtl865x_getArpFid(oldArpMapping.ip,&fid)==SUCCESS) + { + rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEI|RTL865x_L2_TYPEII, fid, &oldArpMapping.mac); + } + rtl865x_raiseEvent(EVENT_DEL_ARP,(void*)(&oldArpMapping)); + } + } + /*here to handle the new arp mapping*/ + newArpMapping.ip=ip; + memcpy(&newArpMapping.mac,mac,sizeof(ether_addr_t)); + if(rtl865x_getArpFid(newArpMapping.ip, &fid)!=SUCCESS) + { + return FAILED; + } + + for(i=0; i<2; i++) + { + /* + printk("%s:%d\n,fid(%d),mac(%02x:%02x:%02x:%02x:%02x:%02x)\n",__FUNCTION__,__LINE__,fid,mac->octet[0],mac->octet[1], + mac->octet[2],mac->octet[3],mac->octet[4],mac->octet[5]); + + printk("%s:%d\n",__FUNCTION__,__LINE__); + */ + if(rtl865x_Lookup_fdb_entry(fid, mac, fdb_type[i], &column,&fdbEntry) != SUCCESS) + { + continue; + } + + /*indicate new arp mapping*/ + if((oldArpMapping.ip!=ip) ||(memcmp(&(oldArpMapping.mac),mac, 6)!=0)) + { + /*in case of layer2 auto learn, add hardware entry to layer 2 software table*/ + l2temp_entry.l2type = (fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII; + l2temp_entry.process = FDB_TYPE_FWD; + l2temp_entry.memberPortMask = fdbEntry.memberPortMask; + l2temp_entry.auth = fdbEntry.auth; + l2temp_entry.SrcBlk = fdbEntry.srcBlk; + memcpy(&(l2temp_entry.macAddr), mac, sizeof(ether_addr_t)); +#ifdef CONFIG_RTL865X_SYNC_L2 +#else +// rtl865x_addFilterDatabaseEntryExtension(fid, &l2temp_entry); +#endif +// _rtl865x_addFilterDatabaseEntry((fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII, fid, mac, FDB_TYPE_FWD, fdbEntry.memberPortMask, fdbEntry.auth,fdbEntry.srcBlk); + + } + + /*update or reflesh arp mapping*/ + asicArpEntry.nextHopColumn = column; + asicArpEntry.aging = 300; + asicArpEntry.nextHopRow=rtl865x_getHWL2Index(mac, fid); + rtl8651_setAsicArp(hash, &asicArpEntry); + rtl865x_refleshHWL2Table(mac, FDB_DYNAMIC|FDB_STATIC,fid); + /*update mapping table*/ + memcpy(&(arpTables.mappings[hash]),&newArpMapping,sizeof(rtl865x_arpMapping_entry_t)); + rtl865x_raiseEvent(EVENT_ADD_ARP,(void*)(&newArpMapping)); + return SUCCESS; + + } + + return FAILED; +} + + + +int32 rtl865x_delArp(ipaddr_t ip) +{ + uint32 hash; + uint16 fid = 0; + + rtl865x_arpMapping_entry_t arpMapping; + + if(ip==0) + { + return FAILED; + } + + + #if defined(CONFIG_RTL_MULTIPLE_WAN) + if(rtl_get_advRt_entry_by_nexthop(ip)) + { + arpMapping.ip = ip; + memset(arpMapping.mac.octet,0,ETHER_ADDR_LEN); + rtl865x_eventHandle_delArp_for_multiWan(&arpMapping); + } + #endif + + if(rtl865x_arp_hash(ip,&hash)==FAILED) + { + return FAILED; + } + + //printk("%s:%d***************************************\n",__FUNCTION__,__LINE__); + memcpy(&arpMapping, &arpTables.mappings[hash], sizeof(rtl865x_arpMapping_entry_t)); + + if(arpMapping.ip!=ip) + { + return FAILED; + } + + if(rtl865x_getArpFid(ip, &fid)!=SUCCESS) + { + return FAILED; + } + + /*should clear old arp mapping before delete fdb entry and raise arp event*/ + rtl8651_delAsicArp(hash); + memset(&arpTables.mappings[hash], 0, sizeof(rtl865x_arpMapping_entry_t)); + +#ifdef CONFIG_RTL865X_SYNC_L2 +#else +// rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEI|RTL865x_L2_TYPEII, fid, &arpMapping.mac); +#endif + rtl865x_raiseEvent(EVENT_DEL_ARP,(void *)(&arpMapping)); + + + return SUCCESS; +} + +uint32 rtl865x_arpSync(ipaddr_t ip, uint32 refresh ) +{ + uint32 hash; + rtl865x_arpMapping_entry_t arpMapping; + rtl865x_tblAsicDrv_arpParam_t asicArpEntry; + + uint16 fid; + rtl865x_tblAsicDrv_l2Param_t l2entry; + uint32 age=0; + + if(ip==0) + { + return 0; + } + + if(rtl865x_arp_hash(ip,&hash)==FAILED) + { + return 0; + } + + memcpy(&arpMapping, &(arpTables.mappings[hash]), sizeof(rtl865x_arpMapping_entry_t)); + + if(arpMapping.ip!=ip) + { + return 0; + } + + /*asic arp entry is invalid*/ + if (rtl8651_getAsicArp(hash, &asicArpEntry)!=SUCCESS) + { + goto delete_and_out; + + } + + if(rtl865x_getHWL2Table(asicArpEntry.nextHopRow, asicArpEntry.nextHopColumn, &l2entry)!=SUCCESS) + { + /*the old fdb entry has timed out*/ + goto delete_and_out; + } + + if(memcmp(&(l2entry.macAddr), &(arpMapping.mac), 6)!= 0) + { + /*this layer 2 entry has different mac address, + also indicates the old fdb entry has timed out*/ + goto delete_and_out; + } + + age = l2entry.ageSec; + if (refresh) + { + rtl865x_refleshHWL2Table(&(l2entry.macAddr), FDB_DYNAMIC|FDB_STATIC,l2entry.fid); + age=150; + } + else + { + if(age>=300) + { + age=age-150; + } + else + { + age=0; + + /*to make sure linux arp entry time out before fdb entry*/ + /*asic fdb entry's age is 150 seconds*/ + /*since linux protocol stack arp entry has timed out and l2 entry's precision is also 150 second, + we should delete both arp and fdb to sync between linux protocol stack and asic*/ + //goto delete_and_out; + } + } + return age; + + +delete_and_out: + + if(rtl865x_getArpFid(ip, &fid)==SUCCESS) + { + /*should clear old arp mapping before delete fdb entry and raise arp event*/ + rtl8651_delAsicArp(hash); + memset(&arpTables.mappings[hash], 0, sizeof(rtl865x_arpMapping_entry_t)); + + rtl865x_delFilterDatabaseEntry(RTL865x_L2_TYPEI|RTL865x_L2_TYPEII, fid, &arpMapping.mac); + rtl865x_raiseEvent(EVENT_DEL_ARP,(void *)(&arpMapping)); + } + + return 0; + +} + + -- cgit v1.2.3