/* * Copyright c Realtek Semiconductor Corporation, 2008 * All rights reserved. * * Program : route table driver * Abstract : * Author : hyking (hyking_liu@realsil.com.cn) */ /* @doc RTL_LAYEREDDRV_API @module rtl865x_route.c - RTL865x Home gateway controller Layered driver API documentation | This document explains the API interface of the table driver module. Functions with rtl865x prefix are external functions. @normal Hyking Liu (Hyking_liu@realsil.com.cn) 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 //#include #include #include "common/rtl_errno.h" //#include "rtl_utils.h" #include "common/rtl865x_netif_local.h" #include "rtl865x_ppp_local.h" #include "rtl865x_route.h" #include "rtl865x_ip.h" #include "rtl865x_nexthop.h" #include "rtl865x_arp.h" //#include "common/rtl_glue.h" #include "common/rtl865x_eventMgr.h" /*call back function....*/ #include "common/rtl865x_vlan.h" #ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER #include "AsicDriver/rtl865x_asicCom.h" #include "AsicDriver/rtl865x_asicL2.h" #include "AsicDriver/rtl865x_asicL3.h" #else #include "AsicDriver/rtl865xC_tblAsicDrv.h" #endif #include "l2Driver/rtl865x_fdb.h" #include "AsicDriver/rtl865xc_asicregs.h" #include static rtl865x_route_t *rtl865x_route_freeHead; static rtl865x_route_t *rtl865x_route_inusedHead; static RTL_DECLARE_MUTEX(route_sem); #if 0 void _rtl865x_route_print(void) { int32 i; rtl865x_route_t *rt = NULL; rt = rtl865x_route_inusedHead; printk("=============inused list:\n"); while(rt) { printk("asicIdx(%d),ip(0x%x),mask(0x%x),nextHop(0x%x),process(0x%x),dst(%s) valid(%d)\n",rt->asicIdx, rt->ipAddr,rt->ipMask,rt->nextHop,rt->process,rt->dstNetif->name,rt->valid); rt = rt->next; } i = 0; rt = rtl865x_route_freeHead; while(rt) { i++; rt = rt->next; } printk("=======free list count(%d)\n",i); } #endif static rtl865x_route_t* _rtl865x_getDefaultRoute(void) { rtl865x_route_t *rt = NULL; rt = rtl865x_route_inusedHead; while(rt) { if((rt->valid==1)&&(rt->asicIdx == RT_ASIC_ENTRY_NUM -1)) return rt; rt = rt->next; } return NULL; } static rtl865x_route_t* _rtl865x_getRouteEntry(ipaddr_t ipAddr, ipaddr_t ipMask) { rtl865x_route_t *rt = NULL; rt = rtl865x_route_inusedHead; while(rt) { if((rt->valid==1)&&((rt->ipAddr&rt->ipMask)==(ipAddr&ipMask))&&(rt->ipMask==ipMask)) return rt; rt = rt->next; } return NULL; } static int32 _rtl865x_synRouteToAsic(rtl865x_route_t *rt_t) { int32 ret = FAILED; rtl865x_tblAsicDrv_routingParam_t asic_t; rtl865x_tblAsicDrv_l2Param_t asic_l2; rtl865x_netif_local_t *dstNetif = NULL; uint32 columIdx,fid; int32 pppIdx = 0; bzero(&asic_t, sizeof(rtl865x_tblAsicDrv_routingParam_t)); if(rt_t == NULL) { printk("%s(%d):NULL!!!!!!!!!!!!!!!!\n",__FUNCTION__,__LINE__); } /*common information*/ asic_t.ipAddr = rt_t->ipAddr; asic_t.ipMask = rt_t->ipMask; asic_t.ipAddr = rt_t->ipAddr; asic_t.ipMask = rt_t->ipMask; /*if the dstNetif is attach on another interface, the netifIdx should the master interface's index*/ if(rt_t->dstNetif->is_slave == 1) { //printk("========%s(%d), ip(0x%x),mask(0x%x),netif(%s)\n",__FUNCTION__,__LINE__,rt_t->ipAddr,rt_t->ipMask,rt_t->dstNetif->name); dstNetif = _rtl865x_getNetifByName(rt_t->dstNetif->name); if(dstNetif == NULL) dstNetif = _rtl865x_getDefaultWanNetif(); } else dstNetif = rt_t->dstNetif; if(dstNetif == NULL) printk("%s(%d) BUG!!!!!!\n",__FUNCTION__,__LINE__); asic_t.vidx = dstNetif->asicIdx; asic_t.internal = rt_t->dstNetif->is_wan? 0 : 1; asic_t.DMZFlag = rt_t->dstNetif->dmz? 1 : 0; asic_t.process = rt_t->process; switch (rt_t->process) { case RT_PPPOE: ret = rtl865x_getPppIdx(rt_t->un.pppoe.pppInfo, &pppIdx); asic_t.pppoeIdx = pppIdx; /* *if process==RT_PPPOE, the mac address of pppoe server is add in pppoe module, *so, we read the FDB information directly.... */ ret = rtl865x_getVlanFilterDatabaseId(rt_t->dstNetif->vid,&fid); ret = rtl865x_Lookup_fdb_entry(fid, (ether_addr_t *)rt_t->un.pppoe.macInfo, FDB_DYNAMIC, &columIdx,&asic_l2); if(ret != SUCCESS) printk("can't get l2 entry by mac.....\n"); /*FIXME_hyking: update mac/fdb table reference count*/ asic_t.nextHopRow = rtl8651_filterDbIndex( rt_t->un.pppoe.macInfo,fid); asic_t.nextHopColumn = columIdx; break; case RT_L2: /* * NOTE:this type not used now... * if we want to use it, please add FDB entry to sure this L2 entry in both software FDB table and Asic L2 table. */ ret = rtl865x_getVlanFilterDatabaseId(rt_t->dstNetif->vid,&fid); ret = rtl865x_Lookup_fdb_entry(fid, (ether_addr_t *)rt_t->un.direct.macInfo, FDB_STATIC, &columIdx,&asic_l2); if(ret != SUCCESS) printk("can't get l2 entry by mac.....\n"); /*FIXME_hyking: update mac/fdb table reference count*/ asic_t.nextHopRow = rtl8651_filterDbIndex(rt_t->un.direct.macInfo,fid); asic_t.nextHopColumn = columIdx; break; case RT_ARP: /*FIXME_hyking: update arp table reference count??*/ asic_t.arpStart = rt_t->un.arp.arpsta; asic_t.arpEnd = rt_t->un.arp.arpend; asic_t.arpIpIdx = rt_t->un.arp.arpIpIdx; break; case RT_CPU: case RT_DROP: /*do nothing*/ break; case RT_NEXTHOP: asic_t.nhStart = rt_t->un.nxthop.nxtHopSta; asic_t.nhNum = rt_t->un.nxthop.nxtHopEnd - rt_t->un.nxthop.nxtHopSta + 1; asic_t.nhNxt = asic_t.nhStart; asic_t.ipDomain = rt_t->un.nxthop.ipDomain; asic_t.nhAlgo = rt_t->un.nxthop.nhalog; break; default: printk("Process_Type(%d) is not support!\n",rt_t->process); } if(rt_t->asicIdx > RT_ASIC_ENTRY_NUM-1) { printk("BUG!! %s(%d)....", __FUNCTION__,__LINE__); return FAILED; } ret = rtl8651_setAsicRouting(rt_t->asicIdx, &asic_t); return ret; } static int32 _rtl865x_updateDefaultRoute(rtl865x_route_t *rt, int32 action) { int32 i; rtl865x_route_t *entry; int32 retval = FAILED; entry = rt; if(entry == NULL) return RTL_EINVALIDINPUT; /*delete nexthop which is add by default route*/ if(rt->process == RT_NEXTHOP) for ( i = entry->un.nxthop.nxtHopSta; i <= entry->un.nxthop.nxtHopEnd && entry->un.nxthop.nxtHopEnd != 0; i++) { retval = rtl865x_delNxtHop(NEXTHOP_L3, i); } entry->un.nxthop.nxtHopSta = 0; entry->un.nxthop.nxtHopEnd = 0; switch(action) { case RT_DEFAULT_RT_NEXTHOP_CPU: retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)entry, entry->dstNetif, 0,entry->srcIp); break; case RT_DEFAULT_RT_NEXTHOP_NORMAL: { rt->process = RT_NEXTHOP; switch(rt->dstNetif->if_type) { case IF_ETHER: retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, rt->dstNetif, rt->nextHop,entry->srcIp); break; case IF_PPPOE: { rtl865x_ppp_t *pppoe; pppoe = rtl865x_getPppByNetifName(rt->dstNetif->name); if(pppoe != NULL) { /*got pppoe session*/ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, rt->dstNetif, pppoe->sessionId,entry->srcIp); } else /*nexthop's action is to CPU*/ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, rt->dstNetif, 0,entry->srcIp); } break; } } break; } retval = _rtl865x_synRouteToAsic(entry); return retval; } static int32 _rtl865x_arrangeRoute(rtl865x_route_t *start_rt, int32 start_idx) { int32 count; rtl865x_route_t *rt = NULL; rt = start_rt; count = 0; while(rt) { if(rt->valid) { /*if the rule is default route...*/ if(rt->ipMask == 0) rt->asicIdx = RT_ASIC_ENTRY_NUM-1; else { /* entry number more than asic table's capacity*/ /* entry index=RT_ASIC_ENTRY_NUM-1 is reserved for default route*/ if((start_idx + count > RT_ASIC_ENTRY_NUM-2)) break; /*delete old asic entry firstly...*/ if(start_idx+count < rt->asicIdx && rt->asicIdx < RT_ASIC_ENTRY_NUM-1) rtl8651_delAsicRouting(rt->asicIdx); rt->asicIdx = start_idx+count; _rtl865x_synRouteToAsic(rt); } } /*next entry*/ rt= rt->next; count++; } /*more route entry need to add?*/ if(rt) { /*not enough asic table entry! have to update default route's action TOCPU*/ rt = _rtl865x_getDefaultRoute(); _rtl865x_updateDefaultRoute(rt, RT_DEFAULT_RT_NEXTHOP_CPU); } else { rt = _rtl865x_getDefaultRoute(); _rtl865x_updateDefaultRoute(rt, RT_DEFAULT_RT_NEXTHOP_NORMAL); } return SUCCESS; } static int32 _rtl865x_addRouteToInusedList(rtl865x_route_t *rt) { int32 retval = FAILED; int32 start_idx = 0; rtl865x_route_t *entry,*fore_rt,*start_rt; fore_rt = NULL; entry = rtl865x_route_inusedHead; /*always set 0x0f when init..., this value would be reset in arrange route*/ rt->asicIdx = 0x0f; rt->next = NULL; /*find the right position...*/ while(entry) { if(entry->valid == 1) { if(entry->ipMask < rt->ipMask) { break; } } fore_rt = entry; entry = entry->next; } /*insert this rule after insert_entry*/ if(fore_rt) { rt->next = fore_rt->next; fore_rt->next = rt; start_idx = fore_rt->asicIdx+1; start_rt = rt; } else { /*insert head...*/ rt->next = rtl865x_route_inusedHead; rtl865x_route_inusedHead = rt; start_idx = 0; start_rt = rtl865x_route_inusedHead; } retval = _rtl865x_arrangeRoute(start_rt, start_idx); //_rtl865x_route_print(); return retval; } static int32 _rtl865x_delRouteFromInusedList(rtl865x_route_t * rt) { int32 retval,start_idx; rtl865x_route_t *fore_rt = NULL,*entry = NULL,*start_rt = NULL; entry = rtl865x_route_inusedHead; while(entry) { if(entry == rt) break; fore_rt = entry; entry = entry->next; } /*fore_rt == NULL means delete list head*/ if(fore_rt == NULL) { rtl865x_route_inusedHead = rtl865x_route_inusedHead->next; start_rt = rtl865x_route_inusedHead; start_idx = 0; } else { fore_rt->next = rt->next; start_rt = fore_rt->next; start_idx = fore_rt->asicIdx + 1; } /*delete route from asic*/ if(rt->asicIdx < RT_ASIC_ENTRY_NUM) rtl8651_delAsicRouting(rt->asicIdx); retval = _rtl865x_arrangeRoute(start_rt, start_idx); rt->asicIdx = 0x0f; //_rtl865x_route_print(); return retval; } static int32 _rtl865x_usedNetifInRoute(int8 *ifname) { rtl865x_route_t *rt = NULL; rt = rtl865x_route_inusedHead; while(rt) { if(memcmp(rt->dstNetif->name,ifname,strlen(ifname)) == 0) return SUCCESS; rt = rt->next; } return FAILED; } static int32 _rtl865x_addRoute(ipaddr_t ipAddr, ipaddr_t ipMask, ipaddr_t nextHop, int8 * ifName,ipaddr_t srcIp) { rtl865x_netif_local_t *netif = NULL; rtl865x_route_t *rt = NULL,*tmp_rt = NULL; int32 idx; int32 netSize = 0, usedArpCnt = 0; int32 retval = FAILED; /*para check*/ if(ifName == NULL) netif = _rtl865x_getDefaultWanNetif(); else netif = _rtl865x_getSWNetifByName(ifName); if(netif == NULL) return RTL_EINVALIDINPUT; if(netif->if_type == IF_NONE) return RTL_ENOLLTYPESPECIFY; idx = 0; for(idx = 0; idx < 32; idx++) if((1< RT_MAX_ARP_SIZE) return RTL_EINVALIDINPUT; /* *duplicate entry check: * in Driver system, default route is always exist. * so if ipMask == 0, it's means that default route should be update... */ if(ipMask != 0 && (rt = _rtl865x_getRouteEntry(ipAddr, ipMask)) != NULL) { //rt->ref_count++; return RTL_EENTRYALREADYEXIST; } /*add default route: just update the default route becase the default route always exist!*/ if(ipMask == 0) { rt = _rtl865x_getDefaultRoute(); /*deference rt's orginal netif*/ if(rt && rt->dstNetif) rtl865x_deReferNetif(rt->dstNetif->name); } /*allocate a new buffer for adding entry*/ if(rt == NULL) { rt = rtl865x_route_freeHead; if(rt) { rtl865x_route_freeHead = rt->next; } } if(rt == NULL) { /*no buffer, default route should be TOCPU?*/ return RTL_ENOFREEBUFFER; } /*common information*/ rt->ipAddr = ipAddr & ipMask; rt->ipMask = ipMask; rt->nextHop = nextHop; rt->srcIp = srcIp; rt->dstNetif = netif; /*don't specify the nexthop ip address, it's means that: * all packet match this route entry should be forward by network interface with arp */ if(nextHop == 0 && ipMask != 0) { switch(netif->if_type) { case IF_ETHER: rt->process = RT_ARP; tmp_rt = rtl865x_route_inusedHead; while(tmp_rt) { if(tmp_rt->valid && tmp_rt->process == RT_ARP && tmp_rt->dstNetif == netif) usedArpCnt += tmp_rt->un.arp.arpend - tmp_rt->un.arp.arpend + 1; tmp_rt = tmp_rt->next; } if((usedArpCnt + netSize) > RT_MAX_ARP_SIZE) { printk("!!!!ERROR!!!usedArp(%d),netsize(%d)\n",usedArpCnt,netSize); goto addFailed; } /*allocate arp entry for this route rule...*/ retval = rtl865x_arp_tbl_alloc(rt); if( retval != SUCCESS) { printk("error!!can't allocate arp for this route entry....retval(%d)\n",retval); goto addFailed; } rt->un.arp.arpIpIdx = 0; /*FIXME_hyking[this field is invalid, right?]*/ break; case IF_PPPOE: { rtl865x_ppp_t *ppp = NULL; rt->process = RT_PPPOE; ppp = rtl865x_getPppByNetifName(netif->name); if(ppp == NULL) { printk("error!!can't get pppoe session information by interface name(%s)\n",netif->name); goto addFailed; } rt->un.pppoe.macInfo = &ppp->server_mac; rt->un.pppoe.pppInfo = ppp; /*update reference...*/ rtl865x_referPpp(ppp->sessionId); } break; case IF_PPTP: case IF_L2TP: { rtl865x_ppp_t *ppp = NULL; rt->process = RT_L2; ppp = rtl865x_getPppByNetifName(netif->name); if(ppp == NULL) { /*printk("Warning!!CAn't get pptp/l2tp session information by interface name(%s)\n",netif->name);*/ goto addFailed; } rt->un.direct.macInfo = &ppp->server_mac; } break; default: printk("lltype(%d) is not support now....\n",netif->if_type); goto addFailed; } } else { /*if default is valid, delete nexthop firstly...*/ if(rt->valid == 1 && rt->process == RT_NEXTHOP) { int i; for ( i = rt->un.nxthop.nxtHopSta; i <= rt->un.nxthop.nxtHopEnd; i++) { retval = rtl865x_delNxtHop(NEXTHOP_L3, i); } } /*use nexthop type*/ rt->process = RT_NEXTHOP; switch(netif->if_type) { case IF_ETHER: retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, netif, nextHop,srcIp); break; case IF_PPPOE: case IF_PPTP: case IF_L2TP: { rtl865x_ppp_t *pppoe; pppoe = rtl865x_getPppByNetifName(netif->name); if(pppoe != NULL) { /*got pppoe session*/ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, netif, pppoe->sessionId,srcIp); } else /*nexthop's action is to CPU*/ retval = rtl865x_addNxtHop(NEXTHOP_L3, (void*)rt, netif, 0,srcIp); } break; default: retval = FAILED; break; } if(retval != SUCCESS) { printk("error!!add nexthop error! retval (%d)\n",retval); goto addFailed; } rt->un.nxthop.nhalog = RT_ALOG_SIP; /* use per-source IP */ rt->un.nxthop.ipDomain = RT_DOMAIN_16_1; } rt->valid = 1; rt->ref_count = 1; /*update reference....*/ rtl865x_referNetif(netif->name); if(ipMask == 0) _rtl865x_setDefaultWanNetif(netif->name); /**/ if(rt->asicIdx == RT_ASIC_ENTRY_NUM-1) { retval = _rtl865x_synRouteToAsic(rt); } else { /*insert the adding route to inused list*/ retval = _rtl865x_addRouteToInusedList(rt); } /*if route is add, please enable Routing for the releated netif*/ retval = rtl865x_enableNetifRouting(netif); return retval; addFailed: if(rt->asicIdx == RT_ASIC_ENTRY_NUM -1) { _rtl865x_updateDefaultRoute(rt, RT_DEFAULT_RT_NEXTHOP_CPU); } else { /*free this route entry and return error code...*/ memset(rt,0,sizeof(rtl865x_route_t)); rt->next = rtl865x_route_freeHead; rtl865x_route_freeHead = rt; } return retval; } static int32 _rtl865x_delRoute( ipaddr_t ipAddr, ipaddr_t ipMask ) { rtl865x_route_t *entry; int32 i; int32 retval = 0; entry = _rtl865x_getRouteEntry(ipAddr, ipMask); if(entry == NULL) return RTL_EENTRYNOTFOUND; if(entry->asicIdx == RT_ASIC_ENTRY_NUM-1) { /*if default route * 1. reset default route * 2. reset entry->netif... */ rtl865x_netif_local_t *netif = NULL; _rtl865x_clearDefaultWanNetif(entry->dstNetif->name); netif = _rtl865x_getDefaultWanNetif(); if(netif==NULL) { return RTL_EINVNETIFNAME; } if(netif != entry->dstNetif) { rtl865x_deReferNetif(entry->dstNetif->name); entry->dstNetif = netif; rtl865x_referNetif(netif->name); } retval = _rtl865x_updateDefaultRoute(entry, RT_DEFAULT_RT_NEXTHOP_CPU); } else { /*not default route*/ switch(entry->process) { case RT_PPPOE: { rtl865x_ppp_t *ppp = entry->un.pppoe.pppInfo; if(ppp) rtl865x_deReferPpp(ppp->sessionId); } break; case RT_L2: /* * NOTE:this type not used now... * if we want to use it, please DELETE FDB entry to sure this L2 entry is deleted both software FDB table and Asic L2 table. */ break; case RT_ARP: /*free arp*/ retval = rtl865x_arp_tbl_free(entry); if( retval != SUCCESS) { printk("======error!!can't FREE arp entry for this route entry....retval(%d)\n",retval); } break; case RT_CPU: case RT_DROP: /*do nothing*/ break; case RT_NEXTHOP: /*delete nexthop which is add by l3*/ for ( i = entry->un.nxthop.nxtHopSta; i <= entry->un.nxthop.nxtHopEnd; i++) { retval = rtl865x_delNxtHop(NEXTHOP_L3, i); } break; } /*FIXME_hyking: update netif reference count*/ rtl865x_deReferNetif(entry->dstNetif->name); /*remove from inused list...*/ _rtl865x_delRouteFromInusedList(entry); if(_rtl865x_usedNetifInRoute(entry->dstNetif->name) == FAILED) rtl865x_disableNetifRouting(entry->dstNetif); /*add to free list*/ memset(entry,0,sizeof(rtl865x_route_t)); entry->next = rtl865x_route_freeHead; rtl865x_route_freeHead = entry; retval = SUCCESS; } //_rtl865x_route_print(); return retval; } rtl865x_route_t* _rtl85x_getRouteEntry(ipaddr_t dst) { rtl865x_route_t *tmpRtEntry = NULL; rtl865x_route_t *rt=rtl865x_route_inusedHead; uint32 mask; mask = 0; while(rt) { if (rt->valid == 1 && rt->ipAddr == (rt->ipMask & dst) && mask <= rt->ipMask) { mask = rt->ipMask; tmpRtEntry = rt; } rt = rt->next; } return tmpRtEntry; } /* @func int32 | rtl865x_addRoute |add a route entry. @parm ipaddr_t | ipAddr | ip address. @parm ipaddr_t | ipMask | ip mask. @parm ipaddr_t | nextHop | the route's next hop. @parm int8* | ifName | destination network interface. @parm ipaddr_t | srcIp |source IP @rvalue SUCCESS | success. @rvalue FAILED | failed. @rvalue RTL_EINVALIDINPUT | invalid input. @rvalue RTL_ENOLLTYPESPECIFY | network interface's link type is not specified. @rvalue RTL_EENTRYALREADYEXIST | route entry is already exist. @rvalue RTL_ENOFREEBUFFER | not enough memory in system. @comm if ifName=NULL, it means the destionation network interface of route entry with ip/ipMask/nextHop is default wan. */ int32 rtl865x_addRoute(ipaddr_t ipAddr, ipaddr_t ipMask, ipaddr_t nextHop,int8 * ifName,ipaddr_t srcIp) { int32 retval = 0; unsigned long flags; //printk("========%s(%d), ip(0x%x),mask(0x%x),ifname(%s),nxthop(0x%x)\n",__FUNCTION__,__LINE__,ipAddr,ipMask,ifName,nextHop); //rtl_down_interruptible(&route_sem); local_irq_save(flags); retval = _rtl865x_addRoute(ipAddr,ipMask,nextHop,ifName,srcIp); //rtl_up(&route_sem); local_irq_restore(flags); //printk("========%s(%d), ip(0x%x),mask(0x%x),ifname(%s),nxthop(0x%x),retval(%d)\n",__FUNCTION__,__LINE__,ipAddr,ipMask,ifName,nextHop,retval); //_rtl865x_route_print(); return retval; } /* @func int32 | rtl865x_delRoute |delete a route entry. @parm ipaddr_t | ipAddr | ipAddress. @parm ipaddr_t | ipMask | ipMask. @rvalue SUCCESS | success. @rvalue FAILED | failed. @rvalue RTL_EENTRYNOTFOUND | not found the entry. @comm */ int32 rtl865x_delRoute(ipaddr_t ipAddr, ipaddr_t ipMask) { int32 retval = 0; unsigned long flags; //printk("========%s(%d), ip(0x%x),mask(0x%x)\n",__FUNCTION__,__LINE__,ipAddr,ipMask); //rtl_down_interruptible(&route_sem); local_irq_save(flags); retval = _rtl865x_delRoute(ipAddr,ipMask); //rtl_up(&route_sem); local_irq_restore(flags); //printk("==================================retval(%d)\n",retval); return retval; } /* @func int32 | rtl865x_getRouteEntry |according the destination ip address, get the matched route entry. @parm ipaddr_t | dst | destionation ip address. @parm rtl865x_route_t* | rt | retrun value: route entry pointer @rvalue SUCCESS | success. @rvalue FAILED | failed. @comm */ int32 rtl865x_getRouteEntry(ipaddr_t dst,rtl865x_route_t *rt) { int32 retval = FAILED; rtl865x_route_t *ret_entry = NULL; ret_entry = _rtl85x_getRouteEntry(dst); if(ret_entry && rt) { memcpy(rt,ret_entry,sizeof(rtl865x_route_t)); retval = SUCCESS; } return retval; } /* @func int32 | rtl865x_initRouteTable |initialize route tabel. @rvalue SUCCESS | success. @rvalue FAILED | failed. @comm */ int32 rtl865x_initRouteTable(void) { int32 i; rtl865x_route_t *rt; rtl865x_route_freeHead = NULL; rtl865x_route_inusedHead = NULL; /*malloc buffer*/ TBL_MEM_ALLOC(rt, rtl865x_route_t, RT_DRV_ENTRY_NUM); memset(rt,0,sizeof(rtl865x_route_t)*RT_DRV_ENTRY_NUM); for(i = 0; i < RT_DRV_ENTRY_NUM; i++) { rt[i].next = rtl865x_route_freeHead; rtl865x_route_freeHead = &rt[i]; } return SUCCESS; } /* @func int32 | rtl865x_reinitRouteTable |reinitialize route tabel. @rvalue SUCCESS | success. @rvalue FAILED | failed. @comm */ int32 rtl865x_reinitRouteTable(void) { rtl865x_route_t *rt; rt = rtl865x_route_inusedHead; while(rt && rt->asicIdx != RT_ASIC_ENTRY_NUM -1) { _rtl865x_delRoute(rt->ipAddr,rt->ipMask); rt = rtl865x_route_inusedHead; } /*delete the last route*/ rt = rtl865x_route_inusedHead; if(rt) { /*FIXME_hyking: update netif reference count*/ rtl865x_deReferNetif(rt->dstNetif->name); /*remove from inused list...*/ _rtl865x_delRouteFromInusedList(rt); /*add to free list*/ memset(rt,0,sizeof(rtl865x_route_t)); rt->next = rtl865x_route_freeHead; rtl865x_route_freeHead = rt; } return SUCCESS; } #if defined (CONFIG_RTL_LOCAL_PUBLIC) int rtl865x_getLanRoute(rtl865x_route_t routeTbl[], int tblSize ) { int cnt=0; rtl865x_route_t *rt = NULL; rt = rtl865x_route_inusedHead; while(rt) { if((rt->valid==1) && (rt->dstNetif->is_wan==0)) { memcpy(&routeTbl[cnt], rt, sizeof(rtl865x_route_t) ); cnt++; } rt = rt->next; } return cnt; } #endif